@gordon.gan/specflow 1.5.0-beta → 1.8.0-beta

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 (41) hide show
  1. package/README.md +2 -2
  2. package/dist/cli/commands/approval-assemble.d.ts +48 -5
  3. package/dist/cli/commands/approval-assemble.js +347 -34
  4. package/dist/core/approval/assemble.js +15 -22
  5. package/dist/core/approval/bundle.d.ts +9 -0
  6. package/dist/core/approval/bundle.js +172 -0
  7. package/dist/core/approval/forbidden-patterns.d.ts +6 -0
  8. package/dist/core/approval/forbidden-patterns.js +40 -0
  9. package/dist/core/approval/index-schema.d.ts +203 -0
  10. package/dist/core/approval/index-schema.js +47 -0
  11. package/dist/core/approval/index.d.ts +10 -2
  12. package/dist/core/approval/index.js +7 -1
  13. package/dist/core/approval/lint.d.ts +10 -0
  14. package/dist/core/approval/lint.js +302 -0
  15. package/dist/core/approval/paths.d.ts +5 -0
  16. package/dist/core/approval/paths.js +15 -0
  17. package/dist/core/approval/pipeline.d.ts +28 -0
  18. package/dist/core/approval/pipeline.js +146 -0
  19. package/dist/core/approval/playbook-schema.d.ts +182 -0
  20. package/dist/core/approval/playbook-schema.js +51 -0
  21. package/dist/core/approval/render.d.ts +20 -0
  22. package/dist/core/approval/render.js +210 -0
  23. package/dist/core/approval/review-pack.d.ts +26 -0
  24. package/dist/core/approval/review-pack.js +205 -0
  25. package/dist/core/approval/types.d.ts +103 -0
  26. package/dist/integrations/shared/capability-evidence.js +3 -0
  27. package/dist/integrations/shared/parity-manifest.js +3 -0
  28. package/package.json +2 -1
  29. package/prompts/approval/acp-pipeline.md +106 -0
  30. package/prompts/approval/ai-review.md +145 -0
  31. package/prompts/approval/generate.md +107 -9
  32. package/prompts/approval/multi-repo-guidance.md +71 -10
  33. package/prompts/approval/multi-repo-spoke-subagent.md +94 -0
  34. package/prompts/approval/runtime-guidance.md +64 -0
  35. package/prompts/approval/segmented-generation.md +14 -8
  36. package/skills/GUIDANCE_PACKS.md +1 -1
  37. package/skills/specflow-approval/SKILL.md +160 -22
  38. package/templates/approval-index.yaml +25 -4
  39. package/templates/approval-part.md +1 -1
  40. package/templates/approval-playbook-talos-scenario-job-compile.yaml +29 -0
  41. package/templates/approval-playbook.yaml +28 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gordon.gan/specflow",
3
- "version": "1.5.0-beta",
3
+ "version": "1.8.0-beta",
4
4
  "type": "module",
5
5
  "description": "SpecFlow — unified spec-driven development: OpenSpec planning + Superpowers execution in one CLI and cross-IDE workflow",
6
6
  "keywords": [
@@ -58,6 +58,7 @@
58
58
  "chalk": "^5.4.1",
59
59
  "commander": "^13.1.0",
60
60
  "js-yaml": "^4.1.0",
61
+ "marked": "^15.0.12",
61
62
  "zod": "^3.24.4"
62
63
  },
63
64
  "devDependencies": {
@@ -0,0 +1,106 @@
1
+ # Approval · ACP Pipeline (Approval Compiler Pipeline)
2
+
3
+ > Router for `/specflow:approval` **Stage 12** when `acp.pipeline=acp/v2` (recommended for non-lightweight changes).
4
+ > Legacy segmented flow remains valid; ACP adds **lint**, **AI review**, and **bundle** gates.
5
+
6
+ ---
7
+
8
+ ## Pipeline (hard order)
9
+
10
+ ```text
11
+ Phase 1 Analyze → analysis.json + IR planner (chat gate)
12
+ Phase 2 IR Freeze → index.yaml (+ interfaces[].frozen, feature_slices, acp.review)
13
+ Phase 3 Skeleton → parts 01–03, 04-detail-core, 06/09/10
14
+ Phase 4 Slot Map → batched parts 04.4–04.9 (vertical slice first)
15
+ Phase 5 AI Review → Stage 12e in-session (prompts/approval/ai-review.md) — **inside /specflow-approval**
16
+ Phase 6 finalize → specflow approval finalize <change> [--bundle] [--render]
17
+ Phase 7 render → specflow approval render <change> [--input] [--output]
18
+
19
+ **Preferred**: one `finalize` after Map + AI review. Subcommands (`lint`, `assemble`, …) are for CI/debug only.
20
+ ```
21
+
22
+ **Never** skip Phase 6a–6b with LLM paste. **Never** write `approval-unified.md` by hand when bundle is enabled.
23
+
24
+ ---
25
+
26
+ ## index.yaml ACP block
27
+
28
+ ```yaml
29
+ acp:
30
+ pipeline: acp/v2
31
+ context_budget_tokens: 40000
32
+ output_budget_tokens: 8000
33
+ feature_slices:
34
+ - id: step-reporting
35
+ parts: [04.5-api-worker, 04.5-api-east, 04-detail-core]
36
+ interfaces: [I13, I14, I16, I17]
37
+ review:
38
+ enabled: true
39
+ required_pass: true
40
+ ```
41
+
42
+ ## interfaces[].frozen (IR freeze before Map)
43
+
44
+ ```yaml
45
+ interfaces:
46
+ - id: I14
47
+ short: SubmitStepResult
48
+ change: scenario-job-compile
49
+ part: 04.5-api-worker
50
+ pairs_with: I13
51
+ layers: [L3]
52
+ frozen:
53
+ rpc: scheduler.Scheduler.SubmitStepResult
54
+ http_path: POST /internal/v1/tasks/{job_id}/step-results
55
+ status_enum: [passed, failed, skipped, error]
56
+ ```
57
+
58
+ ---
59
+
60
+ ## Multi-repo default
61
+
62
+ - **True source**: `per_repo` — each repo `approval/` + `approval.md`
63
+ - **Read-only view**: `approval bundle` from `approval-playbook.yaml`
64
+ - Do **not** LLM-unify three repos into one primary `approval/parts`
65
+
66
+ See `multi-repo-guidance.md` + `templates/approval-playbook.yaml` (+ example `templates/approval-playbook-talos-scenario-job-compile.yaml`).
67
+
68
+ **Orchestration**: multi-repo mode A uses **Stage 1c** subagent parallel dispatch (`multi-repo-spoke-subagent.md`) — not a single-repo `finalize` across repos.
69
+
70
+ ---
71
+
72
+ ## Context packet (Map batch)
73
+
74
+ Read only:
75
+
76
+ 1. `index.yaml` subset for this batch (ids + frozen fields)
77
+ 2. `analysis.json` verdicts (not full Pass essays)
78
+ 3. design/spec **snippets** for batch entities
79
+ 4. 1–2 anchor files for this batch
80
+ 5. guidance router (path only, not full paste)
81
+
82
+ Do **not** reload entire four-artifact sets each batch.
83
+
84
+ ---
85
+
86
+ ## CLI reference
87
+
88
+ | Command | Purpose |
89
+ |---------|---------|
90
+ | `approval render` | MD → standalone HTML (tables, GFM, mermaid via CDN) |
91
+ | `approval finalize` | **Preferred** — full lint → review-check → check → assemble → bundle |
92
+ | `approval lint` | Cross-part consistency (CI / debug) |
93
+ | `approval review-pack` | Emit `review-packet.json` (debug; finalize auto-runs when needed) |
94
+ | `approval review-check` | Validate `review-result.json` (debug) |
95
+ | `approval check` | Part presence + lazy stub (debug) |
96
+ | `approval assemble` | Deterministic Reduce (debug) |
97
+ | `approval bundle` | Multi-repo readonly merge (debug; finalize can auto-run) |
98
+
99
+ ---
100
+
101
+ ## Related guidance
102
+
103
+ - `segmented-generation.md` — Map anti-lazy L1–L10
104
+ - `ai-review.md` — Stage 12e AI approval/revision
105
+ - `runtime-guidance.md` — optional async/lease/cancel (when in scope)
106
+ - `api-guidance.md` — optional multi-layer API contracts (when api_in_scope)
@@ -0,0 +1,145 @@
1
+ # Approval · Stage 12e AI Review (审批 / 修订)
2
+
3
+ > Runs **after** Map parts written, **before** `specflow approval finalize` completes.
4
+ > Purpose: catch **long-document / multi-part semantic drift** that mechanical lint cannot judge; **revise parts in place**.
5
+
6
+ **Scope**: checks apply to **any** segmented approval — not tied to a specific product, repo, or domain.
7
+ Use `index.yaml` + `analysis.json` as the contract; do not inject checks from unrelated case studies.
8
+
9
+ ---
10
+
11
+ ## 0. Trigger
12
+
13
+ Run when **any**:
14
+
15
+ - `acp.review.enabled=true` in `index.yaml` (default for non-lightweight)
16
+ - User asks for AI 审批 / 方案审查 / 一致性检查
17
+ - `specflow approval finalize` paused at `review-required`
18
+
19
+ ---
20
+
21
+ ## 1. Prep (hard)
22
+
23
+ ```bash
24
+ specflow approval finalize <change> # pauses + writes review-packet.json if needed
25
+ ```
26
+
27
+ Read:
28
+
29
+ - `approval/review-packet.json` (checklist + lint diagnostics)
30
+ - `approval/index.yaml` (inventory, design_points, frozen fields, parts_order)
31
+ - `approval/analysis.json` (Pass verdicts — gaps to close)
32
+ - **All** `approval/parts/*.md` in `parts_order`
33
+
34
+ Optional domain packs (only when design **actually** touches that topic):
35
+
36
+ - `runtime-guidance.md` — async job / lease / retry / cancel semantics
37
+ - `api-guidance.md` — multi-layer API contracts
38
+ - `frontend-guidance.md` — §4.6 depth
39
+
40
+ ---
41
+
42
+ ## 2. Review dimensions (long-document generic)
43
+
44
+ These target **failure modes of long, batched documents** — inconsistency across parts written at different times.
45
+
46
+ | ID | Category | Check (generic) |
47
+ |----|----------|-----------------|
48
+ | R1 | **Cross-part naming** | Same entity (service, table, interface, page, enum) uses **one** canonical name/id across §2, §4, diagrams, and `index.yaml`. No 「暂定 / 实现时 / 如 Xxx / TBD」 for listed inventory ids. |
49
+ | R2 | **Decision traceability** | Each `decisions[]` / §2 row appears in §4 with concrete behavior — not only repeated in summary. |
50
+ | R3 | **Inventory ↔ body** | Every `tables[]` / `interfaces[]` / `pages[]` / `design_points[]` entry in index has **substantive** content in its assigned `part`. No orphan ids; no body content for ids missing from index. |
51
+ | R4 | **Depth parity** | Parts in the same `feature_slices` or batch have **comparable** depth. No pattern of one part fully detailed while sibling parts are one-line stubs. |
52
+ | R5 | **Cross-reference integrity** | Internal refs use stable ids (`§4.5 I2`, `P3`, `Page·列表`, `T1`) — not bare 「详见 design/tasks」. Ref targets exist and match. |
53
+ | R6 | **Diagram ↔ prose** | Sequence / flow diagrams agree with adjacent prose (actors, message names, order, error branches). |
54
+ | R7 | **Contract completeness** | Each listed interface/page-api has minimum skeleton from Part E (fields, success example, **failure example**, error table) — depth scaled to `api_in_scope` / `ui_in_scope`. |
55
+ | R8 | **Enum / state closure** | Status, enum, and terminal-state sets are **explicit and closed** wherever the doc defines them — no 「等」 or open-ended lists unless explicitly extensible by design. |
56
+ | R9 | **Unclosed branches** | Every **mentioned** branch (retry, cancel, timeout, idempotency, rollback, concurrency) has a documented outcome — or is flagged `[待 refine 澄清: …]` with owner. Do **not** assume domain-specific branches (e.g. lease reclaim) unless design/analysis mentions them. |
57
+ | R10 | **UI ↔ API alignment** | When `ui_in_scope`: §4.6 field names, types, and api refs align with §4.5 / `pages[].apis`. |
58
+ | R11 | **Multi-repo parity** | When `multi_repo.enabled`: each repo slice in scope has proportionate depth; no 「主仓详、他仓 stub」 unless explicitly out of scope. |
59
+ | R12 | **Stub purge** | No `TODO` / `待补充` / `此处省略` / placeholder-only sections in parts slated for assemble. |
60
+ | R13 | **Verdict coherence** | §9 implementability / readiness matches §4 depth — no READY alongside unexplained NEEDS REFINEMENT or contradictory gates. |
61
+
62
+ **Not in default scope**: product-specific rules (talos lease wipe, ingest whitelist, L2/L3 layering) — load the matching guidance pack **only** when the change design requires it.
63
+
64
+ ---
65
+
66
+ ## 3. Revision rules (hard)
67
+
68
+ 1. **Edit `approval/parts/*.md` only** — never edit assembled `approval.md` directly
69
+ 2. **Update `index.yaml` first** when changing frozen ids, rpc names, or inventory
70
+ 3. Each finding → fix in named `part` OR waive (`minor` only) with `waiver_reason`
71
+ 4. Re-run:
72
+
73
+ ```bash
74
+ specflow approval finalize <change>
75
+ ```
76
+
77
+ ---
78
+
79
+ ## 4. Write review-result.json
80
+
81
+ Path: `approval/review-result.json`
82
+
83
+ ```json
84
+ {
85
+ "schema": "specflow.approval.review/v1",
86
+ "change": "<change-name>",
87
+ "reviewed_at": "2026-08-26T12:00:00Z",
88
+ "reviewer": "ai",
89
+ "verdict": "pass",
90
+ "summary": "Fixed cross-part naming for I3; expanded P2 error path in 04-detail-core",
91
+ "part_hashes": [
92
+ { "id": "04.5-api", "sha256": "<sha256-after-fixes>" },
93
+ { "id": "04-detail-core", "sha256": "<sha256-after-fixes>" }
94
+ ],
95
+ "findings": [
96
+ {
97
+ "id": "F1",
98
+ "severity": "critical",
99
+ "category": "cross_part_naming",
100
+ "message": "I3 RPC name differs between §2 and 04.5-api",
101
+ "part": "04.5-api",
102
+ "status": "fixed"
103
+ },
104
+ {
105
+ "id": "F2",
106
+ "severity": "important",
107
+ "category": "unclosed_branch",
108
+ "message": "Retry path mentioned in §4.3 but no terminal outcome",
109
+ "part": "04-detail-core",
110
+ "status": "fixed"
111
+ }
112
+ ]
113
+ }
114
+ ```
115
+
116
+ | verdict | When |
117
+ |---------|------|
118
+ | `pass` | All findings `fixed`; strict lint pass; **`part_hashes` match current parts** |
119
+ | `pass_with_waivers` | Only `minor` waived with `waiver_reason` |
120
+ | `fail` | Any `critical` / `important` still `open` |
121
+
122
+ **Waive policy**: only `minor` may be waived; critical/important must fix or escalate to user.
123
+
124
+ **part_hashes (required when `acp.review.enabled`)**: After fixing parts, run `specflow approval review-hashes <change> --json` and copy the array into `review-result.json`. `review-check` fails if parts change after review without updating review-result.
125
+
126
+ ---
127
+
128
+ ## 5. User gate
129
+
130
+ When a finding requires a **product/architecture choice** the artifacts do not resolve:
131
+
132
+ ```text
133
+ [待用户确认] <topic>: options A / B / C — record choice as new decision + update affected parts
134
+ ```
135
+
136
+ Stop finalize until user chooses; do not invent policy.
137
+
138
+ ---
139
+
140
+ ## 6. Announce
141
+
142
+ ```text
143
+ AI Review: findings=<n> fixed=<n> waived=<n> verdict=pass|fail
144
+ Next: specflow approval finalize <change>
145
+ ```
@@ -1412,7 +1412,8 @@ When `approval/index.yaml` has `mode: segmented` (default for non-trivial §4),
1412
1412
  2. **Gate** — user confirms index inventory + optional chapters + mode
1413
1413
  3. **12b Map Append** — batched `04.4*` / `04.5*` / `04.6*` / `04.7–04.9`
1414
1414
  4. **12c Optional** — `05*` / `07` / `08` only when opted in
1415
- 5. **12d CLI Reduce** — `specflow approval check` then `specflow approval assemble --force`
1415
+ 5. **12e AI Review** — fix parts; write `review-result.json` with `part_hashes` (see `ai-review.md`)
1416
+ 6. **12f Finalize** — `specflow approval finalize <change>` (lint → review-check → check → assemble → bundle)
1416
1417
 
1417
1418
  **Reduce 禁止 LLM** — never stitch parts in chat or paste from memory.
1418
1419
 
@@ -1420,7 +1421,7 @@ When `approval/index.yaml` has `mode: segmented` (default for non-trivial §4),
1420
1421
 
1421
1422
  | # | Forbidden | Required |
1422
1423
  |---|-----------|----------|
1423
- | L1 | One-shot full `approval.md` when `mode=segmented` | Write parts; CLI assemble |
1424
+ | L1 | One-shot full `approval.md` when `mode=segmented` | Write parts; `specflow approval finalize` |
1424
1425
  | L2 | Empty part, `< 20` chars, placeholder-only | Full section per Part E |
1425
1426
  | L3 | `TODO` / `待补充` / `此处省略` / bare `TBD` | Concrete text or `[待 refine 澄清: <元素>]` |
1426
1427
  | L4 | `详见 design/tasks` without §/In/Page id | Cross-ref `§4.5 I2` / `Page·列表` / `P1` |
@@ -1431,7 +1432,7 @@ When `approval/index.yaml` has `mode: segmented` (default for non-trivial §4),
1431
1432
  | L7 | Skip IDE skills/rules scan for §4.6 | `frontend-guidance.md` §3 before Map |
1432
1433
  | L8 | Paste skill/rule bodies verbatim | Readable Chinese + path in §4.6.1 |
1433
1434
  | L9 | Foreign `## N.` headings in parts | `###`/`####` only; CLI injects chapter headers |
1434
- | L10 | Mark done without `specflow approval check` passing | Fix diagnostics; then assemble |
1435
+ | L10 | Mark done without finalize passing | Fix diagnostics; run `specflow approval finalize` |
1435
1436
 
1436
1437
  CLI lazy validation mirrors L2–L3 (`lazy_part_content` on assemble/check).
1437
1438
 
@@ -1475,24 +1476,121 @@ User natural language, workset, or cross-repo design → `multi_repo.enabled=tru
1475
1476
 
1476
1477
  ### G.2 User gates (hard, before Stage 12a)
1477
1478
 
1478
- 1. **Document mode**: `unified` (一份合订) **or** `per_repo` (多份分仓).
1479
- 2. If **unified**: **主仓** `primary_repo` — only this repo holds `approval/` + final `approval.md`.
1480
- 3. Record in `index.yaml`; do not assemble until both answered.
1479
+ 1. **Document mode**: **A** bundle (per_repo + CLI bundle, recommended) **or** **B** per_repo only **or** **C** legacy unified LLM merge (discourage).
1480
+ 2. If **A or C**: **主仓** `primary_repo` — playbook/bundle or unified workspace path.
1481
+ 3. Record in `index.yaml`; set `acp.pipeline: acp/v2`; do not assemble until answered.
1481
1482
 
1482
- ### G.3 Unified 合订
1483
+ ### G.3 Bundle 合订视图 (recommended)
1484
+
1485
+ - Each repo: own `approval/` + `specflow approval assemble <repo.change>`.
1486
+ - Primary repo: `approval-playbook.yaml` + `specflow approval bundle <primary.change>`.
1487
+ - Output: `approval-unified.md` (readonly concatenation, no LLM merge).
1488
+
1489
+ ### G.4 Legacy unified LLM 合订 (discouraged)
1483
1490
 
1484
1491
  - Read **every** repo's four artifacts + anchors.
1485
1492
  - `index.change` **should equal** primary repo's change name.
1486
1493
  - Header lists all repos; §2.3 / 附录 B per-repo tables.
1487
1494
  - CLI: `specflow approval assemble <primary.change>` from **primary** planning root.
1488
1495
 
1489
- ### G.4 Per-repo 分仓
1496
+ ### G.5 Per-repo 分仓
1490
1497
 
1491
1498
  - Separate `approval/` (or monolithic `approval.md`) **in each repo**.
1492
1499
  - Each document scoped to that repo only; cross-ref sibling paths.
1493
1500
  - Separate assemble per repo.
1494
1501
 
1495
- ### G.5 Inventory
1502
+ ### G.6 Inventory
1496
1503
 
1497
1504
  Recommend `repo` on `tables[]` / `interfaces[]` / `pages[]` entries for unified mode traceability.
1498
1505
 
1506
+ ### G.7 主仓一键 · Subagent 并行 (mode A)
1507
+
1508
+ > Router: `prompts/approval/multi-repo-spoke-subagent.md` · Orchestrator: `skills/specflow-approval/SKILL.md` **Stage 1c**
1509
+
1510
+ When user starts `/specflow:approval` from **primary** repo and chose **A (bundle)**:
1511
+
1512
+ 1. Primary writes `approval-playbook.yaml`; spoke indexes set `bundle.enabled: false`.
1513
+ 2. **Parallel** Task subagents per non-primary repo → full spoke Map + 12e + `finalize` (no `--bundle`).
1514
+ 3. Primary **wait gate** — all spokes `finalize_ok`.
1515
+ 4. Primary Map + finalize + `finalize --bundle --workspace-root <primary.planning_root>`.
1516
+
1517
+ **Anti-lazy (multi-repo)**: no unified LLM merge when mode A chosen; no stub spoke parts (`见 design.md` rows without decision text); each spoke needs `analysis.json` + `review-result.json` when `acp.review.enabled`.
1518
+
1519
+ ---
1520
+
1521
+ ## Part H: ACP Pipeline (Approval Compiler Pipeline)
1522
+
1523
+ > Router: `prompts/approval/acp-pipeline.md` · AI review: `prompts/approval/ai-review.md`
1524
+
1525
+ ### H.1 When to use
1526
+
1527
+ | Signal | Action |
1528
+ |--------|--------|
1529
+ | Segmented mode (`approval/parts/`) | **Always** run ACP Verify before assemble |
1530
+ | Multi-repo bundle | per_repo assemble → `approval bundle` |
1531
+ | Long doc / cross-part inconsistency risk | Enable `acp.review` (Stage 12e) |
1532
+
1533
+ ### H.2 Pipeline stages
1534
+
1535
+ ```text
1536
+ Analyze (Pass 1–7) → IR Freeze (index.yaml + interfaces[].frozen)
1537
+ → Map (batched parts) → lint → review-pack → AI Review (12e) → review-check
1538
+ → check → assemble → bundle (optional)
1539
+ ```
1540
+
1541
+ ### H.3 index.yaml `acp` block
1542
+
1543
+ ```yaml
1544
+ acp:
1545
+ pipeline: acp/v2
1546
+ review:
1547
+ enabled: true
1548
+ required_pass: true # assemble --require-review gates on this
1549
+ ```
1550
+
1551
+ Also freeze RPC names in `interfaces[].frozen` before Map batches.
1552
+
1553
+ ### H.4 CLI
1554
+
1555
+ **Preferred (skill default)**:
1556
+
1557
+ ```bash
1558
+ specflow approval finalize <change> [--bundle] [--workspace-root <root>]
1559
+ ```
1560
+
1561
+ | Command | Purpose |
1562
+ |---------|---------|
1563
+ | `specflow approval review-hashes <change> [--json]` | Emit `part_hashes[]` for `review-result.json` |
1564
+ | `specflow approval finalize <change>` | One-shot: lint → review-check → check → assemble → bundle |
1565
+ | `specflow approval lint <change> [--strict]` | Debug / CI: cross-part consistency |
1566
+ | `specflow approval review-pack <change>` | Debug: generate review packet |
1567
+ | `specflow approval review-check <change>` | Debug: validate review-result |
1568
+ | `specflow approval check <change>` | Debug: parts/index validation |
1569
+ | `specflow approval assemble <change> [--require-review]` | Debug: merge parts only |
1570
+ | `specflow approval bundle <change>` | Debug: multi-repo readonly merge |
1571
+
1572
+ ### H.5 Stage 12e AI Review (mandatory when `acp.review.enabled`)
1573
+
1574
+ Runs **inside `/specflow-approval`** — not as separate user steps:
1575
+
1576
+ 1. `specflow approval finalize <change>` — pauses with `review-packet.json` if needed
1577
+ 2. Agent reads `prompts/approval/ai-review.md` + parts; fixes parts; writes `review-result.json`
1578
+ 3. Re-run `specflow approval finalize <change>`
1579
+
1580
+ AI review targets **long-document failure modes**: cross-part naming drift, inventory/body mismatch, depth imbalance across batches, unclosed branches, diagram/prose divergence, §4.6/§4.5 misalignment — not product-specific case rules.
1581
+
1582
+ Optional domain packs (`runtime-guidance.md`, `api-guidance.md`) apply **only when** design/analysis mentions those topics.
1583
+
1584
+ ### H.6 Render (MD → HTML)
1585
+
1586
+ ```bash
1587
+ specflow approval render <change> [--input approval.md] [--output approval.html]
1588
+ specflow approval finalize <change> --render # optional: render after finalize
1589
+ ```
1590
+
1591
+ Standalone HTML with embedded CSS; Mermaid diagrams load from CDN when present.
1592
+
1593
+ ### H.7 Playbook bundle (multi-repo)
1594
+
1595
+ Template: `templates/approval-playbook.yaml`. Lists per-repo `approval.md` paths; `bundle` concatenates with repo headers — **no LLM merge**.
1596
+
@@ -69,25 +69,61 @@ multi_repo:
69
69
  ```text
70
70
  本需求跨 N 个仓库,审批技术文档如何产出?
71
71
 
72
- A) 一份合订文档 (unified) — 单份 approval.md,含各仓决策/接口/前端/Worker 切片
73
- B) 多份分仓文档 (per_repo) — 每个仓库各自一份 approval.md,仅写本仓范围
72
+ A) 一份合订视图 (bundle) — 各仓 per_repo 真源 + CLI bundle 只读合订 (**推荐**)
73
+ B) 多份分仓 (per_repo) — 每仓各自 approval.md(默认 Map 模式)
74
+ C) 一份 LLM 合订 (legacy unified) — 仅当用户明确要求且无 bundle;不推荐
74
75
 
75
- 请选择 A 或 B
76
+ 请选择 A、BC
76
77
  ```
77
78
 
78
- ### 2.1 Unified(一份合订)
79
+ ### 2.1 Bundle(推荐 — A)
79
80
 
80
- 再询问:
81
+ **真源**: 各仓 **per_repo** `approval.md` + `approval/parts/`(ACP Map 分片)。
81
82
 
82
- ```text
83
- 合订文档存放在哪个主仓?(approval.md 与 approval/ 工作区写在该仓 change 目录下)
83
+ **只读合订**: 主仓 `approval-playbook.yaml` + `specflow approval bundle <primary.change>` → `approval-unified.md`(**无 LLM 合并**)。
84
+
85
+ 再询问主仓:
84
86
 
87
+ ```text
88
+ 合订 playbook 与 bundle 输出存放在哪个主仓?
85
89
  1) talos (平台)
86
90
  2) talos-web (控制台)
87
- 3) talos-worker (Worker)
88
91
 
92
+ ```
93
+
94
+ **硬规则**:
95
+
96
+ - `multi_repo.document_mode: per_repo`
97
+ - `multi_repo.bundle.enabled: true`
98
+ - `multi_repo.primary_repo: <id>` — playbook 与 bundle 输出路径
99
+ - 各仓独立 Stage 12 + assemble;**全部 assemble 通过后** 在主仓执行 bundle
100
+ - `acp.pipeline: acp/v2` 写入 `index.yaml`
89
101
 
90
- 请选主仓 id。
102
+ ```yaml
103
+ multi_repo:
104
+ document_mode: per_repo
105
+ primary_repo: talos
106
+ bundle:
107
+ enabled: true
108
+ output: approval-unified.md
109
+ outputs:
110
+ per_repo: [ …各仓路径… ]
111
+ bundle:
112
+ repo: talos
113
+ change: scenario-job-compile
114
+ path: specflow/changes/scenario-job-compile/approval-unified.md
115
+ ```
116
+
117
+ ### 2.2 Per-repo only(B)
118
+
119
+ 见 §2.3;`bundle.enabled: false`。
120
+
121
+ ### 2.3 Legacy unified LLM 合订(C — 不推荐)
122
+
123
+ 仅在用户 **明确要求** 且拒绝 bundle 时使用。再询问主仓:
124
+
125
+ ```text
126
+ 合订文档存放在哪个主仓?(approval.md 与 approval/ 工作区写在该仓 change 目录下)
91
127
  ```
92
128
 
93
129
  **硬规则**:
@@ -112,7 +148,7 @@ outputs:
112
148
  path: specflow/changes/scenario-job-compile/approval.md
113
149
  ```
114
150
 
115
- ### 2.2 Per-repo(多份分仓)
151
+ ### 2.4 Per-repo(B 详情)
116
152
 
117
153
  **硬规则**:
118
154
 
@@ -200,3 +236,28 @@ interfaces:
200
236
  ## 7. 与单仓关系
201
237
 
202
238
  `multi_repo.enabled=false` 时忽略本章;`change` 字段为当前规划根 change,行为与旧版一致。
239
+
240
+ ---
241
+
242
+ ## 8. 主仓一键 · Subagent 并行 (mode A/B)
243
+
244
+ > Router: `prompts/approval/multi-repo-spoke-subagent.md` · Orchestrator: `skills/specflow-approval/SKILL.md` **Stage 1c**
245
+
246
+ 当用户在 **主仓** 发起 `/specflow:approval` 且已选 **A (bundle)** 或 **B (per_repo)**:
247
+
248
+ | 角色 | 职责 |
249
+ |------|------|
250
+ | **主 Agent(主仓)** | intake、playbook、scope 拆分、闭环 Pass 1–11、主仓 Map、等待子仓、主仓 finalize、bundle |
251
+ | **Subagent × 子仓** | 各子仓独立 `approval/` → Map → 12e → `finalize <spoke.change>`(**禁止** `--bundle`) |
252
+
253
+ **硬顺序**:
254
+
255
+ 1. 主仓写好 `approval-playbook.yaml` + `multi_repo.repos[].root_hint`
256
+ 2. **并行**派发子仓 subagent(web / worker / …)
257
+ 3. **等待**全部 `finalize_ok: true`
258
+ 4. 主仓 Map + finalize
259
+ 5. 主仓 `finalize --bundle --workspace-root <主仓规划根>`
260
+
261
+ **禁止**: 仅在主仓 unified 合订而不拆仓;子仓未 finalize 就 bundle;让用户手动 cd 子仓跑 CLI(除非 subagent 不可用)。
262
+
263
+ **从 unified 迁移**: 将 `04.6-ui`、Worker L2 接口等 **搬迁** 到对应子仓 parts;主仓留 cross-ref + 平台/L3 正文。示例 playbook: `templates/approval-playbook-talos-scenario-job-compile.yaml`。
@@ -0,0 +1,94 @@
1
+ # Approval · Multi-Repo Spoke Subagent Brief
2
+
3
+ > **Invoked by** primary `/specflow:approval` orchestrator via **Task** subagent (one per non-primary repo).
4
+ > Primary repo Map/Review/Finalize stays on the **orchestrator** unless user explicitly runs approval from a spoke root.
5
+
6
+ ---
7
+
8
+ ## Mission
9
+
10
+ Run **full ACP approval for ONE spoke repo only** — Index → Map → Stage 12e AI Review → `specflow approval finalize <spoke.change>` — scoped to that repo's four artifacts and **only** entities assigned to this repo in the shared playbook / primary `index.yaml`.
11
+
12
+ **Do NOT** write into the primary repo. **Do NOT** LLM-merge cross-repo content into one file.
13
+
14
+ **Spoke index rule**: only **`primary_repo`** sets `multi_repo.bundle.enabled: true` + hosts `approval-playbook.yaml`. Spoke repos set `bundle.enabled: false` — they **never** run `--bundle`.
15
+
16
+ ---
17
+
18
+ ## Inputs (primary must pass all)
19
+
20
+ | Field | Example |
21
+ |-------|---------|
22
+ | `repo_id` | `talos-web` |
23
+ | `planning_root` | `/Users/gankang/TALOS-WORK/talos-web` |
24
+ | `change` | `web-scenario-cases` |
25
+ | `role` | `web` |
26
+ | `primary_change` | `scenario-job-compile` |
27
+ | `primary_repo_id` | `talos` |
28
+ | `workset_root` | `/Users/gankang/TALOS-WORK` |
29
+ | `scope` | Which parts/capabilities/interfaces/pages belong to this spoke (from playbook or primary index) |
30
+ | `cross_ref_policy` | Cross-repo refs: `见 talos approval §4.5 I8` — never duplicate platform DDL/RPC bodies |
31
+
32
+ Read before writing:
33
+
34
+ 1. `specflow/changes/<change>/` four artifacts (phase must be `refined`)
35
+ 2. `prompts/approval/generate.md` (Part E/F), `acp-pipeline.md`, `ai-review.md`
36
+ 3. Role packs: `frontend-guidance.md` (web), `api-guidance.md` (worker), etc.
37
+ 4. Primary `approval/index.yaml` `multi_repo.repos[]` entry for this repo
38
+
39
+ ---
40
+
41
+ ## Hard scope rules
42
+
43
+ | Role | Own in approval/parts | Cross-ref only (do not copy bodies) |
44
+ |------|----------------------|-------------------------------------|
45
+ | `platform` | compile, scheduler RPC/L4, DDL, gateway, ingest | Worker L2 HTTP, console pages |
46
+ | `web` | §4.6 UI, web APIs (I5/I6), nav/routes | Platform scheduler/result RPC details |
47
+ | `worker` | L2 Worker HTTP (I7/I9), executor logic, Pack | Platform L3 SubmitStepResult, Web UI |
48
+
49
+ Each spoke document is **standalone per repo**: `01-intro` … `10-signoff` with **repo-scoped** §1–§3 and detailed §4 batches for that repo only.
50
+
51
+ ---
52
+
53
+ ## Execution order (spoke)
54
+
55
+ ```text
56
+ cd <planning_root>
57
+ → Write approval/index.yaml (multi_repo.enabled=false OR spoke-local block only)
58
+ → Write approval/analysis.json (Passes scoped to this repo)
59
+ → 12a skeleton parts
60
+ → 12b Map batches (repo scope only)
61
+ → 12e: specflow approval finalize <change> # may pause → review-packet
62
+ → Fix parts; write review-result.json + part_hashes (specflow approval review-hashes --json)
63
+ → specflow approval finalize <change> # must exit ok
64
+ ```
65
+
66
+ **Never** run `--bundle` on a spoke. Bundle is **primary only**, after all spokes report success.
67
+
68
+ ---
69
+
70
+ ## Return payload to orchestrator (required)
71
+
72
+ Report in final message:
73
+
74
+ ```yaml
75
+ repo_id: talos-web
76
+ change: web-scenario-cases
77
+ finalize_ok: true
78
+ output_path: specflow/changes/web-scenario-cases/approval.md
79
+ review_result: specflow/changes/web-scenario-cases/approval/review-result.json
80
+ lint_errors: []
81
+ blocked: false
82
+ notes: ""
83
+ ```
84
+
85
+ If `finalize_ok: false`, set `blocked: true` and paste diagnostics — orchestrator **must not** bundle.
86
+
87
+ ---
88
+
89
+ ## Anti-patterns
90
+
91
+ - Writing `04.6-ui` into platform repo when web spoke exists
92
+ - Running bundle from spoke cwd
93
+ - Skipping finalize and pasting assembled markdown
94
+ - Unified LLM merge (mode C) when mode A was chosen