From 5af574de0b5f2ac5834c14a53e2c98359f57630e Mon Sep 17 00:00:00 2001 From: prode Date: Wed, 19 Aug 2026 20:19:50 -0300 Subject: [PATCH 1/2] feat(templates): read docs/ before the first artifact, and fill it with /scc-init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two halves of the same gap. `prior-art.md` is the read side of the knowledge base: `docs/` is consulted before a spec, a plan, or a line of code exists, because it is the constraint set rather than reference material for when somebody is stuck. It is its own rule instead of a paragraph in knowledge-base.md because the two fire at opposite moments — that one when something was learned, this one when something is about to be written — and it has to state what no index states, that `scc map` covers plans/ and specs/ and the graph covers code, so docs/ is the one corpus reached by opening a file. The `init` skill and /scc-init are what make that base worth reading in a repository that already exists. `scc init` lays four anchors down empty; the skill surveys the code and fills them, holding the order across the six knowledge authors and one bar the authors cannot state for themselves — everything on that run is reconstructed rather than remembered, so nothing goes in that cannot be pointed at, and what nobody can justify is reported by name instead of filled in with something plausible. Template set 15 -> 17. The entry file's rules preamble loses a line to keep the new trigger inside the 60-line budget. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01K5jmMZ1sZeQKgcgAnStj7f --- CLAUDE.md | 8 +- design/orchestration.md | 73 +++++++++- internal/assets/assets.go | 33 ++++- .../assets/templates/commands/scc-init.md | 22 +++ internal/assets/templates/entry.md | 6 +- internal/assets/templates/rules/prior-art.md | 53 +++++++ .../assets/templates/skills/init/SKILL.md | 132 ++++++++++++++++++ 7 files changed, 317 insertions(+), 10 deletions(-) create mode 100644 internal/assets/templates/commands/scc-init.md create mode 100644 internal/assets/templates/rules/prior-art.md create mode 100644 internal/assets/templates/skills/init/SKILL.md diff --git a/CLAUDE.md b/CLAUDE.md index d06da40..0f496f1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,7 +12,7 @@ This file covers working *on* scc. The product's own rules and methodology are n Note: this repo is not itself an scc workspace (no harness directory, `specs/`, `plans/`, or `docs/` are committed) — those trees only exist in workspaces the binary scaffolds, and in test temp dirs. -**Status: v0.4.0-shaped.** Everything through `design/plan.md` phase 10 is built and green: scaffolding (`init`), artifact creation (`spec`, `plan`), and all eight validators behind `scc validate`. `init` also scaffolds the seven skills named in `design/orchestration.md` §6 — the six knowledge-base authors (one per `docs/` artifact a validator checks, plus `prd`) and the `plan-run` workflow skill — each with a `scc-`-prefixed slash command derived from the same list (`assets.Skills()`, which is `KnowledgeSkills` + `WorkflowSkills`), wherever the harness has a command surface. +**Status: v0.4.0-shaped.** Everything through `design/plan.md` phase 10 is built and green: scaffolding (`init`), artifact creation (`spec`, `plan`), and all eight validators behind `scc validate`. `init` also scaffolds the eight skills named in `design/orchestration.md` §6 — the six knowledge-base authors (one per `docs/` artifact a validator checks, plus `prd`) and the two workflow skills, `plan-run` and `init` — each with a `scc-`-prefixed slash command derived from the same list (`assets.Skills()`, which is `KnowledgeSkills` + `WorkflowSkills`), wherever the harness has a command surface. These landed after phase 10, and all are documented in `design/orchestration.md` §6 and §12: @@ -94,6 +94,12 @@ These landed after phase 10, and all are documented in `design/orchestration.md` What it must never compress is the line that keeps it honest: artifacts under `specs/`, `plans/`, `docs/`, anything a validator parses or a shell runs, quoted output, commit and PR bodies, and questions asked of the user. A denser EARS line is a finding, not a saving. **The language is the third kickoff answer.** `autonomy.md` asks it with the other two and it lands in the artifact's frontmatter as `lang: en|wenyan`, graded by `checkKickoffAs` on exactly the terms `autonomy` and `ci` are — checked when present, absent meaning the run predates the question. There is no `--lang` flag on `spec new` or `plan new`: it is the one answer that can arrive after the file exists, so `scc patch fm lang=wenyan` is the whole path to it, and a value neither the rule nor the validator knows is rolled back like any other bad edit. `TestTheRuleOffersEveryKickoffAnswerThisAccepts` is what stops the rule and the validator from naming different values. +- **`prior-art.md`, the read side of the knowledge base.** `docs/` is consulted *before the first artifact of a piece of work exists* — before `scc spec new`, before `scc plan new`, before code — because it is the constraint set and not reference material for when somebody is stuck: an ADR binds the design about to be written, `stack.md` says what may be built on, `glossary.md` says what to call it, and a spec already covering the area makes the work a delta rather than a second statement of the same feature. It prevents a failure that is invisible on review — a spec that re-decides a settled decision reads as new work, not as a contradiction — and under autonomy nobody sees the phase where noticing was still possible. + + **It is a rule of its own rather than a paragraph in `knowledge-base.md`**, because the two halves fire at opposite moments: that one is triggered by having learned something, this one by being about to write, and a read-side instruction filed under the write-side rule is read after the spec exists. It also has to state the thing no index states — `scc map` covers `plans/` and `specs/`, the symbol graph covers code, so **`docs/` is the one corpus reached by opening a file**. That stays cheap only because the seeded anchors are built for it: `glossary.md` and `stack.md` are lists, `wiki/index.md` and the ADR filenames are tables of contents, so a page is opened when its title bears on the work and never to survey the base. What it finds is stated up front and then cited into the artifact (`adr:0007-…`, a delta, a `[[wikilink]]`), which is the only trace an `auto` run leaves that the pass happened at all. +- **The `init` skill and `/scc-init`, which fill what `scc init` can only lay down empty.** The CLI command scaffolds four anchors holding the format their validators check; what turns them into this project's knowledge base is a survey of the code, and a survey is judgment rather than scaffolding. So the skill holds the three things no rule can: the survey that precedes every artifact, the order across the six knowledge authors — `stack.md` first because `stack.undocumented-dependency` gives it a finish line, `docs/adr/` last because it is where invention is most likely, `scc validate` between stages — and one bar that applies only here. + + **That bar is the design.** Everything written on this run is *reconstructed rather than remembered*, so nothing goes in that cannot be pointed at (a manifest, a CI file, a commit, a migration), and what nobody can justify is reported by name instead of filled in with something plausible: a gap is visible, an invention is believed, and the base's whole value is being trustworthy without checking. Each reconstructed ADR says so in its own `## Context`. It is a second `WorkflowSkill` for the same reason `plan-run` was the first — the knowledge skills each fire when *their* concern goes live, and none of them fires when the base is empty. What it deliberately never writes is `specs/`: restating a working system as requirements is the failure mode of a documentation pass, and `specs.md` already says a spec meets existing code as a delta, so the first spec is written by the next change. - **The four seeded `docs/` anchors** (`assets.Seeds`). `init` writes `glossary.md`, `stack.md`, `wiki/index.md`, and `wiki/changelog.md` — the knowledge base's only fixed-name documents, each holding the format its validator checks. A seed is written once and tracked nowhere: not in the manifest, not by `scc update`. `scc` is a redesign of `csdd` (`github.com/protonspy/csdd`), narrowed to spec-driven development and deliberately leaner. When reaching for something from there, port the *decision*, not the file. Already decided against: a TUI, an embedded web dashboard, an MCP server, a devcontainer. diff --git a/design/orchestration.md b/design/orchestration.md index 31c4c25..2ede386 100644 --- a/design/orchestration.md +++ b/design/orchestration.md @@ -118,6 +118,42 @@ What the two-vehicle split buys is that the *weight* of the record matches the w the work. A one-line change gets one checklist item in a plan, not three ceremonial files in `specs/`. +### Before either vehicle — read the record + +Routing is not the first act. **Before the first artifact of a piece of work exists — +before `scc spec new`, before `scc plan new`, before a line of code — the orchestrator +reads what this workspace already settled.** `docs/` is not reference material for when +someone is stuck: it is the constraint set. An ADR binds the design about to be written, +`stack.md` says what may be built on, `glossary.md` says what to call it, and a spec +already covering the area turns new work into a delta (§10) rather than a second +statement of the same feature. + +The failure it prevents is silent, which is why it is a rule rather than a habit. A spec +written without the pass re-decides a decision somebody already made, names a concept a +second way, or adds a dependency for something the stack already carries — and none of +it reads as wrong on review, because it reads as *new work* rather than as a +contradiction. Under autonomy nobody sees the phase where the contradiction was +available to notice. + +**It is its own rule (`prior-art.md`), not a paragraph in `knowledge-base.md`.** The two +halves fire at opposite moments: that one is triggered by having learned something, this +one by being about to write. A read-side instruction filed under the write-side rule is +read after the spec exists, which is after it was any use. + +**The pass has to say what no index says.** `scc map` covers `plans/` and `specs/`, and +the symbol graph covers code — so `docs/` is the one corpus reached by opening a file. +That is affordable only because the seeded anchors (§6) are built for it: `glossary.md` +and `stack.md` are lists, `wiki/index.md` and the ADR filenames are tables of contents. +The rule says to open a page when its title bears on the work, never to survey the base. + +What the pass finds is then **stated and cited**: one or two lines up front naming the +ADRs that bind and the spec that already covers the area — the material of the first +checkpoint under `gated`, and the only trace the pass happened at all under `auto` — +then carried into the artifact as an `adr:` citation, a delta, or a `[[wikilink]]`, +where it outlives the session. "Nothing here governs this" is a result and is said out +loud; an empty `docs/` is a young workspace, not a finding, so nothing is invented to +fill it. + ## 2 · Autonomy — the gate is a question, not a flag The spec phases are **autonomous by default**: the orchestrator writes @@ -431,9 +467,9 @@ rewriting a file the user owns. `scc update` keeps both trees current regardless, because it works from each harness's own manifest rather than from the entry file. -### Which skills ship — the authors of `docs/`, plus one runner +### Which skills ship — the authors of `docs/`, plus the runners -Seven, in two lists, and each list has its own rule. The first is mechanical: **a +Eight, in two lists, and each list has its own rule. The first is mechanical: **a skill ships for each `docs/` artifact a validator checks, and for nothing else.** | Skill | Authors | Checked by | @@ -455,12 +491,13 @@ delivery are rules under `.claude/rules/` (§3, §7, §9) — read when the conc live. csdd shipped `tdd-cycle`, `unit-cycle`, and `verify-change` as skills; here that would be a second copy of a rule, and the copy is the one that goes stale. -**The one exception, and the line it draws — `plan-run`.** The second list holds -skills that *run* the methodology rather than describe it, and it holds exactly one. +**The exceptions, and the line they draw — `plan-run` and `init`.** The second list +holds skills that *run* the methodology rather than describe it, and it holds two. | Skill | Runs | Owned by no rule | |---|---|---| | `plan-run` | a whole `plans/.md`, group by group | the loop **across** units of work | +| `init` | a repository's whole knowledge base, from the code already there | the order **across** the six authors, and the bar on reconstructed knowledge | The rule above is what makes it admissible rather than a leak. §9's delivery sequence ends at one merged pull request, because that is where one unit of work ends — a spec, @@ -516,6 +553,34 @@ respects a decision it disagrees with; overriding is how it stops being trusted. `no-wait` therefore stays available inside a loop, and the skill says out loud what it buys and what it costs before accepting it. +**`init` clears the same bar, one layer up.** Every knowledge skill is triggered by a +concern going live — something was learned, a decision was made, a dependency was +added. None of them fires when the base is *empty*, and no rule can order them, because +a rule is read at the moment its own concern arrives and this is the moment before any +of them has one. Bootstrapping an existing repository needs three things no rule holds: +a survey that precedes every artifact, an order across the six (checkable first, +interpretive last, `scc validate` between stages), and a bar that only applies here. + +That bar is the reason it is a skill rather than a `--bootstrap` flag on the CLI. +**Everything written on this run is reconstructed rather than remembered**, so nothing +goes in that cannot be pointed at — a manifest, a CI file, a commit, a migration — and +what nobody can justify is *reported by name* instead of filled in with something +plausible. A gap is visible and an invention is believed, and the knowledge base's whole +value is that it can be trusted without checking. The ADRs are last and strictest for +exactly that reason, and each says in its own `## Context` that it was written after the +fact and from what. + +It shares its name with `scc init` deliberately: the CLI command lays the four anchors +down empty, which is all a binary can do, and the skill is what fills them. So a person +who has just scaffolded a repository and asks "now what" has one word to type, and the +skill's first act is to check that the workspace exists at all — the harness, when it +does not, is the user's call and not the agent's. + +**What it deliberately does not write is `specs/`.** Restating a working system as +requirements is the failure mode of every documentation pass; §11 already says a spec +meets existing code as a **delta**, so the first spec in a bootstrapped repository is +written by the next change rather than by this run. + **One slash command per skill, namespaced `scc-`.** A skill is model-invoked through its description; a command is the human saying *now*. Both are cheap, they are derived from one list so they cannot drift, and the prefix is not decoration — slash commands diff --git a/internal/assets/assets.go b/internal/assets/assets.go index 1cabd84..7f6d562 100644 --- a/internal/assets/assets.go +++ b/internal/assets/assets.go @@ -111,7 +111,27 @@ import ( // three questions instead of four, `worktree:` stops being a frontmatter answer, and // what survives is the one line the worktree was really carrying — leave the checkout // back on `main` and clean, because that is where the next unit of work starts. -const Version = "15" +// 16: prior-art.md — the knowledge base is read before the first artifact is written, +// not consulted once someone is stuck. `docs/` is the constraint set: an ADR binds the +// design, `stack.md` says what may be built on, `glossary.md` says what to call it. It +// is a rule of its own rather than a paragraph in knowledge-base.md because the two +// halves fire at opposite moments — that one is triggered by having learned something, +// this one by being about to write — and a read-side instruction filed under the +// write-side rule is read after the spec exists, which is after it was any use. It +// also has to state the thing no index states: `scc map` covers `plans/` and `specs/` +// and the symbol graph covers code, so `docs/` is the one corpus reached by opening a +// file, and the anchors are what keep that cheap. +// 17: the `init` skill and `/scc-init` — the knowledge base is bootstrapped from a +// repository that already exists. It is the counterpart to the CLI command of the same +// name, which lays the four anchors down empty and can do nothing else: what fills them +// is a survey of the code, and a survey is judgment. The skill holds the order across +// the six knowledge authors (checkable first, interpretive last, `scc validate` between +// stages) and one bar the authors cannot state for themselves — everything written on +// this run is reconstructed rather than remembered, so nothing goes in that cannot be +// pointed at, and what nobody can justify is reported by name instead of filled in. The +// ADRs are last and strictest for that reason, and each says in its `## Context` that it +// was reconstructed after the fact. +const Version = "17" // The embedded tree. "all:" so nothing is silently dropped for having a name the // default embed pattern skips. @@ -178,6 +198,7 @@ func Workspace(h paths.Harness) []File { "caveman.md", "routing.md", "autonomy.md", + "prior-art.md", "methodology.md", "tasks.md", "verification.md", @@ -326,7 +347,15 @@ var KnowledgeSkills = []string{"adr", "codewiki", "glossary", "prd", "stack", "w // it from the merge the last group produced, and recovering the position from `main` // when a session dies mid-plan. That is a procedure, and a procedure a person invokes // needs an entry point they can type. -var WorkflowSkills = []string{"plan-run"} +// +// init clears it for the same reason, one layer up. The knowledge skills each own one +// artifact and are triggered by a concern going live — something was learned, a +// decision was made, a dependency was added. None of them fires when the whole base is +// empty, and no rule can say which artifact comes first, because a rule is read at the +// moment its own concern arrives. Bootstrapping an existing repository is the one job +// that needs the order *across* the six, a survey before any of them, and a bar on +// what may be written when the answer is being reconstructed rather than remembered. +var WorkflowSkills = []string{"init", "plan-run"} // Skills is every skill scc ships, knowledge first. Both the skill directory and its // slash command are derived from this one list, so the two cannot drift apart, and a diff --git a/internal/assets/templates/commands/scc-init.md b/internal/assets/templates/commands/scc-init.md new file mode 100644 index 0000000..d96e8b0 --- /dev/null +++ b/internal/assets/templates/commands/scc-init.md @@ -0,0 +1,22 @@ +--- +description: Bootstrap the knowledge base from the code that is already here — survey the repository, then write stack, glossary, the project rule's real commands, the wiki, and the ADRs for decisions already taken +argument-hint: [anchors | full, and the subtree to cover if not the whole repository] +--- + +Use the `init` skill. + +Scope: $ARGUMENTS + +Survey before you write, and report the map back — the areas, the pages you would +write, the decisions you would record — before a single file is created. Ask the +graph and the history rather than reading the tree file by file. + +**Write only what you can point at.** Everything here is reconstructed from what +survived, not remembered by anyone, so a dependency nobody can justify, an area whose +reasoning is unrecorded, and a decision with no evidence behind it are all *reported* +rather than filled in with something plausible. A gap is visible; an invention is +believed. + +If nothing was named above, take it as `anchors` over the whole repository — stack, +glossary, the project rule's real build and test commands, and a wiki someone can +enter — and say that is what you took. diff --git a/internal/assets/templates/entry.md b/internal/assets/templates/entry.md index 33cd792..d00a0e9 100644 --- a/internal/assets/templates/entry.md +++ b/internal/assets/templates/entry.md @@ -5,9 +5,8 @@ Spec-driven development, scaffolded and checked by `scc`. The methodology lives ## Rules — `{{.Rules}}/.md` {{if .RulesPreloaded -}} -{{.Label}} loads `{{.Rules}}/` at session start: they are in front of you, nothing to open. -The triggers below say *when* each governs — the failure is not a rule you never read, -it is one you had all along and applied at the wrong moment, or not at all. +{{.Label}} loads `{{.Rules}}/` at session start — nothing to open. The triggers say *when* +each governs: the failure is not a rule you never read, it is one you had and misapplied. {{- else -}} Nothing loads these for you. Open the file whose moment has arrived, and open it again in a new session: a rule you read yesterday is not a rule you have read. @@ -16,6 +15,7 @@ in a new session: a rule you read yesterday is not a rule you have read. `caveman.md` is always on: the register you answer in. The rest, by where you are: - `autonomy.md` — at kickoff, before writing anything +- `prior-art.md` — then read what `docs/` already decides, before the first artifact - `routing.md` — work arrives and needs a vehicle: a spec, or a plan - `methodology.md` — starting a task: which cycle, what to run first - `verification.md` — code is written and you think it is done diff --git a/internal/assets/templates/rules/prior-art.md b/internal/assets/templates/rules/prior-art.md new file mode 100644 index 0000000..d9cde42 --- /dev/null +++ b/internal/assets/templates/rules/prior-art.md @@ -0,0 +1,53 @@ +# Prior art — read the record before you write one + +Before the first artifact of a piece of work exists — before `scc spec new`, before +`scc plan new`, before a line of code — find out what this workspace already settled. +`docs/` is not reference material for when you get stuck: it is the constraint set. An +ADR binds the design you are about to write, `stack.md` says what you may build on, +`glossary.md` says what to call it. + +The failure it prevents is silent. A spec written without this pass re-decides a +decision somebody already made, names a concept a second way, or adds a dependency for +something the stack already carries — and none of it reads as wrong on review, because +it reads as new work rather than as a contradiction. + +## The passes, before writing + +| Ask | Where | What binds you | +|---|---|---| +| Has this been decided? | `docs/adr/` — the filenames are the index | a record that constrains this design; `rejected` and `superseded` count | +| Has this been built? | `scc map` · `scc map trace specs//` | a spec covering the area — then this is a delta, not a new spec | +| What is it called? | `docs/glossary.md` | the canonical term, and the synonyms that are findings | +| What may I build on? | `docs/stack.md` | what is adopted; anything absent is an open decision | +| How does it work today? | `docs/wiki/index.md` · `docs/codewiki/` | the concept pages, and the code already narrated | + +**`docs/` is in no index.** `scc map` covers `plans/` and `specs/`; the symbol graph +covers code ([code-search.md](code-search.md)). So this pass is deliberate reading, and +it is cheap only because the anchors are built for it: `glossary.md` and `stack.md` are +lists, `wiki/index.md` and the ADR filenames are tables of contents. Open a page when +its title bears on this work — never to survey the base. + +## Say what you found, then cite it + +Report it in a line or two before you write anything: the ADRs that bind, the spec that +already covers the area, the terms you will use. Under `gated` that is the material of +the first checkpoint; under `auto` it is the only trace that the pass happened at all. +"Nothing here governs this" is a result, and worth saying. + +Then carry it into the artifact, where it outlives the session: + +- an ADR that governs is cited from `design.md` as `adr:0007-use-sqlite-for-the-cache` +- a spec covering the area is amended as a delta, never re-specified ([specs.md](specs.md)) +- a wiki page explaining the ground is `[[linked]]`, not summarized a second time +- the glossary's term is the one the requirements use — a synonym is a finding + +## What the pass turns up is usually work + +A decision you had to reconstruct from the code was never written down; a concept you +found under three names is a glossary entry; a page describing what the system no +longer does is stale. Writing that is [knowledge-base.md](knowledge-base.md), and it +belongs in this delivery rather than a later one. + +Do not invent a record to fill a gap. An empty `docs/` is a young workspace, not a +finding: write the ADR when the decision you are making is hard to reverse, and the +page when you learned something the next session would otherwise learn again. diff --git a/internal/assets/templates/skills/init/SKILL.md b/internal/assets/templates/skills/init/SKILL.md new file mode 100644 index 0000000..2d56cba --- /dev/null +++ b/internal/assets/templates/skills/init/SKILL.md @@ -0,0 +1,132 @@ +--- +name: init +description: Bootstrap this project's knowledge base from the code that already exists — survey the repository, then write docs/stack.md, docs/glossary.md, the wiki, the codewiki, the ADRs for decisions already taken, and the project rule's real build, test, and lint commands. Use it on a workspace whose docs/ is still the four seeded anchors, when someone asks to document an existing codebase, when a repository has just been scaffolded and nothing under docs/ is filled in, or when someone runs /scc-init. Not for one page or one new decision — the wiki, glossary, stack, codewiki, and adr skills each own their own artifact, and this run is what calls them. +--- + +You fill an empty knowledge base from a repository that already exists. + +The formats are not yours. Each artifact has an owner — the `stack`, `glossary`, +`wiki`, `codewiki`, and `adr` skills — and the rule they all enforce is +`{{.Rules}}/knowledge-base.md`. **Call them; do not restate them.** What this skill +owns is what no rule can: the *order* across artifacts, the survey that precedes all +of them, and the bar for what may be written at all. + +## The bar — nothing without evidence + +Everything here is **reconstructed, not remembered.** Nobody is telling you why this +system is the way it is; you are inferring it from what survived. So write only what +you can point at — a file, a dependency manifest, a CI workflow, a commit, a comment, +a migration. + +Where the code cannot tell you why, **say the reasoning is unrecorded** and move on. A +plausible reason invented here is worse than a gap, because a gap is visible and an +invention is believed. The knowledge base's whole value is that it can be trusted +without checking, and this run is where that trust is either earned or spent. + +## Before anything — is there a workspace + +`scc validate` fails outside one. If `{{.Manifest}}` is absent the repository was +never scaffolded, and which harness it is scaffolded for is **the user's call, not +yours** — `scc init --claude`, `--codex`, or `--opencode`. Ask, then carry on. + +## Ask twice, then start + +One exchange, before the survey, because both answers change how much you read: + +| Ask | Answers | +|---|---| +| How deep — the anchors, or everything? | **anchors** (`stack.md`, `glossary.md`, the project rule, and a wiki a newcomer can enter) · **full** (also `codewiki/` and the ADRs for decisions already taken) | +| The whole repository, or one subtree? | the root · one package, service, or app inside a monorepo | + +Anchors is the right default for a first run. State what you took, so a wrong reading +costs a sentence rather than a session. + +## The survey — read the map, not the territory + +Cheapest sources first, and stop when another pass stops changing the map: + +1. **What was written for a newcomer** — README, CI workflows, `Makefile` or the + scripts block, the dependency manifests, the top-level directories. +2. **The structure** — `scc graph explore ""`, per + `{{.Rules}}/code-search.md`. A survey is exactly the shape of question the graph + answers, and exactly the one that ruins a context window when answered by reading + files. +3. **The history, for what was argued about** — `git log` over a directory that moved, + a revert, a migration, a dependency swapped out. This is the cheapest evidence that + a decision was expensive, which is what an ADR needs and what code alone never says. + +**Report the map back before writing anything** — the areas, the concepts you would +give pages, the decisions you would record. That is the last moment a correction is +cheap. + +## Then write, in this order + +Cheapest and most checkable first, most interpretive last, with `scc validate` between +stages so no stage inherits the previous one's findings. + +1. **`docs/stack.md`** — the `stack` skill. It has a finish line nothing else here + has: `stack.undocumented-dependency` reaching zero, because the validator reads the + direct dependencies straight out of the manifest. Where nobody can justify one, say + what it is *used for* — the import sites are a fact you can point at — and mark the + decision unrecorded. Do not invent a rationale, and do not delete a dependency to + silence a finding. +2. **`{{.Rules}}/project.md`** — the build, test, lint, and format commands. **Run each + one before you write it.** Take them from CI first, since a workflow file is the one + place somebody maintains them, then verify locally. A guessed command that exits `0` + looks exactly like a passing suite, which is the whole reason that rule exists. +3. **`docs/glossary.md`** — the `glossary` skill, conservatively. Every synonym listed + after `Avoid:` becomes a finding wherever it appears under `docs/`, so list one only + where you actually saw two names used for one thing. Take terms from the domain this + project is about, never from its framework. +4. **`docs/wiki/`** — the `wiki` skill. One page per concept a newcomer has to hold to + read the code, never one per directory: a wiki that mirrors the file tree *is* the + file tree, and it goes stale faster. Link every page from `index.md` and log the run + in `changelog.md`. +5. **`docs/codewiki/`** — the `codewiki` skill, only where reading the code does not + tell you why it is shaped that way. Every section cites the lines it explains, and a + citation is a promise to keep the page current, so cite the part that is stable. +6. **`docs/adr/`** — the `adr` skill, last, and the one to be strictest about. A + decision qualifies only when both hold: undoing it would be expensive, **and** there + is evidence in the repository that it was taken. Number from `0001` in the order the + history says they happened. + + **Say that the record is reconstructed.** An ADR is what was believed at the time, + and these were not written at the time — so open `## Context` with one line naming + what it was reconstructed from, and when. `status: accepted` where the code shows + the decision in force; never `proposed` for something already built. + +## What this does not do + +- **It does not write specs.** Documenting a system that already works as `specs/` + means restating the whole product as requirements. `{{.Rules}}/specs.md` is explicit + that a spec meets existing code as a **delta**, so the first spec here is written by + the next change and not by this run. +- **It does not rewrite `{{.Entry}}`.** That file is the user's. +- **It does not touch code.** A defect you notice is worth reporting at the end; it is + not this run's to fix, and a documentation branch that also changes behavior is one + nobody can review. + +## Finishing + +`scc validate` exits `0`, then deliver it as ordinary work — one branch, one pull +request, `{{.Rules}}/delivery.md`. + +Then report **what was left unknown**, by name: the dependency nobody could justify, +the area whose reasoning is unrecorded, the decision that looked expensive and had no +evidence behind it. That list is the most valuable thing this run produces, and it is +the part that disappears if you do not write it down. + +## Re-running + +It is additive and resumable, and it takes its position from the repository rather +than from memory. Read what `docs/` already holds, **never rewrite a page somebody +else wrote**, clear `scc validate` findings first and fill gaps second. A second run +over a documented workspace should report that there is nothing to add — not produce a +second account of the same system. + +## Degrading + +No graph, no CI file, no history worth reading — none of that stops the run. Say which +one is missing, fall back to what is there, and lower the claim rather than the +honesty: five pages somebody can check beat a whole knowledge base assembled out of +inference. From 38be325d1e8f0f39a403524c4b240814d2f314c8 Mon Sep 17 00:00:00 2001 From: prode Date: Wed, 19 Aug 2026 20:21:47 -0300 Subject: [PATCH 2/2] ci: pin Go 1.25.13 for the GO-2026-6088 encoding/xml fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit govulncheck reports the recursion-depth vulnerability in encoding/xml as reachable: stack_manifests.go's pom reader calls xml.Unmarshal. Fixed in 1.25.13 on this branch, so the pin moves up one patch. Nothing else changes — the note in ci.yml still holds, and the float '1.25' still lags on hosted runners. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01K5jmMZ1sZeQKgcgAnStj7f --- .github/workflows/ci.yml | 9 +++++---- .github/workflows/release.yml | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1419465..e4962ae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,10 +35,11 @@ jobs: # Build/test with a current, patched toolchain. Keep this pin AHEAD of # go.mod's directive and do NOT switch to go-version-file: go.mod — # install-compat with older toolchains rides on GOTOOLCHAIN=auto. - # Pinned to .12 for the GO-2026-5856 crypto/tls fix; the float '1.25' - # still resolves to .11 on hosted runners (manifest lag). Float back + # Pinned to .13 for the GO-2026-6088 encoding/xml fix, which the pom + # reader reaches through xml.Unmarshal (.12 was the GO-2026-5856 + # crypto/tls fix). The float '1.25' lags on hosted runners; float back # once runners catch up. - go-version: '1.25.12' + go-version: '1.25.13' cache: true - name: go vet @@ -73,7 +74,7 @@ jobs: - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0 with: - go-version: '1.25.12' # GO-2026-5856 crypto/tls fix; see the test job's note + go-version: '1.25.13' # GO-2026-6088 encoding/xml fix; see the test job's note cache: true - name: gofmt diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c2b2e2b..fcfd7d1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -96,7 +96,7 @@ jobs: - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0 with: - go-version: '1.25.12' # see ci.yml's note before changing + go-version: '1.25.13' # see ci.yml's note before changing cache: true - name: Build & package