@gobing-ai/spur 0.3.78 → 0.3.80

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/spur",
3
- "version": "0.3.78",
3
+ "version": "0.3.80",
4
4
  "description": "Spur CLI — local-first harness for mainstream coding agents: constraint checking, workflow orchestration, agent health, and history analytics. Bun-native; exposes the `spur` command.",
5
5
  "keywords": [
6
6
  "spur",
@@ -53,14 +53,14 @@
53
53
  },
54
54
  "devDependencies": {
55
55
  "@commander-js/extra-typings": "^14.0.0",
56
- "@gobing-ai/ts-db": "^0.4.60",
57
- "@gobing-ai/ts-ai-runner": "^0.4.60",
58
- "@gobing-ai/ts-dual-workflow-engine": "^0.4.60",
59
- "@gobing-ai/ts-infra": "^0.4.60",
60
- "@gobing-ai/ts-llm-jsonl-importer": "^0.4.60",
61
- "@gobing-ai/ts-rule-engine": "^0.4.60",
62
- "@gobing-ai/ts-runtime": "^0.4.60",
63
- "@gobing-ai/ts-utils": "^0.4.60",
56
+ "@gobing-ai/ts-db": "^0.4.62",
57
+ "@gobing-ai/ts-ai-runner": "^0.4.62",
58
+ "@gobing-ai/ts-dual-workflow-engine": "^0.4.62",
59
+ "@gobing-ai/ts-infra": "^0.4.62",
60
+ "@gobing-ai/ts-llm-jsonl-importer": "^0.4.62",
61
+ "@gobing-ai/ts-rule-engine": "^0.4.62",
62
+ "@gobing-ai/ts-runtime": "^0.4.62",
63
+ "@gobing-ai/ts-utils": "^0.4.62",
64
64
  "@types/bun": "1.3.14",
65
65
  "@types/figlet": "^1.7.0",
66
66
  "@types/node-notifier": "8.0.5",
@@ -171,10 +171,12 @@ Commands above are thin wrappers; the actual logic lives in `skills/`. The spine
171
171
  dispatches five competency skills by function — design (`sp:sys-architecture`), decomposition
172
172
  (`sp:spec-decomposition`), implementation (`sp:code-implementation`), testing (`sp:code-testing`),
173
173
  and verification (`sp:code-verification`) — plus a CLI facade (`sp:spur-cli`, one reference per
174
- `spur` noun) and standalone technique skills (`sp:next-router`, `sp:test-driven-development`, `sp:brainstorm`,
175
- `sp:wayfinder`, `sp:sys-debugging`, `sp:code-review`, `sp:code-simplification`, `sp:code-improvement`,
176
- `sp:parallel-execution`, `sp:branch-workflow`, `sp:doc-evolve`, `sp:dogfood-testing`,
177
- `sp:daily-summary`, `sp:reverse-engineering`, `sp:issue-finding`, `sp:conflict-finding`,
174
+ `spur` noun) and standalone technique skills (`sp:next-router`, `sp:next-feature`,
175
+ `sp:test-driven-development`, `sp:source-driven-development`, `sp:doubt-driven-development`,
176
+ `sp:brainstorm`, `sp:wayfinder`, `sp:sys-debugging`, `sp:code-review`, `sp:pr-reviewing`,
177
+ `sp:functional-review`, `sp:code-simplification`, `sp:code-improvement`, `sp:parallel-execution`,
178
+ `sp:branch-workflow`, `sp:doc-evolve`, `sp:dogfood-testing`, `sp:daily-summary`,
179
+ `sp:reverse-engineering`, `sp:history-anatomy`, `sp:issue-finding`, `sp:conflict-finding`,
178
180
  `sp:indexed-context`, `sp:session-review`, `sp:redesign-web-ui`). See
179
181
  [skills/spur-dev/SKILL.md](skills/spur-dev/SKILL.md)'s Step routing table for which skill owns which
180
182
  pipeline step.
@@ -215,6 +217,7 @@ plugins/sp/
215
217
  │ │ └── references/routing-table.md
216
218
  │ ├── parallel-execution/ # Fan-out decision framework + patterns
217
219
  │ │ └── references/{fan-out-patterns, result-synthesis}.md
220
+ │ ├── pr-reviewing/ # GitHub PR review loop backing /sp:dev-pr-review
218
221
  │ ├── source-driven-development/ # Source-first API/contract verification (SKILL.md only)
219
222
  │ ├── spec-decomposition/ # Feature/spec → task-batch competency
220
223
  │ │ └── references/decomposition.md
@@ -255,6 +258,8 @@ plugins/sp/
255
258
  ├── agents/ # 4 specialist subagents (expert-spur, super-coder, super-planner, super-reviewer)
256
259
  ├── hooks/ # hooks.json + task-write-guard.{ts,test.ts} + context-{session-start,post-tool,session-stop}.ts
257
260
  │ # + careful-guard.{ts,test.ts} + context-hooks.test.ts + token-estimate.test.ts
261
+ │ # + shared policy modules: agent-hint.ts, destructive-policy.{ts,test.ts}, task-file-policy.{ts,test.ts}
262
+ │ # + pi/guard-extension.{ts,test.ts} (plugin.json `extensions.pi` entry point)
258
263
  ├── scripts/ # Executable helpers, split from prompts (ADR-031) — validate-commands.ts (thin-wrapper validator), batch-preflight.ts + scripts/<skill>/
259
264
  │ # (daily-summary: {daily-summary, logger}.ts; dogfood-testing: {detect-pipeline-driving, validate-report}.ts)
260
265
  ├── tests/ # Plugin tests — command-contract.test.ts + skill-structure.test.ts + batch-preflight.test.ts + per-skill suites
@@ -318,13 +323,13 @@ surface or run one workflow. All skills target the same five core platforms: `cl
318
323
  | `daily-summary` | 1.0.0 | Daily summary report generator — orchestrates ccusage CLI + git history into structured markdown summaries |
319
324
  | `doc-evolve` | 1.0 | Key-document evolution per `docs/99_PROJECT_CONSTITUTION.md` — drift audits, same-commit sync checks, frontmatter-contract verification, machine-appended lessons |
320
325
  | `reverse-engineering` | 1.1 | Codebase analysis / HLD generation / audit — depth-driven reverse engineering with orthogonal mode, focus, and format controls; backs `/sp:dev-reverse` |
321
- | `issue-finding` | 1.1 | Session-log forensics — multi-source discovery, bottleneck ranking, optional topic focus, CLI-gated fix task generation; **legacy path** — superseded by `history-anatomy` for indexed reporting; backs no current command; directly invocable as sp:issue-finding |
326
+ | `issue-finding` | 2.0 | Session-log forensics — multi-source discovery, bottleneck ranking, optional topic focus, CLI-gated fix task generation; **legacy path** — superseded by `history-anatomy` for indexed reporting; backs no current command; directly invocable as sp:issue-finding |
322
327
  | `conflict-finding` | 1.0 | Authority-aware semantic audit — four-pillar (source/task/feature/authority) conflict discovery, claim-specific authority resolution, reproducible evidence, confirmed owner-routed remediation; backs `/sp:dev-find-conflict` |
323
328
  | `next-feature` | 1.0 | Prompt-first feature frontier prioritizer — sync-first precondition, B3 actionability gate (cited, never restated), tiered rubric over measured signals, D1–D4 defect proposals conforming to the restructure map schema; backs `/sp:dev-find-next` |
324
329
  | `pr-reviewing` | 1.0 | GitHub Codex PR review — PR prepare/reuse, `@codex review` request with per-HEAD dedupe, bounded polling, findings normalization, validated fix + re-review; spine SSOT `pr-review.yaml` + `scripts/pr-reviewing.ts`; backs `/sp:dev-pr-review` |
325
330
  | `indexed-context` | 1.0 | Cross-agent project context — anatomy/learnings/pitfalls/buglog/memory in `.spur/context/`; hook-tracked token-ledger; graceful degradation on agents without hooks |
326
331
  | `history-anatomy` | 1.0 | Diagnostic interpretation owner over already-imported history — daily/ad-hoc mode contract, closed finding taxonomy, twelve-section report contract, `enrich`/`validate` rubrics; no workflow launch, no JSONL fallback, no corpus mutation |
327
- | `session-review` | 1.0 | Inline review of the active coding-agent session — compact outcomes, evidence-backed resolved/open issue classification, proposal-only improvements, and next actions; no workflow, import, delegation, or mutation |
332
+ | `session-review` | 1.1 | Inline review of the active coding-agent session — compact outcomes, evidence-backed resolved/open issue classification, proposal-only improvements, and next actions; no workflow, import, delegation, or mutation |
328
333
  | `redesign-web-ui` | 1.0 | Existing-UI visual upgrade — audit generic AI fingerprints, apply in-stack polish against `DESIGN.md` / live tokens, verify behavior and viewports; does not migrate frameworks |
329
334
 
330
335
  #### Bounded coexistence and retirement gate — `sp:issue-finding` (HA-S1 0661)
@@ -418,7 +423,7 @@ the pipeline's Phase 7 review step.
418
423
  | ---------------- | ------------ | ----------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------- |
419
424
  | `expert-spur` | expert | `sp:spur-cli` | green | "create tasks", "feature lifecycle", "add a rule", "author a workflow" |
420
425
  | `super-coder` | builder | `sp:sys-architecture` + `sp:code-implementation` + `sp:code-testing` + `sp:sys-debugging` | blue | "implement this", "write the code", "fix this bug", "design the architecture" |
421
- | `super-planner` | orchestrator | `sp:spur-dev` + `sp:dogfood-testing` | green | "run this task end to end", "run all tasks", "run the batch", "runall" |
426
+ | `super-planner` | orchestrator | `sp:spur-dev` + `sp:parallel-execution` + `sp:dogfood-testing` + `sp:next-router` | green | "run this task end to end", "run all tasks", "run the batch", "runall" |
422
427
  | `super-reviewer` | reviewer | `sp:code-verification` + `sp:functional-review` + `sp:code-improvement` | crimson | "review this", "check the code", "SECUA review", "run task 0042 through review" |
423
428
 
424
429
  Each agent has:
@@ -97,7 +97,8 @@ HITL gate unless `--auto` was passed.
97
97
  - [ ] Establish scope first: WBS mode (task diff) or path mode (source glob). Derive the diff
98
98
  scope the same way `sp:code-verification` Step 3 does.
99
99
  - [ ] Dispatch each requested dimension to its owning skill — do not inline the review logic.
100
- - [ ] Merge findings into a single ranked report (severity: blocker > major > minor > advisory).
100
+ - [ ] Merge findings into a single ranked report, emitting native priority cells
101
+ (`P1 (blocker)` > `P2 (major)` > `P3 (minor)` > `P4 (advisory)` — see Output Format).
101
102
  - [ ] In pipeline mode, write the merged report to the task's `## Review` section via
102
103
  `spur task update <wbs> --section Review --from-file`; in standalone mode, emit as output.
103
104
  - [ ] Cite `file:line` evidence for every finding — no vague "implemented correctly."
@@ -109,6 +110,8 @@ HITL gate unless `--auto` was passed.
109
110
  - [ ] Never edit `task-pipeline.yaml` or reach into a pipeline step.
110
111
  - [ ] Never auto-approve a HITL gate unless `--auto` was passed.
111
112
  - [ ] Never soften a FAIL to PARTIAL, or PARTIAL to PASS, to avoid surfacing.
113
+ - [ ] Never emit a word-only Severity cell, an empty priority scaffold, or a `##`/`###` heading
114
+ inside a `### Review` body — all three fail the existing checkers.
112
115
  - [ ] Never skip a dimension the operator requested with `--focus`.
113
116
 
114
117
  ## Definition of Done Housekeeping
@@ -120,22 +123,44 @@ enforcement checklist. Reference:
120
123
 
121
124
  ## Output Format
122
125
 
126
+ ### Priority vocabulary (task 0818 R3)
127
+
128
+ Emit priorities **natively** — the consumer (`hasPopulatedPriorityTable`,
129
+ `packages/app/src/services/task-check.ts`) requires a `P1`–`P4` cell, and a word-only severity cell
130
+ fails it. One explicit mapping, no transcription step anywhere downstream:
131
+
132
+ | Priority cell | Severity | Meaning |
133
+ | --- | --- | --- |
134
+ | `P1 (blocker)` | blocker | Ships broken or unsafe; blocks the verdict |
135
+ | `P2 (major)` | major | Real defect or structural problem; must be dispositioned |
136
+ | `P3 (minor)` | minor | Localized issue; fix or accept explicitly |
137
+ | `P4 (advisory)` | advisory | Observation, non-blocking |
138
+
139
+ Severity words stay visible in the same cell — the mapping adds the machine-readable label, it does
140
+ not replace the semantics.
141
+
142
+ **Section-relative headings.** In pipeline mode the report body is written *into* the task's
143
+ `### Review` section, so every heading inside it MUST be `####` or deeper. A `##`/`###` heading in
144
+ the body becomes a new top-level task section and corrupts the document. In standalone mode
145
+ (emitted as output, not written to a task) the same body may be rendered one level shallower.
146
+
123
147
  ```markdown
124
- ## Review Report — <wbs|path>
148
+ #### Review Report — <wbs|path>
125
149
 
126
150
  **Scope:** <wbs diff | path glob>
127
151
  **Dimensions:** functional, security, efficiency, correctness, usability, architecture
128
152
  **Verdict:** PASS | PARTIAL | FAIL
129
153
 
130
- ### Findings (ranked)
154
+ ##### Findings (ranked)
131
155
 
132
- | # | Severity | Dimension | Finding | Location |
156
+ | # | Priority | Dimension | Finding | Location |
133
157
  |---|----------|-----------|---------|----------|
134
- | 1 | blocker | security | SQL injection in query builder | `src/api/users.ts:42` |
135
- | 2 | major | architecture | Shallow pass-through UserService | `src/services/users.ts:15` |
136
- | 3 | minor | correctness | Missing error branch in createUser | `src/api/users.ts:48` |
158
+ | 1 | P1 (blocker) | security | SQL injection in query builder | `src/api/users.ts:42` |
159
+ | 2 | P2 (major) | architecture | Shallow pass-through UserService | `src/services/users.ts:15` |
160
+ | 3 | P3 (minor) | correctness | Missing error branch in createUser | `src/api/users.ts:48` |
161
+ | 4 | P4 (advisory) | usability | `createUser` error text omits the field name | `src/api/users.ts:51` |
137
162
 
138
- ### Functional Traceability
163
+ ##### Functional Traceability
139
164
 
140
165
  | Req | Status | Evidence |
141
166
  |-----|--------|----------|
@@ -145,6 +170,16 @@ enforcement checklist. Reference:
145
170
  **Next:** <one-line action>
146
171
  ```
147
172
 
173
+ **No findings.** Never invent a defect to populate the table. Emit one substantive `P4 (advisory)`
174
+ row that states what was reviewed and what was found — placeholder cells (empty, `—`, `n/a`) are
175
+ rejected by the checker, and so they should be:
176
+
177
+ ```markdown
178
+ | # | Priority | Dimension | Finding | Location |
179
+ |---|----------|-----------|---------|----------|
180
+ | 1 | P4 (advisory) | — | No P1–P3 findings: 6 changed files reviewed across all six dimensions; R1–R3 traceable to tests | `packages/app/src/workflow/proof-input-fingerprint.ts:102-160` |
181
+ ```
182
+
148
183
  With `--json`, emit the same shape as a JSON object for machine consumption.
149
184
 
150
185
  ## Out of scope
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sp",
3
- "version": "0.3.78",
3
+ "version": "0.3.80",
4
4
  "description": "Spur — a local-first harness engineering toolkit that wraps mainstream coding agents with constraint checking, workflow orchestration, and history analytics.",
5
5
  "extensions": {
6
6
  "pi": ["./hooks/pi/guard-extension.ts"]
@@ -282,7 +282,8 @@ function stripAcWrappers(title: string): string {
282
282
  * Normalize an AC identity to its canonical key, mirroring the documented
283
283
  * matching behavior of feature-check `rowMatchesScenario` + ac-style-guide
284
284
  * "Four accepted id forms" (exact/bare title, `Scenario:` prefix, bracket
285
- * tags, `AC-N` ordinal) without importing that private matcher or adopting
285
+ * tags, `AC-N` ordinal) plus the task-side bold-trajectory paragraph
286
+ * (0817 R3), without importing that private matcher or adopting
286
287
  * its permissive trailing-Gherkin fallback (0804 R4). Comparison is
287
288
  * case/quote/whitespace-insensitive. A paraphrase normalizes differently
288
289
  * and still fails.
@@ -307,7 +308,7 @@ function normalizeAcTitle(title: string): string {
307
308
  * A checklist-declared spelling always wins over the positional alias.
308
309
  */
309
310
  interface AcIdentityIndex {
310
- /** normalized canonical title → a declared spelling (label, token, or title). */
311
+ /** normalized canonical title → a declared spelling (label, token, title, or bold trajectory). */
311
312
  readonly byTitle: Map<string, string>;
312
313
  /** AC-N → task scenario title at that 1-based ordinal. */
313
314
  readonly taskScenarios: string[];
@@ -331,6 +332,19 @@ function buildAcIdentityIndex(taskContent: string, featureContent: string | null
331
332
  const leading = label.split(/\s+/)[0] ?? '';
332
333
  if (leading && leading !== label) declareIdentity(leading);
333
334
  }
335
+ // Bold-trajectory form (task 0817 R3): answers may cite an AC by a bare
336
+ // `**AC id**` paragraph (house style for long/complex ids). Only whole-line
337
+ // bold spans count — the line-anchored lazy regex rejects lines with two
338
+ // spans, keeping interpolated bold text out of the index. The head (text
339
+ // before the first colon) is declared like a checklist label, mirroring
340
+ // the `(?::|$)` label extraction above.
341
+ for (const m of section.matchAll(/^\*\*(.+?)\*\*\s*$/gm)) {
342
+ const inner = (m[1] ?? '').trim();
343
+ if (!inner) continue;
344
+ declareIdentity(inner);
345
+ const head = inner.split(':')[0]?.trim() ?? '';
346
+ if (head && head !== inner) declareIdentity(head);
347
+ }
334
348
  const scenarioTitles = (content: string): string[] =>
335
349
  [...content.matchAll(/^[ \t]*Scenario:\s*(.+)\s*$/gm)].map((m) => (m[1] ?? '').trim()).filter((t) => t !== '');
336
350
  const taskScenarios = scenarioTitles(sectionBetween(taskContent, 'Acceptance Criteria'));
@@ -348,6 +362,10 @@ type AcIdentityResolution = { ok: true; canonical: string } | { ok: false; error
348
362
  * alias — accepted only against a real scenario ordinal, and refused with an
349
363
  * actionable diagnostic when task and feature ordinals disagree. Undeclared
350
364
  * `ACn` tokens, paraphrases and invented ordinals never resolve.
365
+ * `ACn` tokens, paraphrases and invented ordinals never resolve.
366
+ *
367
+ * Declared forms recognized in the index include the bold-trajectory
368
+ * `**AC id**` paragraph (task 0817 R3); the AC-N failure hint names it.
351
369
  */
352
370
  function resolveAcIdentity(rowId: string, index: AcIdentityIndex): AcIdentityResolution {
353
371
  const canonical = index.byTitle.get(normalizeAcTitle(rowId));
@@ -365,7 +383,7 @@ function resolveAcIdentity(rowId: string, index: AcIdentityIndex): AcIdentityRes
365
383
  ok: false,
366
384
  error:
367
385
  `AC id "${rowId}" uses the AC-${n} positional alias but no scenario exists at that ordinal ` +
368
- '(task scenario list and linked-feature scenario list) — cite the exact scenario title or checklist label',
386
+ '(task scenario list and linked-feature scenario list) — cite the exact scenario title, checklist label, or a bare `**AC id**` paragraph',
369
387
  };
370
388
  }
371
389
  if (candidates.length > 1) {
@@ -94,6 +94,12 @@ Resolve `<scope>` and `--pillar`; confirm the repository root; establish **audit
94
94
  numbered-document mutation of any kind. With `--resolve`, no write happens until a repair set is
95
95
  presented, explicitly confirmed, and freshness-revalidated.
96
96
 
97
+ Validate every enum flag against the domain declared by the command surface
98
+ (`plugins/sp/commands/dev-find-conflict.md`): `--pillar` ∈ `source|tasks|features|authority|all`,
99
+ `--mode` ∈ `adaptive|full`, `--agent` ∈ `inline|auto|name`. An out-of-domain value **refuses** the
100
+ audit before any discovery work — report the received value, the flag's valid domain, and stop;
101
+ never silently coerce or ignore it. Only `<scope>` is free-form and exempt from this check.
102
+
97
103
  ### Step 2 — Discover local authority
98
104
 
99
105
  Read entry/process rules (`AGENTS.md`, `docs/99_PROJECT_CONSTITUTION.md`) before interpreting any
@@ -166,6 +166,6 @@ Read the skill file and follow the workflow manually.
166
166
  ## Additional Resources
167
167
 
168
168
  - **Script source:** [scripts/daily-summary/daily-summary.ts](../../scripts/daily-summary/daily-summary.ts) — CLI implementation
169
- - **Tests:** [tests/daily-summary.test.ts](tests/daily-summary.test.ts) — unit coverage for parsing, date ranges, markdown output
169
+ - **Tests:** [tests/daily-summary/daily-summary.test.ts](../../tests/daily-summary/daily-summary.test.ts) — unit coverage for parsing, date ranges, markdown output
170
170
  - **Related skills:** `sp:dev-handover` (blocker handoff), `sp:dev-changelog` (commit-based changelog), `sp:spur-cli` (task management)
171
171
  - **Upstream CLI:** [ccusage](https://github.com/ryoppippi/ccusage) — AI agent token usage reporter
@@ -4,7 +4,7 @@ description: "Evolve docs/00-05 + AGENTS.md per docs/99_PROJECT_CONSTITUTION.md:
4
4
  license: Apache-2.0
5
5
  metadata:
6
6
  author: spur
7
- version: "1.0"
7
+ version: "1.1"
8
8
  platforms: "claude-code,codex,openclaw,opencode,antigravity"
9
9
  interactions:
10
10
  - reviewer
@@ -30,17 +30,17 @@ this skill applies it.
30
30
 
31
31
  **Read `docs/99_PROJECT_CONSTITUTION.md` first.** It is the single source of truth for *how* these
32
32
  files are maintained (authority §2, doc map §4.1, frontmatter contracts §4.3, sync triggers §5,
33
- per-file edit rules §6, the audit §7, lessons §8). This skill is a runbook for executing §5/§7/§8;
33
+ per-file edit rules §6, the audit §7, lesson routing §8). This skill is a runbook for executing §5/§7/§8;
34
34
  when the two disagree, the constitution wins and this skill is the bug.
35
35
 
36
36
  ## Operations
37
37
 
38
38
  | Operation | What it does | Constitution authority | Deterministic helper |
39
39
  | --------- | ------------ | ---------------------- | -------------------- |
40
- | **drift-audit** | Reality (code/shipped) vs. what a key file says, and cross-doc contradictions | §7 (the 8-item checklist) | `rg` the real CLI/config surface; diff vs `04`/`AGENTS.md`/`00` |
41
- | **sync-check** | Did a change touch the docs its trigger obligates in the same commit? | §5 (triggers T1–T8) | git diff of code/config vs. the matching doc edit |
40
+ | **drift-audit** | Reality (code/shipped) vs. what a key file says, and cross-doc contradictions | §7 | `rg` the real CLI/config surface; diff vs `04`/`AGENTS.md`/`00` |
41
+ | **sync-check** | Did a change touch the docs its trigger obligates in the same commit? | §5 (applicable triggers) | git diff of code/config vs. the matching doc edit |
42
42
  | **contract-verify** | Each doc's frontmatter matches its §4.1 row; `updated_at` is plausible | §4.3 | parse frontmatter; compare `owns`/`authority` vs §4.1; `git log` recency |
43
- | **lesson-append** | Append a dated lesson; dedup; promote recurring ones to a rule | §8 | format-check the line; `rg` for an equivalent before adding |
43
+ | **lesson-append** | Record a useful lesson in existing project context; deduplicate; propose governance changes separately | §8 | format-check the line; `rg` for an equivalent before adding |
44
44
 
45
45
  No thin `dev-docs` command wrapper exists (`dev-operations.md §7`). Invoke this skill directly for
46
46
  an audit or a lesson, or reach it via `/sp:dev-plan`'s docs step and `/sp:spur-init`'s `customize`.
@@ -84,48 +84,40 @@ stubs filled or deliberately documented; `bun run lint` passes where applicable.
84
84
  Walk the §7 checklist. Each item pairs a detection command with the doc it validates:
85
85
 
86
86
  ```bash
87
- # Real CLI surface vs. what 04 / AGENTS.md / 00 claim
87
+ # Real CLI surface vs. owning non-UI contracts
88
88
  rg -n "\.command\('" apps/cli/src/commands/ # the true verb list
89
- rg -n '^#### `spur ' docs/04_DESIGN.md # documented commands
89
+ rg -n '^#### `spur ' docs/design/ # documented commands
90
90
  # → diff the two sets; a verb in code but not in 04 is T3 drift.
91
91
 
92
92
  # 05 status rows vs. reality
93
- rg -n '✅|🔶|⏳|💤' docs/05_FEATURES.md # claimed states
93
+ cat docs/features/INDEX.md # generated feature states
94
94
  # → spot-check each ✅/🔶 against code; confirm no ⏳ quietly shipped.
95
95
 
96
96
  # 02 phase bullets name real things (no dead names)
97
97
  # 03 module descriptions vs. the real tree
98
- fd -t d -d 2 . apps packages # real modules
98
+ rg --files apps packages # real modules
99
99
  # Frontmatter contracts (see contract-verify) + updated_at recency
100
100
  git log -1 --format='%ci' -- docs/04_DESIGN.md # last touch vs. recent surface changes
101
101
  ```
102
102
 
103
- **Repair protocol (§7, always this order):** fix the **authoritative** doc first (append-only files
104
- by dated amendment, never rewrite), then the derived docs that restate/sequence it, then
105
- `AGENTS.md`, then **flag what drifted and why** in the commit/task (a silent fix hides the systemic
106
- cause). Anything systemic becomes a §8 lesson or, if it recurs, a new §6 rule.
103
+ **Repair protocol (§7):** fix the authoritative statement first, then affected detail/index/entry
104
+ files. Preserve ADR numbers, original titles/dates and decision history; editorial condensation
105
+ follows §6.1, while actual reversals need a superseding decision. Record findings in a task/report.
106
+ Routine lessons go to existing learning/context storage (§8); no automatic constitution edits.
107
107
 
108
108
  Output a **drift report**: per finding, `{ doc, what code says, what the doc says, authority, repair
109
109
  }`. A clean report lists the checks run and that each returned no delta.
110
110
 
111
111
  ## sync-check (§5)
112
112
 
113
- Given a change (a diff, or a just-finished task), check the same-commit obligations:
113
+ Read the live constitution §5; it owns the trigger table. Classify each changed fact, identify
114
+ its owner, and inspect the diff to confirm required synchronization. Update an index or AGENTS.md
115
+ only when its own facts changed. A satellite edit with an unchanged index pointer is synchronized.
114
116
 
115
- | If the change… | Trigger | …the same commit must touch |
116
- | -------------- | ------- | --------------------------- |
117
- | adds/changes a command, flag, config key, env var, schema, DTO | **T3** | `04_DESIGN` + the `AGENTS.md` surface block |
118
- | ships a feature or changes its state | **T4** | its `05` row (+ a `01` scope row if new surface) |
119
- | makes a new cross-cutting decision (or reverses one) | **T1** | `00` first (dated), then `03`, `01` if scope shifts |
120
- | would contradict an existing ADR | **T2** | **stop** — add the superseding ADR entry first |
121
- | completes/reorders a phase | **T5** | `02` (the real shipped name) |
122
- | adds/cuts/defers scope | **T6** | `01` + placement in `02` |
123
- | changes the doc map or process | **T7** | this file → re-sync `AGENTS.md` (§4.4) → siblings |
124
- | plans a multi-wave batch | **T8** | schedule "doc sync" as an explicit work item |
125
-
126
- Detection is a diff read: list the changed code/config paths, map each to its trigger, then confirm
127
- the obligated doc was edited in the same change. A surface change with no `04` edit is the canonical
128
- miss (the one this whole §5 table exists to prevent).
117
+ T1 applies only to real architectural choices passing §6.1. Feature approvals, task completion,
118
+ bugfixes restoring an existing contract and verification receipts do not justify ADR entries.
119
+ T7 applies only to operator-authorized governance corrections under §6.8; a routine doc edit or
120
+ lesson does not justify touching the constitution. Portable changes include in-scope init templates.
129
121
 
130
122
  ## contract-verify (§4.3)
131
123
 
@@ -140,19 +132,13 @@ stale given recent commits?"
140
132
 
141
133
  ## lesson-append (§8)
142
134
 
143
- Append a lesson to the right per-file section of §8:
144
-
145
- ```
146
- - [YYYY-MM-DD] <project>: <lesson — what went wrong / what to do instead>
147
- ```
135
+ Read constitution §8 for the existing project's destination. Record a useful, deduplicated
136
+ lesson in existing learning/context storage or a dated report, with evidence. Do not append
137
+ lessons to the constitution. Do not create a second learning ledger when one already exists.
148
138
 
149
- - **Low threshold** when in doubt, append. **Check for an equivalent first** (`rg` the section);
150
- bump its date instead of duplicating.
151
- - **Promotion is the only sanctioned deletion:** a lesson that recurs or hardens into practice is
152
- promoted into a §6 rule (or §5 trigger) and removed from §8. Lessons are the inbox; §5/§6 are the
153
- law.
154
- - Lessons carry project provenance (this file is byte-identical across projects except §8 + the §3
155
- tool column) — a lesson from one project is a warning, not yet a law, for the others.
139
+ A recurring lesson may justify proposing a document-governance correction; apply it only within
140
+ operator-authorized §6.8 scope. Task receipts remain in task records. Fresh project templates
141
+ contain neither inherited lessons nor fabricated decisions/status claims.
156
142
 
157
143
  ## What this skill is NOT
158
144
 
@@ -15,41 +15,33 @@ it enforces; the skill never invents process.
15
15
 
16
16
  | Operation | Authority § | What "done" means |
17
17
  | --------- | ----------- | ----------------- |
18
- | drift-audit | §7 | the 8-item §7 checklist run, each backed by a command; report lists deltas (or the zero-delta commands) |
19
- | sync-check | §5 (T1–T8) | every changed surface mapped to its trigger; the obligated doc confirmed edited in the same change |
18
+ | drift-audit | §7 | the affected §7 checks run, each backed by a command; report lists deltas (or the zero-delta commands) |
19
+ | sync-check | §5 (applicable §5 triggers) | every changed surface mapped to its trigger; the obligated doc confirmed edited in the same change |
20
20
  | contract-verify | §4.3 (+ §4.1) | each doc's frontmatter `owns`/`authority` matches its §4.1 row; `updated_at` plausible |
21
- | lesson-append | §8 | a dedup'd, correctly-formatted dated line in the right per-file section |
21
+ | lesson-append | §8 | a deduplicated lesson in existing learning/context storage, never appended to 99 |
22
22
 
23
23
  ## drift-audit — §7 checklist → detection commands
24
24
 
25
25
  | §7 item | Detection (deterministic) | Authoritative doc |
26
26
  | ------- | ------------------------- | ----------------- |
27
- | Real CLI surface vs docs | `rg -n "\.command\('" apps/cli/src/commands/` vs `rg -n '^#### \`spur ' docs/04_DESIGN.md` | `04` + `AGENTS.md` surface, `00` committed-surface |
28
- | `05` ✅/🔶 spot-check; no quietly shipped | `rg -n '✅\|🔶\|⏳\|💤' docs/05_FEATURES.md`, then check each against code | `05` |
27
+ | Real CLI surface vs docs | Compare source-local help/registrations with owning `docs/design/` contracts | `04` satellites |
28
+ | Feature state matches evidence | Read the feature tool's generated index, then inspect affected acceptance evidence | `05` / feature records |
29
29
  | Every shipped surface has a `01` scope row | surface set (above) vs `rg` of `01` scope table | `01` |
30
30
  | `02` phase bullets name real things | read `02` current-phase bullets; grep each name in code/docs | `02` |
31
- | `03` modules vs real tree | `fd -t d -d 2 . apps packages` vs `03` module list | `03` |
31
+ | `03` modules vs real tree | `rg --files apps packages` vs `03` module map | `03` |
32
32
  | `04` covers every command/flag/config/schema | the verb/flag/config set vs `04` | `04` |
33
33
  | `AGENTS.md` doc map == §4.1 | diff the two tables | `AGENTS.md` (§4.4) |
34
34
  | frontmatter matches §4.1 + `updated_at` plausible | see contract-verify | each doc (§4.3) |
35
35
 
36
36
  **Judgment:** is a candidate real drift (vs. an intentional, documented exception)? Which doc is
37
- authoritative? What is the *minimal* repair (a one-line dated amendment beats a rewrite)?
37
+ authoritative? What is the *minimal* repair (preserve decision history and condense only editorial noise under §6.1)?
38
38
 
39
- ## sync-check — T1–T8 → obligations
39
+ ## sync-check — applicable §5 triggers → obligations
40
40
 
41
- Read the change (diff or finished task); for each changed path classify the trigger and confirm the
42
- obligated doc was touched in the same change. The high-frequency miss is **T3** (a CLI/config/schema
43
- change without the matching `04` + `AGENTS.md` edit) check it first. (T1–T8 listed in the SKILL.md
44
- table; this reference is the detection recipe, not a restatement of the triggers.)
45
-
46
- ```bash
47
- # Surface changed in this diff?
48
- git diff --name-only | rg 'apps/cli/src/commands/|packages/.*/schema|config/'
49
- # Was 04 / AGENTS.md touched in the same diff?
50
- git diff --name-only | rg 'docs/04_DESIGN.md|^AGENTS.md'
51
- # Both non-empty → likely synced; surface-changed-but-no-04 → T3 drift.
52
- ```
41
+ Read the diff and the live constitution §5. Map changed facts to their owning document and
42
+ check that contract, not merely whether a filename appears in the diff. Unchanged index pointers
43
+ and entry guidance need no edits. T7 additionally requires the governance reason and existing
44
+ operator authorization under §6.8; include affected templates.
53
45
 
54
46
  ## contract-verify — §4.3
55
47
 
@@ -65,15 +57,10 @@ Compare `owns`/`authority` against the §4.1 row (verbatim in meaning; §4.1 win
65
57
 
66
58
  ## lesson-append — §8
67
59
 
68
- ```
69
- - [YYYY-MM-DD] <project>: <lesson what went wrong / what to do instead>
70
- ```
71
-
72
- 1. Identify the per-file `### Lessons for <doc>` section (or the cross-cutting one).
73
- 2. `rg` that section for an equivalent lesson — if found, **bump its date**, don't duplicate.
74
- 3. Append the formatted line. If the lesson restates an existing §6 rule, it's already law — skip.
75
- 4. If it has recurred, **promote** it to a §6 rule / §5 trigger and remove from §8 (the only
76
- sanctioned deletion).
60
+ 1. Resolve the existing learning/context destination from the project's conventions.
61
+ 2. Search for an equivalent lesson; skip duplicates and routine completion receipts.
62
+ 3. Record the useful lesson with evidence outside the constitution.
63
+ 4. Propose any governance correction separately; recurrence does not authorize a §6.8 edit.
77
64
 
78
65
  ## Drift-report shape
79
66
 
@@ -84,7 +71,7 @@ Checks run: <n> (§7 items) · Findings: <m>
84
71
 
85
72
  | # | Doc | Reality says | Doc says | Authority | Trigger | Repair |
86
73
  |---|-----|--------------|----------|-----------|---------|--------|
87
- | 1 | 04_DESIGN | `spur foo` exists (apps/cli/.../foo.ts) | absent | 04 (T3) | | add the §6.4 command block |
74
+ | 1 | 04_DESIGN | Changed command contract | Satellite describes old behavior | 04 | T3 | update its owning satellite under §6.5 |
88
75
 
89
76
  Zero-finding checks: <list the §7 items that returned no delta, with the command used>
90
77
  ```
@@ -67,6 +67,20 @@ frontmatter scalar.
67
67
  wholesale. No inline-body flag. Section names: `Background`, `Requirements`, `Acceptance Criteria`, `Q&A`, `Design`, `Plan`, `Solution`, `Testing`, `Review`, `References`, `History`, `Notes`.
68
68
  - **Frontmatter** (`--feature <id>`, `--priority <p>`): sets the scalar frontmatter field on an
69
69
  existing task — the only post-create path, allow-listed to `feature_id` / `parent_wbs` / `priority`.
70
+ - **AC controls** (`--ac-altitude <graduating|task-local>`, `--ac-numbering task-local`) — independent
71
+ of each other (task 0818 R5). `--ac-altitude task-local` skips the **DD-09 feature-AC subset** rule
72
+ because the task's scenarios are intentionally not the feature's ship criteria; `--ac-numbering
73
+ task-local` opts the task into the **Requirements↔AC coverage** check inside the task. Setting one
74
+ never implies the other. `graduating` remains the default and DD-09 stays enforced for graduating
75
+ tasks. Use it for an issue/fix-batch task that is genuinely linked to a feature but whose
76
+ regression scenarios sit below that feature's ship criteria, and record the rationale in the task
77
+ body:
78
+
79
+ ```bash
80
+ # One frontmatter flag per call — `update` sets a single field and ignores the rest.
81
+ bun run apps/cli/src/index.ts task update 0818 --feature D6 --json
82
+ bun run apps/cli/src/index.ts task update 0818 --ac-altitude task-local --json
83
+ ```
70
84
 
71
85
  Exit code `2` when neither mode's required args are supplied (e.g. `--section` without `--from-file`,
72
86
  or no status and no `--section`/frontmatter flag).
@@ -183,7 +197,9 @@ traceability. Bare = whole corpus; with a WBS = one task. The matrix is loaded f
183
197
 
184
198
  **L4 traceability** resolves `feature_id` / `parent_wbs` / `dependencies` edges and checks **AC
185
199
  coverage** (DD-09): a task's scenarios must be a subset of its linked feature's AC by normalized
186
- title — orphans warn by default.
200
+ title — orphans warn by default. A task declaring `ac_altitude: task-local` is exempt from that
201
+ subset rule only (`--ac-altitude`, above); every graduating task is still enforced, and the exemption
202
+ does not touch `ac_numbering`'s Requirements↔AC coverage or any other layer.
187
203
 
188
204
  `--json` emits an array of per-task results:
189
205
 
@@ -157,13 +157,43 @@ spur task update 0040 --section Review --from-file /tmp/review.md
157
157
  first, then point `--from-file` at it.
158
158
 
159
159
  **Frontmatter set** (the only post-create path to scalar fields, allow-listed to
160
- `feature_id`/`parent_wbs`/`priority`):
160
+ `feature_id`/`parent_wbs`/`priority`, plus the two AC controls below):
161
161
 
162
162
  ```bash
163
163
  spur task update 0040 --feature H2
164
164
  spur task update 0040 --priority P1
165
165
  ```
166
166
 
167
+ ### AC altitude — `--ac-altitude` (task 0818 R5)
168
+
169
+ `--ac-altitude` and `--ac-numbering` are **independent** controls that are easy to confuse:
170
+
171
+ | Flag | Controls | Default | `task-local` means |
172
+ | --- | --- | --- | --- |
173
+ | `--ac-altitude <graduating\|task-local>` | DD-09 **feature-AC subset** rule (task scenarios ⊆ linked feature AC) | `graduating` | the task's scenarios are deliberately **not** feature ship criteria — skip the subset rule |
174
+ | `--ac-numbering <task-local>` | **Requirements↔AC coverage** inside the task | off | opt the task into the R-to-AC coverage check |
175
+
176
+ Setting one says nothing about the other: a `task-local`-altitude task can still be under full
177
+ R-to-AC coverage, and usually should be.
178
+
179
+ **The standing pattern for an issue or fix-batch task.** Link it to the feature it substantively
180
+ belongs to — do not leave it orphaned and do not relink unrelated corpus to silence a diagnostic.
181
+ Then, *only* when its regression scenarios intentionally do not represent that feature's ship
182
+ criteria, declare `--ac-altitude task-local` and record the rationale in the task body (Background
183
+ or Design), so the choice is auditable rather than inferred:
184
+
185
+ ```bash
186
+ # source-local CLI (before `bun link`, or when pinning to this checkout).
187
+ # One frontmatter flag per call: `update` applies a single field, so a second
188
+ # frontmatter flag in the same invocation is silently ignored.
189
+ bun run apps/cli/src/index.ts task update 0818 --feature D6 --json
190
+ bun run apps/cli/src/index.ts task update 0818 --ac-altitude task-local --json
191
+ ```
192
+
193
+ `graduating` stays the default, and DD-09 stays enforced for every graduating task — this flag
194
+ expresses a real altitude distinction, not a gate escape hatch. Ordinary orphan warnings are
195
+ unchanged, and no checker policy changes.
196
+
167
197
  The section-write-then-replace pattern is the workflow agents use to fill in `Plan` / `Solution` /
168
198
  `Testing` / `Review` during a run. See
169
199
  [tasks/section-editing.md](tasks/section-editing.md) for the full recipe. For pipeline
@@ -113,6 +113,20 @@ Any of the four may additionally carry a **bracket tag** in any position — `[d
113
113
  `Scenario: [advisory] Foo`. Tags are stripped before matching (0398 R7), so tagging never breaks
114
114
  the linkage.
115
115
 
116
+ Task-side, `verify-answer-lint` additionally accepts a fifth declared id source — a **bold-trajectory
117
+ paragraph**: a whole-line `**AC id…**` paragraph inside the task's `### Acceptance Criteria`
118
+ block (task 0817 R3). The id up to its first `:` and the paragraph's full spelling are both
119
+ declared; two bold spans on one line are not a declaration (an interpolated bold id stays
120
+ unmatchable):
121
+
122
+ ```markdown
123
+ ### Acceptance Criteria
124
+
125
+ **AC-0817-HERM-SKIP: unpinned project-config resolution is suppressed.**
126
+
127
+ | AC-0817-HERM-SKIP | MET | test | `tests/loader.test.ts:962` | ← declared
128
+ ```
129
+
116
130
  ### The id is exactly the scenario title — no Gherkin body appended
117
131
 
118
132
  An AC row id must be **exactly** the scenario title (plus any of the four forms above), with the
@@ -634,9 +634,9 @@ CLI-gated corpus artifact. The `wrapup-pipeline.yaml` `learning-capture` step wr
634
634
 
635
635
  - **Not CLI-gated.** The file is written directly by the wrap-up pipeline's `learning-capture`
636
636
  agent.run step. It does not go through `spur task update` or `spur feature update`.
637
- - **Not a validated corpus.** The file is a working scratchpad. High-value learnings are promoted
638
- to `docs/99_PROJECT_CONSTITUTION.md §8` (lessons) by the `doc-sync` step (via `sp:doc-evolve`),
639
- not by the learning-capture step itself.
637
+ - **Not a validated corpus.** The file is a working scratchpad. Deduplicate reusable lessons in
638
+ existing project learning/context storage. Constitution §8 routes lessons outside that file;
639
+ doc-sync does not promote lessons into governance without operator-authorized §6.8 scope.
640
640
  - **Append-only within a session.** New entries are appended; existing entries are not rewritten.
641
641
  - **Grouped by date and task.** Each entry has a date and task WBS header so the operator can
642
642
  trace a learning back to its source task.