Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 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.
**Status: v0.4.0-shaped.** Everything through `design/plan.md` phase 10 is built and green: scaffolding (`init`), artifact creation (`spec`, `plan`), and all nine 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:

Expand Down Expand Up @@ -96,11 +96,21 @@ These landed after phase 10, and all are documented in `design/orchestration.md`
**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 <artifact> 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.
**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, and `scc notes find` covers the note log, so **the rest of `docs/` is 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 five 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, then the in-code `TODO`/`HACK` comments harvested into `docs/notes.md` last — 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`.
- **`docs/notes.md` and `scc notes`, and the code stops carrying notes.** A comment says what a thing *is* and how to use it; everything else that used to be written beside code — the gotcha, the why-not, the "careful, this looks wrong and is not" — reaches exactly one reader, the one already looking at that line. Nobody asking *what do we know about this area* ever finds it, no command lists it, and it dies with the file. So `rules/notes.md` moves it into one log, and the log is queryable.

**One note is one line**, index fields first — `- n-0042 2026-02-09 #gotcha @internal/cli/launch.go — wrap writes MCP config to the agent's own file` — and the single line is the entire design. A match is a *whole note*, so `grep ' #gotcha ' docs/notes.md` and `scc notes find --tag gotcha` answer the same question without either one reasoning about where a record ends; that is what lets the file that centralizes every note never be a file anybody reads. It also closes the door the v1 plan format left open, where `## Notes` grew to half the file because nothing forbade it: here there is nowhere for prose to go, and a thought needing a second line is a wiki page, an ADR, or a task — all three of which already exist, and the rule says which is which.

**The CLI is the writer, never a gatekeeper.** `scc notes add` allocates the id and gets the format right, because a format nobody can be made to type is one that decays; `find | show | tags | paths | rm | validate` is the rest. What it adds over grep is the questions a substring cannot answer — which tags exist before somebody coins a fourth, what this project already knows about a path, what is new since a date. `--tag` is required and has no default, since a default would be one tag on everything, which is the drift the index exists to prevent.

**A number is spent, never reused.** `rm` takes the text out and leaves an HTML-comment tombstone where the note stood, so a citation to `n-0042` can dangle but can never come to mean a different note. mdscan blanks comments, so the tombstone is invisible to a rendered read, to a grep for a tag, and to every parser except the one allocating the next id.

**`@path` is the stale check** — the notes half of the codewiki citation rule, since a note about code that no longer exists is read as current, which is worse than the comment it replaced: that one at least died with the file. At *write* time it is a warning and never a block, because a note about a file this branch has not created yet is the note most worth having; `notes add` otherwise writes under the same verify-and-roll-back contract as `scc patch`. The ninth validator also reports the failure this file cannot tolerate quietly: a hand-written line that missed the grammar, which no query will ever return.

- **The five seeded `docs/` anchors** (`assets.Seeds`). `init` writes `glossary.md`, `stack.md`, `notes.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.

Expand Down Expand Up @@ -139,7 +149,7 @@ cmd/scc/main.go os.Exit(cli.Run(os.Args[1:]))
|
scaffold · validate write / check
| \
assets · manifest ears · mdscan · artifact templates, hashes, grammars
assets · manifest ears · mdscan · artifact · notes templates, hashes, grammars
|
paths · workspace · render · textutil · finding
|
Expand All @@ -164,7 +174,8 @@ Three packages sit off to the side of that tree — `rtk`, `headroom`, `codegrap
| `internal/mdscan` | The only Markdown parser: fence- and HTML-comment-aware headings, checkboxes, links, wikilinks, slugs, plus a small frontmatter reader. `Body` is the comment/fence-stripped text every validator applies its grammar to. |
| `internal/artifact` | The navigable model of one artifact, layered on `mdscan`: sections (two ends — the subtree, and the body before the first child), tasks with their continuation *and their flags*, requirements, spec-reference leaves, paragraph blocks. Owns **every grammar** (task, requirement, spec reference, flag), `Find` for address resolution, `Editor` for line splices resolved against the original and applied bottom-up, `Search`, the schedule (`Ready`/`BlockedTasks`/`Next`/`Cycles`, one implementation shared by `--next`, `--ready` and `--blocked`), and the seal. Knows nothing about findings or exit codes. |
| `internal/ears` | EARS requirement parsing, all five patterns plus complex. |
| `internal/validate` | The eight validators, one file each, sharing `mdscan` and `finding`. The exception is `stack_manifests.go`: the seven dependency-file readers age on their own schedule, so they sit beside the rule rather than inside it. |
| `internal/notes` | `docs/notes.md`: the note grammar, the log's regions, the query, and the splice. One note is one line, so a match is a whole note — the property every other decision here protects. Knows nothing about findings or exit codes, the same seam `internal/artifact` keeps with the plan grammar. |
| `internal/validate` | The nine validators, one file each, sharing `mdscan` and `finding`. The exception is `stack_manifests.go`: the seven dependency-file readers age on their own schedule, so they sit beside the rule rather than inside it. |
| `internal/rtk` | RTK's marker pair (`rtk.Markers`, spliced by `internal/mdblock`), the foreign-block detection that names Headroom's copy, and finding or `cargo install`ing the binary. |
| `internal/headroom` | Headroom's agent-slug table, the `wrap` argument vector, the MCP opt-out discovered from `wrap <agent> --help`, and finding or installing the binary (uv, then pip — never npm, which ships the SDK and no CLI). The slugs live here rather than on `paths.Harness` because they are Headroom's vocabulary, not scc's layout. |
| `internal/codegraph` | CodeGraph's argument vectors (`init`/`sync`/`index`/`status`/`query`/`explore`), the `.codegraph/` presence test, `codegraph.Markers` for the usage block `scc launch` splices, and finding or `npm install -g`ing the binary. Composes command lines and reads nothing inside the graph — the database is CodeGraph's schema on CodeGraph's schedule. |
Expand Down
Loading
Loading