docs: reconcile architecture.md and data-model.md with the shipped code - #111
Open
dichovsky wants to merge 2 commits into
Open
docs: reconcile architecture.md and data-model.md with the shipped code#111dichovsky wants to merge 2 commits into
dichovsky wants to merge 2 commits into
Conversation
The authority order in docs/README.md exists so a reader can trust the lower-tier documents to agree with the ADRs, the SRS, and the code. Seven places had stopped agreeing, and each one misleads at the moment it is consulted: the source tree is the map a new contributor opens first, the transaction catalogue is what an auditor reads to learn which operations are all-or-nothing, the Tasks invariants are what a reader trusts to know what survives a crash, and the prune passages in README/EXAMPLES are where understating a destructive command's reach costs the most. Every claim was re-checked against main before editing; where the code and the lower-tier prose disagreed, the prose was the bug. The land invariant is the one correction that is not merely additive: it claimed an atomicity boundary wider than the code provides, which told a reader that a crash between the git half and the database half was impossible when it is not.
The two new transaction rows were 2.6x the catalogue's width band, which is the opposite of the terse style FR-62's acceptance asked for; the two facts they had to shed to fit are now carried in the prose under the table, where width is not scarce. Three further corrections follow from PR #112 retiring FR-H08: the untrusted- configuration bullet promised an executable-confirmation flag that no longer has a requirement behind it and never had code, and the two hardcoded FR-X01-X08 ranges would re-drift the next time a requirement is deferred. Both ranges are dropped rather than bumped, per the precedent PR #91 set, so this change carries no merge-order dependency on #112. The remaining edits close restatements the first pass left standing: discovery described as a pure upward walk in two more places, and the worktree module glossed as owning only two of the three worktree kinds it actually owns.
This was referenced Aug 6, 2026
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.
Closes #35
Closes #58
Closes #62
Closes #65
Closes #67
Closes #89
Closes #99
Seven pieces of drift in the two documents a contributor reads to orient themselves, plus the two user-facing files that restate one of the same facts. Each one misleads exactly where it is consulted: §4.1 is the source map opened first and it named a directory (
src/commands/) that does not exist while omitting four platform modules and five launcher modules; the transaction catalogue is what an auditor reads to learn which operations are all-or-nothing and it was missing both terminal Task operations; the Tasks invariants are what a reader trusts to know what survives a crash and thelandbullet claimed an atomicity boundary wider than the code provides; andREADME.md/EXAMPLES.mdare where understating a destructive command's reach costs the most.Per
docs/README.md:5-12,architecture.mdis authority rank 4 — the lowest — so where it disagreed with ADR-0015 (rank 1), the SRS (rank 2), or the registry, it is the bug.data-model.mdis rank 3, above architecture, which is why #62/#67/#99's data-model half matters more, not less; each edit there conforms to a rank-1 or rank-2 source cited inline.Verified before editing, not taken from the issue bodies
src/commands/(find src -type f -name '*.ts': handlers live at thesrc/root); no top-leveltemplates/(they are embedded string constants insrc/templates.ts);tests/is{unit,integration,spawn,store,fixtures,helpers,tools}with Playwright at top-levele2e/ui/.architecture.md:458-459reproduced verbatim. Six platforms return/crew(claude.ts:34,gemini.ts:35,antigravity.ts:29,pi.ts:51,little-coder.ts:40,opencode.ts:33),codex.ts:30returns$crew,copilot.ts:34the/agentselection form.PARTICIPANT_TARGETS(registry.ts:20-29) has eight entries andBACKEND_TARGETS(:32) two — ten targets, against the recorder comment's "five".abandonTask(src/store/tasks.ts:641-696) andlandTask(:715-751) confirmed, includingland'sWHERE id = ? AND worktree_path = ?CAS predicate, its lack of an appended event, and theagentStatus(...) === 'active'guard on the Sign-off.src/tasks.ts:644-672confirmedremoveTaskWorktreeruns before and outside the transaction and that!removal.branchDeletedwarns on stderr and proceeds.src/store/maintenance.ts:153-157and:176-182both bind(status = 'completed' AND completed_at < ?) OR (status = 'abandoned' AND abandoned_at < ?), and theNOT EXISTS … read_at IS NULLguard inELIGIBLE_TASKSis not status-specific. FR-E24 (srs.md:458-460) requires it.src/workspace.ts:142-155callsreadPointerTarget(dir)after finding a.crew/and returns the pointed-to root on atargetstate, failing (null→NOT_WORKSPACE) oninvalidand on a target that does not itself hold a real.crew/.writeWorkspacePointeris called fromsrc/tasks.ts:255(task start) and:537(task review), so both ADR-0015 worktree kinds take the redirect. FR-W04 issrs.md:1023-1028.Deltas against the issue bodies — noted rather than silently absorbed
/api/eventshalf does not reproduce.architecture.md:155on currentmainalready reads…GET /api/snapshot,/api/events,/api/health,/api/sessions,/api/resumable-sessions,/api/peek…— PR docs: correct CLI contract drift on the --json surface #85 (93433fc, the commit that introduced the string) fixed it after the issue was filed. That line is left byte-identical. Only theactions.tshalf of Docs: architecture.md Console route list omits GET /api/events, and its actions.ts row omits two handlers #89 was still true, and it is fixed here. Also worth recording:GET_PATHS(src/ui/server.ts:251-259) actually has seven entries, not six — the issue counts the six/api/*routes and omits/, which the same line already covers as "static assets".actions.tsgap. It names four missing handlers (listResumableTeamSessions,peekPane,archiveAgent,restoreAgent);resumeTeam(src/ui/actions.ts:377) is a fifth. The gloss now enumerates all fourteen exported handlers, so it is exhaustive as the Acceptance's first option asks.now-view.tsxis "unlisted"; it is in fact already covered collectively by "the six views" (PR docs: correct the Console view count to six #57 corrected that count). Conversely it does not nameweb/api.ts,web/types.ts, orweb/styles.css, which genuinely were absent, norsrc/ui/index.ts, nor twenty-onesrc/root modules (io.ts,fs-safe.ts,init.ts,agents.ts,messages.ts,tasks.ts,maintenance.ts,retention.ts,duration.ts,agent-id.ts,task-id.ts,templates.ts,config.ts,yaml-load.ts,version.ts,delay.ts, and the five it does name). The tree was regenerated from the actual layout rather than patched against the issue's list, and theview-model.tsgloss picks up thenowWorklist/pillBg/rolePillBgomission raised in architecture.md §4.1 source tree is substantially stale #35's comment.landrepairs it. Verified it cannot:hasUnlandedChanges(src/worktree.ts:291-306) runsgit -C <worktreePath> status --porcelainand throwsNOT_FOUNDwhen that directory is gone, so a rerun refuses before reachinglandTask. Stating otherwise would have replaced one false invariant with another.srs.md:513-515now enumerates all eight, so the rank-2-versus-rank-4 contradiction the Impact paragraph describes is the present state, andarchitecture.mdis conformed to FR-G07's exact enumeration.architecture.md:497(correct atmain), Docs: architecture.md §4 and data-model.md describe Workspace discovery without FR-W04's pointer redirect #99 cites:204-207(correct), Docs: architecture.md Console route list omits GET /api/events, and its actions.ts row omits two handlers #89 cites:155/:157(correct); Docs: data-model transaction catalogue omits task abandon and task land #62'sdata-model.md:399-411is:401-413and Data model: the land invariant puts the on-disk worktree removal inside the atomic step, but it happens before the transaction #67'slandbullet is:367-373. Cited here so the mapping is checkable.What changed and why
architecture.md§4.1 treesrc/,web/,tests/,e2e/layout:commands/*.tsand the top-leveltemplates/block removed, 20src/root modules +store/connection.ts,review-worktrees.ts,change-signature.ts+platforms/{antigravity,pi,little-coder,opencode,agent-skills}.ts+launcher/{derive,ref,prompts,stop,resume}.ts+ui/index.ts+web/{api.ts,types.ts,styles.css}added,tests/{…}corrected,e2e/ui/addedarchitecture.md§4.1actions.tsglosssend/create/approve/requeue, launch/resume/stop, listSessions/listResumableTeamSessions, peek, prune/clean, archive/restore)architecture.md§4.1view-model.tsglossarchitecture.md§4.3NOT_WORKSPACEfailure mode, and the ADR-0011 whole-Crew worktree (no pointer, local Store) is split from the ADR-0015 Task / Review Worktrees (pointer, shared Store)architecture.md§8/crew" → the same eight invocations FR-G07 enumeratesarchitecture.md§10prunenames abandoned Tasks withabandoned_atas their cutoff, and the unread-notification retention rule now plainly covers both statusesdata-model.md"Store location and opening"data-model.mdTasks invariants,landbulletdata-model.mdtransaction cataloguetask abandonandtask landrows;land's row states that it is not a transition, appends no event, and CASes onworktree_pathrather thanrevisionREADME.mdretention bulletEXAMPLES.mdprune bullettests/tools/release-smoke.test.ts:15Added in review round 1
data-model.mdcatalogue, both new rowsdata-model.md, prose under the catalogueclear_safeSign-off in both terminal rows, andlandskips it only for an archived assigneearchitecture.md:12and the §3 Workspace rowarchitecture.md§4.1worktree.tsglossarchitecture.md§4.1 treeweb/styles.d.tsandweb/tsconfig.jsonadded;process.ts/which.ts/relay.tsmoved into the contiguous root blockarchitecture.md§4.1, note under the blockweb/, not undertests/architecture.mduntrusted-config bulletarchitecture.md§11 anddecisions.md:152FR-X01–X08ranges droppedWhy three lines changed for a requirement this PR does not touch. PR #112 retires FR-H08 and adds FR-X09. Three lines at this PR's tier go stale as a result, and the coordinator widened scope to cover them (including a narrow authorization to touch
decisions.md:152and nothing else in that file):architecture.md's untrusted-configuration bullet read "A custom executable is accepted only from an explicit command-line flag, and crew prints it for you to confirm before running it." That promised a security mechanism that does not exist:grep -n executable src/cli.tsreturns nothing,participantExecutable(src/launcher/plan.ts:118-124) resolvestarget.executablefrom the registry alone, andsrc/launcher/config.ts:45listsexecutableamong the keys repo config may never supply. With FR-H08 retired there is no requirement behind it either. It now states only that registry ids are selectable, matching what docs: close seven SRS drifts against the code they govern #112 does tosecurity.mdandconfiguration.md.FR-X01–X08ranges (architecture.md§11,decisions.md:152) are dropped, not bumped to–X09, per the precedent PR docs: signpost ADR amendments and fix stale ADR cross-references #91 set: bumping re-drifts the next time a requirement is deferred, and dropping is the only option that cannot. This also removes any merge-order dependency on docs: close seven SRS drifts against the code they govern #112 — noFR-X09reference appears anywhere in this diff (grep -rn "FR-X09" docs/ README.md EXAMPLES.md→ no match), so the id need not exist yet for this PR to be correct.Surroundings were checked for the same claim restated (the #97 lesson).
grep -n "prune\|completed Task"over all three prune files found no second copy beyond the three fixed passages;grepfor the roster overarchitecture.mdfound only §8;data-model.md:519-522already covered both cutoff columns correctly and needed no change;architecture.md:370("one git worktree shared by the whole Crew") is correct as written per ADR-0015:11-16and is deliberately untouched.Width, including the table rows — measured on the pushed tree, nothing excluded. The first push's two catalogue rows were 254 and 245 characters against a catalogue whose widest pre-existing row is 117, and the wrapping note quoted "97" while silently leaving them out. Both are now inside the band:
| task abandon || task land || launch-teardown reap |(widest pre-existing)Two facts had to leave the rows to get there — the
clear_safeidentity of the assignee's notification, andland's archived-assignee skip. Neither was dropped: both moved into the paragraph directly under the table, where width is not scarce.abandon's explicitnotify assignee/creator/reviewerwas kept rather than shortened to a vaguer phrase, becauseabandonTask(src/store/tasks.ts:689) really does notify all three; the six characters came out ofclear lease/review/worktreeinstead.Prose wrapping: new
architecture.mdprose lines top out at 92 chars against an existing distribution that already carries 88/89/90/92; newdata-model.mdprose lines top out at 97, matching the paragraph they replace; newREADME.md/EXAMPLES.mdlines top out at 97 against the same band. Two lines this round exceeded their band on first write and were rewrapped before pushing (architecture.md:14at 137,decisions.md:152at 100). The one line legitimately over band is the §3 module-map table row, at 281 — that column was already 213 characters before this PR. The two touchedREADME.md/EXAMPLES.mdbullets were rewrapped whole so they do not end ragged; no untouched paragraph was reflowed. Prettier isproseWrap: "preserve", soformat:checkpasses either way.Verification
Tests: none added — claiming the docs exemption, granted by
CONTRIBUTING.md:95and.github/ISSUE_TRIAGE.md. The diff is five Markdown files plus a one-line comment in an unshipped maintainer-run recorder; no executable line changes anywhere. Nothing guards the edited passages, checked rather than assumed:tests/unit/docs-facts.test.tsderivesdocs-site/generated/facts.jsonfromsrc/platforms/registry.ts,src/store/schema.ts,src/cli.ts,package.json,vitest.config.ts, and ADR H1 headings — never these files. No regeneration needed.tests/store/schema.test.ts:409-421("data-model.md normative stamp") readsdata-model.md, but asserts only onPRAGMA user_version = N;and the## Schema version N (current)heading. Neither was touched; the test passes.tests/references todocs/design/architecture.md(tests/unit/launcher/{config,prompts}.test.ts,tests/integration/commands/team-launch.test.ts:45,tests/fixtures/launch-plan.dev.json:47) use the path as afocus.docsstring; nothing reads it from disk.npm run typecheckweb/+docs-site/)npm run lintnpm run format:checknpm run build:docsdist-docs/main.js102.1kbnpx vitest run tests/tools/release-smoke.test.tsCREW_RELEASE_SMOKEunset)npx vitest run tests/unit/docs-facts.test.ts tests/store/schema.test.tsRe-run in full after review round 1, on the pushed tree (
b406613):npm run typecheckweb/+docs-site/)npm run lintnpm run format:checknpm run build:docsdist-docs/main.js102.1kbnpx vitest run tests/tools/release-smoke.test.ts tests/unit/docs-facts.test.ts tests/store/schema.test.tsBranch cut from
origin/main@09e67cd.Contract impact
None. Every edit conforms a lower-authority document toward what a higher one already says — ADR-0011/ADR-0015 (rank 1), FR-G07/FR-E24/FR-W04 (rank 2), or the registry and Store code. No ADR is amended, no
FR-*/NFR-*is added, renumbered, or given new meaning, no CLI grammar rule, record type, error code, command, or flag moves, andCURRENT_SCHEMA_VERSIONstays 7.Out of scope
Deliberately untouched, owned by other work:
README.mdandEXAMPLES.mdbeyond the prune bullet — Docs: README Console screenshot predates ADR-0017, and EXAMPLES.md misdescribes it #54, Docs: console-action.png predates ADR-0017, and no capture shows the FR-U25 confirm dialog #82, Docs: EXAMPLES.md omits FR-U36 agent archive/restore and undercounts the FR-U25 gate #83, Docs: README still says the Console needs a typed confirmation phrase #84, Docs: EXAMPLES.md wind-down and worktree bullets over-promise in five places #87 (Console screenshots, FR-U36 archive/restore, FR-U25 confirm gate, wind-down and worktree over-promises) own the rest of both files. Edits here are confined to the one prune/abandoned-Task fact.docs/design/configuration.md:176-182— read only as the model for the ADR-0011-versus-ADR-0015 distinguishing phrasing, per Docs: architecture.md §4 and data-model.md describe Workspace discovery without FR-W04's pointer redirect #99's Acceptance. Another PR owns that file.docs-site/— outside the authority order (docs/README.md:16-18); docs-site prose drift: lifecycle omits abandoned, deferred-seam roster, glossary count #42's scope.docs/design/decisions.mdbeyond line 152 — that one line is in scope only as a narrowly authorized docs: close seven SRS drifts against the code they govern #112 consequence (the droppedFR-X01–X08range). Nothing else in the file was read for edits or touched.docs/design/srs.md,cli-contract.md,security.md,product-spec.md,setup-integration.md,testing-strategy.md,docs/adr/*,CLAUDE.md,AGENTS.md,CONTEXT.md— none needed a change for these seven fixes. In particular FR-H08's retirement and FR-X09's addition belong to docs: close seven SRS drifts against the code they govern #112; this PR only removes the three downstream statements that would otherwise go stale, and asserts nothing about the requirements themselves.One thing worth a maintainer's eye, raised not fixed: @slegarraga commented on #89 offering to take it. No PR was opened and the issue is unassigned, so it was implemented here; if that was the wrong call, the
actions.tsline is a one-line revert.Related open PRs
#112 (FR-H08 retirement, FR-X09 addition) is the only one that interacts with this PR, and only in one direction: three lines here are downstream consequences of it. They are written so that neither merge order matters — the
FR-X01–X08ranges are dropped rather than bumped, and noFR-X09id is referenced, so this PR is correct whether #112 lands before it, after it, or not at all. #112 editssrs.md,security.md, andconfiguration.md; this PR touches none of those three, so there is no line overlap either.