feat: compiled-program visualizer (shared graph spec + CLI render) - #184
Merged
Conversation
See what a demonstration compiled INTO. Adds `openadapt_flow.visualize`, which
emits a shared, serializable program-graph spec from a compiled bundle and
renders it, plus an `openadapt-flow visualize` CLI subcommand.
The engine is the single source of truth: `build_program_graph(workflow)`
projects a compiled Workflow onto a versioned `ProgramGraphSpec` (nodes = steps
with their target-resolution ladder, identity gate, effect check, verification
postconditions, risk class, and control guards; edges = sequence with typed
room for branches/loops/exception paths; per-node HALT points as first-class
annotations). Every visualization surface (this CLI, cloud, desktop) renders
THIS spec; none re-parse the bundle IR. A linear bundle projects to a straight
chain of action nodes; a Phase-2 program graph projects its full state machine.
- `visualize/spec.py` — the wire contract (pydantic models).
- `visualize/builder.py` — bundle -> spec projection (honest; never fabricates
structure the compiler did not produce).
- `visualize/render.py` — self-contained HTML (inlines the shared CSS + a
dependency-free vanilla-JS renderer, CSP-safe, opens offline) and a Mermaid
flowchart source.
- `visualize/static/program_graph.{css,js}` — the ONE shared renderer the CLI
inlines and the desktop (Tauri) view vendors verbatim.
- `schemas/program-graph-v1.json` — committed JSON Schema so non-Python surfaces
validate the same shape.
- CLI `visualize <bundle> [--format html|mermaid|json] [-o OUT]`.
- Tests (11) + a rendered example of the committed OpenEMR showcase bundle
(docs/VISUALIZE.md, docs/showcase-openemr/program-graph.{json,html,png}).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NyCHrzA1psrKMFfroYbzaM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See what a demonstration compiled INTO
A compiled bundle is a governed program, not a video. This adds a way to see its structure — the ordered steps, how each target is re-resolved, whether an identity gate protects the click, what real system-of-record effect must hold, what the screen must look like afterward, its risk class, and where the run will halt rather than guess.
One spec, three surfaces (this PR = engine + CLI)
The engine is the single source of truth.
openadapt_flow.visualize.build_program_graph(workflow)projects a compiledWorkflowonto a versioned, serializableProgramGraphSpec. Every visualization surface — this CLI, the cloud view (app.openadapt.ai), the desktop app — renders that spec; none re-parse the bundle IR. Companion cloud + desktop PRs render the same spec.Spec (v1): nodes = compiled steps/program states (each with its target-resolution ladder + top rung, identity gate armed/unarmed+reason, effect check, verification postconditions, risk class, control guards); edges = sequence with typed room for
branch/loop/exception/loop_body; per-node halt points as first-class annotations; bundle header with PHI/encryption flags, provenance/certification, params, rollups. A linear bundle projects to a straight chain ofactionnodes ending in asuccessterminal; a Phase-2 program graph projects its full state machine 1:1, so richer structure renders without a spec break.Committed JSON Schema
schemas/program-graph-v1.jsonlets non-Python surfaces validate the same shape; a sample emitted spec is atdocs/showcase-openemr/program-graph.json.Rendering choice & tradeoffs
CLI
```bash
openadapt-flow visualize path/to/bundle -o program.html # self-contained HTML
openadapt-flow visualize path/to/bundle --format mermaid # Mermaid flowchart
openadapt-flow visualize path/to/bundle --format json # shared graph spec
```
What's here
openadapt_flow/visualize/{spec,builder,render}.py+static/program_graph.{css,js}(the shared renderer).schemas/program-graph-v1.json, CLIvisualizesubcommand,docs/VISUALIZE.md.tests/test_visualize.py): projection counts, resolution ladder/top-rung, identity-gate + halt-point surfacing, JSON roundtrip, self-contained-HTML assertion, Mermaid validity, schema-in-sync validation, CLI, and a regression against the real committed OpenEMR showcase bundle (18 steps, 2 irreversible, 3 identity gates, 1 halt point).Verification
pytest tests/test_visualize.py→ 11 passed; existing lint/report tests still green.ruff check+ruff format --checkclean;mypy openadapt_flow/visualize/clean.docs/showcase-openemr/program-graph.{html,png}) is produced by the CLI from the committed bundle.🤖 Generated with Claude Code
https://claude.ai/code/session_01NyCHrzA1psrKMFfroYbzaM