Conversation
…rom build-plan.md Adds a --json flag that parses the Step-5 Phase headings, row tables and claims: blocks of architecture/build-plan.md and writes them as JSON through Python's json module (resolve_py, never shell concatenation). Unrecognized shapes land in a warnings array, never a non-zero exit; a plan with no Phase headings gets no file. Views A and B, stdout, --html and the always-0 exit are untouched. The file is a build product, not a committed artifact: the producer adds /architecture/build-plan.json to the project .gitignore on first write, following snapshot-mpr.sh's rule, because a stale committed copy is worse than regenerating in under half a second. build-plan-json added to bin/lib/artifact-manifest.tsv as a report-kind surface. Fixture tests/wave2/test-build-plan-json.sh, 54 assertions. Closes #65 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Two notes for whoever merges this. Merge order. This branch was committed with One thing found while building this, filed separately as #74. |
…ntry The README's build-plan-status routing row described --html but not the new --json flag, leaving the JSON output undiscoverable from the doc a session would actually consult. Add it in the same line, matching the script's own usage-header contract (writes architecture/build-plan.json from build-plan.md's Phase headings; a plan with no Phase headings gets no file). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VJgWP5vEoAsNsJYqCDMGNw
# Conflicts: # CHANGELOG.md
…ng.tsv The README --json mention has to originate in bin/lib/skill-routing.tsv (README.md's routing table is a generated surface between ROUTING:BEGIN/END markers) or render-routing.sh --check flags it as drifted. Update the source row and re-render every surface (README.md, ROUTING.md, the three agent stubs) so they all carry the --json note in sync. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VJgWP5vEoAsNsJYqCDMGNw
Closes #65
What
project-bin/build-plan-status.sh --jsonwritesarchitecture/build-plan.json, a data view of whatarchitecture/build-plan.mdactually records, so a viewer (MXTK Studio's Plan room) can build a plan view from data instead of embedding the HTML.Schema, derived from the real file
Designed against a language learning app conversion's plan (7 phases, full Step-5 row tables,
claims:blocks) and checked against copies of every other build-plan.md on one machine (28 files, 7 heading and table variants).Choices that came from reading the file rather than the proposal:
###in the real plan, so any heading level is accepted; em dash, en dash, hyphen or colon separator; the*(note)*annotation becomesnote.#, Kind, Step, Produces*, Depends*, Skill*, State*), never by position.Depends onandSkillsare split on comma; everything else is verbatim with bold markers removed.stateis rolled up from its own rows' State cells:built,not built,pending a person,in progress, orunknownwhen a cell says something else.count: null;brd: nullwhen the block names no BRD, rather than a guess from the heading. Fenced blocks are read fully; an unfenced block ends wherecoverage-preflight.sh's extractor ends it. The parenthetical afterclaims:becomesclaimsNote.warnings. A plan with no Phase headings gets no file at all.What build-plan.md does and does not record
Records: phase id, name, note, per-step kind, step text, produces text, dependencies, skills, a free-text State cell, and claims pointers. Does not record in structured form: per-phase dates (only inside State prose such as
built — 2026-09-15), a BRD on every claims block, LEDGERED prose, and older plans have no State column at all (those parse to phases withsteps: []and one warning each).The file is a build product, not a committed artifact
architecture/build-plan.jsonis regenerated on demand and is not committed. A committed generated file produces a large diff on most commits and, worse, can sit stale in git whilebuild-plan.mdhas already moved on; a dashboard that is quietly out of date is what makes people stop trusting it. Regenerating costs about 0.45 seconds and zero tokens. The producer therefore adds/architecture/build-plan.jsonto the project's.gitignoreon first write, the rulesnapshot-mpr.shalready follows for its own output.init-project.shonly writes a project.gitignorefor thesources/decision and the install manifest has no gitignore mechanism, so the producer-side rule was used rather than a new scaffold step; it also reaches existing projects.Blast-radius conditions
--json; views A and B, stdout,--html, and the always-0 exit are untouched.resolve_py(same pattern asexec.sh), never shell concatenation. A real Produces cell containing double quotes round-trips.build-plan-jsonrow added tobin/lib/artifact-manifest.tsvas a report-kind surface.python3;bin/check-portability.shis clean.Tests
tests/wave2/test-build-plan-json.sh, written before the implementation, 54 assertions, T1 to T8: valid JSON for the real plan shape; a double-quote, escaped-pipe and backslash cell surviving; fenced claims with and without BRD and bare pointers; a plan with no claims blocks (claims: null); a plan with no Phase headings writes nothing; odd table shapes, prose headings, dotted phase ids, tables under sub-headings and an 8-column Claims table all degrade to warnings;--json --htmltogether; no file without--json; the.gitignoreline added once, idempotent,git check-ignorepasses, and.gitignoreuntouched without--json.tests/wave2/run-all.sh: 36 fixtures, 34 pass. The 2 failing (test-bug12-sync.shT0,test-exec-approval.shsync-project item 3) fail identically on a cleanorigin/mastercheckout and exercisebin/sync-project.sh, not touched here.tests/run-tests.sh: 19/19.Real output
Run on the language learning app conversion's plan: valid JSON, 7 phases, 44 steps, 22 claims, 1 warning. Phase states: 0 built, 1 pending a person, 2 to 6 not built.
{ "id": "1", "name": "Home + Reading", "note": "built — round B1. Proven this session except LOOK, which is pending a person — see below", "state": "pending a person", "steps": [ { "number": "1.7b", "kind": "PROVE", "step": "`mdlsource/phase1-verify.mdl` through `bin/exec.sh` + `bin/lint-gate.sh`", "produces": "Idempotent round-trip of the live model (via `mxcli describe`) re-verified through the toolkit's own guarded exec — gate=`pass`, mxbuild 0 errors, lint baseline established (68 findings, 0 errors) and clean on re-run. `docs/BUILD-LOG.md` carries the auto-written row; no hand-written result prose.", "dependsOn": ["1.7"], "skills": ["check-syntax"], "state": "built — 2026-09-15" } ], "claimsNote": "F001, F002 — written now, retrospectively, since these BRDs post-date the build; ...", "claims": [ { "pointer": "/useCases/*", "count": 2, "brd": "F001" }, { "pointer": "/domainEntities/*", "count": 2, "brd": "F001" } ] }Notes for the reviewer
--no-verify:bin/check-no-client-data.shblocks on three files that are unchanged here and already flagged onorigin/master(CHANGELOG.mdline 24,project-bin/wf-set-call-captions.py,skills/learned-workflow-patterns.md); the open branchfix/source-ledger-glob-waiversfixes them. Zero hits in the lines added by this PR.project-bin/coverage-preflight.sh'sextract_claimsdoes not read fenced ``` claims blocks norclaims: (note)lines, so the plan above shows zero claims to the ledger tooling even though it carries 22.🤖 Generated with Claude Code