@gobing-ai/spur 0.4.7 → 0.4.9

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 (145) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/pipeline-budgets.json +2 -2
  3. package/config/rules/boundary/config-loading-ownership.yaml +1 -0
  4. package/config/rules/boundary/sp-plugin-standalone.yaml +1 -1
  5. package/config/rules/boundary/sp-script-placement.yaml +1 -1
  6. package/config/rules/docs/sourced-api-claims.yaml +45 -7
  7. package/config/rules/strict/runtime-boundaries.yaml +40 -1
  8. package/config/rules/structure/protected-files.yaml +1 -1
  9. package/config/rules/surface/check-cli-surface.yaml +33 -0
  10. package/config/rules/typescript/no-debugger.yaml +3 -0
  11. package/config/workflow-candidates.json +2 -2
  12. package/config/workflows/feature-verification.yaml +6 -11
  13. package/config/workflows/history-anatomy.yaml +14 -28
  14. package/config/workflows/idea-pipeline.yaml +6 -19
  15. package/config/workflows/pr-review.yaml +9 -16
  16. package/config/workflows/task-pipeline.yaml +16 -23
  17. package/config/workflows/wrapup-pipeline.yaml +21 -63
  18. package/package.json +3 -3
  19. package/plugins/sp/README.md +70 -37
  20. package/plugins/sp/agents/super-planner.md +5 -5
  21. package/plugins/sp/agents/super-reviewer.md +2 -2
  22. package/plugins/sp/commands/dev-changelog.md +1 -1
  23. package/plugins/sp/commands/dev-daily.md +1 -1
  24. package/plugins/sp/commands/dev-pr-review.md +1 -1
  25. package/plugins/sp/commands/dev-review-session.md +1 -1
  26. package/plugins/sp/commands/dev-runall.md +4 -4
  27. package/plugins/sp/commands/dev-verify.md +4 -6
  28. package/plugins/sp/commands/dev-verifyall.md +4 -5
  29. package/plugins/sp/hooks/hooks.json +11 -1
  30. package/plugins/sp/lib/context-post-tool.ts +1 -1
  31. package/plugins/sp/lib/context-session-start.ts +1 -1
  32. package/plugins/sp/lib/context-session-stop.ts +1 -1
  33. package/plugins/sp/lib/destructive-policy.ts +65 -1
  34. package/plugins/sp/plugin.json +2 -5
  35. package/plugins/sp/{hooks → scripts/hooks}/agent-lifecycle.ts +1 -1
  36. package/plugins/sp/scripts/hooks/careful-guard.ts +94 -0
  37. package/plugins/sp/{hooks → scripts/hooks}/context-post-tool.ts +2 -2
  38. package/plugins/sp/{hooks → scripts/hooks}/context-session-start.ts +1 -1
  39. package/plugins/sp/{hooks → scripts/hooks}/context-session-stop.ts +1 -1
  40. package/plugins/sp/{hooks → scripts/hooks}/fleet-guest-stop.ts +6 -4
  41. package/plugins/sp/{hooks → scripts/hooks}/task-write-guard.ts +38 -21
  42. package/plugins/sp/skills/code-implementation/SKILL.md +1 -1
  43. package/plugins/sp/skills/code-verification/SKILL.md +8 -8
  44. package/plugins/sp/skills/code-verification/references/secu-review.md +4 -3
  45. package/plugins/sp/skills/code-verification/references/verdict-schema.md +9 -1
  46. package/plugins/sp/skills/daily-summary/SKILL.md +4 -5
  47. package/plugins/sp/skills/dogfood-testing/SKILL.md +9 -9
  48. package/plugins/sp/skills/dogfood-testing/references/report-template.md +1 -1
  49. package/plugins/sp/skills/history-anatomy/references/modes.md +2 -2
  50. package/plugins/sp/skills/next-router/references/routing-table.md +1 -1
  51. package/plugins/sp/skills/parallel-execution/SKILL.md +1 -1
  52. package/plugins/sp/skills/pr-reviewing/SKILL.md +14 -15
  53. package/plugins/sp/skills/session-review/SKILL.md +3 -3
  54. package/plugins/sp/skills/source-driven-development/SKILL.md +7 -4
  55. package/plugins/sp/skills/spur-check/SKILL.md +14 -13
  56. package/plugins/sp/skills/spur-cli/SKILL.md +1 -1
  57. package/plugins/sp/skills/spur-cli/references/agent.md +12 -0
  58. package/plugins/sp/skills/spur-cli/references/builder.md +27 -6
  59. package/plugins/sp/skills/spur-cli/references/features.md +6 -1
  60. package/plugins/sp/skills/spur-cli/references/history.md +3 -0
  61. package/plugins/sp/skills/spur-cli/references/self.md +5 -3
  62. package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +3 -0
  63. package/plugins/sp/skills/spur-cli/references/tasks.md +13 -3
  64. package/plugins/sp/skills/spur-cli/references/workflows.md +36 -1
  65. package/plugins/sp/skills/spur-dev/SKILL.md +1 -1
  66. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +1 -1
  67. package/plugins/sp/skills/spur-dev/references/dev-operations.md +12 -12
  68. package/plugins/sp/skills/spur-dev/references/execution-batch-report.md +10 -11
  69. package/plugins/sp/skills/spur-dev/references/execution-batch.md +16 -17
  70. package/plugins/sp/skills/spur-dev/references/execution-parallel-isolation.md +1 -1
  71. package/plugins/sp/skills/spur-dev/references/execution-worktree-landing.md +8 -11
  72. package/plugins/sp/skills/spur-dev/references/execution-worktree-setup.md +6 -8
  73. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +1 -1
  74. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +33 -40
  75. package/plugins/sp/skills/spur-dev/references/structured-trace-emission.md +24 -24
  76. package/plugins/sp/skills/spur-doctor/SKILL.md +5 -4
  77. package/spur.js +41901 -30598
  78. package/config/plugin-scripts.json +0 -116
  79. package/config/script-placement-baseline.json +0 -33
  80. package/plugins/sp/hooks/careful-guard.ts +0 -74
  81. package/plugins/sp/hooks/pi/guard-extension.ts +0 -304
  82. package/plugins/sp/lib/dogfood-pipeline.ts +0 -265
  83. package/plugins/sp/lib/dogfood-report.ts +0 -278
  84. package/plugins/sp/lib/history-anatomy.generated.d.mts +0 -112
  85. package/plugins/sp/lib/history-anatomy.generated.mjs +0 -691
  86. package/plugins/sp/lib/idea-handoff.generated.d.mts +0 -17
  87. package/plugins/sp/lib/idea-handoff.generated.mjs +0 -1446
  88. package/plugins/sp/lib/inline-run-app.ts +0 -68
  89. package/plugins/sp/lib/inline-run.generated.d.mts +0 -37
  90. package/plugins/sp/lib/inline-run.generated.mjs +0 -3103
  91. package/plugins/sp/lib/plan-projection.generated.d.mts +0 -197
  92. package/plugins/sp/lib/plan-projection.generated.mjs +0 -982
  93. package/plugins/sp/lib/quality-gate.generated.d.mts +0 -139
  94. package/plugins/sp/lib/quality-gate.generated.mjs +0 -30510
  95. package/plugins/sp/lib/residual-scan.generated.d.mts +0 -93
  96. package/plugins/sp/lib/residual-scan.generated.mjs +0 -383
  97. package/plugins/sp/lib/run-summary-core.ts +0 -225
  98. package/plugins/sp/lib/spur-bin.ts +0 -36
  99. package/plugins/sp/lib/step-profile.generated.d.mts +0 -71
  100. package/plugins/sp/lib/step-profile.generated.mjs +0 -174
  101. package/plugins/sp/lib/transcript.ts +0 -112
  102. package/plugins/sp/scripts/batch-plan.mjs +0 -1096
  103. package/plugins/sp/scripts/batch-plan.ts +0 -145
  104. package/plugins/sp/scripts/batch-preflight.mjs +0 -423
  105. package/plugins/sp/scripts/batch-preflight.ts +0 -270
  106. package/plugins/sp/scripts/commit-guard.mjs +0 -226
  107. package/plugins/sp/scripts/commit-guard.ts +0 -248
  108. package/plugins/sp/scripts/daily-summary/daily-summary.mjs +0 -626
  109. package/plugins/sp/scripts/daily-summary/daily-summary.ts +0 -855
  110. package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.mjs +0 -211
  111. package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts +0 -110
  112. package/plugins/sp/scripts/dogfood-testing/validate-report.mjs +0 -282
  113. package/plugins/sp/scripts/dogfood-testing/validate-report.ts +0 -98
  114. package/plugins/sp/scripts/feature-verification-steps.mjs +0 -82
  115. package/plugins/sp/scripts/feature-verification-steps.ts +0 -164
  116. package/plugins/sp/scripts/history-anatomy-cache.mjs +0 -931
  117. package/plugins/sp/scripts/history-anatomy-cache.ts +0 -247
  118. package/plugins/sp/scripts/idea-handoff.mjs +0 -32
  119. package/plugins/sp/scripts/idea-handoff.ts +0 -47
  120. package/plugins/sp/scripts/inline-run-dispatch.mjs +0 -131
  121. package/plugins/sp/scripts/inline-run-dispatch.ts +0 -115
  122. package/plugins/sp/scripts/inline-run-setup.mjs +0 -746
  123. package/plugins/sp/scripts/inline-run-setup.ts +0 -198
  124. package/plugins/sp/scripts/persist-out-check.mjs +0 -217
  125. package/plugins/sp/scripts/persist-out-check.ts +0 -249
  126. package/plugins/sp/scripts/pr-reviewing.mjs +0 -712
  127. package/plugins/sp/scripts/pr-reviewing.ts +0 -952
  128. package/plugins/sp/scripts/quality-gate.mjs +0 -30491
  129. package/plugins/sp/scripts/quality-gate.ts +0 -80
  130. package/plugins/sp/scripts/residual-scan.mjs +0 -634
  131. package/plugins/sp/scripts/residual-scan.ts +0 -248
  132. package/plugins/sp/scripts/run-summary.mjs +0 -758
  133. package/plugins/sp/scripts/run-summary.ts +0 -107
  134. package/plugins/sp/scripts/script-root.mjs +0 -129
  135. package/plugins/sp/scripts/script-root.ts +0 -199
  136. package/plugins/sp/scripts/session-timeline.mjs +0 -359
  137. package/plugins/sp/scripts/session-timeline.ts +0 -190
  138. package/plugins/sp/scripts/task-diffstat.mjs +0 -181
  139. package/plugins/sp/scripts/task-diffstat.ts +0 -219
  140. package/plugins/sp/scripts/workflow-step-profile.mjs +0 -338
  141. package/plugins/sp/scripts/workflow-step-profile.ts +0 -165
  142. package/plugins/sp/scripts/wrapup-drift-probe.mjs +0 -190
  143. package/plugins/sp/scripts/wrapup-drift-probe.ts +0 -261
  144. package/plugins/sp/scripts/wrapup-steps.mjs +0 -627
  145. package/plugins/sp/scripts/wrapup-steps.ts +0 -891
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env bun
2
+
3
+ /**
4
+ * careful-guard — PreToolUse guard for destructive shell commands (task 0215, R3).
5
+ *
6
+ * Warn (permission `ask`) before a `Bash` tool call runs a destructive command — `rm -rf`
7
+ * (any flag spelling, including the POSIX uppercase `-R`), `DROP TABLE`/`DROP DATABASE`/
8
+ * `TRUNCATE`, `git push --force`/`-f`/`+refspec`, `git reset --hard`, `git checkout .`/
9
+ * `git restore .`, `kubectl delete`, `docker system prune`. The operator can confirm to
10
+ * proceed. Pure pattern-match + decision, no domain logic (mirrors `task-write-guard`).
11
+ *
12
+ * Git global options between the executable and the subcommand are recognized — any run of them,
13
+ * not a fixed list: value-less flags (`--no-pager`, `--bare`, `-p`, …), glued long values
14
+ * (`--git-dir=<path>`), and value-taking options in separated form (`-C <path>`,
15
+ * `-c <name>=<value>`, `--git-dir|--work-tree|--namespace|--config-env|--attr-source <value>`).
16
+ * So `git -C . push --force` and `git --no-pager push --force` classify exactly like
17
+ * `git push --force`; the lexical pass only removes that option span and never executes git or
18
+ * expands a substitution. The run cannot cross a command boundary (`;`, `&`, `|`, newline).
19
+ *
20
+ * **Safe exceptions:** `rm -rf` of well-known build/dependency caches (`node_modules`, `dist`,
21
+ * `.next`, `coverage`, `build`, `.turbo`, `.cache`) passes without a warning — deleting a rebuildable
22
+ * cache is routine, not dangerous.
23
+ *
24
+ * **Output contract** (superskill ADR-039 `hook run`): allow prints **nothing** (exit 0). Ask prints
25
+ * Claude-native PreToolUse JSON with the reason in `permissionDecisionReason` (the confirm prompt) and
26
+ * `systemMessage` (Claude Code's user-facing warning, which the host-neutral `{decision,reason}` form
27
+ * cannot carry). Hosts that cannot confirm (Codex, omp, generic) receive a deny with the reason:
28
+ * superskill fails an unconfirmable ask closed. Pi confirms through its native host adapter.
29
+ *
30
+ * **Fail-open contract:** every error path — unparseable payload, non-Bash tool, empty command —
31
+ * allows (prints nothing). A broken guard must never wedge an agent tool call.
32
+ *
33
+ * **Escape hatch:** `SPUR_CAREFUL=off` short-circuits to allow.
34
+ *
35
+ * Classification itself lives in `lib/destructive-policy.ts` — one policy, every platform
36
+ * adapter runs this hook through superskill). This file owns the hook payload/decision shape only.
37
+ * Registered in `hooks/hooks.json` as `PreToolUse` / matcher `Bash` (task 0215 R3).
38
+ */
39
+
40
+ import { classifyCommand } from '../../lib/destructive-policy';
41
+ import { getEnvVar } from '../../lib/env';
42
+
43
+ interface ToolPayload {
44
+ tool_name?: string;
45
+ tool_input?: { command?: string };
46
+ }
47
+
48
+ /** Allow: print nothing and exit 0 (no objection; the host's own permission rules still apply). */
49
+ function allow(): never {
50
+ process.exit(0);
51
+ }
52
+
53
+ /** Ask the operator to confirm, with the reason on the prompt and as a user-facing warning. */
54
+ function ask(reason: string): never {
55
+ process.stdout.write(
56
+ JSON.stringify({
57
+ hookSpecificOutput: {
58
+ hookEventName: 'PreToolUse',
59
+ permissionDecision: 'ask',
60
+ permissionDecisionReason: reason,
61
+ },
62
+ systemMessage: reason,
63
+ }),
64
+ );
65
+ process.exit(0);
66
+ }
67
+
68
+ async function main(): Promise<void> {
69
+ if (getEnvVar('SPUR_CAREFUL') === 'off') allow();
70
+
71
+ const stdinText = await Bun.stdin.text();
72
+ let payload: ToolPayload;
73
+ try {
74
+ payload = JSON.parse(stdinText) as ToolPayload;
75
+ } catch {
76
+ allow(); // unparseable payload — fail open
77
+ }
78
+
79
+ if (payload.tool_name !== 'Bash') allow();
80
+
81
+ const command = payload.tool_input?.command ?? '';
82
+ if (command.trim() === '') allow();
83
+
84
+ const hit = classifyCommand(command);
85
+ if (hit !== null) {
86
+ ask(
87
+ `This command looks like ${hit} — a destructive operation. Confirm you intend to run it. ` +
88
+ 'Set SPUR_CAREFUL=off to disable this guard.',
89
+ );
90
+ }
91
+ allow();
92
+ }
93
+
94
+ if (import.meta.main) void main();
@@ -10,8 +10,8 @@
10
10
  */
11
11
 
12
12
  import { join } from 'node:path';
13
- import { recordToolUseEvent, type ToolPayload } from '../lib/context-post-tool';
14
- import { getEnvVar } from '../lib/env';
13
+ import { recordToolUseEvent, type ToolPayload } from '../../lib/context-post-tool';
14
+ import { getEnvVar } from '../../lib/env';
15
15
 
16
16
  if (import.meta.main) {
17
17
  void (async () => {
@@ -7,7 +7,7 @@
7
7
  * (legacy policy) and every error path exits 0 with no output.
8
8
  */
9
9
 
10
- import { recordSessionStartFromPayloadText } from '../lib/context-session-start';
10
+ import { recordSessionStartFromPayloadText } from '../../lib/context-session-start';
11
11
 
12
12
  if (import.meta.main) {
13
13
  try {
@@ -7,7 +7,7 @@
7
7
  * `agent.run`'s shutdown stays a no-op because the owner gate lives in the core, not here.
8
8
  */
9
9
 
10
- import { recordSessionEndFromPayloadText } from '../lib/context-session-stop';
10
+ import { recordSessionEndFromPayloadText } from '../../lib/context-session-stop';
11
11
 
12
12
  if (import.meta.main) {
13
13
  try {
@@ -15,9 +15,11 @@
15
15
  * - **Bounded.** The pending check is `spur agent wait --inbox <id> --timeout 2000`, which also
16
16
  * heartbeats the guest lease (R5), and the reason names at most the first few messages.
17
17
  *
18
- * Block contract (both hosts that support it): exit 0 with JSON on stdout —
19
- * `{"decision":"block","reason":"<non-empty>"}`. Claude Code uses the reason as the stop reason;
20
- * Codex turns it into the next user prompt. Hosts that drop the Stop event (`codex exec` on
18
+ * Block contract: exit 0 with the host-neutral superskill result on stdout (ADR-039) —
19
+ * `{"decision":"block","reason":"<non-empty>"}`. `superskill hook run` renders it per host: Claude
20
+ * Code and Codex receive that same Stop JSON (Claude uses the reason as the stop reason; Codex turns
21
+ * it into the next user prompt), omp/Pi get exit 2 + the reason on stderr. No pending work prints
22
+ * nothing. Hosts that drop the Stop event (`codex exec` on
21
23
  * 0.160.0 — see `docs/plans/2026-10-05-codex-guest-spike.md`) simply never call it.
22
24
  *
23
25
  * Self-contained by design: hooks are bundled standalone at install time, so this file imports
@@ -27,7 +29,7 @@
27
29
  import { spawnSync } from 'node:child_process';
28
30
  import { existsSync, readdirSync, readFileSync } from 'node:fs';
29
31
  import { join } from 'node:path';
30
- import { getEnvVar } from '../lib/env';
32
+ import { getEnvVar } from '../../lib/env';
31
33
 
32
34
  /** Budget for the pending-work probe; the hook must never noticeably slow a turn. */
33
35
  export const GUEST_STOP_PROBE_MS = 2000;
@@ -7,21 +7,28 @@
7
7
  * hand. Pure delegation: ownership is decided by `spur task resolve --strict --json`'s exit code
8
8
  * alone (exit 0 → owned, non-zero → unowned).
9
9
  *
10
+ * **Output contract** (superskill ADR-039 `hook run`): allow prints **nothing** (exit 0) — a printed
11
+ * Claude `permissionDecision:"allow"` would auto-approve the call and bypass the user's permission
12
+ * rules. Deny prints Claude-native PreToolUse JSON carrying the reason twice: `permissionDecisionReason`
13
+ * (what Claude Code feeds back to the model, and what `hook run` turns into exit 2 + stderr on
14
+ * Codex/omp/generic hosts) and `systemMessage` (Claude Code's user-facing warning — the one field the
15
+ * host-neutral `{decision,reason}` form cannot carry, which is why this guard stays Claude-native).
16
+ *
10
17
  * **Fail-open contract** (inherited from the pre-N3 shim and from superskill's runner): every error
11
18
  * path — unparseable payload, non-Write/Edit tool, empty path, missing `spur` binary, spawn
12
- * failure, timeout, `spur task resolve` non-zero exit, non-JSON stdout — emits an `allow`
13
- * decision. A broken guard must never wedge an agent tool call.
19
+ * failure, timeout, `spur task resolve` non-zero exit, non-JSON stdout — allows (prints nothing).
20
+ * A broken guard must never wedge an agent tool call.
14
21
  *
15
22
  * **Escape hatch:** `SPUR_WRITE_GUARD=off` short-circuits to allow.
16
23
  *
17
- * Self-contained by design (Wave E, task 0181, R3). Installed hook configs still use the portable
18
- * `superskill hook run sp task-write-guard` entrypoint from task 0151, while this source script keeps
19
- * the real guard decisions versioned and covered by this repo's test gate.
24
+ * Self-contained by design (Wave E, task 0181, R3): `node:*` builtins and relative imports only.
25
+ * Installed hook configs invoke `superskill hook run sp task-write-guard`, which resolves this file
26
+ * as `scripts/hooks/task-write-guard.ts` under the native plugin root or the staged scripts root.
20
27
  */
21
28
 
22
29
  import { spawnSync } from 'node:child_process';
23
- import { getEnvVar } from '../lib/env';
24
- import { couldBeTaskFile } from '../lib/task-file-policy';
30
+ import { getEnvVar } from '../../lib/env';
31
+ import { couldBeTaskFile } from '../../lib/task-file-policy';
25
32
 
26
33
  interface ToolPayload {
27
34
  tool_name?: string;
@@ -30,12 +37,23 @@ interface ToolPayload {
30
37
 
31
38
  type TaskOwnership = 'owned' | 'unowned' | 'unknown';
32
39
 
33
- function preToolUseDecision(decision: 'allow' | 'deny', reason?: string): never {
34
- const out: Record<string, unknown> = {
35
- hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: decision },
36
- };
37
- if (reason !== undefined) out.systemMessage = reason;
38
- process.stdout.write(JSON.stringify(out));
40
+ /** Allow: print nothing and exit 0 (no objection; the host's own permission rules still apply). */
41
+ function allow(): never {
42
+ process.exit(0);
43
+ }
44
+
45
+ /** Deny with a reason the model (`permissionDecisionReason`) and the user (`systemMessage`) both see. */
46
+ function deny(reason: string): never {
47
+ process.stdout.write(
48
+ JSON.stringify({
49
+ hookSpecificOutput: {
50
+ hookEventName: 'PreToolUse',
51
+ permissionDecision: 'deny',
52
+ permissionDecisionReason: reason,
53
+ },
54
+ systemMessage: reason,
55
+ }),
56
+ );
39
57
  process.exit(0);
40
58
  }
41
59
 
@@ -55,35 +73,34 @@ function resolveSpurTaskOwnership(filePath: string, cwd: string): TaskOwnership
55
73
  }
56
74
 
57
75
  async function main(): Promise<void> {
58
- if (getEnvVar('SPUR_WRITE_GUARD') === 'off') preToolUseDecision('allow');
76
+ if (getEnvVar('SPUR_WRITE_GUARD') === 'off') allow();
59
77
 
60
78
  const stdinText = await Bun.stdin.text();
61
79
  let payload: ToolPayload;
62
80
  try {
63
81
  payload = JSON.parse(stdinText) as ToolPayload;
64
82
  } catch {
65
- preToolUseDecision('allow'); // unparseable payload — fail open
83
+ allow(); // unparseable payload — fail open
66
84
  }
67
85
 
68
86
  const toolName = payload.tool_name ?? '';
69
- if (toolName !== 'Write' && toolName !== 'Edit') preToolUseDecision('allow');
87
+ if (toolName !== 'Write' && toolName !== 'Edit') allow();
70
88
 
71
89
  const filePath = payload.tool_input?.file_path ?? '';
72
- if (filePath === '') preToolUseDecision('allow');
90
+ if (filePath === '') allow();
73
91
  // Skip the `spur task resolve` subprocess (~120ms) for paths whose basename
74
92
  // cannot name a task file — that is every ordinary source edit.
75
- if (!couldBeTaskFile(filePath)) preToolUseDecision('allow');
93
+ if (!couldBeTaskFile(filePath)) allow();
76
94
 
77
95
  const ownership = resolveSpurTaskOwnership(filePath, getEnvVar('CLAUDE_PROJECT_DIR') ?? process.cwd());
78
96
  if (ownership === 'owned') {
79
- preToolUseDecision(
80
- 'deny',
97
+ deny(
81
98
  `${filePath} is a task file owned by the spur corpus. Edit it through the spur CLI ` +
82
99
  '(e.g. `spur task update <wbs> --section <name> --from-file <file>`), not a raw ' +
83
100
  'Write/Edit. Set SPUR_WRITE_GUARD=off to bypass.',
84
101
  );
85
102
  }
86
- preToolUseDecision('allow');
103
+ allow();
87
104
  }
88
105
 
89
106
  void main();
@@ -169,7 +169,7 @@ that single full gate.
169
169
 
170
170
  **Worker iteration check order (task 1142 R3):**
171
171
  1. The **changed-path matrix** below (narrow behavior tests + affected consumers);
172
- 2. the resolved `quality-gate` script in `light` mode (source-repo probe, else the installed twin) (biome on changed files, per-workspace typecheck, rule presets `rules:pre`/`rules:post`, related tests).
172
+ 2. `spur task gate <wbs> light` (biome on changed files, per-workspace typecheck, rule presets `rules:pre`/`rules:post`, related tests).
173
173
 
174
174
  Neither step takes the full project gate. The full gate is named only for the pipeline's `test` and `test-recheck` hops.
175
175
 
@@ -284,9 +284,8 @@ the deterministic Testing writer `spur task record` (section authorship never ha
284
284
  # write .spur/run/<wbs>-verdict.json (shape in references/verdict-schema.md), then:
285
285
  spur task record <wbs> --verdict-file .spur/run/<wbs>-verdict.json # renders ## Testing, flips proven boxes
286
286
  # F96 residual sweep (observe-only): scan + fold AFTER record, under every --fix mode (0987).
287
- RESIDUAL=$(superskill script path sp residual-scan.mjs)
288
- node "$RESIDUAL" scan <wbs>
289
- node "$RESIDUAL" fold <wbs>
287
+ spur task residual <wbs> scan
288
+ spur task residual <wbs> fold
290
289
  # Downgrade only: re-record so Testing carries the final (folded) verdict.
291
290
  [ "$(jq -r .verdict .spur/run/<wbs>-verdict.json)" = PASS ] \
292
291
  || spur task record <wbs> --verdict-file .spur/run/<wbs>-verdict.json
@@ -297,10 +296,9 @@ node "$RESIDUAL" fold <wbs>
297
296
  > `residual-sweep` check in place (PASS → PARTIAL when a blocking residual exists), and the
298
297
  > downgrade-only re-record transcribes it — a manual verify cannot certify what the pipeline would
299
298
  > reject. The sweep runs after `record` (same order as the pipeline, 0983/0987): before it, a
300
- > verdict-proven box is still unticked and a clean PASS would fold to PARTIAL. Resolve the
301
- > script via `superskill script path sp residual-scan.mjs`; shipped surfaces never reference
302
- > `plugins/sp/scripts/` directly (script-contract-check rule 4). When the task reaches `done`
303
- > through `--next`, run `residual-scan settle` (links follow-up tasks; best-effort).
299
+ > verdict-proven box is still unticked and a clean PASS would fold to PARTIAL. The sweep is the
300
+ > `spur task residual` verb (no plugin script to resolve). When the task reaches `done` through
301
+ > `--next`, run `spur task residual <wbs> settle` (files the follow-up task; best-effort).
304
302
 
305
303
  > **Corrections: the answer file is the source of truth.** `spur task record` re-transcribes
306
304
  > `## Testing` from the verdict artifact — direct `--section Testing` writes are futile. Fix
@@ -447,11 +445,13 @@ gate is **active**, evaluate feature AC satisfaction via the existing CLI.
447
445
 
448
446
  ```bash
449
447
  SPUR_BIN="${SPUR_BIN:-$([ -f apps/cli/src/index.ts ] && echo 'bun apps/cli/src/index.ts' || echo spur)}"
450
- $SPUR_BIN feature check <featureId> --json
448
+ $SPUR_BIN feature check <featureId> --as done --strict --json
451
449
  $SPUR_BIN task list --feature <featureId> --json
452
450
  ```
453
451
 
454
452
  3. Classify **Shippable: PASS** only if **all** of:
453
+ - Strict completion exits 0: PASS feature-verification receipts and required dogfood evidence.
454
+ Projection changes no status; active-state checks are insufficient.
455
455
  - No finding whose code/message indicates **linked but unverified** scenarios
456
456
  (`L4_SCENARIO_UNVERIFIED`).
457
457
  - No **orphan / uncovered** feature scenarios (`L4_ORPHAN_SCENARIOS`,
@@ -83,7 +83,7 @@ verdict artifact so quality failures are not lost behind a requirements-only PAS
83
83
  Before declaring a task `done`, run this lightweight checklist. It catches the most common oversights that survive the formal pipeline gates:
84
84
 
85
85
  - [ ] Check receipt `.spur/run/<wbs>-check-receipt.json` reports `reuse: true` for the current
86
- digest via `quality-gate.ts status`; run `bun run spur-check` only when it reports stale or
86
+ digest via `spur task gate <wbs> status`; run `bun run spur-check` only when it reports stale or
87
87
  missing (0940).
88
88
  - [ ] No `TODO` or `FIXME` without a linked task WBS.
89
89
  - [ ] `git status` shows only intentional changes (no debug artifacts, no temp files).
@@ -91,8 +91,9 @@ Before declaring a task `done`, run this lightweight checklist. It catches the m
91
91
  - [ ] No `--no-verify`, `--force`, or new suppression comments added to bypass gates.
92
92
  - [ ] Solution section contains `file:line` citations for every changed file.
93
93
  - [ ] API/library claims in changed docs carry a source citation (URL or `path:line`) and an honest
94
- confidence level (HIGH/MEDIUM/LOW) per source-driven-development; the deterministic advisory backstop is
95
- the `cited-version-strings` / `cited-api-claims` / `cited-api-claims-confidence` rules
94
+ confidence level (HIGH/MEDIUM/LOW) per source-driven-development — a HIGH claim must show the
95
+ source it was verified against on the same line (MEDIUM/LOW need no anchor); the deterministic advisory backstop is
96
+ the `cited-version-strings` / `cited-api-claims` / `cited-api-claims-confidence` / `cited-high-confidence` rules
96
97
  (`.spur/rules/docs/sourced-api-claims.yaml`, run ad hoc — not wired into a preset).
97
98
  - [ ] Review section has P1–P4 findings table (even if all rows are empty — the table itself proves review happened).
98
99
 
@@ -170,6 +170,14 @@ before the proof capture (task 1109), but it qualifies **unique** basenames only
170
170
  basename (two tracked files share it) is reported and left untouched, and line drift and
171
171
  `L4.anchor-subject-mismatch` are never repaired by that pass — those remain the author's rows.
172
172
 
173
+ A **workspace-relative** path fails the same way, and is the easier mistake to make because the
174
+ command it came from is real. `(cd apps/cli && bun test tests/commands/builder/pr.test.ts)` is the
175
+ right way to run the suite, but `tests/commands/builder/pr.test.ts` does not resolve from the repo
176
+ root, so the AC-coverage guard reports `missing: <AC> — <path>` and refuses `done` (observed
177
+ 2026-10-16, task 1215 — the repair was a fresh verify pass over the whole answer). Cite both halves:
178
+ the workspace-rooted command you ran, then the repo-root-relative anchor of the file it names
179
+ (`apps/cli/tests/commands/builder/pr.test.ts`). One anchor per cited file per cell is enough.
180
+
173
181
  ## Source citations for external claims (task 1070)
174
182
 
175
183
  A Requirement/AC evidence cell that asserts an external API/library claim must carry a verifiable
@@ -185,7 +193,7 @@ citation in the SAME cell, or lint rejects the row with `evidence-citation` (blo
185
193
  presence-only — which citation proves which claim is not deterministically decidable.
186
194
  - The same two predicates (`hasClaimMarker` / `hasCitationForm` in
187
195
  `packages/app/src/services/verify-answer-lint.ts`) gate the review report's findings table through
188
- `residual-scan review-gate` as the blocking `review-contract` category — one definition of
196
+ `spur task residual <wbs> review-gate` as the blocking `review-contract` category — one definition of
189
197
  "external claim" and one set of accepted citation forms for both paths.
190
198
 
191
199
  ## Hedged evidence is rejected on MET rows
@@ -52,13 +52,13 @@ The daily-summary skill:
52
52
 
53
53
  ```bash
54
54
  # Generate summary for today
55
- node "$(superskill script path sp daily-summary/daily-summary.mjs)"
55
+ spur history summary
56
56
 
57
57
  # Generate summary for a specific date
58
- node "$(superskill script path sp daily-summary/daily-summary.mjs)" --date 2026-04-17
58
+ spur history summary --date 2026-04-17
59
59
 
60
60
  # Show summary without writing file
61
- node "$(superskill script path sp daily-summary/daily-summary.mjs)" --dry-run
61
+ spur history summary --dry-run
62
62
  ```
63
63
 
64
64
  ## Workflows
@@ -165,7 +165,6 @@ Read the skill file and follow the workflow manually.
165
165
 
166
166
  ## Additional Resources
167
167
 
168
- - **Script source:** [scripts/daily-summary/daily-summary.ts](../../scripts/daily-summary/daily-summary.ts) — CLI implementation
169
- - **Tests:** [tests/daily-summary/daily-summary.test.ts](../../tests/daily-summary/daily-summary.test.ts) — unit coverage for parsing, date ranges, markdown output
168
+ - **CLI:** `spur history summary [--date d] [--dry-run] [--output p] [--no-git] [--no-ccusage]` — see `sp:spur-cli` (history reference)
170
169
  - **Related skills:** `sp:dev-handover` (blocker handoff), `sp:dev-changelog` (commit-based changelog), `sp:spur-cli` (task management)
171
170
  - **Upstream CLI:** [ccusage](https://github.com/ryoppippi/ccusage) — AI agent token usage reporter
@@ -82,11 +82,11 @@ The command forwards these via `$ARGUMENTS`:
82
82
  > <!-- pipeline-tokens:end -->
83
83
  > matched as a **distinct hyphen-word**
84
84
  > (machine-checked by
85
- > [`detectPipelineDriving`](../../lib/dogfood-pipeline.ts);
85
+ > `detectPipelineDriving` (`spur agent dogfood gate`);
86
86
  > see [§Pipeline-driving word-boundary contract](#pipeline-driving-word-boundary-contract))
87
87
  > → `⚠ pipeline-driving testee detected; pass --max-retry 0 (observe-only) or --max-retry N (fix mode, tree mutation acknowledged)`.
88
88
  > - **Mutating `--fix` modes** — `--fix all` / `--fix blockers-first`, boundary-guarded via
89
- > [`hasMutatingFixMode`](../../lib/dogfood-pipeline.ts) (never matches
89
+ > `hasMutatingFixMode` (`spur agent dogfood gate`) (never matches
90
90
  > `--fix none` / `--focus all` / `--prefix all`). No pipeline token required: a verify/review leg
91
91
  > with `--fix all` mutates the tree on its own (0280 dogfood P2, task 0293). Honesty note:
92
92
  > `--max-retry 0` here bounds **the driver only** — the testee still mutates the tree — so the
@@ -100,7 +100,7 @@ The command forwards these via `$ARGUMENTS`:
100
100
  in-agent):
101
101
 
102
102
  ```bash
103
- node "$(superskill script path sp dogfood-testing/detect-pipeline-driving.mjs)" \
103
+ spur agent dogfood gate \
104
104
  --testee "<raw testee string>" \
105
105
  [--max-retry-present]
106
106
  ```
@@ -109,7 +109,7 @@ The command forwards these via `$ARGUMENTS`:
109
109
  of two independent mutation sources (task 0293); its two refuse lines are the ones quoted
110
110
  verbatim in the repo-mutation warning above.
111
111
  - Exit **0** → proceed. Do not auto-substitute `--max-retry 0`.
112
- - The matcher contract is unit-checked by `tests/dogfood-testing/pipeline-detect.test.ts`.
112
+ - The matcher contract is unit-checked by `packages/app/tests/services/dogfood/pipeline-detect.test.ts`.
113
113
  See [§Pipeline-driving word-boundary contract](#pipeline-driving-word-boundary-contract) and
114
114
  [§Mutating `--fix` mode contract](#mutating---fix-mode-contract).
115
115
  1. **Resolve + classify** the testee: slash command (`/sp:...`), agent skill (`Skill(...)`), or shell
@@ -121,7 +121,7 @@ The command forwards these via `$ARGUMENTS`:
121
121
  re-run the gate with the derived step labels:
122
122
 
123
123
  ```bash
124
- node "$(superskill script path sp dogfood-testing/detect-pipeline-driving.mjs)" \
124
+ spur agent dogfood gate \
125
125
  --testee "<raw testee string>" \
126
126
  --max-retry-present \
127
127
  --steps "step1 label||step2 label||..."
@@ -232,7 +232,7 @@ contract violation**.
232
232
  **before** claiming `status: complete`:
233
233
 
234
234
  ```bash
235
- node "$(superskill script path sp dogfood-testing/validate-report.mjs)" --file <report-path>
235
+ spur agent dogfood validate-report --file <report-path>
236
236
  ```
237
237
 
238
238
  Exit **0** → proceed. Exit **2** → set `status: aborted`, list every error code under §5
@@ -338,7 +338,7 @@ Do **not** use this skill for:
338
338
  Pipeline-driving detection is **word-boundary**, not leading-space substring. The live gate is:
339
339
 
340
340
  ```bash
341
- node "$(superskill script path sp dogfood-testing/detect-pipeline-driving.mjs)" --testee "<testee>" [--max-retry-present] [--steps "…"] [--json]
341
+ spur agent dogfood gate --testee "<testee>" [--max-retry-present] [--steps "…"] [--json]
342
342
  ```
343
343
 
344
344
  | Token shape | Examples | Matches | Rejects |
@@ -347,9 +347,9 @@ node "$(superskill script path sp dogfood-testing/detect-pipeline-driving.mjs)"
347
347
  | Bare noun | <!-- pipeline-tokens:start -->`run`, `runall`, `wrap`, `wrapall`, `idea`, `refineall`, `verifyall`<!-- pipeline-tokens:end --> | `task run 0042` | `runaway`, `wrapper`, `idealist` |
348
348
 
349
349
  `-` is a **word character** for boundaries: a token must be a distinct hyphen-word. Contract tests:
350
- `plugins/sp/tests/dogfood-testing/pipeline-detect.test.ts`. Helpers:
350
+ `packages/app/tests/services/dogfood/pipeline-detect.test.ts`. Helpers:
351
351
  `detectPipelineDriving`, `isImplementHeavyStep`, `detectImplementHeavy`, `evaluateDogfoodGate` in
352
- [`detect-pipeline-driving.ts`](../../scripts/dogfood-testing/detect-pipeline-driving.ts).
352
+ `spur agent dogfood gate` (absorbed into the CLI; was `plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts`).
353
353
 
354
354
  ## Mutating `--fix` mode contract
355
355
 
@@ -336,7 +336,7 @@ Before the skill may stop (success, partial, fail, observe-only end, or abort),
336
336
  and mirror the footer block at the **end of the report file**. A report whose body lacks the
337
337
  footer cannot set `status: complete`.
338
338
  8. **Self-validate (task 0278 R6):** run
339
- `node "$(superskill script path sp dogfood-testing/validate-report.mjs)" --file <report-path>` before
339
+ `spur agent dogfood validate-report --file <report-path>` before
340
340
  claiming `status: complete`. Exit 2 → `status: aborted` + list error codes under
341
341
  `#### Unresolved` (never force complete on a non-@1.2 shape).
342
342
  9. **Refusal rule (@1.2):** when any check above fails, set `status: aborted` and list every
@@ -2,8 +2,8 @@
2
2
 
3
3
  The skill resolves exactly two modes. Everything else fails loud. This matrix is the enforcement
4
4
  surface the workflow (0660) and the skill share; keep the vocabulary frozen. Execution note
5
- (0920): argument validation runs deterministically in the `history-anatomy-cache` helper `paths`
6
- command (logic core: `packages/app/src/services/history-anatomy.ts`, task 1005) before the
5
+ (0920): argument validation runs deterministically in `spur history anatomy paths`
6
+ (formerly the `history-anatomy-cache` helper) (logic core: `packages/app/src/services/history-anatomy.ts`, task 1005) before the
7
7
  workflow starts; the model hop no longer performs it.
8
8
 
9
9
  ## Mode vocabulary (frozen)
@@ -15,7 +15,7 @@ dispatcher: resolve target → load corpus → apply primary table → optional
15
15
 
16
16
  `sp:super-planner` (via `/sp:dev-runall`) **reads** TABLE A STOP preconditions for:
17
17
 
18
- 1. **Preflight** — skip pipeline launch when A2/A7/A8/A9 would stop `dev-next` (`batch-preflight.ts`).
18
+ 1. **Preflight** — skip pipeline launch when A2/A7/A8/A9 would stop `dev-next` (`spur task preflight`).
19
19
  2. **One-shot recovery** — after a failed pipeline, map status → primary hop (A1/A3/A5/A6/A7) at most once.
20
20
 
21
21
  It does **not** reimplement TABLES or replace `task-pipeline.yaml` with a `dev-next` loop. Keep this
@@ -104,7 +104,7 @@ was meant to avoid. Let the reviewer reach its own conclusion.
104
104
 
105
105
  - **`sp:spur-dev`** owns task selection and lifecycle. When a batch contains independent tasks, the spine consults this skill for the fan-out pattern.
106
106
  - **`sp:super-planner`** is the orchestrator that executes the fan-out. Its parallel mode (documented in its agent definition) applies the patterns from this skill.
107
- - **`/sp:dev-runall --mode parallel|auto`** is the task-batch entry point; its `batch-plan.mjs order` schedule applies this skill's dependency and file-overlap rows deterministically.
107
+ - **`/sp:dev-runall --mode parallel|auto`** is the task-batch entry point; its `spur task batch-plan order` schedule applies this skill's dependency and file-overlap rows deterministically.
108
108
 
109
109
  ## When to use
110
110
 
@@ -40,9 +40,9 @@ sp:pr-reviewing (this skill — mode routing, triage, fix, rules)
40
40
  │ deterministic spine, state order + guards:
41
41
  ▼
42
42
  pr-review.yaml ← workflow SSOT (seeded by spur init; project-tunable)
43
- │ every state resolves with `superskill script path` and shells out to:
43
+ │ every deterministic action shells out to:
44
44
  ▼
45
- staged pr-reviewing.ts ← Bun entrypoint for the tested git/gh core
45
+ `spur builder pr` ← Bun entrypoint for the tested git/gh core
46
46
  ```
47
47
 
48
48
  - **State order and guards** are defined once, in the workflow YAML. Do not re-derive them in
@@ -128,44 +128,43 @@ root causes rather than wording, prefer the smallest coherent patch, avoid drive
128
128
  ## Workflow-backed spine (`full`, `submit`, `rerun`)
129
129
 
130
130
  Run the workflow YAML's declared states in order. Every deterministic state invokes the
131
- staged entrypoint below, supports `--json`, and must be parsed. Stop at the first red gate and
131
+ `spur builder pr` operation below, supports `--json`, and must be parsed. Stop at the first red gate and
132
132
  report its artifact. The canonical installed invocation is:
133
133
 
134
134
  ```sh
135
- node "$(superskill script path sp pr-reviewing.mjs)" <subcommand> [flags]
135
+ spur builder pr <subcommand> [flags]
136
136
  ```
137
137
 
138
- Installed targets resolve the staged `.mjs` twin and execute it with Node, matching the standard
139
- superskill script contract.
138
+ The installed Spur CLI owns these operations; no staged script, Node twin or plugin resolver is used.
140
139
 
141
- 1. **Preflight** — `<script> preflight --base "$base" --json`. Hard-fails on a
140
+ 1. **Preflight** — `spur builder pr preflight --base "$base" --json`. Hard-fails on a
142
141
  detached HEAD, missing `gh` auth, no GitHub remote, a dirty tree, or the current branch
143
142
  being the base branch (a PR reviews a feature branch against the base; nothing on the
144
143
  base branch is reviewable, and the guard runs before any push can publish it). On a
145
144
  dirty tree, triage with the user (commit/stash/exclude) before continuing — the
146
145
  workflow refuses to guess.
147
- 2. **Hygiene** — `<script> hygiene --base "$base" --json`. `BLOCK` (secrets, `.env`, conflict markers,
146
+ 2. **Hygiene** — `spur builder pr hygiene --base "$base" --json`. `BLOCK` (secrets, `.env`, conflict markers,
148
147
  private keys) stops the run — never submit a tainted diff. `WARN` (debug residue) rides along
149
148
  into the report. This is a submission sanity check, not a second local review.
150
149
  3. **Precheck** — if the workflow YAML's `preReviewCmd` var is set, run it; a red check stops the
151
150
  run (do not spend a review request on code that fails its own gate). When unset, report that
152
151
  pre-review verification was not configured rather than inventing project commands.
153
- 4. **Push** — `<script> push --json`. Normal push only; sets upstream when missing.
154
- 5. **Ensure PR** — `<script> ensure-pr --base "$base" --json`. Reuses the branch's PR; creates with
152
+ 4. **Push** — `spur builder pr push --json`. Normal push only; sets upstream when missing.
153
+ 5. **Ensure PR** — `spur builder pr ensure-pr --base "$base" --json`. Reuses the branch's PR; creates with
155
154
  `gh pr create --fill` only when absent. Never a duplicate PR.
156
- 6. **Request** — `<script> request --focus "<focus>" --json` (`--force` in `rerun` mode). Dedupes when
155
+ 6. **Request** — `spur builder pr request --focus "<focus>" --json` (`--force` in `rerun` mode). Dedupes when
157
156
  Codex already reviewed the exact pushed HEAD (`ALREADY_REVIEWED` → skip to collect) or a marked
158
157
  request by the current GitHub user is still in flight (`ALREADY_REQUESTED` → pending). The
159
158
  request body is concise when the repo has `## Code Review Rules`, else carries the default
160
159
  actionable-issues focus. Records PR, URL, HEAD, and request time.
161
160
  7. **Wait** (full/rerun unless `--no-wait`; submit stops before it) —
162
- `<script> wait --since "$requestedAt" --head "$requestHead" --json`, using the request result so
161
+ `spur builder pr wait --since "$requestedAt" --head "$requestHead" --json`, using the request result so
163
162
  a fast response is not missed, `rerun` cannot reuse the prior review, and a moved HEAD fails loud.
164
163
  Polls every ~30s for up to
165
164
  ~10 minutes across the current HEAD's PR review and inline comments. Uncorrelated conversation
166
165
  comments are ignored. A current-HEAD clean review is a completed `CLEAN` outcome; findings are
167
166
  `FOUND`; timeout or no current-HEAD result is **pending, not failed** — collect later.
168
- 8. **Collect** — `<script> collect --since "$requestedAt" --head "$requestHead" --json`. Normalize
167
+ 8. **Collect** — `spur builder pr collect --since "$requestedAt" --head "$requestHead" --json`. Normalize
169
168
  only the requested HEAD and request window; then invoke `status` with the same bounds for
170
169
  PR/base/CI/local state. Never turn an absent, stale, or moved-HEAD result into `clean`.
171
170
  `--head` is mandatory on wait/collect/status (0771): an empty or missing pin fails loud
@@ -288,7 +287,7 @@ or review requests.
288
287
 
289
288
  - **Workflow SSOT:** `pr-review.yaml` (seeded by `spur init`; tune per project —
290
289
  wait budget, `preReviewCmd`, dedupe policy)
291
- - **Script source:** [scripts/pr-reviewing.ts](../../scripts/pr-reviewing.ts) — subcommand CLI
292
- - **Tests:** [tests/pr-reviewing.test.ts](../../tests/pr-reviewing.test.ts) — stubbed git/gh suites
290
+ - **Script source:** `spur builder pr` (absorbed; was `plugins/sp/scripts/pr-reviewing.ts`) — subcommand CLI
291
+ - **Tests:** `packages/app/tests/services/pr-review/pr-review.test.ts` — stubbed git/gh suites
293
292
  - **Related skills:** `sp:code-verification` (local SECUA review), `sp:functional-review`
294
293
  (requirements traceability) — complements, never substitutes, the independent Codex review
@@ -90,15 +90,15 @@ issues with its evidence. Notes stay report-only.
90
90
 
91
91
  1. **Resolve scope.** Review the active session from the operator's initiating request through the
92
92
  latest result. Use `[focus]` only to rank relevant material. Measure it with
93
- `node "$(superskill script path sp session-timeline.mjs)" --group "<ranges>"`: one segment per
93
+ `spur history timeline --group "<ranges>"`: one segment per
94
94
  operator prompt, read-only from the host transcript. Run it once without `--group` to list the
95
95
  segments, then map them to stages (`"1-3,4,5-6"`). It splits each segment into `work` and
96
96
  operator `wait` (idle before the next prompt plus AskUserQuestion answer time) and counts tokens
97
97
  once per message id. On pi the transcript is `$PI_SESSION_FILE` (pass it as `--transcript` when
98
98
  the run reports no host session id). **A measurement that returns `segments: []` with zero totals
99
99
  while the session had operator prompts is an unreadable or stale adapter, not an empty session:**
100
- compare the installed copy against this tree's `plugins/sp/scripts/session-timeline.mjs` and
101
- refresh it with `superskill install sp` before reporting numbers; report `n/a` until then.
100
+ check `spur --version` against this tree's release and upgrade the CLI before reporting
101
+ numbers; report `n/a` until then.
102
102
  The transcript resolves from `--transcript`, else `CLAUDE_CODE_SESSION_ID`, else `PI_SESSION_FILE`
103
103
  (the pi host sets it and no Claude session id); with none of them the measurement reports
104
104
  `available:false` with a reason and the table renders `n/a` instead of guessing. A pi
@@ -101,10 +101,13 @@ line: `Verification: HIGH|MEDIUM|LOW — <first failing check and deviation, or
101
101
  - **Honest confidence** — the stated HIGH/MEDIUM/LOW matches the evidence: HIGH requires a check against the pinned source this session; MEDIUM/LOW items are labeled, and LOW is never presented as fact.
102
102
  - **HIGH** — all three checks pass. **MEDIUM** — coverage intact but some citations are off-version (latest docs for a pinned dependency) or secondary-source only. **LOW** — an API/library claim lacks any citation, or a LOW-confidence claim was asserted as fact.
103
103
 
104
- Deterministic backstop: the `cited-version-strings`, `cited-api-claims` and
105
- `cited-api-claims-confidence` rules (`.spur/rules/docs/sourced-api-claims.yaml`) flag markdown lines
106
- that assert a version string or a time-anchored API claim with no citation anchor on the same line,
107
- and claim lines that carry no HIGH/MEDIUM/LOW level. They are an info-severity advisory backstop for
104
+ Deterministic backstop: the `cited-version-strings`, `cited-api-claims`,
105
+ `cited-api-claims-confidence` and `cited-high-confidence` rules
106
+ (`.spur/rules/docs/sourced-api-claims.yaml`) flag markdown lines that assert a version string or a
107
+ time-anchored API claim with no citation anchor on the same line, claim lines that carry no
108
+ HIGH/MEDIUM/LOW level, and claim lines that claim HIGH with no anchor — the one level that asserts
109
+ "verified this session", so its source must be on the line; MEDIUM (recalled) and LOW (memory only)
110
+ need no anchor by contract and are not flagged. They are an info-severity advisory backstop for
108
111
  this contract and are deliberately NOT wired into `recommended-pre-check` — run them ad hoc with
109
112
  `spur rule run --file .spur/rules/docs/sourced-api-claims.yaml`. The checks above and the SECUA
110
113
  checklist remain the enforcement points.