Skip to content

feat(console): localhost operator console over bundles, runs, and skill lineage - #133

Merged
abrichr merged 3 commits into
mainfrom
feat/operator-console
Jul 18, 2026
Merged

feat(console): localhost operator console over bundles, runs, and skill lineage#133
abrichr merged 3 commits into
mainfrom
feat/operator-console

Conversation

@abrichr

@abrichr abrichr commented Jul 17, 2026

Copy link
Copy Markdown
Member

What

openadapt-flow console — the thin operator console: a localhost-only web UI for the one operator who governs production workflows. It is a read-first projection of artifacts the engine already writes (bundle dirs, report.json run dirs, durable pause/approval records, skills.json libraries) plus governance actions wired only to existing verbs. No new engine semantics anywhere.

Surface decision (extend #1008 / revive openadapt-console / new module?)

New module in openadapt-flow (openadapt_flow/console/), for three reasons:

  • OpenAdapt PR #1008 (openadapt panel) fronts the legacy record→train→eval pipeline in the OpenAdapt repo — none of flow's bundle/run/certification model exists there, and the PR is currently conflicting. Its pattern (FastAPI + loopback + a small SPA + a lazy CLI verb) is deliberately mirrored here; its code is the wrong substrate.
  • openadapt-console is a 2-commit Next.js/Vercel MVP from March tied to the old trace schema — a Node toolchain and a deploy-oriented stack for what must be a zero-dependency localhost tool, and it cannot import flow's loaders.
  • Flow already has every loader and gate the console needs (Workflow.load, RunReport, CheckpointStore, SkillLibrary, evaluate_policy, lint_workflow, the identity/effect policy helpers) and FastAPI is an established in-repo pattern (services/vlm_service). This ships in one PR with zero cloud coupling.

Screens (real capture from a live fixture session)

Workflow inventory — version, certification, PHI/encryption flags, last run:
workflows

Workflow detail — identity-armed coverage, effect-contract coverage over irreversible steps, live evaluate_policy violations, compiled steps, lint, diff picker, actions with exact commands:
detail

Bundle-to-bundle diff:
diff

Run history and a halted run with inline evidence (halt reason, PHI-scrubbed observed texts, step screenshots) plus the exact teach command to copy:
runs
halted

Durably paused run — escalation record, checkpoints, and confirm-gated approve/resume:
paused

Skill-library lineage with governed promote / rollback:
skills

Governance posture

  • Loopback only: bind address is hardcoded 127.0.0.1 (no flag).
  • Read-only by default: every mutating endpoint refuses with 403 plus the exact CLI command to copy; --allow-actions opts in, and the UI always shows the command before a confirm.
  • Existing verbs only: approve/resume/certify shell out to the CLI (module-invoked, no shell); promote/rollback call the same SkillLibrary.promote/.quarantine entry points the teach pipeline uses; teach needs a fix demonstration, so it is render-only — never faked.
  • Traversal-safe: URL ids resolve by re-scanning the roots and matching (never path-joined); run artifacts are served only after a containment check.
  • Degrades gracefully: encrypted-without-key / corrupt bundles stay listed with a load_error; effect coverage reports honest n/a (not a fabricated 100%) when a bundle has no irreversible step; missing certification renders the certify command instead of a fake verdict.

Tests

tests/test_console.py: 28 tests over real Workflow.save / RunReport.save / CheckpointStore / SkillLibrary artifacts — projections, coverage numbers vs the policy helpers, diff, halt/pause evidence, artifact traversal refusal, read-only 403-with-command, teach-never-executes, approve subprocess argv, promote/rollback round-trip, and a loopback uvicorn boot smoke test. Local: full fast suite 1862 passed, 16 skipped; ruff check + format and mypy clean.

Packaging: new optional extra openadapt-flow[console] (fastapi + uvicorn); uvicorn added to dev for the smoke test; static UI force-included in the wheel.

Not in scope (deliberately)

  • No auth layer (loopback binding is the boundary; do not expose).
  • No bundle editing, no new run-launch semantics (run is rendered for the deployment terminal).
  • Effect-verification coverage reads only declared Step.effects — when richer coverage fields land in reports (effect-kit work), the same cards can consume them.

🤖 Generated with Claude Code

abrichr and others added 3 commits July 17, 2026 16:38
…ll lineage

The thin operator surface for governing production workflows without the
terminal: `openadapt-flow console` serves a loopback-only (127.0.0.1,
hardcoded) FastAPI app + single-file UI that PROJECTS the artifacts the
engine already writes — no new engine semantics anywhere.

- Workflow list: every bundle under a root, with sealed compiler version /
  content digest / certification status / PHI + encryption flags, joined to
  its newest run.
- Workflow detail: compiled steps (risk, identity armed/unarmed + reason,
  effect contracts, postconditions, confidence), identity coverage and
  effect-contract coverage over irreversible steps (honest n/a when a bundle
  has no consequential step), lint findings, sealed certification + live
  evaluate_policy violations, and step-level diffs between any two bundles.
  All numbers come from the SAME policy helpers the lint/certify verbs use.
- Run history + detail: per-step timeline with identity verdicts, effect
  verdicts, resolution rung, and inline before/after screenshots (served
  traversal-safe from the run dir); the structured HALT observation
  (reason, PHI-scrubbed observed texts, completed pre-context); durable
  pause/approval records and checkpoint listing.
- Skill libraries: per-skill version lineage (active/candidate/superseded/
  rolled_back, scores, provenance).
- Governance actions are the EXISTING verbs only: approve/resume/certify
  shell out to the CLI; promote/rollback call the same SkillLibrary entry
  points the teach pipeline uses; teach (needs a fix demonstration) is
  rendered as the exact command to copy, never faked. The server starts
  READ-ONLY — every mutating endpoint refuses with 403 + the exact command
  unless --allow-actions, and the UI shows the command before any confirm.

Degrades gracefully: encrypted/corrupt bundles stay listed with a load
error, reports predating a field render without it.

Tests: 28 route/behavior tests over real Workflow.save/RunReport.save/
CheckpointStore/SkillLibrary artifacts, incl. a loopback uvicorn boot smoke
test; ruff + mypy clean. New optional extra: openadapt-flow[console]
(fastapi + uvicorn); uvicorn added to dev for the smoke test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Captured headless (chromium) against `openadapt-flow console` serving a
MockMed triage fixture: workflow inventory, coverage + live certification,
bundle diff, run history, halt evidence with inline screenshots, durable
pause, and skill-library lineage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Hatchling ships package data by default, so the explicit force-include of
openadapt_flow/console/static/ collided with the default inclusion and
failed the wheel build with a duplicate-path error. Wheel verified to
contain the static UI without it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@abrichr
abrichr marked this pull request as draft July 17, 2026 22:36
@abrichr
abrichr marked this pull request as ready for review July 18, 2026 17:36
@abrichr
abrichr merged commit 5b21c2f into main Jul 18, 2026
13 checks passed
@abrichr
abrichr deleted the feat/operator-console branch July 18, 2026 17:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant