@gobing-ai/spur 0.3.77 → 0.3.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/templates/AGENTS.md +26 -23
  3. package/config/templates/docs/00_ADR.md +13 -23
  4. package/config/templates/docs/01_PRD.md +5 -2
  5. package/config/templates/docs/02_ROADMAP.md +9 -13
  6. package/config/templates/docs/03_ARCHITECTURE.md +2 -2
  7. package/config/templates/docs/04_DESIGN.md +12 -31
  8. package/config/templates/docs/05_FEATURES.md +6 -18
  9. package/config/templates/docs/99_PROJECT_CONSTITUTION.md +162 -394
  10. package/package.json +9 -9
  11. package/plugins/sp/README.md +12 -7
  12. package/plugins/sp/agents/super-reviewer.md +43 -8
  13. package/plugins/sp/commands/dev-refineall.md +1 -0
  14. package/plugins/sp/commands/dev-run.md +1 -0
  15. package/plugins/sp/commands/dev-runall.md +1 -0
  16. package/plugins/sp/commands/dev-verifyall.md +1 -0
  17. package/plugins/sp/plugin.json +1 -1
  18. package/plugins/sp/scripts/batch-preflight.mjs +173 -2
  19. package/plugins/sp/scripts/batch-preflight.ts +257 -2
  20. package/plugins/sp/scripts/verify-answer-lint.ts +32 -9
  21. package/plugins/sp/skills/conflict-finding/SKILL.md +6 -0
  22. package/plugins/sp/skills/daily-summary/SKILL.md +1 -1
  23. package/plugins/sp/skills/doc-evolve/SKILL.md +26 -40
  24. package/plugins/sp/skills/doc-evolve/references/operations.md +17 -30
  25. package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +17 -1
  26. package/plugins/sp/skills/spur-cli/references/tasks.md +31 -1
  27. package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +14 -0
  28. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +36 -3
  29. package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +12 -0
  30. package/plugins/sp/skills/spur-dev/references/execution-batch.md +17 -0
  31. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +148 -17
  32. package/spur.js +1389 -615
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/spur",
3
- "version": "0.3.77",
3
+ "version": "0.3.80",
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.57",
57
- "@gobing-ai/ts-ai-runner": "^0.4.57",
58
- "@gobing-ai/ts-dual-workflow-engine": "^0.4.57",
59
- "@gobing-ai/ts-infra": "^0.4.57",
60
- "@gobing-ai/ts-llm-jsonl-importer": "^0.4.57",
61
- "@gobing-ai/ts-rule-engine": "^0.4.57",
62
- "@gobing-ai/ts-runtime": "^0.4.57",
63
- "@gobing-ai/ts-utils": "^0.4.57",
56
+ "@gobing-ai/ts-db": "^0.4.62",
57
+ "@gobing-ai/ts-ai-runner": "^0.4.62",
58
+ "@gobing-ai/ts-dual-workflow-engine": "^0.4.62",
59
+ "@gobing-ai/ts-infra": "^0.4.62",
60
+ "@gobing-ai/ts-llm-jsonl-importer": "^0.4.62",
61
+ "@gobing-ai/ts-rule-engine": "^0.4.62",
62
+ "@gobing-ai/ts-runtime": "^0.4.62",
63
+ "@gobing-ai/ts-utils": "^0.4.62",
64
64
  "@types/bun": "1.3.14",
65
65
  "@types/figlet": "^1.7.0",
66
66
  "@types/node-notifier": "8.0.5",
@@ -171,10 +171,12 @@ Commands above are thin wrappers; the actual logic lives in `skills/`. The spine
171
171
  dispatches five competency skills by function — design (`sp:sys-architecture`), decomposition
172
172
  (`sp:spec-decomposition`), implementation (`sp:code-implementation`), testing (`sp:code-testing`),
173
173
  and verification (`sp:code-verification`) — plus a CLI facade (`sp:spur-cli`, one reference per
174
- `spur` noun) and standalone technique skills (`sp:next-router`, `sp:test-driven-development`, `sp:brainstorm`,
175
- `sp:wayfinder`, `sp:sys-debugging`, `sp:code-review`, `sp:code-simplification`, `sp:code-improvement`,
176
- `sp:parallel-execution`, `sp:branch-workflow`, `sp:doc-evolve`, `sp:dogfood-testing`,
177
- `sp:daily-summary`, `sp:reverse-engineering`, `sp:issue-finding`, `sp:conflict-finding`,
174
+ `spur` noun) and standalone technique skills (`sp:next-router`, `sp:next-feature`,
175
+ `sp:test-driven-development`, `sp:source-driven-development`, `sp:doubt-driven-development`,
176
+ `sp:brainstorm`, `sp:wayfinder`, `sp:sys-debugging`, `sp:code-review`, `sp:pr-reviewing`,
177
+ `sp:functional-review`, `sp:code-simplification`, `sp:code-improvement`, `sp:parallel-execution`,
178
+ `sp:branch-workflow`, `sp:doc-evolve`, `sp:dogfood-testing`, `sp:daily-summary`,
179
+ `sp:reverse-engineering`, `sp:history-anatomy`, `sp:issue-finding`, `sp:conflict-finding`,
178
180
  `sp:indexed-context`, `sp:session-review`, `sp:redesign-web-ui`). See
179
181
  [skills/spur-dev/SKILL.md](skills/spur-dev/SKILL.md)'s Step routing table for which skill owns which
180
182
  pipeline step.
@@ -215,6 +217,7 @@ plugins/sp/
215
217
  │ │ └── references/routing-table.md
216
218
  │ ├── parallel-execution/ # Fan-out decision framework + patterns
217
219
  │ │ └── references/{fan-out-patterns, result-synthesis}.md
220
+ │ ├── pr-reviewing/ # GitHub PR review loop backing /sp:dev-pr-review
218
221
  │ ├── source-driven-development/ # Source-first API/contract verification (SKILL.md only)
219
222
  │ ├── spec-decomposition/ # Feature/spec → task-batch competency
220
223
  │ │ └── references/decomposition.md
@@ -255,6 +258,8 @@ plugins/sp/
255
258
  ├── agents/ # 4 specialist subagents (expert-spur, super-coder, super-planner, super-reviewer)
256
259
  ├── hooks/ # hooks.json + task-write-guard.{ts,test.ts} + context-{session-start,post-tool,session-stop}.ts
257
260
  │ # + careful-guard.{ts,test.ts} + context-hooks.test.ts + token-estimate.test.ts
261
+ │ # + shared policy modules: agent-hint.ts, destructive-policy.{ts,test.ts}, task-file-policy.{ts,test.ts}
262
+ │ # + pi/guard-extension.{ts,test.ts} (plugin.json `extensions.pi` entry point)
258
263
  ├── scripts/ # Executable helpers, split from prompts (ADR-031) — validate-commands.ts (thin-wrapper validator), batch-preflight.ts + scripts/<skill>/
259
264
  │ # (daily-summary: {daily-summary, logger}.ts; dogfood-testing: {detect-pipeline-driving, validate-report}.ts)
260
265
  ├── tests/ # Plugin tests — command-contract.test.ts + skill-structure.test.ts + batch-preflight.test.ts + per-skill suites
@@ -318,13 +323,13 @@ surface or run one workflow. All skills target the same five core platforms: `cl
318
323
  | `daily-summary` | 1.0.0 | Daily summary report generator — orchestrates ccusage CLI + git history into structured markdown summaries |
319
324
  | `doc-evolve` | 1.0 | Key-document evolution per `docs/99_PROJECT_CONSTITUTION.md` — drift audits, same-commit sync checks, frontmatter-contract verification, machine-appended lessons |
320
325
  | `reverse-engineering` | 1.1 | Codebase analysis / HLD generation / audit — depth-driven reverse engineering with orthogonal mode, focus, and format controls; backs `/sp:dev-reverse` |
321
- | `issue-finding` | 1.1 | Session-log forensics — multi-source discovery, bottleneck ranking, optional topic focus, CLI-gated fix task generation; **legacy path** — superseded by `history-anatomy` for indexed reporting; backs no current command; directly invocable as sp:issue-finding |
326
+ | `issue-finding` | 2.0 | Session-log forensics — multi-source discovery, bottleneck ranking, optional topic focus, CLI-gated fix task generation; **legacy path** — superseded by `history-anatomy` for indexed reporting; backs no current command; directly invocable as sp:issue-finding |
322
327
  | `conflict-finding` | 1.0 | Authority-aware semantic audit — four-pillar (source/task/feature/authority) conflict discovery, claim-specific authority resolution, reproducible evidence, confirmed owner-routed remediation; backs `/sp:dev-find-conflict` |
323
328
  | `next-feature` | 1.0 | Prompt-first feature frontier prioritizer — sync-first precondition, B3 actionability gate (cited, never restated), tiered rubric over measured signals, D1–D4 defect proposals conforming to the restructure map schema; backs `/sp:dev-find-next` |
324
329
  | `pr-reviewing` | 1.0 | GitHub Codex PR review — PR prepare/reuse, `@codex review` request with per-HEAD dedupe, bounded polling, findings normalization, validated fix + re-review; spine SSOT `pr-review.yaml` + `scripts/pr-reviewing.ts`; backs `/sp:dev-pr-review` |
325
330
  | `indexed-context` | 1.0 | Cross-agent project context — anatomy/learnings/pitfalls/buglog/memory in `.spur/context/`; hook-tracked token-ledger; graceful degradation on agents without hooks |
326
331
  | `history-anatomy` | 1.0 | Diagnostic interpretation owner over already-imported history — daily/ad-hoc mode contract, closed finding taxonomy, twelve-section report contract, `enrich`/`validate` rubrics; no workflow launch, no JSONL fallback, no corpus mutation |
327
- | `session-review` | 1.0 | Inline review of the active coding-agent session — compact outcomes, evidence-backed resolved/open issue classification, proposal-only improvements, and next actions; no workflow, import, delegation, or mutation |
332
+ | `session-review` | 1.1 | Inline review of the active coding-agent session — compact outcomes, evidence-backed resolved/open issue classification, proposal-only improvements, and next actions; no workflow, import, delegation, or mutation |
328
333
  | `redesign-web-ui` | 1.0 | Existing-UI visual upgrade — audit generic AI fingerprints, apply in-stack polish against `DESIGN.md` / live tokens, verify behavior and viewports; does not migrate frameworks |
329
334
 
330
335
  #### Bounded coexistence and retirement gate — `sp:issue-finding` (HA-S1 0661)
@@ -418,7 +423,7 @@ the pipeline's Phase 7 review step.
418
423
  | ---------------- | ------------ | ----------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------- |
419
424
  | `expert-spur` | expert | `sp:spur-cli` | green | "create tasks", "feature lifecycle", "add a rule", "author a workflow" |
420
425
  | `super-coder` | builder | `sp:sys-architecture` + `sp:code-implementation` + `sp:code-testing` + `sp:sys-debugging` | blue | "implement this", "write the code", "fix this bug", "design the architecture" |
421
- | `super-planner` | orchestrator | `sp:spur-dev` + `sp:dogfood-testing` | green | "run this task end to end", "run all tasks", "run the batch", "runall" |
426
+ | `super-planner` | orchestrator | `sp:spur-dev` + `sp:parallel-execution` + `sp:dogfood-testing` + `sp:next-router` | green | "run this task end to end", "run all tasks", "run the batch", "runall" |
422
427
  | `super-reviewer` | reviewer | `sp:code-verification` + `sp:functional-review` + `sp:code-improvement` | crimson | "review this", "check the code", "SECUA review", "run task 0042 through review" |
423
428
 
424
429
  Each agent has:
@@ -97,7 +97,8 @@ HITL gate unless `--auto` was passed.
97
97
  - [ ] Establish scope first: WBS mode (task diff) or path mode (source glob). Derive the diff
98
98
  scope the same way `sp:code-verification` Step 3 does.
99
99
  - [ ] Dispatch each requested dimension to its owning skill — do not inline the review logic.
100
- - [ ] Merge findings into a single ranked report (severity: blocker > major > minor > advisory).
100
+ - [ ] Merge findings into a single ranked report, emitting native priority cells
101
+ (`P1 (blocker)` > `P2 (major)` > `P3 (minor)` > `P4 (advisory)` — see Output Format).
101
102
  - [ ] In pipeline mode, write the merged report to the task's `## Review` section via
102
103
  `spur task update <wbs> --section Review --from-file`; in standalone mode, emit as output.
103
104
  - [ ] Cite `file:line` evidence for every finding — no vague "implemented correctly."
@@ -109,6 +110,8 @@ HITL gate unless `--auto` was passed.
109
110
  - [ ] Never edit `task-pipeline.yaml` or reach into a pipeline step.
110
111
  - [ ] Never auto-approve a HITL gate unless `--auto` was passed.
111
112
  - [ ] Never soften a FAIL to PARTIAL, or PARTIAL to PASS, to avoid surfacing.
113
+ - [ ] Never emit a word-only Severity cell, an empty priority scaffold, or a `##`/`###` heading
114
+ inside a `### Review` body — all three fail the existing checkers.
112
115
  - [ ] Never skip a dimension the operator requested with `--focus`.
113
116
 
114
117
  ## Definition of Done Housekeeping
@@ -120,22 +123,44 @@ enforcement checklist. Reference:
120
123
 
121
124
  ## Output Format
122
125
 
126
+ ### Priority vocabulary (task 0818 R3)
127
+
128
+ Emit priorities **natively** — the consumer (`hasPopulatedPriorityTable`,
129
+ `packages/app/src/services/task-check.ts`) requires a `P1`–`P4` cell, and a word-only severity cell
130
+ fails it. One explicit mapping, no transcription step anywhere downstream:
131
+
132
+ | Priority cell | Severity | Meaning |
133
+ | --- | --- | --- |
134
+ | `P1 (blocker)` | blocker | Ships broken or unsafe; blocks the verdict |
135
+ | `P2 (major)` | major | Real defect or structural problem; must be dispositioned |
136
+ | `P3 (minor)` | minor | Localized issue; fix or accept explicitly |
137
+ | `P4 (advisory)` | advisory | Observation, non-blocking |
138
+
139
+ Severity words stay visible in the same cell — the mapping adds the machine-readable label, it does
140
+ not replace the semantics.
141
+
142
+ **Section-relative headings.** In pipeline mode the report body is written *into* the task's
143
+ `### Review` section, so every heading inside it MUST be `####` or deeper. A `##`/`###` heading in
144
+ the body becomes a new top-level task section and corrupts the document. In standalone mode
145
+ (emitted as output, not written to a task) the same body may be rendered one level shallower.
146
+
123
147
  ```markdown
124
- ## Review Report — <wbs|path>
148
+ #### Review Report — <wbs|path>
125
149
 
126
150
  **Scope:** <wbs diff | path glob>
127
151
  **Dimensions:** functional, security, efficiency, correctness, usability, architecture
128
152
  **Verdict:** PASS | PARTIAL | FAIL
129
153
 
130
- ### Findings (ranked)
154
+ ##### Findings (ranked)
131
155
 
132
- | # | Severity | Dimension | Finding | Location |
156
+ | # | Priority | Dimension | Finding | Location |
133
157
  |---|----------|-----------|---------|----------|
134
- | 1 | blocker | security | SQL injection in query builder | `src/api/users.ts:42` |
135
- | 2 | major | architecture | Shallow pass-through UserService | `src/services/users.ts:15` |
136
- | 3 | minor | correctness | Missing error branch in createUser | `src/api/users.ts:48` |
158
+ | 1 | P1 (blocker) | security | SQL injection in query builder | `src/api/users.ts:42` |
159
+ | 2 | P2 (major) | architecture | Shallow pass-through UserService | `src/services/users.ts:15` |
160
+ | 3 | P3 (minor) | correctness | Missing error branch in createUser | `src/api/users.ts:48` |
161
+ | 4 | P4 (advisory) | usability | `createUser` error text omits the field name | `src/api/users.ts:51` |
137
162
 
138
- ### Functional Traceability
163
+ ##### Functional Traceability
139
164
 
140
165
  | Req | Status | Evidence |
141
166
  |-----|--------|----------|
@@ -145,6 +170,16 @@ enforcement checklist. Reference:
145
170
  **Next:** <one-line action>
146
171
  ```
147
172
 
173
+ **No findings.** Never invent a defect to populate the table. Emit one substantive `P4 (advisory)`
174
+ row that states what was reviewed and what was found — placeholder cells (empty, `—`, `n/a`) are
175
+ rejected by the checker, and so they should be:
176
+
177
+ ```markdown
178
+ | # | Priority | Dimension | Finding | Location |
179
+ |---|----------|-----------|---------|----------|
180
+ | 1 | P4 (advisory) | — | No P1–P3 findings: 6 changed files reviewed across all six dimensions; R1–R3 traceable to tests | `packages/app/src/workflow/proof-input-fingerprint.ts:102-160` |
181
+ ```
182
+
148
183
  With `--json`, emit the same shape as a JSON object for machine consumption.
149
184
 
150
185
  ## Out of scope
@@ -62,5 +62,6 @@ thread `--depth` into each per-task refine.
62
62
  ## Implementation
63
63
 
64
64
  - Apply the [inline-default execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface).
65
+ - Apply the [shared startup contract](../skills/spur-dev/references/cross-cutting.md#shared-startup-contract-task-0814-r1r3r4r6r7r8) — bootstrap checklist, quick readiness before isolation, workflow inventory before YAML, comprehensive checks at owning boundaries (task 0814 R1/R3/R4/R7/R8).
65
66
  - Batch orchestration: `Skill(skill="sp:spur-dev", args="refineall $ARGUMENTS")`
66
67
  - Per-task refine (inner): `Skill(skill="sp:spur-dev", args="refine <wbs> $SHARED_FLAGS")`
@@ -31,6 +31,7 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
31
31
  ## Implementation
32
32
 
33
33
  - Apply the [inline-default execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface).
34
+ - Apply the [shared startup contract](../skills/spur-dev/references/cross-cutting.md#shared-startup-contract-task-0814-r1r3r4r6r7r8) — bootstrap checklist, quick readiness before isolation, workflow inventory before YAML, comprehensive checks at their owning boundaries (task 0814 R1/R3/R4/R7/R8).
34
35
  - Full pipeline (default `--mode full`): interactive omit/`--agent inline` uses the
35
36
  [inline pipeline driver](../skills/spur-dev/references/inline-pipeline-driver.md) via
36
37
  `Skill(skill="sp:spur-dev", args="run-inline $ARGUMENTS")`; `--agent auto` or a named executor
@@ -82,5 +82,6 @@ full distinction.
82
82
  ## Implementation
83
83
 
84
84
  - 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); the resolved selector applies uniformly — eligible `agent.run` stages dispatch once to a native subagent with host fallback (0508). `--agent auto`, a name, or parallel mode retains the isolated per-task workflow boundary.
85
+ - Apply the [shared startup contract](../skills/spur-dev/references/cross-cutting.md#shared-startup-contract-task-0814-r1r3r4r6r7r8) — bootstrap checklist, quick readiness before isolation, workflow inventory before YAML, comprehensive checks at owning boundaries (task 0814 R1/R3/R4/R7/R8).
85
86
  - Interactive sequential omit/inline: `Skill(skill="sp:spur-dev", args="runall-inline $ARGUMENTS")`.
86
87
  - Explicit executor or parallel mode: `Skill(skill="sp:spur-dev", args="runall $ARGUMENTS")` → `sp:super-planner` agent.
@@ -68,6 +68,7 @@ Without `--fix all`, shippable is not evaluated (optional note: use `--fix all`
68
68
  ## Implementation
69
69
 
70
70
  - Apply the [inline-default execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface).
71
+ - Apply the [shared startup contract](../skills/spur-dev/references/cross-cutting.md#shared-startup-contract-task-0814-r1r3r4r6r7r8) — bootstrap checklist, quick readiness before isolation, workflow inventory before YAML, comprehensive checks at owning boundaries (task 0814 R1/R3/R4/R7/R8).
71
72
  - Batch orchestration: `Skill(skill="sp:spur-dev", args="verifyall $ARGUMENTS")`
72
73
  - Per-task verification (inner): `Skill(skill="sp:code-verification", args="verify <wbs> $SHARED_FLAGS")`
73
74
  - Shippable gate: once after the batch (same skill § Shippable readiness gate)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sp",
3
- "version": "0.3.77",
3
+ "version": "0.3.80",
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"]
@@ -3,6 +3,119 @@ import { createRequire } from "node:module";
3
3
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
4
4
 
5
5
  // plugins/sp/scripts/batch-preflight.ts
6
+ function quickReadiness(input) {
7
+ const status = (input.status ?? "").toLowerCase();
8
+ const operation = input.operation;
9
+ if (operation !== "run" && operation !== "refine" && operation !== "verify") {
10
+ return {
11
+ action: "invalid",
12
+ code: "IV",
13
+ reason: `quick-readiness: unknown operation '${operation}' (${input.wbs})`
14
+ };
15
+ }
16
+ if (input.filteredCount !== undefined) {
17
+ if (input.filteredCount < 0) {
18
+ return {
19
+ action: "invalid",
20
+ code: "IV",
21
+ reason: `quick-readiness: invalid negative filtered count '${input.filteredCount}' (${input.wbs})`
22
+ };
23
+ }
24
+ if (input.filteredCount === 0) {
25
+ return {
26
+ action: "skipped",
27
+ code: "EMPTY",
28
+ reason: `quick-readiness: empty status-filtered set — nothing to ${operation} (${input.wbs})`
29
+ };
30
+ }
31
+ }
32
+ if (status === "cancelled" || status === "done") {
33
+ if (operation === "verify" && input.force === true) {
34
+ return {
35
+ action: "runnable",
36
+ code: "FORCE",
37
+ reason: `quick-readiness: verify --force re-verification of ${status} task ${input.wbs}`
38
+ };
39
+ }
40
+ return {
41
+ action: "skipped",
42
+ code: status === "done" ? "DONE" : "CANCELLED",
43
+ reason: `quick-readiness: already ${status} — no ${operation} hop (${input.wbs})`
44
+ };
45
+ }
46
+ if (status === "blocked") {
47
+ return {
48
+ action: "blocked",
49
+ code: "BLK",
50
+ reason: `quick-readiness: blocked — human/handover first (${input.wbs})`
51
+ };
52
+ }
53
+ if (operation === "run" && input.dependencies && input.dependencies.length > 0) {
54
+ const unmet = input.dependencies.filter((d) => (input.depStatuses?.[d] ?? "missing").toLowerCase() !== "done");
55
+ if (unmet.length > 0) {
56
+ return {
57
+ action: "blocked",
58
+ code: "DEP",
59
+ reason: `quick-readiness: unmet deps — ${unmet.join(", ")} (${input.wbs})`,
60
+ unmetDeps: unmet
61
+ };
62
+ }
63
+ }
64
+ const required = input.requiredSections ?? [];
65
+ const present = input.presentSections ?? [];
66
+ const gaps = required.filter((s) => {
67
+ const finding = input.sectionFindings?.[s];
68
+ return !present.includes(s) || finding !== undefined && finding !== "";
69
+ });
70
+ if (operation === "refine") {
71
+ if (status !== "backlog" && status !== "todo") {
72
+ return {
73
+ action: "skipped",
74
+ code: "NONPLAN",
75
+ reason: `quick-readiness: refine targets backlog/todo only, not '${status}' (${input.wbs})`
76
+ };
77
+ }
78
+ return {
79
+ action: "runnable",
80
+ code: "OK",
81
+ reason: `quick-readiness: refine ready for ${input.wbs} (${gaps.length} planning gap(s) to fill)`
82
+ };
83
+ }
84
+ if (operation === "verify") {
85
+ if (status !== "testing" && status !== "wip") {
86
+ return {
87
+ action: "invalid",
88
+ code: "NOVERIFY",
89
+ reason: `quick-readiness: verify needs testing/wip, not '${status}' (${input.wbs})`
90
+ };
91
+ }
92
+ return {
93
+ action: "runnable",
94
+ code: "OK",
95
+ reason: `quick-readiness: verify ready for ${input.wbs}`
96
+ };
97
+ }
98
+ if (status !== "todo" && status !== "wip" && status !== "testing") {
99
+ return {
100
+ action: "invalid",
101
+ code: "NORUN",
102
+ reason: `quick-readiness: run needs todo/wip/testing, not '${status}' (${input.wbs})`
103
+ };
104
+ }
105
+ if (gaps.length > 0) {
106
+ return {
107
+ action: "needs-refinement",
108
+ code: "REFINE",
109
+ reason: `quick-readiness: implementation sections incomplete (${input.wbs})`,
110
+ gaps
111
+ };
112
+ }
113
+ return {
114
+ action: "runnable",
115
+ code: "OK",
116
+ reason: `quick-readiness: run ready for ${input.wbs}`
117
+ };
118
+ }
6
119
  function preflightTask(input) {
7
120
  const status = (input.status ?? "").toLowerCase();
8
121
  const deps = input.dependencies ?? [];
@@ -72,6 +185,11 @@ function parsePreflightCliArgs(argv) {
72
185
  let recovery = false;
73
186
  let help = false;
74
187
  let json = false;
188
+ let operation = null;
189
+ let force = false;
190
+ let filteredCount = null;
191
+ let requiredSections = [];
192
+ let presentSections = [];
75
193
  for (let i = 0;i < argv.length; i++) {
76
194
  const a = argv[i];
77
195
  if (a === "--help" || a === "-h")
@@ -80,7 +198,21 @@ function parsePreflightCliArgs(argv) {
80
198
  json = true;
81
199
  else if (a === "--recovery")
82
200
  recovery = true;
83
- else if (a === "--wbs")
201
+ else if (a === "--force")
202
+ force = true;
203
+ else if (a === "--operation") {
204
+ const v = argv[++i] ?? "";
205
+ operation = v === "run" || v === "refine" || v === "verify" ? v : null;
206
+ } else if (a === "--filtered-count") {
207
+ const v = Number(argv[++i]);
208
+ filteredCount = Number.isFinite(v) ? v : null;
209
+ } else if (a === "--required-sections") {
210
+ const raw = argv[++i] ?? "";
211
+ requiredSections = raw.length === 0 ? [] : raw.split(",").map((s) => s.trim()).filter(Boolean);
212
+ } else if (a === "--present-sections") {
213
+ const raw = argv[++i] ?? "";
214
+ presentSections = raw.length === 0 ? [] : raw.split(",").map((s) => s.trim()).filter(Boolean);
215
+ } else if (a === "--wbs")
84
216
  wbs = argv[++i] ?? wbs;
85
217
  else if (a === "--status")
86
218
  status = argv[++i] ?? null;
@@ -96,11 +228,25 @@ function parsePreflightCliArgs(argv) {
96
228
  }
97
229
  }
98
230
  }
99
- return { status, deps, depStatuses, wbs, recovery, help, json };
231
+ return {
232
+ status,
233
+ deps,
234
+ depStatuses,
235
+ wbs,
236
+ recovery,
237
+ help,
238
+ json,
239
+ operation,
240
+ force,
241
+ filteredCount,
242
+ requiredSections,
243
+ presentSections
244
+ };
100
245
  }
101
246
  var PREFLIGHT_CLI_USAGE = `Usage:
102
247
  bun plugins/sp/scripts/batch-preflight.ts --wbs <wbs> --status <status> \\
103
248
  [--deps 0275,0276] [--dep-status 0275:done,0276:todo] [--recovery] [--json]
249
+ bun plugins/sp/scripts/batch-preflight.ts --operation <run|refine|verify> --wbs <wbs> --status <status> [--filtered-count <n>] [--required-sections A,B] [--present-sections A,B] [--force] [--json]
104
250
 
105
251
  Exit: 0 = run (or recovery hint printed); 2 = skip; 1 = usage.`;
106
252
  function runPreflightCli(argv) {
@@ -117,6 +263,30 @@ function runPreflightCli(argv) {
117
263
  `;
118
264
  return { exitCode: 0, stdout: body, stderr: "" };
119
265
  }
266
+ if (args.operation !== null) {
267
+ const result2 = quickReadiness({
268
+ wbs: args.wbs,
269
+ status: args.status,
270
+ operation: args.operation,
271
+ dependencies: args.deps,
272
+ depStatuses: args.depStatuses,
273
+ ...args.filteredCount !== null ? { filteredCount: args.filteredCount } : {},
274
+ ...args.requiredSections.length > 0 ? { requiredSections: args.requiredSections } : {},
275
+ ...args.presentSections.length > 0 ? { presentSections: args.presentSections } : {},
276
+ ...args.force ? { force: true } : {}
277
+ });
278
+ const runnable = result2.action === "runnable" || result2.action === "needs-refinement";
279
+ if (args.json) {
280
+ return { exitCode: runnable ? 0 : 2, stdout: `${JSON.stringify(result2, null, 2)}
281
+ `, stderr: "" };
282
+ }
283
+ return {
284
+ exitCode: runnable ? 0 : 2,
285
+ stdout: `${result2.action}${result2.code ? ` ${result2.code}` : ""}: ${result2.reason}
286
+ `,
287
+ stderr: ""
288
+ };
289
+ }
120
290
  const result = preflightTask({
121
291
  wbs: args.wbs,
122
292
  status: args.status,
@@ -154,6 +324,7 @@ function runPreflightCli(argv) {
154
324
  export {
155
325
  runPreflightCli,
156
326
  recoveryHint,
327
+ quickReadiness,
157
328
  preflightTask,
158
329
  parsePreflightCliArgs,
159
330
  PREFLIGHT_CLI_USAGE