@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.
Files changed (134) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/config.example.yaml +42 -11
  3. package/config/transition-shims.json +33 -0
  4. package/config/workflows/basic.yaml +2 -0
  5. package/config/workflows/docs-pipeline.yaml +2 -0
  6. package/config/workflows/feature-dev.yaml +8 -0
  7. package/config/workflows/idea-pipeline.yaml +10 -0
  8. package/config/workflows/planning-pipeline.yaml +4 -0
  9. package/config/workflows/task-pipeline.yaml +8 -0
  10. package/config/workflows/wayfinder-resolution.yaml +4 -0
  11. package/config/workflows/wrapup-pipeline.yaml +18 -1
  12. package/package.json +2 -2
  13. package/plugins/sp/agents/expert-spur.md +1 -0
  14. package/plugins/sp/commands/dev-arch.md +2 -1
  15. package/plugins/sp/commands/dev-brainstorm.md +2 -1
  16. package/plugins/sp/commands/dev-changelog.md +1 -0
  17. package/plugins/sp/commands/dev-daily.md +1 -0
  18. package/plugins/sp/commands/dev-debug.md +2 -1
  19. package/plugins/sp/commands/dev-dogfood.md +2 -1
  20. package/plugins/sp/commands/dev-featurechange.md +1 -0
  21. package/plugins/sp/commands/dev-find-conflict.md +2 -1
  22. package/plugins/sp/commands/dev-find-issue.md +20 -32
  23. package/plugins/sp/commands/dev-find-next.md +2 -1
  24. package/plugins/sp/commands/dev-fixall.md +1 -0
  25. package/plugins/sp/commands/dev-gitmsg.md +1 -0
  26. package/plugins/sp/commands/dev-gtd.md +1 -0
  27. package/plugins/sp/commands/dev-handover.md +1 -0
  28. package/plugins/sp/commands/dev-idea.md +1 -0
  29. package/plugins/sp/commands/dev-next.md +2 -1
  30. package/plugins/sp/commands/dev-parallel.md +2 -1
  31. package/plugins/sp/commands/dev-plan.md +2 -1
  32. package/plugins/sp/commands/dev-refine.md +5 -3
  33. package/plugins/sp/commands/dev-refineall.md +2 -1
  34. package/plugins/sp/commands/dev-refresh.md +2 -1
  35. package/plugins/sp/commands/dev-reverse.md +2 -1
  36. package/plugins/sp/commands/dev-review.md +2 -1
  37. package/plugins/sp/commands/dev-run.md +3 -2
  38. package/plugins/sp/commands/dev-runall.md +3 -2
  39. package/plugins/sp/commands/dev-simplify.md +2 -1
  40. package/plugins/sp/commands/dev-unit.md +2 -1
  41. package/plugins/sp/commands/dev-verify.md +2 -1
  42. package/plugins/sp/commands/dev-verifyall.md +2 -1
  43. package/plugins/sp/commands/dev-wrap.md +7 -5
  44. package/plugins/sp/commands/dev-wrapall.md +7 -5
  45. package/plugins/sp/commands/rule-add.md +1 -0
  46. package/plugins/sp/commands/rule-refine.md +1 -0
  47. package/plugins/sp/commands/rule-scan.md +1 -0
  48. package/plugins/sp/commands/spur-init.md +1 -0
  49. package/plugins/sp/commands/workflow-add.md +1 -0
  50. package/plugins/sp/commands/workflow-refine.md +1 -0
  51. package/plugins/sp/hooks/careful-guard.ts +5 -80
  52. package/plugins/sp/hooks/destructive-policy.ts +146 -0
  53. package/plugins/sp/hooks/pi/guard-extension.ts +33 -46
  54. package/plugins/sp/hooks/task-file-policy.ts +31 -0
  55. package/plugins/sp/hooks/task-write-guard.ts +4 -0
  56. package/plugins/sp/plugin.json +1 -1
  57. package/plugins/sp/references/roles.md +93 -0
  58. package/plugins/sp/scripts/feature-sync-bounded.ts +28 -2
  59. package/plugins/sp/scripts/stage-registry-adapter.ts +66 -31
  60. package/plugins/sp/scripts/surface-drift-inventory.ts +908 -0
  61. package/plugins/sp/scripts/task-size-precheck.ts +30 -4
  62. package/plugins/sp/scripts/transition-shim-check.ts +238 -0
  63. package/plugins/sp/scripts/validate-flag-contracts.ts +5 -2
  64. package/plugins/sp/skills/code-verification/SKILL.md +2 -0
  65. package/plugins/sp/skills/issue-finding/SKILL.md +123 -142
  66. package/plugins/sp/skills/issue-finding/examples/expected-findings.json +1 -1
  67. package/plugins/sp/skills/issue-finding/references/session-formats.md +85 -90
  68. package/plugins/sp/skills/next-router/SKILL.md +1 -1
  69. package/plugins/sp/skills/parallel-execution/references/dispatch-surface.md +40 -2
  70. package/plugins/sp/skills/spur-cli/SKILL.md +3 -0
  71. package/plugins/sp/skills/spur-cli/references/agent.md +12 -7
  72. package/plugins/sp/skills/spur-cli/references/team.md +10 -3
  73. package/plugins/sp/skills/spur-dev/SKILL.md +2 -0
  74. package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +17 -0
  75. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +44 -23
  76. package/plugins/sp/skills/spur-dev/references/dev-operations.md +14 -11
  77. package/plugins/sp/skills/spur-dev/references/execution-workflow.md +14 -12
  78. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +14 -3
  79. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +2 -0
  80. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +12 -2
  81. package/schemas/spur-config.schema.json +27 -3
  82. package/spur.js +11637 -7590
  83. package/web/_astro/BoardApp.8hiqShQn.js +1 -0
  84. package/web/_astro/{BoardApp.DKyrGxdo.js → BoardApp.BjQUNhuj.js} +74 -74
  85. package/web/_astro/{TaskDetail.6-27_LMa.js → TaskDetail.CVBuD6dF.js} +1 -1
  86. package/web/_astro/{arc.Df-9AQvS.js → arc.BMMjdODi.js} +1 -1
  87. package/web/_astro/{architectureDiagram-3BPJPVTR.VAI_-paS.js → architectureDiagram-3BPJPVTR.BU5ShzXf.js} +1 -1
  88. package/web/_astro/{blockDiagram-GPEHLZMM.DFpUY1ue.js → blockDiagram-GPEHLZMM.Bj1iEqPD.js} +1 -1
  89. package/web/_astro/{c4Diagram-AAUBKEIU.CF8doOpg.js → c4Diagram-AAUBKEIU.vX8wepCL.js} +1 -1
  90. package/web/_astro/channel.EwdSemIC.js +1 -0
  91. package/web/_astro/{chunk-2J33WTMH.BnjK3fjt.js → chunk-2J33WTMH.BKAipTym.js} +1 -1
  92. package/web/_astro/{chunk-4BX2VUAB.x6ZDnJKq.js → chunk-4BX2VUAB.B68XkPG7.js} +1 -1
  93. package/web/_astro/{chunk-55IACEB6.zY-0uu7w.js → chunk-55IACEB6.BmeDLcrc.js} +1 -1
  94. package/web/_astro/{chunk-727SXJPM.BZxKg_Vi.js → chunk-727SXJPM.PDuBA3Kw.js} +1 -1
  95. package/web/_astro/{chunk-AQP2D5EJ.Cpi9G9Td.js → chunk-AQP2D5EJ.C7A044za.js} +1 -1
  96. package/web/_astro/{chunk-FMBD7UC4.DWTB-Pif.js → chunk-FMBD7UC4.BtzKKFqR.js} +1 -1
  97. package/web/_astro/{chunk-ND2GUHAM.BPDQbiOG.js → chunk-ND2GUHAM.BJuDeeOy.js} +1 -1
  98. package/web/_astro/{chunk-QZHKN3VN.BRWIcuoM.js → chunk-QZHKN3VN.DSeMDgcQ.js} +1 -1
  99. package/web/_astro/{classDiagram-4FO5ZUOK.mGTCZsDO.js → classDiagram-4FO5ZUOK.D53Q4tCw.js} +1 -1
  100. package/web/_astro/{classDiagram-v2-Q7XG4LA2.mGTCZsDO.js → classDiagram-v2-Q7XG4LA2.D53Q4tCw.js} +1 -1
  101. package/web/_astro/{cose-bilkent-S5V4N54A.D1GEut-z.js → cose-bilkent-S5V4N54A.c712AFRH.js} +1 -1
  102. package/web/_astro/{dagre-BM42HDAG.BV0XG9Do.js → dagre-BM42HDAG.D-idisph.js} +1 -1
  103. package/web/_astro/{diagram-2AECGRRQ.DzpYxsjo.js → diagram-2AECGRRQ.DLgnsJCU.js} +1 -1
  104. package/web/_astro/{diagram-5GNKFQAL.Cm9YzJh4.js → diagram-5GNKFQAL.BiaxBVqx.js} +1 -1
  105. package/web/_astro/{diagram-KO2AKTUF.BjhottUj.js → diagram-KO2AKTUF.C8HX1vd8.js} +1 -1
  106. package/web/_astro/{diagram-LMA3HP47.BFsQW5kb.js → diagram-LMA3HP47.CfqDLLes.js} +1 -1
  107. package/web/_astro/{diagram-OG6HWLK6.8pdpzSWO.js → diagram-OG6HWLK6.15SDiEed.js} +1 -1
  108. package/web/_astro/{erDiagram-TEJ5UH35.Bd7KUJmJ.js → erDiagram-TEJ5UH35.DksYtOYM.js} +1 -1
  109. package/web/_astro/{flowDiagram-I6XJVG4X.7LWffkaE.js → flowDiagram-I6XJVG4X.DR_Au-HV.js} +1 -1
  110. package/web/_astro/{ganttDiagram-6RSMTGT7.BeDcO5tI.js → ganttDiagram-6RSMTGT7.CHhHrffI.js} +1 -1
  111. package/web/_astro/{gitGraphDiagram-PVQCEYII.Ca4n730A.js → gitGraphDiagram-PVQCEYII.B2Xehvam.js} +1 -1
  112. package/web/_astro/{index.Dbvuw6d4.css → index.DAxu50UF.css} +1 -1
  113. package/web/_astro/{infoDiagram-5YYISTIA.B0OakQYb.js → infoDiagram-5YYISTIA.C9c3CNNN.js} +1 -1
  114. package/web/_astro/{ishikawaDiagram-YF4QCWOH.DSmNQe-1.js → ishikawaDiagram-YF4QCWOH.BibUHkh8.js} +1 -1
  115. package/web/_astro/{journeyDiagram-JHISSGLW.Cy5ruEUu.js → journeyDiagram-JHISSGLW.BYoVHiyO.js} +1 -1
  116. package/web/_astro/{kanban-definition-UN3LZRKU.CUJXub0p.js → kanban-definition-UN3LZRKU.CM1K5wHE.js} +1 -1
  117. package/web/_astro/{linear.DC1jCCXn.js → linear.SPpjJUb-.js} +1 -1
  118. package/web/_astro/{mermaid.core.DxVP99Ab.js → mermaid.core.BAgx3nnb.js} +4 -4
  119. package/web/_astro/{mindmap-definition-RKZ34NQL.D0MaV6sJ.js → mindmap-definition-RKZ34NQL.D35oPG1R.js} +1 -1
  120. package/web/_astro/{pieDiagram-4H26LBE5.DCC6_q32.js → pieDiagram-4H26LBE5.DiWuRwk7.js} +1 -1
  121. package/web/_astro/{quadrantDiagram-W4KKPZXB.BeUOAM7C.js → quadrantDiagram-W4KKPZXB.B9PBzTWn.js} +1 -1
  122. package/web/_astro/{requirementDiagram-4Y6WPE33.Dbl4MASO.js → requirementDiagram-4Y6WPE33.CYuuamFN.js} +1 -1
  123. package/web/_astro/{sankeyDiagram-5OEKKPKP.HsLg0VS4.js → sankeyDiagram-5OEKKPKP.W24UhhtD.js} +1 -1
  124. package/web/_astro/{sequenceDiagram-3UESZ5HK.DT7DJTnZ.js → sequenceDiagram-3UESZ5HK.BpbNjA51.js} +1 -1
  125. package/web/_astro/{stateDiagram-AJRCARHV.d_ju1Vr1.js → stateDiagram-AJRCARHV.DqVsHudf.js} +1 -1
  126. package/web/_astro/{stateDiagram-v2-BHNVJYJU.DMCAjMJ4.js → stateDiagram-v2-BHNVJYJU.CzwHYX81.js} +1 -1
  127. package/web/_astro/{timeline-definition-PNZ67QCA.DNOHr62_.js → timeline-definition-PNZ67QCA.Bc3B6djw.js} +1 -1
  128. package/web/_astro/{vennDiagram-CIIHVFJN.B7dUy-1W.js → vennDiagram-CIIHVFJN.C-D5rh8O.js} +1 -1
  129. package/web/_astro/{wardley-L42UT6IY.DEqOXvBh.js → wardley-L42UT6IY.D7PdYCqn.js} +1 -1
  130. package/web/_astro/{wardleyDiagram-YWT4CUSO.BCRb2p6x.js → wardleyDiagram-YWT4CUSO.CwmJKXF3.js} +1 -1
  131. package/web/_astro/{xychartDiagram-2RQKCTM6.NxVQLdBh.js → xychartDiagram-2RQKCTM6.avDYnLsb.js} +1 -1
  132. package/web/index.html +2 -2
  133. package/web/_astro/BoardApp.Ce6zJYAH.js +0 -1
  134. package/web/_astro/channel.Uhm9O3UV.js +0 -1
@@ -1,37 +1,38 @@
1
1
  ---
2
2
  name: session-formats
3
- description: "Multi-source session log roots, tool-call field maps, OMP deep dive, and spur history bridge for sp:issue-finding."
3
+ description: "Source session-log root-path table and spur history bridge for sp:issue-finding."
4
4
  see_also:
5
5
  - issue-finding
6
6
  ---
7
7
 
8
- # Session log formats — multi-source discovery
8
+ # Session log formats — source discovery
9
9
 
10
- `sp:issue-finding` analyzes **raw session JSONL** for tool-loop forensics. Layout and event
11
- shapes differ by coding agent. This file is the SSOT for DISCOVER path selection and ANALYZE
12
- field mapping.
10
+ `sp:issue-finding` analyzes **raw session JSONL** for tool-loop forensics as the **fallback**
11
+ path only (task 0556): the primary REPORT path is the typed data plane
12
+ (`spur history report --mode forensics`). Layout and event shapes differ by coding agent. This
13
+ file covers **DISCOVER path** (where logs live) and the **history bridge**.
13
14
 
14
- **Confidence legend**
15
-
16
- | Level | Meaning |
17
- |-------|---------|
18
- | High | Documented adapter used successfully on real sessions (OMP) |
19
- | Medium | Default roots from Spur history help / importer sources; parse best-effort |
20
- | Low | Operator must pass `--sessions`; field map incomplete |
15
+ **What typed tables retain is owned by `mappers.ts`.** The importer
16
+ `@gobing-ai/ts-llm-jsonl-importer/src/mappers.ts` is the single code authority for which JSONL
17
+ fields each source populates on `history_message` / `history_tool_call` — including the
18
+ todo-tool `args_raw` retention allowlist (task 0553 R1). This skill holds **no duplicate field
19
+ map**; two maps that can disagree is the defect closed by 0553 R5.
21
20
 
22
21
  ## Source → default root
23
22
 
24
- | `--source` | Default root (expand `~`) | History import source | Fidelity |
25
- |------------|---------------------------|----------------------|----------|
26
- | `omp` | `~/.omp/agent/sessions/-<project-slug>/` | *(not a history source name)* | High |
27
- | `claude` | `~/.claude/projects/` | `claude` | Medium |
28
- | `codex` | `~/.codex/sessions/` | `codex` | Medium |
29
- | `gemini` | `~/.gemini/sessions/` | `gemini` | Medium |
30
- | `opencode` | agent-specific OpenCode session store (varies by install) | `opencode` | Low–Medium |
31
- | `antigravity` | agent-specific Antigravity session store | `antigravity` | Low–Medium |
32
- | `openclaw` | OpenClaw / `~/.agents/` session trees when present | `openclaw` | Low–Medium |
33
- | `pi` | Pi conversation/session roots (see `spur history` examples) | `pi` | Medium |
34
- | `auto` | Detect: prefer explicit agent if known; else first existing root among `omp`, `claude`, `codex`, `pi`, `gemini` | maps when importing | — |
23
+ | `--source` | Default root (expand `~`) | History import source |
24
+ |------------|---------------------------|----------------------|
25
+ | `omp` | `~/.omp/agent/sessions/-<project-slug>/` | *(not a history source name)* |
26
+ | `claude` | `~/.claude/projects/` | `claude` |
27
+ | `codex` | `~/.codex/sessions/` | `codex` |
28
+ | `gemini` | `~/.gemini/sessions/` | `gemini` |
29
+ | `opencode` | agent-specific OpenCode session store (varies by install) | `opencode` |
30
+ | `antigravity` | agent-specific Antigravity session store | `antigravity` |
31
+ | `openclaw` | OpenClaw / `~/.agents/` session trees when present | `openclaw` |
32
+ | `pi` | Pi conversation/session roots (see `spur history` examples) | `pi` |
33
+ | `grok` | `~/.grok/sessions/<url-encoded-workspace-path>/<session-uuid>/chat_history.jsonl` | `grok` |
34
+ | `agy` | *(no discoverable on-disk session format — VS Code fork)* | `agy` |
35
+ | `auto` | Detect: prefer explicit agent if known; else first existing root among `omp`, `claude`, `codex`, `pi`, `gemini` | maps when importing |
35
36
 
36
37
  **Project slug (OMP):** path under the sessions root is typically the project path with `/`
37
38
  replaced (e.g. `/Users/…/xprojects/spur-new` → `-Users-…-xprojects-spur-new` or
@@ -41,71 +42,20 @@ that matches the cwd project when ambiguous.
41
42
  **When the default root is missing or empty:** stop guessing. Ask for a path or require
42
43
  `--sessions <glob>`.
43
44
 
44
- ## Portable tool-call map
45
-
46
- When parsing a line of JSONL, look for tool/function invocations under common shapes:
47
-
48
- | Source family | Typical tool block type / path | Bash/command field |
49
- |---------------|--------------------------------|--------------------|
50
- | OMP / omp-agent | `message.content[]` entries with `type: "toolCall"` | `arguments.command` |
51
- | Claude Code | `type: "tool_use"` (or nested message content) | `input.command` / `input` |
52
- | Codex / others | Importer-normalized or vendor-specific; search for `command`, `tool_name`, `name` | best-effort |
53
-
54
- Always record **what field path you used** in the inventory Notes so evidence is auditable.
55
-
56
- **Fail-loud rule:** a zero tool-command count across a **non-empty** session set means the field map
57
- is wrong, not that the sessions were idle. Report a probable field-map error instead of an
58
- idle-session / no-waste finding — a parser that matches nothing must never produce a clean verdict
59
- (0534 R3; the OMP shape is `arguments.command`, verified: a toolCall block's keys are
60
- `['arguments','id','intent','name','partialArgs','streamIndex','type']`).
61
-
62
- **Loop detection (all sources):** normalize the shell command string and count consecutive or
63
- near-consecutive identical invocations (≥3) without an intervening source-file edit tool call.
64
-
65
- ## OMP deep dive (High fidelity)
66
-
67
- OMP/agent session logs are JSONL under `~/.omp/agent/sessions/-<project>/`:
68
-
69
- - Each line is a JSON object with a `type` field
70
- - Key event types: `session`, `message`, `compaction`, `title`, `title_change`, `custom`
71
- - Tool calls live in `message.content` as blocks with `type: "toolCall"` (**not** `tool_use`)
72
- - Bash tool calls expose `arguments.command` (verified live against OMP JSONL: a toolCall block's
73
- keys are `['arguments','id','intent','name','partialArgs','streamIndex','type']`)
74
- - Subagent sessions live in subdirectories (e.g. `Run0376/`, `Refine0378/`)
75
- - Subagents may have `*.log` beside the JSONL session file
76
- - Session start: `session.timestamp`
77
- - Session title: `title.title` (often auto-generated from the first user message)
78
- - Session id pattern: `<ISO-timestamp>_<UUID>.jsonl`
79
- - Cross-session: subagent messages may carry `parentId` linking to the parent session
80
-
81
- **Discovery without `--sessions`:** list the project sessions directory; take the newest
82
- timestamped main session file; include sibling subagent JSONL under that session’s tree.
83
-
84
- ## Claude / Codex / Pi / Gemini (Medium)
85
-
86
- Documented import examples (see `docs/help/cmd_history.md`):
87
-
88
- ```bash
89
- spur history import --source claude --root ~/.claude/projects --mode incremental
90
- spur history import --source codex --root ~/.codex/sessions/ --mode incremental
91
- spur history import --source gemini --root ~/.gemini/sessions/ --mode full
92
- spur history import --source pi --file ~/pi/logs/conversation.jsonl
93
- ```
94
-
95
- For issue-finding:
96
-
97
- 1. Prefer raw JSONL under those roots for tool-loop analysis.
98
- 2. Use `--sessions` when multiple projects share a root.
99
- 3. Tool event shapes may differ from OMP — use the portable map; do not force `toolCall`-only parsing.
45
+ **Fail-loud rule:** a zero tool-command count across a **non-empty** session set means the field
46
+ map is wrong, not that the sessions were idle. Report a probable field-map error instead of an
47
+ idle-session / no-waste finding — a parser that matches nothing must never produce a clean
48
+ verdict (0534 R3).
100
49
 
101
- ## History bridge (`--use-history`)
50
+ ## History bridge
102
51
 
103
- `spur history` holds **validated ETL + ledger**, not a full replacement for forensic JSONL:
52
+ `spur history` holds **validated ETL + ledger**. It is the primary REPORT path
53
+ (`spur history report --mode forensics`). Raw session JSONL is the named fallback only.
104
54
 
105
55
  | Need | Use |
106
56
  |------|-----|
107
- | Token / cost aggregates | `spur history analyze [--since …] --json` after import |
108
- | Identical test-command loops, guard retries, git red herrings | Raw session JSONL (this skill’s primary path) |
57
+ | Token / cost aggregates, derived forensics | `spur history analyze` then `spur history report --mode forensics` |
58
+ | Identical test-command loops, guard retries, git red herrings | Raw session JSONL (fallback primitives the typed tables do not retain) |
109
59
  | Multi-agent cost rollups | Import per source, then analyze |
110
60
 
111
61
  Import does not invent bottleneck categories. If import fails or the DB is empty, continue with
@@ -120,13 +70,13 @@ queries from that result:
120
70
  ```bash
121
71
  # one introspection pass, then write data queries against what it reports
122
72
  sqlite3 <db> "SELECT name, sql FROM sqlite_schema WHERE type='table' AND name LIKE 'history_%';"
123
- # (or a single `.schema history_<table>` invocation per referenced table)
124
73
  ```
125
74
 
126
75
  If a column you expected is absent, trust the live schema — do not guess. The importer's
127
- `HISTORY_IMPORT_SCHEMA_SQL` is the authority; this skill holds no duplicate column contract.
76
+ `HISTORY_IMPORT_SCHEMA_SQL` + `mappers.ts` are the authority; this skill holds no duplicate
77
+ column contract.
128
78
 
129
- **Selected-file bridge (task 0507 R3):** `--use-history` imports the frozen Phase-1 file set one
79
+ **Selected-file bridge (task 0507 R3):** the data-plane path imports the frozen Phase-1 file set one
130
80
  file at a time — never a root scan, never a full reconciliation. Ambient discovery covers the
131
81
  normal OMP root (`~/.omp/agent/sessions/`) **and** workflow subprocess sessions under
132
82
  `.spur/run/<run-id>/agent-sessions/<omp-executor>/*.jsonl` (same `type: "message"` envelope). For
@@ -134,25 +84,70 @@ each file, the session key is the JSONL filename stem (importer `sessionIdFromCo
134
84
  analyze per key:
135
85
 
136
86
  ```bash
137
- bun run apps/cli/src/index.ts history import --source omp --file <absolute-file> --mode force-file --json
138
- bun run apps/cli/src/index.ts history analyze --session <filename-stem> --json
87
+ spur history import --source omp --file <absolute-file> --mode force-file --json
88
+ spur history analyze --session <filename-stem> --json
139
89
  ```
140
90
 
141
91
  ETL owns token/cost/message/tool/loop/assistant-duration aggregates; raw JSONL stays authoritative
142
92
  for command text, compactions, test/guard retries, and tool execution duration/status/errors.
143
93
 
94
+ ## OMP tool-call block shapes (task 0564 R5)
95
+
96
+ Live OMP assistant messages emit **flat** toolCall blocks whose argument bag sits under
97
+ `arguments`; older sessions emit the **legacy nested** `{toolCall:{…}}` envelope, and an
98
+ intermediate shape used `input` as the argument key. The fallback parser and this skill must
99
+ read all three the way the importer does — **`mappers.ts` (`normalizeOmpToolCall`,
100
+ `call.input ?? call.arguments`) is the single field-map authority**; this section records the
101
+ shapes for recognition, it is not a second map.
102
+
103
+ 1. **Legacy nested block** — argument bag under a `toolCall` envelope:
104
+
105
+ ```json
106
+ {"type":"message","message":{"role":"assistant","content":[
107
+ {"toolCall":{"id":"call_x","name":"bash","arguments":{"command":"git status","i":"Check state"}}}
108
+ ]}}
109
+ ```
110
+
111
+ 2. **Flat block, legacy `input` key**:
112
+
113
+ ```json
114
+ {"type":"message","message":{"role":"assistant","content":[
115
+ {"type":"toolCall","id":"call_x","name":"bash","input":{"command":"git status","i":"Check state"}}
116
+ ]}}
117
+ ```
118
+
119
+ 3. **Flat block, current `arguments` key (live shape)** — `{type, id, name, arguments, intent,
120
+ partialArgs, streamIndex}`:
121
+
122
+ ```json
123
+ {"type":"message","message":{"role":"assistant","content":[
124
+ {"type":"toolCall","id":"call_x","name":"bash","arguments":{"command":"git status","i":"Check state"},
125
+ "intent":"Check state","partialArgs":"{\"command\":\"git status\",\"i\":\"Check state\"}","streamIndex":0}
126
+ ]}}
127
+ ```
128
+
129
+ The command text is the `command` field inside the argument bag: `call.input ?? call.arguments`
130
+ then `.command` — never a hardcoded key choice.
131
+
132
+ **toolResult messages** are `role: "toolResult"` message envelopes (not content blocks) carrying
133
+ `{toolCallId, toolName, content, details, isError, timestamp}` — `details.wallTimeMs` is the
134
+ tool's own measured wall time when present; `toolCallId` joins the originating `toolCall.id`.
135
+ The importer retains the timing (`history_tool_call.duration_ms` / `started_at` /
136
+ `completed_at`, task 0564 R1); raw logs stay authoritative for result text, which lives in
137
+ `content[].text` — not a `block.output` field.
138
+
144
139
  ## Edge cases
145
140
 
146
141
  | Scenario | Handling |
147
142
  |----------|----------|
148
143
  | No session root found | Fail DISCOVER with a clear message; request `--sessions` |
149
144
  | Huge multi-hour JSONL | Prefer Grep/rg for signal patterns first; sample then deep-read hot regions |
150
- | Mixed agents in one investigation | Run per `--source` or pass an explicit multi-file `--sessions` glob; label each sessions source |
151
- | Only transcript markdown available | Medium/Low confidence; extract commands from fenced blocks if present; mark evidence quality |
145
+ | Mixed agents in one investigation | Run per `--source` or pass an explicit multi-file `--sessions` glob; label each session's source |
152
146
  | Redacted / truncated logs | Analyze what remains; do not invent tool counts |
153
147
 
154
148
  ## Related
155
149
 
156
150
  - Skill entry: [../SKILL.md](../SKILL.md)
157
151
  - History CLI: `spur history --help`, `docs/help/cmd_history.md`
152
+ - Typed-table field authority: `@gobing-ai/ts-llm-jsonl-importer/src/mappers.ts`
158
153
  - Daily usage (not session forensics): `sp:daily-summary` / ccusage
@@ -47,7 +47,7 @@ silently (that is a HITL stop).
47
47
  | `--dry-run` | Print the resolved plan (**P1**) and do not dispatch. |
48
48
  | `--once` | Strip `--next` from the shaped child argv so only the current step runs; no router re-entry. |
49
49
  | `--auto` | Forward into dispatched children that support it. **Never** breaks multi-candidate HITL ties. |
50
- | `--agent <inline\|auto\|name>` | Execution-surface selector forwarded into the dispatched child when that child documents `--agent`. Router defaults inline; a named escalation trigger overrides `--agent inline`. Omit forward nothing. |
50
+ | `--agent <inline\|auto\|name>` | Execution-surface selector forwarded into the dispatched child when that child documents `--agent`. Router defaults to omit semantics: Omit forwards nothing, and the dispatched child applies its own default (host session, 0508 eligibility). Explicit `--agent inline` is the zero-dispatch carve-out, forwarded as-is; escalation triggers reject `inline` (no override). |
51
51
  | `--full` | When the primary route is `dev-run … --next`, substitute `dev-run <wbs> --mode full` (no `--next`). No effect on non-run routes → warning **W-FULL**. |
52
52
 
53
53
  ## Protocol (deterministic)
@@ -57,8 +57,8 @@ wrong choice visible in the transcript.
57
57
  `model_policy` (`min_tier` + ordered `fallback` chain, keyed on the canonical `stage_id`). This
58
58
  reference owns **execution-surface selection**. The two axes are orthogonal and vary independently:
59
59
 
60
- - A `cheap`-tier step can run in-session on a native subagent.
61
- - A `capable-3`-tier step can run headless through `spur agent run`.
60
+ - A `cheap`-floor step (e.g. the `scribe` role) can run in-session on a native subagent.
61
+ - A capable-band step (a role at or above `reviewer`, per [`roles.md`](../../../references/roles.md)) can run headless through `spur agent run`.
62
62
 
63
63
  Do not fold surface choice into `model_policy` - that would couple two axes that vary independently
64
64
  and put prompt-layer routing policy into a domain-layer registry. This reference decides *which
@@ -98,6 +98,44 @@ native subagent with shared-worktree capability); the inline driver remains the
98
98
  provenance, artifact validation, and no-replay guarantees. This reference stays the authority for
99
99
  the native-subagent versus `spur agent run` choice everywhere else.
100
100
 
101
+ ## Role propagation across fan-out (task 0551, feature I4)
102
+
103
+ When a run dispatches subagents, the **effective role** each subagent resolves through follows one
104
+ rule: **a declared role wins; absent a declaration, the subagent inherits the dispatcher's.**
105
+ Propagation is recorded, never implied: the resolution envelope carries `roleOrigin:
106
+ 'declared' | 'inherited'` per dispatched subagent (R3), so a wrong inheritance is observable
107
+ without reading the dispatcher's source. The role travels on the existing `--agent` selector —
108
+ no new flag (feature I4 § Notes).
109
+
110
+ Mechanism: `AgentService` stamps the dispatcher's resolved role into every spawned subprocess
111
+ environment as `SPUR_ROLE` (`RolePropagatingProcessExecutor`,
112
+ `packages/app/src/services/agent-service.ts`). A child `spur agent run` reads it at resolution;
113
+ a subagent that declares its own role (role selector, workflow `role:` step, explicit
114
+ `--agent <role>`) resolves through that role's tier and records `roleOrigin: 'declared'`; one
115
+ that declares nothing resolves through the inherited role's tier and records
116
+ `roleOrigin: 'inherited'` (stage context is engine-internal — stage-registry policy and
117
+ escalation — with no `--stage` CLI flag and no workflow step input; 0539 surface sweep).
118
+ Nested fan-out applies the rule recursively by construction — a grandchild reads
119
+ its parent's `SPUR_ROLE`, which the parent already set. An unknown inherited role (stale env)
120
+ warns once and falls through to `agent.default`/priority — inheritance never hard-fails a
121
+ dispatch (task 0536 R3 precedent).
122
+
123
+ **Dispatch-path inventory (R4)** — every path that shells out to `spur agent run` applies the
124
+ rule at the source, so no per-path shim is needed:
125
+
126
+ | Path | Where it dispatches | Rule coverage |
127
+ | --- | --- | --- |
128
+ | `spur agent run` (CLI) | `AgentService.run` → resolution → child process | Declared wins; absent inherits via `SPUR_ROLE`; envelope carries `roleOrigin` |
129
+ | Workflow `agent.run` step | `AgentRunActionRunner` → `AgentService.runTraced` | Step `role:` is **mandatory** (0538 R2, `agent-run.ts` fails a role-less step before dispatch) — always a declaration (`roleOrigin: 'declared'`); inheritance applies at the next fan-out boundary the step's subagent itself dispatches |
130
+ | `spur agent loop` | `AgentService.run` per drained iteration | Same resolution path as `spur agent run`; inherits its own `SPUR_ROLE` |
131
+ | `spur team` supervisor → member | spawns `spur agent loop` | Member inherits the supervisor's `SPUR_ROLE` (recursive by construction) |
132
+ | Native subagent fan-out (this skill's default) | in-session `Task()`/`Skill()` | In-session subagents share the host session; when they themselves dispatch, the host's role is already in the session env — the rule holds at the next `spur agent run` boundary |
133
+ | `plugins/sp/evals/run-eval.ts` | `spawnSync('spur agent run', …)` per scenario | Out of scope: a top-level eval harness, not a fan-out — no dispatcher role exists to inherit; each scenario is an independent top-level run (documented, no shim) |
134
+
135
+ The inventory is recorded in `docs/04_DESIGN.md` § `spur agent run` envelope (`roleOrigin`).
136
+ Paths that shell out to `spur agent run` without the rule would silently drop or double-attribute
137
+ a role; this table is the check that none do.
138
+
101
139
  ## See also
102
140
 
103
141
  - **`parallel-execution`** SKILL.md - the dispatch disciplines this rule sits beside.
@@ -120,6 +120,9 @@ the whole point of this facade is that the CLI surface has a single, scalable ho
120
120
  post-scaffold init validation (Phase 1.5/1.6 probes).
121
121
  - **`sp:spur-dev`** - the spine that dispatches these verbs into the planning +
122
122
  execution lifecycle. Use it to *drive* work; use this facade to *look up or operate a verb*.
123
+ - **`plugins/sp/references/roles.md`** — the Layer-1 role→tier table (`scribe` / `coder` /
124
+ `reviewer` / `planner`, one per tier). The facade's nouns/verbs serve those roles; the table is
125
+ the role vocabulary, the operator config maps tiers to executors.
123
126
  - **`sp:expert-spur`** — the subagent that loads this facade for multi-step, multi-noun corpus work
124
127
  in its own context window.
125
128
 
@@ -21,8 +21,8 @@ that before using `run` for fan-out dispatch.
21
21
 
22
22
  | Verb | Purpose | Key flags |
23
23
  | ---- | ------- | --------- |
24
- | `run <prompt>` | Execute a prompt or slash command via a coding agent | `--agent <name>` `--model <name>` `--mode <mode>` `--continue` `--cwd <path>` `--drain` `--json` |
25
- | `loop` | Persistent self-draining inbox loop for a team member (supervisor-managed) | `--agent <id>` `--poll <ms>` |
24
+ | `run <prompt>` | Execute a prompt or slash command via a coding agent | `--agent <name>` `--spec <id>` `--model <name>` `--mode <mode>` `--continue` `--cwd <path>` `--drain` `--json` |
25
+ | `loop` | Persistent self-draining inbox loop for a team member (supervisor-managed) | `--spec <id>` `--agent <id>` `--poll <ms>` |
26
26
  | `wait <specId>` | Identity-pinned wait for an occupant run to reach a lifecycle state (G4 wave 2) | `--run <runId>` `--until <state>...` `--timeout <ms>` `--json` |
27
27
  | `list` | List detected coding agents, or team agent specs with `--specs` | `--specs` `--json` |
28
28
  | `doctor [agent]` | Check agent readiness | `--json` |
@@ -36,8 +36,8 @@ invalid usage.
36
36
  ## `run` - execute a prompt via a coding agent
37
37
 
38
38
  ```bash
39
- spur agent run "Fix the login bug in src/auth/" --agent claude
40
- spur agent run "verify on o3" --agent codex --model o3
39
+ spur agent run "Fix the login bug in src/auth/" --agent coder
40
+ spur agent run "verify on o3" --agent reviewer --model o3
41
41
  spur agent run "/sp:dev-verify 0040" --agent omp --drain
42
42
  ```
43
43
 
@@ -48,14 +48,19 @@ through a coding agent as an external process, producing a persisted run record
48
48
 
49
49
  | Flag | Purpose |
50
50
  | ------ | --------- |
51
- | `--agent <name>` | Agent name or `auto`. Selects which installed coding agent executes the prompt. |
51
+ | `--agent <name>` | Role, executor, agent binary, `auto`, or `inline`. A **role** (`scribe`/`coder`/`reviewer`/`planner`, from `plugins/sp/references/roles.md`) selects the starting tier; an **executor** (an `agent.executors` entry) is a permanent pin; a **bare binary name** works with a one-time warning (transition shim); `auto` uses the declared/default role. **`inline` is host-session-only** (G5 / ADR-047 amendment): `agent run` is a headless subprocess surface, so explicit `inline` is rejected with exit 2 and a stable error message — it never normalizes to `agent.default`. |
52
52
  | `--model <name>` | Agent model argument (e.g. `o3`, `sonnet`). Passed through to the agent's model flag. |
53
53
  | `--mode <mode>` | Agent output mode: `text` or `json`. |
54
54
  | `--continue` | Resume the previous agent session instead of starting fresh. |
55
55
  | `--cwd <path>` | Working directory for agent execution (default: current directory). |
56
- | `--drain` | Prepend pending inbox messages addressed to `--agent <id>` before the prompt. |
56
+ | `--spec <id>` | Team agent spec id (occupant addressing, 0542 R1). Pairs with `--drain`; with `--spec` alone the run is addressed to the occupant without touching the inbox. A legacy `--agent <spec-id>` still works during the transition with a one-time warning (shim `agent-flag-spec-id`). |
57
+ | `--drain` | Prepend pending inbox messages addressed to `--spec <id>` before the prompt. |
57
58
  | `--json` | Output machine-readable JSON where supported. |
58
59
 
60
+ `--json` adds a `resolved` block (`{ role?, tier?, executor?, agent, source }`) reporting the
61
+ resolution decision — the role, its tier, and the executor that won for role routing; the pin for
62
+ an explicit executor; the canonical agent; and the resolution source.
63
+
59
64
  ### Dispatch-surface cross-reference
60
65
 
61
66
  `--agent` and `--model` are the **concrete levers** behind dispatch-surface trigger 1 ("Different
@@ -91,7 +96,7 @@ under supervision.
91
96
 
92
97
  | Flag | Purpose |
93
98
  |------|---------|
94
- | `--agent <id>` | **Required.** Agent spec id / message recipient. |
99
+ | `--spec <id>` | **Required.** Team agent spec id / message recipient (0542 R1; legacy `--agent <spec-id>` still read with a one-time warning). |
95
100
  | `--poll <ms>` | Idle poll interval in milliseconds (default: `2000`). |
96
101
 
97
102
  The loop runs until `SIGINT` / `SIGTERM`. Each iteration: check inbox -> if messages, drain each
@@ -49,7 +49,8 @@ spur team status --json # machine-readable
49
49
 
50
50
  Lists agent specs and their live run status. When `spur serve` is reachable, enriches each spec with
51
51
  the supervisor's process status (`running` / `stopped` / etc.); otherwise falls back to local spec
52
- metadata. `--by-team` groups specs by their `agent.team.<id>` tag.
52
+ metadata. Each row carries the member's declared `role` (rendered `unset` when undeclared, 0544)
53
+ and the spec's `executor`. `--by-team` groups specs by their `agent.team.<id>` tag.
53
54
 
54
55
  ### Flags
55
56
 
@@ -67,8 +68,14 @@ spur team up alpha --check # dry-run: show add/prune diff, no writes
67
68
  spur team up alpha --json
68
69
  ```
69
70
 
70
- Materializes a team roster (defined by specs sharing `agent.team.<team>`) into `.spur/agents/`
71
- specs - adding missing specs and pruning stale `spur:generated` ones. When `spur serve` is
71
+ Materializes the roster declared under `agent.team` in the project config for `<team>` into
72
+ `.spur/agents/` specs - adding missing specs and pruning stale `spur:generated` ones. **Role is
73
+ the primary axis (0543):** a member declares `role` (`scribe`/`coder`/`reviewer`/`planner`,
74
+ from `plugins/sp/references/roles.md`) and/or `executor`; a role-only member resolves an executor
75
+ through the shared tier ladder at materialization, and the written spec records both `role` and
76
+ the resolved `executor` so the decision is inspectable. A member declaring neither fails config
77
+ load naming the team and position. Local id stays `id ?? executor`; role-only members derive
78
+ `<role>-<n>` by declaration order. Generated specs carry the `agent.team.<team>` tag. When `spur serve` is
72
79
  reachable, best-effort starts each member. `--check` is a dry-run that shows the add/prune diff
73
80
  without writing.
74
81
 
@@ -211,6 +211,8 @@ for "what's actually in file Y" or for resources that sit outside the step seque
211
211
 
212
212
  **Config & companions (no single pipeline step owns these):**
213
213
 
214
+ - `plugins/sp/references/roles.md` — the Layer-1 role→tier table (`scribe` / `coder` / `reviewer` /
215
+ `planner`, one per tier); the role vocabulary this spine's operations route under.
214
216
  - `.spur/workflows/task-pipeline.yaml` — the execution pipeline definition.
215
217
  - `.spur/workflows/planning-pipeline.yaml` — the front-half state machine.
216
218
  - `.spur/templates/bdd/gherkin.md` — the BDD scenario template.
@@ -113,6 +113,23 @@ Any of the four may additionally carry a **bracket tag** in any position — `[d
113
113
  `Scenario: [advisory] Foo`. Tags are stripped before matching (0398 R7), so tagging never breaks
114
114
  the linkage.
115
115
 
116
+ ### The id is exactly the scenario title — no Gherkin body appended
117
+
118
+ An AC row id must be **exactly** the scenario title (plus any of the four forms above), with the
119
+ Gherkin body left in the task's `### Acceptance Criteria` block. Never append the scenario's
120
+ `Given … / When … / Then …` steps to the row id:
121
+
122
+ ```markdown
123
+ | R3 — Foo | MET | test | `tests/foo.test.ts:12` | ← correct
124
+ | Scenario: R3 — Foo (Given … / When … / Then …) | MET | test | … | ← never
125
+ ```
126
+
127
+ The verifier preserves row ids verbatim in the verdict artifact (evidence is not rewritten), and
128
+ the feature scenario gate strips a trailing parenthetical only as a *backstop* for artifacts that
129
+ already carry one (0561). Appending the body is still a contract violation and makes the row
130
+ unmatchable in edge cases (a title that legitimately ends in `(...)` plus a body), so keep ids
131
+ clean at authoring time.
132
+
116
133
  ### Which tags exempt a row from executable evidence
117
134
 
118
135
  A `MET` row is silently demoted to `PARTIAL` unless it carries `test` or `command` evidence — the
@@ -36,13 +36,23 @@ answer. Everything below is a consequence of that sentence, not an additional ru
36
36
 
37
37
  **Default: execute the backing skill directly in the current coding-agent session.** Do not invoke
38
38
  `spur agent run` when no escalation trigger applies and the operator did not select subprocess via
39
- the `--agent` selector. Omitting `--agent` is exactly `--agent inline`; the explicit value is useful
40
- in scripts and audit output but does not change the default.
39
+ the `--agent` selector. Omitting `--agent` keeps the default the backing skill runs in the
40
+ current session, and eligible model stages may dispatch once to a native subagent (task 0508). The
41
+ explicit value is useful in scripts and audit output but is not the default: explicit `inline`
42
+ selects the zero-dispatch carve-out below.
43
+
44
+ > **Explicit `--agent inline` is a hard host-session guarantee: all model-bearing work executes in
45
+ > the invoking host session — never a native subagent, never a subprocess, never a workflow hop.
46
+ > The 0508 native-subagent eligibility applies to **omitted** `--agent` only. Headless surfaces
47
+ > (`spur agent run`, workflow `agent.run`, serve-side dispatch) reject `inline` with the stable
48
+ > special error (exit 2 at the CLI) and take no further action — no dispatch, no `agent.default`
49
+ > fallback.**
41
50
 
42
51
  | Value | Who does the work | Derived surface |
43
52
  |---|---|---|
44
- | `inline` (default when omitted) | Whoever is running this session (interactive) or `agent.default` (headless) | Interactive: inline — host-controlled, eligible model stages may use a native subagent (0508); headless: subprocess of `agent.default` |
45
- | `auto` | Tier-resolved from the stage's `min_tier` + `fallback` | Subprocess a tier-resolved executor pins a specific agent/model, which the host session cannot supply |
53
+ | `(omitted)` | The agent running this session | Host session — host-controlled; eligible model stages may use a native subagent (0508) |
54
+ | `inline` | The agent running this session | Host sessionhard guarantee: zero dispatch, never a subprocess, never a workflow hop; headless surfaces reject `inline` (exit 2, stable special error) |
55
+ | `auto` | The role the caller declared — this command's `role:` frontmatter or the workflow step's `role:` (Layer 1, `plugins/sp/references/roles.md`); with nothing declared, `agent.default`'s role (0542) | Subprocess — a tier-resolved executor pins a specific agent/model, which the host session cannot supply |
46
56
  | `<name>` (coding agent or configured executor) | That executor | Inline when it resolves to the current session's agent; subprocess otherwise |
47
57
 
48
58
  The previous `--inline` and `--subprocess` flags (feature H82, task 0413) are collapsed into this
@@ -53,8 +63,11 @@ This is a prompt-runtime rule owned by the command wrapper and its backing skill
53
63
  `AgentService`: the current coding agent is already executing the command, so inline means continuing
54
64
  in that session. Threading an `inline` option through `AiRunner` would still start a subprocess and
55
65
  would therefore be a false implementation. On a headless surface (`spur agent run` / workflow
56
- `agent.run`) `inline` is **not** rejected (ADR-047): it resolves exactly like omitting the flag to a
57
- subprocess of `agent.default`.
66
+ `agent.run`) explicit `inline` is **rejected** (ADR-047 G5 amendment) with the stable special error
67
+ headless surfaces cannot host a session: `--agent inline requires a host session: this surface is
68
+ headless and never dispatches inline runs (no fallback to agent.default). Use 'auto', a role, or an
69
+ executor name.` (exit 2 at the CLI; the exported `AGENT_INLINE_HEADLESS_MESSAGE` in
70
+ `agent-service`). No further action is taken — no dispatch, no `agent.default` fallback.
58
71
 
59
72
  ### Objective triggers override the answer
60
73
 
@@ -68,8 +81,10 @@ cannot satisfy, so it wins regardless:
68
81
  | **Durable auditable run record required** | The caller requires a persisted cost/trace/exit-code record. | `trigger 3: durable auditable run record required` |
69
82
  | **Workspace or credential isolation required** | The work must not share the host workspace or credentials. | `trigger 4: workspace or credential isolation required` |
70
83
 
71
- A trigger selects subprocess even when `--agent inline` was supplied, and the applied trigger must be
72
- named in the dispatch or result. When the operator selected a non-current executor and no objective trigger
84
+ A trigger selects subprocess when the selector is omitted, `auto`, or a name, and the applied trigger
85
+ must be named in the dispatch or result. Explicit `--agent inline` is the hard host-session carve-out:
86
+ a trigger requirement that cannot be satisfied in-session rejects with the stable special error rather
87
+ than dispatching a subprocess. When the operator selected a non-current executor and no objective trigger
73
88
  applies, report `operator override` rather than inventing one of the four. The trigger vocabulary and
74
89
  evidence standard are owned by
75
90
  [dispatch-surface.md](../../parallel-execution/references/dispatch-surface.md). If none can be named
@@ -103,20 +118,23 @@ the thinking happens in the stages. Selecting an executor for a loop that runs n
103
118
  meaningless.
104
119
 
105
120
  **Interactive task pipelines invert control into the host session (ADR-047 amendment).**
106
- `dev-run --mode full` and sequential `dev-runall` with omit/`inline` interpret the existing
107
- `task-pipeline.yaml` in the host session; they do not launch `spur workflow run` and never redirect
108
- silently to `agent.default`. Interactive inline is **host-controlled and non-subprocess**, but no
109
- longer guarantees host-context execution for every model stage (task 0508): an eligible `agent.run`
110
- stage — pure-slash input, non-interactive state, native subagent with shared-worktree
111
- read/write/shell capability — dispatches **once** to that native subagent and joins before the
112
- driver continues; any pre-dispatch eligibility failure falls back to one host execution, and a
113
- failure after dispatch follows the stage's error policy with no automatic host replay. Operator
121
+ `dev-run --mode full` and sequential `dev-runall` with omitted `--agent` or explicit `--agent
122
+ inline` interpret the existing `task-pipeline.yaml` in the host session; they do not launch `spur
123
+ workflow run` and never redirect silently to `agent.default`. Interactive **omit** is
124
+ **host-controlled and non-subprocess**, but no longer guarantees host-context execution for every
125
+ model stage (task 0508): an eligible `agent.run` stage — pure-slash input, non-interactive state,
126
+ native subagent with shared-worktree read/write/shell capability — dispatches **once** to that
127
+ native subagent and joins before the driver continues; any pre-dispatch eligibility failure falls
128
+ back to one host execution, and a failure after dispatch follows the stage's error policy with no
129
+ automatic host replay. Explicit `--agent inline` is the zero-dispatch carve-out: every model stage
130
+ executes in the invoking host session — no native-subagent leg. Operator
114
131
  confirmation actions, `pause: true`, and approve/taste/ask decisions stay host-owned. Each inline
115
132
  model stage appends `stage <id> executed inline in session <session-id>` to its run log; a
116
133
  subagent-dispatched stage appends `stage <id> executed via subagent <agent-id> (host session
117
134
  <session-id>)` instead. `dev-plan` remains a workflow subprocess, as do `dev-run`/`dev-runall` with
118
135
  `--agent auto` or a name, parallel batches, and every headless `spur workflow run` / `spur agent
119
- run`. `dev-run --mode implement` continues to run its single competency in-session under omit/`inline`.
136
+ run`. `dev-run --mode implement` continues to run its single competency in-session under omitted
137
+ `--agent` or explicit `--agent inline` (zero-dispatch).
120
138
 
121
139
  ### Executor precedence chain (R7)
122
140
 
@@ -133,10 +151,11 @@ resolved in this order; first match wins:
133
151
 
134
152
  `--agent auto` tier-resolves an executor (stage `model_policy` → `agent.default` → tier priority)
135
153
  **before** merging, so it enters the chain at step 1 already resolved to a concrete name.
136
- On a headless workflow surface, `--agent inline` resolves like omit to `agent.default`. Interactive
137
- task wrappers consume omit/`inline` before this chain and use the host driver. Omitting the flag on a
138
- headless surface forwards nothing, so the spawned step resolves to `agent.default` (step 2) or the
139
- YAML literal (step 3).
154
+ On a headless workflow surface, explicit `--agent inline` is rejected with the stable special error
155
+ the surface cannot host a session. Interactive task wrappers consume omitted `--agent` (0508
156
+ eligibility) and explicit `inline` (zero-dispatch carve-out) before this chain and use the host
157
+ driver. Omitting the flag on a headless surface forwards nothing, so the spawned step resolves to
158
+ `agent.default` (step 2) or the YAML literal (step 3).
140
159
 
141
160
  ### Implement-only executor override (R6)
142
161
 
@@ -181,8 +200,10 @@ explicit process boundary and retain their existing resolution, output, timeout,
181
200
  contracts. The interactive task wrapper does not change the YAML or engine; it reads the YAML as
182
201
  SSOT and interprets the actions in-session before any workflow subprocess exists. It records inline
183
202
  provenance without fabricating an `AgentRunTracedResult`.
184
- `spur agent run` itself resolves omit/`inline` to `agent.default` and `--agent auto` tier-resolves —
185
- the unified `--agent` selector on the dev command surface does not change the CLI's resolution.
203
+ `spur agent run` itself resolves omitted `--agent` to `agent.default`, rejects explicit `--agent
204
+ inline` with the stable special error (a headless surface cannot host a session), and `--agent
205
+ auto` tier-resolves — the unified `--agent` selector on the dev command surface does not change the
206
+ CLI's resolution.
186
207
 
187
208
  ### Inline trade-off
188
209