task-pipeline-skill 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +137 -0
- package/README.md +68 -8
- package/cursor/rules/task-pipeline.mdc +82 -0
- package/package.json +5 -2
- package/plugins/task-pipeline/.claude-plugin/plugin.json +4 -2
- package/plugins/task-pipeline/skills/task-pipeline/SKILL.md +41 -10
- package/plugins/task-pipeline/skills/task-pipeline/pipeline.example.json +6 -3
- package/plugins/task-pipeline/skills/task-pipeline/references/artifacts.md +10 -2
- package/plugins/task-pipeline/skills/task-pipeline/references/audit.md +5 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/companion-skills.md +15 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/conventions.md +19 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/documentation.md +285 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/gates.md +236 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/hooks.md +164 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/knowledge-sources.md +26 -5
- package/plugins/task-pipeline/skills/task-pipeline/references/learned.md +17 -2
- package/plugins/task-pipeline/skills/task-pipeline/references/retrospective.md +55 -14
- package/plugins/task-pipeline/skills/task-pipeline/references/stages.md +71 -9
- package/plugins/task-pipeline/skills/task-pipeline/templates/README.md +14 -1
- package/plugins/task-pipeline/skills/task-pipeline/templates/adr.md +28 -3
- package/plugins/task-pipeline/skills/task-pipeline/templates/brief.md +26 -8
- package/plugins/task-pipeline/skills/task-pipeline/templates/decisions.md +50 -0
- package/plugins/task-pipeline/skills/task-pipeline/templates/docgate.sh +391 -0
- package/plugins/task-pipeline/skills/task-pipeline/templates/docmap.md +86 -0
- package/plugins/task-pipeline/skills/task-pipeline/templates/hooks.example.json +21 -0
- package/plugins/task-pipeline/skills/task-pipeline/templates/open-questions.md +21 -0
- package/plugins/task-pipeline/skills/task-pipeline/templates/retro-archive.md +41 -0
- package/plugins/task-pipeline/skills/task-pipeline/templates/retro.md +27 -13
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# Hooks — agent-time enforcement, and the limit first
|
|
2
|
+
|
|
3
|
+
**One job: stop a bad edit before it lands, and never claim protection you do not
|
|
4
|
+
have.** A hook is rung 5 of [`gates.md`](gates.md)'s ladder — the only mechanism
|
|
5
|
+
that acts *while the agent is working* rather than after the commit.
|
|
6
|
+
|
|
7
|
+
## The limit, before the capability
|
|
8
|
+
|
|
9
|
+
**Hooks exist only in Claude Code.** On Cursor, Codex and the other agents a skill
|
|
10
|
+
can be installed and read, but there is no `PreToolUse`, so nothing blocks anything.
|
|
11
|
+
On those agents the same rules run as a self-check written into the skill body, and
|
|
12
|
+
the run is recorded **`ungated`**.
|
|
13
|
+
|
|
14
|
+
**Never describe a project as protected when its agents run outside Claude Code.**
|
|
15
|
+
The gap between "the rule exists" and "the rule is enforced" is invisible from
|
|
16
|
+
inside a transcript, and a false guarantee is worse than a stated absence: everyone
|
|
17
|
+
downstream stops checking.
|
|
18
|
+
|
|
19
|
+
## The events
|
|
20
|
+
|
|
21
|
+
| Event | Fires | Used for |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| `SessionStart` | session opens (matcher `startup\|resume`) | register the run, print the board, name the one next action |
|
|
24
|
+
| `PreToolUse` | before a tool call | **block** — the only event that can refuse |
|
|
25
|
+
| `PostToolUse` | after every tool call | bookkeeping: renew a lease, stamp a marker |
|
|
26
|
+
| `SessionEnd` | session closes | release leases, flush the journal |
|
|
27
|
+
|
|
28
|
+
## The `PreToolUse` contract
|
|
29
|
+
|
|
30
|
+
A hook blocks a call in **either** of two ways:
|
|
31
|
+
|
|
32
|
+
- **exit 2**, with the reason on **stderr** (stdout is ignored); or
|
|
33
|
+
- **exit 0** with this on stdout:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{"hookSpecificOutput":{"hookEventName":"PreToolUse",
|
|
37
|
+
"permissionDecision":"deny",
|
|
38
|
+
"permissionDecisionReason":"docs gate failed: 2 undefined ids in docs/ARCHITECTURE.md"}}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Any other exit code is a non-blocking error**: execution continues and stderr is
|
|
42
|
+
shown in the transcript. So **a crashing guard fails open** — it stops guarding and
|
|
43
|
+
nothing announces that it has. Write the guard to `exit 2` on its own internal
|
|
44
|
+
errors, or accept that a typo in it silently removes the protection everyone
|
|
45
|
+
believes is there.
|
|
46
|
+
|
|
47
|
+
That asymmetry is the whole reason this file leads with the limit: a hook is the
|
|
48
|
+
strongest rung and the one whose failure is quietest.
|
|
49
|
+
|
|
50
|
+
## What the hook receives
|
|
51
|
+
|
|
52
|
+
JSON on stdin: `session_id`, `prompt_id`, `transcript_path`, `cwd`,
|
|
53
|
+
`permission_mode`, `hook_event_name`, `tool_name`, `tool_input`, `tool_use_id`.
|
|
54
|
+
|
|
55
|
+
`tool_input` is where the target lives — `file_path` for an edit, `command` for a
|
|
56
|
+
Bash call. Parse it; do not infer the target from anything else in the environment.
|
|
57
|
+
|
|
58
|
+
## Where it lives
|
|
59
|
+
|
|
60
|
+
| Placement | Scope | Use when |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| the project's `.claude/settings.json` | this repository | the rule is this project's |
|
|
63
|
+
| a plugin's `hooks/hooks.json`, paths via `${CLAUDE_PLUGIN_ROOT}` | every project the plugin is installed in | the rule travels with a tool |
|
|
64
|
+
|
|
65
|
+
**A globally installed plugin must exit 0 immediately when the project has no
|
|
66
|
+
config for it.** Otherwise installing it once changes every other repository on the
|
|
67
|
+
machine, and the first surprising denial is debugged in the wrong project.
|
|
68
|
+
|
|
69
|
+
## Matchers
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{ "matcher": "Edit|Write|MultiEdit|NotebookEdit",
|
|
73
|
+
"hooks": [{ "type": "command", "command": "…/guard.sh", "timeout": 20 }] }
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- a tool-name pattern (`Edit|Write|…`), or `"*"` for every call;
|
|
77
|
+
- for a specific shell command, add `"if": "Bash(git commit *)"` beside
|
|
78
|
+
`"matcher": "Bash"`.
|
|
79
|
+
|
|
80
|
+
Match as **narrowly** as the rule allows. A `"*"` matcher on a blocking event puts
|
|
81
|
+
your script in the path of every tool call the agent makes.
|
|
82
|
+
|
|
83
|
+
## Performance
|
|
84
|
+
|
|
85
|
+
A `PostToolUse` hook on `"*"` runs after **every** call, so it must be a no-op in
|
|
86
|
+
the common case: read one timestamp file, return. Touch the network at most once
|
|
87
|
+
per throttle interval. If it becomes slower than that, the throttle is broken —
|
|
88
|
+
**fix the throttle, never remove the hook**, because a hook removed for latency is
|
|
89
|
+
a protection removed permanently for a reason that had a fix.
|
|
90
|
+
|
|
91
|
+
## What belongs in a hook, and what does not
|
|
92
|
+
|
|
93
|
+
**Belongs:** cheap, deterministic, and about an edit happening *right now* — a
|
|
94
|
+
guarded path, a staged file, a lease that is not held, a command with a shape the
|
|
95
|
+
project forbids.
|
|
96
|
+
|
|
97
|
+
**Does not belong:** the full test suite; anything needing the network on every
|
|
98
|
+
call; anything whose answer requires a human. Those are rungs 3 and 4
|
|
99
|
+
([`gates.md`](gates.md)) — CI is late, and late is the correct trade for slow.
|
|
100
|
+
|
|
101
|
+
The test is one question: *if this fires, can the agent fix it in the next ten
|
|
102
|
+
seconds without asking anybody?* If not, blocking here only converts a review
|
|
103
|
+
comment into a dead end.
|
|
104
|
+
|
|
105
|
+
## A worked example
|
|
106
|
+
|
|
107
|
+
The one hook this skill ships — run the documentation gate before a commit, and
|
|
108
|
+
refuse the commit if it fails. It is
|
|
109
|
+
[`../templates/hooks.example.json`](../templates/hooks.example.json); copy it into
|
|
110
|
+
the project's `.claude/settings.json`.
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{ "hooks": { "PreToolUse": [
|
|
114
|
+
{ "matcher": "Bash", "if": "Bash(git commit *)",
|
|
115
|
+
"hooks": [{ "type": "command", "shell": "bash", "timeout": 60,
|
|
116
|
+
"command": "bash scripts/check-docs.sh >&2 || exit 2" }] } ] } }
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`|| exit 2` is the contract, not a flourish: without it the gate's own `exit 1`
|
|
120
|
+
lands in the "non-blocking error" branch and the commit proceeds.
|
|
121
|
+
|
|
122
|
+
## Debugging
|
|
123
|
+
|
|
124
|
+
| Symptom | Cause |
|
|
125
|
+
|---|---|
|
|
126
|
+
| Guarded edits go through | the guard crashed — any exit code other than 2 is non-blocking. Run it by hand |
|
|
127
|
+
| Everything is denied | no config, or no lease. The tool's `status` says which |
|
|
128
|
+
| Session start is slow | the backend is unreachable; it must time out and degrade, never hang |
|
|
129
|
+
| The renew hook floods the log | the throttle file is not being written — check the path is writable |
|
|
130
|
+
|
|
131
|
+
Run the guard directly and see what it decides:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
echo '{"tool_name":"Edit","tool_input":{"file_path":"docs/DECISIONS.md"},"cwd":"'"$PWD"'"}' \
|
|
135
|
+
| bash .claude/hooks/guard.sh; echo "exit=$?"
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Removing them
|
|
139
|
+
|
|
140
|
+
Delete the `hooks` block from the project's `.claude/settings.json`. Everything the
|
|
141
|
+
hooks enforced is still available as a command and still stated in the doctrine —
|
|
142
|
+
and the run is **`ungated`** from then on, which is a thing to say out loud rather
|
|
143
|
+
than a detail to omit.
|
|
144
|
+
|
|
145
|
+
## Leases are not reimplemented here
|
|
146
|
+
|
|
147
|
+
Guarded registers and lease arbitration belong to a coordination tool
|
|
148
|
+
([`companion-skills.md`](companion-skills.md) names the optional one). This skill
|
|
149
|
+
ships the **doctrine** and the one example above.
|
|
150
|
+
|
|
151
|
+
Two implementations of one lease will disagree, and the disagreement is invisible:
|
|
152
|
+
each believes it holds the lock, both write, and the register ends up with two
|
|
153
|
+
entries carrying one id — which is the exact failure the lease existed to prevent.
|
|
154
|
+
|
|
155
|
+
## Rationalizations
|
|
156
|
+
|
|
157
|
+
| Excuse | Reality |
|
|
158
|
+
|---|---|
|
|
159
|
+
| "The hook is installed, so the repo is protected" | Only in Claude Code, and only while the guard exits 2. Any other exit code fails open silently. |
|
|
160
|
+
| "It's fine, the guard can't crash" | Then it costs one line to make crashing block instead of pass. Write the line. |
|
|
161
|
+
| "I'll match `*` and filter inside the script" | Now every tool call pays your script's startup. Match narrowly; the matcher is free and the script is not. |
|
|
162
|
+
| "The hook is slow, I'll disable it for now" | "For now" survives the session and the memory of why. Fix the throttle. |
|
|
163
|
+
| "I'll put the test suite in the hook, it's the strongest gate" | It is the strongest and the most expensive. A rule that takes two minutes to answer belongs in CI. |
|
|
164
|
+
| "Other agents will follow the doctrine anyway" | They might. What they will not do is *block*, and the run must say `ungated` so nobody mistakes intention for enforcement. |
|
|
@@ -29,9 +29,11 @@ makes the grill's answers *checkable* instead of merely confident.
|
|
|
29
29
|
| 2 | **The code graph** | `graphify-out/graph.json` — see below | *reach*: what calls this, what breaks if it moves, what every change passes through |
|
|
30
30
|
| 3 | **Host agent docs** | `CLAUDE.md`, `AGENTS.md`, `.cursor/rules/` | conventions, commands, deploy path, house rules |
|
|
31
31
|
| 4 | **Domain docs** | `CONTEXT.md` / `CONTEXT-MAP.md`, `docs/adr/` | the glossary and the decisions with their reasons |
|
|
32
|
+
| 4a | **The decision register and the doc map** | `docs/DECISIONS.md` **or** `docs/adr/` — `docs/DOCMAP.md` says which ([`documentation.md`](documentation.md)) | what is already settled, what it superseded, and which documents this run will owe |
|
|
32
33
|
| 5 | **Product/UX docs** | `docs/ux/` (super-ux chain), `README`, runbooks | user-facing behavior that is already specified |
|
|
33
34
|
| 6 | **Pipeline history** | `docs/superpowers/specs/`, `plans/`, past `-carryover.md` | what a previous run of this pipeline decided or deferred |
|
|
34
|
-
| 7 | **The retro
|
|
35
|
+
| 7 | **The retro, in force** | `docs/superpowers/retro.md` ([`retrospective.md`](retrospective.md)) | what previous runs got wrong here — **read in full**: standing instructions (capped at ten), run stamps and the recent-log window, all bounded by construction |
|
|
36
|
+
| 7a | **The retro archive** | `docs/superpowers/retro/YYYY-QN.md` | *have we been bitten by this class before?* — **queried** by the task's nouns, never read end to end |
|
|
35
37
|
| 8 | **The knowledge wiki** | see below | distilled cross-project knowledge, prior sessions, why decisions were made |
|
|
36
38
|
| 9 | **Other doc repos the project names** | a docs repo URL or submodule in `CLAUDE.md`/`README`, a sibling checkout, a `docs/` monorepo package | specs, contracts and runbooks that live outside this repo |
|
|
37
39
|
| 10 | **Hosted doc systems the project names** | Notion / Confluence / Google Docs referenced in the project | the same, when the team keeps them there |
|
|
@@ -173,10 +175,22 @@ Three shapes and what to do with each:
|
|
|
173
175
|
document; they may not do it by accident. The point of quoting the source is that
|
|
174
176
|
the override becomes a recorded decision instead of an undetected divergence.
|
|
175
177
|
|
|
176
|
-
**Precedence
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
178
|
+
**Precedence — and it splits in two, because two different questions are being
|
|
179
|
+
asked.**
|
|
180
|
+
|
|
181
|
+
*For what **is**:* code, then host docs and ADRs, then the wiki, then anyone's
|
|
182
|
+
memory. The wiki is *distilled* knowledge and can lag the repo by months; the code
|
|
183
|
+
is what runs.
|
|
184
|
+
|
|
185
|
+
*For what **should be**:* the **register outranks the code**
|
|
186
|
+
([`documentation.md`](documentation.md)). A decision that is accepted and not yet
|
|
187
|
+
built is still the decision, and code that contradicts it is a finding — a bug, or
|
|
188
|
+
an unrecorded reversal — never a tie-break in the code's favour. Getting this
|
|
189
|
+
backwards is how a run "discovers" that the system does not work the way the
|
|
190
|
+
project decided, and quietly builds the version it found.
|
|
191
|
+
|
|
192
|
+
Either way a disagreement is a grill question, never a silent pick, and it is
|
|
193
|
+
usually a sign that something is due an update.
|
|
180
194
|
|
|
181
195
|
## Close the loop — stage 9 updates what stage 0 read
|
|
182
196
|
|
|
@@ -184,6 +198,13 @@ The ledger is the stage-9 work list. For each row:
|
|
|
184
198
|
|
|
185
199
|
- **Host repo docs, ADRs, runbooks, `docs/ux/`** — updated in the **same change**,
|
|
186
200
|
per the host's own rules ([`conventions.md`](conventions.md)).
|
|
201
|
+
- **The register and the doc map** — every decision this run settled gets an entry
|
|
202
|
+
with an id; every question it answered is flipped; the doc map gains any new
|
|
203
|
+
document class or ratchet. Note that this list and the **propagation matrix** are
|
|
204
|
+
different lists on purpose: the ledger is what you *read*, the matrix is what you
|
|
205
|
+
*owe* ([`documentation.md`](documentation.md)), and stage 9 walks both.
|
|
206
|
+
- **The retro** — prune, stamp, entry, and rotate what aged out into the archive
|
|
207
|
+
([`retrospective.md`](retrospective.md)).
|
|
187
208
|
- **Anything the run proved stale** — including a doc that was "wrong but nobody
|
|
188
209
|
had time": that's why the conflict was logged in phase 2 instead of only being
|
|
189
210
|
resolved verbally.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
it.** Every rule here names the incident that produced it. A rule with no incident behind it is
|
|
5
5
|
somebody's preference, and it will be argued with at the worst moment.
|
|
6
6
|
|
|
7
|
-
They come from one
|
|
7
|
+
They come from one 260-decision, 72-document specification built across four repositories with
|
|
8
8
|
several agents working at once. Nothing here is hypothetical.
|
|
9
9
|
|
|
10
10
|
**A rule belongs in the table only when it has a check.** Two of the lessons below could not be
|
|
@@ -31,6 +31,7 @@ to be enforced and is not is the same failure as a gate that prints `FAIL` and e
|
|
|
31
31
|
| 12 | **Tests create what they assert on** | any test touching shared state | run the suite against a cold, empty environment | the cold run and the warm run agree |
|
|
32
32
|
| 13 | **Local infrastructure does not fight the host** | any dev compose or service definition | assume the host already runs the defaults | services reachable with the host's own still running |
|
|
33
33
|
| 14 | **A document may not send a reader to something absent** | any instruction naming a command, file or install | resolve it | the gate fails when the target does not exist |
|
|
34
|
+
| 15 | **Identity before coordination** | any lease, lock, claim or run id | ask what two instances with the same identity would do, and make the tool answer it | two instances demonstrably get two identities |
|
|
34
35
|
|
|
35
36
|
---
|
|
36
37
|
|
|
@@ -94,6 +95,18 @@ the migration failed with a permission error that named nothing about the collis
|
|
|
94
95
|
was not installed, with no install line anywhere and no statement of what a session without it
|
|
95
96
|
actually is.
|
|
96
97
|
|
|
98
|
+
**15 · Identity.** The coordination plugin derived one run id **per checkout**. A hook has the
|
|
99
|
+
session id in its environment and a plain shell command does not, so the second session in a
|
|
100
|
+
checkout adopted the first one's identity: **an entire day of work was performed holding another
|
|
101
|
+
session's leases**, and the end-of-work check that had just been written offered to release
|
|
102
|
+
*theirs*. It was invisible from inside — `whoami` reported a lease and a run id, both plausible,
|
|
103
|
+
both somebody else's — and it surfaced only because a new command printed a lease nobody could
|
|
104
|
+
account for. This is the same failure as *the one instruction* below, and it is in the table rather
|
|
105
|
+
than only in that list because it **has** a check. Follow-on, from the first two attempted fixes:
|
|
106
|
+
**do not infer identity from strings the environment is also free to contain** — matching `"claude"`
|
|
107
|
+
in a process command line matched the throwaway shell of every tool call, and matching the binary
|
|
108
|
+
path hit the same wall. Prefer a fact something authoritative wrote down.
|
|
109
|
+
|
|
97
110
|
---
|
|
98
111
|
|
|
99
112
|
## The two that are not in the table, and why
|
|
@@ -128,13 +141,15 @@ answer would have exposed it in a minute.
|
|
|
128
141
|
|
|
129
142
|
| Stage | Rules that apply |
|
|
130
143
|
|---|---|
|
|
144
|
+
| 0 Inventory · 9 Docs · any register write | 8 (compute), 14 (targets resolve — including every commit SHA in the retro), 15 (identity before a lease) — see [`documentation.md`](documentation.md) |
|
|
145
|
+
| any check you write | 4, 5, 7, 10, 11 — the procedure is [`gates.md`](gates.md) |
|
|
131
146
|
| 3 Spec · 4 Plan | 2 (both directions), 8 (compute, never restate) |
|
|
132
147
|
| 5 Dev | 9 (generators seed green), 12 (tests create their own state), 13 (local infra) |
|
|
133
148
|
| 6 Tests | 4, 5, 10, 11 — every new check probed both ways, measured, and asserted on its exit code |
|
|
134
149
|
| 9 Docs | 8, 14 — every number computed, every target resolvable |
|
|
135
150
|
| 10 Acceptance | 1, 3, 6, 7 — axis rotation recorded, closure verified against artefacts, classes swept, ratchets printed |
|
|
136
151
|
|
|
137
|
-
**This file is the shipped list; a project keeps its own.** These
|
|
152
|
+
**This file is the shipped list; a project keeps its own.** These fifteen were
|
|
138
153
|
earned on someone else's build and travel with the skill. The lessons *your*
|
|
139
154
|
project buys go in its retro ([`retrospective.md`](retrospective.md) →
|
|
140
155
|
`docs/superpowers/retro.md`), where they are capped, pruned and retired — and a
|
|
@@ -5,14 +5,16 @@ done. It exists because the pipeline's gates are good at *this* run and blind
|
|
|
5
5
|
across runs: the same class of failure can be caught, fixed and forgotten five
|
|
6
6
|
times, and nothing in the flow notices it is the same one.
|
|
7
7
|
|
|
8
|
-
**
|
|
9
|
-
|
|
8
|
+
**Two artifacts, and the split is the point.** A file that is read *in full* every
|
|
9
|
+
run may not contain anything that grows without limit — otherwise the cap that
|
|
10
|
+
justifies reading it protects one section while the file below it doubles.
|
|
10
11
|
|
|
11
|
-
|
|
|
12
|
+
| Artifact | Parts | How it is read |
|
|
12
13
|
|---|---|---|
|
|
13
|
-
| **Standing instructions**
|
|
14
|
-
|
|
|
15
|
-
|
|
14
|
+
| `docs/superpowers/retro.md` — **one per project** | **Standing instructions** (max **10**) · **Recent log** (entries from the last five run stamps) · **Run stamps** | stage 0, **in full** — all three are bounded by construction |
|
|
15
|
+
| `docs/superpowers/retro/YYYY-QN.md` — the archive | every entry and every retirement ever written, append-only | **queried** by the task's nouns; never read end to end |
|
|
16
|
+
|
|
17
|
+
Seed the archive from [`../templates/retro-archive.md`](../templates/retro-archive.md).
|
|
16
18
|
|
|
17
19
|
Every run writes a **stamp** and runs the **prune**. Only a run that *diverged*
|
|
18
20
|
writes an entry. A retro that is empty after a messy run is the exact failure this
|
|
@@ -34,6 +36,38 @@ Required fields, and none of them is optional:
|
|
|
34
36
|
| **Root cause** | why the pipeline permitted it. "The agent was careless" is not a cause — it is the absence of one, and it produces no fix |
|
|
35
37
|
| **Fix** | one of the three grades below |
|
|
36
38
|
| **The check** | what would have caught this the first time. If the honest answer is "nothing yet", that is the fix, and it is grade 1 |
|
|
39
|
+
| **Commit** | the short SHA of the change that fixed it |
|
|
40
|
+
|
|
41
|
+
## Every lesson carries its commit
|
|
42
|
+
|
|
43
|
+
A standing instruction carries **two** SHAs — `Commit` (the change that introduced
|
|
44
|
+
it) and `Fired at` (the last run in which it fired) — and every log entry and every
|
|
45
|
+
retirement carries one.
|
|
46
|
+
|
|
47
|
+
**Why a SHA and not a `file:line`.** A line number rots at the next edit, and then
|
|
48
|
+
the evidence points at something that has moved or gone; the reader is left with a
|
|
49
|
+
claim and no way to check it. A commit is immutable and carries the diff, the
|
|
50
|
+
message and the parent, so `git show <sha>` reconstructs the entire incident two
|
|
51
|
+
months later — which is exactly when the same class comes back and somebody needs
|
|
52
|
+
to know whether this was already understood.
|
|
53
|
+
|
|
54
|
+
**Every SHA must resolve.** This is [`learned.md`](learned.md) rule 14 — *a
|
|
55
|
+
document may not send a reader to something absent* — applied to history, and it is
|
|
56
|
+
mechanical: the project's documentation gate runs `git rev-parse --verify --quiet
|
|
57
|
+
<sha>^{commit}` over every backticked SHA in the retro and its archive
|
|
58
|
+
([`gates.md`](gates.md)).
|
|
59
|
+
|
|
60
|
+
## Rotation — the archive is how pruning stops losing things
|
|
61
|
+
|
|
62
|
+
At the prune, entries older than the last five run stamps **move** to
|
|
63
|
+
`docs/superpowers/retro/YYYY-QN.md`. Moving is not deleting.
|
|
64
|
+
|
|
65
|
+
- The archive is **append-only**, and a retirement writes its line **there**, with
|
|
66
|
+
the trigger that retired it and the commit.
|
|
67
|
+
- A retired rule that comes back as a real failure is a grade-1 fix — **with its
|
|
68
|
+
history attached**, which is the whole return on having archived it.
|
|
69
|
+
- Nothing is ever removed from the archive to keep it tidy. It is not read in full,
|
|
70
|
+
so its size costs nothing; its completeness is what it is for.
|
|
37
71
|
|
|
38
72
|
## Three grades of fix — take the highest one that can work
|
|
39
73
|
|
|
@@ -60,7 +94,9 @@ rule that could have been a check gets read twice and obeyed once.
|
|
|
60
94
|
Prune first, then write. A lesson that lands in a cluttered file is a lesson nobody
|
|
61
95
|
will reach.
|
|
62
96
|
|
|
63
|
-
|
|
97
|
+
Every row carries its own trigger in a **`Retire when`** column, written at birth —
|
|
98
|
+
a rule whose retirement condition is decided later is a rule the prune can only
|
|
99
|
+
argue about. Check **every** standing instruction against three triggers:
|
|
64
100
|
|
|
65
101
|
| Trigger | Test | Then |
|
|
66
102
|
|---|---|---|
|
|
@@ -73,10 +109,9 @@ them all — the oldest never-fired one goes. "But all of them matter" is precis
|
|
|
73
109
|
the state in which the list stopped being read, and the ninth stale rule is what
|
|
74
110
|
discredits the two that are load-bearing.
|
|
75
111
|
|
|
76
|
-
**Every deletion writes one line in the
|
|
77
|
-
Silent deletion is forbidden: the record is what survives, the
|
|
78
|
-
|
|
79
|
-
you have its history.
|
|
112
|
+
**Every deletion writes one line in the archive** — id, date, which trigger fired,
|
|
113
|
+
and the commit. Silent deletion is forbidden: the record is what survives, the
|
|
114
|
+
instruction is what leaves.
|
|
80
115
|
|
|
81
116
|
**Print the counts beside the gate verdict**, the same way the carry-over ledger
|
|
82
117
|
does ([`audit.md`](audit.md) → *ratchet, never TODO*):
|
|
@@ -93,9 +128,15 @@ A pruned list that nobody prints is a list that quietly grows back.
|
|
|
93
128
|
The standing instructions are an **instruction source**, not background reading:
|
|
94
129
|
[`knowledge-sources.md`](knowledge-sources.md) reads them in full at the harvest —
|
|
95
130
|
they are short by construction — and records the file as a ledger row. Every
|
|
96
|
-
instruction that actually *fires* during the run gets its **last-fired date
|
|
97
|
-
stamped** as it fires. That stamp is the only thing that makes the cold-rule
|
|
98
|
-
without it "five runs without firing" is a guess, and the prune becomes a
|
|
131
|
+
instruction that actually *fires* during the run gets its **last-fired date and
|
|
132
|
+
commit stamped** as it fires. That stamp is the only thing that makes the cold-rule
|
|
133
|
+
honest; without it "five runs without firing" is a guess, and the prune becomes a
|
|
134
|
+
mood.
|
|
135
|
+
|
|
136
|
+
**The archive is queried at the same moment**, by the task's own nouns. It is the
|
|
137
|
+
one source that answers *"have we been bitten by this class before?"* — and that
|
|
138
|
+
question is worth asking precisely when the in-force list says nothing, because a
|
|
139
|
+
rule that was retired for going cold is exactly the rule about to be re-learned.
|
|
99
140
|
|
|
100
141
|
## Where a lesson goes when it is not about this project
|
|
101
142
|
|
|
@@ -51,6 +51,23 @@ stages/agents/types (see SKILL.md → *Bring your own skills*).
|
|
|
51
51
|
explicit "none found"; the graph's row carries its build date). It is retrieval
|
|
52
52
|
scoped by the task's own nouns, not a read of everything — and it is what makes
|
|
53
53
|
phase 2's answers checkable instead of merely confident.
|
|
54
|
+
- **Phase 1b — the documentation inventory**
|
|
55
|
+
([`documentation.md`](documentation.md)). Four questions, answered before the
|
|
56
|
+
interview and written to `docs/DOCMAP.md` (seeded from
|
|
57
|
+
[`../templates/docmap.md`](../templates/docmap.md), **only when absent**): where
|
|
58
|
+
do settled things live, what is each fact's single home, what does a change of
|
|
59
|
+
type X oblige, and what proves it. A project with no answers gets them seeded —
|
|
60
|
+
registers, the matrix and `scripts/check-docs.sh` — and the seeding is itself
|
|
61
|
+
recorded as the register's first entry. **One decision home per project:** an
|
|
62
|
+
existing `docs/adr/` *is* the register and is recorded as such, never duplicated.
|
|
63
|
+
The gate is seeded so that it exits `0` on its own seeds; a project that starts
|
|
64
|
+
red learns on day one that the gate is noise.
|
|
65
|
+
- **Phase 1c — reconcile intent against as-built.** Git says how it *should* be;
|
|
66
|
+
the run record says how it *turned out*. Read both for the area you are about to
|
|
67
|
+
touch and resolve every divergence — the document is stale, the record is wrong,
|
|
68
|
+
or they genuinely disagree and that is a decision. There is no fourth option, and
|
|
69
|
+
starting on an unresolved divergence means building against a system that does
|
|
70
|
+
not exist.
|
|
54
71
|
- **How it runs: [`grill.md`](grill.md)** — the full doctrine, built into this
|
|
55
72
|
skill (nothing to install). In short: one question per turn, a recommended
|
|
56
73
|
answer with each, explore the codebase before asking, depth-first through the
|
|
@@ -77,7 +94,11 @@ stages/agents/types (see SKILL.md → *Bring your own skills*).
|
|
|
77
94
|
an updated `CONTEXT.md` (terms written as they resolved) and any ADRs under
|
|
78
95
|
`docs/adr/` — see `grill.md` → *Domain awareness*.
|
|
79
96
|
- **GATE (manual):** shared understanding reached — **the source ledger is written
|
|
80
|
-
(every source consulted, or an explicit "none found")**,
|
|
97
|
+
(every source consulted, or an explicit "none found")**, **the documentation
|
|
98
|
+
inventory is answered into `docs/DOCMAP.md`** with its registers, single homes,
|
|
99
|
+
a non-empty propagation matrix and the gate command, **the regime is recorded**,
|
|
100
|
+
**intent and as-built are reconciled with every divergence resolved**, the retro's
|
|
101
|
+
in-force sections are read in full and its archive queried, every detected branch has
|
|
81
102
|
a recorded answer or an explicit deferral, **every answer that contradicted a
|
|
82
103
|
harvested source has a recorded resolution** (which governs, and whether the doc
|
|
83
104
|
is now stale), no open contradictions, **every
|
|
@@ -228,7 +249,9 @@ stages/agents/types (see SKILL.md → *Bring your own skills*).
|
|
|
228
249
|
same as stage 5.
|
|
229
250
|
- **GATE (auto):** the **full** suite is green (not just the new tests); new/changed code
|
|
230
251
|
is covered; no `skip`/`xfail` smuggling a red suite past the gate. Never advance
|
|
231
|
-
to deploy on a red or partial run.
|
|
252
|
+
to deploy on a red or partial run. **The carry-over count is printed beside this
|
|
253
|
+
verdict** — a ratchet nobody prints is a TODO with a better name
|
|
254
|
+
([`audit.md`](audit.md)).
|
|
232
255
|
|
|
233
256
|
## 7 — Lint + deploy
|
|
234
257
|
- Read host conventions (`conventions.md`): run the linter; fix failures. The suite
|
|
@@ -240,7 +263,8 @@ stages/agents/types (see SKILL.md → *Bring your own skills*).
|
|
|
240
263
|
- **GATE (manual):** lint clean (host linter **and**, for UI projects, the super-ux
|
|
241
264
|
linter) **and** suite green **before** deploy, **and no REQ is still `open`** — a
|
|
242
265
|
`partial` ships only with the operator's explicit acceptance. A gap is cheapest to
|
|
243
|
-
close before it ships, and the operator is already present at this gate.
|
|
266
|
+
close before it ships, and the operator is already present at this gate. **The
|
|
267
|
+
carry-over count is printed beside this verdict.** Deploy is outward → explicit
|
|
244
268
|
operator go. Respect deploy-from-main rules if the project mandates them.
|
|
245
269
|
|
|
246
270
|
## 8 — Post-deploy
|
|
@@ -250,6 +274,18 @@ stages/agents/types (see SKILL.md → *Bring your own skills*).
|
|
|
250
274
|
steps — never silent success.
|
|
251
275
|
|
|
252
276
|
## 9 — Docs + wiki
|
|
277
|
+
- **The propagation sweep runs first** ([`documentation.md`](documentation.md)).
|
|
278
|
+
The ledger below names the documents you **read**; the matrix in `docs/DOCMAP.md`
|
|
279
|
+
names the documents you **owe**. They are not the same list, and the gap between
|
|
280
|
+
them is where documentation rots — the document nobody read is exactly the
|
|
281
|
+
document nobody updated. Walk the matrix row for **every** change type this run
|
|
282
|
+
produced. Every settled thing gets an id in the register, every answered question
|
|
283
|
+
is flipped to `Resolved→<id>`, and every document named in a
|
|
284
|
+
`Consequences / affects:` line cites its decision.
|
|
285
|
+
- **Then run the documentation gate** (`bash scripts/check-docs.sh`, or whatever
|
|
286
|
+
`docs/DOCMAP.md` → *Gates* names) and print its **ratchet counts** beside the
|
|
287
|
+
verdict, so "green" reads as *"green, and here is exactly what was not looked
|
|
288
|
+
at"* ([`gates.md`](gates.md)). A check that skipped says so.
|
|
253
289
|
- **The stage-0 source ledger is the work list** ([`knowledge-sources.md`](knowledge-sources.md)
|
|
254
290
|
→ *Close the loop*): every source the harvest read gets updated if this run
|
|
255
291
|
changed or disproved it. What was worth reading at stage 0 and is wrong now is
|
|
@@ -278,11 +314,17 @@ stages/agents/types (see SKILL.md → *Bring your own skills*).
|
|
|
278
314
|
- **Docs living in another repository** are outward: propose the edit, get an
|
|
279
315
|
explicit go, then open a PR there. No go → the exact edit goes in the carry-over
|
|
280
316
|
ledger.
|
|
281
|
-
- **GATE (auto):**
|
|
282
|
-
|
|
283
|
-
|
|
317
|
+
- **GATE (auto):** **the propagation matrix walked for every change type this run
|
|
318
|
+
produced**, with every settled thing recorded under an id and every answered
|
|
319
|
+
question resolved; **the documentation gate green, its ratchet counts printed and
|
|
320
|
+
any skip stated** — this is what replaced the unfalsifiable *"docs in sync with
|
|
321
|
+
code"*, which named no artefact and no command; every stale row in the source
|
|
322
|
+
ledger either updated or carried over with its edit; the **as-built record
|
|
323
|
+
written and reconciled**; UI: super-ux layers current + linter green; wiki synced
|
|
324
|
+
(or absent and recommended once); **the code graph
|
|
284
325
|
refreshed where one exists, or the reason it wasn't written into the carry-over
|
|
285
|
-
ledger** (absent and recommended once is fine); dangling links fixed
|
|
326
|
+
ledger** (absent and recommended once is fine); dangling links fixed; **the
|
|
327
|
+
carry-over count printed beside this verdict**.
|
|
286
328
|
|
|
287
329
|
## 10 — Acceptance
|
|
288
330
|
- **What:** the closing stage — go back to the brief and account for **every**
|
|
@@ -348,8 +390,12 @@ stages/agents/types (see SKILL.md → *Bring your own skills*).
|
|
|
348
390
|
instructions in full next time, which is why the cap is not negotiable.
|
|
349
391
|
- **GATE (manual):** the ladder walk ran and its absences became REQ rows before
|
|
350
392
|
the table was written; **the retrospective is written — prune before entry, the
|
|
351
|
-
list at or under its cap
|
|
352
|
-
|
|
393
|
+
list at or under its cap, every deletion logged **in the archive with its commit**,
|
|
394
|
+
entries older than five run stamps rotated into `docs/superpowers/retro/`, the run
|
|
395
|
+
stamped **with its commit**, every SHA in either file resolvable, and the
|
|
396
|
+
counts printed beside this verdict**; **the documentation gate has been seen
|
|
397
|
+
failing once against a planted defect and its ratchet counts are printed**
|
|
398
|
+
([`gates.md`](gates.md)); **every repository is closed — the parent included:
|
|
353
399
|
`git submodule status` shows no `+`, each repo clean and pushed**; **every check this gate leans on has been seen failing
|
|
354
400
|
once against a planted defect** (an unproven check's green is not evidence);
|
|
355
401
|
every REQ has a status (none `unknown`); every `verified`
|
|
@@ -387,6 +433,22 @@ module N → 3 spec (dossier) → 4 plan → 5 build → 6 tests → 7 lint+depl
|
|
|
387
433
|
cross-module contracts are covered by tests that cross the seam, and a final
|
|
388
434
|
acceptance covers the platform's whole REQ table — not module by module.
|
|
389
435
|
|
|
436
|
+
## Cross-cutting — the Doc Loop
|
|
437
|
+
|
|
438
|
+
A decision is not made at stage 9. It is made the moment something is settled —
|
|
439
|
+
in the grill, in the brainstorm's approved design, in the spec's locked contract,
|
|
440
|
+
in a ruling on a review finding at stage 5 — and every one of those is a stage that
|
|
441
|
+
can lose it.
|
|
442
|
+
|
|
443
|
+
- **It fires at any stage**, and the seven steps live in
|
|
444
|
+
[`documentation.md`](documentation.md): orient and reconcile → reserve the id and
|
|
445
|
+
record → resolve the question it answers → propagate by the matrix → adjust scope
|
|
446
|
+
→ record as-built → commit with the ids.
|
|
447
|
+
- **Step 7 is part of the loop, not after it.** A decision recorded and uncommitted
|
|
448
|
+
is a decision that survives exactly as long as the working tree.
|
|
449
|
+
- **Reserve before you mint.** Reading *"Next free ID"* is not reserving it, and a
|
|
450
|
+
second agent reading it in the same minute gets the same number.
|
|
451
|
+
|
|
390
452
|
## Cross-cutting — the loop guard
|
|
391
453
|
|
|
392
454
|
Any stage can be re-entered and any loop can churn: a pass undoing what an earlier
|
|
@@ -13,7 +13,20 @@ from `super-ux`.
|
|
|
13
13
|
| `carryover.md` | `docs/superpowers/specs/YYYY-MM-DD-<topic>-carryover.md` | 0 seeds, all stages append, 10 reads |
|
|
14
14
|
| `context.md` | `CONTEXT.md` at the repo root (or per context) | 0 — grill, domain awareness |
|
|
15
15
|
| `adr.md` | `docs/adr/NNNN-<slug>.md` | 0 — grill, hard-to-reverse decisions |
|
|
16
|
-
| `
|
|
16
|
+
| `docmap.md` | `docs/DOCMAP.md` — **one per project** | 0 — the documentation inventory |
|
|
17
|
+
| `decisions.md` | `docs/DECISIONS.md` — the decision register | 0 seeds it, the Doc Loop appends |
|
|
18
|
+
| `open-questions.md` | `docs/OPEN_QUESTIONS.md` | 0 seeds it, the Doc Loop resolves rows |
|
|
19
|
+
| `docgate.sh` | `scripts/check-docs.sh` | 0 seeds it · 9 runs it · 10 proves it |
|
|
20
|
+
| `hooks.example.json` | the project's `.claude/settings.json` | 0 — offered, never installed silently |
|
|
21
|
+
| `retro.md` | `docs/superpowers/retro.md` — **one per project, not per run** | 10 writes (prune → stamp → entry), 0 reads it in full |
|
|
22
|
+
| `retro-archive.md` | `docs/superpowers/retro/YYYY-QN.md` | 10 rotates into it, 0 **queries** it |
|
|
23
|
+
|
|
24
|
+
The documentation-track templates (`docmap.md`, `decisions.md`,
|
|
25
|
+
`open-questions.md`, `docgate.sh`) are seeded **together**, and they are useful at
|
|
26
|
+
three entries: the register opens with the decision that established it, and the
|
|
27
|
+
gate exits `0` on exactly those seeds. A scaffold that seeds red teaches everyone on
|
|
28
|
+
day one that the gate is noise, so this repo's own validator runs the seeded gate
|
|
29
|
+
over a scratch project on every `npm test` and fails if it is not green.
|
|
17
30
|
|
|
18
31
|
`context.md` and `adr.md` are **format references**, not files to copy wholesale:
|
|
19
32
|
the grill writes `CONTEXT.md` entries and ADRs in their shape, lazily — only once
|
|
@@ -18,15 +18,40 @@ increment. Create the directory **lazily** — only when the first ADR is needed
|
|
|
18
18
|
That's it. An ADR can be a single paragraph. The value is recording *that* a
|
|
19
19
|
decision was made and *why* — not filling out sections.
|
|
20
20
|
|
|
21
|
+
## When this directory IS the register
|
|
22
|
+
|
|
23
|
+
An ADR set and `docs/DECISIONS.md` are **two shapes of one decision home**, and a
|
|
24
|
+
project has exactly one ([`../references/documentation.md`](../references/documentation.md)).
|
|
25
|
+
If `docs/adr/` already holds an `NNNN-*.md`, that is the register — record it in
|
|
26
|
+
`docs/DOCMAP.md` and never seed a second home beside it.
|
|
27
|
+
|
|
28
|
+
In that role an ADR owes the same six things the register does, so these stop being
|
|
29
|
+
optional and become the format:
|
|
30
|
+
|
|
31
|
+
```md
|
|
32
|
+
# {Short title of the decision}
|
|
33
|
+
|
|
34
|
+
- **Status:** Accepted <!-- or: Superseded by ADR-0012 · Reversed ·
|
|
35
|
+
Accepted · **Partially superseded by ADR-0012** — <clause> -->
|
|
36
|
+
- **Consequences / affects:** `docs/SECURITY.md`, `docs/DATA_MODEL.md`
|
|
37
|
+
- **Source:** run `2026-08-03-<topic>` · commit `<sha>`
|
|
38
|
+
- **Supersedes:** ADR-0004 <!-- or Refines: / Contradicts: -->
|
|
39
|
+
|
|
40
|
+
{1–3 sentences: what the context was, what was decided, and why.}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`Refines:` is additive and needs no annotation on the target; `Contradicts:` and
|
|
44
|
+
`Supersedes:` both **oblige the target's status line to say so**. Never renumber,
|
|
45
|
+
never delete — add a new ADR and edit only the old one's status line.
|
|
46
|
+
|
|
21
47
|
## Optional sections
|
|
22
48
|
|
|
23
49
|
Only when they add genuine value; most ADRs need none.
|
|
24
50
|
|
|
25
|
-
- **Status** frontmatter (`proposed | accepted | deprecated | superseded by
|
|
26
|
-
ADR-NNNN`) — useful once decisions start getting revisited.
|
|
27
51
|
- **Considered options** — only when the rejected alternatives are worth
|
|
28
52
|
remembering.
|
|
29
|
-
- **Consequences** — only when non-obvious downstream effects need calling
|
|
53
|
+
- **Consequences** (prose) — only when non-obvious downstream effects need calling
|
|
54
|
+
out beyond the `Consequences / affects:` file list.
|
|
30
55
|
|
|
31
56
|
## When to write one
|
|
32
57
|
|
|
@@ -23,18 +23,35 @@ premise if the run leaves it wrong.
|
|
|
23
23
|
| wiki: `projects/…/concepts/…` | … | YYYY-MM | context | **yes — update at stage 9** |
|
|
24
24
|
| `CLAUDE.md` | test/lint/deploy commands, house rules | current | convention | no |
|
|
25
25
|
|
|
26
|
-
Precedence
|
|
27
|
-
ADRs, then the code graph, then the wiki, then memory
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
Precedence splits by the question being asked. **For what *is*:** code first, then
|
|
27
|
+
host docs and ADRs, then the code graph, then the wiki, then memory — the graph
|
|
28
|
+
points, the code decides. **For what *should be*:** the decision register outranks
|
|
29
|
+
the code, because a decision accepted and not yet built is still the decision, and
|
|
30
|
+
code that contradicts it is a finding rather than a tie-break. The operator
|
|
31
|
+
outranks every document — but only **out loud**: an override quoted against its
|
|
32
|
+
source is a recorded decision, an unquoted one is an undetected divergence.
|
|
33
|
+
|
|
34
|
+
## Documentation (the phase-1b inventory — the four questions)
|
|
35
|
+
|
|
36
|
+
| Question | Answer |
|
|
37
|
+
|---|---|
|
|
38
|
+
| **Regime** | governed — seeded this run / already in place since … |
|
|
39
|
+
| **Decision home** (exactly one) | `docs/DECISIONS.md` (`DEC-####`) / `docs/adr/` (`ADR-NNNN`) — never both |
|
|
40
|
+
| **Open questions** | `docs/OPEN_QUESTIONS.md` (`OQ-####`) |
|
|
41
|
+
| **Doc map** | `docs/DOCMAP.md` — single homes + the propagation matrix (non-empty; every row names its check or the word `review` with a reason) |
|
|
42
|
+
| **Gate** | `bash scripts/check-docs.sh` — seeded / already present; ratchet floors: … |
|
|
43
|
+
| **Shared state** | lease mechanism present / **`ungated`** (say so out loud in the run) |
|
|
44
|
+
| **Intent vs as-built** | reconciled on … ; divergences found: … ; each resolved how |
|
|
31
45
|
|
|
32
46
|
- **Doc repos / hosted doc systems this project names:** … (or `none`)
|
|
33
47
|
- **Knowledge wiki:** installed / not installed
|
|
34
48
|
([obsidian-wiki](https://github.com/ar9av/obsidian-wiki); recommended, never a gate)
|
|
35
|
-
- **Retro
|
|
36
|
-
(read **in full
|
|
37
|
-
|
|
49
|
+
- **Retro, in force:** `docs/superpowers/retro.md` — none / N standing instructions
|
|
50
|
+
(read **in full**, together with the run stamps and the recent-log window; list
|
|
51
|
+
which ones bind this run, and stamp each as it fires **with the commit** — that
|
|
52
|
+
stamp is the only evidence behind stage 10's cold-retirement rule)
|
|
53
|
+
- **Retro archive:** `docs/superpowers/retro/` — **queried** by this task's nouns;
|
|
54
|
+
what it returned: … (or `nothing`)
|
|
38
55
|
- **Code graph:** built / installed-not-built / not installed
|
|
39
56
|
([graphify](https://github.com/Graphify-Labs/graphify); recommended, never a gate —
|
|
40
57
|
built → its row above carries the build date and stage 9 refreshes it)
|
|
@@ -88,6 +105,7 @@ is not neutral — it is a scheduled interruption.
|
|
|
88
105
|
| run-wide | Model for this run | … (most capable available unless overridden; per-stage overrides here) |
|
|
89
106
|
| run-wide | Decide autonomously vs escalate to me | … |
|
|
90
107
|
| 0 Harvest | Doc sources beyond this repo — other repos, hosted docs, the knowledge wiki, the code graph; and may stage 9 write to them? | … (another repo is outward: propose + PR, never a direct push; graph built / not built) |
|
|
108
|
+
| 0 Docs regime | Where settled things live (register or ADR set — one home, never both); who may write it; lease mechanism present, or is this run `ungated`? Gate command + ratchet floors; may this run raise a floor? | … |
|
|
91
109
|
| 1 Docs | External libs/APIs/SDKs in play; any context7 can't resolve → where their docs live | … |
|
|
92
110
|
| 2 Decompose | Platform (several capabilities/surfaces) or one module? If platform — deploy cadence: per module, or once at the end | … |
|
|
93
111
|
| 2–3 Spec | UI verdict (arms super-ux); scenario-tracing waiver, if any | … |
|