@gobing-ai/spur 0.3.47 → 0.3.49
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 +94 -15
- 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/pr-review.yaml +338 -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 +8 -8
- package/plugins/sp/README.md +9 -6
- 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 → dev-feature-change.md} +8 -10
- package/plugins/sp/commands/dev-find-conflict.md +2 -1
- package/plugins/sp/commands/dev-find-issue.md +36 -43
- package/plugins/sp/commands/dev-find-next.md +5 -4
- 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 +12 -12
- package/plugins/sp/commands/dev-handover.md +1 -0
- package/plugins/sp/commands/dev-history-load.md +63 -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-pr-review.md +39 -0
- 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 +106 -0
- package/plugins/sp/scripts/feature-sync-bounded.ts +28 -2
- package/plugins/sp/scripts/history-load.ts +400 -0
- package/plugins/sp/scripts/pr-reviewing.ts +867 -0
- 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-commands.ts +33 -2
- package/plugins/sp/scripts/validate-flag-contracts.ts +5 -2
- package/plugins/sp/skills/code-implementation/SKILL.md +9 -1
- package/plugins/sp/skills/code-verification/SKILL.md +29 -28
- package/plugins/sp/skills/issue-finding/SKILL.md +123 -141
- package/plugins/sp/skills/issue-finding/examples/expected-findings.json +1 -1
- package/plugins/sp/skills/issue-finding/references/session-formats.md +87 -90
- package/plugins/sp/skills/next-feature/SKILL.md +6 -6
- package/plugins/sp/skills/next-feature/references/handoff-routing.md +5 -5
- package/plugins/sp/skills/next-feature/references/signal-derivation.md +7 -2
- 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/pr-reviewing/SKILL.md +285 -0
- 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/hierarchy-mece.md +5 -5
- package/plugins/sp/skills/spur-cli/references/features.md +1 -1
- 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 +28 -7
- 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 +47 -3
- package/spur.js +12223 -7716
- 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,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
|
-
|
|
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"` | `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
|
|
50
|
+
## History bridge
|
|
102
51
|
|
|
103
|
-
`spur history` holds **validated ETL + ledger
|
|
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
|
|
108
|
-
| 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) |
|
|
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`
|
|
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):**
|
|
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,72 @@ each file, the session key is the JSONL filename stem (importer `sessionIdFromCo
|
|
|
134
84
|
analyze per key:
|
|
135
85
|
|
|
136
86
|
```bash
|
|
137
|
-
|
|
138
|
-
|
|
87
|
+
# Monorepo-safe spur resolution (0568 R6): SPUR_BIN env > monorepo-local CLI > PATH.
|
|
88
|
+
SPUR_BIN="${SPUR_BIN:-$([ -f apps/cli/src/index.ts ] && echo 'bun apps/cli/src/index.ts' || echo spur)}"
|
|
89
|
+
$SPUR_BIN history import --source omp --file <absolute-file> --mode force-file --json
|
|
90
|
+
$SPUR_BIN history analyze --session <filename-stem> --json
|
|
139
91
|
```
|
|
140
92
|
|
|
141
93
|
ETL owns token/cost/message/tool/loop/assistant-duration aggregates; raw JSONL stays authoritative
|
|
142
94
|
for command text, compactions, test/guard retries, and tool execution duration/status/errors.
|
|
143
95
|
|
|
96
|
+
## OMP tool-call block shapes (task 0564 R5)
|
|
97
|
+
|
|
98
|
+
Live OMP assistant messages emit **flat** toolCall blocks whose argument bag sits under
|
|
99
|
+
`arguments`; older sessions emit the **legacy nested** `{toolCall:{…}}` envelope, and an
|
|
100
|
+
intermediate shape used `input` as the argument key. The fallback parser and this skill must
|
|
101
|
+
read all three the way the importer does — **`mappers.ts` (`normalizeOmpToolCall`,
|
|
102
|
+
`call.input ?? call.arguments`) is the single field-map authority**; this section records the
|
|
103
|
+
shapes for recognition, it is not a second map.
|
|
104
|
+
|
|
105
|
+
1. **Legacy nested block** — argument bag under a `toolCall` envelope:
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{"type":"message","message":{"role":"assistant","content":[
|
|
109
|
+
{"toolCall":{"id":"call_x","name":"bash","arguments":{"command":"git status","i":"Check state"}}}
|
|
110
|
+
]}}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
2. **Flat block, legacy `input` key**:
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{"type":"message","message":{"role":"assistant","content":[
|
|
117
|
+
{"type":"toolCall","id":"call_x","name":"bash","input":{"command":"git status","i":"Check state"}}
|
|
118
|
+
]}}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
3. **Flat block, current `arguments` key (live shape)** — `{type, id, name, arguments, intent,
|
|
122
|
+
partialArgs, streamIndex}`:
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{"type":"message","message":{"role":"assistant","content":[
|
|
126
|
+
{"type":"toolCall","id":"call_x","name":"bash","arguments":{"command":"git status","i":"Check state"},
|
|
127
|
+
"intent":"Check state","partialArgs":"{\"command\":\"git status\",\"i\":\"Check state\"}","streamIndex":0}
|
|
128
|
+
]}}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The command text is the `command` field inside the argument bag: `call.input ?? call.arguments`
|
|
132
|
+
then `.command` — never a hardcoded key choice.
|
|
133
|
+
|
|
134
|
+
**toolResult messages** are `role: "toolResult"` message envelopes (not content blocks) carrying
|
|
135
|
+
`{toolCallId, toolName, content, details, isError, timestamp}` — `details.wallTimeMs` is the
|
|
136
|
+
tool's own measured wall time when present; `toolCallId` joins the originating `toolCall.id`.
|
|
137
|
+
The importer retains the timing (`history_tool_call.duration_ms` / `started_at` /
|
|
138
|
+
`completed_at`, task 0564 R1); raw logs stay authoritative for result text, which lives in
|
|
139
|
+
`content[].text` — not a `block.output` field.
|
|
140
|
+
|
|
144
141
|
## Edge cases
|
|
145
142
|
|
|
146
143
|
| Scenario | Handling |
|
|
147
144
|
|----------|----------|
|
|
148
145
|
| No session root found | Fail DISCOVER with a clear message; request `--sessions` |
|
|
149
146
|
| 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 session
|
|
151
|
-
| Only transcript markdown available | Medium/Low confidence; extract commands from fenced blocks if present; mark evidence quality |
|
|
147
|
+
| Mixed agents in one investigation | Run per `--source` or pass an explicit multi-file `--sessions` glob; label each session's source |
|
|
152
148
|
| Redacted / truncated logs | Analyze what remains; do not invent tool counts |
|
|
153
149
|
|
|
154
150
|
## Related
|
|
155
151
|
|
|
156
152
|
- Skill entry: [../SKILL.md](../SKILL.md)
|
|
157
153
|
- History CLI: `spur history --help`, `docs/help/cmd_history.md`
|
|
154
|
+
- Typed-table field authority: `@gobing-ai/ts-llm-jsonl-importer/src/mappers.ts`
|
|
158
155
|
- Daily usage (not session forensics): `sp:daily-summary` / ccusage
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: next-feature
|
|
3
|
-
description: "Prompt-first feature frontier prioritizer — answers 'which feature should we work on now?' by deriving importance/urgency from corpus, git, and authority-doc evidence, and emits rank-distorting tree defects as proposals /sp:dev-
|
|
3
|
+
description: "Prompt-first feature frontier prioritizer — answers 'which feature should we work on now?' by deriving importance/urgency from corpus, git, and authority-doc evidence, and emits rank-distorting tree defects as proposals /sp:dev-feature-change consumes. Triggers: find next, which feature, feature ranking, frontier priority, what should I work on."
|
|
4
4
|
license: Apache-2.0
|
|
5
5
|
version: 1.0.0
|
|
6
6
|
metadata:
|
|
@@ -30,7 +30,7 @@ A prompt-first prioritizer that answers **"which feature should we work on now?"
|
|
|
30
30
|
`sp:next-router` deliberately does not answer (`routing-table.md` §0 step 1c: target omitted → not
|
|
31
31
|
v1). It derives importance and urgency from evidence already in the corpus, ranks the actionable
|
|
32
32
|
frontier in **tiers with per-candidate evidence**, and emits rank-distorting tree defects as
|
|
33
|
-
**proposals** `/sp:dev-
|
|
33
|
+
**proposals** `/sp:dev-feature-change` consumes.
|
|
34
34
|
|
|
35
35
|
**Honesty contract:** prompt-first. The model applies the rubric; existing deterministic tools
|
|
36
36
|
(`spur feature|task … --json`, `git`, `rg`) gather facts. No TypeScript analyzer, no numeric scores,
|
|
@@ -39,7 +39,7 @@ in this corpus it is 76% one value (0493 measurement).
|
|
|
39
39
|
|
|
40
40
|
**Propose, never apply.** This skill performs no `spur feature move` and writes nothing under
|
|
41
41
|
`docs/features/**`. The only path from a structure proposal to a changed tree is
|
|
42
|
-
`/sp:dev-
|
|
42
|
+
`/sp:dev-feature-change` (dry-run → confirm → apply). Ranking runs are read-only; the sole exception is
|
|
43
43
|
`--task`, which after an **operator confirm** (interactive, or auto-accepted under `--auto`)
|
|
44
44
|
dispatches `/sp:dev-plan` and `/sp:dev-refineall` — commands that write `docs/tasks*/` through their
|
|
45
45
|
own gates. This skill still creates no tasks itself.
|
|
@@ -52,7 +52,7 @@ own gates. This skill still creates no tasks itself.
|
|
|
52
52
|
**Do NOT use for:**
|
|
53
53
|
|
|
54
54
|
- Advancing an already-chosen task or feature — that is `/sp:dev-next` (`sp:next-router`).
|
|
55
|
-
- Applying tree changes — that is `/sp:dev-
|
|
55
|
+
- Applying tree changes — that is `/sp:dev-feature-change` (feature F31).
|
|
56
56
|
- Task-level ordering inside a feature — next-router's TABLE A owns that.
|
|
57
57
|
|
|
58
58
|
## Protocol
|
|
@@ -106,7 +106,7 @@ Run the steps in order. Each step's depth lives in its reference; this file is t
|
|
|
106
106
|
- Ranking a feature whose actionability gate fails. Gate first, rank second.
|
|
107
107
|
- Emitting a numeric score (WSJF/RICE arithmetic) from absent value/effort estimates.
|
|
108
108
|
- Copying the B3 predicate into this skill. Cite it; read it at runtime.
|
|
109
|
-
- Any `spur feature move`, or writing proposals anywhere `docs/features/**` —
|
|
109
|
+
- Any `spur feature move`, or writing proposals anywhere `docs/features/**` — feature-change owns apply.
|
|
110
110
|
- Decomposing a feature here, or calling `spur task create` / `spur task batch-create` under `--task`.
|
|
111
111
|
Dispatch `/sp:dev-plan`; it owns decomposition and the batch-create schema gate. Equally:
|
|
112
112
|
dispatching under `--auto` without `--task` (there is no confirm to skip), auto-accepting a target
|
|
@@ -123,7 +123,7 @@ Run the steps in order. Each step's depth lives in its reference; this file is t
|
|
|
123
123
|
| [references/signal-derivation.md](references/signal-derivation.md) | Sync precondition, B3 runtime citation, per-signal derivation commands, degenerate-spread rejection |
|
|
124
124
|
| [references/ranking-rubric.md](references/ranking-rubric.md) | Tier definitions, tie-breaks, evidence-per-candidate output contract |
|
|
125
125
|
| [references/proposal-contract.md](references/proposal-contract.md) | D1–D4 defect set, evidence bar, mapping-schema conformance, silence |
|
|
126
|
-
| [references/handoff-routing.md](references/handoff-routing.md) |
|
|
126
|
+
| [references/handoff-routing.md](references/handoff-routing.md) | feature-change handoff, next-router seam, the `--task` tier→hop routing table and its confirm contract |
|
|
127
127
|
|
|
128
128
|
Grounding: tickets 0493 (measured signals), 0494 (reuse ledger), 0495 (defect contract) under
|
|
129
129
|
feature H12.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Handoff routing —
|
|
1
|
+
# Handoff routing — feature-change handoff, next-router seam, conditional dispatch
|
|
2
2
|
|
|
3
3
|
## The seam with `/sp:dev-next` (next-router)
|
|
4
4
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
- When the operator picks a winner from the ranked report, the printed handoff line is:
|
|
9
9
|
`/sp:dev-next <feature-id>`.
|
|
10
10
|
|
|
11
|
-
## The handoff to `/sp:dev-
|
|
11
|
+
## The handoff to `/sp:dev-feature-change` (feature F31)
|
|
12
12
|
|
|
13
13
|
Defect proposals follow the 0495 Artifact C boundary, traced end to end:
|
|
14
14
|
|
|
@@ -16,9 +16,9 @@ Defect proposals follow the 0495 Artifact C boundary, traced end to end:
|
|
|
16
16
|
| --- | --- | --- |
|
|
17
17
|
| 1. Detect + emit proposal rows | this skill | No |
|
|
18
18
|
| 2. Handoff | printed inline in the report (report reading of OQ1) | No |
|
|
19
|
-
| 3. `--dry-run` | `/sp:dev-
|
|
19
|
+
| 3. `--dry-run` | `/sp:dev-feature-change` | No |
|
|
20
20
|
| 4. Confirm | operator | — |
|
|
21
|
-
| 5. `--apply` (`spur feature move`) | `/sp:dev-
|
|
21
|
+
| 5. `--apply` (`spur feature move`) | `/sp:dev-feature-change` only | **Yes — sole writer** |
|
|
22
22
|
|
|
23
23
|
There is no path from this skill to a mutated tree that bypasses step 4. Proposal rows are printed
|
|
24
24
|
inline in the default report; writing them into `docs/plans/feature-tree-restructure-map.md` as new
|
|
@@ -83,7 +83,7 @@ inside dispatched children remain governed by their own contracts (`--approve-ta
|
|
|
83
83
|
### What `--task` does not change
|
|
84
84
|
|
|
85
85
|
The defect half is untouched: still no `spur feature move`, still nothing written under
|
|
86
|
-
`docs/features/**`, still `/sp:dev-
|
|
86
|
+
`docs/features/**`, still `/sp:dev-feature-change` as the sole applier of structure proposals. `--task`
|
|
87
87
|
adds one gated path to `docs/tasks*/`, through commands that own their own gates.
|
|
88
88
|
|
|
89
89
|
## Where outputs go
|
|
@@ -7,7 +7,10 @@ cannot be derived is reported as **unavailable**, never fabricated.
|
|
|
7
7
|
## §0 — Sync-first precondition (step zero)
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
spur
|
|
10
|
+
# Monorepo-safe spur resolution (0568 R6): SPUR_BIN env > monorepo-local CLI > PATH.
|
|
11
|
+
# Defined once here; §1+ reuse $SPUR_BIN — §0 runs first by construction.
|
|
12
|
+
SPUR_BIN="${SPUR_BIN:-$([ -f apps/cli/src/index.ts ] && echo 'bun apps/cli/src/index.ts' || echo spur)}"
|
|
13
|
+
$SPUR_BIN feature sync --all --dry-run --json
|
|
11
14
|
```
|
|
12
15
|
|
|
13
16
|
Feature `status` is manual bookkeeping and drifts (0493: 24 of 25 rankable features would change
|
|
@@ -34,7 +37,7 @@ renamed, the fallback key is its content: "frontier = open ∧ unblocked".)
|
|
|
34
37
|
Inputs per candidate feature:
|
|
35
38
|
|
|
36
39
|
```bash
|
|
37
|
-
|
|
40
|
+
$SPUR_BIN task list --feature <id> --json
|
|
38
41
|
```
|
|
39
42
|
|
|
40
43
|
`task list --feature` is **active-folder-only**: it enumerates tasks in the active task folder
|
|
@@ -52,9 +55,11 @@ is not authoritative — a frontier task may be archived outside it. Run the fal
|
|
|
52
55
|
the feature's row as an **anomaly hint** only: it may flag the feature without naming a WBS. The
|
|
53
56
|
sync reason is never treated as a WBS source — no WBS is ever inferred from sync prose.
|
|
54
57
|
2. Scan the whole corpus for linked tasks:
|
|
58
|
+
|
|
55
59
|
```bash
|
|
56
60
|
rg -l '^feature_id: "?<id>"?$' docs/tasks*/
|
|
57
61
|
```
|
|
62
|
+
|
|
58
63
|
Corpus ids are `[A-Z][0-9]+`-shaped, so `<id>` is regex-safe as-is; escape metacharacters if a
|
|
59
64
|
non-conforming id ever appears.
|
|
60
65
|
3. Parse the leading WBS from each matched basename; resolve every corpus-only WBS (not present in
|
|
@@ -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.
|