@gobing-ai/spur 0.3.42 → 0.3.43

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.
@@ -6,7 +6,7 @@
6
6
  },
7
7
  "plugins": [
8
8
  {
9
- "version": "0.3.42",
9
+ "version": "0.3.43",
10
10
  "name": "sp",
11
11
  "source": "./plugins/sp",
12
12
  "description": "Spur - my harness toolkits"
@@ -188,6 +188,11 @@ states:
188
188
  # a tree already dirty with another task's implementation is how 0485's diff
189
189
  # got swept into 0486's run. Corpus dirs are excluded: the pipeline writes
190
190
  # those itself.
191
+ # R1 (0511): task-corpus dirt gets its own advisory NOTE — docs/tasks* is
192
+ # excluded from the non-corpus warning, so pre-existing task-corpus edits are
193
+ # invisible at launch yet can be accidentally staged with the current task
194
+ # later. Advisory only (never a block): the pipeline legitimately updates
195
+ # task files, so corpus dirt is launch-time visibility, not a lifecycle guard.
191
196
  - kind: shell
192
197
  options:
193
198
  command: >-
@@ -196,6 +201,11 @@ states:
196
201
  echo "precheck: WARNING - working tree has uncommitted non-corpus changes; commit or stash before starting a new task:";
197
202
  echo "$DIRTY";
198
203
  fi;
204
+ CORPUS_DIRTY=$(git status --porcelain -- ':(glob)docs/tasks*/**' 2>/dev/null);
205
+ if [ -n "$CORPUS_DIRTY" ]; then
206
+ echo "precheck: NOTE - task corpus has uncommitted changes; review before staging with this task:";
207
+ echo "$CORPUS_DIRTY";
208
+ fi;
199
209
  exit 0
200
210
  - kind: note
201
211
  options:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/spur",
3
- "version": "0.3.42",
3
+ "version": "0.3.43",
4
4
  "description": "Spur CLI — local-first harness for mainstream coding agents: constraint checking, workflow orchestration, agent health, and history analytics. Bun-native; exposes the `spur` command.",
5
5
  "keywords": [
6
6
  "spur",
@@ -53,14 +53,14 @@
53
53
  },
54
54
  "devDependencies": {
55
55
  "@commander-js/extra-typings": "^14.0.0",
56
- "@gobing-ai/ts-db": "^0.4.24",
57
- "@gobing-ai/ts-ai-runner": "^0.4.24",
58
- "@gobing-ai/ts-dual-workflow-engine": "^0.4.24",
59
- "@gobing-ai/ts-infra": "^0.4.24",
60
- "@gobing-ai/ts-llm-jsonl-importer": "^0.4.24",
61
- "@gobing-ai/ts-rule-engine": "^0.4.24",
62
- "@gobing-ai/ts-runtime": "^0.4.24",
63
- "@gobing-ai/ts-utils": "^0.4.24",
56
+ "@gobing-ai/ts-db": "^0.4.27",
57
+ "@gobing-ai/ts-ai-runner": "^0.4.27",
58
+ "@gobing-ai/ts-dual-workflow-engine": "^0.4.27",
59
+ "@gobing-ai/ts-infra": "^0.4.27",
60
+ "@gobing-ai/ts-llm-jsonl-importer": "^0.4.27",
61
+ "@gobing-ai/ts-rule-engine": "^0.4.27",
62
+ "@gobing-ai/ts-runtime": "^0.4.27",
63
+ "@gobing-ai/ts-utils": "^0.4.27",
64
64
  "@types/bun": "1.3.14",
65
65
  "@types/figlet": "^1.7.0",
66
66
  "@types/node-notifier": "8.0.5",
@@ -14,10 +14,10 @@ Wraps the **sp:spur-dev** and **sp:code-implementation** skills.
14
14
  | --- | --- | --- |
15
15
  | `<wbs>` | Task WBS to run. | required |
16
16
  | `--mode` `<full\|implement>` | Full pipeline or single implement step. | full |
17
- | `--agent` `<inline\|auto\|name>` | Who runs the model-bearing stages. In an interactive session, omit/`inline` runs implement mode and full-mode stages in the host session. `auto` or a name keeps subprocess dispatch. | inline |
17
+ | `--agent` `<inline\|auto\|name>` | Who runs the model-bearing stages. In an interactive session, omit/`inline` keeps the controller in the host session (non-subprocess); eligible full-mode `agent.run` stages may dispatch once to a native subagent, with host fallback (task 0508). `auto` or a name keeps subprocess dispatch. | inline |
18
18
  | `--auto` | Skip objective HITL confirmations. | off |
19
19
  | `--next` | Chain-to-completion via the next-router. | off |
20
- | `--wrap` | Run the wrap hop after the main step. | off |
20
+ | `--wrap` | Run the wrap hop after the main step. The `--agent` selector is preserved into the `/sp:dev-wrap <wbs>` handoff when supplied; omission remains omission. The wrap hop is workflow-backed and reports its trigger-3 subprocess override. | off |
21
21
  | `--continue` | Resume an interrupted task from its checkpoint. | off |
22
22
 
23
23
  For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag-glossary.md).
@@ -37,7 +37,7 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
37
37
 
38
38
  **Flags:**
39
39
 
40
- - `--auto` | `--agent <inline|auto|name>` — Skip objective HITL confirmations (taste/irreversible gates still pause). `--agent` names who does the model-bearing work. Interactive omit/`inline` keeps both implement-only and full-mode model stages in this session. Full mode reads `task-pipeline.yaml` as the SSOT and interprets its actions/guards through the inline driver; it records `stage <id> executed inline in session <session-id>` in the run log. `auto` or a name is merged into `vars.agent` and `vars.implementAgent` and keeps the existing subprocess workflow. Headless `spur workflow run` / `spur agent run` is unchanged. See the [execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface).
40
+ - `--auto` | `--agent <inline|auto|name>` — Skip objective HITL confirmations (taste/irreversible gates still pause). `--agent` names who does the model-bearing work. Interactive omit/`inline` keeps the controller and implement-only stages in this session; full mode reads `task-pipeline.yaml` as the SSOT and interprets its actions/guards through the inline driver, where eligible `agent.run` stages may dispatch once to a native subagent and otherwise run in the host (task 0508). It records `stage <id> executed inline in session <session-id>` or `stage <id> executed via subagent <agent-id> (host session <session-id>)` in the run log. `auto` or a name is merged into `vars.agent` and `vars.implementAgent` and keeps the existing subprocess workflow. Headless `spur workflow run` / `spur agent run` is unchanged. See the [execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface).
41
41
 
42
42
  **Mode split (load-bearing — bug-742)**
43
43
 
@@ -17,9 +17,9 @@ Wraps the **sp:spur-dev** skill.
17
17
  | `--mode` `<sequential\|parallel>` | Batch execution order. | sequential |
18
18
  | `--keep-going` | Continue past per-task failures. | off |
19
19
  | `--auto` | Skip objective HITL gates. | off |
20
- | `--agent` `<inline\|auto\|name>` | Who runs each task's pipeline stages. Interactive sequential omit/`inline` uses the host-session driver; `auto`, a name, parallel mode, and headless invocation use subprocesses. | inline |
20
+ | `--agent` `<inline\|auto\|name>` | Who runs each task's pipeline stages. Interactive sequential omit/`inline` uses the host-session driver — host-controlled, eligible `agent.run` stages may use a native subagent (task 0508); `auto`, a name, parallel mode, and headless invocation use subprocesses. | inline |
21
21
  | `--json` | Emit structured JSON. | off |
22
- | `--wrap` | Run the wrap hop per task. | off |
22
+ | `--wrap` | Run the wrap hop per task. The `--agent` selector is preserved into each `/sp:dev-wrap <wbs>` handoff when supplied; omission remains omission. | off |
23
23
  | `--next` | Chain-to-completion via the next-router. | off |
24
24
  | `--continue` | Resume an interrupted batch. | off |
25
25
  | `--worktree` `[<name>]` | Run the batch in an isolated git worktree; FF-merge on success, retain on failure. Bare `--worktree` creates a fresh tree; `--worktree <name>` adopts an existing worktree by name/path/branch. | off |
@@ -33,7 +33,10 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
33
33
  ```
34
34
 
35
35
  Flags: `--tasks <selector>` (required — explicit WBS list, status pseudo-list, `feature:<id>`,
36
- or `ready`), `--feature <id>` (sugar for `feature:<id>`), `--mode`
36
+ or `ready`), `--feature <id>` (sugar for `feature:<id>`; when the effective selector is
37
+ feature-derived, `dev-runall` runs `spur feature check <id> --strict --json` **once** before
38
+ resolving tasks — a non-zero strict check aborts the batch with verdict `aborted` and the
39
+ structured findings, before any task pipeline action, task 0510 R2), `--mode`
37
40
  `<sequential|parallel>` (default `sequential`; `parallel` fans out a proven-independent subset —
38
41
  see `execution-batch.md` § Parallel Execution), `--keep-going`
39
42
  (batch failure policy — skip a failed task's in-batch dependents, continue independents; default
@@ -75,6 +78,6 @@ full distinction.
75
78
 
76
79
  ## Implementation
77
80
 
78
- - Apply the [inline-default execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface). Interactive sequential omit/`inline` keeps the orchestrator and each task's model stages in the host session through the [inline pipeline driver](../skills/spur-dev/references/inline-pipeline-driver.md). `--agent auto`, a name, or parallel mode retains the isolated per-task workflow boundary.
81
+ - Apply the [inline-default execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface). Interactive sequential omit/`inline` keeps the orchestrator in the host session through the [inline pipeline driver](../skills/spur-dev/references/inline-pipeline-driver.md); eligible `agent.run` stages may dispatch once to a native subagent with host fallback (task 0508). `--agent auto`, a name, or parallel mode retains the isolated per-task workflow boundary.
79
82
  - Interactive sequential omit/inline: `Skill(skill="sp:spur-dev", args="runall-inline $ARGUMENTS")`.
80
83
  - Explicit executor or parallel mode: `Skill(skill="sp:spur-dev", args="runall $ARGUMENTS")` → `sp:super-planner` agent.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Wrap up a single completed task — learnings, metrics, doc-sync, optional feature transition and branch cleanup
3
- argument-hint: "<wbs> [--auto] [--merge] [--dry-run]"
3
+ argument-hint: "<wbs> [--agent <inline|auto|name>] [--auto] [--merge] [--dry-run]"
4
4
  allowed-tools: ["Bash", "Read", "AskUserQuestion"]
5
5
  ---
6
6
 
@@ -13,6 +13,7 @@ Wraps the **wrapup-pipeline.yaml** workflow.
13
13
  | Flag | Description | Default |
14
14
  | --- | --- | --- |
15
15
  | `<wbs>` | Task WBS to wrap. | required |
16
+ | `--agent` `<inline\|auto\|name>` | Who runs the wrap's model-bearing steps. Wrap is workflow-backed: omit/`inline` resolves to `agent.default` (objective trigger 3 — durable auditable run record required); `auto` tier-resolves an executor; a name pins that executor into `vars.agent`. | agent.default |
16
17
  | `--auto` | Skip objective HITL gates. | off |
17
18
  | `--merge` | Merge the wrap branch. | off |
18
19
  | `--dry-run` | Render the wrap without writing. | off |
@@ -21,10 +22,27 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
21
22
 
22
23
  ## Usage
23
24
 
24
- /sp:dev-wrap <wbs> [--auto] [--merge] [--dry-run]
25
+ /sp:dev-wrap <wbs> [--agent <inline|auto|name>] [--auto] [--merge] [--dry-run]
25
26
 
26
27
  ## Implementation
27
28
 
29
+ - Apply the [inline-default execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface).
30
+ - Wrap stays **workflow-backed** — `spur workflow run .spur/workflows/wrapup-pipeline.yaml` is the only implementation; there is no inline wrap driver.
31
+ - Resolve the executor **before** launching the workflow:
32
+ - `--agent <name>` → pass the name unchanged into `vars.agent`.
33
+ - `--agent auto` → tier-resolve a concrete executor first, then merge it into `vars.agent`.
34
+ - omit/`--agent inline` → resolve to `agent.default` (the documented headless resolution of `inline`).
35
+ - Emit a pre-dispatch notice naming the override before `spur workflow run`, exactly:
36
+ `execution surface: subprocess`, `reason: trigger 3 — durable auditable run record required`, `requested agent: inline|auto|<name>`, `executor: agent.default|<resolved-name>`.
37
+ - The wrap workflow still creates its durable run record (task_run_links / trace) — the notice reports the override, it does not change the workflow.
38
+
28
39
  ```bash
29
- spur workflow run .spur/workflows/wrapup-pipeline.yaml --vars '{"tasks":"[\"<wbs>\"]","profile":"interactive|auto","merge":"true|false"}' [--dry-run]
40
+ AGENT=… # resolved above: agent.default for inline/omitted, tier-resolved for auto, unchanged for <name>
41
+ echo "execution surface: subprocess; reason: trigger 3 — durable auditable run record required; requested agent: <inline|auto|name>; executor: $AGENT"
42
+ VARS=$(jq -nc --arg tasks "[\"$WBS\"]" --arg agent "$AGENT" --arg profile "$PROFILE" --arg merge "$MERGE" \
43
+ '{tasks:$tasks, agent:$agent, profile:$profile, merge:$merge}')
44
+ spur workflow run .spur/workflows/wrapup-pipeline.yaml --vars "$VARS" [--dry-run]
30
45
  ```
46
+
47
+ The executor resolution is described in the bullets above; the snippet's `AGENT` variable carries
48
+ the resolved name (`agent.default` for omit/`inline`).
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Wrap up a batch of completed tasks — learnings, metrics, doc-sync, feature transition, optional branch cleanup
3
- argument-hint: "[--since <iso-date>] [--feature <id>] [--status <s>] [--auto] [--merge] [--dry-run]"
3
+ argument-hint: "[--since <iso-date>] [--feature <id>] [--status <s>] [--agent <inline|auto|name>] [--auto] [--merge] [--dry-run]"
4
4
  allowed-tools: ["Bash", "Read", "AskUserQuestion"]
5
5
  ---
6
6
 
@@ -15,6 +15,7 @@ Wraps the **wrapup-pipeline.yaml** workflow.
15
15
  | `--since` `<iso-date>` | Wrap tasks completed since a date. | configured |
16
16
  | `--feature` `<id>` | Wrap tasks in a feature. | omitted |
17
17
  | `--status` `<s>` | Only wrap tasks in a status. | done |
18
+ | `--agent` `<inline\|auto\|name>` | Who runs the wrap's model-bearing steps. Wrap is workflow-backed: omit/`inline` resolves to `agent.default` (objective trigger 3 — durable auditable run record required); `auto` tier-resolves an executor; a name pins that executor into `vars.agent`. | agent.default |
18
19
  | `--auto` | Skip objective HITL gates. | off |
19
20
  | `--merge` | Merge wrap branches. | off |
20
21
  | `--dry-run` | Render wraps without writing. | off |
@@ -23,11 +24,28 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
23
24
 
24
25
  ## Usage
25
26
 
26
- /sp:dev-wrapall [--since <iso-date>] [--feature <id>] [--status <s>] [--auto] [--merge] [--dry-run]
27
+ /sp:dev-wrapall [--since <iso-date>] [--feature <id>] [--status <s>] [--agent <inline|auto|name>] [--auto] [--merge] [--dry-run]
27
28
 
28
29
  ## Implementation
29
30
 
31
+ - Apply the [inline-default execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface).
32
+ - Wrap stays **workflow-backed** — `spur workflow run .spur/workflows/wrapup-pipeline.yaml` is the only implementation; there is no inline wrap driver.
33
+ - Resolve the executor **before** launching the workflow:
34
+ - `--agent <name>` → pass the name unchanged into `vars.agent`.
35
+ - `--agent auto` → tier-resolve a concrete executor first, then merge it into `vars.agent`.
36
+ - omit/`--agent inline` → resolve to `agent.default` (the documented headless resolution of `inline`).
37
+ - Emit a pre-dispatch notice naming the override before `spur workflow run`, exactly:
38
+ `execution surface: subprocess`, `reason: trigger 3 — durable auditable run record required`, `requested agent: inline|auto|<name>`, `executor: agent.default|<resolved-name>`.
39
+ - The wrap workflow still creates its durable run record — the notice reports the override, it does not change the workflow.
40
+
30
41
  ```bash
31
- spur workflow run .spur/workflows/wrapup-pipeline.yaml --vars '{"tasks":"<json-encoded-wbs-list>","feature":"<id|>","profile":"interactive|auto","merge":"true|false"}' [--dry-run]
42
+ AGENT=… # resolved above: agent.default for inline/omitted, tier-resolved for auto, unchanged for <name>
43
+ echo "execution surface: subprocess; reason: trigger 3 — durable auditable run record required; requested agent: <inline|auto|name>; executor: $AGENT"
44
+ VARS=$(jq -nc --arg tasks "$TASKS" --arg feature "$FEATURE" --arg agent "$AGENT" --arg profile "$PROFILE" --arg merge "$MERGE" \
45
+ '{tasks:$tasks, feature:$feature, agent:$agent, profile:$profile, merge:$merge}')
46
+ spur workflow run .spur/workflows/wrapup-pipeline.yaml --vars "$VARS" [--dry-run]
32
47
  ```
33
48
 
49
+ The executor resolution is described in the bullets above; the snippet's `AGENT` variable carries
50
+ the resolved name (`agent.default` for omit/`inline`).
51
+
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sp",
3
- "version": "0.3.42",
3
+ "version": "0.3.43",
4
4
  "description": "Spur — a local-first harness engineering toolkit that wraps mainstream coding agents with constraint checking, workflow orchestration, and history analytics.",
5
5
  "extensions": {
6
6
  "pi": ["./hooks/pi/guard-extension.ts"]
@@ -92,6 +92,33 @@ only burns wall clock and context budget.
92
92
  - If a targeted probe reveals a failure you cannot fix within implement scope, note it in
93
93
  `## Solution` and let the `test` hop's fixall handle it — do not pre-empt the gate.
94
94
 
95
+ ## Changed-path targeted checks (dependency-aware verification, task 0510 R3)
96
+
97
+ "Run the narrow test first" needs a second half: *which* narrow tests, when a change to a shared
98
+ surface can break a downstream consumer. The matrix below is dependency-aware — domain → app →
99
+ CLI — so a shared change verifies its consumers without recreating the full project check inside
100
+ implement. **It augments narrow behavior tests; it never authorizes `bun run spur-check`,
101
+ `bun run test`, or another full project check inside implement** — the pipeline's `test` hop owns
102
+ that single full gate.
103
+
104
+ | Changed surface | Required targeted tests | Required typechecks |
105
+ | --- | --- | --- |
106
+ | `packages/domain/src/**` public type/query | affected domain test; affected app service test; affected CLI command test | `@gobing-ai/spur-domain`, `@gobing-ai/spur-app`, `@gobing-ai/spur` |
107
+ | `packages/app/src/**` public service/type | affected app test; affected CLI command test | `@gobing-ai/spur-app`, `@gobing-ai/spur` |
108
+ | `apps/cli/src/**` | affected `apps/cli/tests/**` file | `@gobing-ai/spur` |
109
+ | shared plugin flag/command/reference | affected plugin structure/contract test; add `flag-contract-parity.test.ts` **only** when the shared flag surface changes | no package typecheck unless TypeScript also changed |
110
+
111
+ - Apply **only the matching rows** for the surfaces actually changed; a multi-surface change applies
112
+ the union.
113
+ - Workspace typechecks run as `bun run --filter <workspace> typecheck` for each listed workspace
114
+ (monorepo; installed/other projects substitute their package-manager surface).
115
+ - The shared plugin row is deliberately conditional: a pure reference/prose change needs only the
116
+ affected structure test; `flag-contract-parity.test.ts` is added only when the shared flag surface
117
+ (a flag the plugin layer consumes) actually changes, so an unconditional parity suite does not
118
+ creep into every plugin edit.
119
+ - Run the applicable rows, then stop: the single full project check belongs to the pipeline's
120
+ `test` hop (`task-pipeline.yaml` `${vars.qualityGateCmd}`).
121
+
95
122
  ## Behavior
96
123
 
97
124
  This skill behaves as a **technique**: given a task (read its Background, AC, Design, Plan), it maps
@@ -169,9 +169,27 @@ count identical commands for loop detection.
169
169
  Produce per-session metrics (duration, tools, compactions, test runs, spur calls, guard failures,
170
170
  key finding). Aggregate totals across sessions.
171
171
 
172
- When `--use-history` is set, optionally run `spur history import --source <mapped> …` and
173
- `spur history analyze` for token/cost aggregates. Do **not** treat history ETL as a substitute
174
- for raw tool-loop evidence.
172
+ When `--use-history` is set, the **selected-file history bridge** supplies ETL aggregates for the
173
+ frozen session set (task 0507 R3):
174
+
175
+ 1. **Freeze Phase 1's selected OMP JSONL files once** — the same inventory the raw analysis reads.
176
+ Discovery roots: the normal OMP session root (`~/.omp/agent/sessions/`) **and**
177
+ `.spur/run/<run-id>/agent-sessions/<omp-executor>/*.jsonl` for workflow subprocess sessions.
178
+ Never import a broad `.spur/run` scan and never run a full/source-root reconciliation here.
179
+ 2. **Import each frozen file once, through the source-local CLI**, with single-file `force-file`
180
+ mode:
181
+ `bun run apps/cli/src/index.ts history import --source omp --file <absolute-file> --mode force-file --json`.
182
+ The importer derives the session key from the filename; use the same stem for analysis.
183
+ 3. **Analyze scoped to that key**: `history analyze --session <filename-stem> --json`.
184
+ 4. Use the artifact for the aggregates ETL can represent — tokens, cost, messages, tool calls,
185
+ loops, and assistant response duration. **Continue parsing the same raw files** for command text,
186
+ compactions, test/guard retries, tool execution duration/status/errors, and every other signal
187
+ the ETL does not carry.
188
+
189
+ ETL supplies normalized aggregates; it is **not** a substitute for raw tool-loop evidence. If an
190
+ import fails or the DB is empty, continue with raw logs and note that cost data is unavailable.
191
+ Before any ad-hoc verification SQL against `history_*` tables, follow the schema-first rule in
192
+ [references/session-formats.md](references/session-formats.md) — inspect the live schema once.
175
193
 
176
194
  ### Phase 3: IDENTIFY — Root Cause Ranking
177
195
 
@@ -104,6 +104,36 @@ For issue-finding:
104
104
  Import does not invent bottleneck categories. If import fails or the DB is empty, continue with
105
105
  raw logs and note that cost data is unavailable.
106
106
 
107
+ **Schema-first rule (task 0506 R3):** history tables are owned by
108
+ `@gobing-ai/ts-llm-jsonl-importer` and can change between versions — never copy column lists
109
+ into this skill. Before any ad-hoc verification SQL that references importer-owned `history_*`
110
+ tables, run **one** schema-introspection query for every table you need and compose the data
111
+ queries from that result:
112
+
113
+ ```bash
114
+ # one introspection pass, then write data queries against what it reports
115
+ 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
+ ```
118
+
119
+ If a column you expected is absent, trust the live schema — do not guess. The importer's
120
+ `HISTORY_IMPORT_SCHEMA_SQL` is the authority; this skill holds no duplicate column contract.
121
+
122
+ **Selected-file bridge (task 0507 R3):** `--use-history` imports the frozen Phase-1 file set one
123
+ file at a time — never a root scan, never a full reconciliation. Ambient discovery covers the
124
+ normal OMP root (`~/.omp/agent/sessions/`) **and** workflow subprocess sessions under
125
+ `.spur/run/<run-id>/agent-sessions/<omp-executor>/*.jsonl` (same `type: "message"` envelope). For
126
+ each file, the session key is the JSONL filename stem (importer `sessionIdFromContext`); import and
127
+ analyze per key:
128
+
129
+ ```bash
130
+ bun run apps/cli/src/index.ts history import --source omp --file <absolute-file> --mode force-file --json
131
+ bun run apps/cli/src/index.ts history analyze --session <filename-stem> --json
132
+ ```
133
+
134
+ ETL owns token/cost/message/tool/loop/assistant-duration aggregates; raw JSONL stays authoritative
135
+ for command text, compactions, test/guard retries, and tool execution duration/status/errors.
136
+
107
137
  ## Edge cases
108
138
 
109
139
  | Scenario | Handling |
@@ -65,7 +65,7 @@ Statuses from `TASK_STATUSES`: backlog | todo | wip | testing | blocked | done |
65
65
  | A5 | `status == wip` (no usable checkpoint) | `task.show.status` | `/sp:dev-run <wbs> --mode implement --auto --next` | yes | **yes** → verify | Completes implement step then chain |
66
66
  | A6 | `status == testing` | `task.show.status` | `/sp:dev-verify <wbs> --auto --next` | yes | **yes** — verify `--next` → done (FSM + provenance guards) | On PARTIAL/FAIL → stop review-pending (do not force done) |
67
67
  | A7 | `status == blocked` | `task.show` + Notes/History for blocker text | `/sp:dev-handover "<blocker summary from Notes or status>"` | no | no | **STOP** after handover doc; human unblocks |
68
- | A8 | `status == done` | `task.show.status` | `/sp:dev-wrap <wbs>` | no | **no** (wrap's `--merge` is irreversible HITL; never auto) | Operator may re-invoke with `--merge` explicitly later |
68
+ | A8 | `status == done` | `task.show.status` | `/sp:dev-wrap <wbs>` (`--agent <value>` preserved when the originating command supplied it; omission remains omission) | no | **no** (wrap's `--merge` is irreversible HITL; never auto) | Operator may re-invoke with `--merge` explicitly later |
69
69
  | A9 | `status == cancelled` | `task.show.status` | *(none)* | no | no | **STOP** — no-op; print "cancelled — nothing to advance" |
70
70
 
71
71
  **Priority when multiple TABLE A rows could match:** lowest row number wins (A1–A9 are mutually
@@ -83,7 +83,7 @@ When input is a feature id:
83
83
  | B3 | Feature has ≥1 frontier task | task list under feature | **Recurse TABLE A** on chosen task | per A | per A | Frontier = open (`backlog`\|`todo`\|`wip`\|`testing`\|`blocked`), unblocked (all `dependencies[]` done), prefer WBS-ascending among `todo` then `backlog` then `wip` then `testing` then `blocked` |
84
84
  | B4 | No frontier tasks AND `feature.status == backlog` AND AC placeholder/invalid | `feature check` / AC body | `/sp:dev-plan` continuation is not WBS-shaped — **STOP** with: run `/sp:dev-plan --feature <id>` or fix AC then `spur feature check <id>` | no | no | Planning-half entry needs a description; do not invent idea text |
85
85
  | B5 | No frontier tasks AND feature has valid AC but zero tasks | feature + empty task roster | **STOP** with: `/sp:dev-plan --feature <id>` (decompose/batch-create) | no | no | Avoid auto-running plan without operator description confirmation in v1 |
86
- | B6 | No frontier tasks AND all child tasks `done` AND feature in `active`\|`verifying` | task list all done | `/sp:dev-wrapall --feature <id>` | no | no | Advances feature via wrapall guards; `--merge` never auto |
86
+ | B6 | No frontier tasks AND all child tasks `done` AND feature in `active`\|`verifying` | task list all done | `/sp:dev-wrapall --feature <id>` (`--agent <value>` preserved when the originating command supplied it; omission remains omission) | no | no | Advances feature via wrapall guards; `--merge` never auto |
87
87
  | B7 | No frontier tasks AND mixed cancelled/done only | statuses | **STOP** — print summary; suggest feature status update manually | no | no | |
88
88
  | B8 | `feature.status == blocked` | feature status | **STOP** — print feature blocked; do not pick tasks | no | no | |
89
89
 
@@ -89,6 +89,15 @@ non-sandboxed shell, or a workspace that owns the storage path). The upstream fi
89
89
  pi-coding-agent's storage-path resolution; it is out of scope here and recorded as motivating
90
90
  evidence only.
91
91
 
92
+ ## Composition with the inline pipeline driver (task 0508)
93
+
94
+ The interactive inline driver (`cross-cutting.md` § Inline-default execution surface) applies this
95
+ reference's default — native subagent first — to sequential `task-pipeline.yaml` `agent.run`
96
+ stages. Eligibility there is the same observable test (pure-slash action, non-interactive state,
97
+ native subagent with shared-worktree capability); the inline driver remains the authority for
98
+ provenance, artifact validation, and no-replay guarantees. This reference stays the authority for
99
+ the native-subagent versus `spur agent run` choice everywhere else.
100
+
92
101
  ## See also
93
102
 
94
103
  - **`parallel-execution`** SKILL.md - the dispatch disciplines this rule sits beside.
@@ -68,7 +68,9 @@ See [tasks/verbs.md](tasks/verbs.md) for the variant detail.
68
68
  exit code `3` and names the existing WBS — reuse it.
69
69
  - **`--dedupe-within <seconds>`** overrides the default window (e.g. `--dedupe-within 60`).
70
70
  - **`--allow-duplicate-name`** disables the guard entirely (explicit override).
71
- - Tasks created without `--feature` are never guarded (no collision scope).
71
+ - The guard applies to every create: feature-scoped tasks collide within the same
72
+ feature; unscoped tasks (no `--feature`) collide with other unscoped tasks of the
73
+ same title (their own collision scope).
72
74
  - With `--json`, a duplicate emits `{ ok: false, error: { code, message, existingWbs,
73
75
  existingName, attemptedName } }` for deterministic reuse.
74
76
 
@@ -41,7 +41,7 @@ in scripts and audit output but does not change the default.
41
41
 
42
42
  | Value | Who does the work | Derived surface |
43
43
  |---|---|---|
44
- | `inline` (default when omitted) | Whoever is running this session (interactive) or `agent.default` (headless) | Interactive: inline (host session); headless: subprocess of `agent.default` |
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
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 |
46
46
  | `<name>` (coding agent or configured executor) | That executor | Inline when it resolves to the current session's agent; subprocess otherwise |
47
47
 
@@ -105,11 +105,18 @@ meaningless.
105
105
  **Interactive task pipelines invert control into the host session (ADR-047 amendment).**
106
106
  `dev-run --mode full` and sequential `dev-runall` with omit/`inline` interpret the existing
107
107
  `task-pipeline.yaml` in the host session; they do not launch `spur workflow run` and never redirect
108
- silently to `agent.default`. Each inline model stage appends
109
- `stage <id> executed inline in session <session-id>` to its run log. `dev-plan` remains a workflow
110
- subprocess, as do `dev-run`/`dev-runall` with `--agent auto` or a name, parallel batches, and every
111
- headless `spur workflow run` / `spur agent run`. `dev-run --mode implement` continues to run its
112
- single competency in-session under omit/`inline`.
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
114
+ confirmation actions, `pause: true`, and approve/taste/ask decisions stay host-owned. Each inline
115
+ model stage appends `stage <id> executed inline in session <session-id>` to its run log; a
116
+ subagent-dispatched stage appends `stage <id> executed via subagent <agent-id> (host session
117
+ <session-id>)` instead. `dev-plan` remains a workflow subprocess, as do `dev-run`/`dev-runall` with
118
+ `--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`.
113
120
 
114
121
  ### Executor precedence chain (R7)
115
122
 
@@ -429,6 +436,15 @@ iterating one task).
429
436
  2. Loop on that narrow target until green.
430
437
  3. **Then** run the single full `spur-check` (or `bun run check`) as the final gate.
431
438
 
439
+ **Dependency-aware selection (task 0510 R3).** "Narrow" is not "whatever file I touched" — a change
440
+ to a shared surface must also verify its downstream consumers. Pick the targeted tests and
441
+ typechecks from the **changed-path matrix** in `code-implementation/SKILL.md` (§ Changed-path
442
+ targeted checks): domain changes run affected domain + app/CLI consumer tests and
443
+ domain/app/CLI typechecks; app changes run affected app + CLI tests and app/CLI typechecks; CLI
444
+ changes run affected CLI tests and the CLI typecheck; shared plugin flag/command contract changes
445
+ run their focused structure/parity tests. Run only the applicable rows, then stop — the full
446
+ project check is still the pipeline's single final gate, never a per-iteration re-run.
447
+
432
448
  Do not re-run the full suite per iteration, and do not `spur-check` before you have a green narrow
433
449
  target. **Target:** full `spur-check` runs ≤2 per task (one during iteration, one final) instead of
434
450
  4 across a chain.
@@ -77,8 +77,8 @@ each would be scope creep for one-liner procedures.
77
77
  | 12 | brainstorm | `dev-brainstorm` | `Skill()` | `sp:brainstorm` (`dev-brainstorm`) | `<topic> [--depth <basic\|detailed\|comprehensive>] [--options <n>] [--agent <inline\|auto\|name>] [--skip-discovery] [--wayfind] [--task [<feature-id>]] [--feature [<parent-id>]] [--next]` |
78
78
  | 13 | runall | `dev-runall` | `Skill()` → agent | `sp:spur-dev` (`runall`) → `sp:super-planner` | `--tasks <selector> [--feature <id>] [--mode <sequential\|parallel>] [--keep-going] [--auto] [--agent <inline\|auto\|name>] [--json] [--wrap] [--next] [--continue] [--worktree [<name>]]` |
79
79
  | 13a | parallel | `dev-parallel` | `Skill()` | `sp:parallel-execution` | `--tasks <selector> [--feature <id>] [--mode <fan-out\|review-panel\|investigation>] [--agent <inline\|auto\|name>] [--json]` |
80
- | 14 | wrap | `dev-wrap` | `Skill()` | `spur workflow run` (wrapup-pipeline) | `<wbs> [--auto] [--merge] [--dry-run]` |
81
- | 15 | wrapall | `dev-wrapall` | `Skill()` | `spur workflow run` (wrapup-pipeline) | `[--since <iso>] [--feature <id>] [--status <s>] [--auto] [--merge] [--dry-run]` |
80
+ | 14 | wrap | `dev-wrap` | `Skill()` | `spur workflow run` (wrapup-pipeline) | `<wbs> [--agent <inline\|auto\|name>] [--auto] [--merge] [--dry-run]` |
81
+ | 15 | wrapall | `dev-wrapall` | `Skill()` | `spur workflow run` (wrapup-pipeline) | `[--since <iso>] [--feature <id>] [--status <s>] [--agent <inline\|auto\|name>] [--auto] [--merge] [--dry-run]` |
82
82
  | 16 | idea | `dev-idea` | `Skill()` | `spur workflow run` (idea-pipeline) | `"<idea>" [--auto] [--skip-design] [--approve-taste]` |
83
83
 
84
84
  ## Skill-backed operations
@@ -137,10 +137,10 @@ must not be changed without updating the backing skill.
137
137
  ### 4. run
138
138
 
139
139
  - **Purpose:** Run a task through the execution pipeline (full) or execute a single pipeline step (implement).
140
- - **Inputs:** `<wbs>` (required). `--mode <full|implement>` selects the execution mode. `implement` invokes `sp:code-implementation` inline by default. Interactive `full` with omit/`--agent inline` reads `task-pipeline.yaml` and drives its actions/guards in the host session; `--agent auto`, a name, or headless invocation launches the workflow subprocess. `--agent <inline|auto|name>` selects the execution surface (see [SSOT](cross-cutting.md#inline-default-execution-surface)). `--auto` skips the HITL approve gate / confirmations and propagates down the `--next` chain. `--next` controls chaining only and never changes the mode; a pipeline implement stage must invoke `/sp:dev-run <wbs> --mode implement`. On implement success with `--next`, transition `todo → wip → testing` through the FSM (guards honored — no `--no-lifecycle`) + chain to `/sp:dev-verify <wbs> --auto --next`. On a guard failure, stop as review-pending. **Partial-deliverable rule:** if the task ships only part of its requirements (e.g. an R1/R2 split with the rest in a follow-up task), the `## Solution` section must state that explicitly and the verify verdict will record the scope.
140
+ - **Inputs:** `<wbs>` (required). `--mode <full|implement>` selects the execution mode. `implement` invokes `sp:code-implementation` inline by default. Interactive `full` with omit/`--agent inline` reads `task-pipeline.yaml` and drives its actions/guards in the host session — host-controlled and non-subprocess, with eligible `agent.run` stages dispatching once to a native subagent and host fallback (task 0508); `--agent auto`, a name, or headless invocation launches the workflow subprocess. `--agent <inline|auto|name>` selects the execution surface (see [SSOT](cross-cutting.md#inline-default-execution-surface)). `--auto` skips the HITL approve gate / confirmations and propagates down the `--next` chain. `--next` controls chaining only and never changes the mode; a pipeline implement stage must invoke `/sp:dev-run <wbs> --mode implement`. On implement success with `--next`, transition `todo → wip → testing` through the FSM (guards honored — no `--no-lifecycle`) + chain to `/sp:dev-verify <wbs> --auto --next`. On a guard failure, stop as review-pending. **Partial-deliverable rule:** if the task ships only part of its requirements (e.g. an R1/R2 split with the rest in a follow-up task), the `## Solution` section must state that explicitly and the verify verdict will record the scope. `--wrap` hands off to `/sp:dev-wrap <wbs>` after the main step; the `--agent` selector is preserved into that handoff when supplied (omission remains omission), and the wrap hop reports its own trigger-3 subprocess override per the wrap contract.
141
141
  - **Backing:** `sp:spur-dev` skill — `run` operation for the full pipeline (the spine drives it); `sp:code-implementation` competency skill for the implement step (the spine dispatches to it).
142
142
  - **Modes:**
143
- - **`full`** (default): Drive the full pipeline — precheck → implement → test → review → approve(HITL) → verify → record → done. Interactive omit/inline uses [inline-pipeline-driver.md](inline-pipeline-driver.md); explicit/headless executor selection invokes `spur workflow run .spur/workflows/task-pipeline.yaml --vars '{"wbs":"<wbs>"}'` (with `profile: auto` when `--auto`). Both monitor/surface HITL and preserve the YAML gates. `--next` never changes this mode.
143
+ - **`full`** (default): Drive the full pipeline — precheck → implement → test → review → approve(HITL) → verify → record → done. Interactive omit/inline uses [inline-pipeline-driver.md](inline-pipeline-driver.md) (host-controlled; eligible stages may use a native subagent); explicit/headless executor selection invokes `spur workflow run .spur/workflows/task-pipeline.yaml --vars '{"wbs":"<wbs>"}'` (with `profile: auto` when `--auto`). Both monitor/surface HITL and preserve the YAML gates. `--next` never changes this mode.
144
144
  - **`implement`** (explicit `--mode implement` only): Execute only the implement step. Read the task's `## Requirements` / `## Design` / `## Plan`, write the code that satisfies them, author the `## Solution` change-map section (file:line + what/why per changed file) via `spur task update <wbs> --section Solution --from-file`. This is the implement step the pipeline calls — it is NOT the pipeline driver. With `--next`: on success, transition `todo → wip → testing` through the FSM (guards honored — no `--no-lifecycle`) + chain to `/sp:dev-verify <wbs> --auto --next`; on a guard failure, stop as review-pending. **Partial-deliverable rule:** if the task ships only part of its requirements (e.g. an R1/R2 split with the rest in a follow-up task), the `## Solution` and `## Review` sections MUST carry a `⚠️ PARTIAL` marker naming the deferred part and the follow-up WBS — see `plugins/sp/commands/dev-run.md` → "Section ownership".
145
145
  - **Delegation:** `Skill(skill="sp:spur-dev", args="run-inline $ARGUMENTS")` for interactive full omit/inline; `Skill(skill="sp:spur-dev", args="run $ARGUMENTS")` for explicit/headless full mode; `Skill(skill="sp:code-implementation", args="$ARGUMENTS")` for implement mode.
146
146
 
@@ -288,7 +288,7 @@ must not be changed without updating the backing skill.
288
288
  ### 13. runall
289
289
 
290
290
  - **Purpose:** Run a batch of tasks through their pipelines in dependency-correct order — resolve a set, topo-sort, run each via `task-pipeline.yaml`, inspect verdicts, apply the failure policy, emit a batch report.
291
- - **Inputs:** `--tasks <selector>` (required — explicit WBS list, status pseudo-list, `feature:<id>`, or `ready`). `--mode <sequential|parallel>` (default `sequential`; `parallel` fans out a proven-independent subset per `execution-batch.md` § Parallel Execution). `--keep-going` skips a failed task's in-batch dependents and continues independents (default halts on first failure). `--auto` sets `profile=auto` on each per-task run (skips the HITL approve gate). The orchestrator loop itself continues in this session; each full per-task workflow's `agent.run` stages always dispatch a subprocess. `--agent <inline|auto|name>` pins the executor for the per-task stages (see [SSOT](cross-cutting.md#inline-default-execution-surface)); the value crosses into per-task `vars.agent`, not the orchestrator. `--json` emits the report as JSON. `--wrap` triggers `wrapup-pipeline.yaml` after the batch completes, `--next` chains each task to terminal status then runs the wrap hop **once for the batch**, `--continue` resumes from checkpoint.
291
+ - **Inputs:** `--tasks <selector>` (required — explicit WBS list, status pseudo-list, `feature:<id>`, or `ready`). `--mode <sequential|parallel>` (default `sequential`; `parallel` fans out a proven-independent subset per `execution-batch.md` § Parallel Execution). `--keep-going` skips a failed task's in-batch dependents and continues independents (default halts on first failure). `--auto` sets `profile=auto` on each per-task run (skips the HITL approve gate). `--feature <id>` is sugar for `--tasks feature:<id>`; when the effective selector is feature-derived, the batch runs `spur feature check <id> --strict --json` **once** before task resolution — a non-zero strict check aborts with verdict `aborted`, zero attempted tasks, and the structured findings (task 0510 R2). Explicit WBS/status/`ready` selectors add no feature check. The orchestrator loop itself continues in this session; interactive sequential omit/`inline` uses the host driver — host-controlled with eligible `agent.run` stages dispatching once to a native subagent and host fallback (task 0508) — while `--agent auto`/a name, parallel mode, and headless invocation keep the isolated per-task workflow subprocess boundary. `--agent <inline|auto|name>` pins the executor for the per-task stages (see [SSOT](cross-cutting.md#inline-default-execution-surface)); the value crosses into per-task `vars.agent`, not the orchestrator. `--json` emits the report as JSON. `--wrap` triggers `wrapup-pipeline.yaml` after the batch completes, `--next` chains each task to terminal status then runs the wrap hop **once for the batch**, `--continue` resumes from checkpoint.
292
292
  - **Three orthogonal axes (do not confuse):** `--keep-going` = batch failure policy (halt vs skip dependents); `--continue` = resume from checkpoint (pick up an interrupted batch); `--next` = per-task lifecycle chaining (advance status on a verdict — `dev-verify`/`dev-verifyall` only). `routing-table.md` offers `--continue` and `--next` as competing options for the same situation only when the batch was interrupted mid-run; otherwise they address different problems.
293
293
  - **Backing:** `sp:spur-dev` skill, `runall` operation → delegates the driver loop to the **`sp:super-planner`** agent (the batch orchestrator).
294
294
  - **Behavior:** The orchestrator reads [execution-batch.md](execution-batch.md) and drives: resolve selector → freeze set → topo-sort by `dependencies[]` (Kahn, WBS-ascending tie-break; cycle aborts) → resolve out-of-set deps by status (done → allow, else → block subtree) → run each task via `spur workflow run task-pipeline.yaml --async` + `spur workflow trace` polling → inspect terminal state + `.spur/run/<wbs>-verdict.json` → stop-the-batch default or `--keep-going` subtree skip → emit batch report. Per-task pipeline is invoked **verbatim** — no new FSM, no step edits. `--auto`/`--agent` are the only flags that cross the orchestrator→pipeline boundary (both into per-task `--vars`).
@@ -297,14 +297,14 @@ must not be changed without updating the backing skill.
297
297
  ### 14. wrap
298
298
 
299
299
  - **Purpose:** Wrap up a single completed task — capture learnings, record metrics, sync docs, and optionally advance the feature / clean up the branch.
300
- - **Inputs:** `<wbs>` (required, positional). `--auto` skips objective confirmations (the branch-cleanup HITL gate still pauses — irreversible). `--merge` triggers branch cleanup (irreversible HITL gate).
300
+ - **Inputs:** `<wbs>` (required, positional). `--agent <inline|auto|name>` names the wrap's model-bearing executor (default: `agent.default`); wrap is workflow-backed, so omit/`inline` resolves to `agent.default` under objective trigger 3 (durable auditable run record required), `auto` tier-resolves an executor, and a name pins that executor into `vars.agent` (see [SSOT](cross-cutting.md#inline-default-execution-surface)). `--auto` skips objective confirmations (the branch-cleanup HITL gate still pauses — irreversible). `--merge` triggers branch cleanup (irreversible HITL gate).
301
301
  - **Backing:** `spur workflow run .spur/workflows/wrapup-pipeline.yaml` — direct workflow invocation (no backing skill; the pipeline IS the procedure).
302
- - **Behavior:** Builds `--vars '{"tasks":"[\"<wbs>\"]","profile":"interactive|auto","merge":"true|false"}'` and invokes the wrapup pipeline. The pipeline runs: task-resolve → doc-sync → learning-capture → metrics-record → (feature-transition) → (branch-cleanup) → done. Task statuses are NOT mutated. Branch cleanup is an irreversible HITL gate that always pauses, even under `--auto`.
302
+ - **Behavior:** Resolves the executor (`agent.default` for omit/`inline`, tier-resolved for `auto`, unchanged for a name), emits a pre-dispatch notice naming the subprocess override — `execution surface: subprocess`, `reason: trigger 3 — durable auditable run record required`, `requested agent: <selector>`, `executor: <resolved>` — then builds `--vars '{"tasks":"[\"<wbs>\"]","agent":"<resolved>","profile":"interactive|auto","merge":"true|false"}'` and invokes the wrapup pipeline. The pipeline runs: task-resolve → doc-sync → learning-capture → metrics-record → (feature-transition) → (branch-cleanup) → done. Task statuses are NOT mutated. Branch cleanup is an irreversible HITL gate that always pauses, even under `--auto`.
303
303
  - **Vars string typing:** `tasks` is a JSON-encoded **string**, not a JSON array — `spur workflow run --vars` accepts only string values (`--vars values must be strings`); the pipeline's guards parse the string with `jq length`. `jq -nc` guarantees the shape:
304
304
 
305
305
  ```bash
306
- VARS=$(jq -nc --arg tasks "[\"$WBS\"]" --arg profile "$PROFILE" --arg merge "$MERGE" \
307
- '{tasks:$tasks, profile:$profile, merge:$merge}')
306
+ VARS=$(jq -nc --arg tasks "[\"$WBS\"]" --arg agent "$AGENT" --arg profile "$PROFILE" --arg merge "$MERGE" \
307
+ '{tasks:$tasks, agent:$agent, profile:$profile, merge:$merge}')
308
308
  spur workflow run .spur/workflows/wrapup-pipeline.yaml --vars "$VARS"
309
309
  ```
310
310
 
@@ -313,14 +313,14 @@ must not be changed without updating the backing skill.
313
313
  ### 15. wrapall
314
314
 
315
315
  - **Purpose:** Wrap up a batch of completed tasks — capture learnings, record metrics, sync docs, advance a feature through legal lifecycle edges, and optionally clean up branches.
316
- - **Inputs:** `--since <iso-date>` filters done tasks by frontmatter `updated_at >= date` (v1 approximation). `--feature <id>` selects all tasks under a feature AND advances the feature through legal lifecycle edges (`backlog → active → verifying → done`, guards honored). `--status <s>` (default: `done`) filters by task status. `--auto` skips objective confirmations. `--merge` triggers branch cleanup (irreversible HITL gate).
316
+ - **Inputs:** `--since <iso-date>` filters done tasks by frontmatter `updated_at >= date` (v1 approximation). `--feature <id>` selects all tasks under a feature AND advances the feature through legal lifecycle edges (`backlog → active → verifying → done`, guards honored). `--status <s>` (default: `done`) filters by task status. `--agent <inline|auto|name>` names the wrap's model-bearing executor (default: `agent.default`); wrap is workflow-backed, so omit/`inline` resolves to `agent.default` under objective trigger 3 (durable auditable run record required), `auto` tier-resolves an executor, and a name pins that executor into `vars.agent` (see [SSOT](cross-cutting.md#inline-default-execution-surface)). `--auto` skips objective confirmations. `--merge` triggers branch cleanup (irreversible HITL gate).
317
317
  - **Backing:** `spur workflow run .spur/workflows/wrapup-pipeline.yaml` — direct workflow invocation.
318
- - **Behavior:** Resolves the task list via `spur task list --json` (filtered by `--feature`, `--since`, `--status`), builds `--vars '{"tasks":"[...]","feature":"<id>","profile":"interactive|auto","merge":"true|false"}'`, and invokes the wrapup pipeline. The pipeline runs the same states as `wrap` but with the full task list and optional feature transition. Task statuses are NOT mutated. Feature transitions go through `spur feature update` so lifecycle guards apply. Branch cleanup is an irreversible HITL gate.
318
+ - **Behavior:** Resolves the task list via `spur task list --json` (filtered by `--feature`, `--since`, `--status`), resolves the executor (`agent.default` for omit/`inline`, tier-resolved for `auto`, unchanged for a name), emits a pre-dispatch notice naming the subprocess override — `execution surface: subprocess`, `reason: trigger 3 — durable auditable run record required`, `requested agent: <selector>`, `executor: <resolved>` — then builds `--vars '{"tasks":"[...]","feature":"<id>","agent":"<resolved>","profile":"interactive|auto","merge":"true|false"}'` and invokes the wrapup pipeline. The pipeline runs the same states as `wrap` but with the full task list and optional feature transition. Task statuses are NOT mutated. Feature transitions go through `spur feature update` so lifecycle guards apply. Branch cleanup is an irreversible HITL gate.
319
319
  - **Vars string typing:** `tasks` is a JSON-encoded **string**, not a JSON array — `--vars` values must be strings (the CLI rejects raw arrays); `jq -nc` passes the array text through as a string value:
320
320
 
321
321
  ```bash
322
- VARS=$(jq -nc --arg tasks "$TASKS" --arg feature "$FEATURE" --arg profile "$PROFILE" --arg merge "$MERGE" \
323
- '{tasks:$tasks, feature:$feature, profile:$profile, merge:$merge}')
322
+ VARS=$(jq -nc --arg tasks "$TASKS" --arg feature "$FEATURE" --arg agent "$AGENT" --arg profile "$PROFILE" --arg merge "$MERGE" \
323
+ '{tasks:$tasks, feature:$feature, agent:$agent, profile:$profile, merge:$merge}')
324
324
  spur workflow run .spur/workflows/wrapup-pipeline.yaml --vars "$VARS"
325
325
  ```
326
326