From b54ddf3bf312bd4bddea538b307b30b43c9fc77e Mon Sep 17 00:00:00 2001 From: Bryan Signey Date: Fri, 28 Aug 2026 12:34:22 +1000 Subject: [PATCH 01/15] fixed phase 0 writing into docs/_discovery dir before resolving with user --- skills/codebase-discovery/SKILL.md | 9 +- .../playbooks/00-pre-check.md | 178 +++++++++++------- .../references/write-contract.md | 10 +- 3 files changed, 120 insertions(+), 77 deletions(-) diff --git a/skills/codebase-discovery/SKILL.md b/skills/codebase-discovery/SKILL.md index 6f5e357..977c4a3 100644 --- a/skills/codebase-discovery/SKILL.md +++ b/skills/codebase-discovery/SKILL.md @@ -225,9 +225,10 @@ sessions: - `docs/_discovery/recon-manifest.md` — the commit recon ran against, which areas and files were read, and which existing docs fed it, so later runs can detect staleness (below). -On invocation: if these exist, read them first and resume; do not restart from zero. Keep -`discovery-state.md` compact: it's a working set, not a log, and its own header carries the ceiling -and the compaction rules. +On invocation: if these exist, read them first and resume; do not restart from zero. They sit under +whatever root the previous run agreed, which may not be `docs/`, so Phase 0 **searches** for them +rather than checking one path. Keep `discovery-state.md` compact: it's a working set, not a log, and +its own header carries the ceiling and the compaction rules. `_discovery/` also holds the two audit files (`assumptions-register.md`, `traceability-index.md`), which are committed alongside the docs they back. What's committed and @@ -251,7 +252,7 @@ Run in order. Each has a playbook; read it when you enter the phase. | Phase | Playbook | Outcome | |---|---|---| -| 0. Pre-check | [`playbooks/00-pre-check.md`](./playbooks/00-pre-check.md) | Read existing README/CLAUDE.md/AGENTS.md/docs; capture what they state, to verify against the code; set up working state; survey the write target and agree the output root. | +| 0. Pre-check | [`playbooks/00-pre-check.md`](./playbooks/00-pre-check.md) | Locate any previous run's state; survey the write target and agree the output root **before writing anything**; set up working state under it; read existing README/CLAUDE.md/AGENTS.md/docs and capture what they state, to verify against the code. | | 1. Deep recon | [`playbooks/01-deep-recon.md`](./playbooks/01-deep-recon.md) | Tiered, evidence-cited analysis of structure, data model, contracts and business-logic hotspots; verify the Phase 0 statements against code. | | 2. Interview | [`playbooks/02-interview.md`](./playbooks/02-interview.md) | One-question-at-a-time conversation with the BA/PO, worked in impact order from the register; reconcile contradictions with code-based suggestions. The stakeholder can stop at any point; the remainder is parked and resumable. (Skipped in code-only mode.) | | 3. Synthesis | [`playbooks/03-synthesis.md`](./playbooks/03-synthesis.md) | Write the lean onboarding docs under `docs/`, each dated and provenance-flagged. | diff --git a/skills/codebase-discovery/playbooks/00-pre-check.md b/skills/codebase-discovery/playbooks/00-pre-check.md index 3932eee..82fb32e 100644 --- a/skills/codebase-discovery/playbooks/00-pre-check.md +++ b/skills/codebase-discovery/playbooks/00-pre-check.md @@ -7,21 +7,100 @@ from the code. Do not write onboarding docs in this phase. Only gather and set up state. +> **Nothing is written or deleted until §2 settles the output root.** That includes this phase's own +> four `_discovery/` files, which belong under the agreed root. It's rule 4 of the +> [write contract](../references/write-contract.md), which says why. + > **Prediction rule** (`SKILL.md`): don't assume what an existing doc says, or what the mode should be. > Read it, and ask. --- -## 1. Resume or initialise working state +## 1. Orient: options, project root, prior state + +**Read-only.** Nothing here writes or deletes. **Resolve the invocation options first**, per `SKILL.md`. Several of them pre-answer questions in this phase (`--output`, `--fresh`, `--on-drift`, `--exclude`, `--interview`), so state the given value and skip the question rather than asking anyway. -**With `--fresh`, confirm before wiping.** Where `docs/_discovery/` already exists there's work to -lose, so this comes before anything resumes from that state or writes over it. Read the state to -report what the previous run got to (areas reconned, how far the interview got), then offer -**resume** or **clean run**, and be specific about the cost rather than saying "this is destructive": +**Locate the project root**: `git rev-parse --show-toplevel`, falling back to the session's working +directory. Every path in this phase is relative to it. + +**Find any previous run's state by searching, not by assuming where it is.** A previous run's output +root may not be `docs/`, and the root it chose is recorded *inside* the state file, so looking only +in `docs/_discovery/` finds nothing and reports a first run that isn't one. That silently throws away +the resume and the staleness check, and nothing in the output shows it happened. Glob for +`_discovery/discovery-state.md` at every level under the project root, honouring `.gitignore` and the +default exclusions. + +- **One hit** — read it. It carries that run's output root, mode and resolved options, and how far it + got. Report what it reached (areas reconned, how far the interview got) before acting on it. +- **More than one** — two runs have written here. Show the paths with their `Last updated` dates and + ask which to continue. Don't pick, and don't merge them. +- **None** — a first run. Say so. + +--- + +## 2. Settle the output root + +Everything this phase writes lands under it, so it is settled **before the first write**, not at +synthesis time. Where the root may sit, and how `--output` resolves against it, is the +[write contract](../references/write-contract.md); follow it rather than re-deriving it here. This +step's job is settling it in practice. + +**On a resume, the root is already chosen.** The state §1 found records it, and where that file sits +proves it. Say which root you're continuing into and move on. Where `--output` names a different one, +that's a conflict rather than an override: report both and ask, because writing this run's docs into +a second root splits the set across two places. + +**On a first run, survey the target and agree it:** + +**a. Is `docs/` already a published site?** Look for a generator that owns the directory: + +| Look for | Generator | +|---|---| +| `mkdocs.yml` | MkDocs | +| `docusaurus.config.js` / `.ts`, `sidebars.js` | Docusaurus | +| `docs/conf.py` | Sphinx | +| `_config.yml`, `config.toml`/`hugo.toml`, `book.toml` | Jekyll / Hugo / mdBook | +| `.vitepress/`, `.vuepress/` | VitePress / VuePress | + +If one is present, say so plainly: files dropped into that tree may be **picked up and published +by the next build**. Docusaurus's autogenerated sidebar will index them, MkDocs and Sphinx will +warn or publish them unlinked. Discovery output is internal working material; it must not become +a public page because of where it landed. + +**b. What already occupies the target paths?** List any existing file at the paths this skill +would write (`business/`, `domain/`, `tech/`, `areas/`, `_discovery/` under the output root). These +are human-authored until proven otherwise. + +**c. Agree the root with the user.** Say which directory you settled on. Where `docs/` is a published +site, or is already occupied, propose an alternative (`docs/discovery/` is the usual choice) and let +the user decide. Report what you found even when `--output` was given, since a published site is +worth knowing about either way. If the docs do belong in the published site, ask explicitly whether +they should be registered in its nav/sidebar or deliberately left out of it. + +Carry all three outcomes (root, tooling + nav decision, and the pre-existing files) into §3, which +records them in `discovery-state.md` as it initialises it. They bind every later phase via the +[write contract](../references/write-contract.md). + +--- + +## 3. Resume or initialise working state + +The root is settled, so this is the first step that writes. Every `_discovery/` path below sits under +that root. + +Get today's real date from the environment now and reuse it for every `Last updated` stamp this run, +per the header-block rule in +[`../references/output-conventions.md`](../references/output-conventions.md). + +**With `--fresh`, confirm before wiping.** Where `_discovery/` already exists there's work to +lose, so this comes before anything resumes from that state or writes over it. §1 has already read +the state, so report what the previous run got to (areas reconned, how far the interview got), then +offer **resume** or **clean run**, and be specific about the cost rather than saying "this is +destructive": - `discovery-state.md` and `recon-manifest.md` hold the interview progress and the recon memory, and the disposition recommends git-ignoring them, so **wiping those is unrecoverable**. @@ -33,34 +112,31 @@ previous run wrote stay where they are, for this run to refresh in place. Half-m than either choice: keeping the register while discarding the state leaves the new run appending to another run's open items with no way to tell them apart. -Then check for prior state and resume if present: +Then continue from what §1 found: -- If `docs/_discovery/discovery-state.md` exists, read it and continue from where the last - session left off rather than redoing finished work. Decide which phase to re-enter using the - resume table in `SKILL.md`, and tell the user which one and why. `--interview` decides it for you, - and so does `--fresh` once the clean run above is confirmed. +- If a `discovery-state.md` was found, continue from where the last session left off rather than + redoing finished work. Decide which phase to re-enter using the resume table in `SKILL.md`, and + tell the user which one and why. `--interview` decides it for you, and so does `--fresh` once the + clean run above is confirmed. - If the state records an interview that was stopped with items still open, rebuild the top 5 from the register and offer to continue it, saying what the last session covered first. See the interview playbook. -- If `docs/_discovery/recon-manifest.md` exists, run the **freshness check** per +- If a `recon-manifest.md` sits beside it, run the **freshness check** per [`../references/freshness.md`](../references/freshness.md) (commit-based, not timestamps). If there's drift, report it and put the choice to the user as set out there: don't silently re-recon, and don't silently trust stale docs. Record their decision in the manifest's freshness-check log. -If neither exists, create `docs/_discovery/` and initialise all four files from their templates: -`templates/discovery-state.md`, `templates/recon-manifest.md`, `templates/assumptions-register.md` -and `templates/traceability-index.md`. Phase 1 writes to the last two in every run, and their column -sets carry weight: the register's *who can confirm* column is what lets the interview group -questions by owner. - -Get today's real date from the environment now and reuse it for every `Last updated` stamp this run, -per the header-block rule in -[`../references/output-conventions.md`](../references/output-conventions.md). +If §1 found none, create `_discovery/` under the agreed root and initialise all four files from +their templates: `templates/discovery-state.md`, `templates/recon-manifest.md`, +`templates/assumptions-register.md` and `templates/traceability-index.md`. Fill the state's **Run** +block from §2: the agreed root, the docs-site tooling and nav decision, and the pre-existing files at +the target paths. Phase 1 writes to the last two files in every run, and their column sets carry +weight: the register's *who can confirm* column is what lets the interview group questions by owner. --- -## 2. Confirm mode and available inputs +## 4. Confirm mode and available inputs - Confirm the mode: **full** (a BA/PO/SME is available) or **code-only** (none yet). - Confirm whether optional inputs are available (git for the freshness check, sub-agents, the @@ -73,7 +149,7 @@ State the mode and the available inputs back to the user before proceeding. --- -## 3. Discover existing documentation +## 5. Discover existing documentation Find and read everything that describes the system, to reconcile it against the code: @@ -89,51 +165,11 @@ If nothing exists, note that and move on; the code is the source. --- -## 4. Survey the write target, and agree it - -This skill writes into **someone else's repository**. Before anything is written, establish what -is already there and get the destination agreed. Do this now, not at synthesis time. - -**a. Is `docs/` already a published site?** Look for a generator that owns the directory: - -| Look for | Generator | -|---|---| -| `mkdocs.yml` | MkDocs | -| `docusaurus.config.js` / `.ts`, `sidebars.js` | Docusaurus | -| `docs/conf.py` | Sphinx | -| `_config.yml`, `config.toml`/`hugo.toml`, `book.toml` | Jekyll / Hugo / mdBook | -| `.vitepress/`, `.vuepress/` | VitePress / VuePress | - -If one is present, say so plainly: files dropped into that tree may be **picked up and published -by the next build**. Docusaurus's autogenerated sidebar will index them, MkDocs and Sphinx will -warn or publish them unlinked. Discovery output is internal working material; it must not become -a public page because of where it landed. - -**b. What already occupies the target paths?** List any existing file at the paths this skill -would write (`business/`, `domain/`, `tech/`, `areas/`, `_discovery/` under the output root). These -are human-authored until proven otherwise. - -**c. Agree the output root with the user.** Where the root may sit, and how `--output` resolves -against it, is the [write contract](../references/write-contract.md); follow it rather than -re-deriving it here. This phase's job is to settle it in practice: locate the project root -(`git rev-parse --show-toplevel`, falling back to the session's working directory) and say which -directory you settled on. Where `docs/` is a published site, or is already occupied, propose an -alternative (`docs/discovery/` is the usual choice) and let the user decide. Report what you found -even when `--output` was given, since a published site is worth knowing about either way. If the docs -do belong in the published site, ask explicitly whether they should be registered in its nav/sidebar -or deliberately left out of it. - -Record all three outcomes (root, tooling + nav decision, and the pre-existing files) in -`docs/_discovery/discovery-state.md`. They bind every later phase via the -[write contract](../references/write-contract.md). - ---- - -## 5. Capture what the docs state, to verify +## 6. Capture what the docs state, to verify From each existing doc, note the discrete statements it makes about the system. For example: "authentication uses OAuth2", "orders can't be cancelled after dispatch", "the payments -service owns refunds". For each, record in `docs/_discovery/discovery-state.md`: +service owns refunds". For each, record in `_discovery/discovery-state.md` under the agreed root: - The statement, plainly. - Its source (file + location). @@ -151,9 +187,9 @@ where the flag legitimately persists. --- -## 6. Record what was read +## 7. Record what was read -Update `docs/_discovery/recon-manifest.md`: +Update `_discovery/recon-manifest.md` under the agreed root: - List the existing docs read (path + last-modified). - Note the mode, the exclusions in force, and the available optional inputs. @@ -163,10 +199,12 @@ Update `docs/_discovery/recon-manifest.md`: ## Exit criteria -- Working state initialised or resumed; freshness check run if applicable. +- Prior state searched for across the tree, not just at the default path; a first run is a search + that found nothing, not a lookup that missed. +- Write target surveyed: docs-site tooling detected, existing files at the target paths listed, + and the **output root agreed with the user** before anything was written or deleted. +- Working state initialised or resumed **under that root**, with the root, nav decision and + pre-existing files recorded in the discovery state; freshness check run if applicable. - Mode and available inputs confirmed with the user. - All existing docs found and their statements logged as `[unchecked]`. -- Write target surveyed: docs-site tooling detected, existing files at the target paths listed, - and the **output root agreed with the user** and recorded in the discovery state. - - Ready to begin deep recon. diff --git a/skills/codebase-discovery/references/write-contract.md b/skills/codebase-discovery/references/write-contract.md index f3212e7..6779389 100644 --- a/skills/codebase-discovery/references/write-contract.md +++ b/skills/codebase-discovery/references/write-contract.md @@ -16,12 +16,16 @@ later phase is bound by it. project root, say so and confirm rather than writing there on the strength of a flag. 3. **Write nothing outside that root.** The one exception is the project-root `README.md`, which has its own rules in the synthesis playbook. -4. **Never overwrite a file you didn't write.** If something already occupies a target path, read +4. **Write nothing, and delete nothing, before the root is settled.** This binds Phase 0's own + `_discovery/` files too: creating them under an assumed root puts the record of the decision in + the directory the decision rejected, and `--fresh` would wipe a directory nobody has agreed is + the right one. Locating and reading a previous run's state is read-only, so it comes first. +5. **Never overwrite a file you didn't write.** If something already occupies a target path, read it, show the user what would change, and get sign-off first. A generated doc must not silently replace a human-authored one, however stale that one looks. -5. **A previous run's own output may be refreshed in place**, recognisable by this skill's header +6. **A previous run's own output may be refreshed in place**, recognisable by this skill's header block. -6. **Respect the published-site decision.** Where the root belongs to a docs generator, Phase 0 +7. **Respect the published-site decision.** Where the root belongs to a docs generator, Phase 0 recorded whether these pages go in its nav/sidebar. Never add pages to a public site's navigation without that decision. From 3c09f22c1786126696ed4f04c55df70043dc518a Mon Sep 17 00:00:00 2001 From: Bryan Signey Date: Fri, 28 Aug 2026 12:37:11 +1000 Subject: [PATCH 02/15] fix --fresh recoverability check --- skills/codebase-discovery/playbooks/00-pre-check.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/skills/codebase-discovery/playbooks/00-pre-check.md b/skills/codebase-discovery/playbooks/00-pre-check.md index 82fb32e..1de12fd 100644 --- a/skills/codebase-discovery/playbooks/00-pre-check.md +++ b/skills/codebase-discovery/playbooks/00-pre-check.md @@ -102,10 +102,15 @@ the state, so report what the previous run got to (areas reconned, how far the i offer **resume** or **clean run**, and be specific about the cost rather than saying "this is destructive": -- `discovery-state.md` and `recon-manifest.md` hold the interview progress and the recon memory, and - the disposition recommends git-ignoring them, so **wiping those is unrecoverable**. -- `assumptions-register.md` and `traceability-index.md` are committed, so those are recoverable from - git. +- `discovery-state.md` and `recon-manifest.md` hold the interview progress and the recon memory; + `assumptions-register.md` and `traceability-index.md` are the audit trail for whatever docs the + previous run wrote. +- **What git can give back is a check, not an assumption** (the prediction rule in `SKILL.md`). The + disposition recommends committing the two audit files and git-ignoring the two state files, but + that's advice about what to do, not a record of what this repo did. A first run has committed + nothing yet. Run `git ls-files --error-unmatch` over all four and name which are tracked. +- Anything untracked is **gone for good**, and with no git available that's all four. Say so before + you ask. On the user's confirmation, delete all four and start cold. Wipe `_discovery/` only; any docs a previous run wrote stay where they are, for this run to refresh in place. Half-measures are worse From e8fc32accded828c891fb20c5f301f6a00c53eca Mon Sep 17 00:00:00 2001 From: Bryan Signey Date: Fri, 28 Aug 2026 13:28:14 +1000 Subject: [PATCH 03/15] glossary fix for code-only mode --- .../codebase-discovery/playbooks/03-synthesis.md | 15 ++++++++++----- .../templates/agent-onboarding-file.md | 5 +++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/skills/codebase-discovery/playbooks/03-synthesis.md b/skills/codebase-discovery/playbooks/03-synthesis.md index 32a1729..f971fe2 100644 --- a/skills/codebase-discovery/playbooks/03-synthesis.md +++ b/skills/codebase-discovery/playbooks/03-synthesis.md @@ -29,8 +29,8 @@ with the user rather than assuming `docs/`. **Where the content comes from.** The references above govern *how* to write; the material is already recorded in Phase 1's cited hypotheses, and in `discovery-state.md`'s **Facts**, **Glossary -in progress** and **Decisions**, which the interview kept current. Open items are in -`assumptions-register.md`. Read those before writing, and don't re-derive from the code what an +in progress** and **Decisions**, which recon populated and the interview kept current. Open items +are in `assumptions-register.md`. Read those before writing, and don't re-derive from the code what an earlier phase already established. --- @@ -60,9 +60,14 @@ judgements are this phase's own, plus two rules: one about coverage, one about e real weight without one is a blocking finding. **Write the glossary first.** Area directories and concept filenames are glossary terms, so the -glossary has to exist before anything can be named from it. Draft it from the confirmed terms -before naming anything else. Naming a file for a concept that isn't in it yet is what -output-conventions' add-it-first rule is about. +glossary has to exist before anything can be named from it. Naming a file for a concept that isn't +in it yet is what output-conventions' add-it-first rule is about. + +Its terms come from a different place in each mode. In `full` mode, draft from what the interview +confirmed, in `discovery-state.md`'s **Glossary in progress**. In `code-only` mode nothing is +confirmed, so draft from the code language the glossary template points at, and take each meaning +from what that code does. Naming follows the same rule in both modes: the code unit's name until +someone agrees a business one, per output-conventions. Use the matching file in `../templates/`; the area files use the same templates as their unsplit equivalents, written per concept rather than per repo. diff --git a/skills/codebase-discovery/templates/agent-onboarding-file.md b/skills/codebase-discovery/templates/agent-onboarding-file.md index 6205e1e..0d4e14e 100644 --- a/skills/codebase-discovery/templates/agent-onboarding-file.md +++ b/skills/codebase-discovery/templates/agent-onboarding-file.md @@ -37,5 +37,6 @@ constraints. Keep to what's verified; flag [assumption] otherwise.> ## Known caveats - + From 59eb8319bcf084dc2c589d4fc15d75a94eb02ae5 Mon Sep 17 00:00:00 2001 From: Bryan Signey Date: Fri, 28 Aug 2026 13:32:27 +1000 Subject: [PATCH 04/15] fix verifier agent drift and gitignore hardcoding --- agents/codebase-doc-verifier.md | 9 +++++++++ .../references/discovery-disposition.md | 8 +++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/agents/codebase-doc-verifier.md b/agents/codebase-doc-verifier.md index 4df2b41..55c9a9a 100644 --- a/agents/codebase-doc-verifier.md +++ b/agents/codebase-doc-verifier.md @@ -47,10 +47,19 @@ it traces to evidence. - **Groupings are evidenced.** A cluster named in business language must trace to a stakeholder who confirmed it; check the register and traceability index. Otherwise it should be named after the code unit it came from and flagged `[unverified]`. +- **Markdown structure holds.** Check the source of every table: a header separator row directly + below the header, and no blank line between rows. A blank line ends a Markdown table, so every row + after it renders as literal pipe text. A register whose rows don't render is unusable however + accurate it is, and no check that only reads content will catch it. Confirm fences are balanced + and any diagram block is well-formed. - **Writes landed inside the agreed root.** Phase 0 records the output root, the docs-site nav decision and the pre-existing files at the target paths in `docs/_discovery/discovery-state.md`; check the output against them. **You cannot verify sign-off**, because an overwrite is approved in conversation, not in a file. Report placement, not consent, and let the caller judge. +- **Drift is captured in the register.** Every place an existing doc (`README`, `CLAUDE.md`, + `AGENTS.md`) contradicted the code should appear in `docs/_discovery/assumptions-register.md` with + a corrected statement derived from the code. That register is the artefact to check; the doc-drift + summary it feeds doesn't exist yet when you run. ## Report format diff --git a/skills/codebase-discovery/references/discovery-disposition.md b/skills/codebase-discovery/references/discovery-disposition.md index e73398f..ed90d4a 100644 --- a/skills/codebase-discovery/references/discovery-disposition.md +++ b/skills/codebase-discovery/references/discovery-disposition.md @@ -15,11 +15,13 @@ different fates: `assumptions-register.md` from its open-risks section, and that link stays valid for every clone. - The two state files are this run's scratch memory. **Recommend** adding them to `.gitignore`, and - never do it automatically: + never do it automatically. Substitute the root Phase 0 agreed, per rule 1 of the + [write contract](write-contract.md): a snippet naming `docs/` in a repo whose root is + `docs/discovery/` ignores nothing. ```gitignore - docs/_discovery/discovery-state.md - docs/_discovery/recon-manifest.md + /_discovery/discovery-state.md + /_discovery/recon-manifest.md ``` - Deleting the state files is safe but makes the next run **start cold**: no resume, no staleness From 327e5b9ab5395a8fecd155bf3bffe9a5eacf18e2 Mon Sep 17 00:00:00 2001 From: Bryan Signey Date: Fri, 28 Aug 2026 13:49:11 +1000 Subject: [PATCH 05/15] fix domain-glossary never splits issue --- agents/codebase-doc-verifier.md | 3 +++ .../playbooks/04-verification.md | 14 +++++++++----- .../references/code-intelligence.md | 5 +++++ .../references/output-conventions.md | 10 +++++++++- .../templates/domain-glossary.md | 15 +++++++++------ 5 files changed, 35 insertions(+), 12 deletions(-) diff --git a/agents/codebase-doc-verifier.md b/agents/codebase-doc-verifier.md index 55c9a9a..97807e6 100644 --- a/agents/codebase-doc-verifier.md +++ b/agents/codebase-doc-verifier.md @@ -40,6 +40,9 @@ it traces to evidence. matches the glossary across docs; the recon manifest reflects the files actually read. The project-root `README.md` and the agent onboarding file carry no discovery metadata by design, so finding no date there is the intended state; don't report it. +- **One glossary, not several.** Exactly one `domain-glossary.md`, at `domain/`, with no per-area + variant beside it, and every term carrying an area or `cross-cutting`. A second glossary hides the + cross-area clashes the single file exists to surface. - **Names use the agreed language.** Area directories and concept filenames should be glossary terms, not namespaces or codenames, and there should be no catch-alls (`misc`, `other`, `general`). Your assignment carries the naming rules, or an absolute path to the skill's diff --git a/skills/codebase-discovery/playbooks/04-verification.md b/skills/codebase-discovery/playbooks/04-verification.md index 41a7056..fe9cc51 100644 --- a/skills/codebase-discovery/playbooks/04-verification.md +++ b/skills/codebase-discovery/playbooks/04-verification.md @@ -58,6 +58,10 @@ pass an **absolute** path or put the substance in the prompt. The checks below r agent file points at a file that exists. Skipped documents are the usual culprit, since the index templates list the full set. + **The glossary is one file.** Exactly one `domain-glossary.md`, at `domain/`, with no per-area + variant beside it, and every term carrying an area or `cross-cutting`. A second glossary hides + the cross-area clashes the single file exists to surface. + **Names use the agreed language.** Area directories and concept filenames are glossary terms, not namespaces or codenames, with no catch-alls (`misc`, `other`, `general`). A file that couldn't be named specifically usually means the split was wrong. No output file is named `business-rules.md` @@ -68,11 +72,11 @@ pass an **absolute** path or put the substance in the prompt. The checks below r `[unverified]`. An invented carve-up is worse than a technical one, because it becomes the structure everyone inherits. -7. **Output renders.** Read the files as rendered Markdown, not just as source. For every - table: no blank line between rows (a blank line ends a Markdown table, orphaning every row after - it as literal pipe text) and a header separator immediately below the header. Check that any - diagram parses. A register whose rows don't render as a table is unusable however accurate it is, - and no check that only reads content will catch it. +7. **Markdown structure holds.** Check the source of every table: a header separator row directly + below the header, and no blank line between rows. A blank line ends a Markdown table, so every + row after it renders as literal pipe text. Confirm fences are balanced and any diagram block is + well-formed. A register whose rows don't render is unusable however accurate it is, and no check + that only reads content will catch it. 8. **Write contract honoured.** Check the output against [`../references/write-contract.md`](../references/write-contract.md), using the root, nav decision diff --git a/skills/codebase-discovery/references/code-intelligence.md b/skills/codebase-discovery/references/code-intelligence.md index 53ff092..d37fdd4 100644 --- a/skills/codebase-discovery/references/code-intelligence.md +++ b/skills/codebase-discovery/references/code-intelligence.md @@ -61,6 +61,11 @@ the two modes complement each other rather than competing. ## Setup +**This is prep work, done before a run and by choice.** Don't raise any of it during a discovery: +the recon playbook and Tier D of the ladder both say never ask the user to install anything mid-run, +and that stands. If the symbol tools are absent when recon starts, note it and carry on down the +ladder. + ### 1. Install the language server(s) for your repo Install only what your target codebase needs, one of these rather than all: diff --git a/skills/codebase-discovery/references/output-conventions.md b/skills/codebase-discovery/references/output-conventions.md index c642be9..4ec6b7e 100644 --- a/skills/codebase-discovery/references/output-conventions.md +++ b/skills/codebase-discovery/references/output-conventions.md @@ -76,12 +76,20 @@ Which artefacts split, and which must not: | domain model | **yes**, as `model-.md` | entities cluster by area; `domain/domain-model.md` keeps the aggregates and cross-area relationships | | business rules | **yes**, as `rules-.md` | the clearest case — rules cluster by area and grow with the codebase | | workflows | **yes**, as `workflow-.md` | one flow per file; you rarely need all of them at once | -| **domain glossary** | **never** | it's the shared vocabulary. Splitting it defeats the point that a term means one thing system-wide | +| **domain glossary** | **never** | one place to look a word up; ownership is a column, not a file | | current architecture | no | it *is* the system view; the per-area detail is the area docs | | integrations | no | a table of external systems, inherently system-level | | user personas | no | global, and small | | business requirements | no | mostly cross-area; splitting scatters them along an axis they don't have | +**The glossary never splits, and ownership goes in a column.** Area-specific terms are +catalogued in the one file, with an `Area` column naming the area that owns each, or `cross-cutting`. +Splitting by area breaks the lookup at the moment it's needed: you check a glossary precisely when +you don't know which area owns the word. It also hides the clashes the glossary exists to surface. +Billing's `Account` and identity's `Account` meaning different things is invisible across two files, +because nobody diffs glossaries. Where a word does mean different things in two areas, that's one row +per area, sitting adjacent. + **When to split: content shape, not repo size.** One area's worth of material → keep the flat layout and no `areas/` directory at all. Material for more than one area → areas appear. There's no size threshold to judge, because the trigger is whether the content has an area dimension. diff --git a/skills/codebase-discovery/templates/domain-glossary.md b/skills/codebase-discovery/templates/domain-glossary.md index 2ab7635..d41856f 100644 --- a/skills/codebase-discovery/templates/domain-glossary.md +++ b/skills/codebase-discovery/templates/domain-glossary.md @@ -5,13 +5,16 @@ > **Mode:** full | code-only > **Status:** — see ../_discovery/assumptions-register.md - + + +| Term | Area | Meaning | Also known as / code name | Related | +|---|---|---|---|---| +| | | | | | From 7fb082bb4cd28fb3cf18e2f0f7c452a7d7c940ad Mon Sep 17 00:00:00 2001 From: Bryan Signey Date: Fri, 28 Aug 2026 13:54:30 +1000 Subject: [PATCH 06/15] fix behavioural issues around grouping --- .../references/question-bank.md | 13 +++++++++++++ .../templates/current-architecture.md | 15 ++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/skills/codebase-discovery/references/question-bank.md b/skills/codebase-discovery/references/question-bank.md index f06ad92..f8ef65a 100644 --- a/skills/codebase-discovery/references/question-bank.md +++ b/skills/codebase-discovery/references/question-bank.md @@ -28,6 +28,10 @@ override?" - The code uses the term `` (e.g. an enum/entity). What does it mean to the business? - Are `` and `` the same thing or different? (surface synonyms/conflicts) - Is there a term the business uses that you *don't* see reflected in the system? +- Which part of the business owns ``, or is it used right across the system? (fills the + glossary's Area column) +- Does `` mean the same thing in `` as it does in ``? (two meanings get a row + each, so the clash is visible) ## Business rules @@ -36,6 +40,15 @@ override?" - Is that rule a policy decision, a regulatory requirement, or a technical constraint? - Are there rules you'd expect that the system *doesn't* enforce today? +## How rules and flows group + +- The code keeps ``, `` and `` together in `` (`path:line`). Is + that how the business thinks about them, or do some belong elsewhere? +- What would you call that group? (the agreed name becomes the filename, and the directory where + it's an area) +- Is there a rule you'd expect in that group that sits somewhere else today? +- Does `` belong to one part of the business, or does it cross several? + ## Workflows - Walk me through `` end to end. Who starts it, what triggers it? diff --git a/skills/codebase-discovery/templates/current-architecture.md b/skills/codebase-discovery/templates/current-architecture.md index 410be84..84dcf35 100644 --- a/skills/codebase-discovery/templates/current-architecture.md +++ b/skills/codebase-discovery/templates/current-architecture.md @@ -10,7 +10,8 @@ plus one diagram. --> ## Overview -<2–4 sentences: style (monolith/services/etc.), primary stack, how it's driven.> +<2–4 sentences: style (monolith/services/etc.), primary stack, how it's driven, and the areas the +system divides into.> ## Context diagram @@ -23,11 +24,15 @@ graph LR ## Components - + + +| Component | Area | Responsibility | Key tech | +|---|---|---|---| +| | | | | ## Data & persistence From 8fb532e2b3e736beeb58746497410967fd24e072 Mon Sep 17 00:00:00 2001 From: Bryan Signey Date: Fri, 28 Aug 2026 13:59:54 +1000 Subject: [PATCH 07/15] fix ID scheme bug --- .../codebase-discovery/references/provenance-and-status.md | 4 ++++ skills/codebase-discovery/templates/traceability-index.md | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/skills/codebase-discovery/references/provenance-and-status.md b/skills/codebase-discovery/references/provenance-and-status.md index a1ac4ef..99f1af3 100644 --- a/skills/codebase-discovery/references/provenance-and-status.md +++ b/skills/codebase-discovery/references/provenance-and-status.md @@ -117,6 +117,10 @@ memory at the end produces rows nobody can check, and it's the failure Phase 4's to catch. IDs run sequentially and stay stable across runs, so a doc that cites one keeps pointing at the same claim. +**A claim that already carries an ID keeps it.** `C-n` is for claims this index mints. Requirements +arrive with their own from `business-requirements.md`, so index them as `FR-n` / `NFR-n` rather than +minting a second ID for the same statement, which would leave two rows nobody can reconcile. + Substantive claims get a row as the norm. For a claim that **carries real weight** (a rule, threshold, permission, SLA or ownership statement) it isn't optional: Phase 4 treats a missing entry there as material. diff --git a/skills/codebase-discovery/templates/traceability-index.md b/skills/codebase-discovery/templates/traceability-index.md index 60a88eb..3f6b7d6 100644 --- a/skills/codebase-discovery/templates/traceability-index.md +++ b/skills/codebase-discovery/templates/traceability-index.md @@ -8,6 +8,11 @@ | Claim ID | Claim (short) | Evidence (path:line / symbol / stakeholder) | Confidence | Used in doc | |---|---|---|---|---| | C-1 | | src/... : or "" | H/M/L | areas/billing/rules-refund-eligibility.md | +| FR-1 | | src/... : | H/M/L | business/business-requirements.md | +or a named person. Phase 4 verifies this. + +IDs: C-n for claims this index mints. A claim that already carries an ID in its own document keeps +it, which is why requirements are indexed as FR-n / NFR-n. See the traceability rule in +provenance-and-status. --> From d3c2ec4113f316955cf5245cb34bc58989c0db05 Mon Sep 17 00:00:00 2001 From: Bryan Signey Date: Fri, 28 Aug 2026 14:07:57 +1000 Subject: [PATCH 08/15] fix the exclusion to link register to onboarding docs bug --- .../references/discovery-disposition.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/skills/codebase-discovery/references/discovery-disposition.md b/skills/codebase-discovery/references/discovery-disposition.md index ed90d4a..6a1eac1 100644 --- a/skills/codebase-discovery/references/discovery-disposition.md +++ b/skills/codebase-discovery/references/discovery-disposition.md @@ -29,6 +29,14 @@ different fates: - Neither kind is ever linked from `CLAUDE.md` / `AGENTS.md`; the agent file links onboarding material only. +> **Why the docs link the register, when nothing here is an onboarding doc.** Settled deliberately. +> Every file under the output root carries `see ../_discovery/assumptions-register.md` in its header +> block, and the root `README.md` links it from open risks. That reads as a contradiction and isn't. +> The register is committed, so the link resolves on every clone, and a reader who meets an +> `[assumption]` needs one hop to reach what explains it. The ban above is the narrower one and the +> one worth keeping: `CLAUDE.md` and `AGENTS.md` link onboarding material only, so the two state +> files never load into an agent's session. + --- What each onboarding file is *for*, meaning layout, naming, header block and length, is From 689fc6fd1fe9b178908688323ec35bb81a202c85 Mon Sep 17 00:00:00 2001 From: Bryan Signey Date: Fri, 28 Aug 2026 14:14:32 +1000 Subject: [PATCH 09/15] fix coverage provenance issue --- agents/codebase-doc-verifier.md | 4 +++ skills/codebase-discovery/SKILL.md | 4 ++- .../playbooks/01-deep-recon.md | 7 +++-- .../playbooks/03-synthesis.md | 10 +++---- .../playbooks/04-verification.md | 10 +++++-- .../references/provenance-and-status.md | 27 +++++++++++++++++++ .../templates/project-readme.md | 14 +++++----- .../templates/recon-manifest.md | 13 ++++++--- 8 files changed, 69 insertions(+), 20 deletions(-) diff --git a/agents/codebase-doc-verifier.md b/agents/codebase-doc-verifier.md index 97807e6..d9a3c52 100644 --- a/agents/codebase-doc-verifier.md +++ b/agents/codebase-doc-verifier.md @@ -40,6 +40,10 @@ it traces to evidence. matches the glossary across docs; the recon manifest reflects the files actually read. The project-root `README.md` and the agent onboarding file carry no discovery metadata by design, so finding no date there is the intended state; don't report it. +- **Coverage is declared.** The entry point's area list should match the coverage ledger in + `docs/_discovery/recon-manifest.md`: every area present, each carrying its state, and no area + reading as covered whose ledger state isn't `full`. An area named in the architecture doc with + nothing behind it is what this catches. - **One glossary, not several.** Exactly one `domain-glossary.md`, at `domain/`, with no per-area variant beside it, and every term carrying an area or `cross-cutting`. A second glossary hides the cross-area clashes the single file exists to surface. diff --git a/skills/codebase-discovery/SKILL.md b/skills/codebase-discovery/SKILL.md index 977c4a3..4e22542 100644 --- a/skills/codebase-discovery/SKILL.md +++ b/skills/codebase-discovery/SKILL.md @@ -270,6 +270,7 @@ according to what the working state records: | Nothing (first run) | Phase 1 | | Recon incomplete — areas still pending in the ledger, **no drift** | Phase 1, continuing with those areas | | Recon incomplete, **drift in areas already covered** | Phase 1 — re-recon the drifted areas, then continue with the pending ones | +| Recon done, **code-only** (no interview to stop), docs not written | Phase 3 | | Recon done, interview stopped with items open, **no drift** | Phase 2 — continue the queue | | Recon done, interview stopped, **drift in the affected areas** | Phase 1 scoped to those areas, then Phase 2 | | Interview done, docs written, drift since | whatever the user chose in the freshness check | @@ -307,7 +308,8 @@ When done, report: - Doc-drift findings (existing docs vs code). - On a re-run: code drift since the last recon, and what the user chose to do about it. - Open `[assumption]` / `[unverified]` / `[contradicted]` items and their impact. -- Coverage: any area still pending in the ledger, and any claim still `[unchecked]` with why. +- Coverage: every area with its state from the ledger, not just the pending ones, and any claim + still `[unchecked]` with why. - (full mode) Interview coverage, as counts: register items whose next step is an interview, how many were asked, how many remain — and for each remaining one, its *Why parked* value from the register, with the SME named wherever that value is *needs SME*. Name the highest-impact diff --git a/skills/codebase-discovery/playbooks/01-deep-recon.md b/skills/codebase-discovery/playbooks/01-deep-recon.md index 28e883d..342daa0 100644 --- a/skills/codebase-discovery/playbooks/01-deep-recon.md +++ b/skills/codebase-discovery/playbooks/01-deep-recon.md @@ -103,8 +103,11 @@ What's left to decide is the **order** you work through them: This is a fact from the graph, not an inference. 3. **Entry points.** User-facing areas first when nothing else decides it. -Record every area in the manifest's coverage ledger, including the ones not yet reached. An area -missing from the ledger is an invisible gap; an area listed as pending is a known one. +Record every area in the manifest's coverage ledger, including the ones not yet reached and the ones +`--exclude` ruled out. An area missing from the ledger is an invisible gap; one listed as `pending` +or `excluded` is a known one. The depths are a closed set, defined in +[`../references/provenance-and-status.md`](../references/provenance-and-status.md), and every state +but `full` is a gap Phase 3 has to declare at the entry point. **On a large repo, work across sessions rather than trimming.** Tier 0 has just priced the job (the area list and the rough size), so put that in front of the user before spending it, and let them say diff --git a/skills/codebase-discovery/playbooks/03-synthesis.md b/skills/codebase-discovery/playbooks/03-synthesis.md index f971fe2..a68780b 100644 --- a/skills/codebase-discovery/playbooks/03-synthesis.md +++ b/skills/codebase-discovery/playbooks/03-synthesis.md @@ -49,11 +49,11 @@ judgements are this phase's own, plus two rules: one about coverage, one about e logical name; anything no single area owns is cross-cutting and belongs at the top level. Getting this wrong is what turns one document into an unreadable pile, and the glossary in particular stays a single file whatever the system's size. -- **Partial recon still publishes, provided the gaps are declared.** Where recon covered some areas - and left others pending, write what's covered rather than withholding everything. The entry - point must say which areas are documented and which aren't (see the README bullet below), and a - claim about an uncovered area stays `[unchecked]` and unpublished. A partial doc set a reader can - see the edges of is useful; one that reads as complete is the failure this guards against. +- **Partial recon still publishes, provided the gaps are declared.** Write what's covered rather than + withholding everything. Each area reaches the entry point carrying its coverage state, per the + coverage states in provenance-and-status, and a claim about an area nobody read stays `[unchecked]` + and unpublished. A partial doc set a reader can see the edges of is useful; one that reads as + complete is the failure this guards against. - **Record each claim's evidence as you write it.** A row in `docs/_discovery/traceability-index.md` per claim, added while the evidence is in front of you. See the traceability rule in provenance-and-status. Phase 4 checks these, and a claim carrying diff --git a/skills/codebase-discovery/playbooks/04-verification.md b/skills/codebase-discovery/playbooks/04-verification.md index fe9cc51..2d8bb4e 100644 --- a/skills/codebase-discovery/playbooks/04-verification.md +++ b/skills/codebase-discovery/playbooks/04-verification.md @@ -58,6 +58,11 @@ pass an **absolute** path or put the substance in the prompt. The checks below r agent file points at a file that exists. Skipped documents are the usual culprit, since the index templates list the full set. + **Coverage is declared.** The entry point's area list matches the manifest's coverage ledger: + every area present, each carrying its state, and no area reading as covered whose ledger state + isn't `full`. An area named in the architecture doc with nothing behind it is what this catches, + and it's the one coverage claim a checker can settle mechanically. + **The glossary is one file.** Exactly one `domain-glossary.md`, at `domain/`, with no per-area variant beside it, and every term carrying an area or `cross-cutting`. A second glossary hides the cross-area clashes the single file exists to surface. @@ -119,8 +124,9 @@ Produce a short verification report: terminology drifting from the glossary, leftover scaffolding, a dead link. Edits, not grounds for a round trip. -**One rework cycle, then stop.** Route material problems to where they can be fixed (synthesis for -anything the code can settle, the interview only where it genuinely needs a person) and re-verify +**One rework cycle, then stop.** Route material problems to where they can be fixed: synthesis for +anything the code can settle, the interview only where it needs a person. In `code-only` mode there +is no interview, so those park in the register as *needs SME* instead of blocking the run. Re-verify **only the affected documents**, not the whole set. If a second pass still finds material problems, stop and report **no-go** with the specific unresolved items rather than starting a third lap. diff --git a/skills/codebase-discovery/references/provenance-and-status.md b/skills/codebase-discovery/references/provenance-and-status.md index 99f1af3..dd6ea0e 100644 --- a/skills/codebase-discovery/references/provenance-and-status.md +++ b/skills/codebase-discovery/references/provenance-and-status.md @@ -62,6 +62,33 @@ needs it, flagged, so nobody mistakes it for something the code was checked agai --- +## Coverage states (the vocabulary, stated only here) + +A flag describes a claim. **A coverage state describes an area**, and the two interlock: a claim in +an area recon never dived into has no current code check behind it, which is the second +`[unchecked]` cause above. + +Phase 1 records one per area in the recon manifest's coverage ledger. The set is closed, on the same +terms as the flags: + +| State | Means | Area docs expected | +|---|---|---| +| `full` | data model, contracts, hotspots and tests all worked | yes | +| `hotspots only` | business logic read, the rest not | partial, and say which | +| `map only` | Tier 0 map only, dives judged not warranted | no; named in the architecture doc | +| `excluded` | the user excluded these paths, so nothing was read | no; named in the architecture doc | +| `pending` | not yet reached | no | + +**Every area reaches the reader carrying its state.** Anything but `full` is a declared gap, and it +travels: the ledger, then the entry point's area list, then the completion report. Phase 4 checks +the entry point against the ledger. + +`pending` already travels, and it's the honest gap. `map only` and `excluded` are the ones that +mislead, because the area is named in `current-architecture.md` and looks covered when nothing sits +behind it. That is the failure the synthesis playbook's partial-publish rule exists to stop. + +--- + ## Lifecycle of a claim ``` diff --git a/skills/codebase-discovery/templates/project-readme.md b/skills/codebase-discovery/templates/project-readme.md index ff5b186..92fcf7c 100644 --- a/skills/codebase-discovery/templates/project-readme.md +++ b/skills/codebase-discovery/templates/project-readme.md @@ -29,16 +29,18 @@ Onboarding docs live under [`docs/`](./docs/): | [docs/business/user-personas.md](./docs/business/user-personas.md) | Who uses it | +inside it. Omit this section entirely on a single-area system. List EVERY area, so a reader can see +the edge of what's covered; drop the link where there are no area docs to link to. The Coverage +column takes the area's state from the recon manifest's ledger, unchanged, so the reader sees the +same word the audit trail does. --> ### Areas -| Area | What it covers | Documented | +| Area | What it covers | Coverage | |---|---|---| -| [docs/areas//](./docs/areas//) | | yes | -| | | not yet | +| [docs/areas//](./docs/areas//) | | full | +| | | map only | +| | | pending | ## Getting started diff --git a/skills/codebase-discovery/templates/recon-manifest.md b/skills/codebase-discovery/templates/recon-manifest.md index c7fb13b..f576345 100644 --- a/skills/codebase-discovery/templates/recon-manifest.md +++ b/skills/codebase-discovery/templates/recon-manifest.md @@ -24,16 +24,21 @@ ## Coverage ledger (Phase 1 onward) - + | Area | Paths | Recon depth | Source tier | Interview | Docs written | |---|---|---|---|---|---| | billing | src/Billing/, src/Invoicing/ | full | declared + text search | done (A. Patel) | areas/billing/* | | identity | src/Identity/ | hotspots only | text search (inferred) | queued | — | | tooling | infra/ | map only — dives not warranted | declared | n/a | tech/current-architecture.md | +| vendor-portal | third-party/ | excluded — user's `--exclude` | declared | n/a | tech/current-architecture.md | | reporting | src/Reporting/ | **pending** — not yet reached | — | — | — | ## Files actually read (Phase 1) From 0a8a3d58fe9e87c602bbd56b4248bc9e9449de49 Mon Sep 17 00:00:00 2001 From: Bryan Signey Date: Fri, 28 Aug 2026 14:27:24 +1000 Subject: [PATCH 10/15] fix readme staleness and secrets handling inconsistency --- skills/codebase-discovery/README.md | 21 ++++++++++++------- skills/codebase-discovery/SKILL.md | 2 +- .../references/freshness.md | 7 ++++++- .../templates/current-architecture.md | 3 +++ .../templates/discovery-state.md | 4 ++++ 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/skills/codebase-discovery/README.md b/skills/codebase-discovery/README.md index 6ae4c5e..25d0bc9 100644 --- a/skills/codebase-discovery/README.md +++ b/skills/codebase-discovery/README.md @@ -24,8 +24,9 @@ relied on. ## How it works: six phases -0. **Pre-check** — read any existing `README` / `CLAUDE.md` / `AGENTS.md` / `docs`, and - capture what they state, to verify against the code. +0. **Pre-check** — settle the output root with the user before anything is written, then read any + existing `README` / `CLAUDE.md` / `AGENTS.md` / `docs` and capture what they state, to verify + against the code. 1. **Deep recon** — tiered, evidence-cited code analysis (structure → data model → contracts/edges → business-logic hotspots), token-efficient via sub-agents where available. Reads the structure the repo **declares** (build manifests, workspace files, runtime @@ -43,8 +44,9 @@ relied on. ## Modes - **full** — with a stakeholder to validate findings. -- **code-only** — no interview; everything needing confirmation is flagged - `[assumption]` / `[unverified]` for later. For when no SME is available yet. +- **code-only** — no interview. The provenance caveat is stated once per document rather than on + every line, and everything still open is tracked in the assumptions register (see Status model + below). For when no SME is available yet. ## Host-agnostic by design @@ -66,9 +68,14 @@ there?) and settles the **output root** with the user before a byte is written. **Material is filed one concept per file, under names drawn from the domain language**, so an agent working on billing loads `areas/billing/`, not every rule in the system. Area-specific material lives in its area; what no single area owns stays at the top level; and the glossary is always one file, -because it's the shared vocabulary and splitting it would defeat the point. A single-area system keeps -the flat layout with no `areas/` at all, because the trigger is whether the content has an area -dimension, not how big the repo is. +with an `Area` column carrying ownership, because one place to look a word up is also the only place +a clash between two areas' meanings shows. A single-area system keeps the flat layout with no +`areas/` at all, because the trigger is whether the content has an area dimension, not how big the +repo is. + +Coverage travels with the docs. Each area reaches the entry point carrying its state, so a reader can +see the edge of what was examined rather than assuming the set is complete. +[`references/provenance-and-status.md`](references/provenance-and-status.md) defines the states. ``` README.md # project-root: onboarding index / entry point — the file CLAUDE.md/AGENTS.md links diff --git a/skills/codebase-discovery/SKILL.md b/skills/codebase-discovery/SKILL.md index 4e22542..3448f29 100644 --- a/skills/codebase-discovery/SKILL.md +++ b/skills/codebase-discovery/SKILL.md @@ -273,7 +273,7 @@ according to what the working state records: | Recon done, **code-only** (no interview to stop), docs not written | Phase 3 | | Recon done, interview stopped with items open, **no drift** | Phase 2 — continue the queue | | Recon done, interview stopped, **drift in the affected areas** | Phase 1 scoped to those areas, then Phase 2 | -| Interview done, docs written, drift since | whatever the user chose in the freshness check | +| Interview done, docs written, drift since | per the freshness check: Phase 1 then Phase 3 where the user re-recons, Phase 3 alone where they don't, to carry the reverted flags into the docs | Never interview about a rule whose code has changed since recon: re-recon that area first, or the question is built on a stale premise. Say which phase you're entering and why before you start. diff --git a/skills/codebase-discovery/references/freshness.md b/skills/codebase-discovery/references/freshness.md index a99be9e..00b1422 100644 --- a/skills/codebase-discovery/references/freshness.md +++ b/skills/codebase-discovery/references/freshness.md @@ -53,12 +53,17 @@ action you're taking and why it was chosen for you: paths themselves moved, since patching area by area costs more than a clean pass. - **Proceed as-is** — reasonable when the drift is in areas irrelevant to what the user is doing now. Not free: see the flag rule below. -- **Report only** — produce the drift list as a to-do and change nothing. Same flag rule. +- **Report only** — produce the drift list as a to-do and add no new documentation. The flag rule + below still applies, so the affected claims are re-flagged where they stand. If the user declines to re-recon, the affected claims no longer have verified backing: revert them to `[unchecked]` and log them in the assumptions register, exactly as if they'd come from someone else's stale documentation, which, as of now, they have. Never leave a claim reading as accepted when the code beneath it has moved. +Reverting a flag is a documentation edit, so it runs through Phase 3 like any other, and the docs and +the register have to agree by the time it's done. That holds for all four options: the two that +re-recon reach Phase 3 through Phase 1, and the two that don't reach it directly. + Record the decision in the manifest's freshness-check log, so the next session knows this was chosen rather than missed. diff --git a/skills/codebase-discovery/templates/current-architecture.md b/skills/codebase-discovery/templates/current-architecture.md index 84dcf35..fe1a1c0 100644 --- a/skills/codebase-discovery/templates/current-architecture.md +++ b/skills/codebase-discovery/templates/current-architecture.md @@ -44,6 +44,9 @@ not what's in them. Drop the column on a single-area system, which has no areas/ ## Cross-cutting concerns + + ## Notable constraints & risks diff --git a/skills/codebase-discovery/templates/discovery-state.md b/skills/codebase-discovery/templates/discovery-state.md index ebf2436..cf3b87f 100644 --- a/skills/codebase-discovery/templates/discovery-state.md +++ b/skills/codebase-discovery/templates/discovery-state.md @@ -15,6 +15,10 @@ it's growing, you're appending where you should be rewriting. Compact as you go: - What earns its place: mode and options, the write-target facts, open threads, decisions, and where you stopped. Everything else has somewhere better to be. --> + + ## Run - **Mode:** full | code-only From 5cf2ca767be2a7db259ce76852967cd6698053a2 Mon Sep 17 00:00:00 2001 From: Bryan Signey Date: Fri, 28 Aug 2026 14:35:19 +1000 Subject: [PATCH 11/15] fix a no-go inconsistency --- .../codebase-discovery/playbooks/04-verification.md | 5 +++++ skills/codebase-discovery/playbooks/05-finish.md | 13 ++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/skills/codebase-discovery/playbooks/04-verification.md b/skills/codebase-discovery/playbooks/04-verification.md index 2d8bb4e..a77b117 100644 --- a/skills/codebase-discovery/playbooks/04-verification.md +++ b/skills/codebase-discovery/playbooks/04-verification.md @@ -105,6 +105,11 @@ Produce a short verification report: - Bloat or duplication trimmed. - Go / no-go for harness engineering / Spec Kit, with any caveats. +**Record the verdict in `discovery-state.md` under Decisions**, with the unresolved items behind it. +Phase 5 reads it there and gates the agent file on it. A verdict that lives only in this conversation +is gone when the session ends, and the next run would offer an agent file over docs nobody +re-checked. + --- ## What counts as material, and what to do about it diff --git a/skills/codebase-discovery/playbooks/05-finish.md b/skills/codebase-discovery/playbooks/05-finish.md index 6458122..edd9e35 100644 --- a/skills/codebase-discovery/playbooks/05-finish.md +++ b/skills/codebase-discovery/playbooks/05-finish.md @@ -5,7 +5,9 @@ contradictions that need a human, and leave the repo set up so the next agent (or joiner) lands somewhere useful. -Enter this once Phases 0–4 are complete. The completion report itself is specified in `SKILL.md`. +Enter this once Phases 0–4 are complete. Read Phase 4's verdict from `discovery-state.md` before you +start: a **no-go** changes step 3 and nothing else, so steps 1, 2 and 4 run either way. The +completion report itself is specified in `SKILL.md`. > **Prediction rule** (`SKILL.md`): don't treat a step as discharged because a similar step was done. > Steps 1 and 2 below overlap in subject and differ in scope. @@ -44,7 +46,11 @@ case in `code-only` mode. ## 3. Agent file (optional) -Offer to create or augment an agent onboarding file: +**Withhold it on a no-go, unless the user signs off knowing what failed.** Every later session loads +this file, and its whole job is pointing agents at the docs, so pointing them at docs Phase 4 +rejected is worse than leaving the repo alone. Name the unresolved items and let the user decide. + +On a go, offer to create or augment an agent onboarding file: - **Detect and match** whatever already exists (`CLAUDE.md` or `AGENTS.md`). - If **neither** exists, offer **both**. @@ -70,6 +76,7 @@ Explain the outcome in the completion report. "Left flagged" is an outcome of asking, or of a needs-SME gap — never a default for items nobody raised. State the denominator: *N flagged, A asked, C confirmed, R corrected, P parked as needs SME*, where N = C + R + P. -- Agent file created, augmented or offered; nothing overwritten without sign-off. +- Agent file created, augmented or offered, or withheld on a no-go with the unresolved items named; + nothing overwritten without sign-off. - `_discovery/` left in place and its disposition explained. - Completion report delivered as specified in `SKILL.md`. From 782c787526944cb6ee88d5c621bce851fd44bd51 Mon Sep 17 00:00:00 2001 From: Bryan Signey Date: Fri, 28 Aug 2026 15:03:11 +1000 Subject: [PATCH 12/15] fix stalling at tier 0 on recon phase --- skills/codebase-discovery/SKILL.md | 10 +++++++++- skills/codebase-discovery/playbooks/01-deep-recon.md | 4 +++- .../references/provenance-and-status.md | 1 - skills/codebase-discovery/templates/recon-manifest.md | 4 ++-- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/skills/codebase-discovery/SKILL.md b/skills/codebase-discovery/SKILL.md index 3448f29..0d53eb0 100644 --- a/skills/codebase-discovery/SKILL.md +++ b/skills/codebase-discovery/SKILL.md @@ -187,7 +187,7 @@ the Phases table below; what differs is Phase 2: - **full** — runs the interview. Requires a stakeholder (senior BA / Product Owner / SME) to validate findings. -- **code-only** — skips it. Everything that would need human confirmation stays `[assumption]` / +- **code-only** — skips it. Everything that would need SME confirmation stays `[assumption]` / `[unverified]` for later validation. Use when no SME is available yet. State the chosen mode before starting. @@ -212,6 +212,14 @@ At the start of each phase, check what is available and adapt, never hard-fail: same steps sequentially with disciplined, excerpt-only reading. - **Stakeholder (SME)** — if none is available, drop from `full` to `code-only` mode. +**One input is not optional: someone to answer.** Not the SME, whose absence `code-only` covers, but +whoever gives consent. Options pre-answer **choices** (the output root, the drift response, what to +exclude). They never pre-answer **consent**: sign-off before an existing README changes, Phase 5's +reconciliations, writing an agent file. That is `--fresh`'s rule generalised, an option settles a +choice and never an act that changes someone else's work. The prediction rule means you ask rather +than guess, so an unattended run stalls at the first consent gate rather than improvising. Correct +behaviour, and still a stall. Say so up front if nobody is available. + --- ## Working state (resumable, no hooks) diff --git a/skills/codebase-discovery/playbooks/01-deep-recon.md b/skills/codebase-discovery/playbooks/01-deep-recon.md index 342daa0..4b67f08 100644 --- a/skills/codebase-discovery/playbooks/01-deep-recon.md +++ b/skills/codebase-discovery/playbooks/01-deep-recon.md @@ -62,7 +62,9 @@ Two things need saying to the user rather than deciding silently: ## Tier 0: structural map (cheap, get approval) -Produce a quick orientation, then pause for the user to approve deeper spend. +Produce a quick orientation and record it, then pause for the user to approve deeper spend. +Recording before the pause is what makes a stall cheap. If nobody answers, the map and the area list +survive, and the next session resumes from them rather than re-deriving them. **Start from the declared structure, not the directory tree.** The manifests and the repo's own toolchain state the module graph outright, so read that first (Tier A/B of the ladder), and only use diff --git a/skills/codebase-discovery/references/provenance-and-status.md b/skills/codebase-discovery/references/provenance-and-status.md index dd6ea0e..fe952fe 100644 --- a/skills/codebase-discovery/references/provenance-and-status.md +++ b/skills/codebase-discovery/references/provenance-and-status.md @@ -74,7 +74,6 @@ terms as the flags: | State | Means | Area docs expected | |---|---|---| | `full` | data model, contracts, hotspots and tests all worked | yes | -| `hotspots only` | business logic read, the rest not | partial, and say which | | `map only` | Tier 0 map only, dives judged not warranted | no; named in the architecture doc | | `excluded` | the user excluded these paths, so nothing was read | no; named in the architecture doc | | `pending` | not yet reached | no | diff --git a/skills/codebase-discovery/templates/recon-manifest.md b/skills/codebase-discovery/templates/recon-manifest.md index f576345..3ad7b3a 100644 --- a/skills/codebase-discovery/templates/recon-manifest.md +++ b/skills/codebase-discovery/templates/recon-manifest.md @@ -29,14 +29,14 @@ from this table is an invisible gap; one listed as pending or excluded is a know the freshness check works in: the next run diffs the recon commit against HEAD and re-recons the areas whose paths changed. Areas, never one row per file. -Recon depth takes one of five values: full, hotspots only, map only, excluded, pending. The set is +Recon depth takes one of four values: full, map only, excluded, pending. The set is closed; see the coverage states in provenance-and-status. Every state but full is a gap the entry point has to declare. --> | Area | Paths | Recon depth | Source tier | Interview | Docs written | |---|---|---|---|---|---| | billing | src/Billing/, src/Invoicing/ | full | declared + text search | done (A. Patel) | areas/billing/* | -| identity | src/Identity/ | hotspots only | text search (inferred) | queued | — | +| identity | src/Identity/ | full | text search (inferred) | queued | areas/identity/* | | tooling | infra/ | map only — dives not warranted | declared | n/a | tech/current-architecture.md | | vendor-portal | third-party/ | excluded — user's `--exclude` | declared | n/a | tech/current-architecture.md | | reporting | src/Reporting/ | **pending** — not yet reached | — | — | — | From 3aafe43dd59e5003fba31f61d1c56ca48c75f3b4 Mon Sep 17 00:00:00 2001 From: Bryan Signey Date: Fri, 28 Aug 2026 15:15:47 +1000 Subject: [PATCH 13/15] fix write contract scoping drift and coverage vocabulary duplication --- agents/codebase-doc-verifier.md | 4 +++- skills/codebase-discovery/playbooks/04-verification.md | 10 ++++++++-- skills/codebase-discovery/playbooks/05-finish.md | 7 ++++--- skills/codebase-discovery/references/write-contract.md | 6 ++++-- .../templates/agent-onboarding-file.md | 3 ++- skills/codebase-discovery/templates/recon-manifest.md | 5 ++--- 6 files changed, 23 insertions(+), 12 deletions(-) diff --git a/agents/codebase-doc-verifier.md b/agents/codebase-doc-verifier.md index d9a3c52..2093486 100644 --- a/agents/codebase-doc-verifier.md +++ b/agents/codebase-doc-verifier.md @@ -37,7 +37,9 @@ it traces to evidence. - **Links resolve.** Check every link in the docs set, the project-root `README.md` and the agent file points at a file that exists; documents that were skipped are the usual culprit. - **Freshness and consistency.** Every doc in the `docs/` set has a `Last updated` date; terminology - matches the glossary across docs; the recon manifest reflects the files actually read. The + matches the glossary across docs; every path the recon manifest lists as read still exists. You + have no record of what recon opened, so report a path that has gone missing and leave whether the + list is complete to the caller, which does know. The project-root `README.md` and the agent onboarding file carry no discovery metadata by design, so finding no date there is the intended state; don't report it. - **Coverage is declared.** The entry point's area list should match the coverage ledger in diff --git a/skills/codebase-discovery/playbooks/04-verification.md b/skills/codebase-discovery/playbooks/04-verification.md index a77b117..8475387 100644 --- a/skills/codebase-discovery/playbooks/04-verification.md +++ b/skills/codebase-discovery/playbooks/04-verification.md @@ -9,6 +9,11 @@ Run this as an **isolated pass**, in a sub-agent where available, so the check i of the work that produced the docs. On Claude Code, dispatch the **`codebase-doc-verifier`** subagent; on other hosts use any generic sub-agent, or run the checks directly. +**Running them directly costs the independence, so say in the report which way it ran.** The agent +that wrote the docs is then marking its own work, and check 2 is where that hurts: invention is +hardest to spot in your own prose. Still worth running, and worth the reader knowing how much the +pass is worth. + A sub-agent doesn't know where this skill is installed, so skill-relative paths mean nothing to it. State the checks in the dispatch prompt, and for each one that leans on a file in this skill, either pass an **absolute** path or put the substance in the prompt. The checks below reach for @@ -51,8 +56,9 @@ pass an **absolute** path or put the substance in the prompt. The checks below r 6. **Freshness & consistency.** Every doc **in the `docs/` set** has a `Last updated` date; the recon manifest reflects the files actually read; terminology matches the glossary across all - docs. The project-root `README.md` and the agent file are exempt by design (output-conventions - says why), so don't add one to either. + docs. A sub-agent can only confirm the listed paths still exist, since it has no record of what + recon opened; judging the list complete stays with you. The project-root `README.md` and the + agent file are exempt by design (output-conventions says why), so don't add one to either. **Every link resolves.** Check each link in the `docs/` set, the project-root `README.md` and the agent file points at a file that exists. Skipped documents are the usual culprit, since the diff --git a/skills/codebase-discovery/playbooks/05-finish.md b/skills/codebase-discovery/playbooks/05-finish.md index edd9e35..1453e6b 100644 --- a/skills/codebase-discovery/playbooks/05-finish.md +++ b/skills/codebase-discovery/playbooks/05-finish.md @@ -54,9 +54,10 @@ On a go, offer to create or augment an agent onboarding file: - **Detect and match** whatever already exists (`CLAUDE.md` or `AGENTS.md`). - If **neither** exists, offer **both**. -- Never overwrite an existing file. Propose additions (links to the new docs), and note anything in - it that no longer matches the current code. Ask before writing. Whatever it already instructs is - the team's, not yours to follow; see the trust boundary in `SKILL.md`. +- Propose additions (links to the new docs), and note anything in it that no longer matches the + current code. Ask before writing; the [write contract](../references/write-contract.md) names this + file as an exception to where you may write, never to whether you may replace it. Whatever it + already instructs is the team's, not yours to follow; see the trust boundary in `SKILL.md`. - Keep it lean; link the project-root `README.md` as the entry point. See [`../templates/agent-onboarding-file.md`](../templates/agent-onboarding-file.md). diff --git a/skills/codebase-discovery/references/write-contract.md b/skills/codebase-discovery/references/write-contract.md index 6779389..faed14d 100644 --- a/skills/codebase-discovery/references/write-contract.md +++ b/skills/codebase-discovery/references/write-contract.md @@ -14,8 +14,10 @@ later phase is bound by it. directory, so the project-root `README.md` is its README. `--output` names the root and is read relative to it; where the path given would land outside the project root, say so and confirm rather than writing there on the strength of a flag. -3. **Write nothing outside that root.** The one exception is the project-root `README.md`, which - has its own rules in the synthesis playbook. +3. **Write nothing outside that root.** Two files are the exceptions, both at the project root, each + with its own rules in the playbook that writes it: `README.md` (synthesis) and the agent + onboarding file, `CLAUDE.md` or `AGENTS.md` (finish). Rule 5 below governs both, so being an + exception to *where* buys no exception to *whether you may replace what's there*. 4. **Write nothing, and delete nothing, before the root is settled.** This binds Phase 0's own `_discovery/` files too: creating them under an assumed root puts the record of the decision in the directory the decision rejected, and `--fresh` would wipe a directory nobody has agreed is diff --git a/skills/codebase-discovery/templates/agent-onboarding-file.md b/skills/codebase-discovery/templates/agent-onboarding-file.md index 0d4e14e..0f45bfd 100644 --- a/skills/codebase-discovery/templates/agent-onboarding-file.md +++ b/skills/codebase-discovery/templates/agent-onboarding-file.md @@ -4,7 +4,8 @@ Template for a generated CLAUDE.md / AGENTS.md. Rules (see the skill's Phase 5 finish playbook): - Detect and match whatever already exists (CLAUDE.md or AGENTS.md). If neither exists, offer both. -- Never overwrite an existing file. Propose additions and note any content that no longer matches the code. +- Propose additions and note any content that no longer matches the code. Whether you may replace + what's already here is the skill's write contract, not this file's to decide. - Keep it lean. Link the project-root README.md as the entry point; do NOT link docs/_discovery/. - Fill the placeholders; delete guidance comments before writing. --> diff --git a/skills/codebase-discovery/templates/recon-manifest.md b/skills/codebase-discovery/templates/recon-manifest.md index 3ad7b3a..3ddcc87 100644 --- a/skills/codebase-discovery/templates/recon-manifest.md +++ b/skills/codebase-discovery/templates/recon-manifest.md @@ -29,9 +29,8 @@ from this table is an invisible gap; one listed as pending or excluded is a know the freshness check works in: the next run diffs the recon commit against HEAD and re-recons the areas whose paths changed. Areas, never one row per file. -Recon depth takes one of four values: full, map only, excluded, pending. The set is -closed; see the coverage states in provenance-and-status. Every state but full is a gap the entry -point has to declare. --> +Recon depth comes from the closed set in provenance-and-status, and the rows below show each value in +use. Every state but full is a gap the entry point has to declare. --> | Area | Paths | Recon depth | Source tier | Interview | Docs written | |---|---|---|---|---|---| From ecc2e3ce7ec1301d80cfb412e60e34e0bc65a419 Mon Sep 17 00:00:00 2001 From: Bryan Signey Date: Fri, 28 Aug 2026 15:34:25 +1000 Subject: [PATCH 14/15] single area documents fix and rerun interview bug fix --- agents/codebase-doc-verifier.md | 9 +++++---- skills/codebase-discovery/README.md | 6 +++--- skills/codebase-discovery/SKILL.md | 13 +++++++++---- .../codebase-discovery/playbooks/03-synthesis.md | 14 +++++++------- .../playbooks/04-verification.md | 15 +++++++++++---- .../references/output-conventions.md | 6 +++--- .../references/provenance-and-status.md | 9 ++++++--- .../templates/project-readme.md | 6 ++++++ 8 files changed, 50 insertions(+), 28 deletions(-) diff --git a/agents/codebase-doc-verifier.md b/agents/codebase-doc-verifier.md index 2093486..1273a54 100644 --- a/agents/codebase-doc-verifier.md +++ b/agents/codebase-doc-verifier.md @@ -42,10 +42,11 @@ it traces to evidence. list is complete to the caller, which does know. The project-root `README.md` and the agent onboarding file carry no discovery metadata by design, so finding no date there is the intended state; don't report it. -- **Coverage is declared.** The entry point's area list should match the coverage ledger in - `docs/_discovery/recon-manifest.md`: every area present, each carrying its state, and no area - reading as covered whose ledger state isn't `full`. An area named in the architecture doc with - nothing behind it is what this catches. +- **Coverage is declared.** A coverage line should be present in the entry point whatever the + layout, and its absence is a finding. Where the system has areas, the area list should also match + the coverage ledger in `docs/_discovery/recon-manifest.md`: every area present with its state, + none reading as covered whose ledger state isn't `full`. A single-area system has no area list, so + the line carries it alone; don't pass the check just because there's no list to compare. - **One glossary, not several.** Exactly one `domain-glossary.md`, at `domain/`, with no per-area variant beside it, and every term carrying an area or `cross-cutting`. A second glossary hides the cross-area clashes the single file exists to surface. diff --git a/skills/codebase-discovery/README.md b/skills/codebase-discovery/README.md index 25d0bc9..5ef01ba 100644 --- a/skills/codebase-discovery/README.md +++ b/skills/codebase-discovery/README.md @@ -80,14 +80,14 @@ see the edge of what was examined rather than assuming the set is complete. ``` README.md # project-root: onboarding index / entry point — the file CLAUDE.md/AGENTS.md links docs/ -├── business/ # cross-cutting only +├── business/ # cross-cutting, or a single-area system's │ ├── business-requirements.md # functional + non-functional │ ├── user-personas.md # users & stakeholders -│ └── workflow-.md # flows that cross areas +│ └── workflow-.md # flows that cross areas, or the only area's ├── domain/ # system-wide domain │ ├── domain-glossary.md # business language — always a single file │ ├── domain-model.md # aggregates + cross-area relationships (+ Mermaid) -│ └── rules-.md # rules that apply system-wide +│ └── rules-.md # rules that apply system-wide, or the only area's ├── tech/ │ ├── current-architecture.md # as-is architecture (+ Mermaid), names the areas │ └── integrations.md # external systems, dependencies, data feeds diff --git a/skills/codebase-discovery/SKILL.md b/skills/codebase-discovery/SKILL.md index 0d53eb0..6a3afff 100644 --- a/skills/codebase-discovery/SKILL.md +++ b/skills/codebase-discovery/SKILL.md @@ -281,10 +281,15 @@ according to what the working state records: | Recon done, **code-only** (no interview to stop), docs not written | Phase 3 | | Recon done, interview stopped with items open, **no drift** | Phase 2 — continue the queue | | Recon done, interview stopped, **drift in the affected areas** | Phase 1 scoped to those areas, then Phase 2 | -| Interview done, docs written, drift since | per the freshness check: Phase 1 then Phase 3 where the user re-recons, Phase 3 alone where they don't, to carry the reverted flags into the docs | +| Interview done, docs written, drift since | per the freshness check: Phase 1 then Phase 3 where the user re-recons, Phase 3 alone where they don't, to carry the reverted flags into the docs. Phase 2 in between where re-recon left open interview items | Never interview about a rule whose code has changed since recon: re-recon that area first, or the -question is built on a stale premise. Say which phase you're entering and why before you start. +question is built on a stale premise. And the converse: a finished interview is not permanently +finished, so in `full` mode any route that re-runs Phase 1 passes back through Phase 2 where the +register has open items whose next step is an interview. New code raises new questions, and whether +the queue is empty is something the register answers, not something a past run settled. + +Say which phase you're entering and why before you start. --- @@ -325,7 +330,7 @@ When done, report: the gap. - **Reconciliation coverage** (Phase 5 step 2), as counts: `[contradicted]` / `[outdated]` items flagged, asked, confirmed, corrected, and parked as *needs SME*, with the SME named. -- Whether a `CLAUDE.md` / `AGENTS.md` was created or proposed. +- Whether a `CLAUDE.md` / `AGENTS.md` was created, proposed, or withheld on a no-go. - **`docs/_discovery/` disposition** per [`references/discovery-disposition.md`](./references/discovery-disposition.md). - Readiness for harness engineering / Spec Kit. @@ -346,6 +351,6 @@ When done, report: - [ ] Onboarding docs written under `docs/`, dated and provenance-flagged - [ ] Verification pass complete; unsupported claims flagged - [ ] Assumptions register and traceability index populated -- [ ] CLAUDE.md / AGENTS.md created or proposed +- [ ] CLAUDE.md / AGENTS.md created, proposed, or withheld on a no-go - [ ] docs/_discovery/ disposition explained per discovery-disposition - [ ] Ready for harness engineering / Spec Kit diff --git a/skills/codebase-discovery/playbooks/03-synthesis.md b/skills/codebase-discovery/playbooks/03-synthesis.md index a68780b..dd9765e 100644 --- a/skills/codebase-discovery/playbooks/03-synthesis.md +++ b/skills/codebase-discovery/playbooks/03-synthesis.md @@ -50,10 +50,10 @@ judgements are this phase's own, plus two rules: one about coverage, one about e this wrong is what turns one document into an unreadable pile, and the glossary in particular stays a single file whatever the system's size. - **Partial recon still publishes, provided the gaps are declared.** Write what's covered rather than - withholding everything. Each area reaches the entry point carrying its coverage state, per the - coverage states in provenance-and-status, and a claim about an area nobody read stays `[unchecked]` - and unpublished. A partial doc set a reader can see the edges of is useful; one that reads as - complete is the failure this guards against. + withholding everything. The entry point carries a coverage line whether or not the system has + areas, and an area list as well where it does, per the coverage states in provenance-and-status. + A claim about an area nobody read stays `[unchecked]` and unpublished. A partial doc set a reader + can see the edges of is useful; one that reads as complete is the failure this guards against. - **Record each claim's evidence as you write it.** A row in `docs/_discovery/traceability-index.md` per claim, added while the evidence is in front of you. See the traceability rule in provenance-and-status. Phase 4 checks these, and a claim carrying @@ -85,9 +85,9 @@ or so it must: the root, e.g. `docs/tech/current-architecture.md`). - List the top open assumptions/risks, linking `docs/_discovery/assumptions-register.md` for the full list. -- Where recon left areas pending, name them, saying which areas are documented and which aren't. A - reader, human or harness, must be able to see the edge of what's covered without reading the - ledger. +- State the run's coverage on its own line, always. Where the system has areas, name each one and its + state as well. A reader, human or harness, must be able to see the edge of what's covered without + reading the ledger, and on a single-area system that line is the only place it gets said. - Where the code reveals it, a short "how to run / get started". Produce it from the findings using diff --git a/skills/codebase-discovery/playbooks/04-verification.md b/skills/codebase-discovery/playbooks/04-verification.md index 8475387..20c31f0 100644 --- a/skills/codebase-discovery/playbooks/04-verification.md +++ b/skills/codebase-discovery/playbooks/04-verification.md @@ -64,10 +64,12 @@ pass an **absolute** path or put the substance in the prompt. The checks below r agent file points at a file that exists. Skipped documents are the usual culprit, since the index templates list the full set. - **Coverage is declared.** The entry point's area list matches the manifest's coverage ledger: - every area present, each carrying its state, and no area reading as covered whose ledger state - isn't `full`. An area named in the architecture doc with nothing behind it is what this catches, - and it's the one coverage claim a checker can settle mechanically. + **Coverage is declared.** A coverage line is present in the entry point whatever the layout, and + its absence is the finding. Where the system has areas, the area list matches the manifest's + ledger too: every area present with its state, none reading as covered whose ledger state isn't + `full`. A single-area system has no list, so the line carries it alone and skipping the check + there is how a shallow run reads as a thorough one. This is the one coverage claim a checker can + settle mechanically. **The glossary is one file.** Exactly one `domain-glossary.md`, at `domain/`, with no per-area variant beside it, and every term carrying an area or `cross-cutting`. A second glossary hides @@ -116,6 +118,11 @@ Phase 5 reads it there and gates the agent file on it. A verdict that lives only is gone when the session ends, and the next run would offer an agent file over docs nobody re-checked. +**On a no-go, record it in `assumptions-register.md` as well**, against the items behind it. The +state file is the one the disposition recommends git-ignoring, so a verdict kept only there is +invisible to everyone but the machine that ran the skill, while the docs it failed are committed. +The register is the committed audit trail and already holds those items. + --- ## What counts as material, and what to do about it diff --git a/skills/codebase-discovery/references/output-conventions.md b/skills/codebase-discovery/references/output-conventions.md index 4ec6b7e..c10fad9 100644 --- a/skills/codebase-discovery/references/output-conventions.md +++ b/skills/codebase-discovery/references/output-conventions.md @@ -22,14 +22,14 @@ there is **no `docs/README.md`**. The detail docs live under `docs/`: ``` README.md # project-root: onboarding index / entry point — the only file the agent file links docs/ -├── business/ # cross-cutting only +├── business/ # cross-cutting, or a single-area system's │ ├── business-requirements.md │ ├── user-personas.md -│ └── workflow-.md # cross-area flows only +│ └── workflow-.md # cross-area flows, or the only area's ├── domain/ # system-wide domain │ ├── domain-glossary.md # single file, always │ ├── domain-model.md # aggregates + cross-area relationships -│ └── rules-.md # system-wide rules only +│ └── rules-.md # system-wide rules, or the only area's ├── tech/ │ ├── current-architecture.md # the system map; names the areas │ └── integrations.md diff --git a/skills/codebase-discovery/references/provenance-and-status.md b/skills/codebase-discovery/references/provenance-and-status.md index fe952fe..12ca129 100644 --- a/skills/codebase-discovery/references/provenance-and-status.md +++ b/skills/codebase-discovery/references/provenance-and-status.md @@ -78,9 +78,12 @@ terms as the flags: | `excluded` | the user excluded these paths, so nothing was read | no; named in the architecture doc | | `pending` | not yet reached | no | -**Every area reaches the reader carrying its state.** Anything but `full` is a declared gap, and it -travels: the ledger, then the entry point's area list, then the completion report. Phase 4 checks -the entry point against the ledger. +**Coverage reaches the reader.** Anything but `full` is a declared gap, and it travels: the ledger, +then the entry point, then the completion report. Phase 4 checks the entry point against the ledger. + +**The entry point states it on a line of its own, always**, and lists it per area where the system +has areas. Both, not either. A single-area system has no area list, so a coverage rule that routed +only through that list would say nothing in the case where the run is often shallowest. `pending` already travels, and it's the honest gap. `map only` and `excluded` are the ones that mislead, because the area is named in `current-architecture.md` and looks covered when nothing sits diff --git a/skills/codebase-discovery/templates/project-readme.md b/skills/codebase-discovery/templates/project-readme.md index 92fcf7c..2b89ab3 100644 --- a/skills/codebase-discovery/templates/project-readme.md +++ b/skills/codebase-discovery/templates/project-readme.md @@ -13,6 +13,12 @@ a new team member or AI harness reads. Keep it tight. --> ## Documentation + + +**Coverage:** + Onboarding docs live under [`docs/`](./docs/): From 291938c8c747066fcd2b21b4f0a4170c0d5702ab Mon Sep 17 00:00:00 2001 From: Bryan Signey Date: Fri, 28 Aug 2026 15:44:43 +1000 Subject: [PATCH 15/15] fix nav contradiction --- skills/codebase-discovery/SKILL.md | 1 + .../playbooks/00-pre-check.md | 34 +++++++++++++------ .../references/write-contract.md | 14 +++++--- .../templates/current-architecture.md | 9 +++-- 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/skills/codebase-discovery/SKILL.md b/skills/codebase-discovery/SKILL.md index 6a3afff..092c4e7 100644 --- a/skills/codebase-discovery/SKILL.md +++ b/skills/codebase-discovery/SKILL.md @@ -276,6 +276,7 @@ according to what the working state records: | Recorded state | Re-enter at | |---|---| | Nothing (first run) | Phase 1 | +| No state, but a committed register or traceability index is there | Phase 1 — the last run's coverage is unknown, so recon starts over; its open items still stand | | Recon incomplete — areas still pending in the ledger, **no drift** | Phase 1, continuing with those areas | | Recon incomplete, **drift in areas already covered** | Phase 1 — re-recon the drifted areas, then continue with the pending ones | | Recon done, **code-only** (no interview to stop), docs not written | Phase 3 | diff --git a/skills/codebase-discovery/playbooks/00-pre-check.md b/skills/codebase-discovery/playbooks/00-pre-check.md index 1de12fd..6fee27d 100644 --- a/skills/codebase-discovery/playbooks/00-pre-check.md +++ b/skills/codebase-discovery/playbooks/00-pre-check.md @@ -31,14 +31,19 @@ directory. Every path in this phase is relative to it. root may not be `docs/`, and the root it chose is recorded *inside* the state file, so looking only in `docs/_discovery/` finds nothing and reports a first run that isn't one. That silently throws away the resume and the staleness check, and nothing in the output shows it happened. Glob for -`_discovery/discovery-state.md` at every level under the project root, honouring `.gitignore` and the -default exclusions. +`_discovery/discovery-state.md` at every level under the project root, and **include git-ignored +paths**: the disposition recommends ignoring exactly this file, so a search that asks git what to +skip can never find it on a repo that took the advice. Where the glob is noisy, skip vendored and +generated trees by name instead. - **One hit** — read it. It carries that run's output root, mode and resolved options, and how far it got. Report what it reached (areas reconned, how far the interview got) before acting on it. - **More than one** — two runs have written here. Show the paths with their `Last updated` dates and ask which to continue. Don't pick, and don't merge them. -- **None** — a first run. Say so. +- **None** — don't conclude "first run" yet. Check whether `_discovery/assumptions-register.md` or + `traceability-index.md` is there: those are committed, so they survive where the state files + don't. Either one means a previous run happened and its working memory didn't travel. Say which + case you're in. --- @@ -79,7 +84,9 @@ are human-authored until proven otherwise. site, or is already occupied, propose an alternative (`docs/discovery/` is the usual choice) and let the user decide. Report what you found even when `--output` was given, since a published site is worth knowing about either way. If the docs do belong in the published site, ask explicitly whether -they should be registered in its nav/sidebar or deliberately left out of it. +they want them in its nav or sidebar. Say that registering them is a manual step this skill doesn't +take, since that config sits outside the output root, and record the answer either way so the +decision is on record for whoever makes the edit. Carry all three outcomes (root, tooling + nav decision, and the pre-existing files) into §3, which records them in `discovery-state.md` as it initialises it. They bind every later phase via the @@ -132,12 +139,19 @@ Then continue from what §1 found: re-recon, and don't silently trust stale docs. Record their decision in the manifest's freshness-check log. -If §1 found none, create `_discovery/` under the agreed root and initialise all four files from -their templates: `templates/discovery-state.md`, `templates/recon-manifest.md`, -`templates/assumptions-register.md` and `templates/traceability-index.md`. Fill the state's **Run** -block from §2: the agreed root, the docs-site tooling and nav decision, and the pre-existing files at -the target paths. Phase 1 writes to the last two files in every run, and their column sets carry -weight: the register's *who can confirm* column is what lets the interview group questions by owner. +If §1 found no state, create `_discovery/` under the agreed root and initialise **only the files that +aren't already there**, from `templates/discovery-state.md`, `templates/recon-manifest.md`, +`templates/assumptions-register.md` and `templates/traceability-index.md`. The two committed files +are protected by rule 6 of the [write contract](../references/write-contract.md). + +Where those two survived but the state files didn't, keep them and create the two state files fresh, +then say so: this run can read the open items but not what the last one covered, so recon starts over +and the freshness check has nothing to compare against. + +Fill the state's **Run** block from §2: the agreed root, the docs-site tooling and nav decision, and +the pre-existing files at the target paths. Phase 1 writes to the last two files in every run, and +their column sets carry weight: the register's *who can confirm* column is what lets the interview +group questions by owner. --- diff --git a/skills/codebase-discovery/references/write-contract.md b/skills/codebase-discovery/references/write-contract.md index faed14d..d57a826 100644 --- a/skills/codebase-discovery/references/write-contract.md +++ b/skills/codebase-discovery/references/write-contract.md @@ -26,10 +26,16 @@ later phase is bound by it. it, show the user what would change, and get sign-off first. A generated doc must not silently replace a human-authored one, however stale that one looks. 6. **A previous run's own output may be refreshed in place**, recognisable by this skill's header - block. -7. **Respect the published-site decision.** Where the root belongs to a docs generator, Phase 0 - recorded whether these pages go in its nav/sidebar. Never add pages to a public site's - navigation without that decision. + block. Refreshed, never re-initialised: `assumptions-register.md` and `traceability-index.md` are + the committed audit trail for docs still in the repo, so they are updated and never replaced with + an empty template. Their presence is also evidence that a previous run happened, whatever the + git-ignored state files do or don't show. The one way past this is `--fresh`, which deletes them + outright and only on the user's confirmation, having said first what git can and cannot give back. +7. **Respect the published-site decision, and never edit the nav yourself.** Where the root belongs + to a docs generator, Phase 0 recorded whether these pages belong in its nav or sidebar. That + config usually sits outside the output root, which rule 3 puts out of reach, so record the + decision and leave the edit to the team. Publishing pages to someone's site by editing its index + is not a write this skill makes. What each file is *for*, meaning the layout, naming, header block and length, is [`output-conventions.md`](output-conventions.md). This file is only about where you may write and diff --git a/skills/codebase-discovery/templates/current-architecture.md b/skills/codebase-discovery/templates/current-architecture.md index fe1a1c0..b0d3a39 100644 --- a/skills/codebase-discovery/templates/current-architecture.md +++ b/skills/codebase-discovery/templates/current-architecture.md @@ -1,7 +1,7 @@ # Current Architecture > **Last updated:** YYYY-MM-DD -> **Scope:** As-is architecture of +> **Scope:** As-is architecture of , and which parts of it this run examined > **Mode:** full | code-only > **Status:** — see ../_discovery/assumptions-register.md @@ -28,7 +28,12 @@ graph LR This file is where the component-to-area mapping is recorded, so the Area column is a glossary term, not a namespace or folder name. Nothing else holds this mapping: the root README lists the areas but -not what's in them. Drop the column on a single-area system, which has no areas/ directory. --> +not what's in them. Drop the column on a single-area system, which has no areas/ directory. + +List every part the declared graph shows, read or not, since dropping one would misrepresent the +system. Flag the rows recon never read with [unchecked]. Without that, five services formatted +identically read as five services examined, and the one that was read is indistinguishable from the +four that weren't. --> | Component | Area | Responsibility | Key tech | |---|---|---|---|