@gobing-ai/spur 0.3.46 → 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/templates/docs/99_PROJECT_CONSTITUTION.md +16 -4
- 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 +124 -143
- package/plugins/sp/skills/issue-finding/examples/expected-findings.json +1 -1
- package/plugins/sp/skills/issue-finding/references/session-formats.md +85 -83
- 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/features.md +3 -0
- package/plugins/sp/skills/spur-cli/references/tasks.md +3 -0
- 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 +11648 -7595
- 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,37 +1,38 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: session-formats
|
|
3
|
-
description: "
|
|
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 —
|
|
8
|
+
# Session log formats — source discovery
|
|
9
9
|
|
|
10
|
-
`sp:issue-finding` analyzes **raw session JSONL** for tool-loop forensics
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
**
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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 |
|
|
25
|
-
|
|
26
|
-
| `omp` | `~/.omp/agent/sessions/-<project-slug>/` | *(not a history source name)* |
|
|
27
|
-
| `claude` | `~/.claude/projects/` | `claude` |
|
|
28
|
-
| `codex` | `~/.codex/sessions/` | `codex` |
|
|
29
|
-
| `gemini` | `~/.gemini/sessions/` | `gemini` |
|
|
30
|
-
| `opencode` | agent-specific OpenCode session store (varies by install) | `opencode` |
|
|
31
|
-
| `antigravity` | agent-specific Antigravity session store | `antigravity` |
|
|
32
|
-
| `openclaw` | OpenClaw / `~/.agents/` session trees when present | `openclaw` |
|
|
33
|
-
| `pi` | Pi conversation/session roots (see `spur history` examples) | `pi` |
|
|
34
|
-
| `
|
|
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,64 +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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
| Source family | Typical tool block type / path | Bash/command field |
|
|
49
|
-
|---------------|--------------------------------|--------------------|
|
|
50
|
-
| OMP / omp-agent | `message.content[]` entries with `type: "toolCall"` | `input.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
|
-
**Loop detection (all sources):** normalize the shell command string and count consecutive or
|
|
57
|
-
near-consecutive identical invocations (≥3) without an intervening source-file edit tool call.
|
|
58
|
-
|
|
59
|
-
## OMP deep dive (High fidelity)
|
|
60
|
-
|
|
61
|
-
OMP/agent session logs are JSONL under `~/.omp/agent/sessions/-<project>/`:
|
|
62
|
-
|
|
63
|
-
- Each line is a JSON object with a `type` field
|
|
64
|
-
- Key event types: `session`, `message`, `compaction`, `title`, `title_change`, `custom`
|
|
65
|
-
- Tool calls live in `message.content` as blocks with `type: "toolCall"` (**not** `tool_use`)
|
|
66
|
-
- Bash tool calls expose `input.command`
|
|
67
|
-
- Subagent sessions live in subdirectories (e.g. `Run0376/`, `Refine0378/`)
|
|
68
|
-
- Subagents may have `*.log` beside the JSONL session file
|
|
69
|
-
- Session start: `session.timestamp`
|
|
70
|
-
- Session title: `title.title` (often auto-generated from the first user message)
|
|
71
|
-
- Session id pattern: `<ISO-timestamp>_<UUID>.jsonl`
|
|
72
|
-
- Cross-session: subagent messages may carry `parentId` linking to the parent session
|
|
73
|
-
|
|
74
|
-
**Discovery without `--sessions`:** list the project sessions directory; take the newest
|
|
75
|
-
timestamped main session file; include sibling subagent JSONL under that session’s tree.
|
|
76
|
-
|
|
77
|
-
## Claude / Codex / Pi / Gemini (Medium)
|
|
78
|
-
|
|
79
|
-
Documented import examples (see `docs/help/cmd_history.md`):
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
spur history import --source claude --root ~/.claude/projects --mode incremental
|
|
83
|
-
spur history import --source codex --root ~/.codex/sessions/ --mode incremental
|
|
84
|
-
spur history import --source gemini --root ~/.gemini/sessions/ --mode full
|
|
85
|
-
spur history import --source pi --file ~/pi/logs/conversation.jsonl
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
For issue-finding:
|
|
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).
|
|
89
49
|
|
|
90
|
-
|
|
91
|
-
2. Use `--sessions` when multiple projects share a root.
|
|
92
|
-
3. Tool event shapes may differ from OMP — use the portable map; do not force `toolCall`-only parsing.
|
|
50
|
+
## History bridge
|
|
93
51
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
`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.
|
|
97
54
|
|
|
98
55
|
| Need | Use |
|
|
99
56
|
|------|-----|
|
|
100
|
-
| Token / cost aggregates | `spur history analyze
|
|
101
|
-
| Identical test-command loops, guard retries, git red herrings | Raw session JSONL (
|
|
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) |
|
|
102
59
|
| Multi-agent cost rollups | Import per source, then analyze |
|
|
103
60
|
|
|
104
61
|
Import does not invent bottleneck categories. If import fails or the DB is empty, continue with
|
|
@@ -113,13 +70,13 @@ queries from that result:
|
|
|
113
70
|
```bash
|
|
114
71
|
# one introspection pass, then write data queries against what it reports
|
|
115
72
|
sqlite3 <db> "SELECT name, sql FROM sqlite_schema WHERE type='table' AND name LIKE 'history_%';"
|
|
116
|
-
# (or a single `.schema history_<table>` invocation per referenced table)
|
|
117
73
|
```
|
|
118
74
|
|
|
119
75
|
If a column you expected is absent, trust the live schema — do not guess. The importer's
|
|
120
|
-
`HISTORY_IMPORT_SCHEMA_SQL`
|
|
76
|
+
`HISTORY_IMPORT_SCHEMA_SQL` + `mappers.ts` are the authority; this skill holds no duplicate
|
|
77
|
+
column contract.
|
|
121
78
|
|
|
122
|
-
**Selected-file bridge (task 0507 R3):**
|
|
79
|
+
**Selected-file bridge (task 0507 R3):** the data-plane path imports the frozen Phase-1 file set one
|
|
123
80
|
file at a time — never a root scan, never a full reconciliation. Ambient discovery covers the
|
|
124
81
|
normal OMP root (`~/.omp/agent/sessions/`) **and** workflow subprocess sessions under
|
|
125
82
|
`.spur/run/<run-id>/agent-sessions/<omp-executor>/*.jsonl` (same `type: "message"` envelope). For
|
|
@@ -127,25 +84,70 @@ each file, the session key is the JSONL filename stem (importer `sessionIdFromCo
|
|
|
127
84
|
analyze per key:
|
|
128
85
|
|
|
129
86
|
```bash
|
|
130
|
-
|
|
131
|
-
|
|
87
|
+
spur history import --source omp --file <absolute-file> --mode force-file --json
|
|
88
|
+
spur history analyze --session <filename-stem> --json
|
|
132
89
|
```
|
|
133
90
|
|
|
134
91
|
ETL owns token/cost/message/tool/loop/assistant-duration aggregates; raw JSONL stays authoritative
|
|
135
92
|
for command text, compactions, test/guard retries, and tool execution duration/status/errors.
|
|
136
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
|
+
|
|
137
139
|
## Edge cases
|
|
138
140
|
|
|
139
141
|
| Scenario | Handling |
|
|
140
142
|
|----------|----------|
|
|
141
143
|
| No session root found | Fail DISCOVER with a clear message; request `--sessions` |
|
|
142
144
|
| Huge multi-hour JSONL | Prefer Grep/rg for signal patterns first; sample then deep-read hot regions |
|
|
143
|
-
| Mixed agents in one investigation | Run per `--source` or pass an explicit multi-file `--sessions` glob; label each session
|
|
144
|
-
| 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 |
|
|
145
146
|
| Redacted / truncated logs | Analyze what remains; do not invent tool counts |
|
|
146
147
|
|
|
147
148
|
## Related
|
|
148
149
|
|
|
149
150
|
- Skill entry: [../SKILL.md](../SKILL.md)
|
|
150
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`
|
|
151
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
|
|
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`-
|
|
61
|
-
- A
|
|
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
|
|
40
|
-
spur agent run "verify on o3" --agent
|
|
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>` |
|
|
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`
|
|
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
|
-
| `--
|
|
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
|
|
@@ -99,6 +99,9 @@ spur feature update H2 --section "Acceptance Criteria" --from-file /tmp/ac.md
|
|
|
99
99
|
`--section` **requires** `--from-file` (exit `2` otherwise). Replaces the whole named section body.
|
|
100
100
|
The `## Tasks` block is still rebuilt by `refresh` (files win for that region).
|
|
101
101
|
|
|
102
|
+
Valid section names without a failed write: `spur task sections <wbs> list` (the same pointer
|
|
103
|
+
`spur task update --help` carries).
|
|
104
|
+
|
|
102
105
|
**Advance** (multi-hop forward walk):
|
|
103
106
|
|
|
104
107
|
```bash
|
|
@@ -24,6 +24,7 @@ Start from the WBS, not the corpus layout:
|
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
26
|
spur task show <wbs> --json # metadata + full content + filePath
|
|
27
|
+
spur task get <wbs> --json # alias of `show` — same output, no separate code path
|
|
27
28
|
spur task path <wbs> --json # absolute path only
|
|
28
29
|
```
|
|
29
30
|
|
|
@@ -148,6 +149,8 @@ spur task update 0040 --section Review --from-file /tmp/review.md
|
|
|
148
149
|
read from a file (this is what makes edits crash-safe and reviewable). Exit `2` otherwise.
|
|
149
150
|
- Section names match the DD-08 task headings: `Background`, `Acceptance Criteria`, `Plan`,
|
|
150
151
|
`Solution`, `Testing`, `Review`, `References`, `History`.
|
|
152
|
+
- Valid section names without a failed write: `spur task sections <wbs> list` (the same
|
|
153
|
+
pointer `task update --help` carries).
|
|
151
154
|
- The write replaces the **whole** named section body; assemble the full section in the temp file
|
|
152
155
|
first, then point `--from-file` at it.
|
|
153
156
|
|
|
@@ -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.
|
|
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
|
|
71
|
-
specs - adding missing specs and pruning stale `spur:generated` ones.
|
|
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`
|
|
40
|
-
|
|
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
|
-
| `
|
|
45
|
-
| `
|
|
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 session — hard 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 **
|
|
57
|
-
|
|
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
|
|
72
|
-
named in the dispatch or result.
|
|
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
|
|
107
|
-
`task-pipeline.yaml` in the host session; they do not launch `spur
|
|
108
|
-
silently to `agent.default`. Interactive
|
|
109
|
-
longer guarantees host-context execution for every
|
|
110
|
-
stage — pure-slash input, non-interactive state,
|
|
111
|
-
read/write/shell capability — dispatches **once** to that
|
|
112
|
-
driver continues; any pre-dispatch eligibility failure falls
|
|
113
|
-
failure after dispatch follows the stage's error policy with no
|
|
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
|
|
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`
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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
|
|
185
|
-
|
|
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
|
|