diff --git a/docs/assets/screenshots/PROVENANCE.txt b/docs/assets/screenshots/PROVENANCE.txt index c6e0038..11c63fb 100644 --- a/docs/assets/screenshots/PROVENANCE.txt +++ b/docs/assets/screenshots/PROVENANCE.txt @@ -2,11 +2,18 @@ Screenshot provenance ===================== All screenshots below are rendered from OpenAdapt's own tooling in local / -mock mode. None are mocked-up or hand-drawn. Each capture that shows product -chrome is a byte-identical copy of a file in OpenAdaptAI/openadapt-web, which -owns the published visual record for every OpenAdapt surface; +mock mode. None are mocked-up or hand-drawn. + +Most captures that show product chrome are byte-identical copies of a file in +OpenAdaptAI/openadapt-web, which owns the published visual record. The four +program-view captures are the exception: openadapt-web publishes those surfaces +as live components rather than as stills, so these are captured here and their +entry names the upstream repository and commit instead. + docs/assets/visual-palette.json records the measured dominant colours of every -image on this site. +image on this site, and tests/test_design_tokens.py refuses a warm ground. An +image on a retired palette is not something a reader can see, so a capture from +a build that predates the palette move is caught by measurement or not at all. program-graph-cloud.png The compiled-program visualizer in the OpenAdapt Cloud workspace @@ -18,6 +25,36 @@ program-graph-cli.png visualizer) for the OpenEMR showcase bundle, headless-Chrome capture of the self-contained page. Used on concepts/program-visualizer.md. +program-state-live-relation.png + The public synthetic Program State Console in openadapt-web at the final + event of its exact retained trace. It compares synthetic recorded and current + frames. Used on concepts/program-visualizer.md. SHA-256: + 676f0e57c4a19a490d4c9ee9bfccaecfb44dfe99d83febf24fc4f00c2fc1ae13. + +program-workbench-cloud.png + The public-safe Program map in openadapt-cloud local mock mode. The graph + contains exact emitted edges and generic synthetic labels. Used on + concepts/program-visualizer.md. SHA-256: + 0f77308464f618efcb04814b411eb322af779699d33298ea9f0e57f7edab6d6e. + +program-workbench-cli.png + A public-synthetic openadapt-flow HTML export for a loop program. The page is + self-contained and was captured in a local browser. Used on + concepts/program-visualizer.md. SHA-256: + aa5ff1e1455b0444f234f398e3f645490b974c3b48c5e38156fd041964fec4d2. + +program-workbench-desktop.png + The development-only OpenAdapt Desktop preview that renders the production + qualification workbench with a public synthetic graph. It has no bound live + trace. Captured at 1440x1000 with Playwright Chromium from + http://localhost:1421/?surface=program-workbench-preview, against `npm run + dev` in OpenAdaptAI/openadapt-desktop at exact commit + ebc10b037533f7adc0b12e0664d718d373245108. That is the first commit carrying + the canonical design tokens, which matters: the first version of this capture + came from a build before that merge and grounded on the retired #f2f1ed. + Used on concepts/program-visualizer.md. SHA-256: + 4fbc62dd9ee5b48f758aca0ed5a13e072b3e0a4b6fc391847202297673f12e3f. + workflow-catalog.png The workflow catalog and step-level halt map in the OpenAdapt Cloud workspace, headless-Chrome capture in local mock mode. Used on @@ -36,11 +73,11 @@ settings-governance.png dashboard-overview.png The /dashboard overview of the OpenAdapt Cloud workspace at exact commit - 021a9caf99a6832bff9f32e14b1b34d42ec2e290, captured at 2560x1440 with + ee84df868c56f099f14c3c5cb39c1eef724ba762, captured at 2560x1440 with Playwright Chromium through openadapt-cloud scripts/capture-public-previews.mjs against the local Cloud mock UI. The runtime-mode banner and the account chip are hidden during capture because both report the environment the capture ran in, not the product. The fixture is synthetic OpenEMR patient registration. Byte-identical source: OpenAdaptAI/openadapt-web, public/product-preview/dashboard-workflows.png. SHA-256: - f9f894a60e44b266f16b8d138d8747e1a1fb639bf92370db6adbf4d4aab5bde4. + d93431712b5b36addf77fb5600e8b5f208291b80776940c1c76f9c7b4f6b4679. diff --git a/docs/assets/screenshots/dashboard-overview.png b/docs/assets/screenshots/dashboard-overview.png index d2e1e14..f7c81e7 100644 Binary files a/docs/assets/screenshots/dashboard-overview.png and b/docs/assets/screenshots/dashboard-overview.png differ diff --git a/docs/assets/screenshots/program-state-live-relation.png b/docs/assets/screenshots/program-state-live-relation.png new file mode 100644 index 0000000..b647069 Binary files /dev/null and b/docs/assets/screenshots/program-state-live-relation.png differ diff --git a/docs/assets/screenshots/program-workbench-cli.png b/docs/assets/screenshots/program-workbench-cli.png new file mode 100644 index 0000000..4b81c34 Binary files /dev/null and b/docs/assets/screenshots/program-workbench-cli.png differ diff --git a/docs/assets/screenshots/program-workbench-cloud.png b/docs/assets/screenshots/program-workbench-cloud.png new file mode 100644 index 0000000..c26c02c Binary files /dev/null and b/docs/assets/screenshots/program-workbench-cloud.png differ diff --git a/docs/assets/screenshots/program-workbench-desktop.png b/docs/assets/screenshots/program-workbench-desktop.png new file mode 100644 index 0000000..828af9f Binary files /dev/null and b/docs/assets/screenshots/program-workbench-desktop.png differ diff --git a/docs/assets/visual-palette.json b/docs/assets/visual-palette.json index 2c135c4..8273f75 100644 --- a/docs/assets/visual-palette.json +++ b/docs/assets/visual-palette.json @@ -28,13 +28,13 @@ "screenshots/dashboard-overview.png": { "source_repository": "OpenAdaptAI/openadapt-web", "source_path": "public/product-preview/dashboard-workflows.png", - "sha256": "f9f894a60e44b266f16b8d138d8747e1a1fb639bf92370db6adbf4d4aab5bde4", + "sha256": "d93431712b5b36addf77fb5600e8b5f208291b80776940c1c76f9c7b4f6b4679", "width": 2560, "height": 1440, "dominant_colors": [ { "hex": "#ffffff", - "share_percent": 46.48 + "share_percent": 46.49 }, { "hex": "#f5f7fa", @@ -216,6 +216,94 @@ "share_percent": 11.5 } ] + }, + "screenshots/program-state-live-relation.png": { + "source_repository": "OpenAdaptAI/openadapt-web", + "source_path": null, + "note": "The public-synthetic Program State Console, captured for these docs rather than vendored: openadapt-web publishes the component, not a still of it. The console is built from the canonical tokens, so its ground is cool by construction.", + "sha256": "676f0e57c4a19a490d4c9ee9bfccaecfb44dfe99d83febf24fc4f00c2fc1ae13", + "width": 1440, + "height": 1000, + "dominant_colors": [ + { + "hex": "#f6f7fb", + "share_percent": 23.08 + }, + { + "hex": "#f9fafc", + "share_percent": 7.55 + }, + { + "hex": "#0c1220", + "share_percent": 3.92 + } + ] + }, + "screenshots/program-workbench-cloud.png": { + "source_repository": "OpenAdaptAI/openadapt-cloud", + "source_path": null, + "note": "The remote-safe Program map in Cloud local mock mode, captured for these docs. The workbench canvas is the canonical dark inset, which is why the dominant colour is #0c1220 rather than a page ground.", + "sha256": "0f77308464f618efcb04814b411eb322af779699d33298ea9f0e57f7edab6d6e", + "width": 1280, + "height": 720, + "dominant_colors": [ + { + "hex": "#0c1220", + "share_percent": 19.7 + }, + { + "hex": "#f6f7fb", + "share_percent": 13.78 + }, + { + "hex": "#121a27", + "share_percent": 11.0 + } + ] + }, + "screenshots/program-workbench-cli.png": { + "source_repository": "OpenAdaptAI/openadapt-flow", + "source_path": null, + "note": "A self-contained `openadapt flow visualize` HTML export. It is generated output rather than product chrome, and its ground is plain white.", + "sha256": "aa5ff1e1455b0444f234f398e3f645490b974c3b48c5e38156fd041964fec4d2", + "width": 1280, + "height": 720, + "dominant_colors": [ + { + "hex": "#ffffff", + "share_percent": 26.46 + }, + { + "hex": "#0c1220", + "share_percent": 14.34 + }, + { + "hex": "#131b28", + "share_percent": 9.43 + } + ] + }, + "screenshots/program-workbench-desktop.png": { + "source_repository": "OpenAdaptAI/openadapt-desktop", + "source_path": null, + "note": "The development-only qualification workbench preview at ?surface=program-workbench-preview, captured at 1440x1000 from openadapt-desktop ebc10b037533f7adc0b12e0664d718d373245108, which is the first commit carrying the canonical tokens (its #139). The first capture came from a build before that merge and grounded on the retired #f2f1ed.", + "sha256": "4fbc62dd9ee5b48f758aca0ed5a13e072b3e0a4b6fc391847202297673f12e3f", + "width": 1440, + "height": 1000, + "dominant_colors": [ + { + "hex": "#f5f7fa", + "share_percent": 35.05 + }, + { + "hex": "#ffffff", + "share_percent": 13.71 + }, + { + "hex": "#0b1220", + "share_percent": 11.29 + } + ] } } } diff --git a/docs/concepts/program-visualizer.md b/docs/concepts/program-visualizer.md index c8483ce..14c6de2 100644 --- a/docs/concepts/program-visualizer.md +++ b/docs/concepts/program-visualizer.md @@ -1,61 +1,193 @@ -# The program visualizer +# Read a compiled program and its live evidence -A compiled bundle is a program, not a recording. Before you trust it in a -deployment, read it: what steps it takes, how it finds each target, where it -refuses, where it can stop. The visualizer renders that graph from the bundle -itself, so what you review is the artifact that actually runs. +A compiled bundle is a program, not a video. Before you approve it, inspect the +steps it can take, the evidence each action needs, and the paths that stop the +run. During a run, inspect a second object: the exact program occurrence and the +current evidence that the runtime bound to it. -## What the graph shows +
+ ![The Program State Console compares retained recorded evidence with the exact current application frame. The current target is outlined only after the runtime binds its geometry to that frame.](../assets/screenshots/program-state-live-relation.png){ width="1180" } +
The public synthetic console plays one retained event trace. The program stays fixed while the current observation, target resolution, identity check, action, screen check, and effect check advance.
+
-For each step the visualizer surfaces the parts that decide whether a run is safe: +## Two timelines, four views -- **Steps, in order.** The action at each step and the target it acts on. -- **The resolution ladder.** The ordered rungs a step tries to re-find its - target at replay time (structural element match, template, OCR, landmark - geometry, and optionally a grounding model). The ladder shows how much drift a - step can absorb before it halts. See - [the capability ladder](capability-ladder.md). -- **Armed identity gates.** Which steps re-verify identity before acting, and - which do not. An unarmed step has no identity check at all, and the graph - shows that rather than leaving it implied. See - [the identity gate](identity-gate.md). -- **Effect checks.** Which writes carry a typed effect verified against the - system of record. See [effect verification](effect-verification.md). -- **Halt points.** Every place the run may stop: a low-confidence match on an - irreversible step, a failed postcondition, a refuted write, an ambiguous - target. This is the run's stop map. +The workbench keeps two timelines separate. -For a program bundle it also shows the structure the linear case hides: loops -and their bounds, guarded transitions, and exception paths. +1. The **program artifact** moves from recorded evidence to a compiled version. + A repair creates a new candidate version. It doesn't change the version that + is running. +2. **One live run** moves through current observation, target resolution, + identity, action, and verification. Each event has an exact sequence number. -## One graph, three renderings +The four views answer different questions: -The CLI reads the bundle and emits one of three formats from the same -[graph spec](../reference/bundle-format.md): +| View | Question | Source | +|---|---|---| +| Program map | What can this version do? | Compiled nodes and exact edges | +| Live relation | How does the current observation relate to the retained evidence? | One frame-bound runtime occurrence | +| Evidence lanes | Which target, identity, screen, and effect controls exist or passed? | Declared contract or exact run verdict | +| Repair | What would change in a new version? | A separate candidate and its review state | + +Do not combine a declared control with a live verdict. A compiled node can say +that an identity gate is armed. Only a bound run event can say that the current +identity passed. + +## Read the program map + +The program map follows the emitted edge targets. It does not arrange the nodes +as if the bundle were a linear list. Branches, loop returns, exception paths, +and terminal states remain visible. + +For each node, inspect these lanes: + +- **Target evidence.** The retained structural locator, template, OCR anchor, + relational landmarks, or geometry that the resolver may use. +- **Identity.** The pre-action identity contract and whether it is armed. +- **Screen check.** The postcondition that the runtime checks after the action. +- **Effect check.** The independent system-of-record check for a declared + business effect. +- **Stop rules.** The conditions that make the runtime halt before or after a + delivery boundary. + +
+ ![The OpenAdapt Cloud program workbench renders compiled nodes and exact directed edges beside an inspector for the selected step.](../assets/screenshots/program-workbench-cloud.png){ width="1180" } +
Cloud shows the shared graph projection. Select a node to inspect its declared resolution, identity, screen, and effect lanes.
+
+ +A terminal node named `End of declared steps` means that graph traversal ended. +It does not prove `VERIFIED`. The run outcome still depends on the exact +authorization, identity, postcondition, and effect evidence required by the +execution profile. + +## Follow one live occurrence + +The same program node can run more than once inside a loop. A useful live view +must identify one occurrence. It should retain the graph id, state id, program +scope, incoming edge, and event sequence when the runtime provides them. The UI +must not identify an occurrence from a row number or animation time. + +The current marker advances only when the runtime emits an event. Controlled +playback is useful for review, but it must replay the retained sequence. It must +not infer a missing phase. + +The comparison view can show: + +- the retained recorded frame and its asset reference; +- the exact current frame and decoded frame index; +- typed facts such as role, text, layout delta, candidate count, and identity; +- the resolver decision and the evidence rung that supported it; +- the exact target rectangle when the runtime bound it to the displayed frame; +- the post-action screen check and independent effect verdict. + +If the runtime did not retain a frame binding, show the status without a target +rectangle. Do not carry a rectangle forward, interpolate it, or rebuild it from +a selector in the viewer. + +## Show disagreement without hiding it + +A single similarity score is not enough. It can hide a disagreement that +matters. Show the typed facts that drove the decision. + +| Difference | Useful display | Safe runtime meaning | +|---|---|---| +| Layout moved | Recorded and current rectangles, plus the measured delta | The target can still resolve if retained evidence supports one current candidate | +| Text changed | Recorded text, current text, and match verdict | Continue only if the declared text rule passes | +| Role changed | Recorded and current structural role | Treat a required role mismatch as refuted evidence | +| Multiple candidates | Candidate count and ambiguity reason | Halt before action | +| Identity conflict | Bound identity signals and their verdicts | Halt before action | +| Fresh frame changed | Pre-action observation and revalidation verdict | Halt or reconcile according to the delivery state | +| Effect is uncertain | Independent effect evidence and transaction outcome | Return `RECONCILIATION_REQUIRED`; never retry blindly | + +The viewer can use a neutral difference overlay for review. It cannot turn a +pixel difference into target resolution, identity proof, or effect proof. + +## Keep repair separate from execution + +A halted run can retain useful repair evidence. A repair view should show the +source version, the proposed locator or contract change, the changed nodes and +edges, the reason for the proposal, and the trials required before promotion. + +The proposal is a new artifact. It does not edit the running version. Review, +qualification, and admission remain separate steps. If a repair candidate is +not bound to the exact halt evidence, the UI should not present it as the fix +for that run. + +## Use the right projection + +OpenAdapt uses the same graph contract across its surfaces, but each surface +has a different data boundary. + +
+ ![The OpenAdapt Desktop qualification workbench shows a local compiled program with exact loops, stop paths, and selected-step evidence.](../assets/screenshots/program-workbench-desktop.png){ width="1180" } +
Desktop can show local operator detail. It says when no exact live trace is bound, so a static qualification contract cannot look like runtime evidence.
+
+ +| Surface | Projection | Intended use | +|---|---|---| +| Desktop | `operator-local` | Local qualification and private evidence review | +| Cloud | `remote-safe` | Tenant-bound topology and reviewed remote-safe labels | +| Website | `public-synthetic` | Interactive product explanation with synthetic evidence | +| Exported report | `sanitized-derivative` | Hash-bound review artifact with an explicit egress decision | + +A projection removes fields from a view. It does not sanitize the source bundle. +Keep the original inside its trusted boundary. + +## Render the graph offline + +The CLI reads the bundle and writes HTML, Mermaid, or JSON from the same graph +specification. HTML is self-contained. It uses a deterministic edge layout and +does not load a graph library or a network asset. ```bash -openadapt flow visualize bundle -o graph.html # self-contained page -openadapt flow visualize bundle --format mermaid # flowchart source -openadapt flow visualize bundle --format json # the shared graph spec +openadapt flow visualize bundle -o graph.html +openadapt flow visualize bundle --profile remote-safe -o review.html +openadapt flow visualize bundle --profile public-synthetic -o public.html +openadapt flow visualize bundle --format mermaid +openadapt flow visualize bundle --format json ``` -- **HTML** is a self-contained page you can open offline and hand to a reviewer. -- **Mermaid** is flowchart source you can paste into a Markdown file or design - doc. -- **JSON** is the shared program-graph spec. The Cloud and desktop surfaces - render the same spec, so a reviewer in Cloud and an engineer at the CLI see - the same graph. - -## Reading is safe +
+ ![The self-contained OpenAdapt Flow visualizer shows a public-safe loop program and exact return edges.](../assets/screenshots/program-workbench-cli.png){ width="1180" } +
The offline view keeps the topology and declared controls. A non-local profile removes recorded values, target text, selectors, URLs, guard text, and local provenance.
+
`visualize` never runs the workflow. It reads the bundle and describes it with -no side effects, so you can point it at any bundle, including one that would -refuse to certify. That is the intended order: visualize the program, -[lint](policy-and-certify.md) its coverage gaps, certify it against a policy, -then run it. +no side effects. You can inspect a bundle that will later refuse certification. +The normal order is to visualize the program, lint its contract, qualify the +exact version, and then run it. + +## Rendering choices + +The current renderer uses semantic HTML for nodes, SVG for exact edges, and a +small deterministic layout function. The website uses controlled CSS motion for +its retained event playback. This keeps the offline export self-contained and +keeps every node available to a screen reader. + +| Option | Strength | Cost or limit | Decision | +|---|---|---|---| +| HTML, SVG, and local layout | Small payload, offline output, accessible nodes, exact edge control | The layout code must handle each supported graph form | Use now | +| React Flow | Strong pan, zoom, selection, and future editing tools | Adds a client dependency and editor concepts that a read-only review does not need | Consider for a future repair editor | +| ELK or Dagre | Better automatic layout for large nested graphs | Adds bundle weight and can move nodes between releases when layout settings change | Add when real graphs exceed the local layout limits | +| Mermaid | Easy export into documents | Limited evidence inspector and live-state interaction | Keep as an export format | +| Canvas or WebGL | Handles very large graphs | Weaker native accessibility and more work for text selection and printing | Do not use for the normal review surface | +| A pixel-difference library | Useful local review overlay | A difference score is not resolution, identity, or effect evidence | Permit only as a local review aid | +| A motion library | Useful for complex transitions | More runtime code; animation time can be mistaken for event time | Use controlled CSS motion until a real need appears | + +The layout switch point should come from measured graph size and interaction +latency. It should not come from the wish to make the graph look more animated. + +## Visual review checklist -## In Cloud +Before you approve a program or a run view, check these items: -The same graph appears in the Cloud workspace on a workflow's page, so a -reviewer who never touches the CLI can read the compiled program, its gates, and -its halt points before approving a version for deployment. +- Every displayed connection comes from an emitted edge. +- Every live state comes from an exact runtime event. +- A loop occurrence has enough scope data to distinguish it from another pass. +- Recorded and current media have explicit asset and frame references. +- The target rectangle is bound to the displayed frame or is absent. +- A declared gate does not appear as a passed gate. +- A halted run shows whether delivery was attempted or remains unknown. +- A repair appears as a candidate version with a review path. +- A terminal graph state does not appear as a verified business outcome. +- A remote or public view contains only fields allowed by its projection. diff --git a/docs/reference/cli.md b/docs/reference/cli.md index a8648fd..42b977f 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -687,6 +687,7 @@ See [Visualize a compiled program](../concepts/program-visualizer.md). ```bash openadapt flow visualize bundle -o graph.html # self-contained page +openadapt flow visualize bundle --profile remote-safe -o review.html openadapt flow visualize bundle --format mermaid # flowchart source, to stdout openadapt flow visualize bundle --format json # the shared graph spec ``` @@ -695,6 +696,7 @@ openadapt flow visualize bundle --format json # the shared graph spec |---|---| | `bundle` (positional) | Workflow bundle directory | | `--format {html,mermaid,json}` | `html` (default): a self-contained, offline-openable page. `mermaid`: flowchart source for Markdown and docs. `json`: the shared program-graph spec every surface renders. | +| `--profile {operator-local,remote-safe,public-synthetic,sanitized-derivative}` | Select the fields allowed in the output. Non-local profiles keep topology and remove recorded values, target text, selectors, URLs, guard text, and local provenance. A projection does not sanitize the source bundle. | | `-o`, `--out FILE` | Write to a file instead of stdout (parent directories are created) | Reading is offline and side-effect-free: `visualize` never runs the workflow, so