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
9 changes: 5 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 7 additions & 1 deletion 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 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:

Expand Down Expand Up @@ -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 <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.

**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.
Expand Down
73 changes: 69 additions & 4 deletions design/orchestration.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 |
Expand All @@ -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/<name>.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,
Expand Down Expand Up @@ -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
Expand Down
33 changes: 31 additions & 2 deletions internal/assets/assets.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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
Expand Down
22 changes: 22 additions & 0 deletions internal/assets/templates/commands/scc-init.md
Original file line number Diff line number Diff line change
@@ -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.
Loading
Loading