@gobing-ai/spur 0.3.40 → 0.3.42

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 (185) hide show
  1. package/.claude-plugin/marketplace.json +15 -0
  2. package/README.md +15 -1
  3. package/config/templates/AGENTS.md +5 -3
  4. package/config/workflows/task-pipeline.yaml +103 -12
  5. package/package.json +15 -12
  6. package/plugins/README.md +655 -0
  7. package/plugins/sp/README.md +621 -0
  8. package/plugins/sp/agents/expert-spur.md +109 -0
  9. package/plugins/sp/agents/super-coder.md +126 -0
  10. package/plugins/sp/agents/super-planner.md +283 -0
  11. package/plugins/sp/agents/super-reviewer.md +154 -0
  12. package/plugins/sp/commands/dev-arch.md +30 -0
  13. package/plugins/sp/commands/dev-brainstorm.md +40 -0
  14. package/plugins/sp/commands/dev-changelog.md +28 -0
  15. package/plugins/sp/commands/dev-daily.md +29 -0
  16. package/plugins/sp/commands/dev-debug.md +29 -0
  17. package/plugins/sp/commands/dev-dogfood.md +33 -0
  18. package/plugins/sp/commands/dev-featurechange.md +130 -0
  19. package/plugins/sp/commands/dev-find-conflict.md +51 -0
  20. package/plugins/sp/commands/dev-find-issue.md +76 -0
  21. package/plugins/sp/commands/dev-find-next.md +60 -0
  22. package/plugins/sp/commands/dev-fixall.md +33 -0
  23. package/plugins/sp/commands/dev-gitmsg.md +28 -0
  24. package/plugins/sp/commands/dev-gtd.md +97 -0
  25. package/plugins/sp/commands/dev-handover.md +26 -0
  26. package/plugins/sp/commands/dev-idea.md +50 -0
  27. package/plugins/sp/commands/dev-next.md +31 -0
  28. package/plugins/sp/commands/dev-parallel.md +30 -0
  29. package/plugins/sp/commands/dev-plan.md +46 -0
  30. package/plugins/sp/commands/dev-refine.md +48 -0
  31. package/plugins/sp/commands/dev-refineall.md +65 -0
  32. package/plugins/sp/commands/dev-refresh.md +32 -0
  33. package/plugins/sp/commands/dev-reverse.md +32 -0
  34. package/plugins/sp/commands/dev-review.md +31 -0
  35. package/plugins/sp/commands/dev-run.md +63 -0
  36. package/plugins/sp/commands/dev-runall.md +80 -0
  37. package/plugins/sp/commands/dev-simplify.md +39 -0
  38. package/plugins/sp/commands/dev-unit.md +29 -0
  39. package/plugins/sp/commands/dev-verify.md +48 -0
  40. package/plugins/sp/commands/dev-verifyall.md +72 -0
  41. package/plugins/sp/commands/dev-wrap.md +30 -0
  42. package/plugins/sp/commands/dev-wrapall.md +33 -0
  43. package/plugins/sp/commands/rule-add.md +18 -0
  44. package/plugins/sp/commands/rule-refine.md +18 -0
  45. package/plugins/sp/commands/rule-scan.md +18 -0
  46. package/plugins/sp/commands/spur-init.md +22 -0
  47. package/plugins/sp/commands/workflow-add.md +18 -0
  48. package/plugins/sp/commands/workflow-refine.md +18 -0
  49. package/plugins/sp/hooks/agent-hint.ts +60 -0
  50. package/plugins/sp/hooks/careful-guard.ts +147 -0
  51. package/plugins/sp/hooks/context-post-tool.ts +325 -0
  52. package/plugins/sp/hooks/context-session-start.ts +182 -0
  53. package/plugins/sp/hooks/context-session-stop.ts +95 -0
  54. package/plugins/sp/hooks/hooks.json +51 -0
  55. package/plugins/sp/hooks/pi/guard-extension.ts +341 -0
  56. package/plugins/sp/hooks/task-write-guard.ts +84 -0
  57. package/plugins/sp/plugin.json +8 -0
  58. package/plugins/sp/scripts/batch-preflight.ts +204 -0
  59. package/plugins/sp/scripts/daily-summary/daily-summary.ts +606 -0
  60. package/plugins/sp/scripts/daily-summary/logger.ts +28 -0
  61. package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts +363 -0
  62. package/plugins/sp/scripts/dogfood-testing/validate-report.ts +168 -0
  63. package/plugins/sp/scripts/feature-sync-bounded.ts +451 -0
  64. package/plugins/sp/scripts/stage-registry-adapter.ts +1341 -0
  65. package/plugins/sp/scripts/task-size-precheck.ts +202 -0
  66. package/plugins/sp/scripts/validate-commands.ts +651 -0
  67. package/plugins/sp/scripts/validate-flag-contracts.ts +875 -0
  68. package/plugins/sp/skills/brainstorm/SKILL.md +361 -0
  69. package/plugins/sp/skills/brainstorm/agents/openai.yaml +14 -0
  70. package/plugins/sp/skills/brainstorm/examples/ideation-example.md +209 -0
  71. package/plugins/sp/skills/brainstorm/metadata.openclaw +7 -0
  72. package/plugins/sp/skills/brainstorm/references/grilling-interview.md +68 -0
  73. package/plugins/sp/skills/brainstorm/references/workflows.md +255 -0
  74. package/plugins/sp/skills/branch-workflow/SKILL.md +109 -0
  75. package/plugins/sp/skills/branch-workflow/references/branch-lifecycle.md +69 -0
  76. package/plugins/sp/skills/branch-workflow/references/worktree-patterns.md +100 -0
  77. package/plugins/sp/skills/code-implementation/SKILL.md +176 -0
  78. package/plugins/sp/skills/code-implementation/references/debugging.md +64 -0
  79. package/plugins/sp/skills/code-implementation/references/implementation-patterns.md +113 -0
  80. package/plugins/sp/skills/code-improvement/SKILL.md +231 -0
  81. package/plugins/sp/skills/code-improvement/references/deepening-signals.md +205 -0
  82. package/plugins/sp/skills/code-review/SKILL.md +112 -0
  83. package/plugins/sp/skills/code-review/references/receiving-code-review.md +70 -0
  84. package/plugins/sp/skills/code-review/references/review-lenses.md +117 -0
  85. package/plugins/sp/skills/code-review/references/self-review-checklist.md +53 -0
  86. package/plugins/sp/skills/code-review/references/verification-before-completion.md +68 -0
  87. package/plugins/sp/skills/code-simplification/SKILL.md +225 -0
  88. package/plugins/sp/skills/code-testing/SKILL.md +108 -0
  89. package/plugins/sp/skills/code-testing/references/stacks/bun-ts.md +165 -0
  90. package/plugins/sp/skills/code-testing/references/stacks/go.md +88 -0
  91. package/plugins/sp/skills/code-testing/references/stacks/python.md +117 -0
  92. package/plugins/sp/skills/code-testing/references/test-loop-breaker.md +37 -0
  93. package/plugins/sp/skills/code-testing/references/test-output-discipline.md +52 -0
  94. package/plugins/sp/skills/code-testing/references/unit-testing.md +212 -0
  95. package/plugins/sp/skills/code-verification/SKILL.md +535 -0
  96. package/plugins/sp/skills/code-verification/references/code-improvement.md +39 -0
  97. package/plugins/sp/skills/code-verification/references/secu-review.md +94 -0
  98. package/plugins/sp/skills/code-verification/references/verdict-schema.md +141 -0
  99. package/plugins/sp/skills/conflict-finding/SKILL.md +254 -0
  100. package/plugins/sp/skills/conflict-finding/references/authority-resolution.md +258 -0
  101. package/plugins/sp/skills/conflict-finding/references/comparison-protocol.md +277 -0
  102. package/plugins/sp/skills/conflict-finding/references/finding-contract.md +346 -0
  103. package/plugins/sp/skills/conflict-finding/references/remediation-routing.md +276 -0
  104. package/plugins/sp/skills/daily-summary/SKILL.md +171 -0
  105. package/plugins/sp/skills/daily-summary/agents/openai.yaml +13 -0
  106. package/plugins/sp/skills/doc-evolve/SKILL.md +175 -0
  107. package/plugins/sp/skills/doc-evolve/references/operations.md +93 -0
  108. package/plugins/sp/skills/dogfood-testing/SKILL.md +608 -0
  109. package/plugins/sp/skills/dogfood-testing/references/monitor-ledger.md +211 -0
  110. package/plugins/sp/skills/dogfood-testing/references/report-template.md +351 -0
  111. package/plugins/sp/skills/doubt-driven-development/SKILL.md +136 -0
  112. package/plugins/sp/skills/functional-review/SKILL.md +364 -0
  113. package/plugins/sp/skills/functional-review/references/verdict-schema.md +133 -0
  114. package/plugins/sp/skills/indexed-context/SKILL.md +164 -0
  115. package/plugins/sp/skills/issue-finding/SKILL.md +424 -0
  116. package/plugins/sp/skills/issue-finding/agents/openai.yaml +15 -0
  117. package/plugins/sp/skills/issue-finding/examples/expected-findings.json +27 -0
  118. package/plugins/sp/skills/issue-finding/examples/session-test-loop.jsonl +23 -0
  119. package/plugins/sp/skills/issue-finding/references/session-formats.md +121 -0
  120. package/plugins/sp/skills/next-feature/SKILL.md +125 -0
  121. package/plugins/sp/skills/next-feature/references/handoff-routing.md +92 -0
  122. package/plugins/sp/skills/next-feature/references/proposal-contract.md +49 -0
  123. package/plugins/sp/skills/next-feature/references/ranking-rubric.md +52 -0
  124. package/plugins/sp/skills/next-feature/references/signal-derivation.md +67 -0
  125. package/plugins/sp/skills/next-router/SKILL.md +181 -0
  126. package/plugins/sp/skills/next-router/references/messages.md +90 -0
  127. package/plugins/sp/skills/next-router/references/routing-table.md +216 -0
  128. package/plugins/sp/skills/parallel-execution/SKILL.md +148 -0
  129. package/plugins/sp/skills/parallel-execution/references/dispatch-surface.md +100 -0
  130. package/plugins/sp/skills/parallel-execution/references/fan-out-patterns.md +101 -0
  131. package/plugins/sp/skills/parallel-execution/references/result-synthesis.md +94 -0
  132. package/plugins/sp/skills/reverse-engineering/SKILL.md +375 -0
  133. package/plugins/sp/skills/reverse-engineering/agents/openai.yaml +18 -0
  134. package/plugins/sp/skills/source-driven-development/SKILL.md +124 -0
  135. package/plugins/sp/skills/spec-decomposition/SKILL.md +117 -0
  136. package/plugins/sp/skills/spec-decomposition/references/decomposition.md +539 -0
  137. package/plugins/sp/skills/spur-cli/SKILL.md +133 -0
  138. package/plugins/sp/skills/spur-cli/references/agent.md +179 -0
  139. package/plugins/sp/skills/spur-cli/references/features/acceptance-criteria.md +82 -0
  140. package/plugins/sp/skills/spur-cli/references/features/hierarchy-mece.md +177 -0
  141. package/plugins/sp/skills/spur-cli/references/features/roadmap-priority.md +84 -0
  142. package/plugins/sp/skills/spur-cli/references/features/verbs.md +122 -0
  143. package/plugins/sp/skills/spur-cli/references/features.md +234 -0
  144. package/plugins/sp/skills/spur-cli/references/init.md +119 -0
  145. package/plugins/sp/skills/spur-cli/references/message.md +98 -0
  146. package/plugins/sp/skills/spur-cli/references/rules/authoring-rules.md +212 -0
  147. package/plugins/sp/skills/spur-cli/references/rules/fine-tuning.md +148 -0
  148. package/plugins/sp/skills/spur-cli/references/rules/operations.md +228 -0
  149. package/plugins/sp/skills/spur-cli/references/rules/validation-and-extension.md +129 -0
  150. package/plugins/sp/skills/spur-cli/references/rules.md +209 -0
  151. package/plugins/sp/skills/spur-cli/references/serve.md +58 -0
  152. package/plugins/sp/skills/spur-cli/references/tasks/l3-guard-cheatsheet.md +98 -0
  153. package/plugins/sp/skills/spur-cli/references/tasks/section-editing.md +95 -0
  154. package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +361 -0
  155. package/plugins/sp/skills/spur-cli/references/tasks.md +278 -0
  156. package/plugins/sp/skills/spur-cli/references/team.md +133 -0
  157. package/plugins/sp/skills/spur-cli/references/workflows/authoring-workflows.md +226 -0
  158. package/plugins/sp/skills/spur-cli/references/workflows/operations.md +211 -0
  159. package/plugins/sp/skills/spur-cli/references/workflows/validation-and-extension.md +129 -0
  160. package/plugins/sp/skills/spur-cli/references/workflows.md +355 -0
  161. package/plugins/sp/skills/spur-dev/SKILL.md +224 -0
  162. package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +196 -0
  163. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +664 -0
  164. package/plugins/sp/skills/spur-dev/references/decision-brief.md +80 -0
  165. package/plugins/sp/skills/spur-dev/references/dev-operations.md +546 -0
  166. package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +164 -0
  167. package/plugins/sp/skills/spur-dev/references/execution-batch.md +727 -0
  168. package/plugins/sp/skills/spur-dev/references/execution-workflow.md +350 -0
  169. package/plugins/sp/skills/spur-dev/references/feature-link-helper.md +191 -0
  170. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +417 -0
  171. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +171 -0
  172. package/plugins/sp/skills/spur-dev/references/glossary.md +95 -0
  173. package/plugins/sp/skills/spur-dev/references/idea-evaluation.md +80 -0
  174. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +88 -0
  175. package/plugins/sp/skills/spur-dev/references/planning-workflow.md +302 -0
  176. package/plugins/sp/skills/spur-dev/references/product-planning.md +206 -0
  177. package/plugins/sp/skills/spur-dev/references/section-batching.md +24 -0
  178. package/plugins/sp/skills/sys-architecture/SKILL.md +155 -0
  179. package/plugins/sp/skills/sys-architecture/references/decision-method.md +137 -0
  180. package/plugins/sp/skills/sys-architecture/references/upkeep-survey.md +75 -0
  181. package/plugins/sp/skills/sys-debugging/SKILL.md +228 -0
  182. package/plugins/sp/skills/sys-debugging/references/debugging-protocol.md +62 -0
  183. package/plugins/sp/skills/test-driven-development/SKILL.md +248 -0
  184. package/plugins/sp/skills/wayfinder/SKILL.md +292 -0
  185. package/spur.js +6093 -5180
@@ -0,0 +1,211 @@
1
+ ---
2
+ name: monitor-ledger
3
+ description: "The dogfood monitor methodology + on-disk live ledger column contract + dual-write + token/cache estimation heuristic + the cache-health finding rule. The on-disk ledger is the single source of truth the report is assembled from — recorded live, per step, never reconstructed."
4
+ see_also:
5
+ - dogfood-testing
6
+ - report-template
7
+ protocol: sp:dogfood-testing@1.2
8
+ ---
9
+
10
+ # Monitor + Ledger
11
+
12
+ The ledger is the **single source of truth** for the report. It is recorded **live on disk** — one
13
+ row per step, written the moment the step resolves — never reconstructed from memory at the end.
14
+ Reconstruction produces fiction: it cannot honestly distinguish a step that passed first-try from
15
+ one that took three attempts, and it loses the per-step signal that drives testee refinement.
16
+
17
+ **Disk SSOT (protocol @1.2).** Working-memory-only ledgers are a contract violation. The ledger
18
+ lives in the dual artifacts (see [report-template.md](report-template.md) → Always-on dual
19
+ artifacts):
20
+
21
+ | File | Path |
22
+ |------|------|
23
+ | Live | `.spur/run/dogfood/<run_id>.md` |
24
+ | Report | `docs/dogfood/YYYY-MM-DD-<testee-slug>-dogfood.md` |
25
+
26
+ ## The live-ledger rule
27
+
28
+ 1. **Open both artifacts in Phase 1**, before the first step runs (frontmatter `status: running` +
29
+ empty ledger table in each).
30
+ 2. **Write a row the instant a step resolves** (pass, fixed, unresolved, or N/A) — not after the run.
31
+ 3. **Dual-write every step:** append/update the row on the **live** file first, then mirror to the
32
+ **report** path. Do not batch rows until Phase 4. If the report write fails, continue with live
33
+ as SSOT, emit a P2 finding, and retry promote on finalize.
34
+ 4. **The report reads the on-disk ledger, not your memory.** Every number in the report traces to a
35
+ ledger row on disk. If it is not in the ledger file, it does not go in the report.
36
+ 5. **Cardinality (@1.2).** The ledger's data-row count MUST equal the `**Steps:** N derived, N executed` declared
37
+ in the report's §2 Execution Summary. N/A steps are not dropped — each gets its own row with
38
+ `Outcome: N/A`. A count mismatch refuses `status: complete` at finalize (see
39
+ 6. **R2 drift row (task 0296).** A ledger row tagged `drift:external` in the `Step` column documents
40
+ workspace drift detected during the run — files changed by an external writer that neither the
41
+ driver nor testee ledger rows name. The row carries `Outcome: drift`, `Fix Applied: <drifted paths>`,
42
+ `Finding: P2 — workspace drift detected during run; attribution to external writer`,
43
+ and `Basis: <fingerprint diff>`. A drift row never changes a step's outcome and never results in
44
+ a `FIXED` / `PASS` outcome — it is purely documentary. Cache columns carry `—` (not estimated).
45
+ See [SKILL.md §Workspace-drift guard](../SKILL.md#workspace-drift-guard-r2--task-0296).
46
+
47
+ ### Fast-run exemption (task 0294 R6a)
48
+
49
+ The per-step live-write mandate (rules 1–4) exists to bound information loss when a mid-run crash
50
+ terminates the driver before finalize. That risk is real for long runs (multi-step pipelines,
51
+ mutating testees); it is **marginal for fast runs** where wall-clock is short enough that an
52
+ operator would naturally watch the run to completion.
53
+
54
+ **Codified exemption.** A run with **total wall-clock < 3 minutes** MAY batch-write all ledger
55
+ rows at finalize, provided **both** of the following hold:
56
+
57
+ 1. The report's §2 Execution Summary carries an explicit note:
58
+ `Ledger write mode: batch-finalize (fast-run exemption, total wall-clock < 3 min)`.
59
+ 2. The driver is still prepared to reconstruct per-step ordering honestly — batched does not mean
60
+ fictional. If the driver cannot reconstruct attempts/outcomes per step from its own tool-call
61
+ history, the exemption does NOT apply and the strict per-step rule is back in force (rule 4:
62
+ "if it is not in the ledger file, it does not go in the report").
63
+
64
+ This matches how the 0280 fast-run actually behaved (batch-finalize, still validated `complete`)
65
+ and preserves the strict mandate for long runs where mid-run crash loss is the real risk. A run
66
+ ≥ 3 min that batch-writes is a **protocol violation the driver must self-report** as a P3 finding
67
+ in the report's §6 Findings (no exemption applies).
68
+
69
+ ## Column contract
70
+
71
+ ```
72
+ | Step | Attempts | Outcome | Fix Applied | Finding | Fresh Tokens | Cached Tokens | Cache % | Basis | Wall-clock |
73
+ ```
74
+
75
+ | Column | Meaning |
76
+ |--------|---------|
77
+ | `Step` | The derived step label (Phase 1) or `N` for a single-step testee. |
78
+ | `Attempts` | How many times the step was run (1 = first-try; >1 = retried under the fix budget). |
79
+ | `Outcome` | `PASS` / `FIXED` / `UNRESOLVED` / `N/A`. (`FIXED` = failed then passed within budget.) |
80
+ | `Fix Applied` | `file:line` + one-line summary, or `—`. |
81
+ | `Finding` | One-line finding surfaced at this step, or `—`. A finding does **not** change `Outcome`. |
82
+ | `Fresh Tokens` | Estimated fresh context for the step. Prefix with `~`. |
83
+ | `Cached Tokens` | Estimated reused context for the step. Prefix with `~`. |
84
+ | `Cache %` | `Cached Tokens / (Fresh Tokens + Cached Tokens)`, rounded to the nearest whole percent. |
85
+ | `Basis` | Observable basis for the estimate: command output, prior file read reused, generated text, etc. |
86
+ | `Wall-clock` | Elapsed time for the step. |
87
+
88
+ ## Token + cache estimation heuristic
89
+
90
+ A skill **cannot read its own exact token meter** — derive an estimate and label every number
91
+ `~estimate`. The accepted methodology is deterministic from the ledger rows:
92
+
93
+ 1. Estimate **Fresh Tokens** from new material consumed or produced by the step:
94
+ - text read from files or command output: `ceil(characters / 4)`, rounded to the nearest 100;
95
+ - generated prose/code/report text: `ceil(characters / 4)`, rounded to the nearest 100;
96
+ - short command/control overhead: add `~100` per tool invocation that produced non-empty output.
97
+ 2. Estimate **Cached Tokens** only for material already present in the current session and actively
98
+ reused by reference in this step. Use the same `ceil(characters / 4)` basis and round to the
99
+ nearest 100. Do not count fresh command output, newly read files, or regenerated scaffolding as
100
+ cached.
101
+ 3. Compute each row: `Cache % = round(Cached Tokens / (Fresh Tokens + Cached Tokens) * 100)`.
102
+ 4. Compute the report aggregate from row sums:
103
+ `aggregate cache% = round(sum(Cached Tokens) / sum(Fresh Tokens + Cached Tokens) * 100)`.
104
+
105
+ The **trend across runs** is the signal, not the absolute value: rising cache% = the testee is
106
+ reusing context efficiently; falling cache% = context bloat creeping in.
107
+
108
+ > Never print a precise token number you cannot substantiate. The numbers exist to show a *trend*,
109
+ > not to bill anyone.
110
+
111
+ ### Multi-source Cost block (report §2)
112
+
113
+ Ledger estimates alone are **confidence: LOW**. When assembling the report Cost block
114
+ ([report-template.md](report-template.md) §2):
115
+
116
+ | Source | When to use | Confidence | Scope label |
117
+ |--------|-------------|------------|-------------|
118
+ | Ledger `chars/4` heuristic | Always | LOW | per-step trend |
119
+ | `ccusage` daily/session | If CLI available and returns data | MEDIUM | day or session — **not** per-step |
120
+ | Agent usage fields in tool results | If present (never invent) | MEDIUM | as reported by the tool |
121
+
122
+ If no external meter is available, print `Meter: n/a`. Never merge a day-level meter into a
123
+ per-step ledger cell as if it were measured per step.
124
+
125
+ ### Chained-step rows (implement-heavy derived steps)
126
+
127
+ When a derived step is implement-heavy (it runs a pipeline leg, writes code, or otherwise mutates more
128
+ than its own arguments), its row is tagged `chained:<step>` in the Step column and its Fresh/Cached
129
+ columns reflect the **chained leg's** cost, not the driver's. The driver's monitoring cost for that
130
+ step stays on the driver's own row.
131
+
132
+ - Observable chained usage (subagent output in driver context, or the operator explicitly provided
133
+ the artifact) → estimate Fresh/Cached from that output normally.
134
+ - Unobservable chained usage (subagent ran in a different session, usage data never surfaced) →
135
+ label Fresh `~unknown`, Cached `~0`, Basis `chained-leg usage not observable from driver`. **MUST**
136
+ emit a P3 finding: `P3 — chained-step cost not observable` (task 0278 R3). Do not invent totals.
137
+
138
+ Never fold a chained row into the driver's row; the whole point of dogfooding a pipeline-driving
139
+ testee is to see the testee's own cost separately from the driver's monitoring cost. See
140
+ [SKILL.md §Cost segmentation for implement-heavy steps](../SKILL.md#cost-segmentation-for-implement-heavy-steps).
141
+
142
+ ## Anti-fiction rule
143
+
144
+ Never reuse a convenient cache percentage such as `45%` because it "feels right." A cache percentage
145
+ is valid only when it can be recomputed from the ledger row sums. If the basis is missing, mark the
146
+ row pessimistically (`Cached Tokens = ~0`) and explain the missing basis.
147
+
148
+ ## Cache-health finding rule
149
+
150
+ Cache% is the operational signal for testee-tuning:
151
+
152
+ - Any **individual step with cache% < 40%** → it is re-reading files or re-sending prompt context
153
+ unnecessarily. Emit a **P3** finding naming that step, **even if the step succeeded**.
154
+ - A run with **aggregate cache% < 50%** → the testee is a tuning candidate regardless of the
155
+ PASS/PARTIAL/FAIL verdict. Emit a **P3** finding: "Low cache hit rate — candidate for
156
+ context-window or prompt trimming."
157
+
158
+ These feed the report's §6 Findings (see [report-template.md](report-template.md)).
159
+
160
+ ## Cache-conservation discipline (how to keep cache% high)
161
+
162
+ The cache-health rule above *detects* waste; this section is the mitigation. The dogfooding driver
163
+ (the agent running Phase 2/3) controls most of the cache% it later reports — low cache% is usually
164
+ the driver re-fetching data it already holds. Apply these while monitoring each step:
165
+
166
+ ### Driver cache checklist (task 0278 R7)
167
+
168
+ When aggregate cache% risks falling under 50%, apply this checklist **before** re-reading:
169
+
170
+ | # | Action | Why |
171
+ |---|--------|-----|
172
+ | 1 | Reuse the Step-1 `spur task show --json` capture for the rest of the run | Avoids re-tokenizing the full task body |
173
+ | 2 | Do not re-Read SKILL.md / report-template after Phase 1 loaded them | Skill body is large; keep one copy in context |
174
+ | 3 | Prefer `--json` CLI over re-parsing freeform prose | Smaller, stable payloads |
175
+ | 4 | Dual-write ledger rows without re-reading the whole report each step | Append/patch; don't full-file re-load |
176
+ | 5 | Skip redundant `bun test` full suite between steps when a focused file suite already green | Run the broad suite once at the end |
177
+ | 6 | For batch testees (`verifyall` / `runall` / `refineall`): freeze `task list --json` once at resolve | Re-listing the set per task is the #1 sub-50% cache pattern on feature dogfoods |
178
+ | 7 | On re-verify of done tasks: re-read only cited `file:line` anchors, not full Solution blobs | Anchor-first re-verify keeps cache% above the 50% floor |
179
+
180
+ 1. **Reuse CLI output already in context.** If a prior step (or a prior tool call this step)
181
+ captured `spur task show`/`check`/`list` output, do **not** re-invoke the same command for that
182
+ data — reference the prior result. Re-invocation is the #1 cause of sub-40% steps. Only re-fetch
183
+ when the underlying state *changed* (e.g. you just wrote a section and need the new
184
+ `requiredSections`).
185
+ 2. **Don't re-ground shared scaffolding per step.** Command docs, the skill preamble, and the
186
+ testee's own argument-hint are loaded once into your context — they do not need to be re-read or
187
+ re-quoted for each step. Re-sending unchanged preamble registers as fresh tokens, not cached.
188
+ 3. **Prefer `--json` + targeted fields over full human output.** When you must fetch, ask for the
189
+ smallest shape that answers the question (`--json` and read one field), not the full
190
+ human-formatted dump.
191
+ 4. **Estimate `~cached` honestly against this discipline.** If *you* re-read a file or re-sent
192
+ scaffolding this step, that portion is **not** cached — mark cache% down. The estimate is only
193
+ useful as a trend if it reflects what actually happened.
194
+
195
+ The point is not to game the number — it is to drive the testee (and your own monitoring) toward
196
+ reusing context, which is the real cost saving the cache% signal stands for.
197
+
198
+ ## Worked ledger example
199
+
200
+ ```
201
+ | Step | Attempts | Outcome | Fix Applied | Finding | Fresh Tokens | Cached Tokens | Cache % | Basis | Wall-clock |
202
+ |------|----------|---------|-------------|---------|--------------|---------------|---------|-------|------------|
203
+ | 1 resolve | 1 | PASS | — | — | ~600 | ~400 | 40% | task JSON output + prior command docs reused | ~3s |
204
+ | 2 analyze | 1 | PASS | — | over-specified for refine | ~1100 | ~700 | 39% | task file read + prior task summary reused | ~5s |
205
+ | 3 synthesize | 2 | FIXED | spur-dev/SKILL.md:88 thread --agent | — | ~1500 | ~600 | 29% | edit diff + prior plan reused | ~8s |
206
+ | 4 profile | 1 | PASS | — | — | ~500 | ~350 | 41% | command output + prior profile reused | ~2s |
207
+ ```
208
+
209
+ Aggregate: total = `3700 + 2050 = 5750`; cached = `2050`; cache% =
210
+ `round(2050 / 5750 * 100) = 36%` `[~estimate]` — below the 50% floor, so emit the P3 cache-health
211
+ finding.
@@ -0,0 +1,351 @@
1
+ ---
2
+ name: report-template
3
+ description: "The dogfood report section contract + dual-path always-on delivery + mandatory summary footer + the --task sink L3 rule. The report is assembled from the on-disk live ledger and is designed to be actionable — a reader should be able to fine-tune the testee from the report alone."
4
+ see_also:
5
+ - dogfood-testing
6
+ - monitor-ledger
7
+ protocol: sp:dogfood-testing@1.2
8
+ ---
9
+
10
+ # Dogfood Report Template
11
+
12
+ The report is the deliverable. It is assembled from the **on-disk** live ledger (never reconstructed
13
+ from memory) and is designed so a reader can **fine-tune the testee from the report alone** — every
14
+ finding carries a location and a recommended action, not just an observation.
15
+
16
+ **Protocol version:** `sp:dogfood-testing@1.2` — dual-path always-on delivery, status model, Cost
17
+ block with multi-source honesty. Bump this field when the contract changes. **@1.2 changes:**
18
+ finalize hard structure (unique §1–§6 headings; Issues requires `#### Fixed` + `#### Unresolved`);
19
+ mandatory summary footer mirrored at the report end (footer missing ⇒ `status: complete` refused);
20
+ ledger cardinality (data rows == declared executed steps); protocol string normalized to the
21
+ colon form — the dash form `sp-dogfood-testing@…` is rejected in new runs.
22
+
23
+ ## Always-on dual artifacts (delivery contract)
24
+
25
+ Every dogfood run **always** writes **two** files — with or without `--save`:
26
+
27
+ | Artifact | Path | Role |
28
+ |----------|------|------|
29
+ | **Live** | `.spur/run/dogfood/<run_id>.md` | Mid-run SSOT; opened in Phase 1; ledger rows appended on every step resolve |
30
+ | **Report** | `docs/dogfood/YYYY-MM-DD-<testee-slug>-dogfood.md` | Operator artifact; same content promoted on open + every step + finalize |
31
+
32
+ `--save` is **back-compat no-op** for delivery: it still documents/prints the report path but is
33
+ **not required** to create the file. A run that ends with no file under `docs/dogfood/` (and no live
34
+ file under `.spur/run/dogfood/`) has failed the dogfood delivery contract.
35
+
36
+ ### Frontmatter (canonical — every artifact MUST open with this)
37
+
38
+ ```yaml
39
+ ---
40
+ run_id: <uuid-or-timestamp-slug>
41
+ status: running | aborted | complete
42
+ testee: "<exact invocation string>"
43
+ classification: slash-command | agent-skill | cli
44
+ mode: observe-only | fix
45
+ max_retry: <n>
46
+ testee_agent: omitted | <name>
47
+ started_at: <ISO-8601>
48
+ finished_at: <ISO-8601 or null while running>
49
+ live_path: .spur/run/dogfood/<run_id>.md
50
+ report_path: docs/dogfood/YYYY-MM-DD-<slug>-dogfood.md
51
+ protocol: sp:dogfood-testing@1.2
52
+ workspace_fingerprint: ← optional — recorded in Phase 1 for fix-mode and mutating-`--fix` dogfoods
53
+ head: <`git rev-parse HEAD`>
54
+ porcelain_hash: <sha256 of `git status --porcelain`>
55
+ taken_at: <ISO-8601>
56
+ ---
57
+ ```
58
+
59
+ ### Status model (partial-OK)
60
+
61
+ | `status` | When |
62
+ |----------|------|
63
+ | `running` | Phase 1 opened; steps still in progress |
64
+ | `aborted` | Finalize-or-abort after mid-run stop / incomplete narrative |
65
+ | `complete` | Phase 4 finished a normal end-of-run report |
66
+
67
+ A mid-run death that left only a live file with `status: running` and ledger rows is still valid
68
+ partial evidence. On any intentional stop, the driver MUST run finalize-or-abort and set
69
+ `complete` or `aborted` — never leave a deliberate stop at `running`.
70
+
71
+ Unfinished narrative sections (What We Did / Issues / Findings) use:
72
+
73
+ ```
74
+ ⚠ incomplete — not reached
75
+ ```
76
+
77
+ Never invent narrative for steps that did not run.
78
+
79
+ ## Section contract
80
+
81
+ Emit these sections in order. Headings are fixed (machine-parseable); never rename or drop one.
82
+ Skeleton is written in Phase 1; filled as the run progresses; finalized in Phase 4.
83
+
84
+ ### 1. Testee
85
+
86
+ ```
87
+ ## Dogfood Report — `<testee invocation>`
88
+
89
+ ### 1. Testee
90
+
91
+ - **Command:** `<slash command or CLI invocation>`
92
+ - **Classification:** `slash command` | `agent skill` | `CLI invocation`
93
+ - **Exact invocation:** the underlying `Skill()` call or shell command
94
+ - **Repro:** `<exact string an operator can re-run>`
95
+ - **Testee agent:** `<value forwarded via --agent>` | `omitted (testee runs in current session)`
96
+ - **Mode:** `observe-only (--max-retry 0)` | `fix (--max-retry N)`
97
+ - **Task under test:** WBS + title (if applicable)
98
+ - **Run id:** `<run_id>` · **Live:** `<live_path>` · **Report:** `<report_path>`
99
+ ```
100
+
101
+ When `status` is `aborted` or the report is partial, add under §1:
102
+
103
+ ```
104
+ - **Delivery status:** aborted | partial ⚠ incomplete run
105
+ ```
106
+
107
+ ### 2. Execution Summary
108
+
109
+ ```
110
+ ### 2. Execution Summary
111
+
112
+ - **Result:** PASS / PARTIAL / FAIL `(N fixed, N unresolved, N findings)`
113
+ - **Wall-clock:** ~N min `[~estimate]`
114
+ - **Steps:** N derived, N executed, N N/A
115
+ - **Fix attempts:** N (one brief label per fix)
116
+
117
+ #### Cost
118
+ - **Ledger estimate:** ~N total | ~N cached (~X% hit rate) `[~estimate]`
119
+ - **Method:** chars/4 heuristic (monitor-ledger.md); confidence: LOW
120
+ - **Meter:** n/a
121
+ ```
122
+
123
+ **Cost honesty rules:**
124
+
125
+ - Always include ledger-derived `~estimate` total / cached / cache% with a **Method** line and
126
+ **confidence** (`LOW` when estimate-only; `MEDIUM` when a real meter is also present).
127
+ - Optional meters when available (never invent):
128
+ - `ccusage` session/daily delta — label scope (`day` / `session`), **not** per-step
129
+ - agent usage fields if present in tool results
130
+ - If no meter: print `Meter: n/a` explicitly.
131
+ - Never present an unsubstantiated precise integer as billed/metered cost.
132
+ - Aggregate cache% MUST equal the ledger formula (see §3); otherwise the report is invalid.
133
+ - **Chained-step segmentation (@1.2):** when a derived step is implement-heavy (the step runs a
134
+ pipeline leg, writes code, or mutates more than its own arguments), its cost MUST be a separate
135
+ ledger row tagged `chained:<step>` and kept out of the driver's row. If the chained leg ran in a
136
+ subagent/session whose usage the driver cannot read, label the row `~unknown` and emit a P3 finding.
137
+ See [SKILL.md §Cost segmentation for implement-heavy steps](../SKILL.md#cost-segmentation-for-implement-heavy-steps).
138
+
139
+ **Verdict rule** — `PASS` = every step ran and no unresolved issue; `PARTIAL` = ran to the end but
140
+ ≥1 unresolved issue; `FAIL` = the run could not complete (a step blocked all downstream steps). A
141
+ finding alone never lowers the verdict — findings are improvements, not failures.
142
+
143
+ **The verdict grades the TESTEE, not the surrounding task.** If the testee is a
144
+ pipeline/command and it failed, the verdict is `FAIL` (or `PARTIAL` per the rule above) even
145
+ when the task was completed by other means; record the recovery under Issues/What-We-Did,
146
+ never in the verdict value. Only `PASS` / `PARTIAL` / `FAIL` are legal values.
147
+
148
+ ### 3. Monitor Ledger
149
+
150
+ The report MUST include the live ledger table before the narrative. Do not summarize the ledger away:
151
+ it is the audit trail for step outcomes, fix attempts, findings, and cache math. Rows are written to
152
+ **disk** (both artifacts) when each step resolves — see [monitor-ledger.md](monitor-ledger.md).
153
+
154
+ ```
155
+ ### 3. Monitor Ledger
156
+
157
+ | Step | Attempts | Outcome | Fix Applied | Finding | Fresh Tokens | Cached Tokens | Cache % | Basis | Wall-clock |
158
+ |------|----------|---------|-------------|---------|--------------|---------------|---------|-------|------------|
159
+ | resolve | 1 | PASS | — | — | ~800 | ~300 | 27% | 1 command + reused task summary | ~3s |
160
+
161
+ **Cache calculation:** aggregate cache% = round((sum(Cached Tokens) / sum(Fresh Tokens + Cached Tokens)) * 100).
162
+ ```
163
+
164
+ Ledger rules:
165
+
166
+ - Every executed step gets exactly one row, recorded when the step resolves (**on disk**, both files).
167
+ - `Fresh Tokens` and `Cached Tokens` must be numbers with `~` prefixes; `Cache %` must be computed
168
+ from those two cells, not guessed.
169
+ - `Basis` is mandatory. It names the observable inputs used for the estimate: command output,
170
+ previously-read file reused from context, generated report text, or similar.
171
+ - The aggregate cache line in `#### Cost` under §2 must equal the ledger formula above. If it
172
+ does not, the report is invalid.
173
+ - **Cardinality (@1.2):** the number of ledger data rows MUST equal the `**Steps:** N derived, N executed`
174
+ declared in §2. Steps marked N/A are documented explicitly as their own rows (`Outcome: N/A`);
175
+ an unaccounted step or an extra row refuses `status: complete` at finalize.
176
+ - If the driver cannot make a defensible estimate for a row, write `~0` cached and explain the
177
+ missing basis in `Basis`; do not invent a stable percentage.
178
+
179
+ ### 4. What We Did
180
+
181
+ Narrative, one numbered entry per logical action (a step, a fix, a gate check). Include `path:line`
182
+ references. Someone should understand the run without reading the ledger.
183
+
184
+ ```
185
+ ### 4. What We Did
186
+
187
+ 1. **Action label** — what happened, what was observed, the decision made.
188
+ 2. **Action label** — …
189
+ ```
190
+
191
+ If the run aborted before narrative was written: `⚠ incomplete — not reached`.
192
+
193
+ ### 5. Issues
194
+
195
+ Always include both sub-headings, with `(none)` when empty — consistent structure matters for parsing.
196
+
197
+ ```
198
+ ### 5. Issues
199
+
200
+ #### Fixed
201
+
202
+ 1. **Issue title** — description.
203
+ - Root cause: why it happened.
204
+ - Fix: `file:line` + one-line summary of the change.
205
+
206
+ #### Unresolved
207
+
208
+ - (none) | each with diagnosis + everything tried.
209
+ ```
210
+
211
+ ### 6. Findings
212
+
213
+ Findings are the **fine-tuning payload**. Each carries a severity, a `file:line`, and a concrete
214
+ **recommended action** — what to change, not just what's wrong. Default lists P1+P2; `--full` adds
215
+ P3+P4.
216
+
217
+ ```
218
+ ### 6. Findings
219
+
220
+ - **P1** — <what's wrong>. → **Action:** <concrete change>. (`file:line`, ~effort) `[feasible]`
221
+ - **P2** — …
222
+ ```
223
+
224
+ Each finding MUST carry a **verification-feasibility tag** in brackets at the end of the line, so
225
+ downstream task creation does not inherit an unactionable acceptance criterion:
226
+
227
+ - `[feasible]` — the recommendation is verifiable (a test, a CLI check, an observable behavior).
228
+ This is the default; most findings are feasible.
229
+ - `[stale]` — on re-check the finding no longer holds (the code already does the right thing, the
230
+ condition was misread). Do **not** file as a task — close inline with evidence. Catching this at
231
+ report time saves a no-op implementation task downstream.
232
+ - `[unverifiable]` — the recommendation cannot be confirmed with existing tooling (e.g. a
233
+ cache-hit finding with no per-step telemetry; a perf claim with no measurement loop). If filed as
234
+ a task, its acceptance criterion must be reframed to what *can* be verified (e.g. "ship the
235
+ lever; measured proof deferred"), or the task should be deferred until the missing tooling exists.
236
+ Do not let it become a normal implementation task — it will ship an unverifiable "improvement."
237
+
238
+ The tag is a prompt to whoever turns findings into tasks: `[stale]` → drop, `[unverifiable]` →
239
+ reframe or defer, `[feasible]` → proceed. A finding without a tag is treated as `[feasible]`.
240
+ Severity scale:
241
+ - **P1** — blocks correct use or causes drift/wrong output; fix before shipping the testee.
242
+ - **P2** — real friction or a latent correctness gap; fix soon. **Includes mandatory workspace-drift
243
+ finding:** when a drift row (`drift:external`) is present in the ledger, a P2 finding naming the
244
+ drifted paths is mandatory in the report (not optional). The finding states the run's evidence is
245
+ degraded, not voided. See [SKILL.md §Workspace-drift guard](../SKILL.md#workspace-drift-guard-r2--task-0296).
246
+ - **P3** — efficiency / DX / observation (includes the cache-health rule below).
247
+ - **P4** — nice-to-have, cosmetic, or speculative.
248
+
249
+ **Cache-health rule** (from [monitor-ledger.md](monitor-ledger.md)): if aggregate cache% < 50% or any
250
+ step < 40%, emit a **P3** — "Low cache hit rate — candidate for context-window or prompt trimming"
251
+ with the offending step(s). Absolute token totals from the heuristic are trend-only (`[unverifiable]`
252
+ as billable cost proof is expected).
253
+
254
+ **Migration grep rule.** When dogfooding migrations or retired surfaces, distinguish intentional
255
+ legacy-term mentions in guidance from live routed surfaces. Pair any broad grep for old skill or
256
+ command names with a live-surface grep over the command and agent roots before filing a stale-routing
257
+ finding. A deliberate rejection note in a reference file is not a live surface.
258
+
259
+ ## Phase 4 — finalize-or-abort (non-skippable terminal gate)
260
+
261
+ Before the skill may stop (success, partial, fail, observe-only end, or abort), the driver MUST:
262
+
263
+ 1. Set frontmatter `status: complete` or `status: aborted` (and `finished_at`).
264
+ 2. **Structure scrub (@1.2):** all six mandatory section headings exist **exactly once each**
265
+ (`### 1.` … `### 6.` — a duplicated heading refuses `complete`); §5 Issues carries both
266
+ `#### Fixed` and `#### Unresolved` (`(none)` when empty); unfinished narrative uses
267
+ `⚠ incomplete — not reached`; no leftover "run in progress" markers survive finalization.
268
+ 3. **Ledger cardinality (@1.2):** Monitor Ledger data rows == the `**Steps:** N derived, N executed` declared in
269
+ §2 (N/A steps documented explicitly as rows; drift rows count separately, not toward executed
270
+ steps — include `drift:external` rows in the table but subtract them from the executed count in
271
+ §2). A mismatch refuses `complete`.
272
+ 4. Write the Cost block (method + confidence + Meter).
273
+ 5. **R2 drift check at finalize.** If a workspace fingerprint was recorded, re-take snapshot
274
+ and diff against baseline minus run-touched files. Detected drift → append `drift:external`
275
+ ledger row + mandatory P2 finding. See [SKILL.md §Workspace-drift guard](../SKILL.md#workspace-drift-guard-r2--task-0296).
276
+ 6. Sync final content to **both** live and report paths.
277
+ 7. **Footer mandatory (@1.2):** print the mandatory summary footer with **both** paths always,
278
+ and mirror the footer block at the **end of the report file**. A report whose body lacks the
279
+ footer cannot set `status: complete`.
280
+ 8. **Self-validate (task 0278 R6):** run
281
+ `bun plugins/sp/scripts/dogfood-testing/validate-report.ts --file <report-path>` before
282
+ claiming `status: complete`. Exit 2 → `status: aborted` + list error codes under
283
+ `#### Unresolved` (never force complete on a non-@1.2 shape).
284
+ 9. **Refusal rule (@1.2):** when any check above fails, set `status: aborted` and list every
285
+ failed check under §5 `#### Unresolved` — never force `complete`.
286
+
287
+ Any early-exit path still runs this checklist. Stopping without it is a **driver contract violation**.
288
+
289
+ ## Mandatory Summary Footer
290
+
291
+ Print **after every run, inline, always** — it is the last thing the user sees.
292
+
293
+ ```
294
+ ── Dogfood Summary ──
295
+ Result: PASS (N fixed, N unresolved, N findings)
296
+ Tokens: ~N total | ~N cached (~X% hit rate) [~estimate]
297
+
298
+ Fixed issues:
299
+ • <label> (or: (none))
300
+
301
+ Unresolved issues:
302
+ • <label> (or: (none))
303
+
304
+ Findings (P1+P2):
305
+ • P? — <label> (or: (none))
306
+
307
+ [Live: .spur/run/dogfood/<run_id>.md]
308
+ [Report: docs/dogfood/YYYY-MM-DD-<slug>-dogfood.md]
309
+ [Task: <wbs>] ← only with --task
310
+ ```
311
+
312
+ Rules:
313
+ - **Result** and **Tokens** lines are mandatory; always tag token numbers `[~estimate]`.
314
+ - List Fixed / Unresolved / Findings; print `(none)` when empty — never omit a sub-list.
315
+ - With `--full`, Findings include P3+P4.
316
+ - If PASS with zero issues and zero findings: collapse to one line `Result: PASS — no issues, no
317
+ findings.` (still print the Tokens line).
318
+ - **`[Live:]` and `[Report:]` are always printed** after a normal stop (not gated on `--save`).
319
+ - Print `--task` WBS only when that sink ran.
320
+
321
+ ## Task sink — the `task check` L3 contract
322
+
323
+ `--task` files findings as a `review`-template task:
324
+
325
+ ```bash
326
+ spur task create "<testee> dogfood findings" --template review --json
327
+ ```
328
+
329
+ Write the **Unresolved issues** and **Findings** into the task's `#### Review Findings` table — one
330
+ row per item: `Severity` (`P1`–`P4`), `File`, `Finding`, `Recommendation`. That heading is a
331
+ sub-section of `### Background`, so:
332
+
333
+ ```bash
334
+ spur task update <wbs> --section "Background" --from-file <path> # body starts with "#### Review Findings"
335
+ ```
336
+
337
+ **Where the P-rows live, and how the L3 Review rule behaves.** The review template ships two tables:
338
+ `#### Review Findings` (under `### Background`) is the *input* you populate from the dogfood findings;
339
+ `### Review` is the *post-fix reflection* table, shipped as an **empty-cell scaffold**
340
+ (`| P1 | | | |`). `spur task check`'s L3 Review rule keys off `### Review`, not `#### Review Findings`:
341
+
342
+ - Write the dogfood findings into **`#### Review Findings`** (that is the `--task` sink target).
343
+ - Leave **`### Review`** as the shipped empty-cell scaffold. The hardened L3 rule tolerates the empty
344
+ scaffold **wherever `### Review` is optional** (review variant: `backlog`/`todo` — the freshly
345
+ created state) and only requires a *populated* P-table once `### Review` becomes **required**
346
+ (`wip`+). So a freshly created `review` task at `backlog`/`todo` passes `task check` with the
347
+ scaffold untouched — no hand-written P-row is needed, and a bare prose note in `### Review` is the
348
+ thing that errors (it is neither the scaffold nor a populated table).
349
+
350
+ Always verify with `spur task check <wbs> --json` before handoff; the sink path below writes only
351
+ `#### Review Findings` and leaves `### Review` as the scaffold.