@gobing-ai/spur 0.3.64 → 0.3.66
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/corpus-baseline.json +4104 -7381
- package/config/rules/boundary/sp-runtime-path.yaml +45 -35
- package/config/rules/surface/check-cli-surface.yaml +7 -5
- package/config/workflows/history-anatomy.yaml +40 -8
- package/package.json +9 -9
- package/plugins/sp/README.md +13 -9
- package/plugins/sp/commands/dev-find-issue.md +4 -1
- package/plugins/sp/commands/dev-review-session.md +41 -0
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/references/environment-lens.md +4 -2
- package/plugins/sp/references/roles.md +8 -5
- package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.mjs +4 -0
- package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts +4 -0
- package/plugins/sp/scripts/dogfood-testing/validate-report.mjs +1 -1
- package/plugins/sp/scripts/dogfood-testing/validate-report.ts +3 -2
- package/plugins/sp/skills/dogfood-testing/SKILL.md +19 -11
- package/plugins/sp/skills/session-review/SKILL.md +139 -0
- package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +7 -1
- package/plugins/sp/skills/spur-cli/references/workflows.md +1 -1
- package/plugins/sp/skills/spur-dev/SKILL.md +5 -0
- package/plugins/sp/skills/spur-dev/references/dev-operations.md +13 -10
- package/plugins/sp/skills/spur-dev/references/execution-batch.md +71 -15
- package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +8 -6
- package/spur.js +1397 -932
- package/web/_astro/{BoardApp.CKolAjUz.js → BoardApp.BEtcJqde.js} +62 -62
- package/web/_astro/BoardApp.DBEin4N5.js +1 -0
- package/web/_astro/{TaskDetail.Bre7G4gC.js → TaskDetail.ClAbCXom.js} +1 -1
- package/web/_astro/arc.CCvf51_y.js +1 -0
- package/web/_astro/architectureDiagram-3BPJPVTR.C0cb0J5M.js +36 -0
- package/web/_astro/{blockDiagram-GPEHLZMM.CCGHeRVi.js → blockDiagram-GPEHLZMM.CIyjqoCE.js} +4 -4
- package/web/_astro/{c4Diagram-AAUBKEIU.CpqewGmd.js → c4Diagram-AAUBKEIU.fs14IuFs.js} +1 -1
- package/web/_astro/channel.BGn_DUCD.js +1 -0
- package/web/_astro/chunk-2J33WTMH.CaBKv4ZO.js +1 -0
- package/web/_astro/{chunk-4BX2VUAB.ifGXoUA3.js → chunk-4BX2VUAB.BOllTPto.js} +1 -1
- package/web/_astro/chunk-55IACEB6.ChEof0O4.js +1 -0
- package/web/_astro/{chunk-727SXJPM.DzPE41OS.js → chunk-727SXJPM.Co2kdjD8.js} +2 -2
- package/web/_astro/{chunk-AQP2D5EJ.UF2QRXYF.js → chunk-AQP2D5EJ.SWmfcnog.js} +2 -2
- package/web/_astro/{chunk-FMBD7UC4.D2zXKa1R.js → chunk-FMBD7UC4.rDAFifF3.js} +1 -1
- package/web/_astro/chunk-ND2GUHAM.BCnoXKCw.js +1 -0
- package/web/_astro/{chunk-QZHKN3VN.nUKFBiLD.js → chunk-QZHKN3VN.RSmy2hDO.js} +1 -1
- package/web/_astro/{classDiagram-4FO5ZUOK.DZg9K9mO.js → classDiagram-4FO5ZUOK.Be7PEfrX.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.DZg9K9mO.js → classDiagram-v2-Q7XG4LA2.Be7PEfrX.js} +1 -1
- package/web/_astro/{client.CdFpTatq.js → client.yhYJvxCU.js} +1 -1
- package/web/_astro/cose-bilkent-S5V4N54A.BkUp2aSK.js +1 -0
- package/web/_astro/cynefin-OW5HDTMX.BegGGlUV.js +166 -0
- package/web/_astro/cytoscape.esm.DzSz-X2X.js +321 -0
- package/web/_astro/dagre-BM42HDAG.BkUdjsaC.js +4 -0
- package/web/_astro/{defaultLocale.CrowFXzY.js → defaultLocale.DX6XiGOO.js} +1 -1
- package/web/_astro/diagram-2AECGRRQ.E9vugt3-.js +43 -0
- package/web/_astro/diagram-5GNKFQAL.Dj4yeHXB.js +10 -0
- package/web/_astro/diagram-KO2AKTUF.Buaquwli.js +3 -0
- package/web/_astro/diagram-LMA3HP47.BV3dgGgm.js +24 -0
- package/web/_astro/diagram-OG6HWLK6.Cnx3s-tc.js +24 -0
- package/web/_astro/{erDiagram-TEJ5UH35.CF2U-pQZ.js → erDiagram-TEJ5UH35.DKK_abu4.js} +3 -3
- package/web/_astro/{flowDiagram-I6XJVG4X.BJK4M3in.js → flowDiagram-I6XJVG4X.BNuu9fbm.js} +4 -4
- package/web/_astro/ganttDiagram-6RSMTGT7.b16KUMjy.js +292 -0
- package/web/_astro/gitGraphDiagram-PVQCEYII.Kh41lbG5.js +106 -0
- package/web/_astro/{graph.D2o_JWn5.js → graph.-OzhPTMs.js} +1 -1
- package/web/_astro/{index.A0eX93qW.js → index.De90oHcH.js} +1 -1
- package/web/_astro/infoDiagram-5YYISTIA.DEWBXkp-.js +2 -0
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.BmWDZtwF.js → ishikawaDiagram-YF4QCWOH.DiAdmcL6.js} +4 -4
- package/web/_astro/{journeyDiagram-JHISSGLW.CpB1YWDP.js → journeyDiagram-JHISSGLW.D1Ki7IRm.js} +1 -1
- package/web/_astro/{kanban-definition-UN3LZRKU.k-fukQX9.js → kanban-definition-UN3LZRKU.CWUhrQpc.js} +21 -21
- package/web/_astro/layout.owoKPs3z.js +1 -0
- package/web/_astro/linear.BaFsgcCe.js +1 -0
- package/web/_astro/{mermaid.core.DnpzzuPU.js → mermaid.core.CHw_AsGy.js} +5 -5
- package/web/_astro/{mindmap-definition-RKZ34NQL.D9NnlLBu.js → mindmap-definition-RKZ34NQL.UIhghgmN.js} +8 -8
- package/web/_astro/ordinal.DBvzRdQf.js +1 -0
- package/web/_astro/pieDiagram-4H26LBE5.D05l3JUA.js +30 -0
- package/web/_astro/{quadrantDiagram-W4KKPZXB.BkAygRlm.js → quadrantDiagram-W4KKPZXB.BcWIhIcE.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.CX8ibmwc.js → requirementDiagram-4Y6WPE33.B1rYvKGn.js} +1 -1
- package/web/_astro/sankeyDiagram-5OEKKPKP.CKylVRC4.js +40 -0
- package/web/_astro/{sequenceDiagram-3UESZ5HK.veO8c2tk.js → sequenceDiagram-3UESZ5HK.Dm3uA_s4.js} +3 -3
- package/web/_astro/stateDiagram-AJRCARHV.Bgca_BLe.js +1 -0
- package/web/_astro/stateDiagram-v2-BHNVJYJU.C1T7YFrG.js +1 -0
- package/web/_astro/{timeline-definition-PNZ67QCA.DayoPp_2.js → timeline-definition-PNZ67QCA.ZOHJn3Sn.js} +4 -4
- package/web/_astro/vennDiagram-CIIHVFJN.DegZitjD.js +34 -0
- package/web/_astro/{wardleyDiagram-YWT4CUSO.lIAjSkZJ.js → wardleyDiagram-YWT4CUSO.BDsC115d.js} +1 -1
- package/web/_astro/{xychartDiagram-2RQKCTM6.D8_2K6U1.js → xychartDiagram-2RQKCTM6.D0MO70ea.js} +4 -4
- package/web/index.html +1 -1
- package/web/_astro/BoardApp.DXD--ybM.js +0 -1
- package/web/_astro/arc.7luwOGiC.js +0 -1
- package/web/_astro/architectureDiagram-3BPJPVTR.F6KaHXp-.js +0 -36
- package/web/_astro/channel.DxfOFf1l.js +0 -1
- package/web/_astro/chunk-2J33WTMH.CB9vKa5F.js +0 -1
- package/web/_astro/chunk-55IACEB6.VIaRo7l8.js +0 -1
- package/web/_astro/chunk-ND2GUHAM.Cb9bDyvx.js +0 -1
- package/web/_astro/cose-bilkent-S5V4N54A.D9STo90d.js +0 -1
- package/web/_astro/cytoscape.esm.D3_iZ_3b.js +0 -321
- package/web/_astro/dagre-BM42HDAG.D3IbwhHz.js +0 -4
- package/web/_astro/diagram-2AECGRRQ.BWTDxBe9.js +0 -43
- package/web/_astro/diagram-5GNKFQAL.XnXlonHG.js +0 -10
- package/web/_astro/diagram-KO2AKTUF.CywOngCO.js +0 -3
- package/web/_astro/diagram-LMA3HP47.DY1D21Iu.js +0 -24
- package/web/_astro/diagram-OG6HWLK6.DQxb59KA.js +0 -24
- package/web/_astro/ganttDiagram-6RSMTGT7.BSniMzdB.js +0 -292
- package/web/_astro/gitGraphDiagram-PVQCEYII.Dxg-yRov.js +0 -106
- package/web/_astro/infoDiagram-5YYISTIA.BY4CgO_n.js +0 -2
- package/web/_astro/layout.DNLMvjEt.js +0 -1
- package/web/_astro/linear.BNNCobvI.js +0 -1
- package/web/_astro/ordinal.BYWQX77i.js +0 -1
- package/web/_astro/pieDiagram-4H26LBE5.CKhoMiyC.js +0 -30
- package/web/_astro/sankeyDiagram-5OEKKPKP.Dvurpa0Y.js +0 -40
- package/web/_astro/stateDiagram-AJRCARHV.DpMr4CO3.js +0 -1
- package/web/_astro/stateDiagram-v2-BHNVJYJU.CKjso86_.js +0 -1
- package/web/_astro/vennDiagram-CIIHVFJN.XNHf04O9.js +0 -34
- package/web/_astro/wardley-L42UT6IY.CpM_031g.js +0 -161
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: session-review
|
|
3
|
+
description: "Review the active coding-agent session: separate resolved from open issues with evidence, propose bounded improvements. With --triage, apply pure-doc / 1–2-line fixes inline and file the rest as one task. Triggers: review this session, wrap-up, triage findings."
|
|
4
|
+
license: Apache-2.0
|
|
5
|
+
version: 1.1.0
|
|
6
|
+
metadata:
|
|
7
|
+
author: spur
|
|
8
|
+
platforms: "claude-code,codex,openclaw,opencode,antigravity,pi"
|
|
9
|
+
category: analysis-core
|
|
10
|
+
interactions:
|
|
11
|
+
- reviewer
|
|
12
|
+
see_also:
|
|
13
|
+
- sp:history-anatomy
|
|
14
|
+
- sp:indexed-context
|
|
15
|
+
- sp:code-verification
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# sp:session-review — Active Session Review
|
|
19
|
+
|
|
20
|
+
Review the active coding-agent session while its conversation context is still available. Produce a
|
|
21
|
+
compact, evidence-backed report of outcomes, resolved issues, remaining risks, and improvements.
|
|
22
|
+
|
|
23
|
+
## When to use
|
|
24
|
+
|
|
25
|
+
Use this skill immediately after focused operations when the operator asks what happened, what was
|
|
26
|
+
resolved, or how the session could improve. Use imported-history analysis for ended sessions,
|
|
27
|
+
cross-agent windows, recurrence, trends, or quantitative performance forensics.
|
|
28
|
+
|
|
29
|
+
## Arguments
|
|
30
|
+
|
|
31
|
+
| Argument | Description | Default |
|
|
32
|
+
| --- | --- | --- |
|
|
33
|
+
| `[focus]` | Question or operation to emphasize. It changes ordering, not evidence collection. | full active session |
|
|
34
|
+
| `--triage` | Opt into bounded remediation after the report: apply direct fixes (pure docs / one-to-two-line fixes) inline, then file all remaining actionable findings as exactly one new task via the CLI-gated corpus surface. | off (report-only) |
|
|
35
|
+
|
|
36
|
+
## Evidence boundary
|
|
37
|
+
|
|
38
|
+
- Treat the active conversation as the primary evidence plane.
|
|
39
|
+
- Verify each material claim with source evidence from the conversation or a read-only repository
|
|
40
|
+
check, and cite the exact result or path in the report.
|
|
41
|
+
- Use read-only repository checks only when they confirm a material claim; prefer existing tool
|
|
42
|
+
results already visible in the session over rerunning commands.
|
|
43
|
+
- Mark an issue **resolved** only when the session shows the symptom, root cause, applied resolution,
|
|
44
|
+
and verification evidence. Otherwise classify it as open or attempted.
|
|
45
|
+
- Separate observation from inference. Label an unsupported causal explanation as a hypothesis and
|
|
46
|
+
name the confirmation needed.
|
|
47
|
+
- State `not available` when compaction or missing output removed evidence. Never reconstruct it from
|
|
48
|
+
memory or claim a verification that did not run.
|
|
49
|
+
|
|
50
|
+
## Triage mode (`--triage`)
|
|
51
|
+
|
|
52
|
+
Report-only stays the default. With `--triage`, run the same evidence pass, then remediate in
|
|
53
|
+
three buckets — never skip triage and start fixing from the raw findings list.
|
|
54
|
+
|
|
55
|
+
1. **Triage every finding into exactly one bucket:**
|
|
56
|
+
- **Direct fix** — pure documentation work, or a one-to-two-line fix with obvious, local,
|
|
57
|
+
low-risk scope. Read the root cause first; a "one-liner" that needs design or touches a
|
|
58
|
+
shared write path is not direct.
|
|
59
|
+
- **Task** — real, actionable, and not already owned by an existing task. Deferred
|
|
60
|
+
requirements recorded inside their own task files are pointers, not duplicates.
|
|
61
|
+
- **Note** — pre-existing, environmental, or ownerless observations; report only.
|
|
62
|
+
2. **Apply direct fixes inline** — smallest surgical diff, project style, and re-verify each
|
|
63
|
+
with the targeted check (lint / test / the exact command that exhibited the issue).
|
|
64
|
+
3. **Create exactly one task** for the Task bucket through the CLI-gated corpus surface
|
|
65
|
+
(`spur task create`, then `spur task update <wbs> --section <s> --from-file` per section).
|
|
66
|
+
One task, not one per finding: each finding keeps its evidence, a suggested fix direction,
|
|
67
|
+
and an AC where verifiable. Exclude what direct fixes already resolved — say so in the task
|
|
68
|
+
Background instead.
|
|
69
|
+
4. **Report** — add a Triage section: applied fixes (path + one-line what + verification) and
|
|
70
|
+
the created task WBS. The Resolved/Open tables keep their evidence rules unchanged.
|
|
71
|
+
|
|
72
|
+
## Protocol
|
|
73
|
+
|
|
74
|
+
1. **Resolve scope.** Review the active session from the operator's initiating request through the
|
|
75
|
+
latest result. Use `[focus]` only to rank relevant material.
|
|
76
|
+
2. **Inventory outcomes.** List requested outcomes and classify each as completed, partial, blocked,
|
|
77
|
+
or not attempted. Collapse repeated attempts into one outcome.
|
|
78
|
+
3. **Classify issues.** For every material issue, distinguish resolved, open, or attempted. Record
|
|
79
|
+
root cause only when the evidence boundary supports it.
|
|
80
|
+
4. **Select improvements.** Keep at most three changes that would prevent meaningful recurrence.
|
|
81
|
+
Apply the placement rule in
|
|
82
|
+
[the environment-improvement mapping](../../references/environment-lens.md): automate with a
|
|
83
|
+
check when possible, place coding standards on the review path, and keep always-loaded steering
|
|
84
|
+
as navigation pointers.
|
|
85
|
+
5. **Render the report.** Use the exact compact output contract below. Omit empty table rows, not
|
|
86
|
+
headings; write `None observed` when a section has no supported entry.
|
|
87
|
+
|
|
88
|
+
## Output contract
|
|
89
|
+
|
|
90
|
+
### Outcome
|
|
91
|
+
|
|
92
|
+
State the overall result in one to three sentences, including partial or blocked scope.
|
|
93
|
+
|
|
94
|
+
### Resolved issues
|
|
95
|
+
|
|
96
|
+
| Issue | Root cause | Resolution | Evidence |
|
|
97
|
+
| --- | --- | --- | --- |
|
|
98
|
+
|
|
99
|
+
Evidence names the tool result, verification command, or concrete repository state visible in the
|
|
100
|
+
session. Do not list ordinary implementation steps as issues.
|
|
101
|
+
|
|
102
|
+
### Open issues and risks
|
|
103
|
+
|
|
104
|
+
| Issue or risk | State | Evidence or confirmation needed |
|
|
105
|
+
| --- | --- | --- |
|
|
106
|
+
|
|
107
|
+
### Process and environment improvements
|
|
108
|
+
|
|
109
|
+
For each supported proposal, name its owner surface, expected impact, verification method, and
|
|
110
|
+
reversibility. Proposals remain report-only: apply no change and create no task.
|
|
111
|
+
|
|
112
|
+
### Triage (only when `--triage` was passed)
|
|
113
|
+
|
|
114
|
+
| Applied fix / created task | Bucket | What + verification |
|
|
115
|
+
| --- | --- | --- |
|
|
116
|
+
|
|
117
|
+
One row per applied fix and one per created task (with its WBS). Omit the section entirely when
|
|
118
|
+
`--triage` was not passed.
|
|
119
|
+
|
|
120
|
+
### Next actions
|
|
121
|
+
|
|
122
|
+
List only actions needed to finish partial scope, confirm a hypothesis, or preserve a demonstrated
|
|
123
|
+
improvement. Use `None` when the session is complete and no follow-up is justified.
|
|
124
|
+
|
|
125
|
+
## Boundaries
|
|
126
|
+
|
|
127
|
+
- Stay in the active host session. Do not delegate; a fresh context loses the evidence being reviewed.
|
|
128
|
+
- Do not launch a workflow, import history, append indexed-context memory, perform baseline
|
|
129
|
+
comparison or recurrence classification, or emit a twelve-section forensic report; those belong
|
|
130
|
+
to imported-history analysis.
|
|
131
|
+
- Report-only by default: do not create or update corpus items or edit files. The single exception
|
|
132
|
+
is `--triage` mode, which permits exactly two mutation classes — direct fixes from the triage
|
|
133
|
+
bucket, and the one triage task. Anything beyond that stays a proposal.
|
|
134
|
+
- Do not turn a single low-impact observation into a new policy. Report it as a candidate until it
|
|
135
|
+
recurs or demonstrates a high-impact contract violation.
|
|
136
|
+
|
|
137
|
+
## Platform notes
|
|
138
|
+
|
|
139
|
+
On platforms without slash commands, invoke this skill directly before ending the active session.
|
|
@@ -54,7 +54,9 @@ frontmatter scalar.
|
|
|
54
54
|
cancelled`. Two transitions run a target-aware `check` guard (§7.5): `wip→testing` →
|
|
55
55
|
`spur task check <wbs> --as testing`; `testing→done` → `spur task check <wbs> --as done`
|
|
56
56
|
(F92 R3 — each evaluates the transition target, so `testing→done` checks the `done` row).
|
|
57
|
-
A failing gate blocks the transition.
|
|
57
|
+
A failing gate blocks the transition. The `wip→testing` guard additionally requires a Solution
|
|
58
|
+
section citing concrete `file:line` evidence — a missing/unsubstantiated Solution is rejected with
|
|
59
|
+
`[invalid-solution]`.
|
|
58
60
|
- **`--no-lifecycle`**: suppress lifecycle workflow *run record* creation (use inside pipeline runs
|
|
59
61
|
to avoid orphaned nested lifecycle runs). **It is not a guard bypass** — the `wip→testing` and
|
|
60
62
|
`testing→done` `check` gates above still run; the CLI evaluates them inline when the FSM guard
|
|
@@ -230,6 +232,10 @@ only the exact corpus path, with no basename-WBS fallback. Returns exit `1` if n
|
|
|
230
232
|
|
|
231
233
|
## `verdict <wbs>`
|
|
232
234
|
|
|
235
|
+
There is **no `verify` verb**. The verify leg is three steps: the agent writes its structured
|
|
236
|
+
evidence write-up to `.spur/run/<wbs>-verify-answer.txt`, then `spur task verdict <wbs>` derives
|
|
237
|
+
the verdict artifact, then `spur task record <wbs>` lands it into the task.
|
|
238
|
+
|
|
233
239
|
Derive a PASS / PARTIAL / FAIL / UNKNOWN verdict from a verify-step answer text file (the agent's
|
|
234
240
|
structured evidence write-up). Replaces the pipeline's verify→record transition's previous grep/shell
|
|
235
241
|
ladder (0108; ADR-022). On a readable answer, emits `.spur/run/<wbs>-verdict.json` (mkdir-p the
|
|
@@ -255,7 +255,7 @@ the operator accepts it, and never hot-edit a running workflow's shell in place.
|
|
|
255
255
|
|
|
256
256
|
```
|
|
257
257
|
spur workflow validate <file> [--no-schema] [--json]
|
|
258
|
-
spur workflow show <file>
|
|
258
|
+
spur workflow show <file> [--format <mermaid|todo>] [--json]
|
|
259
259
|
spur workflow run <file> [--run-id <id>] [--vars <json>] [--dry-run] [--async] [--no-plan] [--quiet/--silent/--verbose] [--detail <level>] [--trace-file] [--no-log] [--steer] [--json]
|
|
260
260
|
spur workflow continue [run-id] [--yes] [--answer <yes|no|cancel>] [--json]
|
|
261
261
|
spur workflow cancel <run-id> [--json]
|
|
@@ -234,6 +234,11 @@ or `args="refine <wbs>"` for task refinement, or `args="refineall --feature <id>
|
|
|
234
234
|
batch refine under a feature (add `--depth ready` for implement-ready freeze). Use `spur agent run`
|
|
235
235
|
for isolated LLM invocations within pipeline steps.
|
|
236
236
|
|
|
237
|
+
**Argument parsing.** Split `$ARGUMENTS` into target + flags before dispatching. Unknown flags are
|
|
238
|
+
not silently dropped: note them in the plan line, or stop (rule imported from `next-router`,
|
|
239
|
+
task 0701 R3 — e.g. `--worktree` on `dev-refine` is undeclared, so it must be surfaced, never
|
|
240
|
+
discarded).
|
|
241
|
+
|
|
237
242
|
### Codex / OpenClaw / OpenCode / Antigravity
|
|
238
243
|
|
|
239
244
|
Run `spur` CLI via the Bash tool; parse `--json` output. Invoke this skill directly for
|
|
@@ -32,14 +32,17 @@ each would be scope creep for one-liner procedures.
|
|
|
32
32
|
> backbone skill (which owns the 4-phase dogfood protocol, the live ledger, and the report template);
|
|
33
33
|
> it does not map to a numbered dev-\* operation. See its command file and the backing skill for details.
|
|
34
34
|
|
|
35
|
-
> **`dev-find-issue`** is not in this table. It is a thin `Skill()` wrapper over
|
|
36
|
-
>
|
|
37
|
-
>
|
|
38
|
-
>
|
|
39
|
-
>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
> **`dev-find-issue`** is not in this table. It is a thin `Skill()` wrapper over
|
|
36
|
+
> **`sp:history-anatomy`** for daily/ad-hoc imported-history forensics: fixed twelve-section report,
|
|
37
|
+
> baseline comparison, cache branch, independent validation, and atomic publication. It never
|
|
38
|
+
> imports history or creates a task. See `plugins/sp/commands/dev-find-issue.md` and
|
|
39
|
+
> `plugins/sp/skills/history-anatomy/SKILL.md`.
|
|
40
|
+
|
|
41
|
+
> **`dev-review-session`** is not in this table. It is a thin `Skill()` wrapper over
|
|
42
|
+
> **`sp:session-review`** for an immediate, inline, report-only review of the active conversation.
|
|
43
|
+
> It launches no workflow or agent and performs no import, persistence, or mutation. Use it before
|
|
44
|
+
> the active session ends; use history-anatomy for ended sessions, cross-agent windows, trends, or
|
|
45
|
+
> quantitative forensics.
|
|
43
46
|
|
|
44
47
|
> **`dev-find-conflict`** is not in this table. It is a thin `Skill()` wrapper over
|
|
45
48
|
> **`sp:conflict-finding`** (authority-aware four-pillar semantic audit → optional confirmed,
|
|
@@ -233,7 +236,7 @@ must not be changed without updating the backing skill.
|
|
|
233
236
|
- **Purpose:** Batch-refine a set of tasks (or all refine-eligible tasks under a feature) — resolve a set, topo-sort by dependencies, run per-task `refine`, emit a summary report. Planning-half counterpart of `verifyall` / `runall` for the just-in-time spec-completion gate. With `--depth ready`, batch **implement-ready** freeze before multi-agent implement or runall.
|
|
234
237
|
- **Inputs:**
|
|
235
238
|
- `--feature <id>` **or** `--tasks <selector>` (required — at least one). `--feature` is sugar for `--tasks feature:<id>` (shared selector grammar: explicit WBS list, `feature:<id>`, `ready`, status pseudo-list — [execution-batch.md](execution-batch.md) Step 1). If both are present, `--tasks` wins (one-line note in the report).
|
|
236
|
-
- Shared refine flags (passed through to each per-task refine): `--focus <mode>`, `--description <text>`, `--depth <standard|ready>`, `--agent <inline|auto|name>`, `--auto
|
|
239
|
+
- Shared refine flags (passed through to each per-task refine): `--focus <mode>`, `--description <text>`, `--depth <standard|ready>`, `--agent <inline|auto|name>`, `--auto`.
|
|
237
240
|
- Batch-only flags: `--keep-going` (continue independents after a failure; default halt), `--status <s>` (filter resolved membership; default **`backlog,todo`** — planning-side fill candidates), `--json` (machine-readable batch report).
|
|
238
241
|
- **Backing:** `sp:spur-dev` skill, `refineall` operation (orchestrates; per-task body is the single-task `refine` operation — never a second refine implementation).
|
|
239
242
|
- **Behavior:**
|
|
@@ -245,7 +248,7 @@ must not be changed without updating the backing skill.
|
|
|
245
248
|
6. Emit a batch report (markdown or `--json`) that records `depth` once at the header.
|
|
246
249
|
- **Per-task outcome vocabulary:** `refined` (synthesis wrote sections) | `SKIP` (already meets the active depth bar under `--auto`) | `failed` | `skipped` (dep failed under `--keep-going`) | `not-attempted` (halted) | `blocked` (unmet out-of-set dep).
|
|
247
250
|
- **Batch verdict:** `clean` (all attempted tasks `refined` or `SKIP`) | `halted` (a failure stopped the batch) | `aborted` (cycle / unknown selector / empty set after filter).
|
|
248
|
-
- **`--next`
|
|
251
|
+
- **`--next` is not accepted** (dropped by feature H8, 2026-07-31 — see `plugins/sp/commands/dev-refineall.md` for the removal record). Chain execution explicitly: refineall, then `/sp:dev-runall --feature <id>`.
|
|
249
252
|
- **`--auto` recommendation:** Batch refine without `--auto` requires per-task interactive Q&A and does not scale. Default operator path: `/sp:dev-refineall --feature <id> --auto`. For implement handoffs: `/sp:dev-refineall --feature <id> --auto --depth ready`.
|
|
250
253
|
- **Delegation:** `Skill(skill="sp:spur-dev", args="refineall $ARGUMENTS")` → per task `Skill(skill="sp:spur-dev", args="refine <wbs> $SHARED_FLAGS")` (shared flags include `--depth` when set).
|
|
251
254
|
|
|
@@ -61,6 +61,7 @@ function normalizeArgs(raw: Args): Args {
|
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
**Normalization rules (performed by the command layer before the skill sees $ARGUMENTS, or by the batch resolver):**
|
|
64
|
+
|
|
64
65
|
- If `--feature FOO` is present and `--tasks` is absent, treat the effective selector as `feature:FOO`.
|
|
65
66
|
- If both are present, `--tasks` wins (with a one-line note in the batch report).
|
|
66
67
|
|
|
@@ -101,7 +102,7 @@ bun run apps/cli/src/index.ts feature check <id> --strict --json
|
|
|
101
102
|
kickoff** — the driver never re-queries `spur task list` to recompute membership mid-batch (R2.1).
|
|
102
103
|
|
|
103
104
|
| Selector form | Regex / match | Resolution |
|
|
104
|
-
|
|
105
|
+
| --- | --- | --- |
|
|
105
106
|
| Explicit WBS list | `^[0-9, ]+$` | Split on comma; validate each token is a 4-digit WBS; collect the explicit set. (R1.1) |
|
|
106
107
|
| `feature:<id>` (via `--tasks` or `--feature <id>`) | literal `feature:` prefix or `--feature` flag | `spur task list --feature <id> --json`; collect `wbs` from each row. The `--feature` flag is sugar that becomes `--tasks feature:<id>` at the command layer. (R1.3) |
|
|
107
108
|
| `ready` | literal `ready` | Resolve the union of `spur task list --status todo --json` + `spur task list --status backlog --json`, drop tasks with open children (R1.5, umbrella-parent exclusion below), then keep only tasks whose every `dependencies[]` entry resolves to `status == done` (via `spur task show <dep> --json | jq '{wbs, status, dependencies, feature_id}'` — R5 metadata-only). Report each excluded task with its unmet dependency. (R1.4) |
|
|
@@ -185,7 +186,7 @@ node "$(superskill script path sp batch-preflight.mjs)" \
|
|
|
185
186
|
```
|
|
186
187
|
|
|
187
188
|
| Result | Batch action |
|
|
188
|
-
|
|
189
|
+
| -------- | ---------------- |
|
|
189
190
|
| `action: run` | Launch `task-pipeline.yaml` for this WBS (happy path **unchanged**) |
|
|
190
191
|
| `action: skip` code **A2** | Do not launch; report `preflight-skip` + unmet deps (mirrors TABLE A2) |
|
|
191
192
|
| `action: skip` code **A7** | Do not launch; report blocked (handover is operator-side) |
|
|
@@ -253,7 +254,7 @@ Only two flags cross the orchestrator→pipeline boundary; both are merged into
|
|
|
253
254
|
`--vars` JSON:
|
|
254
255
|
|
|
255
256
|
| Flag | Effect on per-task `--vars` |
|
|
256
|
-
|
|
257
|
+
| --- | --- |
|
|
257
258
|
| `--auto` | sets `"profile":"auto"` (skips the HITL approve gate). Omitting it forwards nothing, so the pipeline uses its default profile (standard — HITL pause surfaces to the operator). (R4.2) |
|
|
258
259
|
| `--agent <value>` | omit/`inline` in interactive sequential mode selects the host driver and is not forwarded. `auto` or a name sets **both** `"agent":"<value>"` and `"implementAgent":"<value>"` so every workflow `agent.run` step — including implement — spawns that executor. Headless omit/inline falls through the executor precedence chain. To pin ONLY implement, pass `--vars '{"implementAgent":"..."}'` separately; that explicit var selects the subprocess path. (R4.3, tasks 0483/0503) |
|
|
259
260
|
|
|
@@ -283,7 +284,7 @@ node "$(superskill script path sp batch-preflight.mjs)" --wbs <wbs> --status <st
|
|
|
283
284
|
```
|
|
284
285
|
|
|
285
286
|
| Rule | Detail |
|
|
286
|
-
|
|
287
|
+
| ------ | -------- |
|
|
287
288
|
| Budget | **≤ 1** recovery consult per WBS per batch — never loop until done |
|
|
288
289
|
| Default | Print the exact child command in the batch report |
|
|
289
290
|
| `--auto` batch | May dispatch the child **once** when cardinality is 1 and the hop is a single lifecycle command |
|
|
@@ -295,7 +296,6 @@ in next-router; this only maps status → primary TABLE A hop for recovery.
|
|
|
295
296
|
|
|
296
297
|
### 3.3c Bounded feature-sync retry suppression (task 0411)
|
|
297
298
|
|
|
298
|
-
|
|
299
299
|
During a batch, the per-task `record` step and the wrap-up `feature-transition` step each invoke
|
|
300
300
|
feature status sync. When a feature is L4-gate-blocked (e.g. not all linked tasks are `done`), the
|
|
301
301
|
identical blocked proposal repeats on every call with no intervening input change — in the H9
|
|
@@ -413,6 +413,14 @@ The per-task outcome vocabulary: `done` | `failed` | `blocked` | `skipped` | `no
|
|
|
413
413
|
The batch verdict: `clean` (all attempted tasks `done`) | `halted` (a failure stopped the batch) |
|
|
414
414
|
`aborted` (cycle or selector error before any run).
|
|
415
415
|
|
|
416
|
+
**Zero-task rule (task 0701 R7b).** A selector that resolves to an **empty set after the status
|
|
417
|
+
filter** is an `aborted` verdict (`aborted (empty set after filter)`), matching dev-operations.md
|
|
418
|
+
§5a. Under `--worktree`, **WT-2 is skipped entirely**: no worktree is cut and no WT-3 marker is
|
|
419
|
+
written for a batch with nothing to run. The early-exit report carries zero per-task rows,
|
|
420
|
+
`Steps: 0 derived, 0 executed`, and the `aborted` verdict; no WT-3b commit step and no WT-4/WT-5
|
|
421
|
+
terminal action runs. A contract test pins this
|
|
422
|
+
(`plugins/sp/tests/dogfood-testing/execution-batch-contract.test.ts`).
|
|
423
|
+
|
|
416
424
|
## Worktree isolation (`--worktree [<name>]`)
|
|
417
425
|
|
|
418
426
|
When a batch command (`dev-runall`, `dev-refineall`, `dev-verifyall`) is invoked with
|
|
@@ -487,7 +495,12 @@ Create one worktree on a new branch cut from the current HEAD's ref (the **base
|
|
|
487
495
|
BASE_REF=$(git rev-parse --abbrev-ref HEAD)
|
|
488
496
|
BASE_SHA=$(git rev-parse HEAD)
|
|
489
497
|
BRANCH="sp/<command>-<selector-slug>-<short-id>" # e.g. sp/runall-h1-a3f2
|
|
490
|
-
git worktree add
|
|
498
|
+
# `git worktree add -b` creates the branch BEFORE the directory, so a failed create leaves a
|
|
499
|
+
# dangling branch and the natural retry dies on "a branch named ... already exists"
|
|
500
|
+
# (task 0701 R2b). Wrap the create: on failure, delete the branch — or derive a fresh
|
|
501
|
+
# short-id per attempt — before surfacing the error.
|
|
502
|
+
git worktree add "../<repo>-<command>-<selector-slug>-<short-id>" -b "$BRANCH" "$BASE_REF" \
|
|
503
|
+
|| { git branch -D "$BRANCH"; false; }
|
|
491
504
|
```
|
|
492
505
|
|
|
493
506
|
Branch and directory names are derived (command + selector slug + short id); the create path never
|
|
@@ -497,10 +510,15 @@ not resolve is an error, not a create).
|
|
|
497
510
|
A fresh worktree has no `node_modules` (gitignored), so the first `bun test` or
|
|
498
511
|
typecheck fails on the first workspace import. Install before any task work:
|
|
499
512
|
|
|
500
|
-
cd "../<worktree-dir>" && bun install --frozen-lockfile
|
|
513
|
+
cd "../<worktree-dir>" && bun install --frozen-lockfile --ignore-scripts
|
|
501
514
|
|
|
502
515
|
`--frozen-lockfile` pins the worktree to `bun.lock` rather than re-resolving,
|
|
503
|
-
so the worktree's dependency tree matches the base ref's.
|
|
516
|
+
so the worktree's dependency tree matches the base ref's. `--ignore-scripts` is required, not
|
|
517
|
+
stylistic (task 0701 R2a): worktrees share the main tree's `.git`, and this repo's `prepare`
|
|
518
|
+
script is `lefthook install` (`package.json`) — a bare install rewrites the operator's
|
|
519
|
+
main-repo hooks from inside the "isolated" tree. Scripts are skipped only at this call site;
|
|
520
|
+
a normal clone keeps `prepare`. The worktree still gets a usable dependency tree — the install
|
|
521
|
+
exists so the first `bun test` resolves workspace imports.
|
|
504
522
|
|
|
505
523
|
#### Reuse mode (`--worktree <name>`)
|
|
506
524
|
|
|
@@ -510,8 +528,8 @@ invoking tree's current HEAD ref (not the worktree's branch) and `BASE_SHA` is
|
|
|
510
528
|
`git merge-base <BASE_REF> <BRANCH>` — so WT-4's FF-merge lands the worktree's accumulated commits
|
|
511
529
|
onto the invoking tree's base ref, exactly as create mode does.
|
|
512
530
|
|
|
513
|
-
`bun install --frozen-lockfile` runs **only when `node_modules` is absent** in
|
|
514
|
-
worktree. A warm reused tree does not re-pay the install; a cold one (hand-made, or a retained tree
|
|
531
|
+
`bun install --frozen-lockfile --ignore-scripts` runs **only when `node_modules` is absent** in
|
|
532
|
+
the resolved worktree (same `--ignore-scripts` rationale as create mode — task 0701 R2a). A warm reused tree does not re-pay the install; a cold one (hand-made, or a retained tree
|
|
515
533
|
whose deps were removed) installs exactly once before the first task. This is the R3 conditional
|
|
516
534
|
install rule (source: task 0481) — create mode always installs because a fresh tree is always cold.
|
|
517
535
|
|
|
@@ -570,7 +588,9 @@ verb) whose path argument you control.
|
|
|
570
588
|
|
|
571
589
|
Worktree identity lives on disk under `.spur/run/`, not only in the orchestrator's memory, so a
|
|
572
590
|
session that dies mid-batch is recoverable. Write the marker at creation and update it at the
|
|
573
|
-
terminal transition (merged / retained).
|
|
591
|
+
terminal transition (merged / retained). The marker is written to the **invoking** tree's
|
|
592
|
+
`.spur/run/` (task 0701 R2c) — the tree where the driver process started, not the worktree's own
|
|
593
|
+
`.spur/run/` — so WT-6's resume scan finds it regardless of where the operator stands. Schema:
|
|
574
594
|
|
|
575
595
|
```json
|
|
576
596
|
{
|
|
@@ -617,6 +637,22 @@ Reuse mode resolves the marker by the resolved worktree's `path` (not by `comman
|
|
|
617
637
|
(AGENTS.md one-writer-per-tree; task 0487 R5). Overridable with `--force` (the operator can tell
|
|
618
638
|
a crashed-session marker from a live-session one; the harness cannot).
|
|
619
639
|
|
|
640
|
+
### WT-3b — Commit the batch's writes on `$BRANCH` (task 0701 R1)
|
|
641
|
+
|
|
642
|
+
Before any terminal action, commit the batch's corpus writes **on `$BRANCH`, inside the
|
|
643
|
+
worktree** — including the generated task files under `docs/tasks*/` and the kanban index:
|
|
644
|
+
|
|
645
|
+
```bash
|
|
646
|
+
cd "../<worktree-dir>"
|
|
647
|
+
git add <files-the-batch-wrote>
|
|
648
|
+
git commit -m "<type>(<scope>): <command> <selector> batch writes"
|
|
649
|
+
cd - >/dev/null
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
The FF-only git merge carries only commits — uncommitted writes in the worktree would be left
|
|
653
|
+
behind by the merge and then destroyed by create mode's `git worktree remove`. WT-3b exists so
|
|
654
|
+
that can never happen.
|
|
655
|
+
|
|
620
656
|
### WT-4 — Success path (R4)
|
|
621
657
|
|
|
622
658
|
When the batch completes with **no failed task**, fast-forward-merge the worktree branch onto the
|
|
@@ -629,6 +665,11 @@ only what it created*):
|
|
|
629
665
|
# Run these from the main tree (not inside the worktree) - you merge the worktree branch
|
|
630
666
|
# back onto the base ref there:
|
|
631
667
|
git checkout "$BASE_REF"
|
|
668
|
+
# Guard (task 0701 R1): a zero-commit branch makes the FF-only git merge exit 0
|
|
669
|
+
# ("Already up to date") while merging nothing — the two lines below would then delete
|
|
670
|
+
# the worktree holding the only copy of the batch's writes. Refuse instead:
|
|
671
|
+
[ "$(git rev-list --count "$BASE_SHA..$BRANCH")" -gt 0 ] \
|
|
672
|
+
|| { echo "halt: branch carries no commits - nothing to merge" >&2; false; } # -> WT-5
|
|
632
673
|
git merge --ff-only "$BRANCH" # FF-only: never rebase, merge-commit, or resolve conflicts
|
|
633
674
|
# if FF succeeded:
|
|
634
675
|
git worktree remove "../<worktree-dir>"
|
|
@@ -636,6 +677,9 @@ git branch -d "$BRANCH"
|
|
|
636
677
|
# update marker: status = "merged"
|
|
637
678
|
```
|
|
638
679
|
|
|
680
|
+
On the zero-commit guard firing, fall through to **WT-5** with the halt cause *"branch carries no
|
|
681
|
+
commits — nothing to merge"*: the worktree and branch are retained, never removed (task 0701 R1).
|
|
682
|
+
|
|
639
683
|
#### Reuse mode — merge, retain
|
|
640
684
|
|
|
641
685
|
The FF-merge runs identically (same `git checkout "$BASE_REF" && git merge --ff-only "$BRANCH"`),
|
|
@@ -667,12 +711,23 @@ risk losing work); WT-5 retains the worktree and branch whenever FF is impossibl
|
|
|
667
711
|
Reuse mode is **narrower** than the carve-out (it merges but does not delete the branch), so the
|
|
668
712
|
carve-out text needs no widening.
|
|
669
713
|
|
|
714
|
+
**Lifecycle-DB disposition (task 0701 R2d).** The worktree has its own `.spur` lifecycle DB, and
|
|
715
|
+
WT-4/WT-5 remove or retain that tree — the DB state does **not** travel with the merge. The
|
|
716
|
+
**committed task file is authoritative**: after a green merge the branch's task files read
|
|
717
|
+
`done`/`testing` while the invoking tree's DB still reports the pre-batch statuses. Re-sync
|
|
718
|
+
explicitly by replaying the recorded terminal transitions in the invoking tree (`spur task update
|
|
719
|
+
<wbs> <status>` per task, then `spur task record <wbs>`), or treat the batch report's per-task
|
|
720
|
+
table as the source of truth. This is a deliberate choice over auto-migrating DB state: the DB is
|
|
721
|
+
per-tree by design and the committed corpus files are the durable record.
|
|
722
|
+
|
|
670
723
|
### WT-5 — Failure path: retain and report (R5)
|
|
671
724
|
|
|
672
725
|
On any per-task failure, batch halt, HITL pause that ends the run, or non-FF merge from WT-4, the
|
|
673
726
|
worktree directory and branch are left **intact**. No destructive automation on this path under any
|
|
674
727
|
flag combination (`--auto`, `--force`, `--keep-going` — all leave the worktree in place). Update the
|
|
675
|
-
marker: `status = "retained"`.
|
|
728
|
+
marker: `status = "retained"`. The worktree's own `.spur` lifecycle DB is retained with the tree,
|
|
729
|
+
so nothing is lost on this path (see the WT-4 lifecycle-DB disposition for the merged case —
|
|
730
|
+
task 0701 R2d). Emit a retention report in the existing halt-report shape:
|
|
676
731
|
|
|
677
732
|
```
|
|
678
733
|
## Worktree retained — <command> <selector>
|
|
@@ -706,7 +761,8 @@ its WT-3 marker rather than creating a second one. Marker lookup tries two paths
|
|
|
706
761
|
This path covers the common resume shapes: the operator remembers the name used last time, or
|
|
707
762
|
passes the path (tier-1 match).
|
|
708
763
|
2. **Command+selector fallback (bare `--worktree` or absent flag)** — scan
|
|
709
|
-
`.spur/run/worktree-*.json`
|
|
764
|
+
`.spur/run/worktree-*.json` **in the invoking tree** (where WT-3 wrote the marker —
|
|
765
|
+
task 0701 R2c) for a marker whose `command` + `selector` match the current
|
|
710
766
|
invocation and whose `status` is `active` or `retained`. Create-mode runs that did not name their
|
|
711
767
|
tree resolve here.
|
|
712
768
|
3. **Found by either path** → `cd` into the marker's `path`, skip WT-1/WT-2 (no new worktree), and
|
|
@@ -769,7 +825,7 @@ time. Before launching a full `spur-check-new`:
|
|
|
769
825
|
## AC traceability
|
|
770
826
|
|
|
771
827
|
| AC | Where satisfied |
|
|
772
|
-
|
|
828
|
+
| --- | --- |
|
|
773
829
|
| R1.1–R1.4 (selector grammar) | Step 1 — selector resolution table |
|
|
774
830
|
| R1.5 (umbrella-parent exclusion) | Step 1 — "Umbrella-parent exclusion" paragraph |
|
|
775
831
|
| R2.1 (freeze at kickoff) | Step 2.1 |
|
|
@@ -793,6 +849,7 @@ time. Before launching a full `spur-check-new`:
|
|
|
793
849
|
When a batch contains tasks with **zero dependency edges between them** and **no file-overlap conflicts**, the orchestrator can fan them out in parallel instead of running them sequentially. This is an **orchestrator-level optimization** — the per-task pipeline (`task-pipeline.yaml`) is unchanged; only the execution order differs.
|
|
794
850
|
|
|
795
851
|
**Decision framework:** `sp:parallel-execution` owns the full fan-out decision logic and patterns. Consult its [fan-out-patterns.md](../../parallel-execution/references/fan-out-patterns.md) before parallelizing. The orchestrator's responsibility is:
|
|
852
|
+
|
|
796
853
|
1. Identify the independent subset from the topo-sorted batch (tasks with no edges to each other).
|
|
797
854
|
2. Check for file-overlap conflicts (two tasks touching the same `file:line` range must serialize).
|
|
798
855
|
3. Verify token budget supports N-way fan-out.
|
|
@@ -803,7 +860,6 @@ When a batch contains tasks with **zero dependency edges between them** and **no
|
|
|
803
860
|
|
|
804
861
|
**See also:** `sp:parallel-execution` skill, `sp:super-planner` agent (parallel mode), `/sp:dev-parallel` command.
|
|
805
862
|
|
|
806
|
-
|
|
807
863
|
## Subagent execution disciplines
|
|
808
864
|
|
|
809
865
|
Parallel fan-out and any subagent dispatch obey the four disciplines owned by
|
|
@@ -32,14 +32,16 @@ command, skill, script, or second workflow.
|
|
|
32
32
|
`host-session-<run-id>` and record that fallback in the log; provenance must never be blank or
|
|
33
33
|
guessed from an executor subprocess.
|
|
34
34
|
4. Render the two-layer plan into the host todo list (task 0596):
|
|
35
|
-
- **Layer 1** =
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
- **Layer 1** = `spur workflow show <pipeline-yaml> --format todo --json` → its `steps[]`: the
|
|
36
|
+
declared state inventory in declaration order with `initial` / `terminal` / `failure` /
|
|
37
|
+
`pause` / `loopBack` / `conditional` markers. Mark the active state. Never re-derive this
|
|
38
|
+
list from the YAML.
|
|
39
|
+
- **Layer 2** = the active state's `onEnter` actions (`kind` + resolved `input`/`command`), from
|
|
40
|
+
the YAML parsed in step 1, shown only for the active state.
|
|
39
41
|
- **Refresh cadence** = stage boundaries only (when the current state changes after a transition),
|
|
40
42
|
never per action.
|
|
41
|
-
- **Source of truth** = the
|
|
42
|
-
state list into the driver, a command, a skill, or a script.
|
|
43
|
+
- **Source of truth** = the CLI projection for layer 1; the YAML parsed in step 1 for layer 2.
|
|
44
|
+
Never hand-copy or hand-derive the state list into the driver, a command, a skill, or a script.
|
|
43
45
|
5. Record lifecycle provenance before entering the FSM:
|
|
44
46
|
|
|
45
47
|
```bash
|