From ed2ac3fa5706605f820d7d2783ecd3c8ed748a2b Mon Sep 17 00:00:00 2001 From: abrichr Date: Mon, 19 Oct 2026 11:26:00 -0400 Subject: [PATCH] ci: one file per openadapt-flow command for the capability map CAPABILITIES.md listed each capability's commands on one line, so any two pull requests that added commands to the same capability conflicted. Each command now has packages/flow/docs/commands//.md (Markdown, so outside the flow artifact inventory). scripts/build_command_map.py renders the "Every command, by capability" list from those files, one command per line. tests/test_capabilities_map.py reads the command names from the files, fails on a command without a file, a file without a command, or a stale list. Co-Authored-By: Claude Opus 5.5 --- CAPABILITIES.md | 117 ++++++++++++++++-- CLAUDE.md | 6 +- .../commands/01-record-and-build/README.md | 1 + .../commands/01-record-and-build/compile.md | 0 .../commands/01-record-and-build/compose.md | 0 .../01-record-and-build/demo-record.md | 0 .../01-record-and-build/disambiguate.md | 0 .../commands/01-record-and-build/for-each.md | 0 .../commands/01-record-and-build/induce.md | 0 .../commands/01-record-and-build/intake.md | 0 .../commands/01-record-and-build/process.md | 0 .../docs/commands/01-record-and-build/pull.md | 0 .../commands/01-record-and-build/record.md | 0 .../commands/01-record-and-build/route.md | 0 .../commands/01-record-and-build/variants.md | 0 .../commands/01-record-and-build/visualize.md | 0 .../commands/02-check-and-admit/README.md | 1 + .../docs/commands/02-check-and-admit/admit.md | 0 .../docs/commands/02-check-and-admit/api.md | 0 .../02-check-and-admit/approver-grant.md | 0 .../02-check-and-admit/bind-record-checks.md | 0 .../commands/02-check-and-admit/certify.md | 0 .../docs/commands/02-check-and-admit/check.md | 0 .../docs/commands/02-check-and-admit/jit.md | 0 .../commands/02-check-and-admit/known-ids.md | 0 .../docs/commands/02-check-and-admit/lint.md | 0 .../propose-qualification.md | 0 .../commands/02-check-and-admit/qualify.md | 0 .../02-check-and-admit/scaffold-verifier.md | 0 .../docs/commands/03-run-and-answer/README.md | 1 + .../commands/03-run-and-answer/approve.md | 0 .../03-run-and-answer/business-decisions.md | 0 .../commands/03-run-and-answer/console.md | 0 .../commands/03-run-and-answer/explain.md | 0 .../03-run-and-answer/item-approval.md | 0 .../docs/commands/03-run-and-answer/replay.md | 0 .../docs/commands/03-run-and-answer/resume.md | 0 .../docs/commands/03-run-and-answer/run.md | 0 .../docs/commands/03-run-and-answer/triage.md | 0 .../commands/04-judge-any-executor/README.md | 1 + .../04-judge-any-executor/serve-reward.md | 1 + .../04-judge-any-executor/verify-run.md | 0 .../commands/05-repair-and-learn/README.md | 1 + .../commands/05-repair-and-learn/fleet.md | 0 .../commands/05-repair-and-learn/repair.md | 0 .../05-repair-and-learn/teach-branch.md | 0 .../commands/05-repair-and-learn/teach.md | 0 .../docs/commands/05-repair-and-learn/undo.md | 1 + .../06-give-agents-the-program/README.md | 1 + .../06-give-agents-the-program/emit-mcp.md | 0 .../06-give-agents-the-program/emit-skill.md | 0 .../serve-execute.md | 0 .../flow/docs/commands/07-proof/README.md | 1 + .../docs/commands/07-proof/attach-seal.md | 0 .../docs/commands/07-proof/countersign.md | 0 .../flow/docs/commands/07-proof/local-seal.md | 0 packages/flow/docs/commands/07-proof/seal.md | 0 .../commands/08-run-on-premises/README.md | 1 + .../08-run-on-premises/no-outbound.md | 0 .../commands/08-run-on-premises/service.md | 0 .../commands/09-share-with-cloud/README.md | 1 + .../09-share-with-cloud/approve-sanitized.md | 0 .../commands/09-share-with-cloud/connect.md | 0 .../commands/09-share-with-cloud/connector.md | 0 .../commands/09-share-with-cloud/login.md | 0 .../materialize-approved.md | 0 .../docs/commands/09-share-with-cloud/push.md | 0 .../09-share-with-cloud/report-break.md | 0 .../09-share-with-cloud/report-run.md | 0 .../09-share-with-cloud/review-sanitized.md | 0 .../commands/09-share-with-cloud/sanitize.md | 0 .../09-share-with-cloud/validate-hosted.md | 0 .../commands/10-try-and-measure/README.md | 1 + .../docs/commands/10-try-and-measure/bench.md | 0 .../commands/10-try-and-measure/benchmark.md | 0 .../docs/commands/10-try-and-measure/demo.md | 0 .../commands/10-try-and-measure/tutorial.md | 0 packages/flow/docs/commands/README.md | 17 +++ packages/flow/tests/test_capabilities_map.py | 46 +++++-- scripts/build_command_map.py | 84 +++++++++++++ 80 files changed, 255 insertions(+), 27 deletions(-) create mode 100644 packages/flow/docs/commands/01-record-and-build/README.md create mode 100644 packages/flow/docs/commands/01-record-and-build/compile.md create mode 100644 packages/flow/docs/commands/01-record-and-build/compose.md create mode 100644 packages/flow/docs/commands/01-record-and-build/demo-record.md create mode 100644 packages/flow/docs/commands/01-record-and-build/disambiguate.md create mode 100644 packages/flow/docs/commands/01-record-and-build/for-each.md create mode 100644 packages/flow/docs/commands/01-record-and-build/induce.md create mode 100644 packages/flow/docs/commands/01-record-and-build/intake.md create mode 100644 packages/flow/docs/commands/01-record-and-build/process.md create mode 100644 packages/flow/docs/commands/01-record-and-build/pull.md create mode 100644 packages/flow/docs/commands/01-record-and-build/record.md create mode 100644 packages/flow/docs/commands/01-record-and-build/route.md create mode 100644 packages/flow/docs/commands/01-record-and-build/variants.md create mode 100644 packages/flow/docs/commands/01-record-and-build/visualize.md create mode 100644 packages/flow/docs/commands/02-check-and-admit/README.md create mode 100644 packages/flow/docs/commands/02-check-and-admit/admit.md create mode 100644 packages/flow/docs/commands/02-check-and-admit/api.md create mode 100644 packages/flow/docs/commands/02-check-and-admit/approver-grant.md create mode 100644 packages/flow/docs/commands/02-check-and-admit/bind-record-checks.md create mode 100644 packages/flow/docs/commands/02-check-and-admit/certify.md create mode 100644 packages/flow/docs/commands/02-check-and-admit/check.md create mode 100644 packages/flow/docs/commands/02-check-and-admit/jit.md create mode 100644 packages/flow/docs/commands/02-check-and-admit/known-ids.md create mode 100644 packages/flow/docs/commands/02-check-and-admit/lint.md create mode 100644 packages/flow/docs/commands/02-check-and-admit/propose-qualification.md create mode 100644 packages/flow/docs/commands/02-check-and-admit/qualify.md create mode 100644 packages/flow/docs/commands/02-check-and-admit/scaffold-verifier.md create mode 100644 packages/flow/docs/commands/03-run-and-answer/README.md create mode 100644 packages/flow/docs/commands/03-run-and-answer/approve.md create mode 100644 packages/flow/docs/commands/03-run-and-answer/business-decisions.md create mode 100644 packages/flow/docs/commands/03-run-and-answer/console.md create mode 100644 packages/flow/docs/commands/03-run-and-answer/explain.md create mode 100644 packages/flow/docs/commands/03-run-and-answer/item-approval.md create mode 100644 packages/flow/docs/commands/03-run-and-answer/replay.md create mode 100644 packages/flow/docs/commands/03-run-and-answer/resume.md create mode 100644 packages/flow/docs/commands/03-run-and-answer/run.md create mode 100644 packages/flow/docs/commands/03-run-and-answer/triage.md create mode 100644 packages/flow/docs/commands/04-judge-any-executor/README.md create mode 100644 packages/flow/docs/commands/04-judge-any-executor/serve-reward.md create mode 100644 packages/flow/docs/commands/04-judge-any-executor/verify-run.md create mode 100644 packages/flow/docs/commands/05-repair-and-learn/README.md create mode 100644 packages/flow/docs/commands/05-repair-and-learn/fleet.md create mode 100644 packages/flow/docs/commands/05-repair-and-learn/repair.md create mode 100644 packages/flow/docs/commands/05-repair-and-learn/teach-branch.md create mode 100644 packages/flow/docs/commands/05-repair-and-learn/teach.md create mode 100644 packages/flow/docs/commands/05-repair-and-learn/undo.md create mode 100644 packages/flow/docs/commands/06-give-agents-the-program/README.md create mode 100644 packages/flow/docs/commands/06-give-agents-the-program/emit-mcp.md create mode 100644 packages/flow/docs/commands/06-give-agents-the-program/emit-skill.md create mode 100644 packages/flow/docs/commands/06-give-agents-the-program/serve-execute.md create mode 100644 packages/flow/docs/commands/07-proof/README.md create mode 100644 packages/flow/docs/commands/07-proof/attach-seal.md create mode 100644 packages/flow/docs/commands/07-proof/countersign.md create mode 100644 packages/flow/docs/commands/07-proof/local-seal.md create mode 100644 packages/flow/docs/commands/07-proof/seal.md create mode 100644 packages/flow/docs/commands/08-run-on-premises/README.md create mode 100644 packages/flow/docs/commands/08-run-on-premises/no-outbound.md create mode 100644 packages/flow/docs/commands/08-run-on-premises/service.md create mode 100644 packages/flow/docs/commands/09-share-with-cloud/README.md create mode 100644 packages/flow/docs/commands/09-share-with-cloud/approve-sanitized.md create mode 100644 packages/flow/docs/commands/09-share-with-cloud/connect.md create mode 100644 packages/flow/docs/commands/09-share-with-cloud/connector.md create mode 100644 packages/flow/docs/commands/09-share-with-cloud/login.md create mode 100644 packages/flow/docs/commands/09-share-with-cloud/materialize-approved.md create mode 100644 packages/flow/docs/commands/09-share-with-cloud/push.md create mode 100644 packages/flow/docs/commands/09-share-with-cloud/report-break.md create mode 100644 packages/flow/docs/commands/09-share-with-cloud/report-run.md create mode 100644 packages/flow/docs/commands/09-share-with-cloud/review-sanitized.md create mode 100644 packages/flow/docs/commands/09-share-with-cloud/sanitize.md create mode 100644 packages/flow/docs/commands/09-share-with-cloud/validate-hosted.md create mode 100644 packages/flow/docs/commands/10-try-and-measure/README.md create mode 100644 packages/flow/docs/commands/10-try-and-measure/bench.md create mode 100644 packages/flow/docs/commands/10-try-and-measure/benchmark.md create mode 100644 packages/flow/docs/commands/10-try-and-measure/demo.md create mode 100644 packages/flow/docs/commands/10-try-and-measure/tutorial.md create mode 100644 packages/flow/docs/commands/README.md create mode 100644 scripts/build_command_map.py diff --git a/CAPABILITIES.md b/CAPABILITIES.md index c9125ded3a..17dacd7238 100644 --- a/CAPABILITIES.md +++ b/CAPABILITIES.md @@ -224,19 +224,110 @@ improvising or retrying when something is off. ## Every command, by capability -Each `openadapt-flow` command, grouped by the capability it serves. A test -fails when a command is added without being listed here. - -- **Record and build a program:** `record`, `demo-record`, `compile`, `induce`, `disambiguate`, `for-each`, `compose`, `process`, `intake`, `visualize`, `pull`, `variants`, `route`. -- **Check and admit:** `lint`, `scaffold-verifier`, `check`, `api`, `bind-record-checks`, `certify`, `qualify`, `propose-qualification`, `known-ids`, `jit`, `admit`, `approver-grant`. -- **Run and answer:** `run`, `replay`, `resume`, `approve`, `item-approval`, `triage`, `business-decisions`, `explain`, `console`. -- **Judge any executor's write:** `verify-run`, `serve-reward` (scores agent training episodes by reading the system of record). -- **Repair and learn from halts:** `teach`, `teach-branch`, `repair`, `fleet`, `undo` (the undo steps a person approves after a stop). -- **Give agents the program:** `emit-skill`, `emit-mcp`, `serve-execute`. -- **Proof:** `seal`, `local-seal`, `countersign`, `attach-seal`. -- **Run on premises:** `service`, `no-outbound`. -- **Share safely with OpenAdapt Cloud:** `sanitize`, `review-sanitized`, `approve-sanitized`, `materialize-approved`, `push`, `validate-hosted`, `report-break`, `report-run`, `connect`, `login`, `connector`. -- **Try it and measure it:** `demo`, `tutorial`, `bench`, `benchmark`. +Each `openadapt-flow` command, grouped by the capability it serves. Each +command has one file under +[`packages/flow/docs/commands/`](packages/flow/docs/commands/): to add a +command, add `/.md` and run `python scripts/build_command_map.py`. +A test fails when a command has no file or this list is out of date. + + + +**Record and build a program:** + +- `compile` +- `compose` +- `demo-record` +- `disambiguate` +- `for-each` +- `induce` +- `intake` +- `process` +- `pull` +- `record` +- `route` +- `variants` +- `visualize` + +**Check and admit:** + +- `admit` +- `api` +- `approver-grant` +- `bind-record-checks` +- `certify` +- `check` +- `jit` +- `known-ids` +- `lint` +- `propose-qualification` +- `qualify` +- `scaffold-verifier` + +**Run and answer:** + +- `approve` +- `business-decisions` +- `console` +- `explain` +- `item-approval` +- `replay` +- `resume` +- `run` +- `triage` + +**Judge any executor's write:** + +- `serve-reward`: Scores agent training episodes by reading the system of record. +- `verify-run` + +**Repair and learn from halts:** + +- `fleet` +- `repair` +- `teach-branch` +- `teach` +- `undo`: The undo steps a person approves after a stop. + +**Give agents the program:** + +- `emit-mcp` +- `emit-skill` +- `serve-execute` + +**Proof:** + +- `attach-seal` +- `countersign` +- `local-seal` +- `seal` + +**Run on premises:** + +- `no-outbound` +- `service` + +**Share safely with OpenAdapt Cloud:** + +- `approve-sanitized` +- `connect` +- `connector` +- `login` +- `materialize-approved` +- `push` +- `report-break` +- `report-run` +- `review-sanitized` +- `sanitize` +- `validate-hosted` + +**Try it and measure it:** + +- `bench` +- `benchmark` +- `demo` +- `tutorial` + + ## Measured results diff --git a/CLAUDE.md b/CLAUDE.md index 69c740b664..c8f6278955 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -11,9 +11,9 @@ under `packages/flow`, next to `packages/agent`, `packages/types` and `packages/capture`. The standalone openadapt-flow, openadapt-agent and openadapt-types repositories are frozen; changes go here. [CAPABILITIES.md](CAPABILITIES.md) is the map of what exists and how proven -it is; update it in the same pull request as any capability change, and list -any new `openadapt-flow` command under "Every command, by capability" (a test -enforces it). Refresh the review brief with `python scripts/build_llms_full.py` when you +it is; update it in the same pull request as any capability change. For a +new `openadapt-flow` command, add `packages/flow/docs/commands//.md` +and run `python scripts/build_command_map.py` (a test enforces it). Refresh the review brief with `python scripts/build_llms_full.py` when you change README.md, CAPABILITIES.md, SURFACES.md, LIMITS.md or the flow CHANGELOG, and always before a release. diff --git a/packages/flow/docs/commands/01-record-and-build/README.md b/packages/flow/docs/commands/01-record-and-build/README.md new file mode 100644 index 0000000000..1ce1d01c88 --- /dev/null +++ b/packages/flow/docs/commands/01-record-and-build/README.md @@ -0,0 +1 @@ +# Record and build a program diff --git a/packages/flow/docs/commands/01-record-and-build/compile.md b/packages/flow/docs/commands/01-record-and-build/compile.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/01-record-and-build/compose.md b/packages/flow/docs/commands/01-record-and-build/compose.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/01-record-and-build/demo-record.md b/packages/flow/docs/commands/01-record-and-build/demo-record.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/01-record-and-build/disambiguate.md b/packages/flow/docs/commands/01-record-and-build/disambiguate.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/01-record-and-build/for-each.md b/packages/flow/docs/commands/01-record-and-build/for-each.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/01-record-and-build/induce.md b/packages/flow/docs/commands/01-record-and-build/induce.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/01-record-and-build/intake.md b/packages/flow/docs/commands/01-record-and-build/intake.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/01-record-and-build/process.md b/packages/flow/docs/commands/01-record-and-build/process.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/01-record-and-build/pull.md b/packages/flow/docs/commands/01-record-and-build/pull.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/01-record-and-build/record.md b/packages/flow/docs/commands/01-record-and-build/record.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/01-record-and-build/route.md b/packages/flow/docs/commands/01-record-and-build/route.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/01-record-and-build/variants.md b/packages/flow/docs/commands/01-record-and-build/variants.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/01-record-and-build/visualize.md b/packages/flow/docs/commands/01-record-and-build/visualize.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/02-check-and-admit/README.md b/packages/flow/docs/commands/02-check-and-admit/README.md new file mode 100644 index 0000000000..e1c6bd46cf --- /dev/null +++ b/packages/flow/docs/commands/02-check-and-admit/README.md @@ -0,0 +1 @@ +# Check and admit diff --git a/packages/flow/docs/commands/02-check-and-admit/admit.md b/packages/flow/docs/commands/02-check-and-admit/admit.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/02-check-and-admit/api.md b/packages/flow/docs/commands/02-check-and-admit/api.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/02-check-and-admit/approver-grant.md b/packages/flow/docs/commands/02-check-and-admit/approver-grant.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/02-check-and-admit/bind-record-checks.md b/packages/flow/docs/commands/02-check-and-admit/bind-record-checks.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/02-check-and-admit/certify.md b/packages/flow/docs/commands/02-check-and-admit/certify.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/02-check-and-admit/check.md b/packages/flow/docs/commands/02-check-and-admit/check.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/02-check-and-admit/jit.md b/packages/flow/docs/commands/02-check-and-admit/jit.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/02-check-and-admit/known-ids.md b/packages/flow/docs/commands/02-check-and-admit/known-ids.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/02-check-and-admit/lint.md b/packages/flow/docs/commands/02-check-and-admit/lint.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/02-check-and-admit/propose-qualification.md b/packages/flow/docs/commands/02-check-and-admit/propose-qualification.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/02-check-and-admit/qualify.md b/packages/flow/docs/commands/02-check-and-admit/qualify.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/02-check-and-admit/scaffold-verifier.md b/packages/flow/docs/commands/02-check-and-admit/scaffold-verifier.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/03-run-and-answer/README.md b/packages/flow/docs/commands/03-run-and-answer/README.md new file mode 100644 index 0000000000..104e7ad6bd --- /dev/null +++ b/packages/flow/docs/commands/03-run-and-answer/README.md @@ -0,0 +1 @@ +# Run and answer diff --git a/packages/flow/docs/commands/03-run-and-answer/approve.md b/packages/flow/docs/commands/03-run-and-answer/approve.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/03-run-and-answer/business-decisions.md b/packages/flow/docs/commands/03-run-and-answer/business-decisions.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/03-run-and-answer/console.md b/packages/flow/docs/commands/03-run-and-answer/console.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/03-run-and-answer/explain.md b/packages/flow/docs/commands/03-run-and-answer/explain.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/03-run-and-answer/item-approval.md b/packages/flow/docs/commands/03-run-and-answer/item-approval.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/03-run-and-answer/replay.md b/packages/flow/docs/commands/03-run-and-answer/replay.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/03-run-and-answer/resume.md b/packages/flow/docs/commands/03-run-and-answer/resume.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/03-run-and-answer/run.md b/packages/flow/docs/commands/03-run-and-answer/run.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/03-run-and-answer/triage.md b/packages/flow/docs/commands/03-run-and-answer/triage.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/04-judge-any-executor/README.md b/packages/flow/docs/commands/04-judge-any-executor/README.md new file mode 100644 index 0000000000..0be1ff6c31 --- /dev/null +++ b/packages/flow/docs/commands/04-judge-any-executor/README.md @@ -0,0 +1 @@ +# Judge any executor's write diff --git a/packages/flow/docs/commands/04-judge-any-executor/serve-reward.md b/packages/flow/docs/commands/04-judge-any-executor/serve-reward.md new file mode 100644 index 0000000000..646b7c5b55 --- /dev/null +++ b/packages/flow/docs/commands/04-judge-any-executor/serve-reward.md @@ -0,0 +1 @@ +Scores agent training episodes by reading the system of record. diff --git a/packages/flow/docs/commands/04-judge-any-executor/verify-run.md b/packages/flow/docs/commands/04-judge-any-executor/verify-run.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/05-repair-and-learn/README.md b/packages/flow/docs/commands/05-repair-and-learn/README.md new file mode 100644 index 0000000000..9d64b07b42 --- /dev/null +++ b/packages/flow/docs/commands/05-repair-and-learn/README.md @@ -0,0 +1 @@ +# Repair and learn from halts diff --git a/packages/flow/docs/commands/05-repair-and-learn/fleet.md b/packages/flow/docs/commands/05-repair-and-learn/fleet.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/05-repair-and-learn/repair.md b/packages/flow/docs/commands/05-repair-and-learn/repair.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/05-repair-and-learn/teach-branch.md b/packages/flow/docs/commands/05-repair-and-learn/teach-branch.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/05-repair-and-learn/teach.md b/packages/flow/docs/commands/05-repair-and-learn/teach.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/05-repair-and-learn/undo.md b/packages/flow/docs/commands/05-repair-and-learn/undo.md new file mode 100644 index 0000000000..155807d41a --- /dev/null +++ b/packages/flow/docs/commands/05-repair-and-learn/undo.md @@ -0,0 +1 @@ +The undo steps a person approves after a stop. diff --git a/packages/flow/docs/commands/06-give-agents-the-program/README.md b/packages/flow/docs/commands/06-give-agents-the-program/README.md new file mode 100644 index 0000000000..310c422d82 --- /dev/null +++ b/packages/flow/docs/commands/06-give-agents-the-program/README.md @@ -0,0 +1 @@ +# Give agents the program diff --git a/packages/flow/docs/commands/06-give-agents-the-program/emit-mcp.md b/packages/flow/docs/commands/06-give-agents-the-program/emit-mcp.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/06-give-agents-the-program/emit-skill.md b/packages/flow/docs/commands/06-give-agents-the-program/emit-skill.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/06-give-agents-the-program/serve-execute.md b/packages/flow/docs/commands/06-give-agents-the-program/serve-execute.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/07-proof/README.md b/packages/flow/docs/commands/07-proof/README.md new file mode 100644 index 0000000000..77cceb3f01 --- /dev/null +++ b/packages/flow/docs/commands/07-proof/README.md @@ -0,0 +1 @@ +# Proof diff --git a/packages/flow/docs/commands/07-proof/attach-seal.md b/packages/flow/docs/commands/07-proof/attach-seal.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/07-proof/countersign.md b/packages/flow/docs/commands/07-proof/countersign.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/07-proof/local-seal.md b/packages/flow/docs/commands/07-proof/local-seal.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/07-proof/seal.md b/packages/flow/docs/commands/07-proof/seal.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/08-run-on-premises/README.md b/packages/flow/docs/commands/08-run-on-premises/README.md new file mode 100644 index 0000000000..b4585da377 --- /dev/null +++ b/packages/flow/docs/commands/08-run-on-premises/README.md @@ -0,0 +1 @@ +# Run on premises diff --git a/packages/flow/docs/commands/08-run-on-premises/no-outbound.md b/packages/flow/docs/commands/08-run-on-premises/no-outbound.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/08-run-on-premises/service.md b/packages/flow/docs/commands/08-run-on-premises/service.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/09-share-with-cloud/README.md b/packages/flow/docs/commands/09-share-with-cloud/README.md new file mode 100644 index 0000000000..093b835b09 --- /dev/null +++ b/packages/flow/docs/commands/09-share-with-cloud/README.md @@ -0,0 +1 @@ +# Share safely with OpenAdapt Cloud diff --git a/packages/flow/docs/commands/09-share-with-cloud/approve-sanitized.md b/packages/flow/docs/commands/09-share-with-cloud/approve-sanitized.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/09-share-with-cloud/connect.md b/packages/flow/docs/commands/09-share-with-cloud/connect.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/09-share-with-cloud/connector.md b/packages/flow/docs/commands/09-share-with-cloud/connector.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/09-share-with-cloud/login.md b/packages/flow/docs/commands/09-share-with-cloud/login.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/09-share-with-cloud/materialize-approved.md b/packages/flow/docs/commands/09-share-with-cloud/materialize-approved.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/09-share-with-cloud/push.md b/packages/flow/docs/commands/09-share-with-cloud/push.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/09-share-with-cloud/report-break.md b/packages/flow/docs/commands/09-share-with-cloud/report-break.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/09-share-with-cloud/report-run.md b/packages/flow/docs/commands/09-share-with-cloud/report-run.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/09-share-with-cloud/review-sanitized.md b/packages/flow/docs/commands/09-share-with-cloud/review-sanitized.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/09-share-with-cloud/sanitize.md b/packages/flow/docs/commands/09-share-with-cloud/sanitize.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/09-share-with-cloud/validate-hosted.md b/packages/flow/docs/commands/09-share-with-cloud/validate-hosted.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/10-try-and-measure/README.md b/packages/flow/docs/commands/10-try-and-measure/README.md new file mode 100644 index 0000000000..168c8ea79a --- /dev/null +++ b/packages/flow/docs/commands/10-try-and-measure/README.md @@ -0,0 +1 @@ +# Try it and measure it diff --git a/packages/flow/docs/commands/10-try-and-measure/bench.md b/packages/flow/docs/commands/10-try-and-measure/bench.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/10-try-and-measure/benchmark.md b/packages/flow/docs/commands/10-try-and-measure/benchmark.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/10-try-and-measure/demo.md b/packages/flow/docs/commands/10-try-and-measure/demo.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/10-try-and-measure/tutorial.md b/packages/flow/docs/commands/10-try-and-measure/tutorial.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/flow/docs/commands/README.md b/packages/flow/docs/commands/README.md new file mode 100644 index 0000000000..5400a574fc --- /dev/null +++ b/packages/flow/docs/commands/README.md @@ -0,0 +1,17 @@ +# openadapt-flow commands, by capability + +One file per command: `/.md`. The group directory names the +capability; its `README.md` holds the title, and the numeric prefix sets the +order. A command's file is empty or holds a one-line note. + +To add a command, add its file to the right group and run: + +```bash +python scripts/build_command_map.py +``` + +That rewrites the "Every command, by capability" list in the root +`CAPABILITIES.md`. `packages/flow/tests/test_capabilities_map.py` fails when a +command has no file, a file names no command, or the list is out of date. +Because each command is its own file and the list has one command per line, two +pull requests that each add a command rarely edit the same line. diff --git a/packages/flow/tests/test_capabilities_map.py b/packages/flow/tests/test_capabilities_map.py index 5f893cfae7..ef5e6d2f1a 100644 --- a/packages/flow/tests/test_capabilities_map.py +++ b/packages/flow/tests/test_capabilities_map.py @@ -1,21 +1,27 @@ """CAPABILITIES.md at the repository root lists every openadapt-flow command. Reviews of OpenAdapt keep missing capabilities that ship because nothing tied -the capability map to the code. A new command fails this test until it is -listed, by capability, in CAPABILITIES.md. +the capability map to the code. A new command fails this test until it has a +file under packages/flow/docs/commands// and the list in CAPABILITIES.md +is regenerated with scripts/build_command_map.py. One file per command keeps +two pull requests that each add a command from editing the same line. """ from __future__ import annotations import argparse -import re +import importlib.util from pathlib import Path import pytest from openadapt_flow.__main__ import build_parser -MAP = Path(__file__).resolve().parents[3] / "CAPABILITIES.md" +REPO = Path(__file__).resolve().parents[3] +SCRIPT = REPO / "scripts" / "build_command_map.py" +pytestmark = pytest.mark.skipif( + not SCRIPT.exists(), reason="runs from the monorepo checkout" +) def _verbs() -> list[str]: @@ -25,12 +31,30 @@ def _verbs() -> list[str]: raise AssertionError("openadapt-flow has no subcommands") -@pytest.mark.skipif(not MAP.exists(), reason="runs from the monorepo checkout") -def test_every_command_is_listed_in_the_capability_map() -> None: - text = MAP.read_text(encoding="utf-8") - section = text[text.index("## Every command, by capability") :] - listed = set(re.findall(r"`([a-z][a-z-]*)`", section)) - missing = [verb for verb in _verbs() if verb not in listed] +def _command_map(): + spec = importlib.util.spec_from_file_location("build_command_map", SCRIPT) + assert spec and spec.loader + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +def test_every_command_has_a_capability_file() -> None: + documented = _command_map().documented_verbs() + missing = sorted(set(_verbs()) - set(documented)) assert not missing, ( - f"add {missing} to 'Every command, by capability' in CAPABILITIES.md" + f"add packages/flow/docs/commands//.md for {missing}, " + "then run: python scripts/build_command_map.py" + ) + stale = sorted(set(documented) - set(_verbs())) + assert not stale, f"no such openadapt-flow command; remove the files for {stale}" + duplicated = sorted({v for v in documented if documented.count(v) > 1}) + assert not duplicated, f"each command belongs to one capability: {duplicated}" + + +def test_capability_map_command_list_is_current() -> None: + command_map = _command_map() + text = command_map.MAP.read_text(encoding="utf-8") + assert command_map.splice(text, command_map.render()) == text, ( + "run: python scripts/build_command_map.py" ) diff --git a/scripts/build_command_map.py b/scripts/build_command_map.py new file mode 100644 index 0000000000..5a3bedaf94 --- /dev/null +++ b/scripts/build_command_map.py @@ -0,0 +1,84 @@ +"""Render CAPABILITIES.md's "Every command, by capability" list from files. + +Each openadapt-flow command has one file, packages/flow/docs/commands//.md. +The group directory names the capability (its README.md holds the title; the +numeric prefix sets the order). A command's file is empty or holds a one-line +note shown after it. Adding a command adds a file, and the rendered list has +one command per line, so two pull requests that add commands rarely touch the +same line. + + python scripts/build_command_map.py # rewrite the section + python scripts/build_command_map.py --check # fail if it is out of date + +packages/flow/tests/test_capabilities_map.py fails when a command has no file, +a file names no command, or the section is out of date. +""" + +from __future__ import annotations + +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parent.parent +MAP = ROOT / "CAPABILITIES.md" +COMMANDS = ROOT / "packages/flow/docs/commands" +HEADING = "## Every command, by capability" +BEGIN = "" +END = "" + + +def groups(root: Path = COMMANDS) -> list[tuple[str, dict[str, str]]]: + """Return (title, {verb: note}) per capability, in directory order.""" + result: list[tuple[str, dict[str, str]]] = [] + for directory in sorted(path for path in root.iterdir() if path.is_dir()): + title = (directory / "README.md").read_text("utf-8").strip() + if not title.startswith("# "): + raise SystemExit(f"{directory}/README.md must be a single '# Title' line") + verbs = { + path.stem: path.read_text("utf-8").strip() + for path in sorted(directory.glob("*.md")) + if path.name != "README.md" + } + result.append((title[2:], verbs)) + return result + + +def documented_verbs(root: Path = COMMANDS) -> list[str]: + return sorted(verb for _, verbs in groups(root) for verb in verbs) + + +def render(root: Path = COMMANDS) -> str: + lines = [BEGIN, ""] + for title, verbs in groups(root): + lines += [f"**{title}:**", ""] + for verb, note in verbs.items(): + lines.append(f"- `{verb}`" + (f": {note}" if note else "")) + lines.append("") + lines.append(END) + return "\n".join(lines) + + +def splice(text: str, block: str) -> str: + start, end = text.index(BEGIN), text.index(END) + len(END) + if text.rfind(HEADING, 0, start) == -1: + raise SystemExit(f"the generated block must sit under '{HEADING}'") + return text[:start] + block + text[end:] + + +def main(argv: list[str]) -> int: + text = MAP.read_text("utf-8") + updated = splice(text, render()) + if "--check" in argv: + if updated != text: + print( + "CAPABILITIES.md command list is out of date; " + "run: python scripts/build_command_map.py" + ) + return 1 + return 0 + MAP.write_text(updated, "utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main(sys.argv[1:]))