@gobing-ai/spur 0.3.47 → 0.3.48
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 +1 -1
- package/config/config.example.yaml +42 -11
- package/config/transition-shims.json +33 -0
- package/config/workflows/basic.yaml +2 -0
- package/config/workflows/docs-pipeline.yaml +2 -0
- package/config/workflows/feature-dev.yaml +8 -0
- package/config/workflows/idea-pipeline.yaml +10 -0
- package/config/workflows/planning-pipeline.yaml +4 -0
- package/config/workflows/task-pipeline.yaml +8 -0
- package/config/workflows/wayfinder-resolution.yaml +4 -0
- package/config/workflows/wrapup-pipeline.yaml +18 -1
- package/package.json +2 -2
- package/plugins/sp/agents/expert-spur.md +1 -0
- package/plugins/sp/commands/dev-arch.md +2 -1
- package/plugins/sp/commands/dev-brainstorm.md +2 -1
- package/plugins/sp/commands/dev-changelog.md +1 -0
- package/plugins/sp/commands/dev-daily.md +1 -0
- package/plugins/sp/commands/dev-debug.md +2 -1
- package/plugins/sp/commands/dev-dogfood.md +2 -1
- package/plugins/sp/commands/dev-featurechange.md +1 -0
- package/plugins/sp/commands/dev-find-conflict.md +2 -1
- package/plugins/sp/commands/dev-find-issue.md +20 -32
- package/plugins/sp/commands/dev-find-next.md +2 -1
- package/plugins/sp/commands/dev-fixall.md +1 -0
- package/plugins/sp/commands/dev-gitmsg.md +1 -0
- package/plugins/sp/commands/dev-gtd.md +1 -0
- package/plugins/sp/commands/dev-handover.md +1 -0
- package/plugins/sp/commands/dev-idea.md +1 -0
- package/plugins/sp/commands/dev-next.md +2 -1
- package/plugins/sp/commands/dev-parallel.md +2 -1
- package/plugins/sp/commands/dev-plan.md +2 -1
- package/plugins/sp/commands/dev-refine.md +5 -3
- package/plugins/sp/commands/dev-refineall.md +2 -1
- package/plugins/sp/commands/dev-refresh.md +2 -1
- package/plugins/sp/commands/dev-reverse.md +2 -1
- package/plugins/sp/commands/dev-review.md +2 -1
- package/plugins/sp/commands/dev-run.md +3 -2
- package/plugins/sp/commands/dev-runall.md +3 -2
- package/plugins/sp/commands/dev-simplify.md +2 -1
- package/plugins/sp/commands/dev-unit.md +2 -1
- package/plugins/sp/commands/dev-verify.md +2 -1
- package/plugins/sp/commands/dev-verifyall.md +2 -1
- package/plugins/sp/commands/dev-wrap.md +7 -5
- package/plugins/sp/commands/dev-wrapall.md +7 -5
- package/plugins/sp/commands/rule-add.md +1 -0
- package/plugins/sp/commands/rule-refine.md +1 -0
- package/plugins/sp/commands/rule-scan.md +1 -0
- package/plugins/sp/commands/spur-init.md +1 -0
- package/plugins/sp/commands/workflow-add.md +1 -0
- package/plugins/sp/commands/workflow-refine.md +1 -0
- package/plugins/sp/hooks/careful-guard.ts +5 -80
- package/plugins/sp/hooks/destructive-policy.ts +146 -0
- package/plugins/sp/hooks/pi/guard-extension.ts +33 -46
- package/plugins/sp/hooks/task-file-policy.ts +31 -0
- package/plugins/sp/hooks/task-write-guard.ts +4 -0
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/references/roles.md +93 -0
- package/plugins/sp/scripts/feature-sync-bounded.ts +28 -2
- package/plugins/sp/scripts/stage-registry-adapter.ts +66 -31
- package/plugins/sp/scripts/surface-drift-inventory.ts +908 -0
- package/plugins/sp/scripts/task-size-precheck.ts +30 -4
- package/plugins/sp/scripts/transition-shim-check.ts +238 -0
- package/plugins/sp/scripts/validate-flag-contracts.ts +5 -2
- package/plugins/sp/skills/code-verification/SKILL.md +2 -0
- package/plugins/sp/skills/issue-finding/SKILL.md +123 -142
- package/plugins/sp/skills/issue-finding/examples/expected-findings.json +1 -1
- package/plugins/sp/skills/issue-finding/references/session-formats.md +85 -90
- package/plugins/sp/skills/next-router/SKILL.md +1 -1
- package/plugins/sp/skills/parallel-execution/references/dispatch-surface.md +40 -2
- package/plugins/sp/skills/spur-cli/SKILL.md +3 -0
- package/plugins/sp/skills/spur-cli/references/agent.md +12 -7
- package/plugins/sp/skills/spur-cli/references/team.md +10 -3
- package/plugins/sp/skills/spur-dev/SKILL.md +2 -0
- package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +17 -0
- package/plugins/sp/skills/spur-dev/references/cross-cutting.md +44 -23
- package/plugins/sp/skills/spur-dev/references/dev-operations.md +14 -11
- package/plugins/sp/skills/spur-dev/references/execution-workflow.md +14 -12
- package/plugins/sp/skills/spur-dev/references/flag-glossary.md +14 -3
- package/plugins/sp/skills/spur-dev/references/gate-checklists.md +2 -0
- package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +12 -2
- package/schemas/spur-config.schema.json +27 -3
- package/spur.js +11637 -7590
- package/web/_astro/BoardApp.8hiqShQn.js +1 -0
- package/web/_astro/{BoardApp.DKyrGxdo.js → BoardApp.BjQUNhuj.js} +74 -74
- package/web/_astro/{TaskDetail.6-27_LMa.js → TaskDetail.CVBuD6dF.js} +1 -1
- package/web/_astro/{arc.Df-9AQvS.js → arc.BMMjdODi.js} +1 -1
- package/web/_astro/{architectureDiagram-3BPJPVTR.VAI_-paS.js → architectureDiagram-3BPJPVTR.BU5ShzXf.js} +1 -1
- package/web/_astro/{blockDiagram-GPEHLZMM.DFpUY1ue.js → blockDiagram-GPEHLZMM.Bj1iEqPD.js} +1 -1
- package/web/_astro/{c4Diagram-AAUBKEIU.CF8doOpg.js → c4Diagram-AAUBKEIU.vX8wepCL.js} +1 -1
- package/web/_astro/channel.EwdSemIC.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.BnjK3fjt.js → chunk-2J33WTMH.BKAipTym.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.x6ZDnJKq.js → chunk-4BX2VUAB.B68XkPG7.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.zY-0uu7w.js → chunk-55IACEB6.BmeDLcrc.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.BZxKg_Vi.js → chunk-727SXJPM.PDuBA3Kw.js} +1 -1
- package/web/_astro/{chunk-AQP2D5EJ.Cpi9G9Td.js → chunk-AQP2D5EJ.C7A044za.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.DWTB-Pif.js → chunk-FMBD7UC4.BtzKKFqR.js} +1 -1
- package/web/_astro/{chunk-ND2GUHAM.BPDQbiOG.js → chunk-ND2GUHAM.BJuDeeOy.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.BRWIcuoM.js → chunk-QZHKN3VN.DSeMDgcQ.js} +1 -1
- package/web/_astro/{classDiagram-4FO5ZUOK.mGTCZsDO.js → classDiagram-4FO5ZUOK.D53Q4tCw.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.mGTCZsDO.js → classDiagram-v2-Q7XG4LA2.D53Q4tCw.js} +1 -1
- package/web/_astro/{cose-bilkent-S5V4N54A.D1GEut-z.js → cose-bilkent-S5V4N54A.c712AFRH.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.BV0XG9Do.js → dagre-BM42HDAG.D-idisph.js} +1 -1
- package/web/_astro/{diagram-2AECGRRQ.DzpYxsjo.js → diagram-2AECGRRQ.DLgnsJCU.js} +1 -1
- package/web/_astro/{diagram-5GNKFQAL.Cm9YzJh4.js → diagram-5GNKFQAL.BiaxBVqx.js} +1 -1
- package/web/_astro/{diagram-KO2AKTUF.BjhottUj.js → diagram-KO2AKTUF.C8HX1vd8.js} +1 -1
- package/web/_astro/{diagram-LMA3HP47.BFsQW5kb.js → diagram-LMA3HP47.CfqDLLes.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.8pdpzSWO.js → diagram-OG6HWLK6.15SDiEed.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35.Bd7KUJmJ.js → erDiagram-TEJ5UH35.DksYtOYM.js} +1 -1
- package/web/_astro/{flowDiagram-I6XJVG4X.7LWffkaE.js → flowDiagram-I6XJVG4X.DR_Au-HV.js} +1 -1
- package/web/_astro/{ganttDiagram-6RSMTGT7.BeDcO5tI.js → ganttDiagram-6RSMTGT7.CHhHrffI.js} +1 -1
- package/web/_astro/{gitGraphDiagram-PVQCEYII.Ca4n730A.js → gitGraphDiagram-PVQCEYII.B2Xehvam.js} +1 -1
- package/web/_astro/{index.Dbvuw6d4.css → index.DAxu50UF.css} +1 -1
- package/web/_astro/{infoDiagram-5YYISTIA.B0OakQYb.js → infoDiagram-5YYISTIA.C9c3CNNN.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.DSmNQe-1.js → ishikawaDiagram-YF4QCWOH.BibUHkh8.js} +1 -1
- package/web/_astro/{journeyDiagram-JHISSGLW.Cy5ruEUu.js → journeyDiagram-JHISSGLW.BYoVHiyO.js} +1 -1
- package/web/_astro/{kanban-definition-UN3LZRKU.CUJXub0p.js → kanban-definition-UN3LZRKU.CM1K5wHE.js} +1 -1
- package/web/_astro/{linear.DC1jCCXn.js → linear.SPpjJUb-.js} +1 -1
- package/web/_astro/{mermaid.core.DxVP99Ab.js → mermaid.core.BAgx3nnb.js} +4 -4
- package/web/_astro/{mindmap-definition-RKZ34NQL.D0MaV6sJ.js → mindmap-definition-RKZ34NQL.D35oPG1R.js} +1 -1
- package/web/_astro/{pieDiagram-4H26LBE5.DCC6_q32.js → pieDiagram-4H26LBE5.DiWuRwk7.js} +1 -1
- package/web/_astro/{quadrantDiagram-W4KKPZXB.BeUOAM7C.js → quadrantDiagram-W4KKPZXB.B9PBzTWn.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.Dbl4MASO.js → requirementDiagram-4Y6WPE33.CYuuamFN.js} +1 -1
- package/web/_astro/{sankeyDiagram-5OEKKPKP.HsLg0VS4.js → sankeyDiagram-5OEKKPKP.W24UhhtD.js} +1 -1
- package/web/_astro/{sequenceDiagram-3UESZ5HK.DT7DJTnZ.js → sequenceDiagram-3UESZ5HK.BpbNjA51.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.d_ju1Vr1.js → stateDiagram-AJRCARHV.DqVsHudf.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.DMCAjMJ4.js → stateDiagram-v2-BHNVJYJU.CzwHYX81.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.DNOHr62_.js → timeline-definition-PNZ67QCA.Bc3B6djw.js} +1 -1
- package/web/_astro/{vennDiagram-CIIHVFJN.B7dUy-1W.js → vennDiagram-CIIHVFJN.C-D5rh8O.js} +1 -1
- package/web/_astro/{wardley-L42UT6IY.DEqOXvBh.js → wardley-L42UT6IY.D7PdYCqn.js} +1 -1
- package/web/_astro/{wardleyDiagram-YWT4CUSO.BCRb2p6x.js → wardleyDiagram-YWT4CUSO.CwmJKXF3.js} +1 -1
- package/web/_astro/{xychartDiagram-2RQKCTM6.NxVQLdBh.js → xychartDiagram-2RQKCTM6.avDYnLsb.js} +1 -1
- package/web/index.html +2 -2
- package/web/_astro/BoardApp.Ce6zJYAH.js +0 -1
- package/web/_astro/channel.Uhm9O3UV.js +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Fix all lint, type, and test errors systematically across the working tree
|
|
3
|
+
role: coder
|
|
3
4
|
argument-hint: "[<validation-command>] [--max-retry <n>] [--scope <path>] [--gate-log <path>] [--findings <anchors>]"
|
|
4
5
|
allowed-tools: ["Bash", "Read", "Write", "Edit", "Grep", "Glob"]
|
|
5
6
|
---
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Get things done — quality gate → fix → act CI simulation → commit → push → gh verify in one flow
|
|
3
|
+
role: coder
|
|
3
4
|
argument-hint: "[<quality-gate-command>] [--dry-run] [--skip-act] [--no-push] [--no-verify] [--scope <path>] [--max-retry <n>]"
|
|
4
5
|
allowed-tools: ["Bash", "Read", "Write", "Edit", "Grep", "Glob"]
|
|
5
6
|
---
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Turn a vague idea into a feature with AC and a decomposed task batch — discovery, idea-eval, feature-create, AC, feature-check, system-design, decompose, batch-create (Design by default), handoff
|
|
3
|
+
role: planner
|
|
3
4
|
argument-hint: "\"<idea>\" [--auto] [--skip-design] [--approve-taste]"
|
|
4
5
|
allowed-tools: ["Bash", "Read", "AskUserQuestion"]
|
|
5
6
|
---
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Status-aware router — pick and run the next best /sp:dev-* step for a task or feature frontier
|
|
3
|
+
role: planner
|
|
3
4
|
argument-hint: "[<wbs|feature-id>] [--dry-run] [--once] [--auto] [--agent <inline|auto|name>] [--full]"
|
|
4
5
|
allowed-tools: ["Bash", "Read", "Skill", "AskUserQuestion"]
|
|
5
6
|
---
|
|
@@ -16,7 +17,7 @@ Wraps the **sp:next-router** skill.
|
|
|
16
17
|
| `--dry-run` | Resolve and print the next step without executing. | off |
|
|
17
18
|
| `--once` | Resolve exactly one step and stop. | off |
|
|
18
19
|
| `--auto` | Skip objective HITL gates in the dispatched step. | off |
|
|
19
|
-
| `--agent` `<inline\|auto\|name>` | Who runs the dispatched model-bearing step. |
|
|
20
|
+
| `--agent` `<inline\|auto\|name>` | Who runs the dispatched model-bearing step. | omit |
|
|
20
21
|
| `--full` | When the primary route is `dev-run … --next`, substitute `dev-run <wbs> --mode full` (no `--next`). No effect on other routes (warning W-FULL). | off |
|
|
21
22
|
|
|
22
23
|
For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag-glossary.md).
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Fan out independent tasks or investigations in parallel via subagents — choose the right pattern and synthesize results
|
|
3
|
+
role: planner
|
|
3
4
|
argument-hint: "--tasks <selector> [--feature <id>] [--mode <fan-out|review-panel|investigation>] [--agent <inline|auto|name>] [--json]"
|
|
4
5
|
allowed-tools: ["Bash", "Read", "Skill"]
|
|
5
6
|
---
|
|
@@ -15,7 +16,7 @@ Wraps the **sp:parallel-execution** skill.
|
|
|
15
16
|
| `--tasks` `<selector>` | Task selector to fan out. | required |
|
|
16
17
|
| `--feature` `<id>` | Restrict the selector to a feature. | omitted |
|
|
17
18
|
| `--mode` `<fan-out\|review-panel\|investigation>` | Fan-out pattern. | fan-out |
|
|
18
|
-
| `--agent` `<inline\|auto\|name>` | Who runs each dispatched slice.
|
|
19
|
+
| `--agent` `<inline\|auto\|name>` | Who runs each dispatched slice. Parallel fan-out is dispatch, so explicit `--agent inline` runs the batch **sequentially in the host session** with a printed notice (zero dispatch); omit keeps the default fan-out semantics; `auto` tier-resolves an executor; a name pins that executor. | omit |
|
|
19
20
|
| `--json` | Emit structured JSON. | off |
|
|
20
21
|
|
|
21
22
|
For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag-glossary.md).
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Plan a feature from a description — intake → feature create → AC generation → feature check gate → decomposition → batch-create (Design by default)
|
|
3
|
+
role: planner
|
|
3
4
|
argument-hint: "\"<description>\" [--feature <id>] [--parent <feature-id>] [--agent <inline|auto|name>] [--skip-design] [--auto] [--approve-taste]"
|
|
4
5
|
allowed-tools: ["Bash", "Read", "Skill", "AskUserQuestion"]
|
|
5
6
|
---
|
|
@@ -15,7 +16,7 @@ Wraps the **sp:spur-dev** skill.
|
|
|
15
16
|
| `"<description>"` | Feature description to plan. | required |
|
|
16
17
|
| `--feature` `<id>` | Attach to an existing feature. | omitted |
|
|
17
18
|
| `--parent` `<feature-id>` | Create under a parent feature. | omitted |
|
|
18
|
-
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing planning. The planning pipeline's `agent.run` stages always dispatch a subprocess
|
|
19
|
+
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing planning. The planning pipeline's `agent.run` stages are headless — they always dispatch a subprocess. Explicit `--agent inline` is rejected there with the stable special error (exit 2): a headless surface cannot host a session — no dispatch, no `agent.default` fallback. Use `omit` (resolves to `agent.default`), `auto` (tier-resolves an executor), or a name (pins that executor). | agent.default |
|
|
19
20
|
| `--skip-design` | Omit the system-design hop. | off |
|
|
20
21
|
| `--auto` | Skip objective HITL gates. | off |
|
|
21
22
|
| `--approve-taste` | With --auto: skip design-approval pause. | off |
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Refine task requirements via structured Q&A — clarify scope, elicit missing details, tighten acceptance criteria; optional implement-ready depth
|
|
3
|
+
role: planner
|
|
3
4
|
argument-hint: "<wbs> [--focus <mode>] [--description <text>] [--depth <standard|ready>] [--agent <inline|auto|name>] [--auto] [--next]"
|
|
4
5
|
allowed-tools: ["Bash", "Read", "Skill", "AskUserQuestion"]
|
|
5
6
|
---
|
|
@@ -18,7 +19,7 @@ agent will implement and L3-clean is not enough (frozen APIs, anti-patterns, fil
|
|
|
18
19
|
| `--focus` `<mode>` | Refinement focus mode. | omitted |
|
|
19
20
|
| `--description` `<text>` | Override the task description. | omitted |
|
|
20
21
|
| `--depth` `<standard\|ready>` | Spec depth bar (see flag glossary). | `standard` |
|
|
21
|
-
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing refinement. |
|
|
22
|
+
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing refinement. | omit |
|
|
22
23
|
| `--auto` | Skip objective HITL gates. | off |
|
|
23
24
|
| `--next` | Hand off to the next-router on success. | off |
|
|
24
25
|
|
|
@@ -34,8 +35,9 @@ Under `--auto` with **`--depth standard`** (default), SKIP only when target sect
|
|
|
34
35
|
findings: Background, Requirements, Acceptance Criteria, Design, Plan. Solution is not a refine
|
|
35
36
|
target. Under **`--depth ready`**, do **not** SKIP on L3-clean alone — run the implement-ready
|
|
36
37
|
checklist (dev-operations § refine) and rewrite Design/Requirements/Plan until another agent can
|
|
37
|
-
implement without inventing design. Stage floor:
|
|
38
|
-
|
|
38
|
+
implement without inventing design. Stage floor: the `planner` role per
|
|
39
|
+
[`roles.md`](../references/roles.md) — this command names roles, never tiers (0538 R4);
|
|
40
|
+
ready synthesis may use a higher tier when the task spans packages/seams.
|
|
39
41
|
|
|
40
42
|
## Implementation
|
|
41
43
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Refine a batch of tasks via structured Q&A — resolve a set (feature or selector), refine each in dependency-correct order, emit a batch report; optional implement-ready depth
|
|
3
|
+
role: planner
|
|
3
4
|
argument-hint: "--feature <id> | --tasks <selector> [--focus <mode>] [--description <text>] [--depth <standard|ready>] [--agent <inline|auto|name>] [--auto] [--keep-going] [--status <s>] [--json] [--worktree [<name>]]"
|
|
4
5
|
allowed-tools: ["Bash", "Read", "Skill", "AskUserQuestion"]
|
|
5
6
|
---
|
|
@@ -19,7 +20,7 @@ operation, applied to a resolved set (typically every task under a feature). Pas
|
|
|
19
20
|
| `--focus` `<mode>` | Refinement focus mode. | omitted |
|
|
20
21
|
| `--description` `<text>` | Override description for each task. | omitted |
|
|
21
22
|
| `--depth` `<standard\|ready>` | Spec depth bar (see flag glossary). | `standard` |
|
|
22
|
-
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing refinement. |
|
|
23
|
+
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing refinement. | omit |
|
|
23
24
|
| `--auto` | Skip objective HITL gates. | off |
|
|
24
25
|
| `--keep-going` | Continue past per-task failures. | off |
|
|
25
26
|
| `--status` `<s>` | Only refine tasks in a status. | backlog,todo |
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Refresh feature status by feature ID, task WBS, or batch sweep via spur feature sync
|
|
3
|
+
role: scribe
|
|
3
4
|
argument-hint: "[<feature-id|wbs>] [--all] [--auto] [--agent <inline|auto|name>]"
|
|
4
5
|
allowed-tools: ["Bash", "Read", "Skill"]
|
|
5
6
|
---
|
|
@@ -15,7 +16,7 @@ Wraps the **sp:spur-dev** skill.
|
|
|
15
16
|
| `[<feature-id\|wbs>]` | Feature id or task WBS to refresh. | active |
|
|
16
17
|
| `--all` | Refresh every feature. | off |
|
|
17
18
|
| `--auto` | Skip objective HITL gates. | off |
|
|
18
|
-
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing refresh. |
|
|
19
|
+
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing refresh. | omit |
|
|
19
20
|
|
|
20
21
|
For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag-glossary.md).
|
|
21
22
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Reverse engineer a codebase with selectable depth, focus, and output format
|
|
3
|
+
role: coder
|
|
3
4
|
argument-hint: "[<path>] [--mode <briefing|structure|architecture|design|full>] [--focus <all|stack|dependencies|data|flows|api|security|quality|performance>] [--format <markdown|json|both>] [--output <file>] [--agent <inline|auto|name>]"
|
|
4
5
|
allowed-tools: ["Read", "Write", "Edit", "Grep", "Glob", "Bash", "Skill"]
|
|
5
6
|
---
|
|
@@ -17,7 +18,7 @@ Wraps the **sp:reverse-engineering** skill.
|
|
|
17
18
|
| `--focus` `<all\|stack\|dependencies\|data\|flows\|api\|security\|quality\|performance>` | Analysis lens. | all |
|
|
18
19
|
| `--format` `<markdown\|json\|both>` | Output format. | markdown |
|
|
19
20
|
| `--output` `<file>` | Write to a file instead of stdout. | stdout |
|
|
20
|
-
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing analysis. |
|
|
21
|
+
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing analysis. | omit |
|
|
21
22
|
|
|
22
23
|
For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag-glossary.md).
|
|
23
24
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: "Review code for a task or path — multi-dimensional review across functional traceability, SECUA quality, and architectural depth. Triggers: \"review this\", \"check the code\", \"SECUA review\", \"dev review\", \"audit this\"."
|
|
3
|
+
role: reviewer
|
|
3
4
|
argument-hint: "[<wbs|path>] [--agent <inline|auto|name>] [--focus <dims>] [--fix (deprecated)]"
|
|
4
5
|
allowed-tools: ["Bash", "Read", "Skill"]
|
|
5
6
|
---
|
|
@@ -13,7 +14,7 @@ Wraps the **sp:functional-review**, **sp:code-verification**, and **sp:code-impr
|
|
|
13
14
|
| Flag | Description | Default |
|
|
14
15
|
| --- | --- | --- |
|
|
15
16
|
| `[<wbs\|path>]` | Task WBS or source path to review. | cwd |
|
|
16
|
-
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing review. |
|
|
17
|
+
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing review. | omit |
|
|
17
18
|
| `--focus` `<dims>` | Review dimensions (functional / SECUA / architecture). | all |
|
|
18
19
|
| `--fix` | Deprecated no-op + warning; route remediation to /sp:dev-verify --fix. | off |
|
|
19
20
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Run a task — full pipeline (precheck→implement→test→review→approve→verify→record→done) or single-step (implement)
|
|
3
|
+
role: coder
|
|
3
4
|
argument-hint: "<wbs> [--mode <full|implement>] [--agent <inline|auto|name>] [--auto] [--next] [--wrap] [--continue]"
|
|
4
5
|
allowed-tools: ["Bash", "Read", "Write", "Edit", "Skill"]
|
|
5
6
|
---
|
|
@@ -14,7 +15,7 @@ Wraps the **sp:spur-dev** and **sp:code-implementation** skills.
|
|
|
14
15
|
| --- | --- | --- |
|
|
15
16
|
| `<wbs>` | Task WBS to run. | required |
|
|
16
17
|
| `--mode` `<full\|implement>` | Full pipeline or single implement step. | full |
|
|
17
|
-
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing stages. In an interactive session, omit/`inline` keeps the controller in the host session (non-subprocess)
|
|
18
|
+
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing stages. In an interactive session, omit/`inline` keeps the controller in the host session (non-subprocess) — **omit**'s eligible full-mode `agent.run` stages may dispatch once to a native subagent, with host fallback (task 0508); explicit `--agent inline` is the zero-dispatch carve-out (every stage executes in the invoking session, never a native subagent). `auto` or a name keeps subprocess dispatch. | omit |
|
|
18
19
|
| `--auto` | Skip objective HITL confirmations. | off |
|
|
19
20
|
| `--next` | Chain-to-completion via the next-router. | off |
|
|
20
21
|
| `--wrap` | Run the wrap hop after the main step. The `--agent` selector is preserved into the `/sp:dev-wrap <wbs>` handoff when supplied; omission remains omission. The wrap hop is workflow-backed and reports its trigger-3 subprocess override. | off |
|
|
@@ -37,7 +38,7 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
|
|
|
37
38
|
|
|
38
39
|
**Flags:**
|
|
39
40
|
|
|
40
|
-
- `--auto` | `--agent <inline|auto|name>` — Skip objective HITL confirmations (taste/irreversible gates still pause). `--agent` names who does the model-bearing work. Interactive omit/`inline` keeps the controller and implement-only stages in this session; full mode reads `task-pipeline.yaml` as the SSOT and interprets its actions/guards through the inline driver, where eligible `agent.run` stages may dispatch once to a native subagent and otherwise run in the host (task 0508). It records `stage <id> executed inline in session <session-id>` or `stage <id> executed via subagent <agent-id> (host session <session-id>)` in the run log. `auto` or a name is merged into `vars.agent` and `vars.implementAgent` and keeps the existing subprocess workflow. Headless `spur workflow run` / `spur agent run` is unchanged. See the [execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface).
|
|
41
|
+
- `--auto` | `--agent <inline|auto|name>` — Skip objective HITL confirmations (taste/irreversible gates still pause). `--agent` names who does the model-bearing work. Interactive omit/`inline` keeps the controller and implement-only stages in this session; full mode reads `task-pipeline.yaml` as the SSOT and interprets its actions/guards through the inline driver, where **omitted** `--agent`'s eligible `agent.run` stages may dispatch once to a native subagent and otherwise run in the host (task 0508); explicit `--agent inline` is the zero-dispatch carve-out — every stage executes in the invoking session. It records `stage <id> executed inline in session <session-id>` or `stage <id> executed via subagent <agent-id> (host session <session-id>)` in the run log. `auto` or a name is merged into `vars.agent` and `vars.implementAgent` and keeps the existing subprocess workflow. Headless `spur workflow run` / `spur agent run` is unchanged. See the [execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface).
|
|
41
42
|
|
|
42
43
|
**Mode split (load-bearing — bug-742)**
|
|
43
44
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Run a batch of tasks through their pipelines in dependency-correct order — resolve a set, topo-sort, run each via task-pipeline.yaml, emit a batch report
|
|
3
|
+
role: planner
|
|
3
4
|
argument-hint: "--tasks <selector> [--feature <id>] [--mode <sequential|parallel>] [--keep-going] [--auto] [--agent <inline|auto|name>] [--json] [--wrap] [--next] [--continue] [--worktree [<name>]]"
|
|
4
5
|
allowed-tools: ["Bash", "Read", "Skill"]
|
|
5
6
|
---
|
|
@@ -17,7 +18,7 @@ Wraps the **sp:spur-dev** skill.
|
|
|
17
18
|
| `--mode` `<sequential\|parallel>` | Batch execution order. | sequential |
|
|
18
19
|
| `--keep-going` | Continue past per-task failures. | off |
|
|
19
20
|
| `--auto` | Skip objective HITL gates. | off |
|
|
20
|
-
| `--agent` `<inline\|auto\|name>` | Who runs each task's pipeline stages. Interactive sequential omit/`inline` uses the host-session driver — host-controlled
|
|
21
|
+
| `--agent` `<inline\|auto\|name>` | Who runs each task's pipeline stages. Interactive sequential omit/`inline` uses the host-session driver — host-controlled; **omit**'s eligible `agent.run` stages may use a native subagent (task 0508); explicit `--agent inline` is the zero-dispatch carve-out (every stage executes in the invoking session). `auto`, a name, parallel mode, and headless invocation use subprocesses. | omit |
|
|
21
22
|
| `--json` | Emit structured JSON. | off |
|
|
22
23
|
| `--wrap` | Run the wrap hop per task. The `--agent` selector is preserved into each `/sp:dev-wrap <wbs>` handoff when supplied; omission remains omission. | off |
|
|
23
24
|
| `--next` | Chain-to-completion via the next-router. | off |
|
|
@@ -80,6 +81,6 @@ full distinction.
|
|
|
80
81
|
|
|
81
82
|
## Implementation
|
|
82
83
|
|
|
83
|
-
- Apply the [inline-default execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface). Interactive sequential omit/`inline` keeps the orchestrator in the host session through the [inline pipeline driver](../skills/spur-dev/references/inline-pipeline-driver.md); eligible `agent.run` stages may dispatch once to a native subagent with host fallback (task 0508). `--agent auto`, a name, or parallel mode retains the isolated per-task workflow boundary.
|
|
84
|
+
- Apply the [inline-default execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface). Interactive sequential omit/`inline` keeps the orchestrator in the host session through the [inline pipeline driver](../skills/spur-dev/references/inline-pipeline-driver.md); **omitted** `--agent`'s eligible `agent.run` stages may dispatch once to a native subagent with host fallback (task 0508); explicit `--agent inline` is the zero-dispatch carve-out. `--agent auto`, a name, or parallel mode retains the isolated per-task workflow boundary.
|
|
84
85
|
- Interactive sequential omit/inline: `Skill(skill="sp:spur-dev", args="runall-inline $ARGUMENTS")`.
|
|
85
86
|
- Explicit executor or parallel mode: `Skill(skill="sp:spur-dev", args="runall $ARGUMENTS")` → `sp:super-planner` agent.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Simplify code for clarity without changing behavior — reduce complexity in recent changes (or a given scope), preserving behavior exactly
|
|
3
|
+
role: coder
|
|
3
4
|
argument-hint: "[<path-or-scope>] [--scope <recent|all|path>] [--check <cmd>] [--agent <inline|auto|name>] [--auto]"
|
|
4
5
|
allowed-tools: ["Bash", "Read", "Edit", "Skill"]
|
|
5
6
|
---
|
|
@@ -15,7 +16,7 @@ Wraps the **sp:code-simplification** skill.
|
|
|
15
16
|
| `[<path-or-scope>]` | Path or scope to simplify. | recent |
|
|
16
17
|
| `--scope` `<recent\|all\|path>` | Scope of the simplification pass. | recent |
|
|
17
18
|
| `--check` `<cmd>` | Validation command to iterate against. | project gate |
|
|
18
|
-
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing simplification. |
|
|
19
|
+
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing simplification. | omit |
|
|
19
20
|
| `--auto` | Skip objective HITL gates (taste gates: over-engineering removal & cross-file utility extraction still require approval). | off |
|
|
20
21
|
|
|
21
22
|
For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag-glossary.md).
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Generate or extend tests until the unit target is met
|
|
3
|
+
role: coder
|
|
3
4
|
argument-hint: "<target> [--coverage <n>] [--agent <inline|auto|name>] [--auto]"
|
|
4
5
|
allowed-tools: ["Bash", "Read", "Write", "Edit", "Skill"]
|
|
5
6
|
---
|
|
@@ -14,7 +15,7 @@ Wraps the **sp:code-testing** skill.
|
|
|
14
15
|
| --- | --- | --- |
|
|
15
16
|
| `<target>` | File / module / path to generate tests for. | required |
|
|
16
17
|
| `--coverage` `<n>` | Coverage percentage target. | configured |
|
|
17
|
-
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing test work. |
|
|
18
|
+
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing test work. | omit |
|
|
18
19
|
| `--auto` | Skip objective HITL gates. | off |
|
|
19
20
|
|
|
20
21
|
For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag-glossary.md).
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Verify a task against its requirements and Acceptance Criteria — traceability check producing a PASS/PARTIAL/FAIL verdict with evidence
|
|
3
|
+
role: reviewer
|
|
3
4
|
argument-hint: "<wbs> [--agent <inline|auto|name>] [--fix <none|blockers-first|all>] [--focus <lens>] [--bdd] [--auto] [--force] [--next] [--skip-shippable]"
|
|
4
5
|
allowed-tools: ["Bash", "Read", "Skill"]
|
|
5
6
|
---
|
|
@@ -13,7 +14,7 @@ Wraps the **sp:code-verification** skill.
|
|
|
13
14
|
| Flag | Description | Default |
|
|
14
15
|
| --- | --- | --- |
|
|
15
16
|
| `<wbs>` | Task WBS to verify. | required |
|
|
16
|
-
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing verification. |
|
|
17
|
+
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing verification. | omit |
|
|
17
18
|
| `--fix` `<none\|blockers-first\|all>` | Auto-fix policy on findings. | none |
|
|
18
19
|
| `--focus` `<lens>` | Verification lens. | omitted |
|
|
19
20
|
| `--bdd` | Run BDD scenarios. | off |
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Verify a batch of tasks against their requirements and Acceptance Criteria — batch traceability check producing per-task verdicts and a summary report
|
|
3
|
+
role: reviewer
|
|
3
4
|
argument-hint: "--tasks <selector> [--feature <id>] [--agent <inline|auto|name>] [--fix <none|blockers-first|all>] [--focus <lens>] [--bdd] [--auto] [--force] [--next] [--json] [--skip-shippable] [--worktree [<name>]]"
|
|
4
5
|
allowed-tools: ["Bash", "Read", "Skill"]
|
|
5
6
|
---
|
|
@@ -14,7 +15,7 @@ Wraps the **sp:spur-dev** and **sp:code-verification** skills.
|
|
|
14
15
|
| --- | --- | --- |
|
|
15
16
|
| `--tasks` `<selector>` | Task selector to verify. | required |
|
|
16
17
|
| `--feature` `<id>` | Restrict to a feature. | omitted |
|
|
17
|
-
| `--agent` `<inline\|auto\|name>` | Who runs each verification. |
|
|
18
|
+
| `--agent` `<inline\|auto\|name>` | Who runs each verification. | omit |
|
|
18
19
|
| `--fix` `<none\|blockers-first\|all>` | Auto-fix policy on findings. | none |
|
|
19
20
|
| `--focus` `<lens>` | Verification lens. | omitted |
|
|
20
21
|
| `--bdd` | Run BDD scenarios. | off |
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Wrap up a single completed task — learnings, metrics, doc-sync, optional feature transition and branch cleanup
|
|
3
|
+
role: coder
|
|
3
4
|
argument-hint: "<wbs> [--agent <inline|auto|name>] [--auto] [--merge] [--dry-run]"
|
|
4
5
|
allowed-tools: ["Bash", "Read", "AskUserQuestion"]
|
|
5
6
|
---
|
|
@@ -13,7 +14,7 @@ Wraps the **wrapup-pipeline.yaml** workflow.
|
|
|
13
14
|
| Flag | Description | Default |
|
|
14
15
|
| --- | --- | --- |
|
|
15
16
|
| `<wbs>` | Task WBS to wrap. | required |
|
|
16
|
-
| `--agent` `<inline\|auto\|name>` | Who runs the wrap's model-bearing steps. Wrap is workflow-backed: omit
|
|
17
|
+
| `--agent` `<inline\|auto\|name>` | Who runs the wrap's model-bearing steps. Wrap is workflow-backed (headless): `omit` resolves to `agent.default` (objective trigger 3 — durable auditable run record required); explicit `--agent inline` is rejected with the stable special error — a headless workflow surface cannot host a session; `auto` tier-resolves an executor; a name pins that executor into `vars.agent`. | agent.default |
|
|
17
18
|
| `--auto` | Skip objective HITL gates. | off |
|
|
18
19
|
| `--merge` | Merge the wrap branch. | off |
|
|
19
20
|
| `--dry-run` | Render the wrap without writing. | off |
|
|
@@ -31,13 +32,13 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
|
|
|
31
32
|
- Resolve the executor **before** launching the workflow:
|
|
32
33
|
- `--agent <name>` → pass the name unchanged into `vars.agent`.
|
|
33
34
|
- `--agent auto` → tier-resolve a concrete executor first, then merge it into `vars.agent`.
|
|
34
|
-
- omit
|
|
35
|
+
- omit → resolve to `agent.default`; explicit `--agent inline` → rejected with the stable special error (headless surface — no dispatch, no `agent.default` fallback).
|
|
35
36
|
- Emit a pre-dispatch notice naming the override before `spur workflow run`, exactly:
|
|
36
|
-
`execution surface: subprocess`, `reason: trigger 3 — durable auditable run record required`, `requested agent: inline|auto|<name
|
|
37
|
+
`execution surface: subprocess`, `reason: trigger 3 — durable auditable run record required`, `requested agent: inline|auto|<name>` (explicit `inline` rejects before dispatch — no executor resolves), `executor: agent.default|<resolved-name>`.
|
|
37
38
|
- The wrap workflow still creates its durable run record (task_run_links / trace) — the notice reports the override, it does not change the workflow.
|
|
38
39
|
|
|
39
40
|
```bash
|
|
40
|
-
AGENT=… # resolved above: agent.default for
|
|
41
|
+
AGENT=… # resolved above: agent.default for omitted, tier-resolved for auto, unchanged for <name>; explicit inline errors (headless)
|
|
41
42
|
echo "execution surface: subprocess; reason: trigger 3 — durable auditable run record required; requested agent: <inline|auto|name>; executor: $AGENT"
|
|
42
43
|
VARS=$(jq -nc --arg tasks "[\"$WBS\"]" --arg agent "$AGENT" --arg profile "$PROFILE" --arg merge "$MERGE" \
|
|
43
44
|
'{tasks:$tasks, agent:$agent, profile:$profile, merge:$merge}')
|
|
@@ -45,4 +46,5 @@ spur workflow run .spur/workflows/wrapup-pipeline.yaml --vars "$VARS" [--dry-run
|
|
|
45
46
|
```
|
|
46
47
|
|
|
47
48
|
The executor resolution is described in the bullets above; the snippet's `AGENT` variable carries
|
|
48
|
-
the resolved name (`agent.default` for
|
|
49
|
+
the resolved name (`agent.default` for omitted `--agent`; explicit `--agent inline` is rejected
|
|
50
|
+
before dispatch).
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Wrap up a batch of completed tasks — learnings, metrics, doc-sync, feature transition, optional branch cleanup
|
|
3
|
+
role: coder
|
|
3
4
|
argument-hint: "[--since <iso-date>] [--feature <id>] [--status <s>] [--agent <inline|auto|name>] [--auto] [--merge] [--dry-run]"
|
|
4
5
|
allowed-tools: ["Bash", "Read", "AskUserQuestion"]
|
|
5
6
|
---
|
|
@@ -15,7 +16,7 @@ Wraps the **wrapup-pipeline.yaml** workflow.
|
|
|
15
16
|
| `--since` `<iso-date>` | Wrap tasks completed since a date. | configured |
|
|
16
17
|
| `--feature` `<id>` | Wrap tasks in a feature. | omitted |
|
|
17
18
|
| `--status` `<s>` | Only wrap tasks in a status. | done |
|
|
18
|
-
| `--agent` `<inline\|auto\|name>` | Who runs the wrap's model-bearing steps. Wrap is workflow-backed: omit
|
|
19
|
+
| `--agent` `<inline\|auto\|name>` | Who runs the wrap's model-bearing steps. Wrap is workflow-backed (headless): `omit` resolves to `agent.default` (objective trigger 3 — durable auditable run record required); explicit `--agent inline` is rejected with the stable special error — a headless workflow surface cannot host a session; `auto` tier-resolves an executor; a name pins that executor into `vars.agent`. | agent.default |
|
|
19
20
|
| `--auto` | Skip objective HITL gates. | off |
|
|
20
21
|
| `--merge` | Merge wrap branches. | off |
|
|
21
22
|
| `--dry-run` | Render wraps without writing. | off |
|
|
@@ -33,13 +34,13 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
|
|
|
33
34
|
- Resolve the executor **before** launching the workflow:
|
|
34
35
|
- `--agent <name>` → pass the name unchanged into `vars.agent`.
|
|
35
36
|
- `--agent auto` → tier-resolve a concrete executor first, then merge it into `vars.agent`.
|
|
36
|
-
- omit
|
|
37
|
+
- omit → resolve to `agent.default`; explicit `--agent inline` → rejected with the stable special error (headless surface — no dispatch, no `agent.default` fallback).
|
|
37
38
|
- Emit a pre-dispatch notice naming the override before `spur workflow run`, exactly:
|
|
38
|
-
`execution surface: subprocess`, `reason: trigger 3 — durable auditable run record required`, `requested agent: inline|auto|<name
|
|
39
|
+
`execution surface: subprocess`, `reason: trigger 3 — durable auditable run record required`, `requested agent: inline|auto|<name>` (explicit `inline` rejects before dispatch — no executor resolves), `executor: agent.default|<resolved-name>`.
|
|
39
40
|
- The wrap workflow still creates its durable run record — the notice reports the override, it does not change the workflow.
|
|
40
41
|
|
|
41
42
|
```bash
|
|
42
|
-
AGENT=… # resolved above: agent.default for
|
|
43
|
+
AGENT=… # resolved above: agent.default for omitted, tier-resolved for auto, unchanged for <name>; explicit inline errors (headless)
|
|
43
44
|
echo "execution surface: subprocess; reason: trigger 3 — durable auditable run record required; requested agent: <inline|auto|name>; executor: $AGENT"
|
|
44
45
|
VARS=$(jq -nc --arg tasks "$TASKS" --arg feature "$FEATURE" --arg agent "$AGENT" --arg profile "$PROFILE" --arg merge "$MERGE" \
|
|
45
46
|
'{tasks:$tasks, feature:$feature, agent:$agent, profile:$profile, merge:$merge}')
|
|
@@ -47,5 +48,6 @@ spur workflow run .spur/workflows/wrapup-pipeline.yaml --vars "$VARS" [--dry-run
|
|
|
47
48
|
```
|
|
48
49
|
|
|
49
50
|
The executor resolution is described in the bullets above; the snippet's `AGENT` variable carries
|
|
50
|
-
the resolved name (`agent.default` for
|
|
51
|
+
the resolved name (`agent.default` for omitted `--agent`; explicit `--agent inline` is rejected
|
|
52
|
+
before dispatch).
|
|
51
53
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Refine a constraint rule or preset, then re-verify it
|
|
3
|
+
role: scribe
|
|
3
4
|
argument-hint: "<rule-file-or-preset> [--intent \"<goal>\"] [--severity <sev>] [--scope <glob>] [--exempt <path>] [--disable <id>] [--override <id>] [--dry-run]"
|
|
4
5
|
allowed-tools: ["Bash", "Read", "Edit", "Skill"]
|
|
5
6
|
---
|
|
@@ -16,8 +16,13 @@
|
|
|
16
16
|
* emits an `allow` decision. A broken guard must never wedge an agent tool call.
|
|
17
17
|
*
|
|
18
18
|
* **Escape hatch:** `SPUR_CAREFUL=off` short-circuits to allow.
|
|
19
|
+
*
|
|
20
|
+
* Classification itself lives in `destructive-policy.ts` — one policy, every platform
|
|
21
|
+
* adapter. This file owns the Claude Code payload/decision shape only.
|
|
19
22
|
*/
|
|
20
23
|
|
|
24
|
+
import { classifyCommand } from './destructive-policy';
|
|
25
|
+
|
|
21
26
|
interface ToolPayload {
|
|
22
27
|
tool_name?: string;
|
|
23
28
|
tool_input?: { command?: string };
|
|
@@ -37,86 +42,6 @@ function preToolUseDecision(decision: Decision, reason?: string): never {
|
|
|
37
42
|
process.exit(0);
|
|
38
43
|
}
|
|
39
44
|
|
|
40
|
-
/** Well-known rebuildable caches a `rm -rf` may target without a warning. */
|
|
41
|
-
const SAFE_RM_TARGET =
|
|
42
|
-
/^(?:\.?\/)?(?:[\w.@-]+\/)*(?:node_modules|dist|\.next|coverage|build|\.turbo|\.cache|\.parcel-cache|out)\/?\*?$/;
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Expand an argument string into the set of flags it sets, splitting short-flag
|
|
46
|
-
* clusters into their individual letters: `-Rf --force` → `{R, f, --force}`.
|
|
47
|
-
*
|
|
48
|
-
* Matching flags with ad-hoc regexes per call site is what let `rm -R` through —
|
|
49
|
-
* `-\w*r` only ever matched the lowercase spelling, even though `man rm` defines
|
|
50
|
-
* `-r` as "Equivalent to -R". Parsing once, case-preserved, makes that class of
|
|
51
|
-
* miss unrepresentable: a caller names every spelling it cares about explicitly.
|
|
52
|
-
*/
|
|
53
|
-
function parseFlags(args: string): Set<string> {
|
|
54
|
-
const flags = new Set<string>();
|
|
55
|
-
for (const token of args.trim().split(/\s+/)) {
|
|
56
|
-
if (token.length < 2 || !token.startsWith('-') || token === '--') continue;
|
|
57
|
-
if (token.startsWith('--')) {
|
|
58
|
-
flags.add(token.split('=')[0] as string); // `--force=x` → `--force`
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
for (const ch of token.slice(1)) flags.add(ch);
|
|
62
|
-
}
|
|
63
|
-
return flags;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/** True when a `rm` invocation is both recursive and forced (any flag spelling). */
|
|
67
|
-
function isRecursiveForceRm(args: string): boolean {
|
|
68
|
-
const flags = parseFlags(args);
|
|
69
|
-
// POSIX rm accepts -r and -R interchangeably; --recursive is the GNU long form.
|
|
70
|
-
const recursive = flags.has('r') || flags.has('R') || flags.has('--recursive');
|
|
71
|
-
const force = flags.has('f') || flags.has('--force');
|
|
72
|
-
return recursive && force;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/** True when every non-flag target of a `rm` invocation is a known-safe cache path. */
|
|
76
|
-
function rmTargetsAllSafe(args: string): boolean {
|
|
77
|
-
const targets = args
|
|
78
|
-
.trim()
|
|
79
|
-
.split(/\s+/)
|
|
80
|
-
.filter((t) => t.length > 0 && !t.startsWith('-'));
|
|
81
|
-
if (targets.length === 0) return false;
|
|
82
|
-
return targets.every((t) => SAFE_RM_TARGET.test(t));
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/** Always-warn destructive patterns (no safe exception). */
|
|
86
|
-
const DESTRUCTIVE: Array<{ label: string; re: RegExp }> = [
|
|
87
|
-
{
|
|
88
|
-
label: 'a SQL DROP/TRUNCATE (DROP TABLE/DATABASE, TRUNCATE)',
|
|
89
|
-
re: /\b(?:DROP\s+(?:TABLE|DATABASE)|TRUNCATE(?:\s+TABLE)?)\b/i,
|
|
90
|
-
},
|
|
91
|
-
{ label: 'a force push (git push --force / -f)', re: /\bgit\s+push\b[^\n]*(?:--force(?!-with-lease)|\s-f\b)/i },
|
|
92
|
-
{
|
|
93
|
-
// `git push origin +main` forces that ref without any --force flag.
|
|
94
|
-
label: 'a force push via a + refspec (git push … +ref)',
|
|
95
|
-
re: /\bgit\s+push\b[^\n]*\s\+[\w./-]+/i,
|
|
96
|
-
},
|
|
97
|
-
{ label: 'a hard reset (git reset --hard)', re: /\bgit\s+reset\b[^\n]*--hard\b/i },
|
|
98
|
-
{
|
|
99
|
-
label: 'a working-tree discard (git checkout . / git restore .)',
|
|
100
|
-
re: /\bgit\s+(?:checkout|restore)\s+(?:--\s+)?\.(?:\s|$)/i,
|
|
101
|
-
},
|
|
102
|
-
{ label: 'a cluster delete (kubectl delete)', re: /\bkubectl\s+delete\b/i },
|
|
103
|
-
{ label: 'a docker prune (docker system prune)', re: /\bdocker\s+system\s+prune\b/i },
|
|
104
|
-
];
|
|
105
|
-
|
|
106
|
-
/** Return a human label for the destructive command, or null when the command is safe. */
|
|
107
|
-
function classifyCommand(command: string): string | null {
|
|
108
|
-
for (const rmMatch of command.matchAll(/\brm\b([^\n&|;]*)/g)) {
|
|
109
|
-
const args = rmMatch[1] ?? '';
|
|
110
|
-
if (isRecursiveForceRm(args) && !rmTargetsAllSafe(args)) {
|
|
111
|
-
return 'a recursive force remove (rm -rf)';
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
for (const { label, re } of DESTRUCTIVE) {
|
|
115
|
-
if (re.test(command)) return label;
|
|
116
|
-
}
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
45
|
async function main(): Promise<void> {
|
|
121
46
|
if (process.env.SPUR_CAREFUL === 'off') preToolUseDecision('allow');
|
|
122
47
|
|