task-pipeline-skill 1.51.0 → 1.53.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/CONTRIBUTING.md +3 -3
  3. package/HOW-IT-WORKS.md +1 -1
  4. package/README.md +15 -1
  5. package/SKILL-CARD.md +1 -1
  6. package/bin/lib/artifact-root.js +123 -0
  7. package/bin/lib/migrate-artifacts.js +221 -0
  8. package/bin/task-pipeline.js +58 -0
  9. package/cursor/rules/task-pipeline.mdc +5 -5
  10. package/package.json +4 -3
  11. package/plugins/task-pipeline/.claude-plugin/plugin.json +1 -1
  12. package/plugins/task-pipeline/commands/task-pipeline.md +3 -3
  13. package/plugins/task-pipeline/hooks/build-gate.sh +107 -0
  14. package/plugins/task-pipeline/hooks/hooks.json +48 -1
  15. package/plugins/task-pipeline/hooks/run-lifecycle.sh +89 -0
  16. package/plugins/task-pipeline/skills/task-pipeline/pipeline.example.json +2 -2
  17. package/plugins/task-pipeline/skills/task-pipeline/pipeline.schema.json +17 -1
  18. package/plugins/task-pipeline/skills/task-pipeline/references/acceptance.md +3 -3
  19. package/plugins/task-pipeline/skills/task-pipeline/references/adoption.md +1 -1
  20. package/plugins/task-pipeline/skills/task-pipeline/references/artifacts.md +43 -14
  21. package/plugins/task-pipeline/skills/task-pipeline/references/backlog.md +1 -1
  22. package/plugins/task-pipeline/skills/task-pipeline/references/continuity.md +1 -1
  23. package/plugins/task-pipeline/skills/task-pipeline/references/decomposition.md +1 -1
  24. package/plugins/task-pipeline/skills/task-pipeline/references/grill.md +2 -2
  25. package/plugins/task-pipeline/skills/task-pipeline/references/knowledge-sources.md +4 -4
  26. package/plugins/task-pipeline/skills/task-pipeline/references/learned.md +2 -2
  27. package/plugins/task-pipeline/skills/task-pipeline/references/planning.md +2 -2
  28. package/plugins/task-pipeline/skills/task-pipeline/references/portability.md +1 -1
  29. package/plugins/task-pipeline/skills/task-pipeline/references/progress.md +18 -3
  30. package/plugins/task-pipeline/skills/task-pipeline/references/retrospective.md +8 -8
  31. package/plugins/task-pipeline/skills/task-pipeline/references/setup.md +24 -1
  32. package/plugins/task-pipeline/skills/task-pipeline/references/spec.md +1 -1
  33. package/plugins/task-pipeline/skills/task-pipeline/references/stages.md +11 -11
  34. package/plugins/task-pipeline/skills/task-pipeline/templates/README.md +6 -6
  35. package/plugins/task-pipeline/skills/task-pipeline/templates/backlog.md +1 -1
  36. package/plugins/task-pipeline/skills/task-pipeline/templates/brief.md +4 -4
  37. package/plugins/task-pipeline/skills/task-pipeline/templates/carryover.md +2 -2
  38. package/plugins/task-pipeline/skills/task-pipeline/templates/retro-archive.md +1 -1
  39. package/plugins/task-pipeline/skills/task-pipeline/templates/retro.md +2 -2
  40. package/plugins/task-pipeline/skills/task-pipeline/templates/run.md +16 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "task-pipeline-skill",
3
- "version": "1.51.0",
3
+ "version": "1.53.0",
4
4
  "description": "Full-cycle delivery pipeline for coding agents: a mandatory built-in intake grill, then 10 gated stages (docs, brainstorm+decompose, spec, plan, build, tests, lint/deploy, post-deploy, docs/wiki, acceptance). Every stage's doctrine ships inside the skill — no companion plugin required. This package is the installer CLI.",
5
5
  "bin": {
6
6
  "task-pipeline": "bin/task-pipeline.js"
@@ -9,8 +9,9 @@
9
9
  "test": "python3 test/validate.py",
10
10
  "test:negatives": "python3 test/negatives.py",
11
11
  "test:probe": "python3 test/probe.py --self-test",
12
- "test:all": "python3 test/validate.py && python3 test/negatives.py && npm run test:probe && npm run test:hooks",
13
- "test:hooks": "python3 test/release_gate_test.py"
12
+ "test:all": "python3 test/validate.py && python3 test/negatives.py && npm run test:probe && npm run test:hooks && npm run test:artifacts",
13
+ "test:hooks": "python3 test/release_gate_test.py",
14
+ "test:artifacts": "python3 test/artifact_root_test.py && python3 test/migrate_artifacts_test.py"
14
15
  },
15
16
  "files": [
16
17
  "bin",
@@ -2,7 +2,7 @@
2
2
  "name": "task-pipeline",
3
3
  "displayName": "Task Pipeline",
4
4
  "description": "Runs a substantial task through a mandatory built-in intake grill, then 10 gated stages (docs, brainstorm+decompose, spec, plan, subagent build, tests, lint/deploy, post-deploy, docs/wiki, acceptance). Every stage's doctrine is built into the skill — no companion plugin required — with typed auto/manual gates, a frozen requirement spine that closes with evidence, a work board and a verification ledger that outlive a run, an exposure line naming what shipped unconfirmed, a progress rail computed from the project's own config, a loop guard whose review ceiling measures rather than stops, and stage-3 tracks for what a product does, how it sounds and how it looks. Two modes need no task: `checkup` (what is unverified) and `setup` (audit existing docs). Retro insights can publish upstream as issues, opt-in and redacted.",
5
- "version": "1.51.0",
5
+ "version": "1.53.0",
6
6
  "author": {
7
7
  "name": "ssheleg",
8
8
  "url": "https://x.com/sshlg93"
@@ -37,15 +37,15 @@ Pull what the project already knows about *this task*:
37
37
  `graphify-out/graph.json`. It answers **reach** — what calls this, what breaks if it
38
38
  moves — which grep cannot.
39
39
  - `CLAUDE.md`, `CONTEXT.md`/ADRs, `docs/` + `docs/ux/`, past briefs and carry-over ledgers.
40
- - **the retro's standing instructions and run stamps** — `docs/superpowers/retro.md`,
40
+ - **the retro's standing instructions and run stamps** — `docs/evidence/retro.md`,
41
41
  read in full; both are bounded and they bind this run. Its **Recent log** is
42
42
  *queried* by the task's nouns, not read: nothing caps it, and an uncapped section
43
43
  inside a binding source is what makes the capped part get skimmed
44
44
  (`references/retrospective.md`).
45
45
  - the **knowledge wiki** if installed ([obsidian-wiki](https://github.com/ar9av/obsidian-wiki);
46
46
  detect `~/.obsidian-wiki/config`), and any other doc system the project names as its docs.
47
- - **the board** (`docs/superpowers/backlog.md`) — open count quoted in the brief, or
48
- seeded when absent. **the verification ledger** (`docs/superpowers/verification.md`) —
47
+ - **the board** (`docs/evidence/backlog.md`) — open count quoted in the brief, or
48
+ seeded when absent. **the verification ledger** (`docs/evidence/verification.md`) —
49
49
  how many rows sit at `never`.
50
50
 
51
51
  Write the **source ledger** into the brief: a row per source, or an explicit *none found*.
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env bash
2
+ # PreToolUse — editing the product before the plan is agreed.
3
+ #
4
+ # `stages.md` says no stage advances until its gate passes, and stage 5 is where
5
+ # code gets written. Editing the product during intake, docs, brainstorm, spec or
6
+ # plan is the pipeline's own discipline being skipped — and it is the skip nobody
7
+ # notices, because the work looks like progress.
8
+ #
9
+ # **`ask`, never `deny`, and the reason is this file's own doctrine.** The routing
10
+ # boundary says a typo, a one-line edit or a mechanical rename does not go through
11
+ # the pipeline, and no hook can tell a typo from a feature. A refusal here would
12
+ # fight the honest cases daily and be removed inside a week; a question answered
13
+ # once costs a keystroke.
14
+ #
15
+ # **The build stage is resolved by ROLE, never by number.** v1.50.0 matched
16
+ # `stage: 6` literally and blocked every release in a six-stage project; the same
17
+ # mistake here would put a prompt in front of every edit in any project whose flow
18
+ # is numbered differently. `pipeline.json` → a stage whose `state` is `build`, else
19
+ # one whose name says build. Unresolvable → silence, because a question nobody can
20
+ # act on is worse than none.
21
+ #
22
+ # **The pipeline's own artefacts are never gated.** Stages 0-4 exist to WRITE
23
+ # things — the brief, the spec, the plan, the ledger. A gate that asked about those
24
+ # would fire on the very work it is protecting.
25
+ set -uo pipefail
26
+
27
+ input=$(cat 2>/dev/null || true)
28
+ project="${CLAUDE_PROJECT_DIR:-$PWD}"
29
+ ledger="$project/.task-pipeline/run.md"
30
+ [ -f "$ledger" ] || exit 0
31
+
32
+ HOOK_INPUT="$input" python3 - "$ledger" "$project" <<'PY' 2>/dev/null || exit 0
33
+ import json, os, re, sys
34
+
35
+ ledger, project = sys.argv[1], sys.argv[2]
36
+ try:
37
+ data = json.loads(os.environ.get("HOOK_INPUT", ""))
38
+ except Exception:
39
+ raise SystemExit(0)
40
+
41
+ ti = data.get("tool_input") or {}
42
+ path = ti.get("file_path") or ti.get("notebook_path") or ""
43
+ if not path:
44
+ raise SystemExit(0)
45
+
46
+ rel = os.path.relpath(path, project) if os.path.isabs(path) else path
47
+ rel = rel.replace(os.sep, "/")
48
+ # The run writes these; gating them would fire on the work stages 0-4 are for.
49
+ if rel.startswith("..") or re.match(r"^(docs/|\.task-pipeline/|\.claude/|CHANGELOG\.md|README\.md)", rel):
50
+ raise SystemExit(0)
51
+
52
+ try:
53
+ text = open(ledger, encoding="utf-8").read()
54
+ except Exception:
55
+ raise SystemExit(0)
56
+
57
+ stage_lines = [l.strip() for l in text.splitlines() if l.strip().startswith("stage:")]
58
+ if not stage_lines:
59
+ raise SystemExit(0)
60
+
61
+
62
+ def build_stage_id():
63
+ """By role, never by number — the mistake v1.50.0 shipped in the release gate."""
64
+ try:
65
+ cfg = json.load(open(os.path.join(project, "pipeline.json"), encoding="utf-8"))
66
+ for s in cfg.get("stages") or []:
67
+ if isinstance(s, dict) and s.get("state") == "build":
68
+ return str(s.get("id"))
69
+ except Exception:
70
+ pass
71
+ for l in stage_lines:
72
+ m = re.match(r"stage:\s*(\S+)\s+([^—]*)", l)
73
+ if m and re.search(r"build|dev\b", m.group(2), re.I):
74
+ return m.group(1)
75
+ return None
76
+
77
+
78
+ build_id = build_stage_id()
79
+ if build_id is None:
80
+ raise SystemExit(0) # unresolvable: a question nobody can act on
81
+
82
+ # Has the run entered the build stage at all? Entering is enough — the gate is
83
+ # about editing BEFORE the plan is agreed, not about the build's own verdict.
84
+ entered = any(re.match(r"stage:\s*%s\b" % re.escape(build_id), l) for l in stage_lines)
85
+ if entered:
86
+ raise SystemExit(0)
87
+
88
+ last = stage_lines[-1]
89
+ m = re.match(r"stage:\s*(\S+)\s+([^—]*)", last)
90
+ now = "%s %s" % (m.group(1), m.group(2).strip()) if m else "an early stage"
91
+
92
+ print(json.dumps({"hookSpecificOutput": {
93
+ "hookEventName": "PreToolUse",
94
+ "permissionDecision": "ask",
95
+ "permissionDecisionReason":
96
+ "This run is at stage %s and has not entered the build stage (%s). Editing "
97
+ "the product before the plan is agreed is the pipeline's own discipline "
98
+ "being skipped — and it is the skip nobody notices, because the work looks "
99
+ "like progress.\n\n"
100
+ "Allow if this is a typo, a one-line fix or a mechanical rename, which the "
101
+ "routing boundary says never went through the pipeline anyway. Otherwise "
102
+ "finish the plan and record stage %s in %s.\n\n"
103
+ "The pipeline's own artefacts — docs/, .task-pipeline/, README, CHANGELOG — "
104
+ "are never gated." % (now, build_id, build_id, ledger),
105
+ }}))
106
+ PY
107
+ exit 0
@@ -1,5 +1,5 @@
1
1
  {
2
- "description": "task-pipeline — the stage-7 gate and the observation it rests on. Every hook exits 0 immediately when the project has no .task-pipeline/run.md, so installing the plugin globally changes nothing in a repository that is not running a pipeline.",
2
+ "description": "task-pipeline — the gates and the observations they rest on. Every hook exits 0 immediately when the project has no .task-pipeline/run.md, so installing the plugin globally changes nothing in a repository that is not running a pipeline.",
3
3
  "hooks": {
4
4
  "PreToolUse": [
5
5
  {
@@ -13,6 +13,17 @@
13
13
  "timeout": 20
14
14
  }
15
15
  ]
16
+ },
17
+ {
18
+ "matcher": "Edit|Write|MultiEdit|NotebookEdit",
19
+ "hooks": [
20
+ {
21
+ "type": "command",
22
+ "shell": "bash",
23
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/build-gate.sh\"",
24
+ "timeout": 20
25
+ }
26
+ ]
16
27
  }
17
28
  ],
18
29
  "PostToolUse": [
@@ -40,6 +51,42 @@
40
51
  }
41
52
  ]
42
53
  }
54
+ ],
55
+ "PreCompact": [
56
+ {
57
+ "hooks": [
58
+ {
59
+ "type": "command",
60
+ "shell": "bash",
61
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-lifecycle.sh\"",
62
+ "timeout": 15
63
+ }
64
+ ]
65
+ }
66
+ ],
67
+ "SubagentStop": [
68
+ {
69
+ "hooks": [
70
+ {
71
+ "type": "command",
72
+ "shell": "bash",
73
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-lifecycle.sh\"",
74
+ "timeout": 15
75
+ }
76
+ ]
77
+ }
78
+ ],
79
+ "SessionEnd": [
80
+ {
81
+ "hooks": [
82
+ {
83
+ "type": "command",
84
+ "shell": "bash",
85
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-lifecycle.sh\"",
86
+ "timeout": 10
87
+ }
88
+ ]
89
+ }
43
90
  ]
44
91
  }
45
92
  }
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env bash
2
+ # PreCompact · SessionEnd · SubagentStop — the three moments the run's own record
3
+ # cannot see, written down as they happen.
4
+ #
5
+ # One line shape for all three:
6
+ #
7
+ # event: <kind> — <detail> — <ISO-8601>
8
+ #
9
+ # **Why one shape and not three.** A ledger grammar is read by four documents and
10
+ # two hooks; every shape added is a shape each of them must learn. These three are
11
+ # the same kind of fact — something happened to the RUN rather than to a stage —
12
+ # and a `kind` field costs one word against three grammars.
13
+ #
14
+ # WHAT EACH ONE IS FOR
15
+ #
16
+ # compact — the ledger exists because compaction happens; `templates/run.md`
17
+ # says so in its own header. Until now the boundary itself was the
18
+ # one event the file could not show, so a resumed run could not
19
+ # tell "the context was compacted here" from "nothing happened".
20
+ # session-end — a run whose session ended without reaching acceptance is
21
+ # ABANDONED, and abandoned runs are exactly what
22
+ # `/task-pipeline checkup` exists to surface. Before this they
23
+ # were invisible: the ledger simply stopped, which looks identical
24
+ # to a run still in progress.
25
+ # subagent — stage 5 dispatches implementers as subagents, and the `hand:`
26
+ # line counts them. Both sides of that count are written by the
27
+ # same agent from the same memory, so the audit comparing them
28
+ # compares a number with itself.
29
+ #
30
+ # **It does NOT write `hand:` lines, and that is not a shortcut.** That shape
31
+ # carries `done`, `surfaced`, `decisions` and `amb` — judgements only the agent
32
+ # holds. A hook filling them in would be fabricating the very evidence the line
33
+ # exists to provide. So it records what it can actually see (a subagent of this
34
+ # type stopped) and leaves the accounting to whoever can account.
35
+ #
36
+ # Silent with no ledger, and never blocking: none of these events should ever cost
37
+ # a session. `SessionEnd` hooks share a 1.5-second budget, so this appends one line
38
+ # and exits.
39
+ set -uo pipefail
40
+
41
+ input=$(cat 2>/dev/null || true)
42
+ project="${CLAUDE_PROJECT_DIR:-$PWD}"
43
+ ledger="$project/.task-pipeline/run.md"
44
+ [ -f "$ledger" ] || exit 0
45
+
46
+ HOOK_INPUT="$input" python3 - "$ledger" <<'PY' 2>/dev/null || true
47
+ import json, os, sys, datetime, re
48
+
49
+ ledger = sys.argv[1]
50
+ try:
51
+ data = json.loads(os.environ.get("HOOK_INPUT", ""))
52
+ except Exception:
53
+ raise SystemExit(0)
54
+
55
+ event = data.get("hook_event_name")
56
+
57
+
58
+ def clean(text, limit=90):
59
+ """One line, no separators that would break the ledger's own grammar."""
60
+ s = re.sub(r"\s+", " ", str(text or "")).replace("—", "-").strip()
61
+ return s[:limit]
62
+
63
+
64
+ if event == "PreCompact":
65
+ kind, detail = "compact", clean(data.get("trigger") or "unknown")
66
+ elif event == "SessionEnd":
67
+ # A run that reached acceptance is finished, not abandoned. Recording an end
68
+ # for it would fill `checkup` with runs that closed exactly as intended.
69
+ try:
70
+ text = open(ledger, encoding="utf-8").read()
71
+ except Exception:
72
+ raise SystemExit(0)
73
+ stages = [l.strip() for l in text.splitlines() if l.strip().startswith("stage:")]
74
+ closed = any(re.search(r"verdict\s+pass", l) and re.search(r"accept", l, re.I) for l in stages)
75
+ if closed:
76
+ raise SystemExit(0)
77
+ kind = "session-end"
78
+ detail = "%s - run not closed, no acceptance recorded" % clean(data.get("reason") or "other", 40)
79
+ elif event == "SubagentStop":
80
+ kind = "subagent"
81
+ detail = clean(data.get("agent_type") or "unknown", 40)
82
+ else:
83
+ raise SystemExit(0)
84
+
85
+ stamp = datetime.datetime.now(datetime.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
86
+ with open(ledger, "a", encoding="utf-8") as fh:
87
+ fh.write('event: %s — %s — %s\n' % (kind, detail, stamp))
88
+ PY
89
+ exit 0
@@ -18,7 +18,7 @@
18
18
  ],
19
19
  "gate": {
20
20
  "type": "manual",
21
- "check": "MANDATORY stage — never skipped (only sanctioned bypass: the entry-from-super-ux short-circuit). PHASE 1, before the first question: harvest the knowledge sources (references/knowledge-sources.md) — code, THE CODE GRAPH when one is built (references/knowledge-graph.md: graphify query/affected/god-nodes answer reach, which grep cannot; detect graphify-out/graph.json — recommended, never required), CLAUDE.md/AGENTS.md, CONTEXT.md + docs/adr, docs/ + docs/ux, past pipeline briefs and carry-over ledgers, THE RETRO'S STANDING INSTRUCTIONS (docs/superpowers/retro.md — read IN FULL, not queried: they are capped at ten and they BIND this run; stamp each one the moment it fires, since that date is the only evidence behind stage 10's cold-retirement rule — references/retrospective.md), the knowledge wiki when installed (obsidian-wiki — recommended, never required; detect ~/.obsidian-wiki/config), and any other repo or hosted doc system the project names as its docs — queried by this task's own terms, with the SOURCE LEDGER written into the brief (a row per source consulted, or an explicit 'none found'; THE GRAPH'S ROW CARRIES ITS MEASURED LAG — commits and days behind HEAD, the signal it was measured with (built_at_commit exact / mtime approximate / unresolvable), and the marker '⚠ not trusted for reach until refreshed' — that exact string, so one marker is greppable across every ledger — on anything but current. A bare build date does NOT satisfy this: it is the graph's own reply about itself, true and self-reported and silent about whether the graph describes the tree this run is about to change — references/knowledge-graph.md -> Measure the lag, and references/gates.md -> False success for the class). PHASE 2, the grill, built into the skill (references/grill.md) — no companion to install. Per its contract: one question at a time, a recommended answer with each, explore the codebase/docs before asking, depth-first, contradictions reconciled; EVERY answer that touches a harvested source is validated against that source — the operator outranks any document, but only out loud, and the losing side is logged for the stage-9 doc update; domain awareness applied (terms challenged against CONTEXT.md, ADRs recorded for hard-to-reverse calls). The autonomy sweep is covered — every stage 1-10 has its blockers pre-resolved (docs sources, branch/tracker policy, test + lint commands, deploy target and authorization, log/health locations, docs+wiki targets, and for UI tasks the design surface: Figma on or text-only, is the Figma MCP connected, and if it is not — ship text-only or stop and connect it, since the UX chain degrades on its own and never blocks; plus, with Figma on, the DESIGN DESTINATION — which team/org by name and which file (the recorded one, a URL the operator gives, or creation in that named team with the creation explicitly authorized), written into the project's canonical record before the first frame, and never created while a recorded file resolves — an unreachable recorded file means stop and ask, never make a replacement) or is explicitly marked 'stop and ask here'. UI verdict recorded (arms super-ux); model decision recorded. All of it locked into a committed task brief the operator confirms before stage 1. The REQ table is written — one row per independently verifiable deliverable, each naming how it is verified — and frozen: adding later is free, removing or narrowing needs the operator's explicit agreement. The carry-over ledger is seeded. PHASE 1b, THE DOCUMENTATION INVENTORY (references/documentation.md): four questions answered into docs/DOCMAP.md before the interview — where settled things live (the DECISION HOME, and there is exactly one per project: an existing docs/adr/ IS the register and is recorded as such, never duplicated), what each fact's single home is, what a change of type X obliges (THE PROPAGATION MATRIX, non-empty, every row naming the check that enforces it or the word 'review' with a one-line reason), and what proves it (the gate command). A project with no answers gets them seeded — registers, matrix and scripts/check-docs.sh from the skill's templates — and the seeding is recorded as the register's first entry; the seeded gate must exit 0 on its own seeds, because a project that starts red teaches everyone on day one that the gate is noise. The regime is recorded. PHASE 1c, RECONCILE: git says how it should be, the run record says how it turned out — read both for the area about to be touched and resolve every divergence (the document is stale, the record is wrong, or they genuinely disagree and that is a decision), because starting on an unresolved divergence means building against a system that does not exist. The retro's in-force sections are read IN FULL and its archive is QUERIED by the task's nouns."
21
+ "check": "MANDATORY stage — never skipped (only sanctioned bypass: the entry-from-super-ux short-circuit). PHASE 1, before the first question: harvest the knowledge sources (references/knowledge-sources.md) — code, THE CODE GRAPH when one is built (references/knowledge-graph.md: graphify query/affected/god-nodes answer reach, which grep cannot; detect graphify-out/graph.json — recommended, never required), CLAUDE.md/AGENTS.md, CONTEXT.md + docs/adr, docs/ + docs/ux, past pipeline briefs and carry-over ledgers, THE RETRO'S STANDING INSTRUCTIONS (docs/evidence/retro.md — read IN FULL, not queried: they are capped at ten and they BIND this run; stamp each one the moment it fires, since that date is the only evidence behind stage 10's cold-retirement rule — references/retrospective.md), the knowledge wiki when installed (obsidian-wiki — recommended, never required; detect ~/.obsidian-wiki/config), and any other repo or hosted doc system the project names as its docs — queried by this task's own terms, with the SOURCE LEDGER written into the brief (a row per source consulted, or an explicit 'none found'; THE GRAPH'S ROW CARRIES ITS MEASURED LAG — commits and days behind HEAD, the signal it was measured with (built_at_commit exact / mtime approximate / unresolvable), and the marker '⚠ not trusted for reach until refreshed' — that exact string, so one marker is greppable across every ledger — on anything but current. A bare build date does NOT satisfy this: it is the graph's own reply about itself, true and self-reported and silent about whether the graph describes the tree this run is about to change — references/knowledge-graph.md -> Measure the lag, and references/gates.md -> False success for the class). PHASE 2, the grill, built into the skill (references/grill.md) — no companion to install. Per its contract: one question at a time, a recommended answer with each, explore the codebase/docs before asking, depth-first, contradictions reconciled; EVERY answer that touches a harvested source is validated against that source — the operator outranks any document, but only out loud, and the losing side is logged for the stage-9 doc update; domain awareness applied (terms challenged against CONTEXT.md, ADRs recorded for hard-to-reverse calls). The autonomy sweep is covered — every stage 1-10 has its blockers pre-resolved (docs sources, branch/tracker policy, test + lint commands, deploy target and authorization, log/health locations, docs+wiki targets, and for UI tasks the design surface: Figma on or text-only, is the Figma MCP connected, and if it is not — ship text-only or stop and connect it, since the UX chain degrades on its own and never blocks; plus, with Figma on, the DESIGN DESTINATION — which team/org by name and which file (the recorded one, a URL the operator gives, or creation in that named team with the creation explicitly authorized), written into the project's canonical record before the first frame, and never created while a recorded file resolves — an unreachable recorded file means stop and ask, never make a replacement) or is explicitly marked 'stop and ask here'. UI verdict recorded (arms super-ux); model decision recorded. All of it locked into a committed task brief the operator confirms before stage 1. The REQ table is written — one row per independently verifiable deliverable, each naming how it is verified — and frozen: adding later is free, removing or narrowing needs the operator's explicit agreement. The carry-over ledger is seeded. PHASE 1b, THE DOCUMENTATION INVENTORY (references/documentation.md): four questions answered into docs/DOCMAP.md before the interview — where settled things live (the DECISION HOME, and there is exactly one per project: an existing docs/adr/ IS the register and is recorded as such, never duplicated), what each fact's single home is, what a change of type X obliges (THE PROPAGATION MATRIX, non-empty, every row naming the check that enforces it or the word 'review' with a one-line reason), and what proves it (the gate command). A project with no answers gets them seeded — registers, matrix and scripts/check-docs.sh from the skill's templates — and the seeding is recorded as the register's first entry; the seeded gate must exit 0 on its own seeds, because a project that starts red teaches everyone on day one that the gate is noise. The regime is recorded. PHASE 1c, RECONCILE: git says how it should be, the run record says how it turned out — read both for the area about to be touched and resolve every divergence (the document is stale, the record is wrong, or they genuinely disagree and that is a decision), because starting on an unresolved divergence means building against a system that does not exist. The retro's in-force sections are read IN FULL and its archive is QUERIED by the task's nouns."
22
22
  }
23
23
  },
24
24
  {
@@ -167,7 +167,7 @@
167
167
  ],
168
168
  "gate": {
169
169
  "type": "manual",
170
- "check": "Close the circle. FIRST the LADDER WALK (references/audit.md), because the REQ table can only find what was named and lost — a comparison needs two sides and an absence has one: walk each REQ bottom-up through its rungs (decision -> spec section -> contract AND its failure behavior -> plan task -> change -> executed test -> surface/docs), check the seam at each step, order findings BY SEAM not by file, and turn every absence into a new REQ row with its check BEFORE the table is written; findings belonging to a lower layer go back to that layer (spec -> stage 3, plan -> stage 4); record the pass's two counts (new findings vs findings caused by this run's own fixes) so the next pass can tell whether the axis is exhausted. THEN the coverage table: every REQ has a status (verified / partial / deferred / dropped) — none unknown; every verified carries evidence (a passing test name, file:line, a command and its output, or a scenario ID) — 'done' without evidence is downgraded to partial, not upgraded, and a green from a check nobody has watched fail against a planted defect is not evidence at all; every partial names what is missing and where it is tracked; every deferred/dropped has the operator's agreement and, for deferred, a tracker entry; no carry-over row is left unresolved and the ledger's counts are printed beside this verdict, so 'green' never reads as 'verified'; EVERY REPOSITORY IS CLOSED, THE PARENT INCLUDED — a submodule is finished only when its parent points at it, so 'git submodule status' shows no line starting with '+' and every repo is clean and pushed ('git -C <repo> status --porcelain' and 'git -C <repo> log @{u}..HEAD' both empty), because a parent records a submodule as a pointer to one commit and moving the submodule does not move the pointer: neither repo looks wrong alone and the disagreement survives every check that runs inside one; and the operator answers the closing question — here is what you asked for, here is what shipped, here is what is deferred, what is missing? — and signs off. LAST ACT, THE RETROSPECTIVE (references/retrospective.md, written to docs/superpowers/retro.md — one file per project, not per run, because every gate in this flow is good at THIS run and blind across runs): PRUNE BEFORE YOU ADD — every standing instruction checked against its three retirement triggers (it became a check; every path/command/stage it names is gone; it has not fired in the last five run stamps), the list held to its hard cap of ten (at eleven the oldest never-fired row goes — 'they all matter' is the state in which the list stopped being read), and EVERY DELETION LOGGED as one line, never silent; THEN stamp the run (date, topic, verdict, counts); THEN, only if the run diverged, write the entry — symptom with evidence, the stage it surfaced at, the stage that OWNED it, the root cause ('the agent was careless' is not one), the fix by grade (mechanical check > standing instruction with its retire-when written at birth > a note that expires in two runs), and the check that catches it the first time from now on. A retro left empty after a messy run is the failure this file exists to stop, and the retro counts are printed beside this gate's verdict like the carry-over ledger's, so a list that quietly grew back is visible where it happened. EVERY LESSON CARRIES ITS COMMIT: each standing instruction has the SHA that introduced it and the SHA of the run in which it last fired, each log entry and each retirement carries one, the run stamp carries the run's own — a file:line rots at the next edit while 'git show <sha>' reconstructs the whole incident two months later — and every SHA must resolve, which the documentation gate checks with 'git rev-parse --verify'. ROTATION: entries older than the last five run stamps MOVE into docs/superpowers/retro/YYYY-QN.md, which is append-only and QUERIED rather than read, so the in-force file stays short enough to be read in full and pruning costs no knowledge. AND THE GATE ITSELF IS PROVEN: every check this close-out leans on — the documentation gate included — has been seen failing once against a planted defect, with the probe recorded, and its ratchet counts are printed beside this verdict (references/gates.md). THE HAND-BACK IS WRITTEN — the request quoted as GIVEN, progress against it, what was solved with evidence, what surfaced unasked, every waiting decision ASKED here with options, and the ambiguity count computed from the four registers; zero prints as zero."
170
+ "check": "Close the circle. FIRST the LADDER WALK (references/audit.md), because the REQ table can only find what was named and lost — a comparison needs two sides and an absence has one: walk each REQ bottom-up through its rungs (decision -> spec section -> contract AND its failure behavior -> plan task -> change -> executed test -> surface/docs), check the seam at each step, order findings BY SEAM not by file, and turn every absence into a new REQ row with its check BEFORE the table is written; findings belonging to a lower layer go back to that layer (spec -> stage 3, plan -> stage 4); record the pass's two counts (new findings vs findings caused by this run's own fixes) so the next pass can tell whether the axis is exhausted. THEN the coverage table: every REQ has a status (verified / partial / deferred / dropped) — none unknown; every verified carries evidence (a passing test name, file:line, a command and its output, or a scenario ID) — 'done' without evidence is downgraded to partial, not upgraded, and a green from a check nobody has watched fail against a planted defect is not evidence at all; every partial names what is missing and where it is tracked; every deferred/dropped has the operator's agreement and, for deferred, a tracker entry; no carry-over row is left unresolved and the ledger's counts are printed beside this verdict, so 'green' never reads as 'verified'; EVERY REPOSITORY IS CLOSED, THE PARENT INCLUDED — a submodule is finished only when its parent points at it, so 'git submodule status' shows no line starting with '+' and every repo is clean and pushed ('git -C <repo> status --porcelain' and 'git -C <repo> log @{u}..HEAD' both empty), because a parent records a submodule as a pointer to one commit and moving the submodule does not move the pointer: neither repo looks wrong alone and the disagreement survives every check that runs inside one; and the operator answers the closing question — here is what you asked for, here is what shipped, here is what is deferred, what is missing? — and signs off. LAST ACT, THE RETROSPECTIVE (references/retrospective.md, written to docs/evidence/retro.md — one file per project, not per run, because every gate in this flow is good at THIS run and blind across runs): PRUNE BEFORE YOU ADD — every standing instruction checked against its three retirement triggers (it became a check; every path/command/stage it names is gone; it has not fired in the last five run stamps), the list held to its hard cap of ten (at eleven the oldest never-fired row goes — 'they all matter' is the state in which the list stopped being read), and EVERY DELETION LOGGED as one line, never silent; THEN stamp the run (date, topic, verdict, counts); THEN, only if the run diverged, write the entry — symptom with evidence, the stage it surfaced at, the stage that OWNED it, the root cause ('the agent was careless' is not one), the fix by grade (mechanical check > standing instruction with its retire-when written at birth > a note that expires in two runs), and the check that catches it the first time from now on. A retro left empty after a messy run is the failure this file exists to stop, and the retro counts are printed beside this gate's verdict like the carry-over ledger's, so a list that quietly grew back is visible where it happened. EVERY LESSON CARRIES ITS COMMIT: each standing instruction has the SHA that introduced it and the SHA of the run in which it last fired, each log entry and each retirement carries one, the run stamp carries the run's own — a file:line rots at the next edit while 'git show <sha>' reconstructs the whole incident two months later — and every SHA must resolve, which the documentation gate checks with 'git rev-parse --verify'. ROTATION: entries older than the last five run stamps MOVE into docs/evidence/retro/YYYY-QN.md, which is append-only and QUERIED rather than read, so the in-force file stays short enough to be read in full and pruning costs no knowledge. AND THE GATE ITSELF IS PROVEN: every check this close-out leans on — the documentation gate included — has been seen failing once against a planted defect, with the probe recorded, and its ratchet counts are printed beside this verdict (references/gates.md). THE HAND-BACK IS WRITTEN — the request quoted as GIVEN, progress against it, what was solved with evidence, what surfaced unasked, every waiting decision ASKED here with options, and the ambiguity count computed from the four registers; zero prints as zero."
171
171
  }
172
172
  }
173
173
  ],
@@ -21,6 +21,9 @@
21
21
  "$ref": "#/definitions/stage"
22
22
  }
23
23
  },
24
+ "paths": {
25
+ "$ref": "#/definitions/paths"
26
+ },
24
27
  "release": {
25
28
  "$ref": "#/definitions/release"
26
29
  },
@@ -32,6 +35,19 @@
32
35
  }
33
36
  },
34
37
  "definitions": {
38
+ "paths": {
39
+ "type": "object",
40
+ "additionalProperties": true,
41
+ "description": "Where this project keeps the pipeline's own paperwork. Optional: omit it and the root is DISCOVERED — docs/evidence/ when it exists and carries a register (retro.md, backlog.md, verification.md, or a specs/plans/briefs/retro directory), else the legacy docs/superpowers/ on the same test, else docs/evidence/ for a project that has neither. The legacy name is the one this pipeline used until 2026-08-13; a project on it keeps it, with no warning on any run. Setting this key outranks both discovered names, which is what finally makes references/artifacts.md's long-standing promise — a host project may relocate the root — something a machine keeps rather than a sentence.",
42
+ "properties": {
43
+ "artifacts": {
44
+ "type": "string",
45
+ "minLength": 1,
46
+ "pattern": "^[^/].*[^/]$|^[^/]$",
47
+ "description": "Relative path from the project root to the artifact home: briefs, specs, plans, the backlog, the verification ledger and the retrospective. Relative, no leading or trailing slash — an absolute path would make the config unusable in any other checkout of the same project."
48
+ }
49
+ }
50
+ },
35
51
  "run": {
36
52
  "type": "object",
37
53
  "additionalProperties": true,
@@ -195,7 +211,7 @@
195
211
  "retro": {
196
212
  "type": "object",
197
213
  "additionalProperties": true,
198
- "description": "Optional. Governs what the retrospective does BEYOND writing to the project's own docs/superpowers/retro.md, which always happens. Omit it and nothing leaves the repository: silence arms nothing, exactly as it authorises no deploy.",
214
+ "description": "Optional. Governs what the retrospective does BEYOND writing to the project's own docs/evidence/retro.md, which always happens. Omit it and nothing leaves the repository: silence arms nothing, exactly as it authorises no deploy.",
199
215
  "properties": {
200
216
  "publish": {
201
217
  "type": "object",
@@ -61,7 +61,7 @@ that was never a row.
61
61
  Read all of them before writing anything:
62
62
 
63
63
  - the ladder walk's findings (above) — they may have added REQ rows
64
- - the brief's **REQ table** (`docs/superpowers/specs/<topic>-brief.md`)
64
+ - the brief's **REQ table** (`<artifacts>/specs/<topic>-brief.md`)
65
65
  - the **carry-over ledger** (`…-carryover.md`) — in full, every row
66
66
  - the plan and its task statuses
67
67
  - git log for the run's branch; the test suite's final output
@@ -70,7 +70,7 @@ Read all of them before writing anything:
70
70
 
71
71
  ## Output — the coverage table
72
72
 
73
- Write `docs/superpowers/specs/YYYY-MM-DD-<topic>-acceptance.md`:
73
+ Write `<artifacts>/specs/YYYY-MM-DD-<topic>-acceptance.md`:
74
74
 
75
75
  ```markdown
76
76
  # Acceptance — <topic>
@@ -177,7 +177,7 @@ whether the run was finished.
177
177
  ## The retrospective — the run's last act
178
178
 
179
179
  After the closing question, before the run is called done:
180
- [`retrospective.md`](retrospective.md), written to `docs/superpowers/retro.md`.
180
+ [`retrospective.md`](retrospective.md), written to `<artifacts>/retro.md`.
181
181
  Every run **stamps and prunes**; only a run that *diverged* writes an entry.
182
182
 
183
183
  The order is fixed, and it is a **dependency, not a preference** — step 2 reads the
@@ -163,7 +163,7 @@ it lands — `templates/hooks.example.json`, and read
163
163
  Only when more than one agent works the repository. Then the registers become shared
164
164
  state ([`documentation.md`](documentation.md) → *Registers are shared state*) and a
165
165
  coordination tool arbitrates: `guardedFiles` must list every register **plus
166
- `docs/DOCMAP.md` and `docs/superpowers/retro.md`**, which are equally shared and
166
+ `docs/DOCMAP.md` and `<artifacts>/retro.md`**, which are equally shared and
167
167
  equally lossy under a concurrent write.
168
168
 
169
169
  Without such a tool the run is **`ungated`** and must say so. The discipline still
@@ -23,7 +23,7 @@ docs/
23
23
  OPEN_QUESTIONS.md # … and its questions (OQ-####) — never delete a resolved row
24
24
  adr/
25
25
  NNNN-<slug>.md # the OTHER permitted decision home — one project uses ONE
26
- superpowers/
26
+ evidence/ # the artifact root — RESOLVED, see the note below
27
27
  retro.md # stage 10's last act — ONE per project, not per run
28
28
  backlog.md # the work-list BETWEEN runs — read at 0, resolved at 10
29
29
  verification.md # one row per shipped REQ; `Human` is a date or `never`
@@ -54,10 +54,39 @@ Naming: date-prefixed `YYYY-MM-DD-<topic>` slugs, one topic per file, kebab-case
54
54
  Brief, carry-over, design, plan and acceptance share the **same `<topic>` slug**, so the chain is traceable
55
55
  at a glance.
56
56
 
57
- > The `docs/superpowers/` directory name is this pipeline's historical convention
58
- > (kept so existing projects don't have to migrate) — **not a dependency on any
59
- > external skill**. A host project may relocate the root via its `CLAUDE.md`; keep
60
- > the shape, keep the slugs.
57
+ ### `<artifacts>/` — the root is resolved, not spelled
58
+
59
+ Every path above is written `<artifacts>/…`. That is not a placeholder you fill in by
60
+ hand: it is **resolved**, in this order, and the answer is the same for the validator,
61
+ the migration command and you.
62
+
63
+ 1. **`paths.artifacts` in `pipeline.json`** wins outright. Any relative path —
64
+ `docs/runs/`, `notes/pipeline/`, whatever this project already uses. Until v1.53.0
65
+ this file promised that a host project *may relocate the root* and nothing kept the
66
+ promise; the config key is what turned the sentence into a mechanism.
67
+ 2. **otherwise the first of `docs/evidence/`, then `docs/superpowers/`** that exists
68
+ **and carries a register** — a `retro.md`, `backlog.md`, `verification.md`, or a
69
+ `specs/`, `plans/`, `briefs/`, `retro/` directory. The new name is checked first, so
70
+ a project that moves one file at a time is never left split.
71
+ 3. **otherwise `docs/evidence/`** — the default for a project that has neither.
72
+
73
+ **Carrying a register is the whole difference between a root and a directory.** A
74
+ project may keep an unrelated `docs/evidence/` full of compliance material; adopting it
75
+ because the name matched would write a run's paperwork into somebody else's folder. When
76
+ the default lands on a directory like that, the resolver says so and the caller asks
77
+ rather than writing.
78
+
79
+ **`docs/superpowers/` is the name this pipeline used until 2026-08-13, and it is
80
+ supported, not deprecated.** A project already on it keeps it — forever, with no
81
+ warning on any run. The name was inherited from an unrelated pack whose own tests walk
82
+ the same path; it was never a dependency on that pack, and renaming the default is what
83
+ finally says so. Nothing migrates on its own: `npx task-pipeline migrate-artifacts`
84
+ moves a project that wants to move, `--dry-run` first, and a project that never runs it
85
+ is not behind.
86
+
87
+ Implementations: `bin/lib/artifact-root.js` (shipped) and `test/artifact_root.py` (the
88
+ validator). `test/artifact_root_test.py` runs both against one case table and fails when
89
+ they disagree — which is why one rule is allowed two implementations here.
61
90
 
62
91
  **Every** run keeps a **git-ignored** run ledger at `.task-pipeline/run.md`, seeded at
63
92
  stage 0 from [`../templates/run.md`](../templates/run.md). Three line shapes: a
@@ -84,7 +113,7 @@ whatever the context happens to hold.
84
113
 
85
114
  | Stage | Reads | From where |
86
115
  |---|---|---|
87
- | **0 Harvest** | the project's own knowledge about this task | code · the code graph (`graphify-out/`) · `CLAUDE.md`/`AGENTS.md` · `CONTEXT.md`/`docs/adr/` · `docs/` + `docs/ux/` · past briefs and carry-over ledgers · **the board** (`docs/superpowers/backlog.md`, open count quoted in the brief) · **the verification ledger** (`docs/superpowers/verification.md`, how many rows sit at `never`) · the retro's standing instructions **in full** · the wiki · any doc repo or hosted system the project names |
116
+ | **0 Harvest** | the project's own knowledge about this task | code · the code graph (`graphify-out/`) · `CLAUDE.md`/`AGENTS.md` · `CONTEXT.md`/`docs/adr/` · `docs/` + `docs/ux/` · past briefs and carry-over ledgers · **the board** (`<artifacts>/backlog.md`, open count quoted in the brief) · **the verification ledger** (`<artifacts>/verification.md`, how many rows sit at `never`) · the retro's standing instructions **in full** · the wiki · any doc repo or hosted system the project names |
88
117
  | **0 Inventory (1b)** | the documentation regime | `docs/DOCMAP.md` — registers, single homes, propagation matrix, gate commands, ratchet floors. Absent ⇒ seeded ([`adoption.md`](adoption.md)) |
89
118
  | **0 Reconcile (1c)** | intent vs as-built | git (how it *should* be) against the run record (how it *turned out*) |
90
119
  | **0 Grill** | the operator | the interview — every answer checked against the harvest, which is what makes it checkable rather than confident |
@@ -108,9 +137,9 @@ that has not read them is running the pipeline's defaults, not this project's.
108
137
  |---|---|---|---|
109
138
  | `CLAUDE.md` / `AGENTS.md` | commands, deploy path, house rules, which docs exist and where | 0 | 6–10 |
110
139
  | `docs/DOCMAP.md` | the decision home, each fact's single home, the propagation matrix, the gate and its ratchet floors | 0 (1b) | 9 |
111
- | `docs/superpowers/verification.md` | one row per shipped REQ, and the one column a machine may not fill: the date a **human** confirmed it, or `never` ([`verification.md`](verification.md)) | 0 | written at 8, required at 10 |
112
- | `docs/superpowers/backlog.md` | the project's work-list **between** runs — ids, the three priority inputs, state. Mutable; rows leave only into its *Closed* list ([`backlog.md`](backlog.md)) | 0 | re-derived at every iteration's end; resolved at 10 |
113
- | `docs/superpowers/retro.md` | standing instructions — the rules no check can decide. Capped at ten, **read in full**, stamped the moment one fires | 0 | pruned at 10 |
140
+ | `<artifacts>/verification.md` | one row per shipped REQ, and the one column a machine may not fill: the date a **human** confirmed it, or `never` ([`verification.md`](verification.md)) | 0 | written at 8, required at 10 |
141
+ | `<artifacts>/backlog.md` | the project's work-list **between** runs — ids, the three priority inputs, state. Mutable; rows leave only into its *Closed* list ([`backlog.md`](backlog.md)) | 0 | re-derived at every iteration's end; resolved at 10 |
142
+ | `<artifacts>/retro.md` | standing instructions — the rules no check can decide. Capped at ten, **read in full**, stamped the moment one fires | 0 | pruned at 10 |
114
143
  | `specs/<topic>-brief.md` → *Autonomy* | every pre-resolved decision; stages 1→10 **answer from it instead of asking** | 0 | 1–10 |
115
144
  | `specs/<topic>-carryover.md` | everything deferred, parked or half-done; appended the moment it is said | all | read in full at 10 |
116
145
  | `docs/ux/scenarios.md` | the source of truth for user-facing behaviour (super-ux) | 3 | 3, 7, 9, 10 |
@@ -130,13 +159,13 @@ them is a finding, not a tie-break ([`knowledge-sources.md`](knowledge-sources.m
130
159
  | 0 Intake | `specs/<topic>-brief.md` — incl. the **REQ table** (seed from `templates/brief.md`) | stages 2–5, 7, 10 |
131
160
  | 0→10 all | `specs/<topic>-carryover.md` — append-only ledger (seed from `templates/carryover.md`) | stage 10, in full |
132
161
  | 10 Acceptance | `specs/<topic>-acceptance.md` — every REQ with a status and evidence | the operator |
133
- | 10 Retro | `superpowers/retro.md` — standing instructions (max 10), the problem→cause→fix log, run stamps. Pruned **before** anything is added (`retrospective.md`) | **stage 0 of the next run**, in full |
162
+ | 10 Retro | `<artifacts>/retro.md` — standing instructions (max 10), the problem→cause→fix log, run stamps. Pruned **before** anything is added (`retrospective.md`) | **stage 0 of the next run**, in full |
134
163
  | 0 Inventory | `docs/DOCMAP.md` + the registers + `scripts/check-docs.sh` — seeded **only when absent**, and the seeding is the register's first entry ([`documentation.md`](documentation.md)) | every later stage; **stage 9** walks the matrix, **stage 10** proves the gate |
135
164
  | 0 Grill (domain) | `CONTEXT.md`, `docs/adr/NNNN-<slug>.md` — created **lazily**, only when a term resolves or a decision qualifies. Where `docs/adr/` **is** the register, entries carry the register's field set | stages 2–4 + the repo |
136
165
  | any stage | a register entry per settled thing, via the **Doc Loop** — recorded, resolved, propagated, committed with its id | the next run's harvest |
137
- | 8 Verification row | `docs/superpowers/verification.md` — one row per REQ the run shipped, written right after the deploy verification; `Human` starts at `never` ([`verification.md`](verification.md)) | stage 10 requires it; stage 0 of every later run reads it |
138
- | 10 Board resolution | `docs/superpowers/backlog.md` — every unresolved ledger row — homed `backlog` or still `open` — arrives with a real id, and the ledger row is updated to name it; priority re-derived ([`backlog.md`](backlog.md)) | the next run's harvest, and every loop iteration |
139
- | 10 Retro rotation | `docs/superpowers/retro/YYYY-QN.md` — entries older than five stamps, plus every retirement, each with its commit | queried by a later run's harvest |
166
+ | 8 Verification row | `<artifacts>/verification.md` — one row per REQ the run shipped, written right after the deploy verification; `Human` starts at `never` ([`verification.md`](verification.md)) | stage 10 requires it; stage 0 of every later run reads it |
167
+ | 10 Board resolution | `<artifacts>/backlog.md` — every unresolved ledger row — homed `backlog` or still `open` — arrives with a real id, and the ledger row is updated to name it; priority re-derived ([`backlog.md`](backlog.md)) | the next run's harvest, and every loop iteration |
168
+ | 10 Retro rotation | `<artifacts>/retro/YYYY-QN.md` — entries older than five stamps, plus every retirement, each with its commit | queried by a later run's harvest |
140
169
  | 2 Decompose | `specs/<topic>-modules.md` — module map, build order, contracts, per-module status (platforms only) | stages 3–10, every module's run |
141
170
  | 3 Spec | `specs/<topic>-design.md` — module dossier for a decomposed platform (+ links `docs/ux/*` for UI) | stage 4 |
142
171
  | 4 Plan | `plans/<topic>.md` | stage 5 |
@@ -180,5 +209,5 @@ test/validate.py # structural validator (npm test)
180
209
  package.json .gitignore
181
210
  README.md CHANGELOG.md LICENSE CLAUDE.md
182
211
  CONTRIBUTING.md SECURITY.md CODE_OF_CONDUCT.md
183
- docs/superpowers/{specs,plans}/ # this repo's own design history
212
+ <artifacts>/{specs,plans}/ # this repo's own design history
184
213
  ```
@@ -47,7 +47,7 @@ pass in each direction finds both.
47
47
 
48
48
  ## Seeded or picked up
49
49
 
50
- Stage 0's harvest reads `docs/superpowers/backlog.md` when it exists — it is a source
50
+ Stage 0's harvest reads `<artifacts>/backlog.md` when it exists — it is a source
51
51
  in the ledger like any other, and its **open count is quoted in the brief**, because a
52
52
  run that begins without knowing what is already queued will cheerfully re-discover it.
53
53
 
@@ -198,7 +198,7 @@ works a stale board for as long as the loop runs. One command, at the top of the
198
198
  iteration, recorded ([`knowledge-sources.md`](knowledge-sources.md) → *Carried-in
199
199
  claims*; [`learned.md`](learned.md) rule 16).
200
200
 
201
- **The work-list is `docs/superpowers/backlog.md`** ([`backlog.md`](backlog.md)), and the
201
+ **The work-list is `<artifacts>/backlog.md`** ([`backlog.md`](backlog.md)), and the
202
202
  other half of the same measurement is the exposure line ([`exposure.md`](exposure.md)).
203
203
  Counted at the top of the iteration, re-derived at the bottom — `age` moves on its own,
204
204
  so the re-derivation is the only moment the board stops being stale.
@@ -65,7 +65,7 @@ into its neighbor or move the disputed data to the module that truly owns it.
65
65
 
66
66
  ## The module map — the artifact
67
67
 
68
- Write `docs/superpowers/specs/YYYY-MM-DD-<topic>-modules.md` and commit it. It is
68
+ Write `<artifacts>/specs/YYYY-MM-DD-<topic>-modules.md` and commit it. It is
69
69
  the program's spine: every later run reads it, and its status column is how a
70
70
  resumed session knows where the program stopped.
71
71
 
@@ -160,7 +160,7 @@ explicit "stop and ask me here":
160
160
  | 7 Lint+deploy | lint command; deploy target and path; release automation on/off; deploy-from-main rule; **deploy authorization** |
161
161
  | 8 Post-deploy | where logs / health live (app name, endpoint, workflow) |
162
162
  | 9 Docs+wiki | which module docs / runbooks this change updates; wiki sync yes/no; **code-graph refresh yes/no** (`/graphify . --update` — the third close-out artifact) |
163
- | 10 Acceptance | who signs off; where deferred REQs are tracked (issue tracker, backlog); the **retro file** — does `docs/superpowers/retro.md` exist, and are its standing instructions in force for this run ([`retrospective.md`](retrospective.md)) |
163
+ | 10 Acceptance | who signs off; where deferred REQs are tracked (issue tracker, backlog); the **retro file** — does `<artifacts>/retro.md` exist, and are its standing instructions in force for this run ([`retrospective.md`](retrospective.md)) |
164
164
 
165
165
  **Deploy authorization has a hard floor.** Deploy and publish are outward and
166
166
  irreversible, so a vague "just do everything" authorizes nothing. A standing
@@ -254,7 +254,7 @@ that shrank without anyone deciding it should.
254
254
 
255
255
  Everything resolved goes into the **task brief**, seeded from
256
256
  [`templates/brief.md`](../templates/brief.md) and committed to
257
- `docs/superpowers/specs/YYYY-MM-DD-<topic>-brief.md` — scope, **the REQ table**,
257
+ `<artifacts>/specs/YYYY-MM-DD-<topic>-brief.md` — scope, **the REQ table**,
258
258
  **the phase-1 source ledger**, users, UI verdict, constraints, locked decisions,
259
259
  the autonomy table, done-criteria, open assumptions. Seed the template only when
260
260
  the file is absent; never overwrite an existing brief.
@@ -47,9 +47,9 @@ makes the grill's answers *checkable* instead of merely confident.
47
47
  | 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 |
48
48
  | 4b | **The task register, for its *state*** | `docs/ROADMAP.md`, a board, a backlog, the tracker `CLAUDE.md` names | **what is open right now** — read with a command, never from memory; see *Carried-in claims* |
49
49
  | 5 | **Product/UX docs** | `docs/ux/` (super-ux chain), `README`, runbooks | user-facing behavior that is already specified |
50
- | 6 | **Pipeline history** | `docs/superpowers/specs/`, `plans/`, past `-carryover.md` | what a previous run of this pipeline decided or deferred |
51
- | 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 |
52
- | 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 |
50
+ | 6 | **Pipeline history** | `<artifacts>/specs/`, `plans/`, past `-carryover.md` | what a previous run of this pipeline decided or deferred |
51
+ | 7 | **The retro, in force** | `<artifacts>/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 |
52
+ | 7a | **The retro archive** | `<artifacts>/retro/YYYY-QN.md` | *have we been bitten by this class before?* — **queried** by the task's nouns, never read end to end |
53
53
  | 8 | **The knowledge wiki** | see below | distilled cross-project knowledge, prior sessions, why decisions were made |
54
54
  | 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 |
55
55
  | 10 | **Hosted doc systems the project names** | Notion / Confluence / Google Docs referenced in the project | the same, when the team keeps them there |
@@ -73,7 +73,7 @@ Rules for the list:
73
73
 
74
74
  ## The retro's standing instructions — an instruction source, not background
75
75
 
76
- `docs/superpowers/retro.md` ([`retrospective.md`](retrospective.md)) is the one
76
+ `<artifacts>/retro.md` ([`retrospective.md`](retrospective.md)) is the one
77
77
  harvested source whose binding part is **read in full rather than queried**: the
78
78
  standing instructions are capped at ten precisely so that this is cheap, and the run
79
79
  stamps are one line each. Its narrative log is queried, not read — an uncapped section