@gobing-ai/spur 0.3.41 → 0.3.43
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/.claude-plugin/marketplace.json +15 -0
- package/README.md +15 -1
- package/config/templates/AGENTS.md +5 -3
- package/config/workflows/task-pipeline.yaml +113 -12
- package/package.json +15 -12
- package/plugins/README.md +655 -0
- package/plugins/sp/README.md +621 -0
- package/plugins/sp/agents/expert-spur.md +109 -0
- package/plugins/sp/agents/super-coder.md +126 -0
- package/plugins/sp/agents/super-planner.md +283 -0
- package/plugins/sp/agents/super-reviewer.md +154 -0
- package/plugins/sp/commands/dev-arch.md +30 -0
- package/plugins/sp/commands/dev-brainstorm.md +40 -0
- package/plugins/sp/commands/dev-changelog.md +28 -0
- package/plugins/sp/commands/dev-daily.md +29 -0
- package/plugins/sp/commands/dev-debug.md +29 -0
- package/plugins/sp/commands/dev-dogfood.md +33 -0
- package/plugins/sp/commands/dev-featurechange.md +130 -0
- package/plugins/sp/commands/dev-find-conflict.md +51 -0
- package/plugins/sp/commands/dev-find-issue.md +76 -0
- package/plugins/sp/commands/dev-find-next.md +60 -0
- package/plugins/sp/commands/dev-fixall.md +33 -0
- package/plugins/sp/commands/dev-gitmsg.md +28 -0
- package/plugins/sp/commands/dev-gtd.md +97 -0
- package/plugins/sp/commands/dev-handover.md +26 -0
- package/plugins/sp/commands/dev-idea.md +50 -0
- package/plugins/sp/commands/dev-next.md +31 -0
- package/plugins/sp/commands/dev-parallel.md +30 -0
- package/plugins/sp/commands/dev-plan.md +46 -0
- package/plugins/sp/commands/dev-refine.md +48 -0
- package/plugins/sp/commands/dev-refineall.md +65 -0
- package/plugins/sp/commands/dev-refresh.md +32 -0
- package/plugins/sp/commands/dev-reverse.md +32 -0
- package/plugins/sp/commands/dev-review.md +31 -0
- package/plugins/sp/commands/dev-run.md +63 -0
- package/plugins/sp/commands/dev-runall.md +83 -0
- package/plugins/sp/commands/dev-simplify.md +39 -0
- package/plugins/sp/commands/dev-unit.md +29 -0
- package/plugins/sp/commands/dev-verify.md +48 -0
- package/plugins/sp/commands/dev-verifyall.md +72 -0
- package/plugins/sp/commands/dev-wrap.md +48 -0
- package/plugins/sp/commands/dev-wrapall.md +51 -0
- package/plugins/sp/commands/rule-add.md +18 -0
- package/plugins/sp/commands/rule-refine.md +18 -0
- package/plugins/sp/commands/rule-scan.md +18 -0
- package/plugins/sp/commands/spur-init.md +22 -0
- package/plugins/sp/commands/workflow-add.md +18 -0
- package/plugins/sp/commands/workflow-refine.md +18 -0
- package/plugins/sp/hooks/agent-hint.ts +60 -0
- package/plugins/sp/hooks/careful-guard.ts +147 -0
- package/plugins/sp/hooks/context-post-tool.ts +325 -0
- package/plugins/sp/hooks/context-session-start.ts +182 -0
- package/plugins/sp/hooks/context-session-stop.ts +95 -0
- package/plugins/sp/hooks/hooks.json +51 -0
- package/plugins/sp/hooks/pi/guard-extension.ts +341 -0
- package/plugins/sp/hooks/task-write-guard.ts +84 -0
- package/plugins/sp/plugin.json +8 -0
- package/plugins/sp/scripts/batch-preflight.ts +204 -0
- package/plugins/sp/scripts/daily-summary/daily-summary.ts +606 -0
- package/plugins/sp/scripts/daily-summary/logger.ts +28 -0
- package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts +363 -0
- package/plugins/sp/scripts/dogfood-testing/validate-report.ts +168 -0
- package/plugins/sp/scripts/feature-sync-bounded.ts +451 -0
- package/plugins/sp/scripts/stage-registry-adapter.ts +1341 -0
- package/plugins/sp/scripts/task-size-precheck.ts +202 -0
- package/plugins/sp/scripts/validate-commands.ts +651 -0
- package/plugins/sp/scripts/validate-flag-contracts.ts +875 -0
- package/plugins/sp/skills/brainstorm/SKILL.md +361 -0
- package/plugins/sp/skills/brainstorm/agents/openai.yaml +14 -0
- package/plugins/sp/skills/brainstorm/examples/ideation-example.md +209 -0
- package/plugins/sp/skills/brainstorm/metadata.openclaw +7 -0
- package/plugins/sp/skills/brainstorm/references/grilling-interview.md +68 -0
- package/plugins/sp/skills/brainstorm/references/workflows.md +255 -0
- package/plugins/sp/skills/branch-workflow/SKILL.md +109 -0
- package/plugins/sp/skills/branch-workflow/references/branch-lifecycle.md +69 -0
- package/plugins/sp/skills/branch-workflow/references/worktree-patterns.md +100 -0
- package/plugins/sp/skills/code-implementation/SKILL.md +203 -0
- package/plugins/sp/skills/code-implementation/references/debugging.md +64 -0
- package/plugins/sp/skills/code-implementation/references/implementation-patterns.md +113 -0
- package/plugins/sp/skills/code-improvement/SKILL.md +231 -0
- package/plugins/sp/skills/code-improvement/references/deepening-signals.md +205 -0
- package/plugins/sp/skills/code-review/SKILL.md +112 -0
- package/plugins/sp/skills/code-review/references/receiving-code-review.md +70 -0
- package/plugins/sp/skills/code-review/references/review-lenses.md +117 -0
- package/plugins/sp/skills/code-review/references/self-review-checklist.md +53 -0
- package/plugins/sp/skills/code-review/references/verification-before-completion.md +68 -0
- package/plugins/sp/skills/code-simplification/SKILL.md +225 -0
- package/plugins/sp/skills/code-testing/SKILL.md +108 -0
- package/plugins/sp/skills/code-testing/references/stacks/bun-ts.md +165 -0
- package/plugins/sp/skills/code-testing/references/stacks/go.md +88 -0
- package/plugins/sp/skills/code-testing/references/stacks/python.md +117 -0
- package/plugins/sp/skills/code-testing/references/test-loop-breaker.md +37 -0
- package/plugins/sp/skills/code-testing/references/test-output-discipline.md +52 -0
- package/plugins/sp/skills/code-testing/references/unit-testing.md +212 -0
- package/plugins/sp/skills/code-verification/SKILL.md +535 -0
- package/plugins/sp/skills/code-verification/references/code-improvement.md +39 -0
- package/plugins/sp/skills/code-verification/references/secu-review.md +94 -0
- package/plugins/sp/skills/code-verification/references/verdict-schema.md +141 -0
- package/plugins/sp/skills/conflict-finding/SKILL.md +254 -0
- package/plugins/sp/skills/conflict-finding/references/authority-resolution.md +258 -0
- package/plugins/sp/skills/conflict-finding/references/comparison-protocol.md +277 -0
- package/plugins/sp/skills/conflict-finding/references/finding-contract.md +346 -0
- package/plugins/sp/skills/conflict-finding/references/remediation-routing.md +276 -0
- package/plugins/sp/skills/daily-summary/SKILL.md +171 -0
- package/plugins/sp/skills/daily-summary/agents/openai.yaml +13 -0
- package/plugins/sp/skills/doc-evolve/SKILL.md +175 -0
- package/plugins/sp/skills/doc-evolve/references/operations.md +93 -0
- package/plugins/sp/skills/dogfood-testing/SKILL.md +608 -0
- package/plugins/sp/skills/dogfood-testing/references/monitor-ledger.md +211 -0
- package/plugins/sp/skills/dogfood-testing/references/report-template.md +351 -0
- package/plugins/sp/skills/doubt-driven-development/SKILL.md +136 -0
- package/plugins/sp/skills/functional-review/SKILL.md +364 -0
- package/plugins/sp/skills/functional-review/references/verdict-schema.md +133 -0
- package/plugins/sp/skills/indexed-context/SKILL.md +164 -0
- package/plugins/sp/skills/issue-finding/SKILL.md +442 -0
- package/plugins/sp/skills/issue-finding/agents/openai.yaml +15 -0
- package/plugins/sp/skills/issue-finding/examples/expected-findings.json +27 -0
- package/plugins/sp/skills/issue-finding/examples/session-test-loop.jsonl +23 -0
- package/plugins/sp/skills/issue-finding/references/session-formats.md +151 -0
- package/plugins/sp/skills/next-feature/SKILL.md +125 -0
- package/plugins/sp/skills/next-feature/references/handoff-routing.md +92 -0
- package/plugins/sp/skills/next-feature/references/proposal-contract.md +49 -0
- package/plugins/sp/skills/next-feature/references/ranking-rubric.md +52 -0
- package/plugins/sp/skills/next-feature/references/signal-derivation.md +67 -0
- package/plugins/sp/skills/next-router/SKILL.md +181 -0
- package/plugins/sp/skills/next-router/references/messages.md +90 -0
- package/plugins/sp/skills/next-router/references/routing-table.md +216 -0
- package/plugins/sp/skills/parallel-execution/SKILL.md +148 -0
- package/plugins/sp/skills/parallel-execution/references/dispatch-surface.md +109 -0
- package/plugins/sp/skills/parallel-execution/references/fan-out-patterns.md +101 -0
- package/plugins/sp/skills/parallel-execution/references/result-synthesis.md +94 -0
- package/plugins/sp/skills/reverse-engineering/SKILL.md +375 -0
- package/plugins/sp/skills/reverse-engineering/agents/openai.yaml +18 -0
- package/plugins/sp/skills/source-driven-development/SKILL.md +124 -0
- package/plugins/sp/skills/spec-decomposition/SKILL.md +117 -0
- package/plugins/sp/skills/spec-decomposition/references/decomposition.md +539 -0
- package/plugins/sp/skills/spur-cli/SKILL.md +133 -0
- package/plugins/sp/skills/spur-cli/references/agent.md +179 -0
- package/plugins/sp/skills/spur-cli/references/features/acceptance-criteria.md +82 -0
- package/plugins/sp/skills/spur-cli/references/features/hierarchy-mece.md +177 -0
- package/plugins/sp/skills/spur-cli/references/features/roadmap-priority.md +84 -0
- package/plugins/sp/skills/spur-cli/references/features/verbs.md +122 -0
- package/plugins/sp/skills/spur-cli/references/features.md +234 -0
- package/plugins/sp/skills/spur-cli/references/init.md +119 -0
- package/plugins/sp/skills/spur-cli/references/message.md +98 -0
- package/plugins/sp/skills/spur-cli/references/rules/authoring-rules.md +212 -0
- package/plugins/sp/skills/spur-cli/references/rules/fine-tuning.md +148 -0
- package/plugins/sp/skills/spur-cli/references/rules/operations.md +228 -0
- package/plugins/sp/skills/spur-cli/references/rules/validation-and-extension.md +129 -0
- package/plugins/sp/skills/spur-cli/references/rules.md +209 -0
- package/plugins/sp/skills/spur-cli/references/serve.md +58 -0
- package/plugins/sp/skills/spur-cli/references/tasks/l3-guard-cheatsheet.md +98 -0
- package/plugins/sp/skills/spur-cli/references/tasks/section-editing.md +95 -0
- package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +361 -0
- package/plugins/sp/skills/spur-cli/references/tasks.md +280 -0
- package/plugins/sp/skills/spur-cli/references/team.md +133 -0
- package/plugins/sp/skills/spur-cli/references/workflows/authoring-workflows.md +226 -0
- package/plugins/sp/skills/spur-cli/references/workflows/operations.md +211 -0
- package/plugins/sp/skills/spur-cli/references/workflows/validation-and-extension.md +129 -0
- package/plugins/sp/skills/spur-cli/references/workflows.md +355 -0
- package/plugins/sp/skills/spur-dev/SKILL.md +224 -0
- package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +196 -0
- package/plugins/sp/skills/spur-dev/references/cross-cutting.md +680 -0
- package/plugins/sp/skills/spur-dev/references/decision-brief.md +80 -0
- package/plugins/sp/skills/spur-dev/references/dev-operations.md +546 -0
- package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +164 -0
- package/plugins/sp/skills/spur-dev/references/execution-batch.md +790 -0
- package/plugins/sp/skills/spur-dev/references/execution-workflow.md +352 -0
- package/plugins/sp/skills/spur-dev/references/feature-link-helper.md +191 -0
- package/plugins/sp/skills/spur-dev/references/flag-glossary.md +417 -0
- package/plugins/sp/skills/spur-dev/references/gate-checklists.md +171 -0
- package/plugins/sp/skills/spur-dev/references/glossary.md +95 -0
- package/plugins/sp/skills/spur-dev/references/idea-evaluation.md +80 -0
- package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +120 -0
- package/plugins/sp/skills/spur-dev/references/planning-workflow.md +302 -0
- package/plugins/sp/skills/spur-dev/references/product-planning.md +206 -0
- package/plugins/sp/skills/spur-dev/references/section-batching.md +24 -0
- package/plugins/sp/skills/sys-architecture/SKILL.md +155 -0
- package/plugins/sp/skills/sys-architecture/references/decision-method.md +137 -0
- package/plugins/sp/skills/sys-architecture/references/upkeep-survey.md +75 -0
- package/plugins/sp/skills/sys-debugging/SKILL.md +228 -0
- package/plugins/sp/skills/sys-debugging/references/debugging-protocol.md +62 -0
- package/plugins/sp/skills/test-driven-development/SKILL.md +248 -0
- package/plugins/sp/skills/wayfinder/SKILL.md +292 -0
- package/spur.js +6035 -4963
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dogfood-testing
|
|
3
|
+
description: "Drive a testee (skill/command/CLI) end-to-end as a real user, fix within a bounded retry budget, monitor with a live ledger, emit a structured report. Triggers: \"dogfood this\", \"drive this command end-to-end\", \"test this skill as a user\", \"dogfood report\"."
|
|
4
|
+
license: Apache-2.0
|
|
5
|
+
metadata:
|
|
6
|
+
author: spur
|
|
7
|
+
version: "1.2"
|
|
8
|
+
protocol: "sp:dogfood-testing@1.2"
|
|
9
|
+
platforms: "claude-code,codex,openclaw,opencode,antigravity"
|
|
10
|
+
interactions:
|
|
11
|
+
- pipeline
|
|
12
|
+
- reviewer
|
|
13
|
+
modes:
|
|
14
|
+
- observe
|
|
15
|
+
- fix
|
|
16
|
+
phases:
|
|
17
|
+
- plan
|
|
18
|
+
- execute
|
|
19
|
+
- monitor
|
|
20
|
+
- report
|
|
21
|
+
openclaw:
|
|
22
|
+
emoji: "🐕"
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# Dogfood Testing — The Backbone Skill
|
|
26
|
+
|
|
27
|
+
`sp:dogfood-testing` drives an agent skill, slash command, or CLI invocation **end-to-end** as a
|
|
28
|
+
real user would: run the testee step by step, fix what breaks (within a bounded retry budget),
|
|
29
|
+
monitor the whole run with a live ledger, and emit a structured report of what happened, what broke,
|
|
30
|
+
what was fixed, and what should improve.
|
|
31
|
+
|
|
32
|
+
This is the codification of the manual dogfooding loop run across tasks `0109`–`0114` and `0124`.
|
|
33
|
+
It backs the `/sp:dev-dogfood` thin-wrapper command — the command parameterizes the testee and
|
|
34
|
+
sinks; this skill owns the protocol.
|
|
35
|
+
|
|
36
|
+
## The 4-phase protocol at a glance
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
testee (a /sp:... command, Skill(...), or shell CLI invocation)
|
|
40
|
+
→ PLAN classify + derive steps + open dual artifacts (live + docs/dogfood) with status:running
|
|
41
|
+
→ EXECUTE run each step as a user; on failure, bounded diagnose→fix→re-run (or observe-only)
|
|
42
|
+
→ MONITOR dual-write ledger row to disk on every step resolve — never reconstruct from memory
|
|
43
|
+
→ REPORT finalize-or-abort (non-skippable): status complete|aborted, Cost block, both paths, footer
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Arguments
|
|
47
|
+
|
|
48
|
+
The command forwards these via `$ARGUMENTS`:
|
|
49
|
+
|
|
50
|
+
| Argument | Description | Default |
|
|
51
|
+
|----------|-------------|---------|
|
|
52
|
+
| `testee` | What to exercise — a slash command, agent skill, or CLI invocation (positional, required). Quote it if it contains flags. | (required) |
|
|
53
|
+
| `--agent <name\|auto>` | **Testee-scoped** agent: the agent the **testee** runs under, forwarded into the testee invocation. The driver (this skill) always runs in the current session. **Omit it** to forward nothing — the testee runs under its own default. See [§Testee-scoped agent](#testee-scoped-agent). | (omitted → forward nothing) |
|
|
54
|
+
| `--max-retry <n>` | Fix attempts per failed step. The **default is `2`** (fix mode): apply `Edit`/`Write` fixes to the working tree, up to 2 attempts per step. This flag is **mandatory** for two independent mutation sources: (a) pipeline-driving testees and (b) testees carrying a mutating `--fix` mode (`--fix all` / `--fix blockers-first`). Pass `--max-retry 0` for **observe-only**, or `--max-retry N` to acknowledge fix-mode mutation risk. For a mutating-`--fix` testee, `--max-retry 0` bounds the **driver only** — the testee still mutates the tree. | `2` unless the testee is pipeline-driving or carries a mutating `--fix` mode |
|
|
55
|
+
| `--save` | **Back-compat no-op for delivery.** Reports are always written to `docs/dogfood/…` and `.spur/run/dogfood/<run_id>.md`. The flag still documents/prints the report path. | always-on (flag optional) |
|
|
56
|
+
| `--task` | File findings as a review-template task via `spur task create --template review`. | off |
|
|
57
|
+
| `--chain-follow` | **Operator override for `--next` chains.** Permits the driver to follow the chain into named chained-leg artifacts (`.spur/run/<wbs>-verdict.json`, task-file section diffs, review tables) and attribute normally instead of stopping at the testing boundary. The flag licenses reading chained-leg evidence that already exists; it does NOT license the driver to execute the chained leg itself. Omit it to keep stop-at-testing as the default. See [§`--next` chain stop-at-testing](#next-chain-stop-at-testing) and [§Platform boundary (Claude Code)](#claude-code). | off |
|
|
58
|
+
| `--full` | Full report verbosity — emit all six sections even when a step set is sparse. Default omits empty narrative sections. | off |
|
|
59
|
+
|
|
60
|
+
> **Single-dash lenient parsing (R6b).** The argument parser accepts `-flag value` as equivalent to
|
|
61
|
+
> `--flag value` for `--max-retry`, `--agent`, `--save`, `--task`, `--full` (and their `--fix`/
|
|
62
|
+
> `--steps` siblings). This is intentional back-compat for terminal ergonomics, but it collides with
|
|
63
|
+
> the mutating-fix refuse-gate, which keys on `--max-retry` presence: an operator typing
|
|
64
|
+
> `-max-retry 3` on a pipeline-driving testee would bypass the refuse message if the gate ran on
|
|
65
|
+
> the raw string. It does not — the gate runs on the **normalized** token after parse. The driver
|
|
66
|
+
> MUST echo the normalized flag in its Phase-1 plan output (`Plan: testee invoked as …
|
|
67
|
+
> --max-retry 3 …`), not the operator's original spelling, so the operator sees which form was
|
|
68
|
+
> honored. A run that silently parsed `-max-retry 3` without echoing the normalized form is a P4
|
|
69
|
+
> finding (verify-0293) — the parsing is allowed, the silent treatment is not.
|
|
70
|
+
|
|
71
|
+
> ⚠️ **Repo-mutation warning.** The default is **fix mode (`--max-retry 2`)** — it applies
|
|
72
|
+
> `Edit`/`Write` fixes to the working tree as it finds breakages. For a non-mutating run, opt into
|
|
73
|
+
> **observe-only** with `--max-retry 0`: monitor and report, never touch files, full findings report
|
|
74
|
+
> still produced. Omission is ambiguous and MUST fail before planning when **either** of two
|
|
75
|
+
> independent mutation sources is present:
|
|
76
|
+
>
|
|
77
|
+
> - **Pipeline-driving testees** — tokens
|
|
78
|
+
> [`--next`, `dev-runall`, `dev-wrapall`, `dev-run`, `dev-wrap`, `dev-idea`,
|
|
79
|
+
> `runall`, `wrapall`, `run`, `wrap`, `idea`] matched as a **distinct hyphen-word**
|
|
80
|
+
> (machine-checked by
|
|
81
|
+
> [`detectPipelineDriving`](../../scripts/dogfood-testing/detect-pipeline-driving.ts);
|
|
82
|
+
> see [§Pipeline-driving word-boundary contract](#pipeline-driving-word-boundary-contract))
|
|
83
|
+
> → `⚠ pipeline-driving testee detected; pass --max-retry 0 (observe-only) or --max-retry N (fix mode, tree mutation acknowledged)`.
|
|
84
|
+
> - **Mutating `--fix` modes** — `--fix all` / `--fix blockers-first`, boundary-guarded via
|
|
85
|
+
> [`hasMutatingFixMode`](../../scripts/dogfood-testing/detect-pipeline-driving.ts) (never matches
|
|
86
|
+
> `--fix none` / `--focus all` / `--prefix all`). No pipeline token required: a verify/review leg
|
|
87
|
+
> with `--fix all` mutates the tree on its own (0280 dogfood P2, task 0293). Honesty note:
|
|
88
|
+
> `--max-retry 0` here bounds **the driver only** — the testee still mutates the tree — so the
|
|
89
|
+
> refuse message is
|
|
90
|
+
`⚠ mutating --fix mode detected (--fix all | --fix blockers-first); pass --max-retry 0 (observe-only for the driver; the testee still mutates the tree) or --max-retry N (fix mode, driver + testee both mutate)`.
|
|
91
|
+
|
|
92
|
+
## Phase 1 — Plan
|
|
93
|
+
|
|
94
|
+
0. **Refuse ambiguous mutation-source testees (live CLI gate — not prose-only).** Before deriving
|
|
95
|
+
steps, run the machine-checked detector as a shell command (do **not** re-implement the matcher
|
|
96
|
+
in-agent):
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
bun plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts \
|
|
100
|
+
--testee "<raw testee string>" \
|
|
101
|
+
[--max-retry-present] # pass this flag only when the dogfood invocation included --max-retry
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
- Exit **2** → print the stdout refuse line and **stop** (do not plan). The CLI refuses on either
|
|
105
|
+
of two independent mutation sources (task 0293); print whichever refuse message it emits:
|
|
106
|
+
- pipeline-driving: `⚠ pipeline-driving testee detected; pass --max-retry 0 (observe-only) or --max-retry N (fix mode, tree mutation acknowledged)`.
|
|
107
|
+
- mutating `--fix`: `⚠ mutating --fix mode detected (--fix all | --fix blockers-first); pass --max-retry 0 (observe-only for the driver; the testee still mutates the tree) or --max-retry N (fix mode, driver + testee both mutate)`.
|
|
108
|
+
- Exit **0** → proceed. Do not auto-substitute `--max-retry 0`.
|
|
109
|
+
- The matcher contract is unit-checked by `tests/dogfood-testing/pipeline-detect.test.ts`.
|
|
110
|
+
See [§Pipeline-driving word-boundary contract](#pipeline-driving-word-boundary-contract) and
|
|
111
|
+
[§Mutating `--fix` mode contract](#mutating---fix-mode-contract).
|
|
112
|
+
1. **Resolve + classify** the testee: slash command (`/sp:...`), agent skill (`Skill(...)`), or shell
|
|
113
|
+
CLI (`spur ...`, `bun run ...`). Everything before the first dogfood flag is the testee; if it
|
|
114
|
+
carries its own flags, it must be quoted.
|
|
115
|
+
2. **Derive ordered steps** from the testee's own docstring / `argument-hint` / workflow. If no step
|
|
116
|
+
list can be derived, treat the whole invocation as one step.
|
|
117
|
+
2b. **Implement-heavy advisory (W8 — emit at derivation time).** Immediately after step derivation,
|
|
118
|
+
re-run the gate with the derived step labels:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
bun plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts \
|
|
122
|
+
--testee "<raw testee string>" \
|
|
123
|
+
--max-retry-present \
|
|
124
|
+
--steps "step1 label||step2 label||..."
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
When stdout prints
|
|
128
|
+
`⚠ implement-heavy pipeline dogfood: prefer --max-retry 0 (observe-only) or step-split; operator --max-retry N overrides`,
|
|
129
|
+
surface that line in the live report §1/§2 **and** continue only because the operator already
|
|
130
|
+
passed an explicit `--max-retry`. Prefer observe-only or step-split on the next run. Record the
|
|
131
|
+
advisory in the ledger `Finding` column for implement-heavy steps. See
|
|
132
|
+
[§Cost segmentation for implement-heavy steps](#cost-segmentation-for-implement-heavy-steps).
|
|
133
|
+
3. **Open dual artifacts (always-on delivery — not gated on `--save`).**
|
|
134
|
+
- Generate `run_id` (uuid or timestamp-slug).
|
|
135
|
+
- `mkdir -p .spur/run/dogfood docs/dogfood`.
|
|
136
|
+
- Write **both** files with identical YAML frontmatter (`status: running`, testee, mode,
|
|
137
|
+
timestamps, paths, `protocol: sp:dogfood-testing@1.2`) + six section heading stubs + empty
|
|
138
|
+
Monitor Ledger table:
|
|
139
|
+
- Live: `.spur/run/dogfood/<run_id>.md`
|
|
140
|
+
- Report: `docs/dogfood/YYYY-MM-DD-<testee-slug>-dogfood.md`
|
|
141
|
+
- Canonical frontmatter and skeleton: [report-template.md](references/report-template.md).
|
|
142
|
+
- Column contract + dual-write: [monitor-ledger.md](references/monitor-ledger.md).
|
|
143
|
+
- **R2 workspace fingerprint (fix-mode and mutating-`--fix` dogfoods only).** When the run is
|
|
144
|
+
fix-mode or a mutating-`--fix` testee, record a `workspace_fingerprint` block (git HEAD +
|
|
145
|
+
`git status --porcelain` hash + timestamp) in the live ledger frontmatter. See
|
|
146
|
+
[§Workspace-drift guard](#workspace-drift-guard-r2--task-0296).
|
|
147
|
+
|
|
148
|
+
## Phase 2 — Execute + bounded fix
|
|
149
|
+
|
|
150
|
+
For each step, in order:
|
|
151
|
+
|
|
152
|
+
1. **Run** the step as a user would — forwarding `--agent` into the testee invocation (§below).
|
|
153
|
+
2. **Success** → log the row, advance.
|
|
154
|
+
3. **Failure** →
|
|
155
|
+
- `--max-retry 0` → log as an **Unresolved issue** with diagnosis, mutate nothing, advance.
|
|
156
|
+
- else → diagnose root cause → apply the smallest `Edit`/`Write` fix → **re-run the same step**,
|
|
157
|
+
up to `--max-retry` times, but **first re-take the workspace snapshot and check drift**
|
|
158
|
+
(R2 — see [§Workspace-drift guard](#workspace-drift-guard-r2--task-0296)). If drift is detected,
|
|
159
|
+
append a `drift:external` warning row and emit a P2 finding; never attribute drifted files to
|
|
160
|
+
the run or claim them as the fix. Pass within budget → **Fixed issue** (record the fix); still
|
|
161
|
+
failing → **Unresolved issue** (record everything tried). Either way, advance — partial signal
|
|
162
|
+
is the point.
|
|
163
|
+
|
|
164
|
+
**Fix discipline.** Fix the testee or its real dependency. Never weaken the testee, stub the failure
|
|
165
|
+
away, or `--no-verify` past a gate to make a step "pass". A fix that hides the bug you are hunting is
|
|
166
|
+
a **finding**, not a fix.
|
|
167
|
+
|
|
168
|
+
**Implement-heavy derived steps.** Each derived step that itself chains into further pipeline work
|
|
169
|
+
multiplies the run's blast radius — when a step is implement-heavy (a `--next` chain to `dev-run`, a
|
|
170
|
+
derived `wrap`/`wrapall`, a verify/review leg carrying a mutating repair mode `--fix all` /
|
|
171
|
+
`--fix blockers-first` — `--fix none` stays observational — or any testee that mutates more than its
|
|
172
|
+
own arguments), surface this in
|
|
173
|
+
the ledger row's `Finding` column and prefer **observe-only** or **step-splitting** rather than
|
|
174
|
+
driving the chain under fix mode. See
|
|
175
|
+
[§Cost segmentation for implement-heavy steps](#cost-segmentation-for-implement-heavy-steps) and
|
|
176
|
+
[§`--next` chain stop-at-testing](#next-chain-stop-at-testing).
|
|
177
|
+
|
|
178
|
+
## Phase 3 — Monitor
|
|
179
|
+
|
|
180
|
+
The ledger is updated **live on disk** during Phase 2 and is the single source of truth for the
|
|
181
|
+
report — the report is assembled from the files, not from memory.
|
|
182
|
+
|
|
183
|
+
On **every** step resolve:
|
|
184
|
+
|
|
185
|
+
1. Append/update the ledger row on the **live** file first.
|
|
186
|
+
2. Mirror the same row to the **report** path under `docs/dogfood/`.
|
|
187
|
+
3. Do **not** batch rows until Phase 4.
|
|
188
|
+
|
|
189
|
+
The final report MUST include a `### 3. Monitor Ledger` section containing those rows, and the
|
|
190
|
+
ledger's data-row count MUST equal the `**Steps:** N derived, N executed` declared in §2 of the report (N/A steps
|
|
191
|
+
documented explicitly as rows) — the cardinality rule in
|
|
192
|
+
[monitor-ledger.md](references/monitor-ledger.md). Full
|
|
193
|
+
methodology, column contract, token/cache estimation, multi-source Cost honesty, the cache-health
|
|
194
|
+
finding rule, and the **cache-conservation discipline** live in
|
|
195
|
+
**[monitor-ledger.md](references/monitor-ledger.md)**. Apply the conservation discipline while
|
|
196
|
+
monitoring — low cache% is usually the driver re-fetching data it already holds.
|
|
197
|
+
|
|
198
|
+
## Phase 4 — Report (finalize-or-abort — non-skippable)
|
|
199
|
+
|
|
200
|
+
**Terminal gate.** Before this skill may stop (PASS / PARTIAL / FAIL / observe-only end / abort /
|
|
201
|
+
any early exit), the driver MUST run the finalize-or-abort checklist. Skipping it is a **driver
|
|
202
|
+
contract violation**.
|
|
203
|
+
|
|
204
|
+
1. Set frontmatter `status: complete` or `status: aborted` and `finished_at`.
|
|
205
|
+
2. **Structure scrub (@1.2).** All six mandatory section headings exist **exactly once each**
|
|
206
|
+
(`### 1.` … `### 6.` — duplicates refuse `complete`). §5 Issues carries both `#### Fixed` and
|
|
207
|
+
`#### Unresolved` (with `(none)` when empty). Unfinished narrative sections:
|
|
208
|
+
`⚠ incomplete — not reached` — never invent What-We-Did / Issues / Findings fiction, and no
|
|
209
|
+
leftover "run in progress" markers may survive finalization.
|
|
210
|
+
3. **Ledger cardinality (@1.2).** Monitor Ledger data rows MUST equal the `**Steps:** N derived, N executed`
|
|
211
|
+
declared in §2 (N/A steps documented explicitly as rows). A mismatch refuses `complete`.
|
|
212
|
+
4. Write the **Cost** block under §2 (ledger `~estimate` + Method + confidence; `Meter: n/a` or
|
|
213
|
+
optional ccusage/agent usage when real). For any `chained:<step>` ledger row whose meter is not
|
|
214
|
+
observable, Fresh/Cached MUST be `~unknown` (or Cached `~0` with Basis `unobservable`) **and**
|
|
215
|
+
emit finding `P3 — chained-step cost not observable` — never invent chained totals.
|
|
216
|
+
5. **R2 drift check at finalize.** If a workspace fingerprint was recorded in Phase 1, re-take
|
|
217
|
+
the snapshot and diff against baseline minus the run's own touched files. If drift is detected,
|
|
218
|
+
append a `drift:external` warning row to the ledger and emit a mandatory P2 report finding
|
|
219
|
+
(under §6 Findings) stating the run's evidence is degraded, not voided. Never claim drifted
|
|
220
|
+
files as run work. See [§Workspace-drift guard](#workspace-drift-guard-r2--task-0296).
|
|
221
|
+
6. Sync final content to **both** live and report paths (always — not gated on `--save`).
|
|
222
|
+
7. **Footer mandatory (@1.2).** Print the mandatory summary footer with **both** `[Live: …]` and
|
|
223
|
+
`[Report: …]` always, **and mirror the footer block at the end of the report file**. A report
|
|
224
|
+
without the footer cannot set `status: complete`.
|
|
225
|
+
8. **Self-validate (task 0278 R6 — non-skippable).** Run the machine checker on the report body
|
|
226
|
+
**before** claiming `status: complete`:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
bun plugins/sp/scripts/dogfood-testing/validate-report.ts --file <report-path>
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Exit **0** → proceed. Exit **2** → set `status: aborted`, list every error code under §5
|
|
233
|
+
`#### Unresolved`, do **not** claim complete (closes non-@1.2 shapes like `## §1` without
|
|
234
|
+
`### 1.`–`### 6.` / footer). Exit **1** → usage/IO failure; fix path and re-run.
|
|
235
|
+
9. **Refusal rule (@1.2).** If any check above fails, set `status: aborted` (never `complete`) and
|
|
236
|
+
list each failed check under §5 `#### Unresolved`.
|
|
237
|
+
|
|
238
|
+
Full section contract, frontmatter, Cost shape, and footer:
|
|
239
|
+
**[report-template.md](references/report-template.md)**.
|
|
240
|
+
|
|
241
|
+
**Sinks** (composable):
|
|
242
|
+
- **Always-on report files** → live + `docs/dogfood/YYYY-MM-DD-<testee-slug>-dogfood.md` (see Phase 1).
|
|
243
|
+
- `--save` → no-op for delivery; still print/document the report path (back-compat).
|
|
244
|
+
- `--task` → file findings as a review task (`spur task create --template review`), writing the
|
|
245
|
+
**Findings** into the task's `#### Review Findings` table under `### Background`. See
|
|
246
|
+
[report-template.md → Task sink](references/report-template.md) for the `task check` L3 contract.
|
|
247
|
+
|
|
248
|
+
## Testee-scoped agent
|
|
249
|
+
|
|
250
|
+
`dogfood-testing` is a **driver** that runs *other* testees, so `--agent` here is different from the
|
|
251
|
+
standard `/sp:dev-*` semantics: it sets the agent the **testee** runs under, **not** the driver.
|
|
252
|
+
|
|
253
|
+
- The **driver** (this skill — planning, monitoring, reporting) always runs in the **current
|
|
254
|
+
session**. `--agent` never changes that.
|
|
255
|
+
- The **testee** invocation receives the forwarded `--agent`. Concretely: append/splice `--agent
|
|
256
|
+
<value>` into the testee's own flags before running it.
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
/sp:dev-dogfood "/sp:dev-run 0125 --auto" --agent codex
|
|
260
|
+
↓ driver = current session (monitors, reports)
|
|
261
|
+
↓ testee runs as: /sp:dev-run 0125 --auto --agent codex
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
If the testee does not accept `--agent` (e.g. a pure-inline command), record that as a **finding**
|
|
265
|
+
("testee ignores `--agent`") rather than forcing the flag. **Omitting `--agent` (the default)
|
|
266
|
+
forwards nothing** — the testee runs under whatever it would default to (which, for a `spur agent
|
|
267
|
+
run`-backed testee, is `--agent auto` → the configured default executor). There is no `inherit` or
|
|
268
|
+
`current` token: "run under the current agent" is simply the default for an inline slash command
|
|
269
|
+
(it executes in this session) and is **not** expressible for the spawned `spur agent run` path,
|
|
270
|
+
which always launches a fresh agent subprocess.
|
|
271
|
+
|
|
272
|
+
## When to use
|
|
273
|
+
|
|
274
|
+
- Debugging or hardening an agent skill / slash command you are actively developing.
|
|
275
|
+
- Validating a command works end-to-end before shipping it.
|
|
276
|
+
- Producing a structured findings report (and optionally a fix task) from a real run.
|
|
277
|
+
|
|
278
|
+
Do **not** use this skill for:
|
|
279
|
+
- Requirements-traceability verdicts — use `sp:code-verification` (`/sp:dev-verify`).
|
|
280
|
+
- SECU code review of a diff — use `sp:code-verification` (`/sp:dev-review`).
|
|
281
|
+
- Running a task through the fix pipeline — use `sp:spur-dev` (`/sp:dev-run`).
|
|
282
|
+
|
|
283
|
+
## Gotchas
|
|
284
|
+
|
|
285
|
+
1. **Observe-only for unfamiliar testees.** The default is fix mode (`--max-retry 2`), which mutates
|
|
286
|
+
the working tree. Against any testee you don't own or fully trust — or one that drives a long,
|
|
287
|
+
mutating pipeline — pass `--max-retry 0` first and inspect the findings before letting it apply
|
|
288
|
+
fixes.
|
|
289
|
+
2. **The ledger is live on disk, not reconstructed.** Honest fixed-vs-unresolved accounting depends
|
|
290
|
+
on dual-writing each step *as it happens* to both artifacts. Reconstructing at the end produces
|
|
291
|
+
fiction. Working-memory-only ledgers are a contract violation.
|
|
292
|
+
3. **A hiding fix is a finding.** If "fixing" a step would mask the bug, log it as a finding and
|
|
293
|
+
leave the step unresolved.
|
|
294
|
+
4. **Token numbers are estimates, but cache math is not free-form.** A skill cannot read its own
|
|
295
|
+
exact token meter, so label numbers `~estimate` and put Method + confidence in the Cost block;
|
|
296
|
+
however, cache% must be recomputable from Monitor Ledger row sums. Never invent or reuse a fixed
|
|
297
|
+
percentage. Optional meters (`ccusage`, agent usage) are session/day scope — never fake per-step.
|
|
298
|
+
5. **Testee-scoped `--agent`.** Don't confuse the driver agent (always current) with the testee
|
|
299
|
+
agent (the forwarded value).
|
|
300
|
+
6. **Stale command snapshot.** Slash-command definitions are snapshotted at session start. If you
|
|
301
|
+
just edited the testee command's own `.md` (or this command's), invoking it in the **same
|
|
302
|
+
session** may run the **old** body. Verify in a fresh session, or invoke the backing skill
|
|
303
|
+
directly, before trusting an in-session dogfood of a command you just changed. Note same-session
|
|
304
|
+
edits under §1 Testee when relevant.
|
|
305
|
+
7. **Finalize-or-abort is non-skippable.** Ending a run without updating `status`, syncing both
|
|
306
|
+
paths, and printing the footer with `[Live:]` + `[Report:]` fails the delivery contract — even if
|
|
307
|
+
the testee itself passed.
|
|
308
|
+
8. **`--save` is not required for a file.** Dual artifacts are always-on. Do not skip writing
|
|
309
|
+
`docs/dogfood/` because the operator omitted `--save`.
|
|
310
|
+
9. **Pipeline-driving + implement-heavy derived step ⇒ prefer observe-only or step-split.** When the
|
|
311
|
+
Phase 1.2b CLI emits the implement-heavy advisory (pipeline-driving + implement-heavy step), the
|
|
312
|
+
dogfood run is **recursive**: it tests a pipeline that mutates the repo while the driver may also
|
|
313
|
+
be in fix mode. Two mutation sources make attribution impossible. The advisory is **emitted at
|
|
314
|
+
derivation time** (not only as docs-time guidance). Operator's explicit `--max-retry N` proceeds;
|
|
315
|
+
prefer `--max-retry 0` or step-split next time. See
|
|
316
|
+
[§Cost segmentation for implement-heavy steps](#cost-segmentation-for-implement-heavy-steps).
|
|
317
|
+
10. **`--next` chain stop-at-testing when provenance is missing.** A `--next` chain (refine→run,
|
|
318
|
+
run→verify, etc.) runs each leg as its own pipeline stage. If the dogfood driver cannot observe
|
|
319
|
+
the chain's intermediate artifacts (task file sections, verify verdicts, review tables) — because
|
|
320
|
+
the chain ran in a subagent, a different session, or the artifacts were never written — the driver
|
|
321
|
+
MUST stop at the **testing boundary** of the chained step and report "chained-step provenance
|
|
322
|
+
missing; cannot attribute outcome" rather than fabricating an outcome from the final state. Do not
|
|
323
|
+
change the chained lifecycle's code (dev-run/dev-verify); this is a reporting discipline, not a
|
|
324
|
+
lifecycle change. See [§`--next` chain stop-at-testing](#next-chain-stop-at-testing).
|
|
325
|
+
|
|
326
|
+
## Pipeline-driving word-boundary contract
|
|
327
|
+
|
|
328
|
+
Pipeline-driving detection is **word-boundary**, not leading-space substring. The live gate is:
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
bun plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts --testee "<testee>" [--max-retry-present] [--steps "…"] [--json]
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
| Token shape | Examples | Matches | Rejects |
|
|
335
|
+
|-------------|----------|---------|---------|
|
|
336
|
+
| Flag / complete | `--next`, `dev-run`, `dev-runall`, `dev-wrap`, `dev-wrapall`, `dev-idea` | `/sp:dev-run 0125`, bare `--next` | `--next-gen`, `dev-runner` |
|
|
337
|
+
| Bare noun | `run`, `runall`, `wrap`, `wrapall`, `idea` | `task run 0042` | `runaway`, `wrapper`, `idealist` |
|
|
338
|
+
|
|
339
|
+
`-` is a **word character** for boundaries: a token must be a distinct hyphen-word. Contract tests:
|
|
340
|
+
`plugins/sp/tests/dogfood-testing/pipeline-detect.test.ts`. Helpers:
|
|
341
|
+
`detectPipelineDriving`, `isImplementHeavyStep`, `detectImplementHeavy`, `evaluateDogfoodGate` in
|
|
342
|
+
[`detect-pipeline-driving.ts`](../../scripts/dogfood-testing/detect-pipeline-driving.ts).
|
|
343
|
+
|
|
344
|
+
## Mutating `--fix` mode contract
|
|
345
|
+
|
|
346
|
+
Task 0293 extended the refuse gate to a **second, independent** mutation source: a testee carrying
|
|
347
|
+
a mutating `--fix` mode — `--fix all` or `--fix blockers-first`. Boundary-guarded via
|
|
348
|
+
`hasMutatingFixMode` so it never matches `--fix none`, `--focus all`, `--prefix all`, or substrings
|
|
349
|
+
inside other flags. No pipeline token required: a verify/review leg with `--fix all` mutates the
|
|
350
|
+
tree on its own (0280 dogfood P2 — the `--fix all` pass was the sole mutation source for 11 dataset
|
|
351
|
+
files, a workflow edit, and 2 corpus writes).
|
|
352
|
+
|
|
353
|
+
| Token shape | Matches | Rejects |
|
|
354
|
+
|-------------|---------|---------|
|
|
355
|
+
| `--fix all` / `--fix=all` / `--fix all` (case-insensitive) | `/sp:dev-verify 0299 --fix all`, `--fix=All`, `--fix BLOCKERS-FIRST` | `--fix none`, `--focus all`, `--prefix all`, `--fix-all-gen` |
|
|
356
|
+
|
|
357
|
+
Refuse message (R2 honesty — `--max-retry 0` bounds **the driver only**; the testee still mutates):
|
|
358
|
+
|
|
359
|
+
```
|
|
360
|
+
⚠ mutating --fix mode detected (--fix all | --fix blockers-first); pass --max-retry 0
|
|
361
|
+
(observe-only for the driver; the testee still mutates the tree) or --max-retry N (fix mode,
|
|
362
|
+
driver + testee both mutate)
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
This is **not** a new token in `PIPELINE_TOKENS` (R5/R6 — back-compat): pipeline-driving and
|
|
366
|
+
mutating-fix are checked by separate matchers, and pipeline-driving's refuse message wins when both
|
|
367
|
+
co-occur (its message is the superset — chain + tree mutation).
|
|
368
|
+
|
|
369
|
+
## Workspace-drift guard (R2 — task 0296)
|
|
370
|
+
|
|
371
|
+
A fix-mode dogfood (`--max-retry ≥ 1`) or a mutating-`--fix` testee writes to the **shared working
|
|
372
|
+
tree**. A concurrent external writer — formatter, another agent, the operator's editor — is then
|
|
373
|
+
indistinguishable from testee/driver mutation in the ledger and report. The guard detects drift,
|
|
374
|
+
attributes it to the external writer, and never claims drifted files as run work.
|
|
375
|
+
|
|
376
|
+
**Additive only** — protocol stays `sp:dogfood-testing@1.2`; the new ledger/report fields are
|
|
377
|
+
optional so existing reports remain valid. No gate refuses a run on drift; drift degrades the
|
|
378
|
+
evidence (a warning + finding), never voids it.
|
|
379
|
+
|
|
380
|
+
### Fingerprint (Phase 1)
|
|
381
|
+
|
|
382
|
+
Before the first testee step, record a **workspace fingerprint** in the live ledger frontmatter:
|
|
383
|
+
|
|
384
|
+
```yaml
|
|
385
|
+
workspace_fingerprint:
|
|
386
|
+
head: <`git rev-parse HEAD`>
|
|
387
|
+
porcelain_hash: <stable hash of `git status --porcelain` output>
|
|
388
|
+
taken_at: <ISO-8601>
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
The hash is over the raw `git status --porcelain` bytes (e.g. `shasum -a 256`). Store the snapshot
|
|
392
|
+
string is NOT required — the hash is enough to detect a change; the live file already records what
|
|
393
|
+
the run itself touched via ledger rows.
|
|
394
|
+
|
|
395
|
+
### Drift check (before each fix application + once at Phase 4 finalize)
|
|
396
|
+
|
|
397
|
+
Re-take the snapshot and diff it against the baseline **minus files the run itself has touched**
|
|
398
|
+
(driver fixes + testee-attributed writes from the ledger `Fix Applied` column). Drift check points:
|
|
399
|
+
|
|
400
|
+
1. Immediately before each Phase 2 fix application (so a fix isn't credited to drift, and drift
|
|
401
|
+
isn't credited to a fix).
|
|
402
|
+
2. Once at Phase 4 finalize (so the final report acknowledges any drift that happened mid-run).
|
|
403
|
+
|
|
404
|
+
**Not** after every testee step — observe-only runs (`--max-retry 0`) stay zero-overhead. A run with
|
|
405
|
+
no fix applications and a clean tree at finalize needs no drift row.
|
|
406
|
+
|
|
407
|
+
### What drift is — and is not
|
|
408
|
+
|
|
409
|
+
**Drift** = a tracked file changes that neither the driver nor the testee ledger row names.
|
|
410
|
+
**Explained** set = files named in ledger `Fix Applied` cells (driver fixes) plus files the testee
|
|
411
|
+
wrote that the driver recorded in the ledger (testee-attributed writes). Anything else in
|
|
412
|
+
`git status --porcelain` that is new or modified since baseline is drift.
|
|
413
|
+
|
|
414
|
+
### On detecting drift
|
|
415
|
+
|
|
416
|
+
- Append a **warning ledger row** tagged `drift:external` in the Step column: paths in `Fix Applied`,
|
|
417
|
+
`Outcome: drift`, `Basis: <fingerprint diff>`. Do NOT mark the step PASSED/FIXED on account of
|
|
418
|
+
drift; the row records the drift, it does not change a step's outcome.
|
|
419
|
+
- Emit a **mandatory report finding** under §6 Findings — `P2 — workspace drift detected during
|
|
420
|
+
run; attribution to external writer` — naming the drifted paths and the snapshot delta. The report
|
|
421
|
+
explicitly states the run's evidence is degraded, not voided.
|
|
422
|
+
- The driver **never** claims drifted files as its own or the testee's work. A fix ledger row's
|
|
423
|
+
`Fix Applied` cites only the file:line the driver changed; drift rows cite the drifted paths
|
|
424
|
+
separately.
|
|
425
|
+
|
|
426
|
+
### Worktree advisory (mutating dogfoods)
|
|
427
|
+
|
|
428
|
+
For fix-mode dogfoods of **pipeline-driving** or **mutating-`--fix`** testees (the two refuse-gate
|
|
429
|
+
cases above), the §Mutating `--fix` mode contract recommends running the dogfood in an **isolated
|
|
430
|
+
`git worktree`** so concurrent external writers cannot collide with the run. This is **advisory,
|
|
431
|
+
not a hard gate** — the refuse-gate semantics from task 0293 are unchanged. A worktree removes the
|
|
432
|
+
drift case entirely (no concurrent writer can reach the isolated checkout), which is why it is the
|
|
433
|
+
preferred setup for mutating dogfoods where the operator cares about clean attribution.
|
|
434
|
+
|
|
435
|
+
## Step-splitting recipe (implement-heavy pipeline dogfoods)
|
|
436
|
+
|
|
437
|
+
When the Phase 1.2b advisory fires (or you know the testee is implement-heavy), **prefer two or
|
|
438
|
+
more non-recursive dogfood runs** over one nested fix-mode chain. Worked recipe:
|
|
439
|
+
|
|
440
|
+
**Bad (recursive fix-mode):** dogfood the whole refine→run→verify chain under `--max-retry N` —
|
|
441
|
+
the driver mutates while the testee pipeline also mutates; attribution fails.
|
|
442
|
+
|
|
443
|
+
```bash
|
|
444
|
+
# Avoid unless you fully accept dual mutation:
|
|
445
|
+
/sp:dev-dogfood "/sp:dev-refine 0278 --auto --next" --max-retry 3 --full
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
**Good (step-split):**
|
|
449
|
+
|
|
450
|
+
```bash
|
|
451
|
+
# 1) Observe refine only (no tree mutation from the driver)
|
|
452
|
+
/sp:dev-dogfood "/sp:dev-refine 0278 --auto" --max-retry 0 --full
|
|
453
|
+
|
|
454
|
+
# 2) After refine is clean, dogfood implement/run alone
|
|
455
|
+
/sp:dev-dogfood "/sp:dev-run 0278 --auto --mode implement" --max-retry 2 --full
|
|
456
|
+
|
|
457
|
+
# 3) Dogfood verify as its own run (corpus gates only)
|
|
458
|
+
/sp:dev-dogfood "/sp:dev-verify 0278 --auto --next --force --focus all --fix all" --max-retry 2 --full
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
Rules: one mutation source per dogfood run; use `--max-retry 0` for unfamiliar pipeline legs; keep
|
|
462
|
+
dual artifacts / finalize for each run. Linked from the implement-heavy advisory
|
|
463
|
+
(`⚠ implement-heavy pipeline dogfood: prefer --max-retry 0 (observe-only) or step-split…`).
|
|
464
|
+
|
|
465
|
+
## Cost segmentation for implement-heavy steps
|
|
466
|
+
|
|
467
|
+
A dogfood run where a derived step is implement-heavy (the step itself writes code, runs a pipeline
|
|
468
|
+
leg, or otherwise mutates more than its own arguments) has **two cost sources** that MUST be
|
|
469
|
+
segregated in the Cost block and the ledger:
|
|
470
|
+
|
|
471
|
+
| Source | What it is | How to label in the ledger |
|
|
472
|
+
|--------|------------|----------------------------|
|
|
473
|
+
| Driver cost | Tokens the dogfood driver spent planning, monitoring, fixing, reporting | normal per-step `Fresh` / `Cached` columns |
|
|
474
|
+
| Chained-step cost | Tokens the testee's own pipeline leg spent (subagent invocations, file reads/writes inside `/sp:dev-run`, etc.) | a separate ledger row tagged `chained:<step>`; Fresh/Cached estimated from observed subagent output, or `~unknown` when not observable |
|
|
475
|
+
|
|
476
|
+
Rules:
|
|
477
|
+
|
|
478
|
+
1. Never fold chained-step cost into the driver's row. The whole point of dogfooding a
|
|
479
|
+
pipeline-driving testee is to see what the *testee* costs to run, separately from what the driver
|
|
480
|
+
costs to monitor it.
|
|
481
|
+
2. When the chained step ran in a subagent or session whose usage data the driver cannot read, label
|
|
482
|
+
the chained row `~unknown` and emit a **P3** finding: "chained-step cost not observable — candidate
|
|
483
|
+
for surfacing subagent usage in the driver context." Do not invent a number.
|
|
484
|
+
3. The chained row still counts toward the aggregate cache% — but mark it pessimistically
|
|
485
|
+
(`Cached = ~0`) when the basis is missing, per the anti-fiction rule in
|
|
486
|
+
[monitor-ledger.md](references/monitor-ledger.md).
|
|
487
|
+
|
|
488
|
+
## `--next` chain stop-at-testing
|
|
489
|
+
|
|
490
|
+
When a dogfood testee ends in `--next` (refine→run, run→verify, idea→plan→run), the chain runs
|
|
491
|
+
multiple lifecycle legs back-to-back. Each leg has its own testing boundary — the point past which the
|
|
492
|
+
dogfood driver cannot attribute an outcome to a specific leg's contract.
|
|
493
|
+
|
|
494
|
+
**Stop-at-testing rule.** If the driver cannot observe a chained leg's intermediate artifact (task
|
|
495
|
+
file section update, verify verdict, review table, pipeline transition), the driver STOPS at that
|
|
496
|
+
leg's testing boundary and reports:
|
|
497
|
+
|
|
498
|
+
```
|
|
499
|
+
chained-leg <name>: provenance missing — intermediate artifact not observable from driver context
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
Do NOT:
|
|
503
|
+
|
|
504
|
+
- Fabricate a PASS/FAIL for the chained leg from the repo's final state. The final state reflects
|
|
505
|
+
every leg's effect combined; attributing it to one leg is fiction.
|
|
506
|
+
- Change the chained lifecycle's code (`dev-run`, `dev-verify`, `dev-refine`) to emit artifacts the
|
|
507
|
+
dogfood driver can read. The chain's contract is owned by `sp:spur-dev`; this skill reports on it,
|
|
508
|
+
it does not alter it. Surface the gap as a finding instead.
|
|
509
|
+
- Silently skip the chained leg in the ledger. Record the row with outcome `provenance-missing` and a
|
|
510
|
+
P3 finding.
|
|
511
|
+
|
|
512
|
+
**`--chain-follow` (sanctioned override).** The operator passes `--chain-follow` to grant the
|
|
513
|
+
driver permission to read the chained leg's named artifacts (`.spur/run/<wbs>-verdict.json`,
|
|
514
|
+
task-file section diffs, review tables) after the leg completes and attribute normally. The flag
|
|
515
|
+
licenses **reading** chained-leg evidence that already exists — it does NOT license the driver to
|
|
516
|
+
execute the chained leg itself. The legacy "operator may direct" prose direction is still honored
|
|
517
|
+
for back-compat; `--chain-follow` is the explicit, machine-recognizable form. Omitting the flag
|
|
518
|
+
keeps stop-at-testing as the **default**. The flag is a driver attribute only — it does not change
|
|
519
|
+
`detect-pipeline-driving` gate semantics (it is not a testee mutation source). See
|
|
520
|
+
[§Arguments](#arguments).
|
|
521
|
+
|
|
522
|
+
## Additional Resources
|
|
523
|
+
|
|
524
|
+
- [references/report-template.md](references/report-template.md) — the report section contract +
|
|
525
|
+
mandatory summary footer + task-sink L3 rule.
|
|
526
|
+
- [references/monitor-ledger.md](references/monitor-ledger.md) — the live-ledger column contract,
|
|
527
|
+
token/cache estimation heuristic, and the cache-health finding rule.
|
|
528
|
+
|
|
529
|
+
## Platform Notes
|
|
530
|
+
|
|
531
|
+
### Claude Code
|
|
532
|
+
|
|
533
|
+
Native — `Skill()` delegation, argument substitution, and the `Edit`/`Write`/`Bash` toolset work
|
|
534
|
+
directly. The `/sp:dev-dogfood` command is the entry point.
|
|
535
|
+
|
|
536
|
+
**Platform boundary (R3 — task 0296).** On Claude Code, `Skill()` runs **inline** in the current
|
|
537
|
+
session — there is no subprocess boundary, so a chained `--next` leg (refine→run, run→verify)
|
|
538
|
+
dispatched from the driver runs in the **same session** and is not independently observable. A
|
|
539
|
+
`--next` dogfood forced to follow the chain would lose per-leg provenance. Therefore a `--next`
|
|
540
|
+
dogfood on Claude Code ends **stop-at-testing** at the chain's testing boundary unless the operator
|
|
541
|
+
overrides — either by passing `--chain-follow` (the sanctioned mechanism; see
|
|
542
|
+
[§Arguments](#arguments) and [§`--next` chain stop-at-testing](#next-chain-stop-at-testing)) or by
|
|
543
|
+
**running the chained leg as its own standalone invocation**, which is exactly how the 0281 pair
|
|
544
|
+
completed: the dev-run dogfood stopped at testing, and `/sp:dev-verify 0281 --auto --next --force
|
|
545
|
+
--focus all --fix all` was driven as its own dogfood (the verify dogfood report). This is a
|
|
546
|
+
reporting discipline, not a bug in the chain — the chain's contract is owned by `sp:spur-dev`.
|
|
547
|
+
|
|
548
|
+
### Codex / OpenClaw / OpenCode / Antigravity
|
|
549
|
+
|
|
550
|
+
Run the four-phase protocol via the Bash/CLI toolset; invoke this skill directly for the protocol
|
|
551
|
+
logic and the `spur` CLI for the `--task` sink. Parse `--json` where the testee supports it.
|
|
552
|
+
|
|
553
|
+
A session on these platforms never sees `Skill()` reference-file expansion, so the report contract
|
|
554
|
+
is restated here **verbatim** rather than by pointer — do not fall back to a looser ad hoc report
|
|
555
|
+
shape just because `report-template.md` wasn't auto-loaded.
|
|
556
|
+
|
|
557
|
+
**Always-on dual artifacts (not gated on `--save`).** Every run MUST open and maintain:
|
|
558
|
+
|
|
559
|
+
- Live: `.spur/run/dogfood/<run_id>.md`
|
|
560
|
+
- Report: `docs/dogfood/YYYY-MM-DD-<testee-slug>-dogfood.md`
|
|
561
|
+
|
|
562
|
+
Both start with YAML frontmatter including `status: running | aborted | complete`, `run_id`,
|
|
563
|
+
`protocol: sp:dogfood-testing@1.2`, and paths. Dual-write a ledger row to both files on every step
|
|
564
|
+
resolve. On stop, set `status` to `complete` or `aborted` (finalize-or-abort — non-skippable).
|
|
565
|
+
|
|
566
|
+
**The six mandatory section headings** (in order, each report MUST contain all six):
|
|
567
|
+
|
|
568
|
+
1. `### 1. Testee` (include **Repro:** line)
|
|
569
|
+
2. `### 2. Execution Summary` (include `#### Cost` with Method, confidence, Meter)
|
|
570
|
+
3. `### 3. Monitor Ledger`
|
|
571
|
+
4. `### 4. What We Did`
|
|
572
|
+
5. `### 5. Issues`
|
|
573
|
+
6. `### 6. Findings`
|
|
574
|
+
|
|
575
|
+
Unfinished narrative sections after abort: `⚠ incomplete — not reached` (never invent).
|
|
576
|
+
|
|
577
|
+
**The ledger requirement.** `### 3. Monitor Ledger` MUST contain the live per-step ledger table
|
|
578
|
+
populated on disk during Phase 2/3 as steps run, never reconstructed from memory at the end.
|
|
579
|
+
|
|
580
|
+
**Cost honesty.** Ledger totals are `~estimate` with Method + confidence LOW unless a real meter
|
|
581
|
+
(`ccusage` day/session, agent usage fields) is also present (then MEDIUM). If no meter:
|
|
582
|
+
`Meter: n/a`. Never invent billed precision.
|
|
583
|
+
|
|
584
|
+
**The footer requirement.** Every report MUST end by printing this exact block (verdict is strictly
|
|
585
|
+
`PASS` / `PARTIAL` / `FAIL`, grading the testee, not the surrounding task):
|
|
586
|
+
|
|
587
|
+
```
|
|
588
|
+
── Dogfood Summary ──
|
|
589
|
+
Result: PASS (N fixed, N unresolved, N findings)
|
|
590
|
+
Tokens: ~N total | ~N cached (~X% hit rate) [~estimate]
|
|
591
|
+
|
|
592
|
+
Fixed issues:
|
|
593
|
+
• <label> (or: (none))
|
|
594
|
+
|
|
595
|
+
Unresolved issues:
|
|
596
|
+
• <label> (or: (none))
|
|
597
|
+
|
|
598
|
+
Findings (P1+P2):
|
|
599
|
+
• P? — <label> (or: (none))
|
|
600
|
+
|
|
601
|
+
[Live: .spur/run/dogfood/<run_id>.md]
|
|
602
|
+
[Report: docs/dogfood/YYYY-MM-DD-<slug>-dogfood.md]
|
|
603
|
+
[Task: <wbs>] ← only with --task
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
A report missing any of the six headings, the on-disk live ledger, dual paths, terminal `status`,
|
|
607
|
+
the Cost block, or this footer does not satisfy the dogfood contract on this platform, regardless
|
|
608
|
+
of `Skill()` availability.
|