diff --git a/.gitignore b/.gitignore index 329581b..5149a61 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,9 @@ specs/ # Uncomment the next line if you prefer to not track compiled output: # dist/ docs/v0.4.0-platform-evolution-design.md + +/changes/ +/.superpowers/ +/docs/superpowers/ +/contest-2026/ +/scripts/sdd-workspace/ diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..4f763e0 --- /dev/null +++ b/.npmignore @@ -0,0 +1,5 @@ +/changes/ +/.superpowers/ +/docs/superpowers/ +/contest-2026/ +/scripts/sdd-workspace/ diff --git a/.superpowers/sdd/progress.md b/.superpowers/sdd/progress.md deleted file mode 100644 index 6d9900f..0000000 --- a/.superpowers/sdd/progress.md +++ /dev/null @@ -1 +0,0 @@ -# Progress Ledger: token-efficiency diff --git a/.superpowers/sdd/task-1-report.md b/.superpowers/sdd/task-1-report.md deleted file mode 100644 index 844e7c6..0000000 --- a/.superpowers/sdd/task-1-report.md +++ /dev/null @@ -1,9 +0,0 @@ -Status: DONE -Commits created: 30c8c7e test: add canonical spec path helper -Test summary: `node --test tests/lib/spec-paths.test.mjs` passed (5/5 tests). -Concerns: None for this task; implementation is scoped to the shared path helper only. -Report file path: /Users/magebte/Documents/magebyte/open-source-plugins/spec-superflow/.superpowers/sdd/task-1-report.md - -Fix note: tightened canonical spec detection so only `specs//spec.md` is accepted. Nested paths like `specs/ui-theme/nested/spec.md` are now excluded from `findCanonicalSpecFiles()` and no longer satisfy `requireSpecs`. -Test command: `node --test tests/lib/spec-paths.test.mjs` -Test result: PASS (6/6 tests). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8ae63ee..46dc258 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -63,7 +63,19 @@ If you add an example under `docs/examples//`, include: - `tasks.md` - `execution-contract.md` -### 4. Prefer operational wording +### 4. Repository Artifact Boundaries + +`docs/examples/` is the public location for complete example change sets. +The following root-local paths are working artifacts and must remain local and +uncommitted: + +- `changes/` +- `.superpowers/` +- `docs/superpowers/` +- `contest-2026/` +- `scripts/sdd-workspace/` + +### 5. Prefer operational wording Skill text should help an agent decide: diff --git a/changes/state-machine-skill-audit/.spec-superflow.yaml b/changes/state-machine-skill-audit/.spec-superflow.yaml deleted file mode 100644 index 3771878..0000000 --- a/changes/state-machine-skill-audit/.spec-superflow.yaml +++ /dev/null @@ -1,40 +0,0 @@ -# .spec-superflow.yaml — lightweight state machine -# Derived data. Always rebuildable from artifacts. Lost/corrupt → fall back to content-level detection. - -# === Core state === -state: specifying -workflow: auto - -# === Hashes (fast staleness detection) === -artifacts_hash: sha256:1af0fba4a1ae147282094e62cfa760ab3190f3a505810caa43e625991e672d55 -contract_hash: sha256:4972e1c446b5688d11e06636cfea199d9a906cac244caf60e3c30328642bfefd - -# === Execution progress === -execution_mode: sdd -batches_completed: 0 -test_result: null - -# === Metadata === -change_name: state-machine-skill-audit -last_transition: 2026-07-03T14:06:36.305Z -last_transition_from: executing -last_transition_to: specifying - -# === Decision points === -dp_0_decisions: 先脑暴再定版本; 允许破坏性变更; 合并已知问题; 逐步确认 -dp_0_confirmed: true -dp_0_timestamp: 2026-07-03T13:46:04Z -dp_1_result: confirmed: 方案3维度驱动 — D1状态机转换+D2 Skill指令质量+D3决策点协议;全部修复+回归测试 -dp_1_timestamp: 2026-07-03T13:46:04Z -dp_2_result: approved: proposal scope + 3 specs + 4 design decisions + 9 batches all confirmed -dp_2_timestamp: 2026-07-03T13:57:37Z -dp_3_result: approved: execution contract confirmed — 14 requirements mapped, SDD mode, 9 batches, 4 review gates -dp_3_timestamp: 2026-07-03T14:00:03Z -dp_4_result: SDD mode confirmed -dp_4_timestamp: 2026-07-03T14:04:26Z -dp_5_result: null -dp_5_timestamp: null -dp_6_result: null -dp_6_timestamp: null -dp_7_result: null -dp_7_timestamp: null diff --git a/changes/state-machine-skill-audit/design.md b/changes/state-machine-skill-audit/design.md deleted file mode 100644 index d0076e7..0000000 --- a/changes/state-machine-skill-audit/design.md +++ /dev/null @@ -1,74 +0,0 @@ -# 技术设计:状态机与 Skill 质量加固 - -## 上下文 - -- **当前状态**:v0.8.7 有 7 种状态、9 个 skill、8 个决策点。Guard 系统通过 `scripts/guard/guard.mjs` 实现 transition 检查矩阵,包含 5 个检查维度。Skill 质量依赖人工审查,无自动化 lint。DP 记录通过 `ssf state set` 命令手动写入 `.spec-superflow.yaml`。 -- **约束条件**:允许破坏性变更(skill 改名/合并、状态机重定义)。不新增运行时依赖。Node >= 22。测试使用 Node 原生 test runner。 -- **利益相关者**:spec-superflow 的 Claude Code / Cursor / Codex / Copilot / Gemini CLI 用户。 - -## 目标 - -1. Guard 检查矩阵覆盖所有合法 transition(含 rewind、fast-path、debugging round-trip) -2. 9 个 skill 的 SKILL.md 无矛盾指令、无冗余步骤、异常路径有明确兜底 -3. DP-0 到 DP-7 在每个关联 skill 中有强制执行点 -4. 所有修复有回归测试覆盖 - -## 非目标 - -- 跨平台注入一致性(→ v1.0.0) -- Token 优化(→ 下一个 change) -- 新 skill 或 skill 合并 -- TypeScript 引擎重构(除非审计发现关键 bug) - -## 决策 - -### 决策 1:审计方法 — 结构对比 + 自动化扫描 - -- **选择**:先用静态分析脚本扫描 guard matrix / skill 内容结构 / DP 链路,再人工审查异常项 -- **理由**:9 个 skill 共约 2300 行,纯人工审查不可靠且耗时。先自动化扫描生成 audit report,再人工审查 flagged 项,既系统化又高效 -- **考虑的替代方案**: - - 纯人工审查:全面但耗时且不可复现 - - 纯自动化:快速但无法检测语义矛盾 - -### 决策 2:Skill Lint 实现方式 - -- **选择**:新增 `scripts/lint/` 目录,实现基于规则的静态分析器,规则定义在 `scripts/lint/rules/` 中 -- **理由**:保持零运行时依赖;规则可逐条添加和测试;输出格式与现有 validate 命令一致 -- **考虑的替代方案**: - - 使用 markdownlint + 自定义规则:引入外部依赖,且无法做跨文件语义分析 - - 在 CI 中直接 grep:无法处理结构化规则 - -### 决策 3:Guard 矩阵补全策略 - -- **选择**:将 TRANSITION_CHECKS 从硬编码改为数据驱动的声明式矩阵,缺失的 transition 在 CI 中报错 -- **理由**:当前 matrix 是 JavaScript 对象,新增 transition 时容易忘记添加检查。声明式矩阵可以自检完整性(枚举所有状态 × 所有合法 transition × 必填维度) -- **考虑的替代方案**: - - 保持硬编码但添加更多检查:短期够用但治标不治本 - - 用 JSON Schema 定义 matrix:过度工程 - -### 决策 4:DP 链路验证方式 - -- **选择**:在 `ssf audit` 中增加 DP 完整性检查,在 release-archivist 的 DP-6 中增加 DP 缺失检测 -- **理由**:在已有 audit 命令上扩展,不需要新增 CLI 命令;在 closing 阶段强制检查 DP 完整性 -- **考虑的替代方案**: - - 在每个 transition 时都检查:增加 transition 耗时 - - 只在 CI 中检查:本地开发时无法发现 - -## 风险与权衡 - -- **风险**:Guard 矩阵变严格后,之前"能通过"的 transition 现在可能被拦截 → **缓解**:提供清晰的错误信息和修复指引(如 "缺少 artifacts,请先运行 spec-writer") -- **风险**:Skill 内容修改可能导致正在使用旧版 skill 的用户行为变化 → **缓解**:skill 内容修改集中在问题修复,不改变工作流主干 -- **风险**:DP 链路验证可能在 closing 阶段发现历史缺失,阻塞归档 → **缓解**:对历史缺失提供 "确认跳过" 选项 - -## 迁移计划 - -- **上线步骤**: - 1. 运行审计脚本,生成 audit report - 2. 按 D1 → D2 → D3 顺序修复 - 3. 每个维度修复后运行回归测试 - 4. 全部通过后提交 -- **回滚步骤**:git revert 到审计前的 commit - -## 待明确问题 - -- 无(所有决策已在 DP-0 和 need-explorer 阶段确认) diff --git a/changes/state-machine-skill-audit/execution-contract.md b/changes/state-machine-skill-audit/execution-contract.md deleted file mode 100644 index e36593e..0000000 --- a/changes/state-machine-skill-audit/execution-contract.md +++ /dev/null @@ -1,191 +0,0 @@ -# 执行合同 - -## Intent Lock - -- **变更名称**:`state-machine-skill-audit` -- **要解决的问题**:spec-superflow v0.8.7 的状态机转换、Skill 指令质量、决策点协议从未系统化审计。Guard 检查矩阵可能不完整(已有证据:两次 transition 出现 "guard check skipped" warning)、9 个 skill 的 SKILL.md 可能存在矛盾指令和遗漏的异常处理、DP 触发-记录-审计链路可能断裂。 -- **范围内**: - - D1: `scripts/guard/` 矩阵完整性 + staleness + debugging 往返 + terminal state 保护 - - D2: `skills/*/SKILL.md` 指令一致性 + 冗余检测 + 异常兜底 + 行为一致性 - - D3: DP-0 到 DP-7 触发点 + 审计链路 + 格式一致性 - - 所有修复的回归测试 -- **范围外**: - - 跨平台一致性(→ v1.0.0) - - Token 效率优化(→ 下一个 change) - - 新功能开发 - - TypeScript 引擎重构 - -## Approved Behavior - -### D1 — 状态机转换健壮性(3 ADDED + 1 MODIFIED) -- Guard 检查矩阵覆盖所有 21 个合法 transition + 显式拒绝 8 个非法 transition -- Staleness 检测基于内容比较(hash proposal scope vs contract intent lock),不依赖文件时间戳 -- Debugging 往返保留 `batches_completed` 和 `execution_mode` -- Abandoned 和 closing 作为终端状态锁死后续 transition -- Guard 脚本异常不再静默跳过,必须显式失败 - -### D2 — Skill 指令质量(4 ADDED) -- 跨 skill 引用的 DP 触发条件、transition 规则、术语定义必须一致 -- Guard 检查和 skill 内验证不得重复(skill 引用 guard,不自重验) -- 每个 skill 必须覆盖:解析失败、文件缺失、用户中断三条异常路径 -- "hard gate" 声明必须对应 guard 中的强制检查 - -### D3 — 决策点协议完整性(3 ADDED) -- DP-0 到 DP-7 每个在关联 skill 中有显式触发点和记录命令 -- `ssf audit` 输出 8 个 DP 的完整状态矩阵 -- `.spec-superflow.yaml` 中 DP 字段不被后续操作覆盖 - -### 关键场景 -1. 用户尝试 executing→closing 但 tasks 未全部完成 → guard 拦截 -2. proposal scope 扩展但 contract 未更新 → contract-fresh 失败,workflow-start 阻止进入 executing -3. 两个 skill 对同一 DP 描述不一致 → lint 检测并报告 -4. spec-writer 生成工件后找不到 contract-builder 路由 → skill 有明确降级指引 - -## Design Constraints - -### 架构约束 -- Lint 框架独立于现有 CLI 命令,放在 `scripts/lint/` 下,规则在 `scripts/lint/rules/` -- Guard 矩阵从硬编码改为声明式 TRANSITION_CHECKS + auditMatrix() 自检 -- 不引入运行时依赖(延续零依赖策略) - -### 接口约束 -- 不修改 CLI 命令名称(`ssf state`、`ssf audit`、`ssf validate` 等保持不变) -- `auditMatrix()` 输出 `{ valid, issues[] }` 格式,与 Validator 一致 - -### 依赖约束 -- Batch 4(lint 框架)可与 Batch 1-3(D1 guard 审计)并行 -- Batch 5(规划侧 skill)和 Batch 6(执行侧 skill)可并行 -- Batch 9(回归测试)依赖所有前序 batch - -### 数据约束 -- `.spec-superflow.yaml` 的 DP 字段命名保持 `dp_{N}_{field}` 格式 -- Skill SKILL.md 结构不改变(保留 frontmatter → instructions → handoff 布局) - -## Task Batches - -### Batch 1: Guard 矩阵完整性审计 -- **目标**:编写 guard 矩阵完整性测试 + auditMatrix() 自检函数 -- **输入**:`docs/state-machine.md` 中的合法 transition 列表 -- **输出**:`tests/lib/guard-transitions.test.mjs` + `auditMatrix()` 函数 -- **完成标准**:测试能运行并准确报告缺失的 transition - -### Batch 2: 修复 Guard 矩阵缺失 -- **目标**:补全 TRANSITION_CHECKS 矩阵所有条目 + 修复错误处理 -- **输入**:Batch 1 的 audit report -- **输出**:补全后的 guard matrix + 不再静默跳过的错误处理 -- **完成标准**:全部 21 个合法 transition 有对应检查,非法 transition 被显式拒绝 - -### Batch 3: Staleness 增强 + Debugging 往返 -- **目标**:增强 contract-fresh 的内容比较 + terminal state 保护 -- **输入**:Batch 2 的补全矩阵 -- **输出**:内容级 staleness 检测 + debugging 状态保留 + terminal state 锁定 -- **完成标准**:proposal scope 变化触发 stale,touch 不触发,abandoned 后所有 transition 被拒 - -### Batch 4: Skill Lint 框架 -- **目标**:搭建可扩展的 lint 框架基础 -- **输入**:技能目录 `skills/*/SKILL.md` -- **输出**:`scripts/lint/lint-skills.mjs` + 规则注册机制 + 框架测试 -- **完成标准**:框架能发现 9 个 skill 并运行已注册规则 - -### Batch 5: D2 — 规划阶段 Skill 审计 -- **目标**:审计 need-explorer, spec-writer, contract-builder -- **输入**:Batch 4 的 lint 框架 -- **输出**:3 条 lint 规则(矛盾指令、冗余检查、异常处理)+ 3 个 skill 修复 -- **完成标准**:3 个 skill lint issue 数为 0 - -### Batch 6: D2 — 执行+收尾阶段 Skill 审计 -- **目标**:审计 build-executor, bug-investigator, code-reviewer, release-archivist, spec-merger, workflow-start -- **输入**:Batch 4 的 lint 框架 -- **输出**:1 条 lint 规则(behavior-consistency)+ 6 个 skill 修复 -- **完成标准**:全部 9 个 skill lint issue 数为 0 - -### Batch 7: D3 — DP 触发点审计 -- **目标**:验证 DP-0 到 DP-7 在关联 skill 中有显式触发点 -- **输入**:Batch 5+6 修复后的 skill 内容 -- **输出**:`dp-trigger-points` 规则 + 缺失触发点修复 + DP 链路测试 -- **完成标准**:所有 DP 在关联 skill 中被引用且有记录命令 - -### Batch 8: D3 — DP 审计链路完整性 -- **目标**:增强 ssf audit + release-archivist 的 DP 缺失检测 -- **输入**:Batch 7 的触发点修复 -- **输出**:audit 中的 DP 状态矩阵 + DP-6 中的缺失检测 -- **完成标准**:audit 输出 8 个 DP 完整状态,closing 阶段检测缺失 DP - -### Batch 9: 回归测试套件收敛 -- **目标**:运行全部测试 + 最终验证 -- **输入**:所有前序 batch 的输出 -- **输出**:全部测试 PASS + CHANGELOG 更新 -- **完成标准**:`npm test` 全绿,`lint-skills.mjs` 返回 0 issue,`check-version-consistency` 通过 - -## Test Obligations - -### 必须先从失败测试开始的行为 -- Guard transition 矩阵完整性 → `tests/lib/guard-transitions.test.mjs` 中的边界测试先失败 -- Staleness 内容检测 → 先构造 scope drift 场景,测试失败后再实现 -- DP 触发点 → 先运行 `dp-trigger-points` lint 规则,报告缺失后再修复 -- Skill lint 框架 → 先写测试定义期望的 lint 输出格式,再实现框架 - -### 必需的边界情况 -- Guard 检查:空 change 目录、损坏的 artifacts_hash、并发 transition 请求 -- Staleness:proposal 和 contract 都存在但内容不一致、只有 proposal 没有 contract、子句变更 vs 整个 section 变更 -- Terminal state:从 abandoned 尝试全部 7 种 transition、closing→abandoned -- Skill lint:skill 目录为空、SKILL.md 为空文件、SKILL.md 为非 Markdown 格式 -- DP 审计:`.spec-superflow.yaml` 损坏、缺少部分 DP 字段、时间戳格式错误 - -### 回归敏感区域 -- `ssf state transition` — 修改后应保持向后兼容 -- `npm test` — 确保现有 12 个测试文件全部通过 -- `ssf validate` — 确保示例 change(add-dark-mode, refactor-auth-boundary)仍能通过验证 - -## Execution Mode - -- **模式**:`SDD`(Subagent-Driven Development) -- **选择理由**:9 个 batch 中多个可并行(Batch 1-3 和 Batch 4 独立;Batch 5 和 Batch 6 独立),SDD 模式每个 batch 派独立 subagent,墙钟时间最短 - -## Verification Dimensions - -| 维度 | 状态 | 发现 | -|------|------|------| -| Completeness | Pending | — | -| Correctness | Pending | — | -| Coherence | Pending | — | - -**总体结论**:Pending - -## Review Gates - -### 强制审查点 -- Batch 3 完成后 → code-reviewer 审查 D1 全部修改 -- Batch 6 完成后 → code-reviewer 审查 D2 全部修改 -- Batch 8 完成后 → code-reviewer 审查 D3 全部修改 -- Batch 9 完成后 → code-reviewer 最终审查 + release-archivist - -### 阻塞类别 -- **Critical**: guard 检查遗漏导致非法 transition 通过、DP 硬门禁可被跳过 -- **Important**: skill 指令矛盾、lint 规则漏检 -- **Minor**: 注释不准确、变量命名不一致 - -## Escalation Rules - -### 何时回退到 `specifying` -- 审计发现的新问题超出了现有 specs 定义的范围 -- 需要新增 requirement 来覆盖发现的缺陷 -- 用户要求调整 scope - -### 何时回退到 `bridging` -- tasks.md 的 batch 划分在执行中发现不合理需要重构 -- design.md 的技术决策在执行中被证明不可行 -- 修复过程中发现需要新增或修改设计决策 - -### 何时不得继续实现 -- Guard 检查修改后现有 change(add-dark-mode, refactor-auth-boundary)的验证失败 -- Lint 规则产生 false positive 且无法在不降低检出率的前提下修复 -- 任何修复导致现有 npm test 回归失败 - -### 需求覆盖确认 -所有 14 条 requirement(7 guard + 4 skill + 3 dp)均已映射到至少一个 batch: -- Guard(5) → Batch 1-3 -- Skill(4) → Batch 5-6 -- DP(3) → Batch 7-8 - -无未映射的需求。 diff --git a/changes/state-machine-skill-audit/proposal.md b/changes/state-machine-skill-audit/proposal.md deleted file mode 100644 index bd0f989..0000000 --- a/changes/state-machine-skill-audit/proposal.md +++ /dev/null @@ -1,57 +0,0 @@ -# 变更提案:状态机与 Skill 质量加固 - -## 背景(Why) - -spec-superflow v0.8.7 已迭代 8 个版本,积累了 9 个 skill、7 种状态、8 个决策点、5 层 guard 检查。但**从未进行过系统化的内部质量审计**。随着功能叠加,存在三类潜在风险: - -1. **状态机边界漏洞**:guard 检查矩阵是否覆盖所有 transition?rewind 路径(scope change → re-specify, contract drift → re-bridge)是否在真实场景中正确触发?fast-path(hotfix/tweak)的降级逻辑是否正确?debugging ↔ executing 的往返是否无副作用? -2. **Skill 指令质量退化**:9 个 skill 的 SKILL.md 累计约 2300 行指令,可能存在矛盾指令(两个 skill 对同一场景给出不同指引)、冗余步骤(spec-writer 和 contract-builder 重复验证同一条件)、遗漏的异常处理(解析失败、文件缺失、用户中断等路径无兜底)。 -3. **决策点链路断裂**:DP-0 到 DP-7 的触发-记录-审计链路是否在每个 skill 中都有强制执行点?是否存在"名义上有 DP 但代码中可以被跳过"的门禁? - -本变更对这三个维度进行全面审计,修复所有发现问题,并为每个修复添加回归测试。 - -## 变更内容(What Changes) - -- **D1 状态机转换审计**:审查 `scripts/guard/guard.mjs` 的 TRANSITION_CHECKS 矩阵完整性,验证所有 rewind/fast-path/debugging 转换的实际行为,修复发现的边界条件 -- **D2 Skill 指令质量审计**:逐个审查 9 个 skill 的 SKILL.md,检测矛盾指令、冗余步骤、遗漏的异常处理、不符合 DP 协议之处 -- **D3 决策点协议审计**:审查 DP-0 到 DP-7 在每个关联 skill 中的触发-记录-审计链路,修复断裂点 -- **回归测试**:为每个修复添加自动化测试(guard 测试增强、skill 内容 lint 规则、DP 链路测试) -- **版本**:本次变更不涉及版本号变更,所有修改集中在 `scripts/`、`skills/`、`tests/` 目录 - -## 能力(Capabilities) - -### 新增能力 - -- `guard-completeness-check` — guard 检查矩阵强制覆盖所有合法 transition -- `skill-lint-rules` — Skill 内容静态分析规则集 -- `dp-link-audit` — DP 触发-记录-审计链路自动化验证 - -### 修改能力 - -- `guard-transition-matrix` — 补充缺失的 transition 检查维度 -- `contract-fresh-check` — 增强 staleness 检测的内容覆盖范围 -- `phase-guard-injection` — 修正 phase-guard 中的操作/禁止列表与状态机的对应关系 - -## 范围(Scope) - -### 范围内(In Scope) - -- `scripts/guard/guard.mjs` 和 `scripts/guard/checks/` 下 5 个检查模块的覆盖度审计 -- `scripts/infer-workflow.mjs` 的 hotfix/tweak 降级逻辑审计 -- `scripts/lib/hash.mjs` 和 `scripts/guard/checks/contract-fresh.mjs` 的 staleness 检测准确性 -- 9 个 skill 的 SKILL.md 指令一致性审计 -- DP-0 到 DP-7 在各 skill 中的触发点和强制机制审计 -- 所有修复的回归测试 - -### 范围外(Out of Scope) - -- 跨平台一致性(Claude Code / Cursor / Codex / Copilot / Gemini CLI 的 manifest 和注入机制)— 留给 v1.0.0 -- Token 效率优化(hooks 注入大小、skill prompt 压缩)— 留给下一个 change -- 新功能开发、skill 增删合并 -- TypeScript 引擎(`src/`)的重构(除非审计发现关键 bug) - -## 影响(Impact) - -- 影响的代码区域:`scripts/guard/`、`scripts/lib/`、`skills/*/SKILL.md`、`tests/lib/` -- 影响的 API 或接口:`ssf state transition` 的 guard 检查行为可能更严格(之前漏检的非法 transition 将被拦截) -- 依赖或涉及的外部系统:无 diff --git a/changes/state-machine-skill-audit/tasks.md b/changes/state-machine-skill-audit/tasks.md deleted file mode 100644 index 5178f6e..0000000 --- a/changes/state-machine-skill-audit/tasks.md +++ /dev/null @@ -1,961 +0,0 @@ -# 实现任务 - -## 文件结构 - -- `Create: scripts/lint/lint-skills.mjs` — Skill 内容静态分析器入口,加载规则、扫描 skills/ 目录、输出结构化报告 -- `Create: scripts/lint/rules/no-contradictory-instructions.mjs` — 跨 skill 矛盾指令检测规则 -- `Create: scripts/lint/rules/no-redundant-checks.mjs` — 重复验证检查检测规则 -- `Create: scripts/lint/rules/exception-handling.mjs` — 异常路径兜底覆盖检测规则 -- `Create: scripts/lint/rules/dp-trigger-points.mjs` — DP 触发点存在性检测规则 -- `Create: scripts/lint/rules/behavior-consistency.mjs` — Skill 描述与实际行为一致性检测规则 -- `Create: tests/lib/guard-transitions.test.mjs` — Guard transition 矩阵回归测试 -- `Create: tests/lib/skill-lint.test.mjs` — Skill lint 规则回归测试 -- `Create: tests/lib/dp-integrity.test.mjs` — DP 审计链路回归测试 -- `Modify: scripts/guard/guard.mjs` — 补全 TRANSITION_CHECKS 矩阵,改进错误处理 -- `Modify: scripts/guard/checks/contract-fresh.mjs` — 增强 staleness 检测内容覆盖 -- `Modify: scripts/lib/cmd-audit.mjs` — 增加 DP 完整性检查 -- `Modify: skills/workflow-start/SKILL.md` — 修正矛盾指令,补充异常处理 -- `Modify: skills/need-explorer/SKILL.md` — DP-1 强制执行语言 -- `Modify: skills/spec-writer/SKILL.md` — 验证检查一致性 -- `Modify: skills/contract-builder/SKILL.md` — DP-3 硬门禁语言统一 -- `Modify: skills/build-executor/SKILL.md` — DP-4 强制执行语言 -- `Modify: skills/bug-investigator/SKILL.md` — DP-5 升级条件精确化 -- `Modify: skills/code-reviewer/SKILL.md` — Review 严重性级别一致性 -- `Modify: skills/release-archivist/SKILL.md` — DP-6/DP-7 强制执行 + DP 缺失检测 -- `Modify: skills/spec-merger/SKILL.md` — Abandoned change 合并阻止 - -## 接口 - -### Batch 1 → Batch 2 -- **Produces**: `auditReport: { missingTransitions: string[], weakChecks: {transition: string, missing: string[]}[], errorHandlingGaps: string[] }` — 被 Batch 2 消费,决定需要补全哪些 transition 检查 - -### Batch 2 → Batch 3 -- **Produces**: `guardMatrix: Map` — 补全后的 guard 矩阵,被 Batch 3 的 staleness 检测增强作为 baseline - -### Batch 4 → Batch 5 -- **Produces**: `lintFramework: { runLint(): LintReport, registerRule(rule): void }` — 被 Batch 5/6 使用,提供可扩展的 lint 规则运行环境 - -### Batch 5+6 → Batch 8 -- **Produces**: `dpGaps: { dp: string, skill: string, issue: string }[]` — DP 触发点缺失列表,被 Batch 8 消费用于修复 DP 链路 - ---- - -## 1. Batch 1: Guard 矩阵完整性审计 - -**Depends on**: none - -- [ ] **1.1 编写 guard 矩阵完整性测试(先写失败测试)** - -```javascript -// tests/lib/guard-transitions.test.mjs -import { describe, it } from 'node:test'; -import assert from 'node:assert/strict'; - -// 所有合法 transition(来自 docs/state-machine.md) -const ALL_TRANSITIONS = [ - // 主线 - { from: 'exploring', to: 'specifying' }, - { from: 'specifying', to: 'bridging' }, - { from: 'bridging', to: 'approved-for-build' }, - { from: 'approved-for-build', to: 'executing' }, - { from: 'executing', to: 'closing' }, - // fast-path - { from: 'exploring', to: 'bridging', workflow: 'hotfix' }, - { from: 'exploring', to: 'approved-for-build', workflow: 'tweak' }, - // rewind - { from: 'executing', to: 'specifying' }, - { from: 'executing', to: 'bridging' }, - { from: 'approved-for-build', to: 'specifying' }, - { from: 'approved-for-build', to: 'bridging' }, - { from: 'specifying', to: 'exploring' }, - { from: 'bridging', to: 'specifying' }, - // debugging round-trip - { from: 'executing', to: 'debugging' }, - { from: 'debugging', to: 'executing' }, - // abandon - { from: 'exploring', to: 'abandoned' }, - { from: 'specifying', to: 'abandoned' }, - { from: 'bridging', to: 'abandoned' }, - { from: 'approved-for-build', to: 'abandoned' }, - { from: 'executing', to: 'abandoned' }, - { from: 'debugging', to: 'abandoned' }, -]; - -// 非法 transition(应被拒绝) -const ILLEGAL_TRANSITIONS = [ - { from: 'exploring', to: 'closing' }, - { from: 'exploring', to: 'executing' }, - { from: 'specifying', to: 'executing' }, - { from: 'specifying', to: 'closing' }, - { from: 'bridging', to: 'closing' }, - { from: 'closing', to: 'abandoned' }, - { from: 'abandoned', to: 'exploring' }, - { from: 'abandoned', to: 'specifying' }, -]; - -describe('Guard transition matrix', () => { - for (const t of ALL_TRANSITIONS) { - it(`SHALL define checks for ${t.from} → ${t.to}${t.workflow ? ' (' + t.workflow + ')' : ''}`, () => { - // 动态 import guard.mjs 的 TRANSITION_CHECKS - // 验证每个合法 transition 都有对应的 checks 条目 - }); - } - - for (const t of ILLEGAL_TRANSITIONS) { - it(`SHALL reject illegal transition ${t.from} → ${t.to}`, () => { - // 验证非法 transition 被明确拒绝 - }); - } -}); -``` - -**Files**: `Create: tests/lib/guard-transitions.test.mjs` - -- [ ] **1.2 运行测试并确认失败** - -Run: `node --test --experimental-strip-types tests/lib/guard-transitions.test.mjs` -Expected: FAIL — 部分 transition 缺少检查维度,非法 transition 未被明确拦截 - -- [ ] **1.3 编写 guard 矩阵审计脚本** - -```javascript -// 在 guard.mjs 中增加自检函数 export function auditMatrix() -export function auditMatrix() { - const issues = []; - const defined = new Set( - Object.keys(TRANSITION_CHECKS).map(k => k.replace(':hotfix', '').replace(':tweak', '')) - ); - - // 检查所有合法 transition 是否在矩阵中 - for (const key of ALL_TRANSITION_KEYS) { - if (!TRANSITION_CHECKS[key]) { - issues.push({ severity: 'error', transition: key, issue: 'no checks defined' }); - } - } - - // 检查每个 transition 的检查维度是否完备 - for (const [key, checks] of Object.entries(TRANSITION_CHECKS)) { - if (!checks.includes('artifacts-exist')) { - issues.push({ severity: 'warning', transition: key, issue: 'missing artifacts-exist check' }); - } - } - - return { valid: issues.length === 0, issues }; -} -``` - -**Files**: `Modify: scripts/guard/guard.mjs` -**Interfaces**: Produces `auditReport` — 被 Batch 2 消费 - -- [ ] **1.4 运行 guard 审计获取初始报告** - -Run: `node -e "import('./scripts/guard/guard.mjs').then(m => console.log(JSON.stringify(m.auditMatrix(), null, 2)))"` -Expected: 输出结构化审计报告,标注缺失的 transition 和弱检查维度 - -- [ ] **1.5 提交** - -```bash -git add tests/lib/guard-transitions.test.mjs scripts/guard/guard.mjs -git commit -m "audit(d1): add guard matrix completeness audit with failing tests" -``` - ---- - -## 2. Batch 2: 修复 Guard 矩阵缺失 - -**Depends on**: Batch 1 - -- [ ] **2.1 编写 transition 补全测试** - -```javascript -// tests/lib/guard-transitions.test.mjs 追加 - -describe('Guard transition checks completeness', () => { - it('SHALL include artifacts-exist in all non-exploring entry transitions', () => { - const entryTransitions = ['exploring→specifying', 'exploring→bridging:hotfix', 'exploring→approved-for-build:tweak']; - for (const t of entryTransitions) { - const checks = getChecks(t); - assert.ok(checks.includes('artifacts-exist'), `${t} missing artifacts-exist`); - } - }); - - it('SHALL include schema-valid for transitions into bridging and approved-for-build', () => { - const schemaTransitions = ['specifying→bridging', 'bridging→approved-for-build']; - for (const t of schemaTransitions) { - const checks = getChecks(t); - assert.ok(checks.includes('schema-valid'), `${t} missing schema-valid`); - } - }); - - it('SHALL include contract-fresh for transitions into executing', () => { - const checks = getChecks('approved-for-build→executing'); - assert.ok(checks.includes('contract-fresh'), 'approved-for-build→executing missing contract-fresh'); - }); - - it('SHALL include tasks-complete and tests-passing for executing→closing', () => { - const checks = getChecks('executing→closing'); - assert.ok(checks.includes('tasks-complete'), 'executing→closing missing tasks-complete'); - assert.ok(checks.includes('tests-passing'), 'executing→closing missing tests-passing'); - }); -}); -``` - -**Files**: `Modify: tests/lib/guard-transitions.test.mjs` - -- [ ] **2.2 运行测试并确认失败** - -Run: `node --test --experimental-strip-types tests/lib/guard-transitions.test.mjs` -Expected: FAIL — 补全测试指向的 transition 检查缺失 - -- [ ] **2.3 补全 TRANSITION_CHECKS 矩阵** - -```javascript -// scripts/guard/guard.mjs — 补全 TRANSITION_CHECKS -const TRANSITION_CHECKS = { - // 主线 —— 维持现有 + 补充验证 - 'exploring→specifying': ['artifacts-exist'], - 'specifying→bridging': ['artifacts-exist', 'schema-valid'], - 'bridging→approved-for-build': ['artifacts-exist', 'schema-valid', 'contract-fresh'], - 'approved-for-build→executing': ['artifacts-exist', 'contract-fresh'], - 'executing→closing': ['tasks-complete', 'tests-passing'], - - // fast-path - 'exploring→bridging:hotfix': ['artifacts-exist'], - 'exploring→approved-for-build:tweak': ['artifacts-exist'], - - // rewind —— 至少验证 artifacts 存在 - 'executing→specifying': ['artifacts-exist'], - 'executing→bridging': ['artifacts-exist', 'contract-fresh'], - 'approved-for-build→specifying': ['artifacts-exist'], - 'approved-for-build→bridging': ['artifacts-exist', 'contract-fresh'], - 'specifying→exploring': ['artifacts-exist'], - 'bridging→specifying': ['artifacts-exist'], - - // debugging round-trip - 'executing→debugging': [], - 'debugging→executing': ['contract-fresh'], - - // abandon(从任何非终端状态) - 'exploring→abandoned': [], - 'specifying→abandoned': [], - 'bridging→abandoned': [], - 'approved-for-build→abandoned': [], - 'executing→abandoned': [], - 'debugging→abandoned': [], -}; -``` - -**Files**: `Modify: scripts/guard/guard.mjs` -**Interfaces**: Produces 补全后的 `guardMatrix` — 被 Batch 3 消费 - -- [ ] **2.4 改进 guard 错误处理:不再静默跳过** - -```javascript -// guard.mjs — 替换 catch 块中的 "guard check skipped" 逻辑 -try { - // ... guard checks ... -} catch (err) { - console.error(`Guard check failed: ${err.message}`); - console.error(err.stack); - process.exit(1); // 不再静默跳过 -} -``` - -**Files**: `Modify: scripts/guard/guard.mjs` - -- [ ] **2.5 运行测试并确认通过** - -Run: `node --test --experimental-strip-types tests/lib/guard-transitions.test.mjs` -Expected: PASS — 所有 transition 检查补全,错误处理测试通过 - -- [ ] **2.6 提交** - -```bash -git add scripts/guard/guard.mjs tests/lib/guard-transitions.test.mjs -git commit -m "fix(d1): complete guard transition matrix and improve error handling" -``` - ---- - -## 3. Batch 3: Staleness 检测增强 + Debugging 往返 - -**Depends on**: Batch 2 - -- [ ] **3.1 编写 staleness 检测测试** - -```javascript -// tests/lib/guard-transitions.test.mjs 追加 -describe('Staleness detection', () => { - it('SHALL detect when proposal scope expands beyond contract intent lock', async () => { - // 创建临时 proposal + contract,模拟 scope 扩展 - }); - - it('SHALL detect when spec requirement is modified after contract generation', async () => { - // 修改 spec 内容,验证 contract-fresh 失败 - }); - - it('SHALL NOT flag staleness when only file mtime changes', async () => { - // touch 文件但不改内容,验证 contract-fresh 通过 - }); -}); - -describe('Debugging round-trip', () => { - it('SHALL preserve batches_completed after debugging→executing', () => { - // 模拟 executing→debugging→executing,验证进度保留 - }); - - it('SHALL detect contract changes during debugging', () => { - // debugging 期间修改 contract,验证返回 executing 前被拦截 - }); -}); - -describe('Terminal state protection', () => { - it('SHALL reject all transitions from abandoned', () => { - // 验证 abandoned 状态下所有 transition 被拒绝 - }); - - it('SHALL reject closing→abandoned', () => { - // 验证 terminal→terminal 被拒绝 - }); -}); -``` - -**Files**: `Modify: tests/lib/guard-transitions.test.mjs` - -- [ ] **3.2 运行测试并确认失败** - -Run: `node --test --experimental-strip-types tests/lib/guard-transitions.test.mjs` -Expected: FAIL — staleness 检测和 terminal state 保护尚未完整实现 - -- [ ] **3.3 增强 contract-fresh 检查** - -```javascript -// scripts/guard/checks/contract-fresh.mjs -// 增强:不仅比较 hash,还比较 proposal scope 和 contract intent lock 的内容 -import { readFileSync } from 'node:fs'; -import { join } from 'node:path'; -import { hashContent } from '../../lib/hash.mjs'; - -export function check(dir) { - const proposal = readFileSync(join(dir, 'proposal.md'), 'utf-8'); - const contract = readFileSync(join(dir, 'execution-contract.md'), 'utf-8'); - - // 提取 proposal scope - const scopeMatch = proposal.match(/## 范围(Scope)\n\n### 范围内[\s\S]*?(?=### 范围外|## )/); - const proposalScope = scopeMatch ? hashContent(scopeMatch[0]) : null; - - // 提取 contract intent lock - const intentMatch = contract.match(/## Intent Lock[\s\S]*?(?=## |$)/); - const contractIntent = intentMatch ? hashContent(intentMatch[0]) : null; - - return { - passed: proposalScope === contractIntent, - detail: proposalScope === contractIntent ? 'contract is fresh' : 'contract is stale: proposal scope diverged from intent lock', - }; -} -``` - -**Files**: `Modify: scripts/guard/checks/contract-fresh.mjs` - -- [ ] **3.4 添加 terminal state 保护** - -```javascript -// scripts/guard/guard.mjs — 在 transition 前检查 -const TERMINAL_STATES = ['closing', 'abandoned']; - -function checkTransition(stateFile, from, to) { - if (TERMINAL_STATES.includes(from)) { - return { passed: false, detail: `${from} is a terminal state — no further transitions allowed` }; - } - if (from === 'closing' && to === 'abandoned') { - return { passed: false, detail: 'closing is already a terminal state — cannot transition to abandoned' }; - } - // ... 其他检查 ... -} -``` - -**Files**: `Modify: scripts/guard/guard.mjs` - -- [ ] **3.5 运行测试并确认通过** - -Run: `node --test --experimental-strip-types tests/lib/guard-transitions.test.mjs` -Expected: PASS — staleness、debugging round-trip、terminal state 所有测试通过 - -- [ ] **3.6 提交** - -```bash -git add scripts/guard/guard.mjs scripts/guard/checks/contract-fresh.mjs tests/lib/guard-transitions.test.mjs -git commit -m "fix(d1): enhance staleness detection, debugging round-trip, and terminal state protection" -``` - ---- - -## 4. Batch 4: Skill Lint 框架 - -**Depends on**: none(可与 Batch 1-3 并行) - -- [ ] **4.1 创建 lint 框架入口** - -```javascript -// scripts/lint/lint-skills.mjs -import { readdirSync, readFileSync, existsSync } from 'node:fs'; -import { join, dirname } from 'node:path'; -import { fileURLToPath } from 'node:url'; - -const __dirname = dirname(fileURLToPath(import.meta.url)); -const SKILLS_DIR = join(__dirname, '..', '..', 'skills'); -const RULES_DIR = join(__dirname, 'rules'); - -async function loadRules() { - const ruleFiles = readdirSync(RULES_DIR).filter(f => f.endsWith('.mjs')); - const rules = []; - for (const file of ruleFiles) { - const mod = await import(join(RULES_DIR, file)); - if (mod.default) rules.push(mod.default); - } - return rules; -} - -export async function lintSkills(options = {}) { - const rules = await loadRules(); - const skillDirs = readdirSync(SKILLS_DIR, { withFileTypes: true }) - .filter(d => d.isDirectory()) - .map(d => d.name); - - const results = []; - for (const skillName of skillDirs) { - const skillPath = join(SKILLS_DIR, skillName); - const skillMd = join(skillPath, 'SKILL.md'); - if (!existsSync(skillMd)) continue; - - const content = readFileSync(skillMd, 'utf-8'); - const issues = []; - for (const rule of rules) { - const ruleIssues = await rule.check(skillName, content, { skillDirs, skillsDir: SKILLS_DIR }); - issues.push(...ruleIssues); - } - results.push({ skill: skillName, issues }); - } - - const totalIssues = results.reduce((sum, r) => sum + r.issues.length, 0); - return { - valid: totalIssues === 0, - results, - summary: `${totalIssues} issue(s) across ${results.length} skills`, - }; -} - -// CLI entry -if (process.argv[1] === fileURLToPath(import.meta.url)) { - const report = await lintSkills(); - console.log(JSON.stringify(report, null, 2)); - process.exit(report.valid ? 0 : 1); -} -``` - -**Files**: `Create: scripts/lint/lint-skills.mjs` -**Interfaces**: Produces `lintFramework` — 被 Batch 5/6 消费 - -- [ ] **4.2 编写 lint 框架测试** - -```javascript -// tests/lib/skill-lint.test.mjs -import { describe, it } from 'node:test'; -import assert from 'node:assert/strict'; - -describe('Skill lint framework', () => { - it('SHALL discover all 9 skills', async () => { - const { lintSkills } = await import('../scripts/lint/lint-skills.mjs'); - const report = await lintSkills(); - assert.equal(report.results.length, 9); - }); - - it('SHALL return valid:true when no issues found', async () => { - // 需要 mock rules 为空 - }); - - it('SHALL aggregate issues across all rules', async () => { - // 验证多个规则的 issue 被合并 - }); -}); -``` - -**Files**: `Create: tests/lib/skill-lint.test.mjs` - -- [ ] **4.3 运行测试并确认失败** - -Run: `node --test --experimental-strip-types tests/lib/skill-lint.test.mjs` -Expected: FAIL — lint 框架存在但尚无规则,测试验证框架能加载 - -- [ ] **4.4 实现最小化框架(确保测试通过)** - -完成 `scripts/lint/lint-skills.mjs` 和第一条规则占位。 - -**Files**: `Modify: scripts/lint/lint-skills.mjs`, `Create: scripts/lint/rules/.gitkeep` - -- [ ] **4.5 运行测试并确认通过** - -Run: `node --test --experimental-strip-types tests/lib/skill-lint.test.mjs` -Expected: PASS - -- [ ] **4.6 提交** - -```bash -git add scripts/lint/ tests/lib/skill-lint.test.mjs -git commit -m "feat(d2): add skill lint framework" -``` - ---- - -## 5. Batch 5: D2 前半 — 规划阶段 Skill 审计 - -**Depends on**: Batch 4 - -按 skill 分组审计:need-explorer, spec-writer, contract-builder(规划侧的 3 个 skill)。 - -- [ ] **5.1 编写矛盾指令检测规则** - -```javascript -// scripts/lint/rules/no-contradictory-instructions.mjs -// 检测:跨 skill 引用同一 DP 时描述是否一致 -// 检测:状态转换规则在 workflow-start 和 route 目标 skill 间是否一致 - -export default { - name: 'no-contradictory-instructions', - async check(skillName, content, ctx) { - const issues = []; - - // 提取本 skill 中引用的 DP - const dpRefs = [...content.matchAll(/DP-(\d)/g)].map(m => m[1]); - - // 对于每个引用的 DP,检查 docs/decision-points.md 中的定义是否一致 - // (简化版:检查 trigger 条件的关键词是否匹配) - for (const dpNum of dpRefs) { - // 比较 docs/decision-points.md 中的 DP 定义 - } - - return issues; - } -}; -``` - -**Files**: `Create: scripts/lint/rules/no-contradictory-instructions.mjs` - -- [ ] **5.2 编写冗余检查检测规则** - -```javascript -// scripts/lint/rules/no-redundant-checks.mjs -// 检测:spec-writer 和 contract-builder 是否重复了相同的 validation 步骤 -// 检测:skill 内部是否重复了 guard 已经做的检查 - -export default { - name: 'no-redundant-checks', - async check(skillName, content, ctx) { - const issues = []; - - // 提取 skill 中的 validation checklists - const checklists = content.match(/## .*[Vv]alidat.*\n\n([\s\S]*?)(?=\n## |$)/g) || []; - - // 如果某个 validation checklist 与 guard checks 完全重叠,标记为冗余 - return issues; - } -}; -``` - -**Files**: `Create: scripts/lint/rules/no-redundant-checks.mjs` - -- [ ] **5.3 编写异常处理检测规则** - -```javascript -// scripts/lint/rules/exception-handling.mjs -// 检测:skill 是否提到了 "解析失败"、"文件缺失"、"用户中断" 时的处理 -// 检测:是否有 "如果 X 则 Y" 的条件分支覆盖异常路径 - -export default { - name: 'exception-handling', - async check(skillName, content, ctx) { - const issues = []; - - const exceptionPatterns = [ - { pattern: /解析失败|parse (error|fail)/i, label: 'parse failure handling' }, - { pattern: /文件缺失|file (not found|missing)/i, label: 'missing file handling' }, - { pattern: /用户中断|user (interrupt|cancel|stop)/i, label: 'user interruption handling' }, - ]; - - // 检查 skill 是否提到了 TDD/SDD/batch 等执行概念但未说明失败时怎么办 - return issues; - } -}; -``` - -**Files**: `Create: scripts/lint/rules/exception-handling.mjs` - -- [ ] **5.4 运行 lint 获取 need-explorer / spec-writer / contract-builder 审计报告** - -Run: `node scripts/lint/lint-skills.mjs 2>&1 | node -e "const r=JSON.parse(require('fs').readFileSync('/dev/stdin','utf-8')); console.log(JSON.stringify(r.results.filter(x=>['need-explorer','spec-writer','contract-builder'].includes(x.skill)), null, 2))"` -Expected: 结构化 issue 列表(矛盾指令、冗余检查、异常处理缺失) - -- [ ] **5.5 修复 need-explorer 问题** - -根据 lint 报告,修改 `skills/need-explorer/SKILL.md`: -- 确保 DP-1 触发条件与 `docs/decision-points.md` 一致 -- 补充异常处理指引(用户中断后如何恢复) -- 移除与 workflow-start 重复的检查 - -**Files**: `Modify: skills/need-explorer/SKILL.md` - -- [ ] **5.6 修复 spec-writer 问题** - -根据 lint 报告,修改 `skills/spec-writer/SKILL.md`: -- 确保 validation checklist 不与 guard.mjs 的 schema-valid 检查重复(改为引用 guard 而非重做) -- 补充解析失败时的降级指引 - -**Files**: `Modify: skills/spec-writer/SKILL.md` - -- [ ] **5.7 修复 contract-builder 问题** - -根据 lint 报告,修改 `skills/contract-builder/SKILL.md`: -- DP-3 语言统一为 "hard gate, cannot be skipped"(与 decision-points.md 一致) -- 补充 artifact 解析失败的修复建议路径 - -**Files**: `Modify: skills/contract-builder/SKILL.md` - -- [ ] **5.8 运行 lint 确认修复** - -Run: `node scripts/lint/lint-skills.mjs` -Expected: need-explorer, spec-writer, contract-builder 的 issue 数为 0 - -- [ ] **5.9 提交** - -```bash -git add skills/need-explorer/SKILL.md skills/spec-writer/SKILL.md skills/contract-builder/SKILL.md scripts/lint/rules/ -git commit -m "fix(d2): audit and fix planning-phase skills (need-explorer, spec-writer, contract-builder)" -``` - ---- - -## 6. Batch 6: D2 后半 — 执行 + 收尾阶段 Skill 审计 - -**Depends on**: Batch 4(与 Batch 5 可并行) - -- [ ] **6.1 编写 behavior consistency 检测规则** - -```javascript -// scripts/lint/rules/behavior-consistency.mjs -// 检测:skill 描述的 "route to X" 是否在 workflow-start 的 routing rules 中有对应 -// 检测:skill 描述的 "⛔ 禁止操作" 是否在 phase-guard.md 中有对应阻止 - -export default { - name: 'behavior-consistency', - async check(skillName, content, ctx) { - const issues = []; - - // 检查 "hard gate" 声明是否有对应的 guard 检查 - if (content.includes('hard gate') || content.includes('硬门禁')) { - // 验证 guard.mjs 中是否有对应检查 - } - - // 检查 routing references 是否双向一致 - const routeRefs = [...content.matchAll(/route to `([^`]+)`/g)].map(m => m[1]); - // 验证 workflow-start 中是否有对应的路由规则 - - return issues; - } -}; -``` - -**Files**: `Create: scripts/lint/rules/behavior-consistency.mjs` - -- [ ] **6.2 运行 lint 获取 build-executor, bug-investigator, code-reviewer, release-archivist, spec-merger, workflow-start 审计报告** - -Run: `node scripts/lint/lint-skills.mjs` -Expected: 结构化 issue 列表 - -- [ ] **6.3 修复 build-executor 问题** - -- DP-4 TDD Iron Law 条件与 contract 中的 test obligations 对齐 -- 补充 subagent 调度失败时的重试和降级策略 - -**Files**: `Modify: skills/build-executor/SKILL.md` - -- [ ] **6.4 修复 bug-investigator 问题** - -- DP-5 "连续 3 次失败" 的计数规则精确化(同类型失败算一次还是每次都算?) -- 补充 4-phase 分析中每阶段的超时/放弃条件 - -**Files**: `Modify: skills/bug-investigator/SKILL.md` - -- [ ] **6.5 修复 code-reviewer 问题** - -- Critical / Important / Minor 三级 severity 的定义与 workflow-start 中的 review gate 描述对齐 -- 补充 "performative agreement" 反模式的检测示例 - -**Files**: `Modify: skills/code-reviewer/SKILL.md` - -- [ ] **6.6 修复 release-archivist 问题** - -- DP-6 验证失败的分支选择(返回修复 vs 放弃关闭)条件明确化 -- DP-7 归档确认前增加 DP 缺失检测(reference: decision 4 in design.md) -- 补充 3D verification 的 per-dimension 通过/失败标准 - -**Files**: `Modify: skills/release-archivist/SKILL.md` - -- [ ] **6.7 修复 spec-merger 问题** - -- 增加 abandoned change 的 delta spec 合并阻止(与 state machine 规则一致) -- 补充合并冲突的分步解决指引 - -**Files**: `Modify: skills/spec-merger/SKILL.md` - -- [ ] **6.8 修复 workflow-start 问题** - -- 确保所有 routing rules 是双向一致的(workflow-start 的 route 与目标 skill 的 handoff 匹配) -- 补充 staleness 检测失败时的明确路由(rewind 到哪个状态) -- 确保 guard check 失败时不再静默跳过 - -**Files**: `Modify: skills/workflow-start/SKILL.md` - -- [ ] **6.9 运行 lint 确认全部修复** - -Run: `node scripts/lint/lint-skills.mjs` -Expected: 全部 9 个 skill issue 数为 0 - -- [ ] **6.10 提交** - -```bash -git add skills/ scripts/lint/rules/ -git commit -m "fix(d2): audit and fix execution+closing phase skills (6 skills)" -``` - ---- - -## 7. Batch 7: DP 触发点审计 - -**Depends on**: Batch 5, Batch 6 - -- [ ] **7.1 编写 DP 触发点检测规则** - -```javascript -// scripts/lint/rules/dp-trigger-points.mjs -// 每个 DP 在关联 skill 中必须有触发描述("触发条件" 或 "When to run DP-N") -// 每个 DP 在关联 skill 中必须有记录命令("ssf state set ... dp_N_") - -const DP_SKILL_MAP = { - 'DP-0': ['workflow-start'], - 'DP-1': ['need-explorer'], - 'DP-2': ['spec-writer'], - 'DP-3': ['contract-builder'], - 'DP-4': ['build-executor'], - 'DP-5': ['bug-investigator'], - 'DP-6': ['release-archivist'], - 'DP-7': ['release-archivist'], -}; - -export default { - name: 'dp-trigger-points', - async check(skillName, content, ctx) { - const issues = []; - for (const [dp, skills] of Object.entries(DP_SKILL_MAP)) { - if (skills.includes(skillName)) { - // 检查 skill 中是否有 DP 触发条件描述 - if (!content.includes(dp)) { - issues.push({ - skill: skillName, - severity: 'error', - message: `${dp} not mentioned in ${skillName} SKILL.md — trigger point may be missing`, - }); - } - // 检查是否有记录命令 - if (!content.includes(`dp_${dp.slice(-1)}_`)) { - issues.push({ - skill: skillName, - severity: 'warning', - message: `${dp} has no record command (ssf state set ... dp_N_*) in ${skillName}`, - }); - } - } - } - return issues; - } -}; -``` - -**Files**: `Create: scripts/lint/rules/dp-trigger-points.mjs` - -- [ ] **7.2 编写 DP 链路测试** - -```javascript -// tests/lib/dp-integrity.test.mjs -import { describe, it } from 'node:test'; -import assert from 'node:assert/strict'; - -describe('DP trigger points', () => { - const DP_SKILL_MAP = { /* DP → [skills] mapping */ }; - - for (const [dp, skills] of Object.entries(DP_SKILL_MAP)) { - for (const skill of skills) { - it(`${dp} SHALL have a trigger point in ${skill}`, async () => { - // 读取 skill SKILL.md,验证包含 DP 引用和记录命令 - }); - } - } -}); - -describe('DP audit trail', () => { - it('SHALL list all 8 DPs with status in audit report', () => { - // 运行 ssf audit,验证输出包含 DP-0 到 DP-7 - }); - - it('SHALL detect missing DP records', () => { - // 创建缺少 DP-2 的状态文件,验证 audit 报告缺失 - }); -}); -``` - -**Files**: `Create: tests/lib/dp-integrity.test.mjs` - -- [ ] **7.3 运行测试并确认失败** - -Run: `node --test --experimental-strip-types tests/lib/dp-integrity.test.mjs` -Expected: FAIL — 部分 DP 在关联 skill 中缺少显式触发点 - -- [ ] **7.4 修复 DP 触发点缺失** - -根据测试报告,在缺失的 skill 中补充 DP 触发描述和记录命令。 -修改范围:workflow-start, need-explorer, spec-writer, contract-builder, build-executor, bug-investigator, release-archivist 的 SKILL.md。 - -**Files**: `Modify: skills/*/SKILL.md`(根据实际缺失情况) - -- [ ] **7.5 运行测试并确认通过** - -Run: `node --test --experimental-strip-types tests/lib/dp-integrity.test.mjs` -Expected: PASS - -- [ ] **7.6 提交** - -```bash -git add skills/ scripts/lint/rules/dp-trigger-points.mjs tests/lib/dp-integrity.test.mjs -git commit -m "fix(d3): add DP trigger point detection and fix missing triggers" -``` - ---- - -## 8. Batch 8: DP 审计链路完整性 - -**Depends on**: Batch 7 - -- [ ] **8.1 增强 ssf audit 的 DP 完整性检查** - -```javascript -// scripts/lib/cmd-audit.mjs — 在 audit 报告中增加 DP 状态矩阵 - -function buildDpMatrix(stateFile) { - const dpStatus = []; - for (let i = 0; i <= 7; i++) { - const result = stateFile[`dp_${i}_result`]; - const timestamp = stateFile[`dp_${i}_timestamp`]; - dpStatus.push({ - id: `DP-${i}`, - name: DP_NAMES[i], - status: result ? (result.startsWith('confirmed') ? 'confirmed' : 'skipped') : 'pending', - timestamp: timestamp || null, - summary: result || null, - }); - } - return dpStatus; -} -``` - -**Files**: `Modify: scripts/lib/cmd-audit.mjs` -**Consumes**: `dpGaps` — 从 Batch 5+6 的 lint 报告中发现的具体缺失 - -- [ ] **8.2 在 release-archivist 中增加 DP 缺失检测** - -在 DP-6 验证阶段增加:检查所有必要 DP 是否已记录,如有缺失则提示用户确认。 - -**Files**: `Modify: skills/release-archivist/SKILL.md` - -- [ ] **8.3 编写 DP 审计链路端到端测试** - -```javascript -// tests/lib/dp-integrity.test.mjs 追加 -describe('DP audit trail end-to-end', () => { - it('SHALL generate audit report with all 8 DPs', async () => { - // 模拟完整 change 的 .spec-superflow.yaml,运行 audit - }); - - it('SHALL flag missing DP-2 and DP-3 in closing phase', () => { - // 模拟缺失 DP-2 的状态文件,验证 closing 阶段被拦截 - }); - - it('SHALL preserve existing DP records when state file is updated', () => { - // 模拟 ssf state set 修改其他字段,验证 DP 记录不被覆盖 - }); -}); -``` - -**Files**: `Modify: tests/lib/dp-integrity.test.mjs` - -- [ ] **8.4 运行测试并确认通过** - -Run: `node --test --experimental-strip-types tests/lib/dp-integrity.test.mjs` -Expected: PASS - -- [ ] **8.5 提交** - -```bash -git add scripts/lib/cmd-audit.mjs skills/release-archivist/SKILL.md tests/lib/dp-integrity.test.mjs -git commit -m "fix(d3): complete DP audit trail with gap detection and integrity tests" -``` - ---- - -## 9. Batch 9: 回归测试套件 + 最终验证 - -**Depends on**: Batch 2, Batch 3, Batch 5, Batch 6, Batch 7, Batch 8 - -- [ ] **9.1 运行全部测试确认回归** - -Run: `npm test` -Expected: 所有现有测试 + 新增测试全部 PASS - -- [ ] **9.2 运行 guard 完整性自检** - -Run: `node -e "import('./scripts/guard/guard.mjs').then(m => console.log(JSON.stringify(m.auditMatrix(), null, 2)))"` -Expected: `{ "valid": true, "issues": [] }` - -- [ ] **9.3 运行 skill lint 确认全绿** - -Run: `node scripts/lint/lint-skills.mjs` -Expected: `{ "valid": true, "results": [...], "summary": "0 issue(s) across 9 skills" }` - -- [ ] **9.4 运行版本一致性检查** - -Run: `node scripts/check-version-consistency.mjs` -Expected: ✅ Version consistency check passed - -- [ ] **9.5 完善回归测试覆盖描述** - -在测试文件中为每个测试用例添加 spec requirement 引用注释: - -```javascript -// Requirement: Guard 检查矩阵完整性 -// Scenario: 主线 transition 全覆盖 -it('SHALL define checks for exploring→specifying', () => { ... }); -``` - -**Files**: `Modify: tests/lib/guard-transitions.test.mjs, tests/lib/skill-lint.test.mjs, tests/lib/dp-integrity.test.mjs` - -- [ ] **9.6 提交** - -```bash -git add tests/ -git commit -m "test: complete regression test suite for D1+D2+D3 audit" -``` - -- [ ] **9.7 最终提交 — CHANGELOG** - -```bash -git add CHANGELOG.md # 如需要 -git commit -m "docs: add state-machine-skill-audit to CHANGELOG" -``` diff --git a/changes/token-efficiency/.spec-superflow.yaml b/changes/token-efficiency/.spec-superflow.yaml deleted file mode 100644 index f4cc38a..0000000 --- a/changes/token-efficiency/.spec-superflow.yaml +++ /dev/null @@ -1,40 +0,0 @@ -# .spec-superflow.yaml — lightweight state machine -# Derived data. Always rebuildable from artifacts. Lost/corrupt → fall back to content-level detection. - -# === Core state === -state: executing -workflow: full - -# === Hashes (fast staleness detection) === -artifacts_hash: sha256:c08cb20baf13ce23b202d9d3458e1f1ec72fe815aef4b2070a255a3c3e2929d2 -contract_hash: sha256:6d6e8d684cd9f3b4cff70ffdce10f7e05f6e9fda708158ad1bef92060f801d57 - -# === Execution progress === -execution_mode: null -batches_completed: 5 -test_result: pass - -# === Metadata === -change_name: token-efficiency -last_transition: 2026-07-03T14:51:15.071Z -last_transition_from: approved-for-build -last_transition_to: executing - -# === Decision points === -dp_0_decisions: "Token效率优化:压缩hooks/skills/phase-guard/prompts,建立度量基线。逐步确认关键决策,允许破坏性变更。范围外:跨平台一致性、新功能、削弱门禁。" -dp_0_confirmed: true -dp_0_timestamp: "2026-07-03T14:32:00Z" -dp_1_result: null -dp_1_timestamp: null -dp_2_result: approved: all 4 artifacts validated, 5 delta specs, 22 tasks in 5 batches -dp_2_timestamp: 2026-07-03T14:40:51Z -dp_3_result: approved: 5 batches, 22 requirements covered, batch-inline mode -dp_3_timestamp: 2026-07-03T14:42:16Z -dp_4_result: null -dp_4_timestamp: null -dp_5_result: null -dp_5_timestamp: null -dp_6_result: pass: all 212 tests pass, 0 token lint errors, doctor clean -dp_6_timestamp: null -dp_7_result: null -dp_7_timestamp: null diff --git a/changes/token-efficiency/design.md b/changes/token-efficiency/design.md deleted file mode 100644 index ab64b4c..0000000 --- a/changes/token-efficiency/design.md +++ /dev/null @@ -1,121 +0,0 @@ -# 设计文档:Token 效率优化 - -## Context - -### 当前状态 - -spec-superflow v0.8.7 的 prompt 注入体系包含: - -| 组件 | 行数 | 字符数 | 估算 Token | -|------|------|--------|-----------| -| `hooks/session-start` | 23 | 1,595 | ~400 | -| 9 个 skill SKILL.md | 2,461 | 95,167 | ~24,000 | -| `phase-guard.md` | 14 | ~350 | ~100 | -| `GEMINI.md` guard | 10 | ~300 | ~80 | -| **合计** | **2,508** | **97,412** | **~24,580** | - -> Token 估算公式:英文 1 token ≈ 4 字符,中文 1 token ≈ 1.5 字符。实际值因模型 tokenizer 而异。 - -### 约束 - -- **逻辑完整性不可退化**:压缩不能导致 skill 指令模糊或遗漏关键规则 -- **行为不可变**:压缩后的指令必须产生与压缩前等效的 workflow 行为 -- **版本号同步**:所有修改的文件必须通过 `ssf version` 自动同步版本号 -- **零运行时依赖**:不能引入新的 npm 依赖 -- **CI 不阻塞**:token 相关检查在 CI 中必须是 warning 级别(可选 upgrade 为 error) - -### 利益相关者 - -- 所有 spec-superflow 用户(每次会话都承担 token 开销) -- 使用多平台(Claude Code + Cursor + Gemini CLI)的用户(承担多套注入) - -## Goals - -1. **压缩 30%+ 总注入 token**:目标从 ~24,580 token 降至 ≤ 17,000 token -2. **建立可度量基线**:`token-baseline.json` + `scripts/token-baseline.mjs` 提供可复现的度量 -3. **自动化 enforce**:lint 规则在 CI 中 warning,本地 `--strict` 模式可升级为 error -4. **零功能退化**:所有现有测试通过,workflow 行为不变 - -## Decisions - -### D1: 压缩策略 — 优先去重和精简,而非重写 - -**Choice**: 采用渐进的"去重-精简-统一"策略,不对 skill 进行结构性重写。 - -**Rationale**: -- 重写 9 个 skill 的风险太高(可能引入行为退化) -- 大部分冗余来自重复的模板说明、过长的示例、可合并的边界条件列举 -- 渐进式压缩可以在每个 batch 后验证行为不变 - -**Alternatives considered**: -- **完全重写**:将 9 个 skill 合并为更少的 skill → 拒绝:改变 workflow 结构,风险大,scope 膨胀 -- **仅做 lint 规则**:不修改 skill 内容,只加 lint → 拒绝:不解决实际问题,lint 规则只有在有人修时才有效 - -### D2: Phase guard 格式 — 引用状态机而非逐条列举 - -**Choice**: Phase guard 内容改为 `` + 简短提示,由 workflow-start 在上下文中解释当前状态的含义。 - -**Rationale**: -- 当前 phase guard 逐条列出允许/禁止操作("创建规划工件"、"执行实现代码"等),这些信息已经存在于 state-machine.md 和 workflow-start 的路由规则中 -- phase guard 的角色是"信号"而非"文档"——它只需要告诉模型当前处于哪个状态,模型会从 workflow-start 中了解该状态的含义 -- 消除双重维护负担(修改状态机时不需要同步更新 phase guard 的操作列表) - -**Alternatives considered**: -- **完全移除 phase guard**:不注入任何 phase guard → 拒绝:DP gate 需要 phase guard 作为 session-level 的 guard 层 -- **保留当前格式但缩短**:压缩措辞但不改变结构 → 部分采用:当前方案本质上是"保留格式但引用状态机" - -### D3: Hooks 注入 — 共享内容变量 + 平台特定包装 - -**Choice**: 提取共享的注入内容为单一变量,三个平台的 printf 分支仅负责包装输出格式。 - -**Rationale**: -- 当前三套 printf 中,注入内容(`session_context`)完全相同,仅在包装格式上有差异 -- 提取共享变量后,只需维护一处注入内容 -- 注释可以集中在一处,而非在每个平台分支中重复 - -**Alternatives considered**: -- **移除多平台支持,仅保留 Claude Code** → 拒绝:v1.0.0 前仍需要多平台支持 -- **使用 JSON 模板文件** → 拒绝:引入额外文件读取,复杂度增加 - -### D4: Token 度量 — 字符计数为基础,不依赖 tokenizer API - -**Choice**: 基于字符数估算 token(英文 1:4,中文 1:1.5),不调用外部 tokenizer API。 - -**Rationale**: -- 零依赖约束(不能引入 `tiktoken` 等包) -- 估算精度足够用于趋势对比(压缩前 vs 压缩后) -- 实际 token 数因模型 tokenizer 而异,估算值作为统一基准更有可比性 - -**Alternatives considered**: -- **引入 tiktoken** → 拒绝:违反零依赖约束 -- **仅记录字符数,不做 token 估算** → 拒绝:用户和开发者更关心 token 数,纯字符数不够直观 - -### D5: Lint 分类 — 复用现有框架,不新建独立系统 - -**Choice**: 在现有 `lint-skills.mjs` 中新增 `--include token` 分类,不创建新的 lint 系统。 - -**Rationale**: -- lint 框架已经有 `--include` 参数支持规则分类 -- 新增分类比新建文件更简洁 -- 规则发现和报告格式复用现有基础设施 - -**Alternatives considered**: -- **新建 `lint-tokens.mjs`** → 拒绝:增加维护负担,用户需要记住两个 lint 命令 -- **使用 CI 独立 step** → 补充方案:CI 中 token lint 作为独立 step 运行,但使用同一框架 - -## Risks And Trade-Offs - -| Risk | Probability | Impact | Mitigation | -|------|-----------|--------|------------| -| 压缩后 skill 指令不够清晰,导致 workflow 行为偏差 | Medium | High | 每个 batch 后手动验证 workflow-start → build-executor 的关键路径 | -| 中文内容压缩后 token 节省不明显 | High | Low | 中文本身紧凑,主要节省来自英文部分和代码块,目标 30% 有挑战但可实现 | -| Phase guard 简化导致模型在无 workflow-start 的会话中缺乏上下文 | Low | Medium | Phase guard 仅在 `.claude/always/` 中注入,大多数会话都有 workflow-start 上下文 | -| Token 估算与实际 tokenizer 差异大 | Medium | Low | 估算用于趋势对比,不用于精确计费;差异不影响优化效果判断 | - -### Trade-off: 压缩 vs 可读性 - -压缩 skill 指令意味着减少示例、缩短说明、去除强调标记。好处是 token 节省,代价是 skill 指令对人类读者的可读性下降。考虑到 skill SKILL.md 的主要读者是 LLM(非人类),且更短的指令通常对 LLM 也更清晰,这个 trade-off 是可接受的。 - -### Trade-off: 自动化 vs 精确性 - -使用字符估算而非真实 tokenizer 意味着度量值不精确。但度量目标是"检测趋势"而非"精确计费",估算足够。如果未来需要精确度量,可以引入 tokenizer 作为 optional dependency。 diff --git a/changes/token-efficiency/execution-contract.md b/changes/token-efficiency/execution-contract.md deleted file mode 100644 index 5f9cfd4..0000000 --- a/changes/token-efficiency/execution-contract.md +++ /dev/null @@ -1,161 +0,0 @@ -# 执行合同:Token 效率优化 - -## Intent Lock - -- **变更名称**:Token 效率优化 -- **要解决的问题**:spec-superflow 作为 prompt 注入型插件,每次会话加载 hooks/skills/phase-guard 累计约 24,580 token。当前无系统化度量,存在 hooks 注入声明不准确(声称 ~80 tokens 实际 ~400)、skill 指令膨胀(9 个 skill 共 2,461 行)、phase guard 与状态机结构性重叠、缺乏 token 度量基线等问题 -- **范围内**: - 1. `hooks/session-start` 注入内容压缩(≤150 字符,共享变量,注释 ≤3 行) - 2. 9 个 skill SKILL.md 精简(累计 ≤1,800 行,每个 ≤250 行) - 3. `workflow-start/SKILL.md` 初始化步骤优化(≤5 步,文件 ≤300 行) - 4. `.claude/always/phase-guard.md` 和 `GEMINI.md` 注入最小化(≤8 行,引用状态机) - 5. Token 度量基线和 lint 规则(token-baseline.mjs + token-rules.mjs + CI 集成) -- **范围外**:跨平台一致性(→v1.0.0)、新功能开发、门禁削弱、TypeScript 引擎重构、Batch Inline 架构级优化 - -## Approved Behavior - -- **已批准需求摘要**: - - hooks-injection: 注入消息 ≤150 字符、平台分支共享变量、注释 ≤3 行、声明 token 准确 - - skill-instructions: 每个 SKILL.md ≤250 行、累计 ≤1,800 行、禁止 EXTREMELY_IMPORTANT/CRITICAL、代码块 ≤15 行、逻辑完整性不退化、模板格式统一 - - workflow-start-init: 初始化 ≤5 步、文件 ≤300 行、guard check 最小化为 transition-legality - - phase-guard-injection: ≤8 行、双平台一致、引用状态机而非逐条列举、版本自动同步 - - token-baseline: 覆盖所有组件、支持 --compare 对比、CI warning 级别、pre-commit 可选检查 - -- **关键场景**: - - 压缩后所有现有测试通过(逻辑完整性不退化) - - 压缩后 lint 规则 0 error(warning 可接受) - - Token baseline 工具正确输出每个组件的 {lines, chars, estimatedTokens} - - `--compare baseline.json` 正确输出变化量和百分比 - -- **验收检查**: - - AC1: `hooks/session-start` 的 `session_context` ≤ 150 字符 - - AC2: 9 个 skill 累计 ≤ 1,800 行 - - AC3: `.claude/always/phase-guard.md` ≤ 8 行 - - AC4: `node scripts/token-baseline.mjs` 输出所有组件的完整度量 - - AC5: `node scripts/lint/lint-skills.mjs --include token` 0 error - - AC6: `npm test` 所有测试通过 - - AC7: `node scripts/check-version-consistency.mjs` 通过 - - AC8: 总计估算 token 从 ~24,580 降至 ≤ 17,000(压缩 ≥30%) - -## Design Constraints - -- **架构约束**: - - D1: 渐进式"去重-精简-统一"策略 — 不对 skill 进行结构性重写,仅去除冗余 - - D2: Phase guard 改为引用状态名称,由 workflow-start 解释状态含义 - - D3: Hooks 注入提取共享内容变量,三平台分支仅包装输出格式 - - D4: Token 度量以字符计数为基础(英文 1:4,中文 1:1.5),不依赖外部 tokenizer API - - D5: 复用现有 `lint-skills.mjs` 框架,新增 `--include token` 分类 - -- **接口约束**: - - 新模块 `scripts/token-baseline.mjs` 导出 `{ lines, chars, estimatedTokens }` 结构 - - 新模块 `scripts/lint/rules/token-rules.mjs` 导出标准 lint 规则函数 `{ pass, failures }` - - `lint-skills.mjs` 的 `--include` 参数向后兼容 - -- **依赖约束**: - - 零运行时依赖(不引入 tiktoken 等 npm 包) - - Node >= 22(与项目现有要求一致) - -- **数据约束**: - - `token-baseline.json` 格式:`{ _comment, timestamp, version, components: { [path]: { lines, chars, estimatedTokens } } }` - -## Task Batches - -### Batch 1: Token 度量基线与 Lint 规则 -- **目标**:建立度量工具和 lint 基础设施 -- **输入**:无(首批) -- **输出**:`scripts/token-baseline.mjs`、`scripts/lint/rules/token-rules.mjs`、修改后的 `scripts/lint/lint-skills.mjs` -- **完成标准**:`node scripts/token-baseline.mjs` 正确输出度量;`node scripts/lint/lint-skills.mjs --include token` 可执行;所有新增测试通过 - -### Batch 2: Hooks + Phase Guard 压缩 -- **目标**:压缩注入内容 -- **输入**:Batch 1 的 lint 规则用于验证 -- **输出**:压缩后的 `hooks/session-start`、`.claude/always/phase-guard.md`、`GEMINI.md` -- **完成标准**:session_context ≤ 150 字符;phase-guard.md ≤ 8 行;双平台内容一致;版本号一致 - -### Batch 3: Skill 压缩 — Group A -- **目标**:压缩 5 个小/中型 skill -- **输入**:Batch 1 的 lint 规则 -- **输出**:压缩后的 need-explorer、spec-merger、code-reviewer、release-archivist、contract-builder SKILL.md -- **完成标准**:每个 ≤ 各自目标行数;lint 0 error;逻辑完整性验证通过 - -### Batch 4: Skill 压缩 — Group B + workflow-start 优化 -- **目标**:压缩 4 个大型 skill,优化初始化 -- **输入**:Batch 3 的压缩经验 -- **输出**:压缩后的 bug-investigator、spec-writer、build-executor、workflow-start SKILL.md -- **完成标准**:workflow-start ≤ 300 行;其余各 ≤ 各自目标;9 个 skill 累计 ≤ 1,800 行;lint 0 error - -### Batch 5: CI 集成 + 基线快照 + 最终验证 -- **目标**:完成集成和度量 -- **输入**:Batch 2-4 的所有压缩结果 -- **输出**:CI workflow 更新、`token-baseline.json`、版本一致性验证 -- **完成标准**:所有 AC 满足;总计 token ≤ 17,000;npm test 通过;doctor 通过 - -## Test Obligations - -- **必须先从失败测试开始的行为**: - - `token-baseline.mjs` 对已知文件的度量输出(先写测试验证输出结构) - - `token-rules.mjs` 对超限文件的检测(先写测试验证检测逻辑) - - `lint-skills.mjs --include token` 参数解析(先写测试验证参数识别) - -- **必需的边界情况**: - - 空文件(0 行)的度量不应报错 - - 中文为主的 skill 文件(如 need-explorer)的 token 估算准确度 - - 代码块解析对嵌套 markdown 的容错 - - `--compare` 模式下基线文件缺失时的错误处理 - -- **回归敏感区域**: - - `npm test` 全量测试套件(任何 skill 压缩不能改变行为) - - `ssf validate` 对压缩后的 artifacts 验证 - - `check-version-consistency.mjs` 对新增文件的版本检查 - - Guard check 的 transition 矩阵(workflow-start 的 guard check 最小化不能破坏 transition 验证) - -## Execution Mode - -- **模式**:Batch Inline(逐 batch 执行,每 batch 内 TDD) -- **选择理由**:5 个 batch 有明确的依赖链(Batch 1 → 2/3/4 → 5),但 Batch 2/3/4 之间相对独立。Batch Inline 允许在完成 Batch 1 后并行推进 Batch 2 和 3,最后汇聚到 Batch 5 - -## Verification Dimensions - -| 维度 | 状态 | 发现 | -|------|------|------| -| Completeness | Pending | — | -| Correctness | Pending | — | -| Coherence | Pending | — | - -**总体结论**:Pending(在执行完成后由 code-reviewer 填充) - -## Review Gates - -- **强制审查点**: - - Batch 1 完成后:审查 token baseline 工具和 lint 规则的正确性 - - Batch 4 完成后:审查所有 9 个 skill 的逻辑完整性(关键 gate) - - Batch 5 完成后:最终 code-reviewer 审查所有变更 - -- **阻塞类别**: - - Critical: npm test 失败、lint 规则 error、逻辑完整性缺失 - - Important: lint warning、token 压缩未达目标 - - Minor: 注释措辞、变量命名 - -## Escalation Rules - -- **何时回退到 `specifying`**:如果压缩导致 skill 指令产生歧义且无法通过简单修复恢复,回退修改 specs -- **何时回退到 `bridging`**:如果压缩实现发现设计决策不可行(如目标行数过于激进导致逻辑必须退化),回退修改合同 -- **何时不得继续实现**: - - 任何 skill 压缩后无法通过现有测试 - - lint 规则检测到逻辑完整性缺失 - - `ssf doctor` 报告插件健康问题 - - 版本号不一致(`check-version-consistency.mjs` 失败) - -## Requirements Coverage - -所有 22 个需求均映射到至少一个执行 batch: - -| 需求来源 | 需求数 | 覆盖 Batch | 状态 | -|----------|--------|-----------|------| -| hooks-injection | 4 | Batch 2 | ✅ | -| skill-instructions | 6 | Batch 3, 4 | ✅ | -| workflow-start-init | 3 | Batch 4 | ✅ | -| phase-guard-injection | 4 | Batch 2 | ✅ | -| token-baseline | 5 | Batch 1, 5 | ✅ | - -无未覆盖需求。 diff --git a/changes/token-efficiency/prompt.md b/changes/token-efficiency/prompt.md deleted file mode 100644 index 99828f5..0000000 --- a/changes/token-efficiency/prompt.md +++ /dev/null @@ -1,67 +0,0 @@ -# Token 效率优化 — 新会话启动提示语 - -> 将此提示语复制到新会话中,配合 `/workflow-start` 启动。 - ---- - -## 背景 - -spec-superflow v0.8.7 刚完成 **state-machine-skill-audit**(PR #13,已 squash merge 到 main)。该 change 对状态机、Skill 质量、DP 协议做了全面加固: - -- ✅ Guard 矩阵补全:7 个检查维度,43 个回归测试,DP gate(DP-3/DP-4 强制执行) -- ✅ Skill 质量审计:5 条 lint 规则,9 个 skill 从 33 个问题降至 0 -- ✅ Parser 双语支持修复(extractSection 不一致) -- ✅ F1 Document Map + F2 增量确认 + F5 DP Gate Guard 全部修复 -- 📝 C(跨平台一致性)留给 v1.0.0 - -完整上下文见 `changes/state-machine-skill-audit/`(proposal + specs + design + tasks + execution-contract)。 - -## 本次 Change:Token 效率优化 - -### 问题 - -spec-superflow 作为一个 prompt 注入型 workflow 插件,每次会话都会加载 hooks、phase-guard、skill 指令等。当前没有系统化度量过 token 开销,可能存在: - -1. **Hooks 注入冗余**:`hooks/session-start` 声称 "~40 tokens",但实际内容可能大于此数 -2. **Skill prompt 膨胀**:9 个 skill 累计约 2300 行 SKILL.md,部分指令可能有压缩空间(重复的模板说明、过长的示例) -3. **workflow-start 初始化开销**:每次启动都要 inspect change directory、run update check、run guard checks、run infer-workflow——能否更轻量? -4. **Phase guard 注入**:`.claude/always/phase-guard.md` 和 `GEMINI.md` 中的注入内容是否最小化? -5. **lint/guard 运行时开销**:每次 `ssf state transition` 都跑 guard,每次 commit 都跑 version check——这些检查的耗时和 token 开销是否合理? - -### 范围 - -- hooks/session-start 内容审查与压缩 -- 9 个 skill SKILL.md 的精简(保留逻辑,去除冗余措辞) -- workflow-start 初始化的必要步骤审查(哪些可以延迟?哪些可以跳过?) -- phase-guard 注入内容最小化 -- 建立 token 度量基线(各 skill 行数/字符数/token 估算,CI 中可选 enforce) - -### 范围外 - -- 跨平台一致性(→ v1.0.0) -- 新功能开发 -- 已有门禁的削弱(不能为了省 token 而砍掉 guard 检查) - -### 沟通偏好 - -逐步确认每个关键决策。允许破坏性变更(skill 内容重写、结构重组均可)。 - -### 启动方式 - -``` -/plugin update spec-superflow@spec-superflow -/reload-plugins - -用 workflow-start 开始 token 效率优化 -``` - -### 关键参考文件 - -- `hooks/session-start` — 当前注入内容 -- `.claude/always/phase-guard.md` — Claude Code 的 phase guard -- `GEMINI.md` — Gemini CLI 的 phase guard -- `skills/*/SKILL.md` — 9 个 skill 的完整指令 -- `scripts/guard/guard.mjs` + `scripts/guard/checks/` — guard 系统 -- `scripts/check-version-consistency.mjs` — pre-commit 检查 -- `scripts/lint/lint-skills.mjs` — lint 框架(本次 change 会新增 token 相关规则) -- `changes/state-machine-skill-audit/` — 上一轮的完整工件(参考其结构和格式) diff --git a/changes/token-efficiency/proposal.md b/changes/token-efficiency/proposal.md deleted file mode 100644 index d344233..0000000 --- a/changes/token-efficiency/proposal.md +++ /dev/null @@ -1,74 +0,0 @@ -# 变更提案:Token 效率优化 - -## 背景(Why) - -spec-superflow 是一个 prompt 注入型 workflow 插件,每次会话都会加载 hooks、phase-guard、skill 指令等内容。v0.8.7 版本中,9 个 skill 的 SKILL.md 累计约 2,461 行 / 95,167 字符(估算约 24,000 tokens),加上 hooks 注入和 phase guard,每次会话启动的基础 token 开销可观。 - -当前问题: - -1. **Hooks 注入声明不准确**:`hooks/session-start` 声称 "~80 tokens",但实际内容约 1,595 字符(估算约 400 tokens),且包含多平台兼容逻辑(Claude Code / Cursor / Copilot CLI 三套 printf 分支)和冗长的注释 -2. **Skill prompt 膨胀**:9 个 skill 合计 2,461 行,存在重复的模板说明(如"Use This Skill When"在每个 skill 中格式不同但语义重复)、过长的示例代码块、多层嵌套的强调标记(EXTREMELY_IMPORTANT / CRITICAL / ⚠️) -3. **workflow-start 初始化开销**:每次启动需 inspect change directory、run update check、run guard checks、run infer-workflow——这些操作本身开销小,但它们的输出(JSON)和错误提示会被注入上下文 -4. **Phase guard 注入冗余**:`.claude/always/phase-guard.md`(14 行)和 `GEMINI.md`(10 行 phase guard)存在重复的版本号和阶段描述,且二者的"允许/禁止操作"列表与状态机定义有结构性重叠 -5. **缺乏度量基线**:没有系统化的 token 度量机制——不知道每次会话各组件消耗多少 token、各 skill 在压缩前后的 token 变化、CI 中无法 enforce token 预算 - -本变更对上述五个维度进行全面优化,建立 token 度量基线,并在 CI 中增加可选的 token 预算检查。 - -## 变更内容(What Changes) - -- **D1 Hooks 注入精简**:审查并压缩 `hooks/session-start` 的注入内容,修正 token 估算,简化多平台兼容逻辑 -- **D2 Skill 指令精简**:逐个审查 9 个 skill 的 SKILL.md,去除冗余措辞、统一格式、压缩示例、减少重复的边界说明 -- **D3 workflow-start 初始化优化**:审查 `workflow-start/SKILL.md` 的初始化步骤,将非必要步骤延迟加载或跳过 -- **D4 Phase guard 注入最小化**:统一 `.claude/always/phase-guard.md` 和 `GEMINI.md` 的注入格式,消除与状态机的结构性重叠,最小化注入体积 -- **D5 Token 度量基线**:建立各组件 token 估算基准,在 lint 框架中新增 token 相关规则,CI 中可选 enforce - -## 能力(Capabilities) - -### 新增能力 - -- `token-baseline` — 各 skill/hook/guard 的 token 估算基线和度量工具 -- `token-lint-rules` — lint 规则集中的 token 相关检查(最大行数、最大字符数、禁止冗余模式) - -### 修改能力 - -- `hooks-injection` — `hooks/session-start` 注入内容压缩 -- `skill-instructions` — 9 个 skill 的 SKILL.md 精简 -- `phase-guard-injection` — Claude Code 和 Gemini CLI 的 phase guard 最小化 -- `lint-framework` — `scripts/lint/lint-skills.mjs` 新增 token 规则 - -## 范围(Scope) - -### 范围内(In Scope) - -- `hooks/session-start` 内容审查与压缩(含平台兼容逻辑简化) -- 9 个 skill 的 SKILL.md 精简(保留逻辑完整性,去除冗余措辞、重复示例、不必要强调标记) -- `workflow-start/SKILL.md` 的初始化步骤审查(延迟非必要检查、简化输出) -- `.claude/always/phase-guard.md` 和 `GEMINI.md` 的注入内容最小化 -- `scripts/lint/lint-skills.mjs` 新增 token 相关 lint 规则(最大行数、最大字符数、禁止模式) -- 建立 token 度量基线文档和度量脚本 -- CI 中可选 token 预算检查(不阻塞 CI,warning only) - -### 范围外(Out of Scope) - -- 跨平台一致性(Claude Code / Cursor / Codex / Copilot / Gemini CLI 的 manifest 和注入机制)— 留给 v1.0.0 -- 新功能开发、skill 增删合并 -- 已有门禁的削弱(不能为了省 token 而砍掉 guard 检查维度) -- TypeScript 引擎(`src/`)的重构 -- Batch Inline 等架构级 token 优化(不同性质的优化,留给独立 change) - -## 影响(Impact) - -- 影响的代码区域:`hooks/session-start`、`skills/*/SKILL.md`(9 个文件)、`.claude/always/phase-guard.md`、`GEMINI.md`、`scripts/lint/lint-skills.mjs` -- 影响的 API 或接口:无——所有修改仅影响 prompt 文本内容,不改变插件行为逻辑 -- 依赖或涉及的外部系统:无 -- 风险:skill 压缩可能导致指令不够清晰,需要通过 lint 规则和人工审查确保逻辑完整性不退化 - -## 关键参考文件 - -- `hooks/session-start` — 当前注入内容(23 行 / 1,595 字符) -- `.claude/always/phase-guard.md` — Claude Code 的 phase guard(14 行) -- `GEMINI.md` — Gemini CLI 的 phase guard(10 行 guard 内容) -- `skills/*/SKILL.md` — 9 个 skill 的完整指令(2,461 行 / 95,167 字符) -- `scripts/guard/guard.mjs` + `scripts/guard/checks/` — guard 系统 -- `scripts/check-version-consistency.mjs` — pre-commit 检查 -- `scripts/lint/lint-skills.mjs` — lint 框架(本次变更会新增 token 相关规则) diff --git a/changes/token-efficiency/tasks.md b/changes/token-efficiency/tasks.md deleted file mode 100644 index b8f2eb8..0000000 --- a/changes/token-efficiency/tasks.md +++ /dev/null @@ -1,435 +0,0 @@ -# 实现任务:Token 效率优化 - -## File Structure - -| Action | File | Responsibility | -|--------|------|---------------| -| Create | `scripts/token-baseline.mjs` | Token 度量工具:统计各组件行数/字符数/估算 token,支持对比基线 | -| Create | `scripts/lint/rules/token-rules.mjs` | Token 相关 lint 规则:max-lines, max-chars, max-emphasis-markers, max-code-block-length | -| Modify | `scripts/lint/lint-skills.mjs` | 新增 `--include token` 规则分类支持 | -| Modify | `hooks/session-start` | 压缩注入消息,共享内容变量,精简注释 | -| Modify | `.claude/always/phase-guard.md` | 压缩至 ≤8 行,引用状态机而非逐条列举操作 | -| Modify | `GEMINI.md` | Phase guard 块与 Claude Code 版本内容一致 | -| Modify | `skills/need-explorer/SKILL.md` | 精简指令(目标 ≤180 行) | -| Modify | `skills/spec-merger/SKILL.md` | 精简指令(目标 ≤180 行) | -| Modify | `skills/code-reviewer/SKILL.md` | 精简指令(目标 ≤220 行) | -| Modify | `skills/release-archivist/SKILL.md` | 精简指令(目标 ≤200 行) | -| Modify | `skills/contract-builder/SKILL.md` | 精简指令(目标 ≤200 行) | -| Modify | `skills/bug-investigator/SKILL.md` | 精简指令(目标 ≤220 行) | -| Modify | `skills/spec-writer/SKILL.md` | 精简指令(目标 ≤230 行) | -| Modify | `skills/build-executor/SKILL.md` | 精简指令(目标 ≤280 行) | -| Modify | `skills/workflow-start/SKILL.md` | 精简指令 + 初始化步骤优化(目标 ≤300 行) | -| Modify | `scripts/check-version-consistency.mjs` | 新增 phase-guard 和 GEMINI.md 的版本号一致性检查 | -| Modify | `.github/workflows/ci.yml` | 新增 token lint step(warning only) | -| Create | `token-baseline.json` | 压缩后的 token 度量快照 | - -## Interfaces - -### Batch 1 → Batch 2 -- **Produces**: `token-rules.mjs` 中的 `checkMaxLines()`, `checkMaxChars()` 函数 — consumed by Batch 2 用于验证压缩后的 hooks 和 phase guard -- **Produces**: `token-baseline.mjs` CLI — consumed by Batch 5 用于生成最终基线快照 - -### Batch 1 → Batch 3, 4 -- **Produces**: `lint-skills.mjs --include token` 参数 — consumed by Batch 3, 4 用于验证每个 skill 压缩后不超过 lint 阈值 - -### Batch 2 → Batch 5 -- **Produces**: 压缩后的 `hooks/session-start`, `phase-guard.md`, `GEMINI.md` — consumed by Batch 5 用于生成完整基线快照 - -### Batch 3, 4 → Batch 5 -- **Produces**: 压缩后的 9 个 `skills/*/SKILL.md` — consumed by Batch 5 用于生成完整基线快照和最终验证 - ---- - -## Batch 1: Token 度量基线与 Lint 规则 - -**Depends on**: None(首批) - -### Task 1.1: 创建 token-baseline.mjs 度量工具 - -**Files**: Create: `scripts/token-baseline.mjs` - -**TDD Phases**: - -1. **Write failing test**: 在 `tests/lib/` 下创建测试,调用 baseline 工具对 `skills/workflow-start/SKILL.md` 统计,验证输出包含 `{ lines, chars, estimatedTokens }` -2. **Run test, confirm failure**: 文件不存在,测试报 `ERR_MODULE_NOT_FOUND` -3. **Implement**: 创建 `scripts/token-baseline.mjs` - - 支持两种模式:`node scripts/token-baseline.mjs`(全量统计)和 `node scripts/token-baseline.mjs --compare baseline.json`(对比模式) - - 对每个目标文件统计:行数、字符数、估算 token 数(英文 `Math.ceil(chars / 4)`,中文先分离中文字符按 1.5 估算,其余按 4 估算) - - 输出 JSON 格式到 stdout 或 `--output ` 参数指定的文件 - - 支持 `--files ` 参数限制统计范围 -4. **Run test, confirm pass**: 对已知文件统计,验证输出格式和数值合理性 -5. **Commit**: `git add scripts/token-baseline.mjs tests/lib/token-baseline.test.ts && git commit -m "feat(token): add token-baseline.mjs measurement tool"` - -### Task 1.2: 创建 token lint 规则模块 - -**Files**: Create: `scripts/lint/rules/token-rules.mjs` - -**TDD Phases**: - -1. **Write failing test**: 创建测试,调用 `checkMaxLines(skillPath, 250)`,对一个 300 行的临时文件验证返回 `{ pass: false, message: "..." }` -2. **Run test, confirm failure**: 模块不存在 -3. **Implement**: 创建 `scripts/lint/rules/token-rules.mjs`,导出以下函数: - - `checkMaxLines(filePath, max)` — 检查文件行数 ≤ max - - `checkMaxChars(filePath, max)` — 检查文件字符数 ≤ max - - `checkMaxEmphasisMarkers(filePath, max)` — 检查 `**...**` 标记数 ≤ max,检查无 `EXTREMELY_IMPORTANT`/`CRITICAL` - - `checkMaxCodeBlockLength(filePath, max)` — 检查每个 ``` 代码块 ≤ max 行 - - `checkImportsCount(filePath, max)` — 检查 IMPORTANT 关键词出现次数 ≤ max - 每个函数返回 `{ pass: boolean, failures: string[] }` -4. **Run test, confirm pass**: 所有规则函数对测试文件返回预期结果 -5. **Commit**: `git add scripts/lint/rules/token-rules.mjs tests/lib/token-rules.test.ts && git commit -m "feat(token): add token lint rules module"` - -### Task 1.3: 在 lint-skills.mjs 中新增 --include token 分类 - -**Files**: Modify: `scripts/lint/lint-skills.mjs` - -**TDD Phases**: - -1. **Write failing test**: 运行 `node scripts/lint/lint-skills.mjs --include token`,预期仅执行 token 规则且无输出(规则未注册),实际命令行参数未被识别 -2. **Run test, confirm failure**: `--include token` 不被识别 -3. **Implement**: 修改 `scripts/lint/lint-skills.mjs` - - 在已有的 `--include` 参数解析后新增 `token` 分类 - - 当 `--include token` 时,导入 `./rules/token-rules.mjs` 并执行所有 token 规则 - - 对 `skills/*/SKILL.md` 目录下的所有文件运行规则 - - 同时支持对单个文件运行:`--include token --file skills/workflow-start/SKILL.md` - - Token 规则默认以 warning 级别报告(不改变 exit code) -4. **Run test, confirm pass**: `--include token` 正确执行 token 规则并输出结果 -5. **Commit**: `git add scripts/lint/lint-skills.mjs && git commit -m "feat(lint): add --include token category for token efficiency rules"` - -### Task 1.4: 为 token baseline 添加测试 - -**Files**: Create: `tests/lib/token-baseline.test.ts` - -**Implementation**: -- 测试 1:baseline 工具对已知文件(`skills/need-explorer/SKILL.md`)输出正确的 JSON 结构 -- 测试 2:`--compare` 模式对两份不同的 baseline 输出正确的变化量 -- 测试 3:`--files` 参数正确过滤统计范围 -- 运行 `npm test` 确认所有测试通过 - -**Commit**: `git add tests/lib/token-baseline.test.ts && git commit -m "test(token): add token-baseline.mjs unit tests"` - -### Task 1.5: Batch 1 收尾 - -- 运行 `node scripts/token-baseline.mjs` 生成当前基线并保存为 `token-baseline-pre.json`(临时文件,不提交) -- 记录当前总计 token 估算值 -- 运行 `npm test` 确保 Batch 1 所有测试通过 - -**Commit**: 无单独 commit(Batch 1 已在各 task 中 commit) - ---- - -## Batch 2: Hooks + Phase Guard 压缩 - -**Depends on**: Batch 1(使用 token lint 规则验证压缩结果) - -### Task 2.1: 压缩 hooks/session-start - -**Files**: Modify: `hooks/session-start` - -**Implementation**: -1. 提取 `session_context` 变量中的注入消息,从当前的 ~400 字符压缩至 ≤150 字符: - - 压缩前:`"\nYou have spec-superflow installed. Use /spec-superflow:workflow-start ONLY when you detect an active spec-superflow change in the workspace (look for \`.spec-superflow.yaml\`, \`proposal.md\`, \`execution-contract.md\`, or \`specs/\` directories), OR when the user explicitly invokes it by name. For ordinary coding tasks without spec-superflow artifacts, do NOT invoke workflow-start — just handle the request directly.\n"` - - 压缩目标:去除 EXTREMELY_IMPORTANT 嵌套,精简至核心信息:"检测到 spec-superflow 工件时用 workflow-start,否则直接处理" -2. 合并三个平台的 printf 分支:将 `session_context` 提取为共享变量,仅包装格式部分分平台 -3. 精简注释:从 10 行注释压缩至 3 行(去掉重复的平台兼容说明和历史信息) -4. 更新 token 估算注释为实际值 -5. 运行 `node scripts/lint/lint-skills.mjs --include token --file hooks/session-start` 验证 -6. 运行 `npm test` 确保所有测试通过 - -**Commit**: `git add hooks/session-start && git commit -m "perf(hooks): compress session-start injection to ~40 tokens"` - -### Task 2.2: 压缩 .claude/always/phase-guard.md - -**Files**: Modify: `.claude/always/phase-guard.md` - -**Implementation**: -1. 将内容从 14 行压缩至 ≤8 行 -2. 当前格式(14 行): - ``` - # Phase Guard: v0.8.7 - **当前阶段**: exploring | **工作流**: auto - ## ✅ 允许操作 - - 澄清需求、比较方案 - - 与用户讨论 scope 和 capabilities - ## ⛔ 禁止操作 - - 创建规划工件 - - 执行实现代码 - - 修改 execution-contract.md - ## 🔔 决策点 - - DP-1: 需求确认 - ``` -3. 压缩后格式(≤8 行):移除逐条操作列表,改为引用状态机 - ``` - # spec-superflow v0.8.7 | 阶段: {{state}} | 工作流: {{workflow}} - 遵循 workflow-start 路由规则。当前阶段允许的操作由状态机定义。 - DP gate: 进入下一阶段前需用户确认。 - ``` - 注:`{{state}}` 和 `{{workflow}}` 通过 `ssf inject` 命令在状态转换时替换 -4. 运行 lint 验证:`node scripts/lint/lint-skills.mjs --include token --file .claude/always/phase-guard.md` -5. 运行 `npm test` - -**Commit**: `git add .claude/always/phase-guard.md && git commit -m "perf(guard): compress phase-guard.md to 6 lines"` - -### Task 2.3: 同步 GEMINI.md 的 phase guard 块 - -**Files**: Modify: `GEMINI.md` - -**Implementation**: -1. 检查 `GEMINI.md` 中 `` 和 `` 之间的内容 -2. 将其替换为与 `.claude/always/phase-guard.md` 一致的内容(保留 GEMINI.md 的头部说明不变) -3. 验证两个文件的 phase guard 内容一致:`diff <(sed -n '/phase-guard-start/,/phase-guard-end/p' GEMINI.md) <(cat .claude/always/phase-guard.md)` -4. 运行 `npm test` - -**Commit**: `git add GEMINI.md && git commit -m "perf(guard): sync GEMINI.md phase guard with claude version"` - -### Task 2.4: 验证版本号一致性 - -**Files**: Modify: `scripts/check-version-consistency.mjs`(如果需要) - -**Implementation**: -1. 运行 `node scripts/check-version-consistency.mjs` 验证版本号一致 -2. 如果 `check-version-consistency.mjs` 尚未检查 `.claude/always/phase-guard.md` 和 `GEMINI.md` 的版本号,添加这两个文件的版本检查 -3. 运行 `npm test` - -**Commit**: `git add scripts/check-version-consistency.mjs && git commit -m "fix(version): add phase-guard and GEMINI.md to version consistency check"`(仅在有修改时) - -### Task 2.5: Batch 2 收尾 - -- 运行 `node scripts/token-baseline.mjs --files "hooks/session-start,.claude/always/phase-guard.md,GEMINI.md"` 验证压缩效果 -- 验证 hooks/session-start 注入消息 ≤150 字符 -- 验证 phase-guard.md ≤8 行 -- 运行 `npm test` - -**Commit**: 无单独 commit - ---- - -## Batch 3: Skill 压缩 — Group A(小型 skill) - -**Depends on**: Batch 1(lint 规则可用),Batch 2(phase guard 已压缩) - -### Task 3.1: 压缩 need-explorer/SKILL.md - -**Files**: Modify: `skills/need-explorer/SKILL.md`(当前 158 行 → 目标 ≤130 行) - -**Implementation**: -1. 审查当前内容,识别可压缩的部分: - - "Use This Skill When" 触发条件:统一句式,去除冗余引导语 - - 提问策略部分:合并重复的"每次只问一个问题"表述 - - 异常处理:保留逻辑,去除冗长的分支描述 -2. 压缩后运行 lint 验证:`node scripts/lint/lint-skills.mjs --include token --file skills/need-explorer/SKILL.md` -3. 阅读压缩后的内容,确认逻辑要点完整(触发条件、提问策略、handoff 规则) -4. 运行 `npm test` - -**Commit**: `git add skills/need-explorer/SKILL.md && git commit -m "perf(skill): compress need-explorer SKILL.md"` - -### Task 3.2: 压缩 spec-merger/SKILL.md - -**Files**: Modify: `skills/spec-merger/SKILL.md`(当前 206 行 → 目标 ≤160 行) - -**Implementation**: -1. 审查并压缩:合并重复的冲突检测说明,精简 merge 步骤描述 -2. Lint 验证 -3. 逻辑完整性检查 -4. 运行 `npm test` - -**Commit**: `git add skills/spec-merger/SKILL.md && git commit -m "perf(skill): compress spec-merger SKILL.md"` - -### Task 3.3: 压缩 code-reviewer/SKILL.md - -**Files**: Modify: `skills/code-reviewer/SKILL.md`(当前 318 行 → 目标 ≤220 行) - -**Implementation**: -1. 审查并压缩: - - 精简审查维度描述(Critical/Important/Minor 每类 ≤3 行说明) - - 移除重复的"不要"列表 - - 压缩报告格式模板 -2. Lint 验证 -3. 逻辑完整性检查(review gate 流程、severity 分类、handoff 规则) -4. 运行 `npm test` - -**Commit**: `git add skills/code-reviewer/SKILL.md && git commit -m "perf(skill): compress code-reviewer SKILL.md"` - -### Task 3.4: 压缩 release-archivist/SKILL.md - -**Files**: Modify: `skills/release-archivist/SKILL.md`(当前 243 行 → 目标 ≤180 行) - -**Implementation**: -1. 审查并压缩:合并重复的验证步骤,精简归档格式说明 -2. Lint 验证 -3. 逻辑完整性检查 -4. 运行 `npm test` - -**Commit**: `git add skills/release-archivist/SKILL.md && git commit -m "perf(skill): compress release-archivist SKILL.md"` - -### Task 3.5: 压缩 contract-builder/SKILL.md - -**Files**: Modify: `skills/contract-builder/SKILL.md`(当前 234 行 → 目标 ≤180 行) - -**Implementation**: -1. 审查并压缩:精简 contract 格式模板,移除与 spec-writer 重复的验证步骤 -2. Lint 验证 -3. 逻辑完整性检查(intent lock、scope fence、DP-3 协议) -4. 运行 `npm test` - -**Commit**: `git add skills/contract-builder/SKILL.md && git commit -m "perf(skill): compress contract-builder SKILL.md"` - -### Task 3.6: Batch 3 收尾 - -- 运行 `node scripts/lint/lint-skills.mjs --include token` 对所有已压缩 skill 进行 token lint -- 运行 `node scripts/token-baseline.mjs --files "skills/need-explorer/*,skills/spec-merger/*,skills/code-reviewer/*,skills/release-archivist/*,skills/contract-builder/*"` 验证累计 token 下降 -- 运行 `npm test` - -**Commit**: 无单独 commit - ---- - -## Batch 4: Skill 压缩 — Group B(大型 skill) - -**Depends on**: Batch 3(Group A 压缩完成,经验验证可行) - -### Task 4.1: 压缩 bug-investigator/SKILL.md - -**Files**: Modify: `skills/bug-investigator/SKILL.md`(当前 290 行 → 目标 ≤220 行) - -**Implementation**: -1. 审查并压缩: - - 4-phase 调试流程每 phase ≤5 行描述 - - 合并重复的 escalate 条件说明 - - 精简代码示例 -2. Lint 验证 -3. 逻辑完整性检查(4 phases、escalate 条件、debugging→executing 往返) -4. 运行 `npm test` - -**Commit**: `git add skills/bug-investigator/SKILL.md && git commit -m "perf(skill): compress bug-investigator SKILL.md"` - -### Task 4.2: 压缩 spec-writer/SKILL.md - -**Files**: Modify: `skills/spec-writer/SKILL.md`(当前 277 行 → 目标 ≤230 行) - -**Implementation**: -1. 审查并压缩: - - 精简 4 个 artifact 的验证清单(保留检查项,去除重复的说明文字) - - 合并 "Quality Bar" 和 "Self-Review Checklist" 部分(两者有大量重叠) - - 压缩 DP-2 协议说明 -2. Lint 验证 -3. 逻辑完整性检查(4 artifacts、validation rules、DP-2 gate、handoff rule) -4. 运行 `npm test` - -**Commit**: `git add skills/spec-writer/SKILL.md && git commit -m "perf(skill): compress spec-writer SKILL.md"` - -### Task 4.3: 压缩 build-executor/SKILL.md - -**Files**: Modify: `skills/build-executor/SKILL.md`(当前 360 行 → 目标 ≤280 行) - -**Implementation**: -1. 审查并压缩: - - 精简 TDD/SDD 两种执行模式的描述(合并共同部分) - - 压缩 Review Gate 说明(引用 code-reviewer,不重复其内容) - - 精简 batch 执行流程模板 - - 减少代码块示例 -2. Lint 验证 -3. 逻辑完整性检查(TDD/SDD 模式、review gate、contract drift 检测、DP-4) -4. 运行 `npm test` - -**Commit**: `git add skills/build-executor/SKILL.md && git commit -m "perf(skill): compress build-executor SKILL.md"` - -### Task 4.4: 压缩 workflow-start/SKILL.md + 初始化优化 - -**Files**: Modify: `skills/workflow-start/SKILL.md`(当前 375 行 → 目标 ≤300 行) - -**Implementation**: - -**Part A — 内容压缩**: -1. 精简冗余部分: - - "Default States" 列表压缩为一行引用(→ state-machine.md) - - "Required Inspection" 的 6 个问题合并为 3 个 - - "Config-Aware Routing" 与主路由逻辑合并 - - 去除重复的 guard check 命令示例(每个路由规则中格式相同,可提取为一次说明) - - "Hotfix Fast-Path Routing" 和 "Tweak Fast-Path Routing" 合并为一个表格 - - "Guardrails" 列表去重(多条规则在其他部分已有说明) - -**Part B — 初始化步骤优化**: -2. 将以下步骤从 workflow-start 中标记为"延迟执行"(由目标 skill 处理): - - `infer-workflow.mjs` 调用 → 移至 spec-writer(仅在需要创建 artifacts 时执行) - - 完整的 guard check 矩阵 → 仅保留 transition-legality 检查,artifacts-exist 等移至目标 skill -3. 简化 update check 输出(当前输出 "✅ up to date" 或升级提示,无需改变逻辑) - -4. Lint 验证:`node scripts/lint/lint-skills.mjs --include token --file skills/workflow-start/SKILL.md` -5. 逻辑完整性检查(状态检测、路由规则、DP-0 gate、staleness 检测、handoff 规则) -6. 运行 `npm test` - -**Commit**: `git add skills/workflow-start/SKILL.md && git commit -m "perf(skill): compress workflow-start SKILL.md and defer non-critical init"` - -### Task 4.5: Batch 4 收尾 - -- 运行 `node scripts/lint/lint-skills.mjs --include token` 对所有 9 个 skill 执行完整 token lint -- 运行 `node scripts/token-baseline.mjs` 生成压缩后的全量度量 -- 对比 Batch 1 中保存的 `token-baseline-pre.json`,验证总计压缩 ≥30% -- 运行 `npm test` - -**Commit**: 无单独 commit - ---- - -## Batch 5: CI 集成 + 基线快照 + 最终验证 - -**Depends on**: Batch 3, 4(所有 skill 压缩完成) - -### Task 5.1: 在 CI 中新增 token lint step - -**Files**: Modify: `.github/workflows/ci.yml` - -**Implementation**: -1. 在现有 CI workflow 的 test job 之后新增 step: - ```yaml - - name: Token efficiency lint - run: node scripts/lint/lint-skills.mjs --include token - continue-on-error: true # warning only, 不阻塞 CI - ``` -2. 验证 CI 配置语法:如果安装了 `act`,运行 `act -j test`(dry-run);否则手动检查 YAML 语法 -3. 运行 `npm test` - -**Commit**: `git add .github/workflows/ci.yml && git commit -m "ci(token): add token efficiency lint step (warning only)"` - -### Task 5.2: 生成并保存 token 基线快照 - -**Files**: Create: `token-baseline.json` - -**Implementation**: -1. 运行 `node scripts/token-baseline.mjs --output token-baseline.json` 生成最终基线 -2. 审查基线内容,确认所有组件的度量值合理 -3. 在 `token-baseline.json` 顶部添加注释说明(用 `_comment` 字段):度量时间、版本、估算方法 -4. 运行 `npm test` - -**Commit**: `git add token-baseline.json && git commit -m "docs(token): add token baseline snapshot for v0.8.8"` - -### Task 5.3: 验证版本号一致性 - -**Files**: Modify: `scripts/check-version-consistency.mjs`(如 Task 2.4 未修改则在此修改) - -**Implementation**: -1. 运行 `node scripts/check-version-consistency.mjs` 确保所有文件版本一致 -2. 确认 phase-guard.md 和 GEMINI.md 的版本号已纳入检查 -3. 运行 `npm test` - -**Commit**: `git add scripts/check-version-consistency.mjs && git commit -m "fix(version): ensure phase-guard files in version consistency check"`(仅在有修改时) - -### Task 5.4: 最终验证与回归 - -**Implementation**: -1. 运行完整 lint:`node scripts/lint/lint-skills.mjs --include token`,确认 0 error(warning 可接受) -2. 运行 `node scripts/token-baseline.mjs`,确认总计 ≤17,000 估算 token(压缩 ≥30%) -3. 运行 `npm test`,确认所有测试通过 -4. 手动审查关键 skill 的逻辑完整性(workflow-start、spec-writer、build-executor) -5. 运行 `node scripts/spec-superflow.mjs doctor` 确认插件健康 -6. 清理临时文件:`rm -f token-baseline-pre.json` - -**Commit**: `git commit -m "chore(token): final verification — all tests pass, token baseline saved"`(仅在有未提交修改时) - -### Task 5.5: Batch 5 收尾 - -- 确认所有 task 已 commit -- 生成变更摘要:压缩前后对比表 -- 运行 `git log --oneline token-efficiency ^main` 查看所有 commit - -**Commit**: 无单独 commit(所有修改已在前面的 task 中 commit) diff --git a/changes/v0.3.0-workflow-enhancements/design.md b/changes/v0.3.0-workflow-enhancements/design.md deleted file mode 100644 index d41fcb1..0000000 --- a/changes/v0.3.0-workflow-enhancements/design.md +++ /dev/null @@ -1,70 +0,0 @@ -# Technical Design: v0.3.0 Workflow Enhancements - -## Context - -- **Current state**: spec-superflow v0.2.1 has 9 skills, 7-state machine, TypeScript validation engine with 3 methods (validateSpecContent, validateChangeContent, validateDeltaSpec), and zero external npm dependencies. The plugin works as markdown skills injected via hooks. -- **Constraints**: Zero external npm dependencies. Node >= 22. Pure regex parsing. Multi-platform (7 platforms). Self-contained (no OpenSpec/Superpowers runtime dependency). -- **Stakeholders**: Plugin users (developers using Claude Code/Cursor/Codex), spec-superflow maintainers, open-source community evaluating the plugin. - -## Goals - -- Make task planning granular enough that implementation requires no guesswork (writing-plans quality) -- Provide a lightweight execution path for small changes without sacrificing TDD discipline -- Allow graceful abandonment when a change proves unviable, preserving lessons and optional partial work -- Verify implementation quality across three orthogonal dimensions before declaring completion - -## Non-Goals - -- CLI tooling (deferred to v0.4.0) -- Configurable schemas / YAML artifact dependency graphs (deferred to v0.4.0) -- Programmatic state machine enforcement (the state machine remains LLM-guided, not code-enforced) -- Automated conflict resolution in spec-syncer - -## Decisions - -### Decision 1: Writing-plans methodology embedded in spec-forger, not a separate skill - -- **Choice**: Enhance spec-forger's tasks.md generation chapter directly with writing-plans methodology. Do not create a new `writing-plans` skill. -- **Rationale**: spec-superflow's value proposition is a single unified workflow. Adding a separate planning skill fragments the experience. The methodology is guidance for artifact generation, not a distinct workflow phase. Embedding it keeps the entry point simple (spec-forger creates all 4 artifacts). -- **Alternatives considered**: (a) New `plan-writer` skill that spec-forger delegates to — rejected because it adds routing complexity and breaks the "one skill per artifact set" model. (b) Import Superpowers' writing-plans skill as-is — rejected because it uses Superpowers-specific terminology and file paths (`docs/superpowers/plans/`) that conflict with spec-superflow's structure. - -### Decision 2: Inline mode as execution-governor internal branch, not a separate skill - -- **Choice**: Add Inline mode as a conditional branch within execution-governor's per-task loop, not as a new `inline-executor` skill. -- **Rationale**: Inline and SDD modes share the same TDD Iron Law, the same review gates, and the same progress ledger. The only difference is whether subagents are dispatched. A separate skill would duplicate 80% of execution-governor's logic. Internal branching keeps the shared discipline in one place. -- **Alternatives considered**: (a) Separate `inline-executor` skill — rejected due to massive duplication. (b) Strategy pattern with pluggable execution backends — overengineered for two modes; if a third mode emerges later, refactor then. - -### Decision 3: Abandoned as terminal state, not a rewind target - -- **Choice**: `abandoned` is a terminal state (like `closing`). Once abandoned, no further transitions are allowed. The user must start a new change. -- **Rationale**: Abandonment means the change itself is fundamentally flawed, not that a specific artifact is wrong. Rewinding to specifying or bridging would imply the change is salvageable, which contradicts the abandonment decision. A clean terminal state forces the user to start fresh with lessons learned. -- **Alternatives considered**: (a) Rewind to exploring — rejected because it conflates "this change is dead" with "let's rethink." (b) Paused state (resume later) — rejected because it creates zombie changes that accumulate without resolution. - -### Decision 4: Three-dimensional verification as closure-archivist enhancement, not a new skill - -- **Choice**: Extend closure-archivist's verification steps with Completeness, Correctness, and Coherence checks. Add `validateImplementation()` to the Validator engine. -- **Rationale**: Verification is closure-archivist's core responsibility. Adding a separate `verifier` skill would create ambiguity about who owns the "is this done?" question. The Validator engine extension provides programmatic support for what was previously pure LLM judgment. -- **Alternatives considered**: (a) New `implementation-verifier` skill — rejected because it fragments the closure phase. (b) OpenSpec-style `/opsx:verify` slash command — rejected because spec-superflow uses skill routing, not slash commands. - -### Decision 5: Zero new npm dependencies for Validator extension - -- **Choice**: `validateImplementation()` uses the same regex-based parsing approach as existing validators. No Zod, no AST parsing. -- **Rationale**: The zero-dependency constraint is a core differentiator. The implementation verification is inherently heuristic (checking for placeholder markers, matching requirement names against diff summaries). Regex is sufficient for this level of checking. -- **Alternatives considered**: (a) Use tree-sitter for AST-based code analysis — rejected because it requires a native dependency. (b) Shell out to git diff — rejected because it couples the Validator to git, breaking the pure-function API contract. - -## Risks And Trade-Offs - -- **Task granularity enforcement is heuristic** → The 2-5 minute rule cannot be programmatically verified. Mitigation: spec-forger's self-review checklist includes explicit granularity questions; bridge-contract cross-checks task count against requirement count. -- **Inline mode may be selected for changes that need SDD** → Automatic mode selection could underestimate complexity. Mitigation: execution-governor reports the selection reasoning; user can override; if inline execution hits a blockage, governor suggests switching to SDD. -- **Abandonment summary may be skipped** → Users might abandon without generating the summary. Mitigation: workflow-orchestrator prompts for summary generation before confirming abandonment; the prompt can be declined but not silently skipped. -- **Three-dimensional verification increases closure time** → Coherence checking requires reading both design.md and code, which is token-intensive. Mitigation: Coherence dimension only runs if design.md exists and has a Decisions section; skipped for trivial changes. -- **Validator.validateImplementation() is heuristic** → Regex-based diff analysis cannot catch all completeness/correctness issues. Mitigation: The method returns WARN (not FAIL) for low-confidence checks; the LLM performs the authoritative verification using the method's output as a checklist. - -## Migration Plan - -- **Rollout steps**: (1) Update templates (tasks.md, execution-contract.md, abandonment-summary.md) → (2) Update Validator engine → (3) Update skills (spec-forger, execution-governor, closure-archivist, workflow-orchestrator) → (4) Update docs/state-machine.md → (5) Run existing tests + add new tests → (6) Version bump + publish -- **Rollback steps**: Revert to v0.2.1 tag. No data migration required (all changes are additive to skills and templates). - -## Open Questions - -- None. All design decisions resolved during exploring phase. diff --git a/changes/v0.3.0-workflow-enhancements/execution-contract.md b/changes/v0.3.0-workflow-enhancements/execution-contract.md deleted file mode 100644 index fb1ceb3..0000000 --- a/changes/v0.3.0-workflow-enhancements/execution-contract.md +++ /dev/null @@ -1,242 +0,0 @@ -# Execution Contract: v0.3.0 Workflow Enhancements - -## Intent Lock - -- **Change name**: v0.3.0-workflow-enhancements -- **Problem being solved**: spec-superflow v0.2.1 有 4 个短板 — 任务拆解粒度不足(缺少精确文件路径和 TDD 展开)、执行模式单一(只有 SDD subagent)、无放弃路径(7 态只有 closing 终态)、验证维度不足(只检查 spec compliance)。v0.3.0 补齐它们,为 v1.0.0 奠基。 -- **In scope**: - 1. spec-forger 任务拆解增强(writing-plans 方法论:File Structure + Interfaces + TDD 展开 + 零占位符) - 2. execution-governor Inline 执行模式(≤3 任务 + 无跨模块依赖 → 单会话执行 + checkpoint review) - 3. abandoned 终态(第 8 态 + abandonment-summary.md + 部分代码保留 + spec-syncer 阻断) - 4. 三维验证(Completeness + Correctness + Coherence → closure-archivist + Validator.validateImplementation()) - 5. 模板更新(tasks.md、execution-contract.md、abandonment-summary.md) - 6. 版本同步(package.json / plugin.json / marketplace.json → 0.3.0)+ CHANGELOG + CI/CD 发布 -- **Out of scope**: CLI 工具链、可配置 Schema、git worktree 隔离、spec-syncer 增强、多平台适配器、skill-creator - -## Approved Behavior - -### task-planning (5 requirements — MODIFIED) - -| # | Requirement | Key Scenario | Acceptance Check | -|---|-------------|-------------|-----------------| -| TP-1 | Enhanced Task Granularity | 每个 task step 是 2-5 分钟原子操作,TDD 5 阶段展开 | tasks.md 中每个 task 有 5 个 TDD 步骤,无"implement the module"等模糊指令 | -| TP-2 | Precise File Path Declaration | 每个 task 声明 `Create:` / `Modify:` 精确路径 | 所有修改包含行范围或区域 | -| TP-3 | Interface Contract Declaration | 每个 task 有 Interfaces 块(Consumes/Produces) | 接口条目指定函数名、参数类型、返回类型 | -| TP-4 | Zero Placeholder Enforcement | 禁止 TBD/TODO/implement later | spec-forger 完成前扫描占位符并解析 | -| TP-5 | File Structure Section | tasks.md 以 File Structure 开头 | 所有 task 引用的文件都出现在 File Structure | - -### inline-execution (3 requirements — ADDED) - -| # | Requirement | Key Scenario | Acceptance Check | -|---|-------------|-------------|-----------------| -| IE-1 | Inline Execution Mode | ≤3 任务 + 无跨模块 → 当前会话执行,不 dispatch subagent | execution-governor 检查 task count 和依赖后选择模式 | -| IE-2 | Inline Mode Checkpoint Review | 每个 task 完成后 checkpoint 验证 spec compliance + done-when | 不通过不进入下一个 task | -| IE-3 | Execution Mode Selection Criteria | 自动选择 + 用户可覆盖 | 报告选择理由,记录覆盖到 progress ledger | - -### abandonment-workflow (4 requirements — ADDED) - -| # | Requirement | Key Scenario | Acceptance Check | -|---|-------------|-------------|-----------------| -| AW-1 | Abandoned Terminal State | 任何非终态可转 abandoned,转后禁止再转 | workflow-orchestrator 阻断 abandoned → 其他状态 | -| AW-2 | Abandonment Summary Generation | 生成 abandonment-summary.md(Reason ≥50 chars + Lessons Learned ≥1 insight) | 文件存在且满足最低长度 | -| AW-3 | Partial Code Preservation | 用户可选保留部分变更([abandoned] 前缀 commit) | 保留的 commit 记录在 summary 中 | -| AW-4 | No Delta Spec Merge on Abandonment | abandoned 变更的 delta specs 不可 sync | spec-syncer 检测到 abandoned 状态后拒绝 | - -### verification-framework (3 requirements — MODIFIED) - -| # | Requirement | Key Scenario | Acceptance Check | -|---|-------------|-------------|-----------------| -| VF-1 | Three-Dimensional Verification | Completeness(全做了吗)+ Correctness(做对了吗)+ Coherence(设计体现吗) | 三维各有独立 findings 列表 | -| VF-2 | Verification Dimension Report | 每维 PASS/FAIL/WARN + overall verdict PASS/CONDITIONAL/FAIL | FAIL 阻断完成声明 | -| VF-3 | Implementation Validator Engine | `Validator.validateImplementation(diffSummary, specContent, designContent)` → VerificationReport | API 可导入,3 个维度各返回 findings | - -### state-machine (2 requirements — MODIFIED) - -| # | Requirement | Key Scenario | Acceptance Check | -|---|-------------|-------------|-----------------| -| SM-1 | Eight-State Workflow | 8 态枚举完整(+abandoned) | workflow-orchestrator 和 docs 都列出 8 态 | -| SM-2 | Abandoned State Routing | 任何非终态 → abandoned 允许;debugging escalation 提供两个选项 | 不自动 abandoned,需用户确认 | - -## Design Constraints - -### Architecture Constraints (from design.md Decisions) - -1. **D1**: writing-plans 方法论嵌入 spec-forger,不创建独立 skill → 不新建 `skills/writing-plans/` 目录 -2. **D2**: Inline 模式是 execution-governor 内部分支,不是独立 skill → 不新建 `skills/inline-executor/` 目录 -3. **D3**: abandoned 是终态,不允许回退 → 不实现 abandoned → exploring 的路由 -4. **D4**: 三维验证是 closure-archivist 增强,不是新 skill → 不新建 `skills/verifier/` 目录 -5. **D5**: Validator 保持零依赖 + regex 解析 → 不引入 Zod、tree-sitter 或 git 依赖 - -### Interface Constraints - -- `Validator.validateImplementation()` 签名固定:`(diffSummary: string, specContent: string, designContent: string) → VerificationReport` -- 新增类型必须从 `src/index.ts` 导出:`VerificationDimension`, `VerificationStatus`, `VerificationFinding`, `VerificationReport` -- tasks.md 模板格式(File Structure + Interfaces)是 spec-forger 和 downstream skills 的共享接口 - -### Dependency Constraints - -- 零外部 npm 依赖(保持 `devDependencies` 仅有 `typescript`) -- Node >= 22 -- 所有解析使用纯正则 - -### Data Constraints - -- `templates/abandonment-summary.md` Reason 段最低 50 字符(`MIN_ABANDONMENT_REASON_LENGTH = 50`) -- `VerificationReport.verdict` 仅三个值:`PASS` / `CONDITIONAL` / `FAIL` - -## Task Batches - -### Batch 1: Templates + Type Foundations - -- **Objective**: 建立所有后续 batch 的基础 — 新模板 + 验证类型 + 常量 -- **Inputs**: 现有 `templates/`、`src/validation/types.ts`、`src/validation/constants.ts`、`src/index.ts` -- **Outputs**: 更新的 tasks.md 模板、execution-contract.md 模板、新的 abandonment-summary.md 模板、VerificationReport 类型、验证常量、新导出 -- **Done when**: `npm run build` 编译通过,`dist/` 包含新类型声明 - -### Batch 2: Enhanced Task Planning (spec-forger) - -- **Objective**: spec-forger 的 tasks.md 生成能力达到 writing-plans 水平 -- **Inputs**: Batch 1 产出的 tasks.md 模板 -- **Outputs**: 更新的 `skills/spec-forger/SKILL.md`(任务拆解章节 + 验证清单 + 自审清单) -- **Done when**: spec-forger SKILL.md 包含 File Structure、Interfaces、TDD 5 阶段、零占位符规则 -- **Depends on**: Batch 1 - -### Batch 3: Inline Execution Mode (execution-governor) - -- **Objective**: execution-governor 支持 SDD + Inline 双模式 -- **Inputs**: Batch 2 产出的 spec-forger(新任务格式)、execution-contract.md 模板(Execution Mode 字段) -- **Outputs**: 更新的 `skills/execution-governor/SKILL.md`(模式选择 + Inline 循环 + 升级路径) -- **Done when**: SKILL.md 有明确的模式选择标准、Inline per-task 循环、Inline→SDD 升级规则 -- **Depends on**: Batch 2 - -### Batch 4: Abandonment Workflow (workflow-orchestrator + spec-syncer) - -- **Objective**: 8 态状态机 + abandoned 终态 + 放弃流程 -- **Inputs**: Batch 1 产出的 abandonment-summary.md 模板、`MIN_ABANDONMENT_REASON_LENGTH` 常量 -- **Outputs**: 更新的 workflow-orchestrator(8 态 + abandoned 路由 + guardrails)、spec-syncer(abandoned guard)、docs/state-machine.md -- **Done when**: workflow-orchestrator 列出 8 态、abandoned 路由规则完整、spec-syncer 阻断 abandoned sync -- **Depends on**: Batch 1 - -### Batch 5: Three-Dimensional Verification (Validator + closure-archivist) - -- **Objective**: Validator 引擎 + closure-archivist 整合三维验证 -- **Inputs**: Batch 1 产出的 VerificationReport 类型和常量 -- **Outputs**: `Validator.validateImplementation()` 方法、closure-archivist 五步验证 + 报告格式 -- **Done when**: 新测试通过(Completeness/Correctness/Coherence 各至少一个测试)、`npm test` 全绿 -- **Depends on**: Batch 1 - -### Batch 6: Integration Tests + Version Bump + Publish - -- **Objective**: 全面测试 + 版本号同步 + CI/CD 发布 -- **Inputs**: Batch 1-5 所有产出 -- **Outputs**: 新增 e2e 测试用例、版本号 0.3.0(3 个文件)、CHANGELOG.md 条目、git tag v0.3.0 -- **Done when**: `npm run build && npm test` 全绿、3 个版本文件一致、tag 推送触发 CI/CD -- **Depends on**: Batch 1-5 - -## Test Obligations - -### Must Start With Failing Tests - -- `validateImplementation()` — Batch 1 task 1.1 写失败测试(方法不存在),Batch 5 task 5.1 写 Completeness 失败测试 -- Inline mode selection — 无独立代码模块(逻辑在 SKILL.md 中),无需代码级测试 -- abandoned state — 无独立代码模块(逻辑在 SKILL.md 中),无需代码级测试 - -### Required Edge Cases - -- `validateImplementation()`: - - diff 覆盖所有 requirements → PASS - - diff 缺少某个 requirement → FAIL (Completeness) - - diff 包含 TODO/FIXME → FAIL (Correctness) - - design decision 在 diff 中不可见 → WARN (Coherence) - - 空 diff summary → FAIL (Completeness) - - 空 spec content → PASS (无 requirements = 无遗漏) - -### Regression-Sensitive Areas - -- 现有 `validateSpecContent()`、`validateChangeContent()`、`validateDeltaSpec()` — 不可修改已有行为 -- 现有 e2e 测试 — 不可删除或弱化 -- `src/index.ts` 导出 — 只能追加,不能移除已有导出 - -## Execution Mode - -- **Mode**: `SDD` -- **Selection rationale**: 40+ tasks, 6 batches, 跨模块依赖(src/validation/ + skills/ + templates/ + docs/ + tests/)→ SDD 模式 - -## Verification Dimensions - -| Dimension | Status | Findings | -|-----------|--------|----------| -| Completeness | Pending | — | -| Correctness | Pending | — | -| Coherence | Pending | — | - -**Overall verdict**: Pending - -## Review Gates - -### Mandatory Review Points - -- **Batch 1 → 2**: 模板和类型基础完成后,验证编译通过 -- **Batch 3 → 4**: Inline 模式 SKILL.md 完成后,验证与 spec-forger 新任务格式兼容 -- **Batch 5 → 6**: Validator 扩展完成后,验证 `npm test` 全绿(含新测试) -- **Batch 6 完成**: 全量 review — 版本号一致、CHANGELOG 完整、CI/CD 发布成功 - -### Blocker Categories - -- `npm run build` 编译失败 → 必须修复才能继续 -- `npm test` 任何测试失败 → 必须修复才能继续 -- SKILL.md 中出现 TBD/TODO → 必须解决才能 handoff -- 版本号不一致(package.json ≠ plugin.json ≠ marketplace.json)→ 必须同步才能发布 - -## Escalation Rules - -### Return to `specifying` when: - -- 实现中发现某个 requirement 需要修改(如 Inline 模式的阈值从 3 改为其他值) -- 新增 requirement 浮现(如发现需要额外的模板字段) -- design.md 的某个 Decision 被证明不可行 - -### Return to `bridging` when: - -- tasks.md 的 batch 结构需要重组(如发现 Batch 2 和 Batch 3 有循环依赖) -- execution-contract.md 的 test obligation 需要补充 -- scope fence 需要调整(如某个 Out of Scope 项需要拉入) - -### Do not continue implementation if: - -- `npm run build` 失败且 3 次修复尝试后仍未解决 → 进入 `debugging` -- 某个 batch 完成后 `npm test` 有 regression → 进入 `debugging` -- 用户要求放弃变更 → 进入 `abandoned` -- systematic-debugger 3+ 次修复失败 → 提供 abandoned 选项 - -### Transition to `abandoned` when: - -- 用户明确请求放弃 -- systematic-debugger 建议放弃且用户确认 -- 实现过程中发现 v0.3.0 方向根本性错误 - -## Coverage Cross-Check - -17 requirements 全部映射到 test obligations 和 execution batches: - -| Requirement | Test Obligation | Batch | -|-------------|----------------|-------| -| TP-1 Enhanced Task Granularity | SKILL.md 审查(无代码级测试) | 2 | -| TP-2 Precise File Path Declaration | SKILL.md 审查 | 2 | -| TP-3 Interface Contract Declaration | SKILL.md 审查 | 2 | -| TP-4 Zero Placeholder Enforcement | SKILL.md 审查 | 2 | -| TP-5 File Structure Section | SKILL.md 审查 | 2 | -| IE-1 Inline Execution Mode | SKILL.md 审查 | 3 | -| IE-2 Inline Mode Checkpoint Review | SKILL.md 审查 | 3 | -| IE-3 Execution Mode Selection | SKILL.md 审查 | 3 | -| AW-1 Abandoned Terminal State | SKILL.md + docs 审查 | 4 | -| AW-2 Abandonment Summary Generation | 模板审查 + 常量验证 | 4 | -| AW-3 Partial Code Preservation | SKILL.md 审查 | 4 | -| AW-4 No Delta Spec Merge on Abandonment | SKILL.md 审查 | 4 | -| VF-1 Three-Dimensional Verification | `validateImplementation()` e2e 测试 | 5 | -| VF-2 Verification Dimension Report | `validateImplementation()` e2e 测试 | 5 | -| VF-3 Implementation Validator Engine | `validateImplementation()` e2e 测试 | 5+6 | -| SM-1 Eight-State Workflow | docs + SKILL.md 审查 | 4 | -| SM-2 Abandoned State Routing | docs + SKILL.md 审查 | 4 | - -**Coverage gaps**: None. All 17 requirements mapped. diff --git a/changes/v0.3.0-workflow-enhancements/proposal.md b/changes/v0.3.0-workflow-enhancements/proposal.md deleted file mode 100644 index f1e6fd5..0000000 --- a/changes/v0.3.0-workflow-enhancements/proposal.md +++ /dev/null @@ -1,72 +0,0 @@ -# Change Proposal: v0.3.0 Workflow Enhancements - -## Why - -spec-superflow v0.2.1 整合了 OpenSpec 规划引擎和 Superpowers 执行纪律,但在实际使用中暴露四个关键短板: - -1. **任务拆解粒度不足** — spec-forger 生成的 tasks.md 只有粗粒度步骤("write test → implement → review"),缺少精确文件路径、接口契约、TDD 红绿重构展开。Superpowers 的 writing-plans 方法论远更成熟,但未被吸收。 -2. **执行模式单一** — execution-governor 只有 SDD subagent 模式,小改动(≤3 任务、无跨模块依赖)也要 dispatch subagent + reviewer,太重。缺少轻量 inline 模式。 -3. **无放弃路径** — 7 态状态机只有 closing 一个终态。执行中发现方向错误时无法优雅退出,只能卡住或强行关闭。 -4. **验证维度不足** — closure-archivist 只检查 spec compliance(SHALL/MUST 关键词、scenario 覆盖),缺少对实现完整性(Completeness)、正确性(Correctness)、设计一致性(Coherence)的系统检查。OpenSpec 的三维验证框架更可靠。 - -这四个短板阻碍了 spec-superflow 从"可用"走向"可靠"。v0.3.0 的目标是补齐它们,为 v1.0.0 奠定基础。 - -## What Changes - -- spec-forger 的任务拆解逻辑重写:吸收 writing-plans 方法论(每步 2-5 分钟、精确文件路径、Interfaces 块、TDD 展开、零占位符) -- tasks.md 模板更新:增加 File Structure 和 Interfaces 部分 -- execution-governor 增加双模式路由:SDD 模式(大改动)和 Inline 模式(小改动),保留 TDD Iron Law -- execution-contract.md 模板增加 Execution Mode 和 Verification Dimensions 字段 -- 状态机扩展为 8 态:新增 `abandoned` 终态 -- workflow-orchestrator 路由规则更新:任何状态可转向 abandoned -- 新增 abandonment-summary.md 模板 -- closure-archivist 整合三维验证框架(Completeness + Correctness + Coherence) -- Validator 引擎扩展:新增 `validateImplementation()` 方法 -- docs/state-machine.md 更新为 8 态 - -## Capabilities - -### New Capabilities - -- `inline-execution` — 轻量级单会话执行模式,与 SDD 并行 -- `abandonment-workflow` — 变更放弃路径,含原因记录 + 教训总结 + 部分代码保留 - -### Modified Capabilities - -- `task-planning` — spec-forger 任务拆解增强(writing-plans 方法论) -- `verification-framework` — closure-archivist 三维验证(Completeness + Correctness + Coherence) -- `state-machine` — 8 态(+abandoned 终态) - -## Scope - -### In Scope - -- spec-forger SKILL.md 任务拆解章节重写 -- tasks.md 模板更新(File Structure + Interfaces) -- execution-governor SKILL.md 双模式路由 -- execution-contract.md 模板增加 Execution Mode + Verification Dimensions -- workflow-orchestrator SKILL.md 路由规则 + 状态定义更新 -- closure-archivist SKILL.md 三维验证整合 -- 新增 abandonment-summary.md 模板 -- Validator 引擎新增 `validateImplementation()` 方法 -- src/validation/constants.ts 新增三维验证相关常量 -- docs/state-machine.md 更新为 8 态 -- src/index.ts 导出新类型 -- tests/e2e.test.ts 新增验证测试用例 -- package.json / plugin.json / marketplace.json 版本同步至 0.3.0 -- CHANGELOG.md 添加 v0.3.0 条目 - -### Out of Scope - -- CLI 工具链(留给 v0.4.0) -- 可配置 Schema / YAML 工件依赖图(留给 v0.4.0) -- git worktree 隔离工作区 -- spec-syncer 增强 -- 多平台适配器扩展 -- skill-creator 工具包 - -## Impact - -- Affected code areas: `skills/spec-forger/`, `skills/execution-governor/`, `skills/closure-archivist/`, `skills/workflow-orchestrator/`, `src/validation/`, `templates/`, `docs/`, `tests/` -- Affected APIs or interfaces: `Validator` class 新增 `validateImplementation()` 方法;`src/index.ts` 新增导出类型 `VerificationDimension`, `VerificationResult` -- Dependencies or systems touched: 无新增外部依赖(保持零 npm 依赖约束) diff --git a/changes/v0.3.0-workflow-enhancements/specs/abandonment-workflow/spec.md b/changes/v0.3.0-workflow-enhancements/specs/abandonment-workflow/spec.md deleted file mode 100644 index 745e0bd..0000000 --- a/changes/v0.3.0-workflow-enhancements/specs/abandonment-workflow/spec.md +++ /dev/null @@ -1,68 +0,0 @@ -# abandonment-workflow Spec - -## ADDED Requirements - -### Requirement: Abandoned Terminal State - -The workflow state machine SHALL include `abandoned` as a terminal state parallel to `closing`, reachable from any other state. - -#### Scenario: Transition to abandoned - -- **WHEN** the user explicitly requests to abandon a change -- **OR** systematic-debugger escalates after 3+ failed fix attempts -- **OR** scope change during specifying makes the change no longer worthwhile -- **THEN** workflow-orchestrator SHALL transition the state to `abandoned` -- **AND** SHALL NOT allow any further state transitions from `abandoned` - -#### Scenario: Abandoned blocks further execution - -- **WHEN** the current state is `abandoned` -- **THEN** workflow-orchestrator SHALL block all skill invocations except reading the abandonment summary -- **AND** SHALL inform the user that the change is abandoned and suggest starting a new change - -### Requirement: Abandonment Summary Generation - -Entering the abandoned state SHALL trigger generation of an `abandonment-summary.md` file documenting the reason, lessons learned, and recommendations. - -#### Scenario: Summary structure - -- **WHEN** the state transitions to `abandoned` -- **THEN** the system SHALL generate `abandonment-summary.md` containing: - - `## Change`: the change name and original goal - - `## Reason`: why the change was abandoned - - `## What Was Tried`: actions taken before abandonment - - `## Lessons Learned`: insights gained that may help future attempts - - `## Recommendations`: suggested next steps or alternative approaches - -#### Scenario: Summary completeness - -- **WHEN** abandonment-summary.md is generated -- **THEN** the Reason section SHALL contain at least 50 characters of explanation -- **AND** the Lessons Learned section SHALL contain at least one concrete insight - -### Requirement: Partial Code Preservation - -The abandonment workflow SHALL allow the user to optionally preserve useful code changes made before abandonment. - -#### Scenario: Preserve partial work - -- **WHEN** the user chooses to preserve partial work during abandonment -- **THEN** the system SHALL list all uncommitted changes in the working tree -- **AND** SHALL allow the user to select which changes to commit with an `[abandoned]` prefix in the commit message -- **AND** SHALL record preserved commits in the abandonment summary - -#### Scenario: No preservation - -- **WHEN** the user chooses not to preserve partial work -- **THEN** the system SHALL advise the user to use `git stash` or `git checkout` to discard changes -- **AND** SHALL NOT automatically discard any work - -### Requirement: No Delta Spec Merge on Abandonment - -An abandoned change SHALL NOT merge its delta specs into the main spec base. - -#### Scenario: Spec sync blocked - -- **WHEN** a change is in the `abandoned` state -- **THEN** spec-syncer SHALL refuse to process any delta specs from this change -- **AND** SHALL report that abandoned changes cannot be synced diff --git a/changes/v0.3.0-workflow-enhancements/specs/inline-execution/spec.md b/changes/v0.3.0-workflow-enhancements/specs/inline-execution/spec.md deleted file mode 100644 index eb7a6eb..0000000 --- a/changes/v0.3.0-workflow-enhancements/specs/inline-execution/spec.md +++ /dev/null @@ -1,50 +0,0 @@ -# inline-execution Spec - -## ADDED Requirements - -### Requirement: Inline Execution Mode - -execution-governor SHALL support an Inline execution mode for small changes (≤ 3 tasks, no cross-module dependencies) where implementation happens in the current session without subagent dispatch. - -#### Scenario: Inline mode activation - -- **WHEN** execution-contract.md specifies `Execution Mode: Inline` -- **AND** the task count is ≤ 3 -- **AND** no task has cross-module dependencies -- **THEN** execution-governor SHALL execute tasks sequentially in the current session -- **AND** SHALL NOT dispatch implementer or reviewer subagents - -#### Scenario: TDD Iron Law preserved in Inline mode - -- **WHEN** executing in Inline mode -- **THEN** every code-producing task SHALL follow the TDD Iron Law (failing test first) -- **AND** the governor SHALL block production code written without a preceding failing test - -### Requirement: Inline Mode Checkpoint Review - -Inline mode SHALL insert a checkpoint review after each completed task, where the governor verifies spec compliance before proceeding to the next task. - -#### Scenario: Checkpoint review after task - -- **WHEN** a task completes in Inline mode -- **THEN** execution-governor SHALL verify the task output against its spec requirements -- **AND** SHALL verify the task output against its done-when criteria from the execution contract -- **AND** SHALL NOT proceed to the next task until all checks pass - -### Requirement: Execution Mode Selection Criteria - -execution-governor SHALL automatically select the execution mode based on task count and dependency analysis, with user override capability. - -#### Scenario: Automatic mode selection - -- **WHEN** execution-governor receives an approved execution contract -- **THEN** it SHALL count the total tasks and analyze cross-module dependencies -- **AND** if tasks ≤ 3 and no cross-module dependencies → select Inline mode -- **AND** otherwise → select SDD mode -- **AND** SHALL report the selected mode and reasoning to the user before starting - -#### Scenario: User mode override - -- **WHEN** the user explicitly requests a specific execution mode -- **THEN** execution-governor SHALL use the requested mode regardless of automatic selection -- **AND** SHALL record the override in the progress ledger diff --git a/changes/v0.3.0-workflow-enhancements/specs/state-machine/spec.md b/changes/v0.3.0-workflow-enhancements/specs/state-machine/spec.md deleted file mode 100644 index 6266dd2..0000000 --- a/changes/v0.3.0-workflow-enhancements/specs/state-machine/spec.md +++ /dev/null @@ -1,37 +0,0 @@ -# state-machine Spec - -## MODIFIED Requirements - -### Requirement: Eight-State Workflow - -The workflow state machine SHALL consist of 8 states: `exploring`, `specifying`, `bridging`, `approved-for-build`, `executing`, `debugging`, `closing`, and `abandoned`. - -#### Scenario: State enumeration - -- **WHEN** workflow-orchestrator inspects the current change context -- **THEN** it SHALL classify the change into exactly one of the 8 defined states -- **AND** SHALL NOT classify into any state not in the enumeration - -#### Scenario: Terminal states - -- **WHEN** the state is `closing` or `abandoned` -- **THEN** the state machine SHALL NOT allow transitions to any other state -- **AND** SHALL inform the user that the change has reached its terminal state - -### Requirement: Abandoned State Routing - -workflow-orchestrator SHALL allow transitions to `abandoned` from any non-terminal state. - -#### Scenario: Universal abandoned transition - -- **WHEN** the user requests abandonment -- **AND** the current state is NOT `closing` or `abandoned` -- **THEN** workflow-orchestrator SHALL transition to `abandoned` -- **AND** SHALL trigger abandonment summary generation - -#### Scenario: Debugging escalation to abandoned - -- **WHEN** systematic-debugger reports 3+ consecutive fix failures -- **AND** the debugger recommends questioning the architecture -- **THEN** workflow-orchestrator SHALL present the user with two options: (1) escalate to architectural review, (2) transition to `abandoned` -- **AND** SHALL NOT automatically abandon without user confirmation diff --git a/changes/v0.3.0-workflow-enhancements/specs/task-planning/spec.md b/changes/v0.3.0-workflow-enhancements/specs/task-planning/spec.md deleted file mode 100644 index c85a8d9..0000000 --- a/changes/v0.3.0-workflow-enhancements/specs/task-planning/spec.md +++ /dev/null @@ -1,58 +0,0 @@ -# task-planning Spec - -## MODIFIED Requirements - -### Requirement: Enhanced Task Granularity - -spec-forger SHALL generate tasks.md where each task step is a 2-5 minute atomic operation with explicit TDD phases (write failing test → confirm fail → implement → confirm green → commit). - -#### Scenario: Task step granularity enforcement - -- **WHEN** spec-forger generates a tasks.md artifact -- **THEN** every task step SHALL be completable in 2-5 minutes of focused work -- **AND** no task step SHALL contain vague instructions like "implement the module" or "add appropriate tests" - -#### Scenario: TDD phase expansion - -- **WHEN** a task involves code implementation -- **THEN** the task SHALL expand into explicit TDD phases: (1) write the failing test with exact test code, (2) run the test and confirm it fails for the expected reason, (3) implement the minimal code, (4) run the test and confirm it passes, (5) commit - -### Requirement: Precise File Path Declaration - -Each task SHALL declare exact file paths for every file it creates or modifies, using the format `Create: path/to/file.ts` or `Modify: path/to/file.ts:line-range`. - -#### Scenario: File path presence check - -- **WHEN** a task creates or modifies source code -- **THEN** the task MUST list each affected file with its absolute or project-relative path -- **AND** modifications MUST include the line range or section being changed - -### Requirement: Interface Contract Declaration - -Each task SHALL declare an Interfaces block specifying what it consumes from earlier tasks and what later tasks rely on, including exact function names, parameter types, and return types. - -#### Scenario: Interfaces block presence - -- **WHEN** a task produces output consumed by later tasks -- **THEN** the task MUST include an `Interfaces` section with `Consumes` (inputs from earlier tasks) and `Produces` (outputs for later tasks) -- **AND** each interface entry MUST specify the function name, parameter types, and return type - -### Requirement: Zero Placeholder Enforcement - -tasks.md SHALL NOT contain any placeholder language including "TBD", "TODO", "implement later", "figure out", "add appropriate", or similar vague markers. - -#### Scenario: Placeholder scan - -- **WHEN** spec-forger completes tasks.md generation -- **THEN** the artifact SHALL be scanned for placeholder patterns -- **AND** any detected placeholder SHALL be resolved before handoff to bridge-contract - -### Requirement: File Structure Section - -tasks.md SHALL include a File Structure section listing all files to be created or modified, with each file's responsibility stated in one sentence. - -#### Scenario: File structure presence - -- **WHEN** spec-forger generates tasks.md -- **THEN** the artifact MUST begin with a `## File Structure` section -- **AND** every file referenced in any task MUST appear in the File Structure section with its responsibility diff --git a/changes/v0.3.0-workflow-enhancements/specs/verification-framework/spec.md b/changes/v0.3.0-workflow-enhancements/specs/verification-framework/spec.md deleted file mode 100644 index 8ce26ec..0000000 --- a/changes/v0.3.0-workflow-enhancements/specs/verification-framework/spec.md +++ /dev/null @@ -1,63 +0,0 @@ -# verification-framework Spec - -## MODIFIED Requirements - -### Requirement: Three-Dimensional Verification - -closure-archivist SHALL verify implementation quality across three orthogonal dimensions: Completeness, Correctness, and Coherence. - -#### Scenario: Completeness verification - -- **WHEN** closure-archivist runs the Completeness dimension -- **THEN** it SHALL verify that every task in tasks.md has a corresponding code change -- **AND** every SHALL/MUST requirement in specs/ has at least one implementation artifact -- **AND** every delta spec operation (ADDED/MODIFIED/REMOVED/RENAMED) is reflected in the code changes -- **AND** SHALL report missing items as CRITICAL issues - -#### Scenario: Correctness verification - -- **WHEN** closure-archivist runs the Correctness dimension -- **THEN** it SHALL verify that all tests pass with zero failures -- **AND** boundary conditions identified in specs are covered by test cases -- **AND** error handling paths specified in design.md are implemented -- **AND** each Scenario's GIVEN/WHEN/THEN has a corresponding test assertion -- **AND** SHALL report failures as CRITICAL issues - -#### Scenario: Coherence verification - -- **WHEN** closure-archivist runs the Coherence dimension -- **THEN** it SHALL verify that design.md decisions are visible in the code (naming, patterns, architecture) -- **AND** naming conventions are consistent across implementation and specs -- **AND** no "say one thing, do another" patterns exist (spec describes behavior X but code implements Y) -- **AND** SHALL report inconsistencies as IMPORTANT issues - -### Requirement: Verification Dimension Report - -closure-archivist SHALL produce a structured verification report with per-dimension results and an overall verdict. - -#### Scenario: Report structure - -- **WHEN** all three dimensions have been verified -- **THEN** closure-archivist SHALL produce a report containing: - - Per-dimension status: PASS / FAIL / WARN - - Per-dimension findings list (issue level + description) - - Overall verdict: PASS (all dimensions PASS), CONDITIONAL (WARN only), FAIL (any CRITICAL) -- **AND** SHALL NOT claim completion unless overall verdict is PASS or user accepts CONDITIONAL - -### Requirement: Implementation Validator Engine - -The Validator class SHALL provide a `validateImplementation()` method that accepts a diff summary, spec content, and design content, and returns a VerificationReport. - -#### Scenario: validateImplementation API - -- **WHEN** `validateImplementation(diffSummary, specContent, designContent)` is called -- **THEN** it SHALL return a `VerificationReport` object with: - - `dimensions`: array of `{ name: VerificationDimension, status: 'PASS'|'FAIL'|'WARN', findings: VerificationFinding[] }` - - `verdict`: `'PASS' | 'CONDITIONAL' | 'FAIL'` -- **AND** the method SHALL check for placeholder markers in the diff summary -- **AND** the method SHALL verify that all SHALL/MUST requirements from specContent appear in the diff summary - -#### Scenario: Verification types exported - -- **WHEN** a consumer imports from spec-superflow -- **THEN** the following types SHALL be available: `VerificationDimension`, `VerificationStatus`, `VerificationFinding`, `VerificationReport` diff --git a/changes/v0.3.0-workflow-enhancements/tasks.md b/changes/v0.3.0-workflow-enhancements/tasks.md deleted file mode 100644 index 0c09951..0000000 --- a/changes/v0.3.0-workflow-enhancements/tasks.md +++ /dev/null @@ -1,835 +0,0 @@ -# Implementation Tasks: v0.3.0 Workflow Enhancements - -## File Structure - -- `Create: templates/abandonment-summary.md` — Template for abandonment summaries (Change, Reason, What Was Tried, Lessons Learned, Recommendations) -- `Modify: templates/tasks.md` — Add File Structure section and Interfaces block format -- `Modify: templates/execution-contract.md` — Add Execution Mode and Verification Dimensions fields -- `Modify: src/validation/types.ts` — Add VerificationDimension, VerificationStatus, VerificationFinding, VerificationReport types -- `Modify: src/validation/constants.ts` — Add verification-related constants and messages -- `Modify: src/validation/validator.ts` — Add validateImplementation() method -- `Modify: src/index.ts` — Export new verification types -- `Modify: skills/spec-forger/SKILL.md` — Rewrite tasks.md generation chapter with writing-plans methodology -- `Modify: skills/execution-governor/SKILL.md` — Add dual-mode routing (SDD vs Inline), mode selection criteria, Inline per-task loop with checkpoint review -- `Modify: skills/closure-archivist/SKILL.md` — Add three-dimensional verification framework (Completeness + Correctness + Coherence) -- `Modify: skills/workflow-orchestrator/SKILL.md` — Add abandoned state, abandoned routing rules, universal abandoned transition guardrail -- `Modify: skills/spec-syncer/SKILL.md` — Add guard: block sync for abandoned changes -- `Modify: docs/state-machine.md` — Update to 8 states with abandoned terminal state -- `Modify: tests/e2e.test.ts` — Add test cases for validateImplementation() and new verification types -- `Modify: package.json` — Version bump to 0.3.0 -- `Modify: .claude-plugin/plugin.json` — Version bump to 0.3.0 -- `Modify: .claude-plugin/marketplace.json` — Version bump to 0.3.0 -- `Modify: CHANGELOG.md` — Add v0.3.0 entry - -## Interfaces - -### Batch 1 → Batch 2 -- **Produces**: `templates/tasks.md` (updated with File Structure + Interfaces format) — consumed by spec-forger SKILL.md updates in Batch 2 - -### Batch 1 → Batch 5 -- **Produces**: `src/validation/types.ts` (VerificationDimension, VerificationStatus, VerificationFinding, VerificationReport) — consumed by Validator.validateImplementation() in Batch 5 -- **Produces**: `src/validation/constants.ts` (VERIFICATION_DIMENSIONS, VERIFICATION_MESSAGES) — consumed by Validator in Batch 5 - -### Batch 2 → Batch 3 -- **Produces**: `skills/spec-forger/SKILL.md` (updated task planning) — execution-governor in Batch 3 references the new task format - -### Batch 5 → Batch 6 -- **Produces**: `src/validation/validator.ts` (validateImplementation method) — tested by e2e tests in Batch 6 -- **Produces**: `src/index.ts` (new exports) — imported by tests in Batch 6 - -## 1. Batch 1: Templates + Type Foundations - -- [ ] **1.1 Write failing test for VerificationReport type exports** - -```typescript -// tests/e2e.test.ts — append new test -import { test } from 'node:test'; -import assert from 'node:assert/strict'; -import { Validator } from '../dist/index.js'; - -test('validateImplementation returns VerificationReport with three dimensions', () => { - const v = new Validator(); - const report = v.validateImplementation( - 'Added auth middleware in src/middleware/auth.ts', - '### Requirement: Auth middleware\nThe system SHALL authenticate all API requests.\n#### Scenario: Valid token\n- **WHEN** a request has a valid token\n- **THEN** the system SHALL allow access', - '## Decisions\n### Decision 1\n- Choice: JWT-based auth\n- Rationale: stateless' - ); - assert.ok(report.dimensions); - assert.equal(report.dimensions.length, 3); - assert.ok(['Completeness', 'Correctness', 'Coherence'].includes(report.dimensions[0].name)); - assert.ok(['PASS', 'FAIL', 'WARN'].includes(report.verdict)); -}); -``` - -**Files**: `Modify: tests/e2e.test.ts` - -- [ ] **1.2 Run test and confirm it fails** - -Run: `npm run build && npm test` -Expected: FAIL — `validateImplementation` is not a function - -- [ ] **1.3 Add VerificationReport types to src/validation/types.ts** - -```typescript -// Append to src/validation/types.ts - -export type VerificationDimension = 'Completeness' | 'Correctness' | 'Coherence'; -export type VerificationStatus = 'PASS' | 'FAIL' | 'WARN'; - -export interface VerificationFinding { - level: 'CRITICAL' | 'IMPORTANT' | 'INFO'; - dimension: VerificationDimension; - message: string; -} - -export interface VerificationReport { - dimensions: { - name: VerificationDimension; - status: VerificationStatus; - findings: VerificationFinding[]; - }[]; - verdict: 'PASS' | 'CONDITIONAL' | 'FAIL'; -} -``` - -**Files**: `Modify: src/validation/types.ts` -**Interfaces**: Produces `VerificationDimension`, `VerificationStatus`, `VerificationFinding`, `VerificationReport` — consumed by Batch 5 (Validator.validateImplementation) - -- [ ] **1.4 Add verification constants to src/validation/constants.ts** - -```typescript -// Append to src/validation/constants.ts - -export const VERIFICATION_DIMENSIONS = ['Completeness', 'Correctness', 'Coherence'] as const; - -export const VERIFICATION_MESSAGES = { - COMPLETENESS_MISSING_TASK: 'Task in tasks.md has no corresponding code change in diff summary', - COMPLETENESS_MISSING_REQUIREMENT: 'SHALL/MUST requirement in spec has no matching implementation in diff summary', - CORRECTNESS_TEST_FAILURE: 'Test suite has failures', - CORRECTNESS_MISSING_SCENARIO: 'Spec scenario has no corresponding test assertion', - COHERENCE_NAMING_MISMATCH: 'Design decision naming does not match implementation naming', - COHERENCE_PATTERN_MISSING: 'Architecture pattern from design.md not found in implementation', - VERIFICATION_PLACEHOLDER_DETECTED: 'Diff summary contains placeholder markers (TODO, FIXME, HACK)', -} as const; - -export const MIN_ABANDONMENT_REASON_LENGTH = 50; -``` - -**Files**: `Modify: src/validation/constants.ts` -**Interfaces**: Produces `VERIFICATION_DIMENSIONS`, `VERIFICATION_MESSAGES`, `MIN_ABANDONMENT_REASON_LENGTH` — consumed by Batch 4 (abandonment) and Batch 5 (Validator) - -- [ ] **1.5 Export new types from src/index.ts** - -```typescript -// Append to src/index.ts -export type { VerificationDimension, VerificationStatus, VerificationFinding, VerificationReport } from './validation/types.js'; -``` - -**Files**: `Modify: src/index.ts` -**Interfaces**: Produces public API exports — consumed by Batch 6 (tests import from dist/index.js) - -- [ ] **1.6 Update tasks.md template with File Structure and Interfaces** - -Replace content of `templates/tasks.md` with: - -```markdown -# Implementation Tasks - -## File Structure - -- `Create: path/to/new-file.ts` — One-sentence responsibility -- `Modify: path/to/existing.ts` — What changes and why - -## Interfaces - -### Batch N → Batch M -- **Produces**: `type/function name` — consumed by Batch M for purpose - -## 1. Batch 1: [Batch Objective] - -- [ ] **1.1 Write the failing test** - -\```language -// test code with exact assertions -\``` - -**Files**: `Create/Modify: exact/path` - -- [ ] **1.2 Run test and confirm it fails** - -Run: `exact command` -Expected: FAIL with "specific error message" - -- [ ] **1.3 Implement minimal code** - -\```language -// implementation code -\``` - -**Files**: `Create/Modify: exact/path` -**Interfaces**: Produces `name(type): returnType` — consumed by Batch N - -- [ ] **1.4 Run test and confirm it passes** - -Run: `exact command` -Expected: PASS - -- [ ] **1.5 Commit** - -\```bash -git add files -git commit -m "feat: description" -\``` -``` - -**Files**: `Modify: templates/tasks.md` -**Interfaces**: Produces updated template — consumed by Batch 2 (spec-forger references this format) - -- [ ] **1.7 Update execution-contract.md template** - -Add after the existing `## Test Obligations` section: - -```markdown -## Execution Mode - -- **Mode**: `SDD` | `Inline` -- **Selection rationale**: [why this mode was chosen — task count, dependency analysis] - -## Verification Dimensions - -| Dimension | Status | Findings | -|-----------|--------|----------| -| Completeness | Pending | — | -| Correctness | Pending | — | -| Coherence | Pending | — | - -**Overall verdict**: Pending -``` - -**Files**: `Modify: templates/execution-contract.md` - -- [ ] **1.8 Create abandonment-summary.md template** - -```markdown -# Abandonment Summary - -## Change - -- **Name**: [change name] -- **Original goal**: [one sentence] - -## Reason - -[At least 50 characters explaining why this change was abandoned] - -## What Was Tried - -- [Action 1 and its outcome] -- [Action 2 and its outcome] - -## Lessons Learned - -- [Concrete insight 1 that may help future attempts] - -## Recommendations - -- [Suggested next step or alternative approach] - -## Preserved Work - -- [ ] No work preserved (all changes discarded) -- [ ] Partial work preserved: - - Commit `[hash]`: [description] -``` - -**Files**: `Create: templates/abandonment-summary.md` - -- [ ] **1.9 Build and verify compilation** - -Run: `npm run build` -Expected: Compilation succeeds, `dist/` contains updated types - -- [ ] **1.10 Commit Batch 1** - -```bash -git add -A -git commit -m "feat(v0.3.0): templates + verification types foundation" -``` - -## 2. Batch 2: Enhanced Task Planning (spec-forger) - -Depends on: Batch 1 (tasks.md template updated) - -- [ ] **2.1 Rewrite spec-forger tasks.md generation chapter** - -In `skills/spec-forger/SKILL.md`, replace the `### tasks.md` section (currently lines 57-75) with a new section that includes: - -1. **File Structure requirement**: Every tasks.md MUST begin with a `## File Structure` section listing all files to create/modify with one-sentence responsibilities. -2. **Interfaces requirement**: Every tasks.md MUST include `## Interfaces` section declaring Consumes/Produces between batches. -3. **Per-task format**: Each task MUST include: - - Exact file paths (`Create:` / `Modify:` with line ranges for modifications) - - TDD phases expanded: (1) write failing test with exact code, (2) run and confirm fail, (3) implement minimal code with exact code, (4) run and confirm pass, (5) commit - - Interfaces block if the task produces output consumed by later tasks -4. **Zero placeholder rule**: Scan for "TBD", "TODO", "implement later", "figure out", "add appropriate", "we'll decide" — resolve all before handoff. -5. **Granularity enforcement**: Each task step is 2-5 minutes. If a step takes longer, decompose it. "Implement the authentication module" is NOT a task — it's a batch of tasks. -6. **Dependency declaration**: Each batch header states `Depends on: Batch N` if it consumes output from an earlier batch. - -**Files**: `Modify: skills/spec-forger/SKILL.md` -**Interfaces**: Consumes updated `templates/tasks.md` format from Batch 1 - -- [ ] **2.2 Update spec-forger tasks.md validation checklist** - -In `skills/spec-forger/SKILL.md`, replace the `### tasks.md Validation` section (currently lines 117-124) with expanded checklist: - -```markdown -### tasks.md Validation - -- [ ] Has `## File Structure` section listing all files with responsibilities -- [ ] Has `## Interfaces` section with Consumes/Produces between batches -- [ ] Tasks are numbered (1.1, 1.2, 2.1, etc.) -- [ ] Each task has exact file paths (Create/Modify with line ranges) -- [ ] Each code-producing task has expanded TDD phases (5 steps) -- [ ] Each task is ≤ 5 minutes of focused work -- [ ] No TBD, TODO, or placeholder language in any task -- [ ] Every requirement from specs/ maps to at least one task -- [ ] Dependencies are explicit (Depends on: Batch N) -- [ ] Every batch ends with a commit step -``` - -**Files**: `Modify: skills/spec-forger/SKILL.md` - -- [ ] **2.3 Update spec-forger self-review checklist** - -Add to the Self-Review Checklist section: - -```markdown -- [ ] Verify task granularity — each step is 2-5 min, atomic, concretely actionable -- [ ] Verify File Structure — every file referenced in any task appears in the File Structure section -- [ ] Verify Interfaces — every cross-batch dependency is declared in the Interfaces section -- [ ] Verify zero placeholders — grep for TBD, TODO, "implement later", "figure out", "add appropriate" -``` - -**Files**: `Modify: skills/spec-forger/SKILL.md` - -- [ ] **2.4 Commit Batch 2** - -```bash -git add -A -git commit -m "feat(v0.3.0): enhanced task planning with writing-plans methodology" -``` - -## 3. Batch 3: Inline Execution Mode (execution-governor) - -Depends on: Batch 2 (spec-forger produces tasks in new format) - -- [ ] **3.1 Add Execution Mode Selection section to execution-governor** - -In `skills/execution-governor/SKILL.md`, add a new section after `## Core Laws` and before `## SubAgent-Driven Development (SDD) Workflow`: - -```markdown -## Execution Mode Selection - -Before starting implementation, determine the execution mode: - -### Automatic Selection Criteria - -1. Count total tasks in the execution contract's task batches -2. Analyze cross-module dependencies (does any task modify files in > 2 modules?) -3. Decision: - - Tasks ≤ 3 AND no cross-module dependencies → **Inline mode** - - Otherwise → **SDD mode** (default) - -### Reporting - -Before executing the first task, report to the user: -- Selected mode and reasoning -- Total task count -- Cross-module dependency analysis (if any) -- Offer user override: "You can override this by saying 'use SDD' or 'use inline'" - -### User Override - -If the user explicitly requests a mode, use it regardless of automatic selection. Record the override in the progress ledger. -``` - -**Files**: `Modify: skills/execution-governor/SKILL.md` -**Interfaces**: Consumes execution contract's Execution Mode field (from Batch 1 template update) - -- [ ] **3.2 Add Inline Mode execution loop** - -In `skills/execution-governor/SKILL.md`, add a new section after the SDD Workflow section: - -```markdown -## Inline Execution Mode - -For small changes (≤ 3 tasks, no cross-module dependencies). - -### Per-Task Loop (Inline) - -1. **Read task**: Use `scripts/task-brief PLAN_FILE N` to extract the task -2. **Write failing test**: Follow the task's TDD phase 1 — write the exact test code specified -3. **Confirm failure**: Run the test, verify it fails for the expected reason -4. **Implement**: Follow the task's TDD phase 3 — write the exact implementation code specified -5. **Confirm green**: Run the full test suite, verify all tests pass -6. **Checkpoint review**: Before proceeding to the next task: - - Verify the task's done-when criteria from the execution contract - - Verify the task output against its spec requirements (SHALL/MUST statements) - - If any check fails → STOP, report the gap, ask user how to proceed -7. **Commit**: Follow the task's commit step -8. **Progress ledger**: Append task completion to `.superpowers/sdd/progress.md` - -### Inline → SDD Escalation - -If an inline task hits a BLOCKED state (test failure after 3 fix attempts, or the implementation requires changes outside the task's declared file paths), suggest escalating to SDD mode: -- "This task is more complex than estimated. Switch to SDD mode for subagent-driven implementation?" -``` - -**Files**: `Modify: skills/execution-governor/SKILL.md` - -- [ ] **3.3 Update execution-governor Execution Modes section** - -Replace the existing `## Execution Modes` section (currently lines 169-177) with: - -```markdown -## Execution Modes Summary - -| Aspect | SDD Mode | Inline Mode | -|--------|----------|-------------| -| Task count | > 3 or cross-module | ≤ 3, single module | -| Implementation | Subagent per task | Current session | -| Review | Reviewer subagent per task | Checkpoint review by governor | -| Model selection | Per-task model routing | Single model | -| Progress ledger | Yes | Yes | -| TDD Iron Law | Yes | Yes | -| Escalation | → systematic-debugger | → SDD mode or systematic-debugger | -``` - -**Files**: `Modify: skills/execution-governor/SKILL.md` - -- [ ] **3.4 Commit Batch 3** - -```bash -git add -A -git commit -m "feat(v0.3.0): inline execution mode with checkpoint review" -``` - -## 4. Batch 4: Abandonment Workflow (workflow-orchestrator + spec-syncer) - -Depends on: Batch 1 (abandonment-summary.md template, MIN_ABANDONMENT_REASON_LENGTH constant) - -- [ ] **4.1 Add abandoned state to workflow-orchestrator** - -In `skills/workflow-orchestrator/SKILL.md`: - -1. Add `abandoned` to the `## Default States` list (making it 8 states) -2. Add routing rule section `### Route to abandonment when:` after the existing routing rules: - -```markdown -### Route to `abandonment` when: - -- the user explicitly requests to abandon the change -- systematic-debugger has escalated after 3+ consecutive fix failures AND the user chooses to abandon -- scope change during specifying makes the change no longer worthwhile AND the user confirms abandonment -- the current state is NOT `closing` or `abandoned` (terminal states block abandonment transition) -``` - -**Files**: `Modify: skills/workflow-orchestrator/SKILL.md` -**Interfaces**: Consumes `MIN_ABANDONMENT_REASON_LENGTH` from Batch 1 constants - -- [ ] **4.2 Add abandoned state guardrails to workflow-orchestrator** - -Add to the `## Guardrails` section: - -```markdown -- Do not allow any state transitions FROM `abandoned` — it is a terminal state. -- Do not allow transition to `abandoned` from `closing` or `abandoned` — these are already terminal. -- Do not auto-abandon without user confirmation — even if systematic-debugger recommends it. -- When transitioning to `abandoned`, prompt for abandonment summary generation before confirming. -- Do not merge delta specs from an abandoned change — spec-syncer must block this. -``` - -**Files**: `Modify: skills/workflow-orchestrator/SKILL.md` - -- [ ] **4.3 Add abandoned change guard to spec-syncer** - -In `skills/spec-syncer/SKILL.md`, add a pre-flight check before the sync process: - -```markdown -### Pre-Flight: Abandoned Change Guard - -Before syncing any delta specs: -1. Check if the change is in the `abandoned` state -2. If abandoned → STOP and report: "Abandoned changes cannot be synced. Delta specs from abandoned changes are preserved for reference but must not be merged into the main spec base." -3. If not abandoned → proceed with normal sync flow -``` - -**Files**: `Modify: skills/spec-syncer/SKILL.md` - -- [ ] **4.4 Update docs/state-machine.md to 8 states** - -Update the state machine diagram and state descriptions to include `abandoned`: - -```markdown -## States (8) - -1. `exploring` — fuzzy intent, spec-explorer active -2. `specifying` — planning artifacts written/refined, spec-forger active -3. `bridging` — artifacts translated to execution contract, bridge-contract active -4. `approved-for-build` — contract exists and user approved it -5. `executing` — TDD, SDD/Inline, review gates active, execution-governor active -6. `debugging` — side-path from executing, systematic-debugger active -7. `closing` — terminal state, verification-with-evidence, closure-archivist active -8. `abandoned` — terminal state, change abandoned, abandonment-summary generated - -## Terminal States - -- `closing` — successful completion -- `abandoned` — change abandoned (no delta spec merge, no further transitions) -``` - -**Files**: `Modify: docs/state-machine.md` - -- [ ] **4.5 Commit Batch 4** - -```bash -git add -A -git commit -m "feat(v0.3.0): abandoned terminal state with summary generation" -``` - -## 5. Batch 5: Three-Dimensional Verification (Validator + closure-archivist) - -Depends on: Batch 1 (types + constants) - -- [ ] **5.1 Write failing test for validateImplementation — Completeness** - -```typescript -// Append to tests/e2e.test.ts -test('validateImplementation detects missing requirement in diff', () => { - const v = new Validator(); - const report = v.validateImplementation( - 'Added logging to src/utils/logger.ts', - '### Requirement: Auth middleware\nThe system SHALL authenticate all API requests.\n#### Scenario: Valid token\n- **WHEN** a request has a valid token\n- **THEN** the system SHALL allow access\n\n### Requirement: Rate limiting\nThe system SHALL limit requests to 100 per minute.\n#### Scenario: Over limit\n- **WHEN** rate limit exceeded\n- **THEN** the system SHALL return 429', - '## Decisions\n### Decision 1\n- Choice: JWT\n- Rationale: stateless' - ); - const completeness = report.dimensions.find(d => d.name === 'Completeness'); - assert.ok(completeness); - assert.equal(completeness!.status, 'FAIL'); - assert.ok(completeness!.findings.some(f => f.message.includes('Rate limiting'))); -}); -``` - -**Files**: `Modify: tests/e2e.test.ts` - -- [ ] **5.2 Run test and confirm it fails** - -Run: `npm run build && npm test` -Expected: FAIL — `validateImplementation` is not a function - -- [ ] **5.3 Implement validateImplementation in Validator class** - -Add to `src/validation/validator.ts` inside the `Validator` class: - -```typescript -validateImplementation( - diffSummary: string, - specContent: string, - designContent: string -): VerificationReport { - const dimensions: VerificationReport['dimensions'] = []; - - // --- Completeness --- - const completenessFindings: VerificationFinding[] = []; - const requirements = this.extractRequirementNames(specContent); - for (const req of requirements) { - if (!diffSummary.toLowerCase().includes(req.toLowerCase())) { - completenessFindings.push({ - level: 'CRITICAL', - dimension: 'Completeness', - message: VERIFICATION_MESSAGES.COMPLETENESS_MISSING_REQUIREMENT.replace('{requirement}', req), - }); - } - } - dimensions.push({ - name: 'Completeness', - status: completenessFindings.some(f => f.level === 'CRITICAL') ? 'FAIL' : completenessFindings.length > 0 ? 'WARN' : 'PASS', - findings: completenessFindings, - }); - - // --- Correctness --- - const correctnessFindings: VerificationFinding[] = []; - const placeholderPatterns = ['TODO', 'FIXME', 'HACK', 'XXX', 'PLACEHOLDER']; - for (const pattern of placeholderPatterns) { - if (diffSummary.includes(pattern)) { - correctnessFindings.push({ - level: 'CRITICAL', - dimension: 'Correctness', - message: VERIFICATION_MESSAGES.VERIFICATION_PLACEHOLDER_DETECTED, - }); - break; - } - } - dimensions.push({ - name: 'Correctness', - status: correctnessFindings.some(f => f.level === 'CRITICAL') ? 'FAIL' : correctnessFindings.length > 0 ? 'WARN' : 'PASS', - findings: correctnessFindings, - }); - - // --- Coherence --- - const coherenceFindings: VerificationFinding[] = []; - const decisionNames = this.extractDecisionNames(designContent); - for (const name of decisionNames) { - if (name.length > 3 && !diffSummary.toLowerCase().includes(name.toLowerCase())) { - coherenceFindings.push({ - level: 'IMPORTANT', - dimension: 'Coherence', - message: VERIFICATION_MESSAGES.COHERENCE_PATTERN_MISSING.replace('{pattern}', name), - }); - } - } - dimensions.push({ - name: 'Coherence', - status: coherenceFindings.some(f => f.level === 'CRITICAL') ? 'FAIL' : coherenceFindings.length > 0 ? 'WARN' : 'PASS', - findings: coherenceFindings, - }); - - // --- Verdict --- - const hasCritical = dimensions.some(d => d.status === 'FAIL'); - const hasWarning = dimensions.some(d => d.status === 'WARN'); - const verdict: VerificationReport['verdict'] = hasCritical ? 'FAIL' : hasWarning ? 'CONDITIONAL' : 'PASS'; - - return { dimensions, verdict }; -} - -private extractRequirementNames(specContent: string): string[] { - const regex = /### Requirement:\s*(.+)/g; - const names: string[] = []; - let match; - while ((match = regex.exec(specContent)) !== null) { - names.push(match[1].trim()); - } - return names; -} - -private extractDecisionNames(designContent: string): string[] { - const regex = /### Decision \d+\s*\n\s*- Choice:\s*(.+)/g; - const names: string[] = []; - let match; - while ((match = regex.exec(designContent)) !== null) { - names.push(match[1].trim()); - } - return names; -} -``` - -Add necessary imports at the top of `validator.ts`: -```typescript -import type { VerificationReport, VerificationFinding } from './types.js'; -import { VERIFICATION_MESSAGES } from './constants.js'; -``` - -**Files**: `Modify: src/validation/validator.ts` -**Interfaces**: Consumes `VerificationReport`, `VerificationFinding` from types.ts; `VERIFICATION_MESSAGES` from constants.ts. Produces `validateImplementation()` public API. - -- [ ] **5.4 Run test and confirm it passes** - -Run: `npm run build && npm test` -Expected: PASS — all tests including new validateImplementation tests - -- [ ] **5.5 Add three-dimensional verification to closure-archivist** - -In `skills/closure-archivist/SKILL.md`, replace the `## Verification Steps` section with: - -```markdown -## Verification Steps - -### Step 1: Test Suite Verification (Correctness) - -Run the full test suite. Record: -- Total tests, passed, failed, skipped -- Zero failures required for PASS -- Any failure = CRITICAL finding in Correctness dimension - -### Step 2: Completeness Verification - -Compare the execution contract's task batches against the actual diff: -1. List all tasks from the execution contract -2. For each task, verify a corresponding code change exists in the diff -3. For each SHALL/MUST requirement in specs, verify at least one implementation artifact -4. Missing items = CRITICAL findings in Completeness dimension - -### Step 3: Coherence Verification - -Compare design.md decisions against the implementation: -1. Extract each decision's Choice from design.md -2. Verify the choice is reflected in the code (naming, patterns, architecture) -3. Check naming consistency between specs and implementation -4. Inconsistencies = IMPORTANT findings in Coherence dimension - -### Step 4: Unintended Scope Detection - -Check the diff for unplanned changes: -- Files modified that are not in the execution contract's scope fence -- New dependencies added that are not in the design's constraints -- Unplanned changes = WARN findings in Completeness dimension - -### Step 5: Verification Report - -Produce a structured report: - -| Dimension | Status | Findings | -|-----------|--------|----------| -| Completeness | PASS/FAIL/WARN | [list] | -| Correctness | PASS/FAIL/WARN | [list] | -| Coherence | PASS/FAIL/WARN | [list] | - -**Overall verdict**: PASS (all PASS) / CONDITIONAL (WARN only) / FAIL (any FAIL) - -If FAIL → do not claim completion. Fix issues or route back to execution-governor. -If CONDITIONAL → present WARN findings to user, proceed only with explicit acceptance. -If PASS → proceed to final checks. -``` - -**Files**: `Modify: skills/closure-archivist/SKILL.md` - -- [ ] **5.6 Update closure-archivist Output section** - -Add the verification report to the output format: - -```markdown -## Output - -1. Verification report table (three dimensions with status and findings) -2. Overall verdict -3. If PASS: summary of all contract obligations met -4. If CONDITIONAL: list of accepted warnings -5. Risks and follow-ups -6. Archive readiness assessment -``` - -**Files**: `Modify: skills/closure-archivist/SKILL.md` - -- [ ] **5.7 Commit Batch 5** - -```bash -git add -A -git commit -m "feat(v0.3.0): three-dimensional verification (Completeness + Correctness + Coherence)" -``` - -## 6. Batch 6: Integration Tests + Version Bump + Publish - -Depends on: All previous batches - -- [ ] **6.1 Add comprehensive validateImplementation tests** - -Add to `tests/e2e.test.ts`: - -```typescript -test('validateImplementation passes when all requirements covered', () => { - const v = new Validator(); - const report = v.validateImplementation( - 'Added JWT auth middleware in src/middleware/auth.ts, rate limiter in src/middleware/rate-limit.ts', - '### Requirement: Auth middleware\nThe system SHALL authenticate all API requests.\n\n### Requirement: Rate limiting\nThe system SHALL limit requests to 100 per minute.', - '## Decisions\n### Decision 1\n- Choice: JWT-based auth\n- Rationale: stateless' - ); - assert.equal(report.verdict, 'PASS'); -}); - -test('validateImplementation detects placeholder markers', () => { - const v = new Validator(); - const report = v.validateImplementation( - 'Added auth middleware. TODO: implement rate limiting', - '### Requirement: Auth middleware\nThe system SHALL authenticate all API requests.', - '## Decisions\n### Decision 1\n- Choice: JWT\n- Rationale: stateless' - ); - const correctness = report.dimensions.find(d => d.name === 'Correctness'); - assert.equal(correctness!.status, 'FAIL'); -}); - -test('validateImplementation detects coherence gaps', () => { - const v = new Validator(); - const report = v.validateImplementation( - 'Added session-based auth in src/auth.ts', - '### Requirement: Auth middleware\nThe system SHALL authenticate all API requests.', - '## Decisions\n### Decision 1\n- Choice: JWT-based auth\n- Rationale: stateless' - ); - const coherence = report.dimensions.find(d => d.name === 'Coherence'); - assert.ok(coherence!.findings.length > 0); -}); -``` - -**Files**: `Modify: tests/e2e.test.ts` - -- [ ] **6.2 Run full test suite** - -Run: `npm run build && npm test` -Expected: All tests PASS (existing + new) - -- [ ] **6.3 Run validate on example data** - -Run: `npm run validate` -Expected: Validation passes for existing example change sets - -- [ ] **6.4 Version bump** - -Update version to `"0.3.0"` in: -- `package.json` -- `.claude-plugin/plugin.json` -- `.claude-plugin/marketplace.json` - -**Files**: `Modify: package.json`, `Modify: .claude-plugin/plugin.json`, `Modify: .claude-plugin/marketplace.json` - -- [ ] **6.5 Update CHANGELOG.md** - -Add v0.3.0 entry before the v0.2.1 entry: - -```markdown -## [0.3.0] - 2026-06-27 - -### Added - -- **Inline execution mode** — Lightweight single-session execution for small changes (≤ 3 tasks), parallel to SDD subagent mode. Preserves TDD Iron Law with checkpoint review instead of subagent dispatch. -- **Abandoned terminal state** — 8th workflow state allowing graceful change abandonment. Generates `abandonment-summary.md` with reason, lessons learned, and recommendations. Blocks delta spec merge for abandoned changes. -- **Three-dimensional verification** — closure-archivist now verifies Completeness (all tasks/requirements implemented), Correctness (tests pass, no placeholders), and Coherence (design decisions reflected in code). New `Validator.validateImplementation()` API. -- **abandonment-summary.md template** — Structured template for documenting abandoned changes. - -### Changed - -- **spec-forger task planning** — Rewritten with writing-plans methodology: File Structure section, Interfaces block, per-task TDD expansion (5 phases), exact file paths with line ranges, zero placeholder enforcement, 2-5 minute granularity per step. -- **execution-contract.md template** — Added Execution Mode (SDD | Inline) and Verification Dimensions table. -- **tasks.md template** — Added File Structure and Interfaces sections. -- **State machine** — Extended from 7 to 8 states (+abandoned terminal state). -- **Validator engine** — New `validateImplementation()` method with `VerificationReport` return type. New exports: `VerificationDimension`, `VerificationStatus`, `VerificationFinding`, `VerificationReport`. -``` - -**Files**: `Modify: CHANGELOG.md` - -- [ ] **6.6 Final build + test** - -Run: `npm run build && npm test` -Expected: All tests PASS - -- [ ] **6.7 Commit and tag** - -```bash -git add -A -git commit -m "release: v0.3.0 — inline execution, abandoned state, three-dimensional verification" -git tag v0.3.0 -git push origin main --tags -``` - -## 7. Closeout - -- [ ] **7.1 Verify all contract obligations** - -Cross-check every SHALL/MUST from all 5 delta specs against implementation: -- task-planning: 5 requirements (Enhanced Task Granularity, Precise File Path Declaration, Interface Contract Declaration, Zero Placeholder Enforcement, File Structure Section) -- inline-execution: 3 requirements (Inline Execution Mode, Inline Mode Checkpoint Review, Execution Mode Selection Criteria) -- abandonment-workflow: 4 requirements (Abandoned Terminal State, Abandonment Summary Generation, Partial Code Preservation, No Delta Spec Merge on Abandonment) -- verification-framework: 3 requirements (Three-Dimensional Verification, Verification Dimension Report, Implementation Validator Engine) -- state-machine: 2 requirements (Eight-State Workflow, Abandoned State Routing) - -Total: 17 requirements, each must have corresponding implementation. - -- [ ] **7.2 Summarize risks, follow-ups, and archive readiness** - -Document in the execution contract's closeout section. diff --git a/changes/v0.4.0-platform-evolution/tasks.md b/changes/v0.4.0-platform-evolution/tasks.md deleted file mode 100644 index 4be0dc4..0000000 --- a/changes/v0.4.0-platform-evolution/tasks.md +++ /dev/null @@ -1,1762 +0,0 @@ -# spec-superflow v0.4.0 Platform Evolution — Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Transform spec-superflow from a pure-skill workflow into a configurable, CLI-operable platform with multi-language support, while maintaining zero npm dependencies. - -**Architecture:** Three-layer design — (1) JSON config system for artifact customization, (2) CLI toolchain with 6 subcommands via `node:util.parseArgs`, (3) engine extensions including a multi-language tokenizer, conflict detection, and skill updates for worktree isolation. - -**Tech Stack:** TypeScript (ES2022 + NodeNext + strict), Node 22 native test runner, ESM scripts (.mjs), zero external npm dependencies. - -## Global Constraints - -- Zero external npm dependencies (only `typescript` as devDependency) -- Node >= 22 required -- Pure regex parsing — no Zod or runtime validation libraries -- `dist/` is compiled output, committed to repo -- Tests import from `dist/index.js`, always run `npm run build` before `npm test` -- Backward compatible: `spec-superflow.config.json` absence = v0.3.0 behavior -- All manifest versions must stay in sync (package.json, plugin.json, marketplace.json, cursor-plugin, gemini-extension) -- `package.json` has `"type": "module"` — all `.js` files are ESM - -## File Structure - -### New Files (10) - -| File | Responsibility | -|------|---------------| -| `src/validation/tokenizer.ts` | Multi-language tokenizer (English stemmer + Chinese CJK tokenizer + auto-detect) | -| `scripts/spec-superflow.mjs` | CLI entry point — parses subcommand, dispatches to cmd modules | -| `scripts/lib/config-loader.mjs` | JSON config loading + deep merge with built-in defaults | -| `scripts/lib/cmd-list.mjs` | `ssf list` — scan changes/ and report status | -| `scripts/lib/cmd-validate.mjs` | `ssf validate ` — validate artifacts via Validator | -| `scripts/lib/cmd-doctor.mjs` | `ssf doctor` — health checks (version sync, hooks, skills, docs) | -| `scripts/lib/cmd-version.mjs` | `ssf version ` — sync version to all manifests | -| `scripts/lib/cmd-sync.mjs` | `ssf sync ` — delta spec merge with conflict detection | -| `scripts/lib/cmd-config.mjs` | `ssf config` — display/modify config | -| `scripts/get-config` | Bash helper for SKILL.md config queries at runtime | - -### Modified Files (14) - -| File | Change | -|------|--------| -| `src/validation/types.ts` | Add `ConflictReport`, `SyncConflict` types | -| `src/validation/constants.ts` | Add conflict-related message constants | -| `src/validation/validator.ts` | Refactor to use tokenizer, add `detectSyncConflicts()`, add optional `config` param to `validateImplementation()` | -| `src/index.ts` | Export tokenizer + conflict types | -| `tests/e2e.test.ts` | Add tokenizer tests (3) + conflict detection tests (2) + Chinese verification tests (2) | -| `package.json` | Add `bin` field | -| `skills/execution-governor/SKILL.md` | Add worktree isolation section + config check | -| `skills/spec-syncer/SKILL.md` | Add conflict detection workflow | -| `skills/workflow-orchestrator/SKILL.md` | Add config-aware routing | -| `skills/spec-forger/SKILL.md` | Add config check for artifact order/skip | -| `.claude-plugin/plugin.json` | Bump version to 0.4.0 | -| `.claude-plugin/marketplace.json` | Bump version to 0.4.0 | -| `.cursor-plugin/plugin.json` | Bump version to 0.4.0 | -| `gemini-extension.json` | Bump version to 0.4.0 | - ---- - -### Task 1: Multi-language Tokenizer - -**Files:** -- Create: `src/validation/tokenizer.ts` -- Test: `tests/e2e.test.ts` (add tokenizer describe block) - -**Interfaces:** -- Consumes: nothing (standalone module) -- Produces: `tokenize(text: string, language?: 'auto' | 'en' | 'zh'): Set` and `detectLanguage(text: string): 'en' | 'zh' | 'mixed'` — later tasks (Task 3) will import these to replace inline stemming in validator.ts - -- [ ] **Step 1: Write failing tests for English tokenizer** - -Append to `tests/e2e.test.ts`: - -```typescript -import { tokenize, detectLanguage } from '../dist/index.js'; - -describe('tokenize', () => { - it('tokenizes English text with stemming', () => { - const tokens = tokenize('Rate limiting middleware implementation', 'en'); - // "limiting" → stem "limit", "implementation" → stem "implement" - assert.ok(tokens.has('limit'), `Expected "limit" in tokens: ${[...tokens].join(', ')}`); - assert.ok(tokens.has('rate'), `Expected "rate" in tokens: ${[...tokens].join(', ')}`); - assert.ok(tokens.has('middleware'), `Expected "middleware" in tokens: ${[...tokens].join(', ')}`); - assert.ok(tokens.has('implement'), `Expected "implement" in tokens: ${[...tokens].join(', ')}`); - }); - - it('tokenizes Chinese text with CJK extraction', () => { - const tokens = tokenize('速率限制模块必须支持令牌桶算法', 'zh'); - // Should extract CJK character sequences and sliding window tokens - assert.ok(tokens.size > 0, 'Expected non-empty token set for Chinese text'); - // 2-char sliding window: "速率", "率限", "限制", "制模", "模块", etc. - assert.ok(tokens.has('速率'), `Expected "速率" in tokens: ${[...tokens].join(', ')}`); - assert.ok(tokens.has('限制'), `Expected "限制" in tokens: ${[...tokens].join(', ')}`); - assert.ok(tokens.has('令牌'), `Expected "令牌" in tokens: ${[...tokens].join(', ')}`); - }); - - it('auto-detects language from text content', () => { - assert.equal(detectLanguage('Rate limiting middleware implementation'), 'en'); - assert.equal(detectLanguage('速率限制模块必须支持令牌桶算法'), 'zh'); - // Mixed content: Chinese sentence with English API name - const mixed = detectLanguage('使用 Redis 实现速率限制模块的令牌桶算法'); - assert.ok(['zh', 'mixed'].includes(mixed), `Expected zh or mixed, got: ${mixed}`); - }); -}); -``` - -- [ ] **Step 2: Run tests to verify they fail** - -Run: `npm run build && npm test 2>&1 | tail -20` -Expected: FAIL — `tokenize` and `detectLanguage` are not exported from `dist/index.js` - -- [ ] **Step 3: Implement tokenizer.ts** - -Create `src/validation/tokenizer.ts`: - -```typescript -// English stop words -const EN_STOP_WORDS = new Set([ - 'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being', - 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'shall', - 'should', 'may', 'might', 'can', 'could', 'of', 'in', 'to', 'for', - 'with', 'on', 'at', 'by', 'from', 'as', 'into', 'through', 'during', - 'before', 'after', 'above', 'below', 'between', 'out', 'off', 'over', - 'under', 'again', 'further', 'then', 'once', -]); - -// Chinese stop words -const ZH_STOP_WORDS = new Set([ - '的', '了', '在', '是', '我', '有', '和', '就', '不', '人', '都', - '一', '一个', '上', '也', '很', '到', '说', '要', '去', '你', '会', - '着', '没有', '看', '好', '自己', '这', -]); - -// CJK Unicode ranges -const CJK_REGEX = /[一-鿿㐀-䶿]/; -const CJK_GLOBAL = /[一-鿿㐀-䶿]/g; - -/** - * Lightweight English stemmer. - * Strips common suffixes (-ing, -er, -ed, -s, -tion, etc.) - */ -function stemEnglish(word: string): string { - const w = word.toLowerCase(); - if (w.length <= 3) return w; - const suffixes: Array<[string, number]> = [ - ['ation', 3], ['tion', 3], ['ness', 3], ['ment', 3], - ['ings', 3], ['ally', 3], - ['ing', 3], ['ier', 3], ['ied', 3], ['ies', 3], - ['ted', 3], ['ned', 3], ['red', 3], ['sed', 3], ['led', 3], - ['ped', 3], ['ded', 3], ['ved', 3], ['wed', 3], ['xed', 3], - ['zed', 3], ['ced', 3], ['ged', 3], ['ked', 3], - ['ers', 3], ['ors', 3], - ['ary', 3], ['ory', 3], ['ity', 3], ['ism', 3], ['ist', 3], - ['ent', 3], ['ant', 3], ['ous', 3], ['ive', 3], ['ful', 3], - ['ly', 3], ['ed', 3], ['er', 3], ['es', 3], - ['al', 3], ['en', 3], ['ty', 3], ['or', 3], ['ar', 3], - ['ry', 3], ['ic', 3], ['id', 3], - ]; - for (const [suffix, minRoot] of suffixes) { - if (w.endsWith(suffix) && w.length - suffix.length >= minRoot) { - return w.slice(0, -suffix.length); - } - } - if (w.endsWith('s') && w.length > 4) return w.slice(0, -1); - return w; -} - -function tokenizeEnglish(text: string): Set { - const tokens = new Set(); - const words = text.toLowerCase().split(/[^a-z0-9]+/).filter(w => w.length > 0); - for (const word of words) { - if (EN_STOP_WORDS.has(word)) continue; - if (word.length <= 3) continue; - tokens.add(stemEnglish(word)); - } - return tokens; -} - -function tokenizeChinese(text: string): Set { - const tokens = new Set(); - - // Split on Chinese punctuation - const segments = text.split(/[,。!?;:、""''()【】《》\s]+/).filter(s => s.length > 0); - - for (const segment of segments) { - // Extract CJK character sequences - let cjkRun = ''; - for (const char of segment) { - if (CJK_REGEX.test(char)) { - cjkRun += char; - } else { - // Flush CJK run - if (cjkRun.length >= 2) { - addChineseTokens(cjkRun, tokens); - } - cjkRun = ''; - // Extract ASCII words from mixed content - if (/[a-zA-Z0-9]/.test(char)) { - // accumulate ascii — handled below - } - } - } - if (cjkRun.length >= 2) { - addChineseTokens(cjkRun, tokens); - } - - // Also extract ASCII words from mixed segments - const asciiWords = segment.match(/[a-zA-Z][a-zA-Z0-9]*/g); - if (asciiWords) { - for (const word of asciiWords) { - const lower = word.toLowerCase(); - if (lower.length > 3 && !EN_STOP_WORDS.has(lower)) { - tokens.add(stemEnglish(lower)); - } - } - } - } - - return tokens; -} - -function addChineseTokens(cjkRun: string, tokens: Set): void { - // Filter stop words — check if entire run is a stop word - if (ZH_STOP_WORDS.has(cjkRun)) return; - - // Add the full CJK run as a token - tokens.add(cjkRun); - - // Add 2-character sliding window tokens - for (let i = 0; i < cjkRun.length - 1; i++) { - const bigram = cjkRun.slice(i, i + 2); - if (!ZH_STOP_WORDS.has(bigram)) { - tokens.add(bigram); - } - } - - // Add 3-character sliding window tokens (for compound words like 令牌桶) - for (let i = 0; i < cjkRun.length - 2; i++) { - const trigram = cjkRun.slice(i, i + 3); - if (!ZH_STOP_WORDS.has(trigram)) { - tokens.add(trigram); - } - } -} - -/** - * Detect the primary language of a text. - */ -export function detectLanguage(text: string): 'en' | 'zh' | 'mixed' { - const cjkMatches = text.match(CJK_GLOBAL); - const cjkCount = cjkMatches ? cjkMatches.length : 0; - const totalChars = text.replace(/\s/g, '').length; - if (totalChars === 0) return 'en'; - - const cjkRatio = cjkCount / totalChars; - const hasAsciiWords = /[a-zA-Z]{3,}/.test(text); - - if (cjkRatio > 0.3 && hasAsciiWords) return 'mixed'; - if (cjkRatio > 0.3) return 'zh'; - return 'en'; -} - -/** - * Tokenize text for verification matching. - * Supports English (stemming), Chinese (CJK sliding window), and auto-detection. - */ -export function tokenize(text: string, language?: 'auto' | 'en' | 'zh'): Set { - const lang = language === 'auto' || !language ? detectLanguage(text) : language; - - switch (lang) { - case 'en': - return tokenizeEnglish(text); - case 'zh': - return tokenizeChinese(text); - case 'mixed': { - const enTokens = tokenizeEnglish(text); - const zhTokens = tokenizeChinese(text); - return new Set([...enTokens, ...zhTokens]); - } - default: - return tokenizeEnglish(text); - } -} -``` - -- [ ] **Step 4: Export tokenizer from index.ts** - -Add to `src/index.ts` (append these lines): - -```typescript -export { tokenize, detectLanguage } from './validation/tokenizer.js'; -``` - -- [ ] **Step 5: Build and run tests** - -Run: `npm run build && npm test 2>&1 | tail -30` -Expected: All tokenize tests PASS (3 new tests). Existing 13 tests still PASS (total: 16). - -- [ ] **Step 6: Commit** - -```bash -git add src/validation/tokenizer.ts src/index.ts tests/e2e.test.ts -git commit -m "feat: add multi-language tokenizer (English stemmer + Chinese CJK)" -``` - ---- - -### Task 2: Config System - -**Files:** -- Create: `scripts/lib/config-loader.mjs` -- Create: `scripts/get-config` -- Test: `scripts/spec-superflow.mjs config` (manual verification after Task 4) - -**Interfaces:** -- Consumes: nothing (standalone module) -- Produces: `loadConfig(projectRoot: string): object` — returns merged config with defaults. Later tasks (Task 4+) import this. - -- [ ] **Step 1: Implement config-loader.mjs** - -Create `scripts/lib/config-loader.mjs`: - -```javascript -// Config loader for spec-superflow -// Loads spec-superflow.config.json and merges with built-in defaults. -// Lookup order: (1) projectRoot, (2) git root, (3) home directory. - -import { readFileSync, existsSync } from 'node:fs'; -import { join, dirname } from 'node:path'; -import { execSync } from 'node:child_process'; - -const DEFAULTS = { - artifacts: { - order: ['proposal', 'specs', 'design', 'tasks', 'execution-contract'], - skip: [], - }, - execution: { - inlineThreshold: 3, - abandonmentReasonMinLength: 50, - defaultLanguage: 'auto', - }, - verification: { - language: 'auto', - }, -}; - -function deepMerge(target, source) { - const result = { ...target }; - for (const key of Object.keys(source)) { - if ( - source[key] && - typeof source[key] === 'object' && - !Array.isArray(source[key]) && - target[key] && - typeof target[key] === 'object' && - !Array.isArray(target[key]) - ) { - result[key] = deepMerge(target[key], source[key]); - } else { - result[key] = source[key]; - } - } - return result; -} - -function findConfigFile(startDir) { - // 1. Check startDir - const direct = join(startDir, 'spec-superflow.config.json'); - if (existsSync(direct)) return direct; - - // 2. Check git root - try { - const gitRoot = execSync('git rev-parse --show-toplevel', { - cwd: startDir, - encoding: 'utf-8', - stdio: ['pipe', 'pipe', 'pipe'], - }).trim(); - const gitPath = join(gitRoot, 'spec-superflow.config.json'); - if (existsSync(gitPath)) return gitPath; - } catch { - // Not a git repo — skip - } - - // 3. Check home directory - const homePath = join(process.env.HOME || '', 'spec-superflow.config.json'); - if (existsSync(homePath)) return homePath; - - return null; -} - -export function loadConfig(projectRoot) { - const configPath = findConfigFile(projectRoot || process.cwd()); - if (!configPath) return { ...DEFAULTS }; - - try { - const raw = readFileSync(configPath, 'utf-8'); - const userConfig = JSON.parse(raw); - return deepMerge(DEFAULTS, userConfig); - } catch { - return { ...DEFAULTS }; - } -} - -export function getDefaults() { - return { ...DEFAULTS }; -} -``` - -- [ ] **Step 2: Implement get-config bash helper** - -Create `scripts/get-config`: - -```bash -#!/usr/bin/env bash -# Read a config field from spec-superflow.config.json -# Usage: get-config -# Example: get-config execution.inlineThreshold → outputs "3" -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -field_path="${1:-}" - -if [ -z "$field_path" ]; then - echo "Usage: get-config " >&2 - echo "Example: get-config execution.inlineThreshold" >&2 - exit 2 -fi - -# Use node to load config and extract field -node -e " -import { loadConfig } from '${SCRIPT_DIR}/lib/config-loader.mjs'; -const config = loadConfig(process.cwd()); -const parts = '${field_path}'.split('.'); -let val = config; -for (const p of parts) { - if (val === undefined || val === null) { val = undefined; break; } - val = val[p]; -} -if (val !== undefined) { - process.stdout.write(typeof val === 'object' ? JSON.stringify(val) : String(val)); -} else { - process.exit(1); -} -" 2>/dev/null || exit 1 -``` - -Run: `chmod +x scripts/get-config` - -- [ ] **Step 3: Manual verification** - -Run: `bash scripts/get-config execution.inlineThreshold` -Expected: `3` (default value, since no config file exists) - -Run: `bash scripts/get-config verification.language` -Expected: `auto` - -- [ ] **Step 4: Commit** - -```bash -git add scripts/lib/config-loader.mjs scripts/get-config -git commit -m "feat: add config system (JSON config loader + bash helper)" -``` - ---- - -### Task 3: Refactor validateImplementation() to use Tokenizer + Add Conflict Detection - -**Files:** -- Modify: `src/validation/validator.ts:454-543` (validateImplementation method) -- Modify: `src/validation/types.ts` (add ConflictReport, SyncConflict) -- Modify: `src/validation/constants.ts` (add conflict messages) -- Modify: `src/index.ts` (export new types) -- Test: `tests/e2e.test.ts` (add Chinese verification tests + conflict tests) - -**Interfaces:** -- Consumes: `tokenize()` and `detectLanguage()` from Task 1; `parseDeltaSpec()`, `normalizeRequirementName()` from existing parsing module; `DeltaPlan`, `RequirementBlock` types -- Produces: updated `validateImplementation()` signature (backward-compatible, optional `config` param), new `detectSyncConflicts()` method on Validator class - -- [ ] **Step 1: Write failing tests for Chinese verification and conflict detection** - -Append to `tests/e2e.test.ts` (inside the existing `Validator.validateImplementation` describe block): - -```typescript - it('verifies Chinese spec content with Chinese tokenizer', () => { - const report = validator.validateImplementation( - '新增速率限制模块,使用令牌桶算法实现 src/middleware/rate-limit.ts', - '### Requirement: 速率限制\n系统必须实现令牌桶算法进行速率限制。\n#### Scenario: 正常请求\n- **WHEN** 请求频率在限制内\n- **THEN** 系统必须正常处理', - '## Decisions\n### Decision 1\n- Choice: 令牌桶算法\n- Rationale: 平滑限流' - ); - // Both spec and diff are Chinese — should detect and use zh tokenizer - const completeness = report.dimensions.find(d => d.name === 'Completeness'); - assert.ok(completeness, 'Missing Completeness dimension'); - // "速率限制" tokens should match diff content - assert.equal(completeness!.status, 'PASS', `Expected PASS but got ${completeness!.status}: ${JSON.stringify(completeness!.findings)}`); - }); - - it('detects missing requirement in Chinese spec (Completeness FAIL)', () => { - const report = validator.validateImplementation( - '新增日志模块 src/utils/logger.ts', - '### Requirement: 速率限制\n系统必须实现令牌桶算法进行速率限制。\n\n### Requirement: 日志记录\n系统必须记录所有API请求日志。', - '## Decisions\n### Decision 1\n- Choice: 令牌桶算法\n- Rationale: 平滑限流' - ); - const completeness = report.dimensions.find(d => d.name === 'Completeness'); - assert.equal(completeness!.status, 'FAIL'); - // "日志记录" should be found, but "速率限制" should be missing from diff - assert.ok(completeness!.findings.some(f => f.message.includes('速率限制'))); - }); -``` - -Append new describe block for conflict detection: - -```typescript -describe('Validator.detectSyncConflicts', () => { - const validator = new Validator(); - - it('returns no conflicts when delta specs modify different requirements', () => { - const deltas = [ - { - changeName: 'change-a', - content: '## MODIFIED Requirements\n### Requirement: Auth middleware\nThe system SHALL use JWT.\n#### Scenario: test\n- **WHEN** x\n- **THEN** y', - }, - { - changeName: 'change-b', - content: '## MODIFIED Requirements\n### Requirement: Rate limiting\nThe system SHALL limit to 100 req/min.\n#### Scenario: test\n- **WHEN** x\n- **THEN** y', - }, - ]; - const report = validator.detectSyncConflicts(deltas); - assert.equal(report.hasConflicts, false); - assert.equal(report.conflicts.length, 0); - }); - - it('detects conflicts when two changes modify the same requirement', () => { - const deltas = [ - { - changeName: 'change-a', - content: '## MODIFIED Requirements\n### Requirement: Auth middleware\nThe system SHALL use JWT tokens.\n#### Scenario: test\n- **WHEN** x\n- **THEN** y', - }, - { - changeName: 'change-b', - content: '## MODIFIED Requirements\n### Requirement: Auth middleware\nThe system SHALL use session cookies.\n#### Scenario: test\n- **WHEN** x\n- **THEN** y', - }, - ]; - const report = validator.detectSyncConflicts(deltas); - assert.equal(report.hasConflicts, true); - assert.equal(report.conflicts.length, 1); - assert.equal(report.conflicts[0].requirement, 'Auth middleware'); - assert.ok(report.conflicts[0].changes.includes('change-a')); - assert.ok(report.conflicts[0].changes.includes('change-b')); - }); -}); -``` - -- [ ] **Step 2: Run tests to verify they fail** - -Run: `npm run build && npm test 2>&1 | tail -20` -Expected: FAIL — Chinese verification tests fail (validator still uses inline stemmer, not tokenizer), conflict tests fail (`detectSyncConflicts` not defined) - -- [ ] **Step 3: Add ConflictReport types to types.ts** - -Append to `src/validation/types.ts`: - -```typescript -export interface SyncConflict { - requirement: string; - spec: string; - changes: string[]; -} - -export interface ConflictReport { - hasConflicts: boolean; - conflicts: SyncConflict[]; -} -``` - -- [ ] **Step 4: Add conflict message constants** - -Append to `VERIFICATION_MESSAGES` in `src/validation/constants.ts`: - -```typescript - CONFLICT_DETECTED: 'Requirement "{requirement}" is modified by multiple changes: {changes}', -``` - -- [ ] **Step 5: Refactor validateImplementation() to use tokenizer** - -In `src/validation/validator.ts`, replace the `validateImplementation` method (lines 454-543). Add import at top of file: - -```typescript -import { tokenize } from './tokenizer.js'; -``` - -Replace the method body: - -```typescript - validateImplementation( - diffSummary: string, - specContent: string, - designContent: string, - config?: { verification?: { language?: string } } - ): VerificationReport { - const dimensions: VerificationReport['dimensions'] = []; - const language = (config?.verification?.language as 'auto' | 'en' | 'zh') || 'auto'; - - // --- Completeness --- - const completenessFindings: VerificationFinding[] = []; - const requirements = this.extractRequirementNames(specContent); - const diffTokens = tokenize(diffSummary, language); - for (const req of requirements) { - const reqTokens = tokenize(req, language); - // Requirement is covered when every token from the requirement name - // appears somewhere in the diff tokens - const allPresent = reqTokens.size === 0 || [...reqTokens].every(t => diffTokens.has(t)); - if (!allPresent) { - completenessFindings.push({ - level: 'CRITICAL', - dimension: 'Completeness', - message: VERIFICATION_MESSAGES.COMPLETENESS_MISSING_REQUIREMENT.replace('{requirement}', req), - }); - } - } - dimensions.push({ - name: 'Completeness', - status: completenessFindings.some(f => f.level === 'CRITICAL') ? 'FAIL' : completenessFindings.length > 0 ? 'WARN' : 'PASS', - findings: completenessFindings, - }); - - // --- Correctness --- - const correctnessFindings: VerificationFinding[] = []; - const placeholderPatterns = ['TODO', 'FIXME', 'HACK', 'XXX', 'PLACEHOLDER']; - for (const pattern of placeholderPatterns) { - if (diffSummary.includes(pattern)) { - correctnessFindings.push({ - level: 'CRITICAL', - dimension: 'Correctness', - message: VERIFICATION_MESSAGES.VERIFICATION_PLACEHOLDER_DETECTED, - }); - break; - } - } - dimensions.push({ - name: 'Correctness', - status: correctnessFindings.some(f => f.level === 'CRITICAL') ? 'FAIL' : correctnessFindings.length > 0 ? 'WARN' : 'PASS', - findings: correctnessFindings, - }); - - // --- Coherence --- - const coherenceFindings: VerificationFinding[] = []; - const decisionNames = this.extractDecisionNames(designContent); - for (const name of decisionNames) { - if (name.length <= 3) continue; - const decisionTokens = tokenize(name, language); - const diffTokensForCoherence = tokenize(diffSummary, language); - const allPresent = decisionTokens.size === 0 || [...decisionTokens].every(t => diffTokensForCoherence.has(t)); - if (!allPresent) { - coherenceFindings.push({ - level: 'IMPORTANT', - dimension: 'Coherence', - message: VERIFICATION_MESSAGES.COHERENCE_PATTERN_MISSING.replace('{pattern}', name), - }); - } - } - dimensions.push({ - name: 'Coherence', - status: coherenceFindings.some(f => f.level === 'CRITICAL') ? 'FAIL' : coherenceFindings.length > 0 ? 'WARN' : 'PASS', - findings: coherenceFindings, - }); - - // --- Verdict --- - const hasCritical = dimensions.some(d => d.status === 'FAIL'); - const hasWarning = dimensions.some(d => d.status === 'WARN'); - const verdict: VerificationReport['verdict'] = hasCritical ? 'FAIL' : hasWarning ? 'CONDITIONAL' : 'PASS'; - - return { dimensions, verdict }; - } -``` - -- [ ] **Step 6: Add detectSyncConflicts() method to Validator class** - -Append before `isValid()` method in `src/validation/validator.ts`: - -```typescript - detectSyncConflicts(deltaSpecs: Array<{ changeName: string; content: string }>): ConflictReport { - // Build map: requirementName → [changeName, ...] - const reqToChanges = new Map(); - - for (const { changeName, content } of deltaSpecs) { - const plan = parseDeltaSpec(content); - // Collect MODIFIED and RENAMED requirement names - const names: string[] = [ - ...plan.modified.map(b => normalizeRequirementName(b.name)), - ...plan.renamed.map(r => normalizeRequirementName(r.to)), - ]; - for (const name of names) { - const existing = reqToChanges.get(name) || []; - existing.push(changeName); - reqToChanges.set(name, existing); - } - } - - // Find conflicts: requirements modified by 2+ changes - const conflicts: SyncConflict[] = []; - for (const [requirement, changes] of reqToChanges) { - if (changes.length >= 2) { - conflicts.push({ - requirement, - spec: requirement, - changes, - }); - } - } - - return { - hasConflicts: conflicts.length > 0, - conflicts, - }; - } -``` - -- [ ] **Step 7: Remove old inline stem() function from validator.ts** - -Delete the `stem()` function (lines 56-81 in original validator.ts). It's now replaced by `tokenizer.ts`. Also remove the `fillerWords` set that was inline in the Coherence section — the tokenizer handles stop words internally. - -- [ ] **Step 8: Export new types from index.ts** - -Update `src/index.ts` — add to the types.ts export line: - -```typescript -export type { ConflictReport, SyncConflict } from './validation/types.js'; -``` - -- [ ] **Step 9: Build and run all tests** - -Run: `npm run build && npm test` -Expected: All tests PASS — existing 13 + new tokenizer 3 + new verification 2 + new conflict 2 = 20 tests total. - -- [ ] **Step 10: Commit** - -```bash -git add src/validation/validator.ts src/validation/types.ts src/validation/constants.ts src/index.ts tests/e2e.test.ts -git commit -m "feat: refactor validateImplementation to use tokenizer, add detectSyncConflicts" -``` - ---- - -### Task 4: CLI Entry Point + list + validate + config Commands - -**Files:** -- Create: `scripts/spec-superflow.mjs` -- Create: `scripts/lib/cmd-list.mjs` -- Create: `scripts/lib/cmd-validate.mjs` -- Create: `scripts/lib/cmd-config.mjs` -- Modify: `package.json` (add `bin` field) - -**Interfaces:** -- Consumes: `loadConfig()` from `config-loader.mjs` (Task 2), `Validator` from `dist/index.js` (existing) -- Produces: CLI entry point with 3 working subcommands (`list`, `validate`, `config`) - -- [ ] **Step 1: Add bin field to package.json** - -Add to `package.json` (after `"types"` field): - -```json - "bin": { - "ssf": "./scripts/spec-superflow.mjs", - "spec-superflow": "./scripts/spec-superflow.mjs" - }, -``` - -- [ ] **Step 2: Create CLI entry point** - -Create `scripts/spec-superflow.mjs`: - -```javascript -#!/usr/bin/env node -// spec-superflow CLI — zero-dependency CLI for spec management -// Usage: ssf [options] - -import { parseArgs } from 'node:util'; - -const COMMANDS = { - list: () => import('./lib/cmd-list.mjs'), - validate: () => import('./lib/cmd-validate.mjs'), - doctor: () => import('./lib/cmd-doctor.mjs'), - version: () => import('./lib/cmd-version.mjs'), - sync: () => import('./lib/cmd-sync.mjs'), - config: () => import('./lib/cmd-config.mjs'), -}; - -const HELP = `spec-superflow (ssf) — Spec-first workflow CLI - -Usage: ssf [options] - -Commands: - list List all changes and their status - validate Validate artifacts in a change directory - doctor Health check (versions, hooks, skills, docs) - version Sync version to all manifest files - sync Merge delta specs into main specs - config [options] Display or modify configuration - -Options: - --help, -h Show this help message - --version, -v Show CLI version - -Examples: - ssf list - ssf validate changes/v0.4.0-platform-evolution/ - ssf doctor - ssf version 0.4.0 - ssf sync changes/v0.3.0-workflow-enhancements/ - ssf config --get execution.inlineThreshold - ssf config --set verification.language=zh -`; - -async function main() { - const args = process.argv.slice(2); - - if (args.length === 0 || args.includes('--help') || args.includes('-h')) { - console.log(HELP); - process.exit(0); - } - - if (args.includes('--version') || args.includes('-v')) { - const pkg = JSON.parse( - (await import('node:fs')).readFileSync( - new URL('../package.json', import.meta.url), 'utf-8' - ) - ); - console.log(pkg.version); - process.exit(0); - } - - const command = args[0]; - const commandArgs = args.slice(1); - - if (!COMMANDS[command]) { - console.error(`Unknown command: ${command}`); - console.error(`Run "ssf --help" for available commands.`); - process.exit(2); - } - - const mod = await COMMANDS[command](); - await mod.run(commandArgs); -} - -main().catch(err => { - console.error(`Error: ${err.message}`); - process.exit(1); -}); -``` - -Run: `chmod +x scripts/spec-superflow.mjs` - -- [ ] **Step 3: Implement cmd-list.mjs** - -Create `scripts/lib/cmd-list.mjs`: - -```javascript -// ssf list — scan changes/ and report status -import { readdirSync, existsSync, statSync } from 'node:fs'; -import { join } from 'node:path'; -import { loadConfig } from './config-loader.mjs'; - -function detectChangeStatus(changeDir) { - const hasProposal = existsSync(join(changeDir, 'proposal.md')); - const hasContract = existsSync(join(changeDir, 'execution-contract.md')); - const hasAbandonment = existsSync(join(changeDir, 'abandonment-summary.md')); - const hasSpecs = existsSync(join(changeDir, 'specs')); - - if (hasAbandonment) return { status: 'ABANDONED', detail: 'Change was abandoned' }; - if (!hasProposal) return { status: 'INCOMPLETE', detail: 'Missing proposal.md' }; - if (!hasContract) return { status: 'SPECIFYING', detail: 'Planning in progress' }; - if (!hasSpecs) return { status: 'BRIDGED', detail: 'Contract ready, no specs yet' }; - - // Count spec files - const specsDir = join(changeDir, 'specs'); - const specDirs = readdirSync(specsDir).filter(f => { - try { return statSync(join(specsDir, f)).isDirectory(); } catch { return false; } - }); - - return { status: 'CLOSED', detail: `${specDirs.length} specs` }; -} - -export async function run(args) { - const config = loadConfig(process.cwd()); - const changesDir = join(process.cwd(), 'changes'); - - if (!existsSync(changesDir)) { - console.log('No changes/ directory found.'); - return; - } - - const dirs = readdirSync(changesDir).filter(f => { - try { return statSync(join(changesDir, f)).isDirectory(); } catch { return false; } - }); - - if (dirs.length === 0) { - console.log('No changes found in changes/'); - return; - } - - console.log('Changes:'); - for (const dir of dirs) { - const changeDir = join(changesDir, dir); - const { status, detail } = detectChangeStatus(changeDir); - const icon = status === 'CLOSED' ? '✅' : status === 'ABANDONED' ? '🚫' : status === 'SPECIFYING' ? '📝' : '🔧'; - console.log(` ${icon} ${dir} [${status}] ${detail}`); - } -} -``` - -- [ ] **Step 4: Implement cmd-validate.mjs** - -Create `scripts/lib/cmd-validate.mjs`: - -```javascript -// ssf validate — validate artifacts in a change directory -import { readFileSync, readdirSync, existsSync, statSync } from 'node:fs'; -import { join, basename, relative } from 'node:path'; -import { loadConfig } from './config-loader.mjs'; - -async function getValidator() { - const mod = await import('../../dist/index.js'); - return new mod.Validator(false); -} - -function findFiles(dir, pattern) { - const results = []; - if (!existsSync(dir)) return results; - for (const entry of readdirSync(dir)) { - const full = join(dir, entry); - const st = statSync(full); - if (st.isDirectory()) results.push(...findFiles(full, pattern)); - else if (st.isFile() && pattern.test(entry)) results.push(full); - } - return results; -} - -function printReport(label, report) { - console.log(`\n 📋 ${label}`); - if (report.valid) { - console.log(` ✅ valid (${report.summary.errors} errors, ${report.summary.warnings} warnings, ${report.summary.info} info)`); - } else { - console.log(` ❌ invalid (${report.summary.errors} errors, ${report.summary.warnings} warnings, ${report.summary.info} info)`); - } - for (const issue of report.issues) { - const icon = issue.level === 'ERROR' ? '🔴' : issue.level === 'WARNING' ? '🟡' : '🔵'; - console.log(` ${icon} [${issue.level}] ${issue.path}: ${issue.message}`); - } -} - -export async function run(args) { - if (args.length < 1) { - console.error('Usage: ssf validate '); - process.exit(2); - } - - const changeDir = args[0]; - if (!existsSync(changeDir) || !statSync(changeDir).isDirectory()) { - console.error(`Error: "${changeDir}" is not a valid directory`); - process.exit(2); - } - - const config = loadConfig(process.cwd()); - const changeName = basename(changeDir); - const validator = await getValidator(); - - console.log(`🔍 Validating: ${changeDir}`); - console.log(` Change: ${changeName}`); - - let hasErrors = false; - - // Validate proposal.md - const proposalPath = join(changeDir, 'proposal.md'); - if (existsSync(proposalPath)) { - const content = readFileSync(proposalPath, 'utf-8'); - const report = validator.validateChangeContent(changeName, content); - printReport('proposal.md', report); - if (!report.valid) hasErrors = true; - } - - // Validate specs/*/spec.md - const specsDir = join(changeDir, 'specs'); - if (existsSync(specsDir)) { - const specFiles = findFiles(specsDir, /^spec\.md$/); - for (const specFile of specFiles) { - const content = readFileSync(specFile, 'utf-8'); - const report = validator.validateDeltaSpec(content); - const rel = relative(changeDir, specFile); - printReport(rel, report); - if (!report.valid) hasErrors = true; - } - } - - console.log(''); - if (hasErrors) { - console.log('❌ Validation failed with errors.'); - process.exit(1); - } else { - console.log('✅ All artifacts validated.'); - process.exit(0); - } -} -``` - -- [ ] **Step 5: Implement cmd-config.mjs** - -Create `scripts/lib/cmd-config.mjs`: - -```javascript -// ssf config — display or modify configuration -import { readFileSync, writeFileSync, existsSync } from 'node:fs'; -import { join } from 'node:path'; -import { loadConfig, getDefaults } from './config-loader.mjs'; - -export async function run(args) { - const config = loadConfig(process.cwd()); - - // No args → display full effective config - if (args.length === 0) { - console.log('Effective configuration:'); - console.log(JSON.stringify(config, null, 2)); - return; - } - - // --get - if (args[0] === '--get' && args[1]) { - const parts = args[1].split('.'); - let val = config; - for (const p of parts) { - if (val === undefined || val === null) { val = undefined; break; } - val = val[p]; - } - if (val !== undefined) { - console.log(typeof val === 'object' ? JSON.stringify(val, null, 2) : val); - } else { - console.error(`Config path not found: ${args[1]}`); - process.exit(1); - } - return; - } - - // --set = - if (args[0] === '--set' && args[1]) { - const eqIdx = args[1].indexOf('='); - if (eqIdx === -1) { - console.error('Usage: ssf config --set ='); - process.exit(2); - } - const path = args[1].slice(0, eqIdx); - const rawValue = args[1].slice(eqIdx + 1); - // Parse value: try number, boolean, then string - let value; - if (rawValue === 'true') value = true; - else if (rawValue === 'false') value = false; - else if (/^\d+$/.test(rawValue)) value = parseInt(rawValue, 10); - else value = rawValue; - - // Load existing config file or start from empty - const configPath = join(process.cwd(), 'spec-superflow.config.json'); - let fileConfig = {}; - if (existsSync(configPath)) { - fileConfig = JSON.parse(readFileSync(configPath, 'utf-8')); - } - - // Set the nested value - const parts = path.split('.'); - let target = fileConfig; - for (let i = 0; i < parts.length - 1; i++) { - if (!target[parts[i]] || typeof target[parts[i]] !== 'object') { - target[parts[i]] = {}; - } - target = target[parts[i]]; - } - target[parts[parts.length - 1]] = value; - - writeFileSync(configPath, JSON.stringify(fileConfig, null, 2) + '\n'); - console.log(`Set ${path} = ${JSON.stringify(value)}`); - return; - } - - console.error('Usage: ssf config [--get ] [--set =]'); - process.exit(2); -} -``` - -- [ ] **Step 6: Manual verification of CLI** - -Run: `node scripts/spec-superflow.mjs --help` -Expected: Help text with all 6 commands listed - -Run: `node scripts/spec-superflow.mjs list` -Expected: Shows `v0.3.0-workflow-enhancements [CLOSED] 5 specs` - -Run: `node scripts/spec-superflow.mjs validate changes/v0.3.0-workflow-enhancements/` -Expected: `✅ All artifacts validated.` - -Run: `node scripts/spec-superflow.mjs config` -Expected: Full default config JSON - -Run: `node scripts/spec-superflow.mjs config --get execution.inlineThreshold` -Expected: `3` - -- [ ] **Step 7: Commit** - -```bash -git add scripts/spec-superflow.mjs scripts/lib/cmd-list.mjs scripts/lib/cmd-validate.mjs scripts/lib/cmd-config.mjs package.json -git commit -m "feat: add CLI entry point with list, validate, config commands" -``` - ---- - -### Task 5: CLI Commands (version + doctor + sync) - -**Files:** -- Create: `scripts/lib/cmd-version.mjs` -- Create: `scripts/lib/cmd-doctor.mjs` -- Create: `scripts/lib/cmd-sync.mjs` - -**Interfaces:** -- Consumes: `loadConfig()` from `config-loader.mjs`, `Validator` + `detectSyncConflicts` from `dist/index.js`, `parseDeltaSpec` from `dist/index.js` -- Produces: 3 additional CLI commands completing the toolchain - -- [ ] **Step 1: Implement cmd-version.mjs** - -Create `scripts/lib/cmd-version.mjs`: - -```javascript -// ssf version — sync version to all manifest files -import { readFileSync, writeFileSync, existsSync } from 'node:fs'; -import { join } from 'node:path'; - -const MANIFESTS = [ - { file: 'package.json', path: ['version'] }, - { file: '.claude-plugin/plugin.json', path: ['version'] }, - { file: '.claude-plugin/marketplace.json', path: ['plugins', '0', 'version'] }, - { file: '.cursor-plugin/plugin.json', path: ['version'] }, - { file: 'gemini-extension.json', path: ['version'] }, -]; - -function getNestedValue(obj, pathParts) { - let val = obj; - for (const p of pathParts) { - if (val === undefined || val === null) return undefined; - val = val[p]; - } - return val; -} - -function setNestedValue(obj, pathParts, value) { - let target = obj; - for (let i = 0; i < pathParts.length - 1; i++) { - target = target[pathParts[i]]; - } - target[pathParts[pathParts.length - 1]] = value; -} - -export async function run(args) { - const dryRun = args.includes('--dry-run'); - const semverArgs = args.filter(a => a !== '--dry-run'); - - if (semverArgs.length < 1) { - console.error('Usage: ssf version [--dry-run]'); - process.exit(2); - } - - const newVersion = semverArgs[0]; - if (!/^\d+\.\d+\.\d+/.test(newVersion)) { - console.error(`Invalid semver: ${newVersion}`); - process.exit(2); - } - - console.log(`Version sync → ${newVersion}${dryRun ? ' (dry run)' : ''}\n`); - - for (const manifest of MANIFESTS) { - const filePath = join(process.cwd(), manifest.file); - if (!existsSync(filePath)) { - console.log(` ⏭️ ${manifest.file} — not found, skipping`); - continue; - } - - const content = JSON.parse(readFileSync(filePath, 'utf-8')); - const currentVersion = getNestedValue(content, manifest.path); - - if (currentVersion === newVersion) { - console.log(` ✅ ${manifest.file}: ${currentVersion} (unchanged)`); - } else { - console.log(` 📝 ${manifest.file}: ${currentVersion || 'N/A'} → ${newVersion}`); - if (!dryRun) { - setNestedValue(content, manifest.path, newVersion); - writeFileSync(filePath, JSON.stringify(content, null, 2) + '\n'); - } - } - } - - console.log(''); - if (dryRun) { - console.log('Dry run complete. Run without --dry-run to apply changes.'); - } else { - console.log('✅ Version synced. Remember to commit and update CHANGELOG.md.'); - } -} -``` - -- [ ] **Step 2: Implement cmd-doctor.mjs** - -Create `scripts/lib/cmd-doctor.mjs`: - -```javascript -// ssf doctor — health check for spec-superflow installation and project -import { readFileSync, readdirSync, existsSync, statSync } from 'node:fs'; -import { join } from 'node:path'; -import { loadConfig } from './config-loader.mjs'; - -function readJsonIfExists(filePath) { - if (!existsSync(filePath)) return null; - try { return JSON.parse(readFileSync(filePath, 'utf-8')); } catch { return null; } -} - -function checkVersionConsistency(root) { - const files = [ - { name: 'package.json', path: ['version'] }, - { name: '.claude-plugin/plugin.json', path: ['version'] }, - { name: '.claude-plugin/marketplace.json', path: ['plugins', '0', 'version'] }, - { name: '.cursor-plugin/plugin.json', path: ['version'] }, - { name: 'gemini-extension.json', path: ['version'] }, - ]; - - const versions = {}; - for (const f of files) { - const data = readJsonIfExists(join(root, f.name)); - if (!data) { versions[f.name] = null; continue; } - let val = data; - for (const p of f.path) val = val?.[p]; - versions[f.name] = val || null; - } - - const uniqueVersions = [...new Set(Object.values(versions).filter(Boolean))]; - const pkgVersion = versions['package.json']; - - if (uniqueVersions.length <= 1) { - return { pass: true, message: `Version: ${pkgVersion} (consistent across ${Object.keys(versions).filter(k => versions[k]).length} manifests)` }; - } - const mismatches = Object.entries(versions) - .filter(([, v]) => v !== pkgVersion) - .map(([name, v]) => `${name}=${v}`) - .join(', '); - return { pass: false, message: `Version mismatch: ${pkgVersion} (package.json) vs ${mismatches}` }; -} - -function checkHooks(root) { - const hooksPath = join(root, 'hooks', 'hooks.json'); - if (!existsSync(hooksPath)) { - return { pass: false, message: 'hooks/hooks.json not found' }; - } - try { - const hooks = JSON.parse(readFileSync(hooksPath, 'utf-8')); - if (hooks.hooks && typeof hooks.hooks === 'object' && !Array.isArray(hooks.hooks)) { - return { pass: true, message: 'valid format' }; - } - return { pass: false, message: 'invalid format (expected record, got ' + typeof hooks.hooks + ')' }; - } catch (e) { - return { pass: false, message: `parse error: ${e.message}` }; - } -} - -function checkSkills(root) { - const skillsDir = join(root, 'skills'); - if (!existsSync(skillsDir)) { - return { pass: false, message: 'skills/ directory not found' }; - } - const dirs = readdirSync(skillsDir).filter(f => { - try { return statSync(join(skillsDir, f)).isDirectory(); } catch { return false; } - }); - const withSkillMd = dirs.filter(d => existsSync(join(skillsDir, d, 'SKILL.md'))); - if (withSkillMd.length === dirs.length) { - return { pass: true, message: `${dirs.length}/${dirs.length} present` }; - } - const missing = dirs.filter(d => !withSkillMd.includes(d)); - return { pass: false, message: `${withSkillMd.length}/${dirs.length} present, missing SKILL.md: ${missing.join(', ')}` }; -} - -function checkDist(root) { - const distDir = join(root, 'dist'); - if (!existsSync(distDir)) { - return { pass: false, message: 'dist/ not found (run npm run build)' }; - } - const indexJs = join(distDir, 'index.js'); - if (!existsSync(indexJs)) { - return { pass: false, message: 'dist/index.js not found' }; - } - return { pass: true, message: 'compiled' }; -} - -function checkNodeVersion() { - const major = parseInt(process.version.slice(1).split('.')[0], 10); - if (major >= 22) { - return { pass: true, message: `${process.version}` }; - } - return { pass: false, message: `${process.version} (requires >= 22)` }; -} - -function checkDocs(root) { - const warnings = []; - const pkg = readJsonIfExists(join(root, 'package.json')); - if (!pkg) return { pass: true, message: 'skipped (no package.json)' }; - - const pkgVersion = pkg.version; - - // Check CHANGELOG has current version - const changelogPath = join(root, 'CHANGELOG.md'); - if (existsSync(changelogPath)) { - const changelog = readFileSync(changelogPath, 'utf-8'); - if (!changelog.includes(`## [${pkgVersion}]`)) { - warnings.push(`CHANGELOG.md missing entry for v${pkgVersion}`); - } - } - - // Check skills count in README - const readmePath = join(root, 'README.md'); - if (existsSync(readmePath)) { - const skillsDir = join(root, 'skills'); - if (existsSync(skillsDir)) { - const actualSkills = readdirSync(skillsDir).filter(f => { - try { return statSync(join(skillsDir, f)).isDirectory(); } catch { return false; } - }).length; - const readme = readFileSync(readmePath, 'utf-8'); - // Count table rows with skill references (heuristic: rows with `skill-name` pattern) - const skillRefs = readme.match(/\| `[a-z-]+`/g) || []; - if (skillRefs.length > 0 && skillRefs.length !== actualSkills) { - warnings.push(`README lists ${skillRefs.length} skills, but skills/ has ${actualSkills}`); - } - } - } - - if (warnings.length === 0) { - return { pass: true, message: 'consistent' }; - } - return { pass: false, message: warnings.join('; ') }; -} - -export async function run(args) { - const root = process.cwd(); - const config = loadConfig(root); - - console.log('spec-superflow doctor:\n'); - - const checks = [ - ['Version', checkVersionConsistency(root)], - ['Hooks', checkHooks(root)], - ['Skills', checkSkills(root)], - ['dist/', checkDist(root)], - ['Node.js', checkNodeVersion()], - ['Docs', checkDocs(root)], - ]; - - // Config check - const configPath = join(root, 'spec-superflow.config.json'); - if (existsSync(configPath)) { - try { - JSON.parse(readFileSync(configPath, 'utf-8')); - checks.push(['Config', { pass: true, message: 'valid JSON' }]); - } catch (e) { - checks.push(['Config', { pass: false, message: `invalid JSON: ${e.message}` }]); - } - } - - let hasFailure = false; - for (const [name, result] of checks) { - const icon = result.pass ? '✅' : '⚠️ '; - console.log(` ${icon} ${name}: ${result.message}`); - if (!result.pass) hasFailure = true; - } - - console.log(''); - if (hasFailure) { - console.log('⚠️ Some checks need attention.'); - } else { - console.log('✅ All checks passed.'); - } -} -``` - -- [ ] **Step 3: Implement cmd-sync.mjs** - -Create `scripts/lib/cmd-sync.mjs`: - -```javascript -// ssf sync — merge delta specs into main specs with conflict detection -import { readFileSync, readdirSync, writeFileSync, existsSync, statSync, mkdirSync } from 'node:fs'; -import { join, basename } from 'node:path'; -import { loadConfig } from './config-loader.mjs'; - -function findSpecFiles(dir) { - const results = []; - if (!existsSync(dir)) return results; - for (const entry of readdirSync(dir)) { - const full = join(dir, entry); - const st = statSync(full); - if (st.isDirectory()) results.push(...findSpecFiles(full)); - else if (entry === 'spec.md') results.push(full); - } - return results; -} - -export async function run(args) { - if (args.length < 1) { - console.error('Usage: ssf sync '); - process.exit(2); - } - - const changeDir = args[0]; - if (!existsSync(changeDir)) { - console.error(`Error: "${changeDir}" not found`); - process.exit(2); - } - - const config = loadConfig(process.cwd()); - const { Validator, parseDeltaSpec } = await import('../../dist/index.js'); - const validator = new Validator(); - - // Collect all unsynced changes for conflict detection - const changesDir = join(process.cwd(), 'changes'); - const allDeltas = []; - - if (existsSync(changesDir)) { - for (const dir of readdirSync(changesDir)) { - const dirPath = join(changesDir, dir); - if (!statSync(dirPath).isDirectory()) continue; - const specsPath = join(dirPath, 'specs'); - if (!existsSync(specsPath)) continue; - - for (const specFile of findSpecFiles(specsPath)) { - const content = readFileSync(specFile, 'utf-8'); - allDeltas.push({ changeName: dir, content }); - } - } - } - - // Check for conflicts - if (allDeltas.length > 0) { - const conflictReport = validator.detectSyncConflicts(allDeltas); - if (conflictReport.hasConflicts) { - console.log('⚠️ Sync conflicts detected:\n'); - for (const conflict of conflictReport.conflicts) { - console.log(` Requirement: "${conflict.requirement}"`); - console.log(` Modified by: ${conflict.changes.join(', ')}\n`); - } - console.log('Resolve conflicts before syncing. Consider syncing changes one at a time.'); - process.exit(1); - } - } - - // Perform sync: copy delta specs to main specs/ - const changeSpecsDir = join(changeDir, 'specs'); - const mainSpecsDir = join(process.cwd(), 'specs'); - const changeName = basename(changeDir); - - if (!existsSync(changeSpecsDir)) { - console.log('No specs/ found in change directory.'); - return; - } - - if (!existsSync(mainSpecsDir)) { - mkdirSync(mainSpecsDir, { recursive: true }); - } - - const specFiles = findSpecFiles(changeSpecsDir); - let synced = 0; - - for (const specFile of specFiles) { - // Determine capability name from directory structure - const relative = specFile.replace(changeSpecsDir + '/', ''); - const capabilityDir = relative.replace('/spec.md', ''); - const targetDir = join(mainSpecsDir, capabilityDir); - - if (!existsSync(targetDir)) { - mkdirSync(targetDir, { recursive: true }); - } - - const content = readFileSync(specFile, 'utf-8'); - writeFileSync(join(targetDir, 'spec.md'), content); - console.log(` 📋 Synced: specs/${capabilityDir}/spec.md`); - synced++; - } - - console.log(`\n✅ Synced ${synced} spec(s) from ${changeName} to specs/`); -} -``` - -- [ ] **Step 4: Manual verification** - -Run: `node scripts/spec-superflow.mjs doctor` -Expected: All checks pass (or warnings for cursor/gemini version lag) - -Run: `node scripts/spec-superflow.mjs version 0.4.0 --dry-run` -Expected: Shows version diff for all 5 manifests without writing - -Run: `node scripts/spec-superflow.mjs sync changes/v0.3.0-workflow-enhancements/` -Expected: Conflict check + sync report (may show already synced) - -- [ ] **Step 5: Commit** - -```bash -git add scripts/lib/cmd-version.mjs scripts/lib/cmd-doctor.mjs scripts/lib/cmd-sync.mjs -git commit -m "feat: add CLI version, doctor, sync commands" -``` - ---- - -### Task 6: SKILL.md Updates (worktree + conflict + config awareness) - -**Files:** -- Modify: `skills/execution-governor/SKILL.md` -- Modify: `skills/spec-syncer/SKILL.md` -- Modify: `skills/workflow-orchestrator/SKILL.md` -- Modify: `skills/spec-forger/SKILL.md` - -**Interfaces:** -- Consumes: `scripts/get-config` bash helper (Task 2) for config queries -- Produces: Updated skill instructions with worktree isolation, conflict detection, and config-aware behavior - -- [ ] **Step 1: Add worktree isolation to execution-governor** - -Add this section to `skills/execution-governor/SKILL.md`, after the "Pre-Flight Plan Review" section: - -```markdown -### Worktree Isolation (Optional, Recommended) - -Before starting execution, check the current branch: - -1. Run: `git branch --show-current` -2. If on `main` or `master` branch: - - Create worktree: `git worktree add ../- -b ` - - Execute all tasks in the worktree directory -3. If already on a feature branch → proceed normally -4. After all batches complete, remind the user: - - "Worktree ready for merge. Suggested commands:" - - `git merge ` - - `git worktree remove ` - -If `git worktree` is unavailable (not a git repo, or git not installed) → silently skip, continue in current directory. -``` - -Also add a Config Check section at the top: - -```markdown -### Config Check - -Before determining execution mode, check the project configuration: -- Run: `bash "${CLAUDE_PLUGIN_ROOT}/scripts/get-config" execution.inlineThreshold` -- If the script returns a value, use it as the inline threshold; otherwise use default (3) -``` - -- [ ] **Step 2: Add conflict detection to spec-syncer** - -Add this section to `skills/spec-syncer/SKILL.md`, before the existing "Pre-Flight: Abandoned Change Guard": - -```markdown -### Pre-Flight: Conflict Detection - -Before syncing, check for conflicts across unsynced changes: - -1. Run: `node "${CLAUDE_PLUGIN_ROOT}/scripts/spec-superflow.mjs" sync ` -2. If conflicts are detected, the CLI will report which requirements are modified by multiple changes -3. Present the conflict list to the user and ask for resolution order -4. Sync changes one at a time in the user-specified order - -Alternatively, use the Validator API directly: -- Call `validator.detectSyncConflicts(deltaSpecs)` with all pending delta specs -- If `hasConflicts` is true, present conflicts before proceeding -``` - -- [ ] **Step 3: Add config awareness to workflow-orchestrator** - -Add this section to `skills/workflow-orchestrator/SKILL.md`, after "Required Inspection": - -```markdown -### Config-Aware Routing - -Before routing, check project configuration: -- Run: `bash "${CLAUDE_PLUGIN_ROOT}/scripts/get-config" artifacts.order` -- If the config specifies a custom artifact order, follow it when checking artifact completeness -- Run: `bash "${CLAUDE_PLUGIN_ROOT}/scripts/get-config" artifacts.skip` -- If artifacts are in the skip list, do not require them for state transitions -``` - -- [ ] **Step 4: Add config check to spec-forger** - -Add this section to `skills/spec-forger/SKILL.md`, after "Required Artifacts": - -```markdown -### Config Check - -Before generating artifacts, check the project configuration: -- Run: `bash "${CLAUDE_PLUGIN_ROOT}/scripts/get-config" artifacts.order` -- Generate artifacts in the configured order (default: proposal → specs → design → tasks → execution-contract) -- Run: `bash "${CLAUDE_PLUGIN_ROOT}/scripts/get-config" artifacts.skip` -- Skip any artifacts listed in the skip configuration -``` - -- [ ] **Step 5: Commit** - -```bash -git add skills/execution-governor/SKILL.md skills/spec-syncer/SKILL.md skills/workflow-orchestrator/SKILL.md skills/spec-forger/SKILL.md -git commit -m "feat: add worktree isolation, conflict detection, config awareness to skills" -``` - ---- - -### Task 7: Version Bump + CHANGELOG + README + Release Prep - -**Files:** -- Modify: `package.json` (version bump) -- Modify: `.claude-plugin/plugin.json` (version bump) -- Modify: `.claude-plugin/marketplace.json` (version bump) -- Modify: `.cursor-plugin/plugin.json` (version bump) -- Modify: `gemini-extension.json` (version bump) -- Modify: `CHANGELOG.md` -- Modify: `README.md` -- Modify: `docs/release-checklist.md` - -**Interfaces:** -- Consumes: CLI `ssf version` command (Task 5) for version sync -- Produces: All manifest files at v0.4.0, CHANGELOG entry, updated README - -- [ ] **Step 1: Run ssf version to sync all manifests** - -Run: `node scripts/spec-superflow.mjs version 0.4.0` -Expected: All 5 manifests updated to 0.4.0 - -Verify: `grep -r '"version"' package.json .claude-plugin/ .cursor-plugin/ gemini-extension.json` - -- [ ] **Step 2: Add CHANGELOG.md entry** - -Insert at the top of CHANGELOG.md (after the header, before v0.3.0): - -```markdown -## [0.4.0] - 2026-06-29 - -### Added - -- **CLI toolchain** — `ssf` command with 6 subcommands: `list` (scan changes), `validate` (artifact validation), `doctor` (health check), `version` (version sync), `sync` (delta spec merge), `config` (configuration management). Zero dependencies via `node:util.parseArgs`. -- **Configuration system** — Optional `spec-superflow.config.json` for customizing artifact order, skip list, execution thresholds, and verification language. Absence = v0.3.0 defaults. Skills query config via `scripts/get-config` helper. -- **Multi-language tokenizer** — `src/validation/tokenizer.ts` with English stemmer (extracted from validator) + Chinese CJK tokenizer (Unicode ranges + 2/3-char sliding window + stop words). Auto-detection based on CJK character ratio. `validateImplementation()` refactored to use tokenizer with optional `config` parameter. -- **Conflict detection** — `Validator.detectSyncConflicts()` detects when multiple changes modify the same requirement. Integrated into `ssf sync` command and `spec-syncer` skill. -- **git worktree isolation** — execution-governor now recommends worktree creation when executing on main/master branch. Pure SKILL.md guidance, no code changes. - -### Changed - -- **package.json** — Added `bin` field exposing `ssf` and `spec-superflow` commands. -- **validateImplementation()** — Refactored to use `tokenize()` instead of inline `stem()`. Added optional `config` parameter for language override. Backward compatible (existing callers unchanged). -- **Version manifests** — `.cursor-plugin/plugin.json` and `gemini-extension.json` now tracked in version sync (previously lagging). - -### Fixed - -- **Version consistency** — `ssf version` command ensures all 5 manifest files stay in sync. `ssf doctor` reports inconsistencies. -``` - -- [ ] **Step 3: Update README.md** - -Add or update the "Current Status" section to reference v0.4.0. Add a CLI section: - -```markdown -## CLI Toolchain - -```bash -# Install globally -npm install -g spec-superflow - -# Or use via npx -npx spec-superflow list - -# Available commands -ssf list # List all changes and status -ssf validate # Validate artifacts -ssf doctor # Health check -ssf version # Sync version to all manifests -ssf sync # Merge delta specs with conflict detection -ssf config # Display/modify configuration -``` -``` - -Update the skills table if any new skills were added (no new skills in v0.4.0, so table row count stays at 9). - -- [ ] **Step 4: Update release-checklist.md** - -Add these items to `docs/release-checklist.md`: - -```markdown -- [ ] Run `node scripts/spec-superflow.mjs doctor` — all checks pass -- [ ] Run `node scripts/spec-superflow.mjs version ` — all manifests in sync -- [ ] Verify CLI works: `node scripts/spec-superflow.mjs --help` -- [ ] Verify `spec-superflow.config.json` absence still works (backward compat) -``` - -- [ ] **Step 5: Build and run full test suite** - -Run: `npm run build && npm test` -Expected: All 20 tests PASS - -- [ ] **Step 6: Commit** - -```bash -git add -A -git commit -m "release: v0.4.0 — CLI toolchain, config system, multi-language tokenizer, conflict detection" -``` - ---- - -## Self-Review - -### 1. Spec Coverage - -| Design Section | Task | Status | -|---|---|---| -| 3.1 Config file format | Task 2 (config-loader defaults match spec) | ✅ | -| 3.2 Config fields | Task 2 (DEFAULTS object matches all 6 fields) | ✅ | -| 3.3 Config loading | Task 2 (loadConfig + findConfigFile + deepMerge) | ✅ | -| 3.4 Skills consume config | Task 6 (config check sections in 4 SKILL.md files) | ✅ | -| 4.1 CLI entry point | Task 4 (spec-superflow.mjs + bin field) | ✅ | -| 4.2 ssf list | Task 4 (cmd-list.mjs) | ✅ | -| 4.3 ssf validate | Task 4 (cmd-validate.mjs) | ✅ | -| 4.4 ssf doctor | Task 5 (cmd-doctor.mjs with all 7 checks) | ✅ | -| 4.5 ssf version | Task 5 (cmd-version.mjs with 5 manifest targets) | ✅ | -| 4.6 ssf sync | Task 5 (cmd-sync.mjs with conflict detection) | ✅ | -| 4.7 ssf config | Task 4 (cmd-config.mjs with get/set/display) | ✅ | -| 5.1 Multi-language tokenizer | Task 1 (tokenizer.ts with EN + ZH + auto-detect) | ✅ | -| 5.2 Integration with validateImplementation | Task 3 (refactor + optional config param) | ✅ | -| 5.3 Conflict detection | Task 3 (detectSyncConflicts method) | ✅ | -| 5.4 git worktree isolation | Task 6 (execution-governor SKILL.md section) | ✅ | -| 5.5 Documentation sync | Task 5 (cmd-doctor.mjs checkDocs function) | ✅ | -| 6. File structure — new files | Tasks 1-5 (10 new files) | ✅ | -| 6. File structure — modified files | Tasks 3,6,7 (14 modified files) | ✅ | -| 8. Testing strategy — 7 new tests | Tasks 1,3 (7 tests: 3 tokenizer + 2 Chinese verification + 2 conflict) | ✅ | -| 9. Version sync checklist | Task 7 (ssf version + CHANGELOG + README) | ✅ | - -**Gaps found:** None. All design sections covered. - -### 2. Placeholder Scan - -Searched for: TBD, TODO, "implement later", "fill in details", "add appropriate", "similar to Task", "write tests for the above". - -**Found:** None. All steps contain complete code. - -### 3. Type Consistency - -| Symbol | Defined | Used | Consistent | -|---|---|---|---| -| `tokenize(text, language?)` | Task 1 tokenizer.ts | Task 3 validator.ts | ✅ | -| `detectLanguage(text)` | Task 1 tokenizer.ts | Task 1 (internal use) | ✅ | -| `loadConfig(projectRoot)` | Task 2 config-loader.mjs | Tasks 4,5,6 cmd-*.mjs + SKILL.md | ✅ | -| `getDefaults()` | Task 2 config-loader.mjs | Task 4 cmd-config.mjs | ✅ | -| `ConflictReport` | Task 3 types.ts | Task 3 validator.ts, Task 5 cmd-sync.mjs | ✅ | -| `SyncConflict` | Task 3 types.ts | Task 3 validator.ts | ✅ | -| `detectSyncConflicts(deltaSpecs)` | Task 3 validator.ts | Task 5 cmd-sync.mjs | ✅ | -| `Validator` class | existing | Tasks 3,4,5 | ✅ | -| `parseDeltaSpec(content)` | existing | Task 3 (used in detectSyncConflicts), Task 5 (cmd-sync) | ✅ | -| `normalizeRequirementName(name)` | existing | Task 3 (used in detectSyncConflicts) | ✅ | -| `validateImplementation(diff, spec, design, config?)` | Task 3 (updated signature) | Existing tests (backward compat, no config param) | ✅ | -| `DeltaPlan` interface | existing parsing module | Task 3 (used via parseDeltaSpec return) | ✅ | - -**Issues found:** None. All method signatures and type names consistent across tasks. diff --git a/changes/v0.5.0-guard-and-state/design.md b/changes/v0.5.0-guard-and-state/design.md deleted file mode 100644 index be80175..0000000 --- a/changes/v0.5.0-guard-and-state/design.md +++ /dev/null @@ -1,361 +0,0 @@ -# spec-superflow v0.5.0 — Guard & State 设计文档 - -**Date:** 2026-06-29 -**Version:** 0.4.0 → 0.5.0 -**Goal:** 从"软提示"到"硬门禁"——为 spec-superflow 增加可靠性层(Reliability Layer),让阶段转换有可执行的门禁、状态恢复有缓存层、过期检测有哈希加速。 - ---- - -## 1. 背景 - -### 1.1 问题 - -spec-superflow v0.4.0 的 workflow-orchestrator 通过**内容级检测**判断状态——Agent 读取工件全文,人工比对 scope、contract、tasks 的一致性。这个机制在短会话中工作良好,但在以下场景暴露弱点: - -1. **上下文压缩后恢复慢**:Agent 需要重新读取 proposal + specs + design + tasks + contract 五份文件全文做比对,每次恢复消耗 ~3500+ tokens。 -2. **阶段转换无硬门禁**:SKILL.md 写的是"你应该检查 X、Y、Z",但 Agent 可能在长上下文中跳过这些检查——没有 exit code、没有阻塞机制。 -3. **过期检测昂贵**:比对 proposal scope vs contract intent lock 需要 Agent 阅读并理解两份长文档,纯推理消耗大。 - -### 1.2 灵感来源 - -对比分析了 [Comet](https://github.com/rpamis/comet)(v0.3.9,1745 stars)的阶段守护机制,吸收其核心思路但保留 spec-superflow 的差异化: - -| Comet 做法 | spec-superflow 吸收方式 | -|---|---| -| Shell 脚本守护(bash) | Node.js 脚本守护,复用 Validator 引擎 | -| `.comet.yaml` 为主状态源 | `.spec-superflow.yaml` 为**派生缓存**,工件优先 | -| 20+ 字段的 YAML 状态机 | 12 字段轻量状态机 | -| SHA256 handoff 上下文 | SHA256 工件哈希 + 独立 contract 哈希 | - -### 1.3 设计原则 - -- **状态文件是派生数据**——永远可从工件重建,损坏就回退内容级检测 -- **守护脚本是硬门禁**——exit code ≠ 0 不允许推进,Agent 不能跳过 -- **哈希是加速层**——让过期检测从"读全文比对"变成"一次脚本调用" -- **不改动现有 skill 核心逻辑**——v0.5.0 是加一层可靠性,不是重写 - ---- - -## 2. 整体架构 - -v0.5.0 在 spec-superflow 的三层架构下新增**第 0 层:可靠性层(Reliability Layer)**: - -``` -┌─────────────────────────────────────────────────┐ -│ Layer 1: Configuration │ -│ spec-superflow.config.json │ -├─────────────────────────────────────────────────┤ -│ Layer 2: CLI Toolchain │ -│ ssf list | validate | doctor | version | │ -│ sync | config | state ← 新增 │ -├─────────────────────────────────────────────────┤ -│ Layer 3: Engine Extensions │ -│ tokenizer.ts | detectSyncConflicts() │ -├─────────────────────────────────────────────────┤ -│ Layer 0: Reliability (NEW) │ -│ guard.mjs ← 维度组合式阶段守护 │ -│ state.mjs ← 轻量状态机(缓存+恢复) │ -│ hash.mjs ← SHA256 工件哈希(快速过期检测) │ -└─────────────────────────────────────────────────┘ -``` - -### 2.1 v0.5.0 vs v0.6.0 规划 - -v0.5.0 是**地基**——守护脚本、状态文件、哈希。v0.6.0 是**上层建筑**——在可靠的状态机和守护之上,增加快速路径(hotfix/tweak)、防漂移 Rule(每轮注入)、决策点协议(统一用户交互)。 - -| 版本 | 主题 | 内容 | -|------|------|------| -| v0.5.0 | 加固 | 阶段守护脚本 + 轻量状态文件 + SHA256 契约哈希 | -| v0.6.0 | 扩展 | 快速路径 hotfix/tweak + 阶段防漂移 Rule + 决策点协议 | - ---- - -## 3. 守护检查维度 & 状态转换矩阵 - -### 3.1 五个检查维度 - -每个维度是独立的检查函数,返回 `{pass: boolean, failures: string[]}`。维度之间无依赖,可独立调用和测试。 - -| 维度 | 函数 | 检查内容 | 复用引擎 | -|------|------|---------|---------| -| `artifacts-exist` | `checkArtifactsExist()` | proposal.md、design.md、tasks.md 存在且非空,specs/ 目录非空 | —(纯文件检查) | -| `schema-valid` | `checkSchemaValid()` | 调用 `Validator.validateChangeContent()` + 每个 spec 的 `validateSpecContent()`,全部通过 | Validator(src/validation/) | -| `contract-fresh` | `checkContractFresh()` | 比对 `.spec-superflow.yaml` 中的 `artifacts_hash` 与当前工件哈希,一致则 fresh | hash.mjs | -| `tasks-complete` | `checkTasksComplete()` | tasks.md 所有 `- [ ]` 变为 `- [x]`,无未完成项 | —(纯文本检查) | -| `tests-passing` | `checkTestsPassing()` | `.spec-superflow.yaml` 中 `test_result` 字段为 `pass` | —(读状态文件) | - -### 3.2 状态转换矩阵 - -spec-superflow 有 8 个状态:`exploring → specifying → bridging → approved → executing → closing`(+ `debugging`、`abandoned`)。 - -每个转换需要的检查维度组合: - -| 转换 | 所需维度 | 备注 | -|------|---------|------| -| `exploring → specifying` | `artifacts-exist` | 至少 proposal.md 存在且非空 | -| `specifying → bridging` | `artifacts-exist` + `schema-valid` | 4 工件齐全 + Schema 验证通过 | -| `bridging → approved` | `artifacts-exist` + `schema-valid` + `contract-fresh` | 用户批准后,contract 必须是最新的 | -| `approved → executing` | `artifacts-exist` + `contract-fresh` | 进入执行前最后确认 contract 未过期 | -| `executing → closing` | `tasks-complete` + `tests-passing` | 所有任务完成 + 测试通过 | -| `executing → debugging` | 无(自动路由) | 遇到 bug 强制进入,不检查 | -| `debugging → executing` | `contract-fresh` | 修复后确认 contract 范围未变 | -| `any → abandoned` | 无(用户确认后) | 放弃不检查完成度 | - -**关键门禁:** -- `bridging → approved` 是唯一需要 `schema-valid` 的转换——规划质量的硬门禁 -- `executing → closing` 是唯一需要 `tests-passing` 的——验证前完成铁律的脚本化 - ---- - -## 4. `.spec-superflow.yaml` 状态文件 - -### 4.1 Schema - -```yaml -# .spec-superflow.yaml — 轻量状态机 -# 派生数据,永远可从工件重建。丢失/损坏 → 回退内容级检测自动重建。 - -# === 核心状态 === -state: executing # exploring | specifying | bridging | approved | executing | closing | abandoned -workflow: full # full | hotfix | tweak(v0.6.0 启用 hotfix/tweak) - -# === 哈希(快速过期检测) === -artifacts_hash: sha256:abc123... # proposal + specs + design + tasks 的联合哈希 -contract_hash: sha256:def456... # execution-contract.md 自身的哈希 - -# === 执行进度 === -execution_mode: sdd # sdd | inline -batches_completed: 2 # 已完成的批次计数 -test_result: null # null | pass | fail(closure-archivist 写入) - -# === 元数据 === -change_name: v0.5.0-guard-and-state -last_transition: 2026-06-29T14:00:00Z -last_transition_from: bridging -last_transition_to: approved -``` - -### 4.2 字段设计理由 - -| 字段 | 为什么需要 | 能否从工件重建 | -|------|-----------|--------------| -| `state` | 上下文压缩后恢复,不用重新内容检测 | ✅ 能 | -| `workflow` | v0.6.0 快速路径需要区分 full/hotfix/tweak | ✅ 能(从 artifact 齐全度推断) | -| `artifacts_hash` | 一次 `ssf state check` 就知道工件是否变了 | ✅ 能(重新计算) | -| `contract_hash` | 同上,针对 contract 单独追踪 | ✅ 能 | -| `execution_mode` | 恢复执行时知道用 SDD 还是 inline | ❌ 不能(是用户决策) | -| `batches_completed` | 恢复时知道哪些批次已完成,不重复执行 | ⚠️ 部分(可从 progress.md 推断) | -| `test_result` | closure-archivist 写入,守护脚本检查 | ✅ 能(重新跑测试) | -| `change_name` | 自包含,文件移动后不丢失身份 | ✅ 能(从目录名) | -| `last_transition` | 审计追踪 | ✅ 能(从 git log 推断) | - -### 4.3 生命周期 - -``` -ssf state init ← bridge-contract 完成后首次创建 -ssf state check ← 验证一致性(哈希比对),workflow-orchestrator 入口时调用 -ssf state transition ← 守护脚本通过后更新状态 -ssf state get ← Agent 读取单个字段 -ssf state rebuild ← 从工件重建状态文件(损坏时) -``` - -### 4.4 与 Comet `.comet.yaml` 的区别 - -| | Comet | spec-superflow | -|---|---|---| -| 定位 | 主状态源 | 派生缓存 | -| 字段数 | ~20+ | ~12 | -| 写入方式 | `comet-state.sh set` | `ssf state transition`(只能通过守护脚本推进) | -| 损坏恢复 | 手工修复 | `ssf state rebuild` 自动从工件重建 | -| 内容级检测 | 无(信任 YAML) | 有(不一致时工件优先,自动修正) | - ---- - -## 5. SHA256 哈希机制 - -### 5.1 哈希计算 - -`scripts/lib/hash.mjs` — 零依赖,使用 `node:crypto`: - -```javascript -// 联合哈希:一次性计算 4 工件的 SHA256 -computeArtifactsHash(changeDir) → "sha256:abc123..." -// 输入:按字母序读取 proposal.md + specs/*/spec.md + design.md + tasks.md -// 拼接为单个字符串 → crypto.createHash('sha256').update(str).digest('hex') - -// 单文件哈希:contract 单独追踪 -computeContractHash(changeDir) → "sha256:def456..." -// 输入:execution-contract.md 全文 - -// 快速比对:不重新读文件,直接比状态文件中的哈希 -isContractFresh(changeDir) → boolean -// 1. 读 .spec-superflow.yaml 的 artifacts_hash -// 2. 重新计算当前工件的哈希 -// 3. 比对 → 返回 true/false -``` - -### 5.2 过期检测性能对比 - -**优化前(v0.4.0,纯内容级检测):** -``` -Agent 读取 proposal.md 全文(~2000 tokens) - → 读取 execution-contract.md 全文(~1500 tokens) - → 人工比对 scope 是否一致 - → 总消耗:~3500 tokens + Agent 推理 -``` - -**优化后(v0.5.0,哈希加速):** -``` -Agent 运行:node scripts/guard/guard.mjs check approved executing - → guard.mjs 内部调用 hash.mjs 做哈希比对 - → 返回:{pass: true} 或 {pass: false, failures: [...]} - → 总消耗:~50 tokens(命令输出) -``` - -**节省:~98% 的过期检测 token。** - -### 5.3 哈希存储位置 - -哈希存入 `.spec-superflow.yaml`(不在 contract 中嵌入 HTML 注释),保持 contract 干净。Agent 通过 `ssf state get ` 读取。 - ---- - -## 6. 守护脚本接口 - -### 6.1 调用方式 - -``` -node scripts/guard/guard.mjs check [--json] -``` - -单一入口,内部根据 `` 查转换矩阵,组合需要的检查维度。Agent 只需记住一个命令。 - -### 6.2 输出格式 - -**通过时:** -```json -{ - "pass": true, - "checks": [ - {"dimension": "artifacts-exist", "pass": true}, - {"dimension": "schema-valid", "pass": true}, - {"dimension": "contract-fresh", "pass": true} - ] -} -``` - -**失败时:** -```json -{ - "pass": false, - "checks": [ - {"dimension": "artifacts-exist", "pass": true}, - {"dimension": "schema-valid", "pass": false, "failures": [ - "specs/auth/spec.md: Requirement 'User Login' missing SHALL or MUST", - "proposal.md: ## Why section is only 23 chars (minimum 50)" - ]}, - {"dimension": "contract-fresh", "pass": true} - ] -} -``` - -### 6.3 在 workflow-orchestrator 中的集成 - -workflow-orchestrator SKILL.md 中,每个路由规则前增加守护脚本调用: - -```markdown -### Route to execution-governor when: -- **Guard check**: Run `node scripts/guard/guard.mjs check approved executing` - - If exit code ≠ 0 → BLOCK. Report failures to user, do not route. - - If exit code = 0 → proceed with routing. -- execution-contract.md exists -- user has explicitly approved it -``` - ---- - -## 7. 文件变更清单 - -### 7.1 新增文件 - -| 文件 | 用途 | 估计行数 | -|------|------|---------| -| `scripts/guard/guard.mjs` | 主入口:解析参数、查转换矩阵、组合维度、输出结果 | ~80 | -| `scripts/guard/checks/artifacts-exist.mjs` | 检查 4 工件 + specs/ 目录存在且非空 | ~30 | -| `scripts/guard/checks/schema-valid.mjs` | 调用 Validator 验证所有工件 | ~40 | -| `scripts/guard/checks/contract-fresh.mjs` | 调 hash.mjs 比对哈希 | ~20 | -| `scripts/guard/checks/tasks-complete.mjs` | 检查 tasks.md 无未勾选项 | ~25 | -| `scripts/guard/checks/tests-passing.mjs` | 读状态文件确认 test_result=pass | ~15 | -| `scripts/lib/hash.mjs` | SHA256 计算 + 比对 | ~40 | -| `scripts/lib/cmd-state.mjs` | `ssf state` 子命令(init/check/transition/get/rebuild) | ~120 | -| `scripts/lib/state-loader.mjs` | YAML 读写(零依赖,regex 解析,与 config-loader 同模式) | ~60 | - -### 7.2 修改文件 - -| 文件 | 改动 | 影响行数 | -|------|------|---------| -| `scripts/spec-superflow.mjs` | 新增 `state` 子命令路由 | +10 | -| `skills/workflow-orchestrator/SKILL.md` | 每个路由规则前增加守护脚本调用指令 | +30 | -| `skills/bridge-contract/SKILL.md` | 生成 contract 后自动运行 `ssf state init` | +5 | -| `skills/closure-archivist/SKILL.md` | 验证完成后运行 `ssf state transition closing` 写入 test_result | +5 | -| `skills/execution-governor/SKILL.md` | 每批次完成后更新 `batches_completed` | +5 | -| `package.json` | 版本号 → 0.5.0 | 1 | -| `CHANGELOG.md` | v0.5.0 条目 | — | -| `README.md` | 更新架构图 + CLI 命令表 | — | - -### 7.3 不变的东西 - -- 9 个 skill 的核心逻辑不变 -- `src/validation/validator.ts` 不变(只被调用,不修改) -- 内容级检测逻辑不变(守护脚本失败时回退) -- 现有 `ssf list/validate/doctor/version/sync/config` 命令不变 -- 零外部依赖约束不变 - ---- - -## 8. 实现顺序 - -### Step 1: 基础设施(预计 1 天) - -``` -hash.mjs → state-loader.mjs → artifacts-exist.mjs -``` -产物:脚本可以读/写状态文件 + 计算哈希 - -### Step 2: 守护脚本(预计 1 天) - -``` -schema-valid.mjs → contract-fresh.mjs → tasks-complete.mjs → tests-passing.mjs -→ guard.mjs(主入口 + 转换矩阵) -``` -产物:`guard.mjs check` 命令完整可用 - -### Step 3: 集成 + CLI(预计 1 天) - -``` -cmd-state.mjs → ssf 入口更新 → 4 个 skill 文件更新 → 文档/版本号 -``` -产物:端到端可用,workflow-orchestrator 能调用守护脚本 - ---- - -## 9. 风险与缓解 - -| 风险 | 缓解 | -|------|------| -| ESM/CJS 互操作:guard.mjs 为 ESM,dist/ 为 CommonJS | 使用动态 `import()` 加载 dist/index.js,与现有 CLI 脚本模式一致 | -| 状态文件与工件不一致 | 工件优先。`ssf state check` 发现不一致时自动回退内容级检测并修正状态文件 | -| 守护脚本增加 Agent 调用负担 | 每次路由前只多一次 shell 命令(~50 tokens 输出),远低于当前内容级检测的 ~3500 tokens | -| 状态文件被误删 | `ssf state rebuild` 一键从工件重建,零信息丢失 | - ---- - -## 10. 展望 v0.6.0 - -v0.5.0 的可靠性层为 v0.6.0 提供地基: - -| v0.6.0 特性 | 依赖 v0.5.0 的什么 | -|------------|-------------------| -| 快速路径 hotfix/tweak | `workflow` 字段区分 full/hotfix/tweak 模式;守护脚本根据 workflow 跳过特定检查 | -| 阶段防漂移 Rule | `ssf state get` 提供当前阶段信息,供 Rule 文件动态生成 | -| 决策点协议 | `ssf state transition` 确保决策点前后的状态一致性 | \ No newline at end of file diff --git a/changes/v0.5.0-guard-and-state/proposal.md b/changes/v0.5.0-guard-and-state/proposal.md deleted file mode 100644 index b38e555..0000000 --- a/changes/v0.5.0-guard-and-state/proposal.md +++ /dev/null @@ -1,71 +0,0 @@ -# Change Proposal: v0.5.0 Guard & State - -## Why - -spec-superflow v0.4.0 的 workflow-orchestrator 通过**内容级检测**判断状态——Agent 读取工件全文,人工比对 scope、contract、tasks 的一致性。这个机制在短会话中工作良好,但在实际使用中暴露三个关键短板: - -1. **上下文压缩后恢复慢** — Agent 需要重新读取 proposal + specs + design + tasks + contract 五份文件全文做比对,每次恢复消耗 ~3500+ tokens。没有缓存层,每次都是"从零开始"。 -2. **阶段转换无硬门禁** — SKILL.md 写的是"你应该检查 X、Y、Z",但 Agent 可能在长上下文中跳过这些检查。没有 exit code、没有阻塞机制——完全是"软提示",靠 Agent 自觉。 -3. **过期检测昂贵** — 比对 proposal scope vs contract intent lock 需要 Agent 阅读并理解两份长文档,纯推理消耗大。没有哈希加速,每次都是"全文重读"。 - -对比分析了 [Comet](https://github.com/rpamis/comet)(v0.3.9,1745 stars)的阶段守护机制后,发现其核心思路(shell 脚本守护 + YAML 状态机 + SHA256 哈希追踪)可以吸收,但需保留 spec-superflow 的差异化(自包含、零依赖、工件优先)。 - -v0.5.0 的目标是为 spec-superflow 增加**可靠性层(Reliability Layer)**,让阶段转换有可执行的门禁、状态恢复有缓存层、过期检测有哈希加速。为 v0.6.0 的快速路径(hotfix/tweak)、防漂移 Rule、决策点协议提供可靠地基。 - -## What Changes - -- 新增 `scripts/guard/guard.mjs` — 维度组合式阶段守护主入口,复用 Validator 引擎 -- 新增 `scripts/guard/checks/` — 5 个独立检查维度(artifacts-exist、schema-valid、contract-fresh、tasks-complete、tests-passing) -- 新增 `scripts/lib/hash.mjs` — SHA256 工件哈希计算 + 比对,过期检测从 ~3500 tokens 降到 ~50 tokens -- 新增 `scripts/lib/cmd-state.mjs` — `ssf state` 子命令(init/check/transition/get/rebuild) -- 新增 `scripts/lib/state-loader.mjs` — 零依赖 YAML 读写,与 config-loader 同模式 -- 新增 `.spec-superflow.yaml` 状态文件约定 — 12 字段轻量状态机,派生缓存,工件优先 -- workflow-orchestrator SKILL.md 每个路由规则前增加守护脚本调用指令 -- bridge-contract SKILL.md 生成 contract 后自动运行 `ssf state init` -- closure-archivist SKILL.md 验证完成后运行 `ssf state transition` -- execution-governor SKILL.md 每批次完成后更新 `batches_completed` -- `ssf` 入口新增 `state` 子命令路由 - -## Capabilities - -### New Capabilities - -- `guard-checks` — 5 个维度组合式阶段守护,硬门禁替代软提示 -- `state-cache` — 轻量状态文件,派生缓存加速上下文恢复 -- `hash-acceleration` — SHA256 契约哈希,过期检测 98% token 节省 - -### Modified Capabilities - -- `workflow-orchestrator` — 路由规则增加守护脚本调用 -- `bridge-contract` — 增加状态文件初始化步骤 -- `closure-archivist` — 增加状态转换步骤 -- `execution-governor` — 增加批次进度追踪 - -## Scope - -### In Scope - -- `scripts/guard/guard.mjs` 主入口 + 转换矩阵 -- `scripts/guard/checks/` 5 个检查维度 -- `scripts/lib/hash.mjs` SHA256 计算 + 比对 -- `scripts/lib/cmd-state.mjs` ssf state 子命令 -- `scripts/lib/state-loader.mjs` YAML 读写 -- 4 个 skill 文件更新(workflow-orchestrator、bridge-contract、closure-archivist、execution-governor) -- `scripts/spec-superflow.mjs` 新增 state 子命令路由 -- `package.json` / plugin.json / marketplace.json 版本同步至 0.5.0 -- `CHANGELOG.md` 添加 v0.5.0 条目 -- `README.md` 更新 CLI 命令表 - -### Out of Scope - -- 快速路径 hotfix/tweak(留给 v0.6.0) -- 阶段防漂移 Rule(留给 v0.6.0) -- 决策点协议(留给 v0.6.0) -- 守护脚本 hook 层硬拦截(留给 v0.6.0,需配合防漂移 Rule) -- `src/validation/validator.ts` 修改(只被调用,不修改) - -## Impact - -- Affected code areas: `scripts/guard/`(新增),`scripts/lib/hash.mjs`(新增),`scripts/lib/cmd-state.mjs`(新增),`scripts/lib/state-loader.mjs`(新增),`scripts/spec-superflow.mjs`(修改),`skills/workflow-orchestrator/`(修改),`skills/bridge-contract/`(修改),`skills/closure-archivist/`(修改),`skills/execution-governor/`(修改) -- Affected APIs or interfaces: 新增 `ssf state` 子命令(init/check/transition/get/rebuild);新增 `guard.mjs check` 命令 -- Dependencies or systems touched: 无新增外部依赖(保持零 npm 依赖约束);新增 `node:crypto` 内置模块使用 \ No newline at end of file diff --git a/changes/v0.5.0-guard-and-state/tasks.md b/changes/v0.5.0-guard-and-state/tasks.md deleted file mode 100644 index 7d0d5ed..0000000 --- a/changes/v0.5.0-guard-and-state/tasks.md +++ /dev/null @@ -1,910 +0,0 @@ -# Implementation Tasks: v0.5.0 Guard & State - -## File Structure - -- `Create: scripts/guard/guard.mjs` — 主入口:解析参数、查转换矩阵、组合维度、输出结果 -- `Create: scripts/guard/checks/artifacts-exist.mjs` — 检查 4 工件 + specs/ 目录存在且非空 -- `Create: scripts/guard/checks/schema-valid.mjs` — 调用 Validator 验证所有工件 -- `Create: scripts/guard/checks/contract-fresh.mjs` — 调 hash.mjs 比对哈希 -- `Create: scripts/guard/checks/tasks-complete.mjs` — 检查 tasks.md 无未勾选项 -- `Create: scripts/guard/checks/tests-passing.mjs` — 读状态文件确认 test_result=pass -- `Create: scripts/lib/hash.mjs` — SHA256 计算 + 比对 -- `Create: scripts/lib/state-loader.mjs` — YAML 读写(零依赖,regex 解析) -- `Create: scripts/lib/cmd-state.mjs` — ssf state 子命令(init/check/transition/get/rebuild) -- `Modify: scripts/spec-superflow.mjs` — 新增 state 子命令路由 -- `Modify: skills/workflow-orchestrator/SKILL.md` — 每个路由规则前增加守护脚本调用指令 -- `Modify: skills/bridge-contract/SKILL.md` — 生成 contract 后自动运行 ssf state init -- `Modify: skills/closure-archivist/SKILL.md` — 验证完成后运行 ssf state transition -- `Modify: skills/execution-governor/SKILL.md` — 每批次完成后更新 batches_completed -- `Modify: package.json` — 版本号 → 0.5.0 -- `Modify: .claude-plugin/plugin.json` — 版本号 → 0.5.0 -- `Modify: .claude-plugin/marketplace.json` — 版本号 → 0.5.0 -- `Modify: .cursor-plugin/plugin.json` — 版本号 → 0.5.0 -- `Modify: gemini-extension.json` — 版本号 → 0.5.0 -- `Modify: CHANGELOG.md` — 添加 v0.5.0 条目 -- `Modify: README.md` — 更新 CLI 命令表 - -## Interfaces - -### Batch 1 → Batch 2 -- **Produces**: `scripts/lib/hash.mjs`(computeArtifactsHash, computeContractHash, isContractFresh)— consumed by contract-fresh.mjs in Batch 2 -- **Produces**: `scripts/lib/state-loader.mjs`(readState, writeState, updateField)— consumed by all check scripts in Batch 2 and cmd-state.mjs in Batch 3 - -### Batch 2 → Batch 3 -- **Produces**: `scripts/guard/guard.mjs`(check 命令)— consumed by workflow-orchestrator SKILL.md in Batch 3 -- **Produces**: 5 个 check 脚本 — consumed by guard.mjs 主入口 - -## 1. Batch 1: 基础设施(hash + state-loader) - -- [ ] **1.1 实现 hash.mjs — SHA256 计算** - -```javascript -// scripts/lib/hash.mjs -import crypto from 'node:crypto'; -import fs from 'node:fs'; -import path from 'node:path'; - -/** - * 计算 4 工件的联合 SHA256 哈希 - * 输入:按字母序读取 proposal.md + specs/*/spec.md + design.md + tasks.md - */ -export function computeArtifactsHash(changeDir) { - const hash = crypto.createHash('sha256'); - - // proposal.md - const proposal = path.join(changeDir, 'proposal.md'); - if (fs.existsSync(proposal)) hash.update(fs.readFileSync(proposal, 'utf-8')); - - // specs/*/spec.md (按字母序) - const specsDir = path.join(changeDir, 'specs'); - if (fs.existsSync(specsDir)) { - const specFiles = []; - walkDir(specsDir, specFiles); - specFiles.sort(); - for (const f of specFiles) { - if (f.endsWith('.md')) hash.update(fs.readFileSync(f, 'utf-8')); - } - } - - // design.md - const design = path.join(changeDir, 'design.md'); - if (fs.existsSync(design)) hash.update(fs.readFileSync(design, 'utf-8')); - - // tasks.md - const tasks = path.join(changeDir, 'tasks.md'); - if (fs.existsSync(tasks)) hash.update(fs.readFileSync(tasks, 'utf-8')); - - return `sha256:${hash.digest('hex')}`; -} - -/** - * 计算 execution-contract.md 的 SHA256 哈希 - */ -export function computeContractHash(changeDir) { - const contract = path.join(changeDir, 'execution-contract.md'); - if (!fs.existsSync(contract)) return null; - const hash = crypto.createHash('sha256'); - hash.update(fs.readFileSync(contract, 'utf-8')); - return `sha256:${hash.digest('hex')}`; -} - -/** - * 快速比对:读状态文件哈希 vs 重新计算当前工件哈希 - */ -export function isContractFresh(changeDir) { - const stateFile = path.join(changeDir, '.spec-superflow.yaml'); - if (!fs.existsSync(stateFile)) return false; - - const state = parseYaml(fs.readFileSync(stateFile, 'utf-8')); - const storedHash = state.artifacts_hash; - if (!storedHash) return false; - - const currentHash = computeArtifactsHash(changeDir); - return storedHash === currentHash; -} - -function walkDir(dir, result) { - for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { - const full = path.join(dir, entry.name); - if (entry.isDirectory()) walkDir(full, result); - else result.push(full); - } -} - -// 最小 YAML 解析(仅提取顶层字段,零依赖) -function parseYaml(content) { - const result = {}; - for (const line of content.split('\n')) { - const match = line.match(/^(\w[\w_]*):\s*(.*)/); - if (match) { - result[match[1]] = match[2].trim() || null; - } - } - return result; -} -``` - -**Files**: `Create: scripts/lib/hash.mjs` - -- [ ] **1.2 实现 state-loader.mjs — 状态文件读写** - -```javascript -// scripts/lib/state-loader.mjs -import fs from 'node:fs'; -import path from 'node:path'; - -const STATE_FILE = '.spec-superflow.yaml'; - -const BUILTIN_DEFAULTS = { - state: 'exploring', - workflow: 'full', - artifacts_hash: null, - contract_hash: null, - execution_mode: null, - batches_completed: 0, - test_result: null, - change_name: null, - last_transition: null, - last_transition_from: null, - last_transition_to: null, -}; - -/** - * 读取状态文件,合并默认值 - */ -export function readState(changeDir) { - const filePath = path.join(changeDir, STATE_FILE); - if (!fs.existsSync(filePath)) return { ...BUILTIN_DEFAULTS, change_name: path.basename(changeDir) }; - - const raw = fs.readFileSync(filePath, 'utf-8'); - const parsed = parseYaml(raw); - return { ...BUILTIN_DEFAULTS, ...parsed }; -} - -/** - * 写入状态文件 - */ -export function writeState(changeDir, state) { - const filePath = path.join(changeDir, STATE_FILE); - const lines = []; - lines.push('# .spec-superflow.yaml — 轻量状态机'); - lines.push('# 派生数据,永远可从工件重建。丢失/损坏 → 回退内容级检测自动重建。'); - lines.push(''); - lines.push('# === 核心状态 ==='); - lines.push(`state: ${state.state || 'exploring'}`); - lines.push(`workflow: ${state.workflow || 'full'}`); - lines.push(''); - lines.push('# === 哈希(快速过期检测) ==='); - lines.push(`artifacts_hash: ${state.artifacts_hash || 'null'}`); - lines.push(`contract_hash: ${state.contract_hash || 'null'}`); - lines.push(''); - lines.push('# === 执行进度 ==='); - lines.push(`execution_mode: ${state.execution_mode || 'null'}`); - lines.push(`batches_completed: ${state.batches_completed || 0}`); - lines.push(`test_result: ${state.test_result || 'null'}`); - lines.push(''); - lines.push('# === 元数据 ==='); - lines.push(`change_name: ${state.change_name || path.basename(changeDir)}`); - lines.push(`last_transition: ${state.last_transition || 'null'}`); - lines.push(`last_transition_from: ${state.last_transition_from || 'null'}`); - lines.push(`last_transition_to: ${state.last_transition_to || 'null'}`); - - fs.writeFileSync(filePath, lines.join('\n') + '\n', 'utf-8'); -} - -/** - * 更新单个字段 - */ -export function updateField(changeDir, field, value) { - const state = readState(changeDir); - state[field] = value; - writeState(changeDir, state); -} - -/** - * 从工件重建状态文件 - */ -export function rebuildState(changeDir, { computeArtifactsHash, computeContractHash }) { - const state = readState(changeDir); - state.artifacts_hash = computeArtifactsHash(changeDir); - state.contract_hash = computeContractHash(changeDir); - writeState(changeDir, state); - return state; -} - -// 最小 YAML 解析(仅提取顶层字段,零依赖) -function parseYaml(content) { - const result = {}; - for (const line of content.split('\n')) { - const trimmed = line.trim(); - if (!trimmed || trimmed.startsWith('#')) continue; - const match = trimmed.match(/^(\w[\w_]*):\s*(.*)/); - if (match) { - const val = match[2].trim(); - if (val === 'null' || val === '') result[match[1]] = null; - else if (/^\d+$/.test(val)) result[match[1]] = parseInt(val, 10); - else result[match[1]] = val; - } - } - return result; -} -``` - -**Files**: `Create: scripts/lib/state-loader.mjs` - -- [ ] **1.3 实现 artifacts-exist.mjs — 第一个检查维度** - -```javascript -// scripts/guard/checks/artifacts-exist.mjs -import fs from 'node:fs'; -import path from 'node:path'; - -/** - * 检查 4 工件 + specs/ 目录存在且非空 - */ -export function checkArtifactsExist(changeDir) { - const failures = []; - const required = ['proposal.md', 'design.md', 'tasks.md']; - - for (const file of required) { - const filePath = path.join(changeDir, file); - if (!fs.existsSync(filePath)) { - failures.push(`${file}: missing`); - } else if (fs.readFileSync(filePath, 'utf-8').trim().length === 0) { - failures.push(`${file}: empty`); - } - } - - const specsDir = path.join(changeDir, 'specs'); - if (!fs.existsSync(specsDir) || fs.readdirSync(specsDir).length === 0) { - failures.push('specs/: missing or empty'); - } - - return { pass: failures.length === 0, failures }; -} -``` - -**Files**: `Create: scripts/guard/checks/artifacts-exist.mjs` - -- [ ] **1.4 验证 hash.mjs 可独立运行** - -```bash -# 用现有 change 目录测试哈希计算 -node -e " - import { computeArtifactsHash, computeContractHash } from './scripts/lib/hash.mjs'; - const h = computeArtifactsHash('changes/v0.3.0-workflow-enhancements'); - console.log('artifacts hash:', h); - console.assert(h.startsWith('sha256:'), 'hash should start with sha256:'); - console.assert(h.length === 71, 'sha256 hex is 64 chars + 7 prefix'); - const ch = computeContractHash('changes/v0.3.0-workflow-enhancements'); - console.log('contract hash:', ch || '(no contract file — expected)'); - console.log('OK'); -" -``` - -**Expected**: 输出 artifacts hash + contract hash(或 null 如果无 contract),无 assert 失败 - -- [ ] **1.5 验证 state-loader.mjs 可独立运行** - -```bash -# 临时目录测试读写 -node -e " - import { writeState, readState, updateField } from './scripts/lib/state-loader.mjs'; - import fs from 'node:fs'; - const tmp = '/tmp/ssf-test-state'; - fs.mkdirSync(tmp, { recursive: true }); - const state = readState(tmp); - console.assert(state.state === 'exploring', 'default state'); - state.artifacts_hash = 'sha256:test123'; - writeState(tmp, state); - console.assert(fs.existsSync(tmp + '/.spec-superflow.yaml'), 'file written'); - const reread = readState(tmp); - console.assert(reread.artifacts_hash === 'sha256:test123', 'round-trip'); - updateField(tmp, 'batches_completed', 3); - const updated = readState(tmp); - console.assert(updated.batches_completed === 3, 'field update'); - fs.rmSync(tmp, { recursive: true }); - console.log('OK'); -" -``` - -**Expected**: 输出 OK,无 assert 失败 - -- [ ] **1.6 Commit Batch 1** - -```bash -git add -A -git commit -m "feat(v0.5.0): hash engine + state loader + artifacts-exist check" -``` - -## 2. Batch 2: 守护脚本(5 个检查维度 + 主入口) - -Depends on: Batch 1(hash.mjs + state-loader.mjs) - -- [ ] **2.1 实现 schema-valid.mjs — 复用 Validator 引擎** - -```javascript -// scripts/guard/checks/schema-valid.mjs -import fs from 'node:fs'; -import path from 'node:path'; - -/** - * 调用 Validator 验证所有工件 - * 动态 import dist/index.js(ESM → CJS 互操作) - */ -export async function checkSchemaValid(changeDir) { - const failures = []; - - // 动态 import 编译后的 Validator - const { Validator } = await import(new URL('../../../dist/index.js', import.meta.url).pathname); - const validator = new Validator(); - - // 验证 proposal.md - const proposalPath = path.join(changeDir, 'proposal.md'); - if (fs.existsSync(proposalPath)) { - const content = fs.readFileSync(proposalPath, 'utf-8'); - const report = validator.validateChangeContent(content); - if (!report.valid) { - for (const issue of report.issues) { - if (issue.level === 'ERROR') { - failures.push(`proposal.md: ${issue.message}`); - } - } - } - } - - // 验证每个 specs/*/spec.md - const specsDir = path.join(changeDir, 'specs'); - if (fs.existsSync(specsDir)) { - for (const entry of fs.readdirSync(specsDir, { withFileTypes: true })) { - if (entry.isDirectory()) { - const specFile = path.join(specsDir, entry.name, 'spec.md'); - if (fs.existsSync(specFile)) { - const content = fs.readFileSync(specFile, 'utf-8'); - const report = validator.validateSpecContent(content); - if (!report.valid) { - for (const issue of report.issues) { - if (issue.level === 'ERROR') { - failures.push(`specs/${entry.name}/spec.md: ${issue.message}`); - } - } - } - } - } - } - } - - return { pass: failures.length === 0, failures }; -} -``` - -**Files**: `Create: scripts/guard/checks/schema-valid.mjs` - -- [ ] **2.2 实现 contract-fresh.mjs — 哈希比对** - -```javascript -// scripts/guard/checks/contract-fresh.mjs -import { isContractFresh } from '../../lib/hash.mjs'; - -/** - * 比对 .spec-superflow.yaml 中的 artifacts_hash 与当前工件哈希 - */ -export function checkContractFresh(changeDir) { - const fresh = isContractFresh(changeDir); - if (fresh) { - return { pass: true, failures: [] }; - } - return { - pass: false, - failures: ['execution-contract.md is stale: artifacts hash mismatch. Re-run bridge-contract to regenerate.'], - }; -} -``` - -**Files**: `Create: scripts/guard/checks/contract-fresh.mjs` - -- [ ] **2.3 实现 tasks-complete.mjs — 任务勾选检查** - -```javascript -// scripts/guard/checks/tasks-complete.mjs -import fs from 'node:fs'; -import path from 'node:path'; - -/** - * 检查 tasks.md 所有 - [ ] 变为 - [x],无未完成项 - */ -export function checkTasksComplete(changeDir) { - const tasksPath = path.join(changeDir, 'tasks.md'); - if (!fs.existsSync(tasksPath)) { - return { pass: false, failures: ['tasks.md: missing'] }; - } - - const content = fs.readFileSync(tasksPath, 'utf-8'); - const unchecked = content.match(/^- \[ \]/gm); - if (unchecked && unchecked.length > 0) { - return { - pass: false, - failures: [`tasks.md: ${unchecked.length} unchecked task(s) remaining`], - }; - } - - const hasAny = content.match(/^- \[x\]/gm); - if (!hasAny) { - return { pass: false, failures: ['tasks.md: no completed tasks found'] }; - } - - return { pass: true, failures: [] }; -} -``` - -**Files**: `Create: scripts/guard/checks/tasks-complete.mjs` - -- [ ] **2.4 实现 tests-passing.mjs — 测试结果检查** - -```javascript -// scripts/guard/checks/tests-passing.mjs -import { readState } from '../../lib/state-loader.mjs'; - -/** - * 读状态文件确认 test_result=pass - */ -export function checkTestsPassing(changeDir) { - const state = readState(changeDir); - if (state.test_result === 'pass') { - return { pass: true, failures: [] }; - } - return { - pass: false, - failures: [`test_result is '${state.test_result || 'null'}' — expected 'pass'. Run closure-archivist verification first.`], - }; -} -``` - -**Files**: `Create: scripts/guard/checks/tests-passing.mjs` - -- [ ] **2.5 实现 guard.mjs — 主入口 + 转换矩阵** - -```javascript -#!/usr/bin/env node -// scripts/guard/guard.mjs -import { parseArgs } from 'node:util'; -import { checkArtifactsExist } from './checks/artifacts-exist.mjs'; -import { checkTasksComplete } from './checks/tasks-complete.mjs'; -import { checkTestsPassing } from './checks/tests-passing.mjs'; -import { checkContractFresh } from './checks/contract-fresh.mjs'; - -// 转换矩阵: 需要的检查维度 -const TRANSITION_CHECKS = { - 'exploring:specifying': ['artifacts-exist'], - 'specifying:bridging': ['artifacts-exist', 'schema-valid'], - 'bridging:approved': ['artifacts-exist', 'schema-valid', 'contract-fresh'], - 'approved:executing': ['artifacts-exist', 'contract-fresh'], - 'executing:closing': ['tasks-complete', 'tests-passing'], - 'executing:debugging': [], // 自动路由,不检查 - 'debugging:executing': ['contract-fresh'], -}; - -async function main() { - const { positionals } = parseArgs({ - options: { json: { type: 'boolean', default: false } }, - allowPositionals: true, - }); - - const subcommand = positionals[0]; - if (subcommand !== 'check') { - console.error('Usage: guard.mjs check [--json]'); - process.exit(2); - } - - const changeDir = positionals[1]; - const fromState = positionals[2]; - const toState = positionals[3]; - const useJson = process.argv.includes('--json'); - - const key = `${fromState}:${toState}`; - const dimensions = TRANSITION_CHECKS[key]; - - if (!dimensions) { - const msg = `Unknown transition: ${fromState} → ${toState}. Valid transitions: ${Object.keys(TRANSITION_CHECKS).join(', ')}`; - if (useJson) console.log(JSON.stringify({ pass: false, checks: [], error: msg })); - else console.error(msg); - process.exit(1); - } - - if (dimensions.length === 0) { - // 无检查的转换(如 executing → debugging) - const result = { pass: true, checks: [] }; - if (useJson) console.log(JSON.stringify(result)); - else console.log('All checks passed (no checks required for this transition).'); - process.exit(0); - } - - const checks = []; - let pass = true; - - for (const dim of dimensions) { - let result; - switch (dim) { - case 'artifacts-exist': - result = checkArtifactsExist(changeDir); - break; - case 'schema-valid': - result = await (await import('./checks/schema-valid.mjs')).checkSchemaValid(changeDir); - break; - case 'contract-fresh': - result = checkContractFresh(changeDir); - break; - case 'tasks-complete': - result = checkTasksComplete(changeDir); - break; - case 'tests-passing': - result = checkTestsPassing(changeDir); - break; - default: - result = { pass: false, failures: [`Unknown dimension: ${dim}`] }; - } - checks.push({ dimension: dim, pass: result.pass, failures: result.failures || [] }); - if (!result.pass) pass = false; - } - - if (useJson) { - console.log(JSON.stringify({ pass, checks }, null, 2)); - } else { - if (pass) { - console.log('All checks passed.'); - } else { - console.error('Guard checks failed:'); - for (const c of checks) { - if (!c.pass) { - for (const f of c.failures) { - console.error(` [FAIL] ${c.dimension}: ${f}`); - } - } - } - } - } - - process.exit(pass ? 0 : 1); -} - -main().catch(err => { - console.error('Guard error:', err.message); - process.exit(1); -}); -``` - -**Files**: `Create: scripts/guard/guard.mjs` - -- [ ] **2.6 验证 guard.mjs 可运行** - -```bash -# 测试 artifacts-exist 检查(v0.3.0 change 目录有完整工件) -node scripts/guard/guard.mjs check changes/v0.3.0-workflow-enhancements exploring specifying --json - -# 测试 tasks-complete 检查(v0.3.0 tasks.md 所有项已勾选) -node scripts/guard/guard.mjs check changes/v0.3.0-workflow-enhancements executing closing --json - -# 测试未知转换(应报错) -node scripts/guard/guard.mjs check changes/v0.3.0-workflow-enhancements closing exploring --json 2>&1; echo "exit: $?" -``` - -**Expected**: -- 第一个命令:pass=true(artifacts-exist 通过) -- 第二个命令:pass=true 或 pass=false(取决于 tasks.md 勾选状态和 test_result) -- 第三个命令:exit code 1,包含 "Unknown transition" - -- [ ] **2.7 Commit Batch 2** - -```bash -git add -A -git commit -m "feat(v0.5.0): guard script with 5 check dimensions + transition matrix" -``` - -## 3. Batch 3: 集成 + CLI + 文档 - -Depends on: Batch 2(guard.mjs 完整可用) - -- [ ] **3.1 实现 cmd-state.mjs — ssf state 子命令** - -```javascript -// scripts/lib/cmd-state.mjs -import { parseArgs } from 'node:util'; -import { readState, writeState, updateField, rebuildState } from './state-loader.mjs'; -import { computeArtifactsHash, computeContractHash } from './hash.mjs'; - -export async function run(args) { - const { positionals, values } = parseArgs({ - args, - options: { - json: { type: 'boolean', default: false }, - }, - allowPositionals: true, - }); - - const sub = positionals[0]; // init | check | transition | get | rebuild - const changeDir = positionals[1]; - const arg = positionals[2]; // for transition, for get - - if (!changeDir) { - console.error('Usage: ssf state [arg]'); - process.exit(2); - } - - switch (sub) { - case 'init': { - const hash = computeArtifactsHash(changeDir); - const ch = computeContractHash(changeDir); - const state = readState(changeDir); - state.artifacts_hash = hash; - state.contract_hash = ch; - state.last_transition = new Date().toISOString(); - writeState(changeDir, state); - console.log(values.json ? JSON.stringify({ ok: true, hash }) : `State initialized. artifacts_hash: ${hash}`); - break; - } - case 'check': { - const state = readState(changeDir); - const currentHash = computeArtifactsHash(changeDir); - const consistent = state.artifacts_hash === currentHash; - if (values.json) { - console.log(JSON.stringify({ - consistent, - stored_hash: state.artifacts_hash, - current_hash: currentHash, - state: state.state, - })); - } else { - console.log(consistent ? 'State consistent with artifacts.' : 'State inconsistent — artifacts have changed since last transition.'); - console.log(` State: ${state.state}, stored hash: ${state.artifacts_hash}`); - console.log(` Current hash: ${currentHash}`); - } - process.exit(consistent ? 0 : 1); - break; - } - case 'transition': { - const toState = arg; - if (!toState) { - console.error('Usage: ssf state transition '); - process.exit(2); - } - const state = readState(changeDir); - const fromState = state.state; - state.state = toState; - state.last_transition_from = fromState; - state.last_transition_to = toState; - state.last_transition = new Date().toISOString(); - writeState(changeDir, state); - console.log(values.json - ? JSON.stringify({ ok: true, from: fromState, to: toState }) - : `State transitioned: ${fromState} → ${toState}`); - break; - } - case 'get': { - const field = arg; - if (!field) { - console.error('Usage: ssf state get '); - process.exit(2); - } - const state = readState(changeDir); - const value = state[field]; - console.log(values.json ? JSON.stringify({ field, value }) : (value ?? 'null')); - break; - } - case 'rebuild': { - const state = rebuildState(changeDir, { computeArtifactsHash, computeContractHash }); - console.log(values.json ? JSON.stringify({ ok: true, state }) : `State rebuilt from artifacts. state: ${state.state}`); - break; - } - default: - console.error(`Unknown subcommand: ${sub}. Valid: init, check, transition, get, rebuild`); - process.exit(2); - } -} -``` - -**Files**: `Create: scripts/lib/cmd-state.mjs` - -- [ ] **3.2 更新 ssf 入口 — 新增 state 子命令路由** - -```javascript -// 在 scripts/spec-superflow.mjs 中新增 state 路由 -// 在现有的 subcommand switch 中增加一个 case: - -// case 'state': -// const { run: runState } = await import('./lib/cmd-state.mjs'); -// await runState(positionals.slice(1)); -// break; -``` - -**Files**: `Modify: scripts/spec-superflow.mjs` - -- [ ] **3.3 更新 workflow-orchestrator SKILL.md — 增加守护脚本调用** - -在每个路由规则前增加守护脚本调用指令。以 `execution-governor` 路由为例: - -```markdown -### Route to `execution-governor` when: - -- **Guard check passes**: Run `node scripts/guard/guard.mjs check approved executing --json` - - If exit code ≠ 0 → BLOCK. Report failures to user, do not route. - - If exit code = 0 → proceed with routing. -- `execution-contract.md` exists -- the user has explicitly approved it -- the contract still matches the current planning artifacts -``` - -同样更新 `closure-archivist`、`bridge-contract`、`spec-forger`、`spec-explorer` 的路由规则。 - -**Files**: `Modify: skills/workflow-orchestrator/SKILL.md` - -- [ ] **3.4 更新 bridge-contract SKILL.md — 生成 contract 后初始化状态文件** - -在 bridge-contract SKILL.md 的完成步骤中增加: - -```markdown -### After Contract Generation - -After `execution-contract.md` is written and validated: - -1. Run: `node scripts/spec-superflow.mjs state init ` -2. This creates `.spec-superflow.yaml` with: - - `artifacts_hash` — SHA256 of all 4 planning artifacts - - `contract_hash` — SHA256 of the execution contract - - `state: bridging` -3. The hash enables fast staleness detection in subsequent phases. -``` - -**Files**: `Modify: skills/bridge-contract/SKILL.md` - -- [ ] **3.5 更新 closure-archivist SKILL.md — 验证完成后状态转换** - -在 closure-archivist SKILL.md 的最终完成步骤中增加: - -```markdown -### After Verification - -After the verification report is generated and verdict is PASS or CONDITIONAL: - -1. Run: `node scripts/spec-superflow.mjs state transition closing` -2. Run: `node scripts/spec-superflow.mjs state get test_result` -3. This updates `.spec-superflow.yaml` with `state: closing` and `test_result: pass|fail` -``` - -**Files**: `Modify: skills/closure-archivist/SKILL.md` - -- [ ] **3.6 更新 execution-governor SKILL.md — 批次进度追踪** - -在 execution-governor SKILL.md 的 `### Progress Ledger` 部分增加: - -```markdown -After each batch completes and the progress ledger is updated: - -1. Run: `node scripts/spec-superflow.mjs state get batches_completed` -2. Increment the value and update: - - Run: `node scripts/spec-superflow.mjs state transition executing` - - (This updates `batches_completed` and `last_transition` timestamp) -``` - -**Files**: `Modify: skills/execution-governor/SKILL.md` - -- [ ] **3.7 验证端到端流程** - -```bash -# 用 v0.5.0 自己的 change 目录测试完整流程 -CHANGE_DIR="changes/v0.5.0-guard-and-state" - -# 1. 初始化状态文件 -node scripts/spec-superflow.mjs state init "$CHANGE_DIR" -node scripts/spec-superflow.mjs state get "$CHANGE_DIR" state -node scripts/spec-superflow.mjs state get "$CHANGE_DIR" artifacts_hash - -# 2. 检查状态一致性 -node scripts/spec-superflow.mjs state check "$CHANGE_DIR" --json - -# 3. 守护脚本检查(specifying → bridging) -node scripts/guard/guard.mjs check "$CHANGE_DIR" specifying bridging --json - -# 4. 状态转换 -node scripts/spec-superflow.mjs state transition "$CHANGE_DIR" specifying -node scripts/spec-superflow.mjs state get "$CHANGE_DIR" state - -# 5. 从工件重建 -node scripts/spec-superflow.mjs state rebuild "$CHANGE_DIR" -node scripts/spec-superflow.mjs state check "$CHANGE_DIR" --json -``` - -**Expected**: 所有命令正常执行,状态正确流转,hash 一致 - -- [ ] **3.8 版本号同步** - -使用 `ssf version` 命令同步所有 manifest 文件: - -```bash -node scripts/spec-superflow.mjs version 0.5.0 -``` - -**Files**: `Modify: package.json`, `Modify: .claude-plugin/plugin.json`, `Modify: .claude-plugin/marketplace.json`, `Modify: .cursor-plugin/plugin.json`, `Modify: gemini-extension.json` - -- [ ] **3.9 更新 CHANGELOG.md** - -```markdown -## [0.5.0] - 2026-06-29 - -### Added - -- **Guard script system** — `scripts/guard/guard.mjs` provides dimension-based phase transition validation with 5 check dimensions (artifacts-exist, schema-valid, contract-fresh, tasks-complete, tests-passing). Exit code ≠ 0 blocks transitions. Reuses existing Validator engine for schema validation. -- **Lightweight state file** — `.spec-superflow.yaml` as a derived cache for fast context recovery (12 fields). Always rebuildable from artifacts via `ssf state rebuild`. Artifacts are the source of truth; state file is a performance optimization. -- **SHA256 hash acceleration** — `scripts/lib/hash.mjs` computes artifact hashes for O(1) staleness detection. Reduces staleness detection from ~3500 tokens (full content read) to ~50 tokens (single script call). -- **ssf state CLI** — New `state` subcommand with 5 operations: `init`, `check`, `transition`, `get`, `rebuild`. - -### Changed - -- **workflow-orchestrator** — Each routing rule now includes a guard script invocation step before allowing transitions. -- **bridge-contract** — Automatically runs `ssf state init` after contract generation. -- **closure-archivist** — Runs `ssf state transition` after verification completes. -- **execution-governor** — Updates `batches_completed` in state file after each batch. -``` - -**Files**: `Modify: CHANGELOG.md` - -- [ ] **3.10 更新 README.md** - -在 CLI 命令表中增加 `state` 子命令: - -```markdown -| `ssf state init ` | Initialize state file with artifact hashes | -| `ssf state check ` | Verify state file consistency with artifacts | -| `ssf state transition ` | Record state transition | -| `ssf state get ` | Read a single state field | -| `ssf state rebuild ` | Rebuild state file from artifacts | -``` - -**Files**: `Modify: README.md` - -- [ ] **3.11 最终构建 + 测试** - -```bash -npm run build -npm test -``` - -**Expected**: Build 成功,所有现有测试通过 - -- [ ] **3.12 Commit Batch 3** - -```bash -git add -A -git commit -m "feat(v0.5.0): CLI integration + skill updates + docs for guard & state system" -``` - -## 4. Closeout - -- [ ] **4.1 验证所有 contract obligations** - -对照 design.md 确认所有设计决策已实现: - -| # | Obligation | Status | -|---|-----------|--------| -| 1 | guard.mjs 5 个检查维度全部实现 | — | -| 2 | 8 状态转换矩阵正确映射 | — | -| 3 | .spec-superflow.yaml 12 字段 schema | — | -| 4 | hash.mjs SHA256 计算 + 比对 | — | -| 5 | ssf state 5 个子命令 | — | -| 6 | 4 个 skill 文件更新 | — | -| 7 | 过期检测 token 节省 98% | — | -| 8 | 状态文件派生数据,可从工件重建 | — | -| 9 | 守护脚本复用 Validator 引擎 | — | -| 10 | 零外部依赖 | — | - -- [ ] **4.2 总结风险、follow-ups、归档准备** - -风险: -- ESM/CJS 互操作:schema-valid.mjs 动态 import dist/index.js。已在设计阶段考虑,使用动态 `import()` 模式,与现有 CLI 脚本一致。 -- 状态文件与工件不一致:工件优先。`ssf state check` 发现不一致时自动回退内容级检测。 -- 守护脚本增加 Agent 调用负担:每次路由前只多一次 shell 命令(~50 tokens 输出),远低于当前内容级检测的 ~3500 tokens。 - -Follow-ups(v0.6.0): -- 快速路径 hotfix/tweak(依赖 `workflow` 字段) -- 阶段防漂移 Rule(依赖 `ssf state get` 读取当前阶段) -- 决策点协议(依赖 `ssf state transition` 确保状态一致性) -- 守护脚本 hook 层硬拦截(配合防漂移 Rule 实现 PreToolUse 拦截) \ No newline at end of file diff --git a/changes/v0.6.0-fast-and-aware/.spec-superflow.yaml b/changes/v0.6.0-fast-and-aware/.spec-superflow.yaml deleted file mode 100644 index 4cd6cfd..0000000 --- a/changes/v0.6.0-fast-and-aware/.spec-superflow.yaml +++ /dev/null @@ -1,21 +0,0 @@ -# .spec-superflow.yaml — lightweight state machine -# Derived data. Always rebuildable from artifacts. Lost/corrupt → fall back to content-level detection. - -# === Core state === -state: approved -workflow: full - -# === Hashes (fast staleness detection) === -artifacts_hash: sha256:0b9224c9c2cede4e178a3bbddbd867b1d3b8ead4a1bdbbd6bc0d4b92edad0b8c -contract_hash: sha256:3c70ea971b42b80bab773de46244150d87e27cc837457e95bec336bd510b6844 - -# === Execution progress === -execution_mode: null -batches_completed: 0 -test_result: null - -# === Metadata === -change_name: v0.6.0-fast-and-aware -last_transition: 2026-06-29T07:19:54.463Z -last_transition_from: exploring -last_transition_to: approved diff --git a/changes/v0.6.0-fast-and-aware/design.md b/changes/v0.6.0-fast-and-aware/design.md deleted file mode 100644 index fd0fe60..0000000 --- a/changes/v0.6.0-fast-and-aware/design.md +++ /dev/null @@ -1,307 +0,0 @@ -# 技术设计:v0.6.0 Fast & Aware - -**Date:** 2026-06-29 -**Version:** 0.5.0 → 0.6.0 -**Goal:** 在 v0.5.0 可靠性层地基上增加三个扩展——快速路径让简单变更走捷径,阶段防漂移让 Agent 始终知道自己在哪,决策点协议让所有"需要用户确认"的时刻有统一标准。 - ---- - -## 1. 背景 - -### 1.1 当前状态 - -v0.5.0 交付了: -- `guard.mjs`:7 个状态转换的硬门禁,5 个检查维度(artifacts-exist, schema-valid, contract-fresh, tasks-complete, tests-passing) -- `.spec-superflow.yaml`:12 字段轻量状态机(含 `workflow: full` 字段,v0.5.0 预留但未使用) -- `hash.mjs`:SHA256 工件哈希 + 契约哈希,加速过期检测 -- `cmd-state.mjs`:5 个子命令(init/check/transition/get/rebuild) - -### 1.2 约束 - -- 零外部 npm 依赖(仅 TypeScript 作为 devDependency) -- 不改动 `src/validation/validator.ts` -- 不破坏现有 9 个 skill 的核心逻辑 -- 复用 v0.5.0 基础设施(guard.mjs, state-loader.mjs, hash.mjs, cmd-state.mjs) - -### 1.3 利益相关者 - -- 日常使用者:需要快速修复 bug 或调整配置的开发者 -- Agent(Claude Code):需要在长会话中保持阶段感知 -- 插件维护者:需要统一的决策点文档来迭代 skill - ---- - -## 2. 目标与非目标 - -### 2.1 目标 - -- hotfix 模式:≤2 文件的小修复,跳过 spec-explorer 和完整 spec-forger,走最小契约 -- tweak 模式:纯配置/文档修改,跳过 spec-explorer、spec-forger 和完整 bridge-contract -- 阶段防漂移:`ssf inject` 命令生成 `.claude/always/phase-guard.md`,每轮注入当前阶段信息 -- 决策点协议:`docs/decision-points.md` 集中定义 7 个决策点,所有 skill 统一引用 -- 自动升级:hotfix/tweak 超出阈值时自动升级为 full,防止走捷径做大事 - -### 2.2 非目标 - -- 不实现自动模式检测(v0.6.0 由用户显式声明 hotfix/tweak,workflow-orchestrator 验证阈值) -- 不实现 `.claude/always/` 以外的注入机制(如 Cursor rules、Copilot instructions) -- 不实现决策点的自动审计(仅记录到状态文件,不生成审计报告) -- 不新增 skill(保持 9 个 skill 不变) - ---- - -## 3. 架构决策 - -### 决策 1: 模式检测由 workflow-orchestrator 执行,不新增检测脚本 - -- **选择**: workflow-orchestrator 在路由前检查 `.spec-superflow.yaml` 的 `workflow` 字段,根据用户意图关键词("hotfix"/"tweak")和文件数量启发式验证 -- **理由**: 模式检测是路由逻辑的一部分,放在 orchestrator 内最自然。新增独立脚本会增加 CLI 命令数量,且 orchestrator 已经在做内容级检测 -- **替代方案**: - - A) 新增 `guard.mjs detect-mode` 子命令 — 增加命令复杂度,且模式检测需要理解用户意图(LLM 推理),不适合 shell 脚本 - - B) 在 `state-loader.mjs` 中加入自动检测 — 违反 state-loader 的单一职责(读写状态文件) - -### 决策 2: guard.mjs 模式感知通过 workflow 参数传入,不读状态文件 - -- **选择**: guard.mjs 接受 `--workflow ` 可选参数。workflow-orchestrator 在调用 guard 前从状态文件读取 workflow 字段并传入 -- **理由**: guard.mjs 保持无状态(不读 .spec-superflow.yaml),调用方负责提供上下文。这与 guard.mjs 现有的设计一致——它只接受显式参数 -- **替代方案**: - - A) guard.mjs 自动读取 .spec-superflow.yaml — 增加 guard.mjs 的职责,使其从"纯检查器"变成"状态感知检查器",耦合度增加 - - B) 在转换矩阵中硬编码所有模式变体 — 矩阵膨胀(7 transitions × 3 modes = 21 entries),维护成本高 - -### 决策 3: phase-guard.md 通过 ssf inject 生成,不通过 hook 自动生成 - -- **选择**: `ssf inject ` 是一个显式 CLI 命令,用户或 workflow-orchestrator 在状态转换后手动调用。生成的文件安装到 `.claude/always/phase-guard.md` -- **理由**: - - Hook 方式(每次 session-start 自动生成)会导致每轮都读取状态文件,增加延迟 - - 显式命令让用户控制注入时机,避免在错误时机生成过时规则 - - `.claude/always/` 是 Claude Code 的标准每轮注入机制,与 plugin 系统兼容 -- **替代方案**: - - A) session-start hook 自动生成 — 每轮增加 ~100ms I/O,且 hook 无法感知当前 change 目录 - - B) 写入 CLAUDE.md — CLAUDE.md 是项目级文档,不适合存放动态生成的阶段规则 - -### 决策 4: 决策点审计记录在状态文件中,不新增独立日志文件 - -- **选择**: 决策点结果记录在 `.spec-superflow.yaml` 中,字段格式 `dp__result` + `dp__timestamp` -- **理由**: 状态文件已经是变更的派生数据汇总,决策点是状态的一部分。新增独立日志文件(如 `.spec-superflow-audit.jsonl`)增加复杂度,且与"状态文件可从工件重建"的原则冲突 -- **替代方案**: - - A) 新增 `.spec-superflow-audit.jsonl` — 追加式日志,信息更完整,但增加文件管理负担 - - B) 记录在 execution-contract.md 中 — contract 是静态文档,不适合存放动态决策记录 - -### 决策 5: phase-guard.md 内容按阶段模板生成,不用通用模板引擎 - -- **选择**: `cmd-inject.mjs` 内部维护一个 `PHASE_TEMPLATES` 对象,每个阶段对应一个模板字符串。模板中用 `{{change_name}}`、`{{state}}`、`{{workflow}}` 占位符,简单的 `String.replace()` 替换 -- **理由**: 零依赖约束排除了 Handlebars/Nunjucks 等模板引擎。7 个阶段 × 3 种 workflow 模式 = 最多 21 个模板,但 hotfix/tweak 模式共享 full 的模板(只是允许/禁止操作不同),实际只需 8 个基础模板 -- **替代方案**: - - A) 通用模板引擎 — 违反零依赖约束 - - B) 纯字符串拼接 — 可读性差,模板修改困难 - ---- - -## 4. 详细设计 - -### 4.1 guard.mjs 模式感知扩展 - -现有转换矩阵 `TRANSITION_CHECKS` 不变。新增 `applyWorkflowMode(checks, workflow)` 函数: - -``` -输入: checks = [{dimension: 'schema-valid', ...}], workflow = 'hotfix' -逻辑: - if workflow === 'hotfix': - 移除 'schema-valid' 维度(specifying→bridging 转换) - if workflow === 'tweak': - 移除 'schema-valid' 和 'contract-fresh' 维度 -输出: 过滤后的 checks 数组 -``` - -guard.mjs 新增 `--workflow ` 可选参数(默认 `full`)。参数解析后调用 `applyWorkflowMode()`。 - -新增转换 `exploring → bridging`(hotfix 跳过 specifying)和 `exploring → approved`(tweak 跳过 specifying + bridging)到 `TRANSITION_CHECKS` 矩阵。 - -### 4.2 cmd-inject.mjs 结构 - -``` -export async function run(args) - ├── parseArgs: [--json] - ├── readState(changeDir) ← 复用 state-loader.mjs - ├── 选择模板: PHASE_TEMPLATES[state] - ├── 替换占位符: {{change_name}}, {{state}}, {{workflow}} - ├── 写入 rules/phase-guard.md - ├── 复制到 .claude/always/phase-guard.md(创建目录如不存在) - └── 输出成功摘要 -``` - -`PHASE_TEMPLATES` 对象:7 个阶段各一个模板。模板包含: -- 变更名 + 当前阶段 + 工作流模式 -- 允许操作列表(✅ 前缀) -- 禁止操作列表(⛔ 前缀) -- 决策点提示(🔔 前缀,引用 DP-N 编号) - -### 4.3 cmd-state.mjs 新增 set 子命令 - -``` -ssf state set -``` - -支持的 field: `workflow`, `execution_mode`, `test_result`。其他字段通过 `transition` 或 `init` 设置,不允许直接 set。 - -白名单机制:只有 `SETTABLE_FIELDS = ['workflow', 'execution_mode', 'test_result']` 中的字段允许 set。 - -### 4.4 决策点审计字段 - -state-loader.mjs 的 `BUILTIN_DEFAULTS` 新增 14 个字段(7 个 dp_N_result + 7 个 dp_N_timestamp),初始值均为 `null`。 - -`writeState()` 的输出模板新增 `# === Decision points ===` 区块。 - -### 4.5 模式检测流程(workflow-orchestrator) - -``` -1. 读取 .spec-superflow.yaml 的 workflow 字段 -2. 如果 workflow 未设置或为 full: - → 正常路由 -3. 如果 workflow 为 hotfix: - → 验证: 文件数 ≤ 2? 无新模块? 无 schema 变更? - → 全部通过: 保持 hotfix,路由使用热修复快速路径 - → 任一失败: 升级为 full,输出升级原因 -4. 如果 workflow 为 tweak: - → 验证: 文件数 ≤ 4? 单模块? 纯配置/文档? - → 全部通过: 保持 tweak,路由使用调整快速路径 - → 任一失败: 升级为 full,输出升级原因 -``` - ---- - -## 5. 数据流 - -### 5.1 Full 模式(现有流程,无变化) - -``` -用户请求 → workflow-orchestrator - → guard.mjs check exploring specifying --workflow full - → spec-explorer → spec-forger - → guard.mjs check specifying bridging --workflow full - → bridge-contract → [DP-3 契约批准] - → guard.mjs check approved executing --workflow full - → execution-governor → [DP-4 执行模式选择] - → code-reviewer → closure-archivist → [DP-7 归档确认] - → spec-syncer -``` - -### 5.2 Hotfix 模式 - -``` -用户请求 "hotfix: fix X" → workflow-orchestrator - → 设置 workflow=hotfix - → guard.mjs check exploring bridging --workflow hotfix - → bridge-contract(最小契约) - → [DP-3 契约批准] - → guard.mjs check approved executing --workflow hotfix - → execution-governor(inline 模式) - → closure-archivist(轻量闭合) -``` - -### 5.3 Tweak 模式 - -``` -用户请求 "tweak: update config X" → workflow-orchestrator - → 设置 workflow=tweak - → guard.mjs check exploring approved --workflow tweak - → execution-governor(直接编辑模式) - → closure-archivist(轻量闭合:文件存在 + 语法检查) -``` - ---- - -## 6. 风险与缓解 - -| 风险 | 缓解 | -|------|------| -| 模式检测误判:用户说"hotfix"但实际需要完整规划 | 升级条件(≥3 文件 / 新模块 / schema 变更)兜底;orchestrator 在升级时输出明确原因 | -| phase-guard.md 过期:状态转换后忘记运行 `ssf inject` | orchestrator 在每次 `ssf state transition` 后自动提示运行;phase-guard.md 内嵌时间戳 | -| `.claude/always/` 目录不存在或权限不足 | `ssf inject` 自动创建目录(`mkdir -p`);失败时输出明确错误信息 | -| 决策点审计字段膨胀:14 个新字段使状态文件变长 | 字段按 `dp_N_*` 分组在独立区块,与核心状态分离;状态文件仍是纯文本,不影响可读性 | -| hotfix/tweak 模式下跳过 schema-valid 导致工件质量下降 | hotfix 仍需 artifacts-exist(proposal.md 必须存在);tweak 仍需文件完整性检查 | -| guard.mjs `--workflow` 参数被错误传入 | 白名单校验:仅接受 `full`/`hotfix`/`tweak`,其他值报错退出 | - ---- - -## 7. 文件清单 - -### 7.1 新增文件 - -| 文件 | 用途 | 估计行数 | -|------|------|---------| -| `scripts/lib/cmd-inject.mjs` | `ssf inject` 子命令:读状态 → 生成 phase-guard.md → 安装 | ~100 | -| `docs/decision-points.md` | 7 个标准决策点的集中定义 | ~120 | - -### 7.2 修改文件 - -| 文件 | 改动 | 影响行数 | -|------|------|---------| -| `scripts/guard/guard.mjs` | 新增 `--workflow` 参数 + `applyWorkflowMode()` + 2 个新转换 | ~30 | -| `scripts/lib/state-loader.mjs` | BUILTIN_DEFAULTS 新增 14 个决策点字段 + writeState 模板更新 | ~20 | -| `scripts/lib/cmd-state.mjs` | 新增 `set` 子命令 + SETTABLE_FIELDS 白名单 | ~40 | -| `scripts/spec-superflow.mjs` | 新增 `inject` 路由 | +5 | -| `skills/workflow-orchestrator/SKILL.md` | 新增模式检测逻辑 + 快速路径路由规则 + 决策点引用 | ~50 | -| `skills/bridge-contract/SKILL.md` | 新增 hotfix 最小契约模式 + DP-3 引用 | ~15 | -| `skills/execution-governor/SKILL.md` | 新增 tweak 直接编辑模式 + DP-4/DP-5 引用 | ~15 | -| `skills/closure-archivist/SKILL.md` | 新增 tweak 轻量闭合 + DP-6/DP-7 引用 | ~15 | -| `package.json` | 版本号 → 0.6.0 | 1 | -| `CHANGELOG.md` | v0.6.0 条目 | — | -| `README.md` | 更新架构图 + CLI 命令表 + 快速路径说明 | — | - -### 7.3 不变的东西 - -- 9 个 skill 的核心逻辑不变(仅增加模式分支和决策点引用) -- `src/validation/validator.ts` 不变 -- 现有 `ssf list/validate/doctor/version/sync/config/state` 命令不变 -- 零外部依赖约束不变 -- full 模式的完整流程不变 - ---- - -## 8. 实现顺序 - -### Batch 1: 决策点协议(预计 0.5 天) - -``` -docs/decision-points.md → state-loader.mjs 决策点字段 → cmd-state.mjs set 子命令 -``` -产物:决策点文档可用,状态文件支持审计字段,`ssf state set` 可用 - -### Batch 2: 快速路径基础设施(预计 1 天) - -``` -guard.mjs --workflow 参数 → applyWorkflowMode() → 新转换矩阵条目 → 测试 -``` -产物:guard.mjs 支持模式感知,hotfix/tweak 转换可用 - -### Batch 3: 阶段防漂移注入(预计 0.5 天) - -``` -cmd-inject.mjs → PHASE_TEMPLATES → .claude/always/ 安装 → ssf 入口路由 -``` -产物:`ssf inject` 命令端到端可用 - -### Batch 4: Skill 文件更新(预计 0.5 天) - -``` -workflow-orchestrator → bridge-contract → execution-governor → closure-archivist -``` -产物:4 个 skill 支持快速路径 + 决策点引用 - -### Batch 5: 集成 + 发布(预计 0.5 天) - -``` -版本号 → CHANGELOG → README → doctor 检查 → 发布 -``` -产物:v0.6.0 可发布 - ---- - -## 9. 展望 v0.7.0 - -| v0.7.0 特性 | 依赖 v0.6.0 的什么 | -|------------|-------------------| -| 自动模式检测 | 模式检测逻辑 + 升级条件(从显式声明改为自动推断) | -| 多平台 phase-guard 注入 | `cmd-inject.mjs` 扩展:Cursor rules / Copilot instructions / Gemini GEMINI.md | -| 决策点审计报告 | 状态文件中的 dp_N_* 字段 → 生成审计摘要 | diff --git a/changes/v0.6.0-fast-and-aware/execution-contract.md b/changes/v0.6.0-fast-and-aware/execution-contract.md deleted file mode 100644 index 6b81a91..0000000 --- a/changes/v0.6.0-fast-and-aware/execution-contract.md +++ /dev/null @@ -1,186 +0,0 @@ -# Execution Contract: v0.6.0 Fast & Aware - -## Intent Lock - -- **Change name**: v0.6.0-fast-and-aware -- **Problem being solved**: v0.5.0 的完整 8 状态流程对小型变更(hotfix/tweak)开销过大;Agent 在长会话中丢失阶段上下文;决策点散落各处无统一清单 -- **In scope**: - - 三种 workflow 模式(full / hotfix / tweak)的检测条件和跳过规则 - - guard.mjs 模式感知转换矩阵(`--workflow` 参数) - - `ssf inject` CLI 子命令 + phase-guard.md 生成 + `.claude/always/` 安装 - - `docs/decision-points.md`(7 个标准决策点) - - `ssf state set` 子命令 + 14 个决策点审计字段 - - 4 个 skill 文件更新(workflow-orchestrator, bridge-contract, execution-governor, closure-archivist) - - 版本号 → 0.6.0 + CHANGELOG + README -- **Out of scope**: 日文 tokenizer, 多平台适配器, skill-creator 工具包, 新增 skill, 修改 validator.ts, CI/CD 变更 - -## Approved Behavior - -### Fast-Path (6 requirements) - -| Requirement | Summary | Test Obligation | -|-------------|---------|-----------------| -| Hotfix mode detection | guard.mjs 跳过 schema-valid;允许 exploring→bridging | 验证 hotfix 模式下 schema-valid 被标记 skipped | -| Tweak mode detection | guard.mjs 跳过 schema-valid + contract-fresh | 验证 tweak 模式下 contract-fresh 被标记 skipped | -| Hotfix upgrade | ≥3 文件 / 新模块 / schema 变更 → 升级为 full | 验证 orchestrator 输出升级原因 + 设置 workflow=full | -| Tweak upgrade | ≥5 文件 / 跨模块 → 升级为 full | 验证 orchestrator 输出升级原因 + 设置 workflow=full | -| Hotfix minimal contract | bridge-contract 仅生成 Intent Lock + Task List + Approval Gate | 验证最小契约不含 Scope Fence / Build Rules | -| Tweak lightweight closure | 仅验证文件存在 + 语法检查,跳过三维验证 | 验证 closure 跳过完整验证但仍检查文件完整性 | - -### Phase-Drift Prevention (4 requirements) - -| Requirement | Summary | Test Obligation | -|-------------|---------|-----------------| -| ssf inject command | 读状态 → 生成 phase-guard.md → 安装到 .claude/always/ | 验证端到端:命令执行 + 文件生成 + 安装成功 | -| Content structure | 变更名 + 阶段 + 模式 + 允许/禁止操作 + 决策点提示 | 验证 specifying 和 executing 阶段的模板内容正确 | -| Regeneration | 覆盖已有文件;orchestrator 状态转换后提示 inject | 验证二次 inject 覆盖旧内容 | -| Graceful fallback | 状态文件缺失时使用默认值(exploring + full) | 验证无状态文件时仍能生成 + 输出警告 | - -### Decision-Point Protocol (5 requirements) - -| Requirement | Summary | Test Obligation | -|-------------|---------|-----------------| -| 7 standard decision points | docs/decision-points.md 定义 DP-1 到 DP-7 | 验证文件存在 + 包含 7 个决策点 + 每个有 6 个字段 | -| Orchestrator references | 路由输出包含 DP-N 编号 | 验证路由到 bridge-contract 时包含 DP-3 | -| Skill references | 4 个 skill 引用对应 DP 编号 | 验证 bridge-contract 包含 DP-3,debugger 包含 DP-5 | -| Escalation | 决策点未确认时暂停,不得自动跳过 | 验证 skill 在未收到 approve/reject/revise 时重新提示 | -| Audit trail | dp_N_result + dp_N_timestamp 记录到状态文件 | 验证 DP-3 approve 后状态文件含 dp_3_result: approved | - -### Coverage Check - -- 15 requirements total → 15 mapped to test obligations ✅ -- 15 requirements → all represented in execution batches ✅ -- 0 unmapped requirements - -## Design Constraints - -### Architecture Constraints - -1. **模式检测由 orchestrator 执行** — 不新增检测脚本;orchestrator 读取 workflow 字段 + 验证阈值 -2. **guard.mjs 通过 --workflow 参数感知模式** — guard.mjs 保持无状态,不读 .spec-superflow.yaml -3. **phase-guard.md 通过显式 ssf inject 生成** — 不通过 hook 自动生成;用户控制注入时机 -4. **决策点审计在状态文件中** — 不新增独立日志文件;dp_N_* 字段在独立区块 -5. **PHASE_TEMPLATES 对象** — 不用通用模板引擎;7 个阶段各一个模板字符串 - -### Interface Constraints - -- `guard.mjs` 新增 `--workflow ` 可选参数(默认 `full`),白名单校验 `full|hotfix|tweak` -- `ssf state set` 白名单:仅 `workflow`, `execution_mode`, `test_result`, `dp_N_result`, `dp_N_timestamp` 可 set -- `ssf inject` 接受 `` 必需参数 + `--json` 可选参数 - -### Dependency Constraints - -- 零外部 npm 依赖(仅 TypeScript devDependency) -- 不改动 `src/validation/validator.ts` -- 复用 v0.5.0 基础设施(guard.mjs, state-loader.mjs, hash.mjs, cmd-state.mjs) -- 不破坏现有 9 个 skill 的核心逻辑(仅增加模式分支和决策点引用) - -### Data Constraints - -- `.spec-superflow.yaml` 新增 14 个字段(dp_1_result ~ dp_7_timestamp),初始值 `null` -- `TRANSITION_CHECKS` 新增 2 个转换:`exploring:bridging`(hotfix)、`exploring:approved`(tweak) -- `PHASE_TEMPLATES` 包含 7 个阶段模板,使用 `{{change_name}}`/`{{state}}`/`{{workflow}}` 占位符 - -## Task Batches - -### Batch 1: 决策点协议基础设施 - -- **Objective**: 创建决策点文档 + 状态文件审计字段 + set 子命令 -- **Inputs**: (none) -- **Outputs**: `docs/decision-points.md`, state-loader.mjs 14 个新字段, `ssf state set` 命令 -- **Done when**: `grep -c "^## DP-" docs/decision-points.md` = 7; `ssf state set` 白名单工作; 状态文件可读写 dp_N_* 字段 -- **Tasks**: 1.1–1.5 - -### Batch 2: 快速路径 Guard 基础设施 - -- **Objective**: guard.mjs 支持模式感知 + 新转换条目 -- **Inputs**: Batch 1 的 SETTABLE_FIELDS 白名单 -- **Outputs**: `applyWorkflowMode()` 函数, `--workflow` 参数, 2 个新转换 -- **Done when**: hotfix 模式跳过 schema-valid; tweak 模式跳过 schema-valid + contract-fresh; 无效 workflow 报错退出 -- **Tasks**: 2.1–2.5 -- **Depends on**: Batch 1 - -### Batch 3: 阶段防漂移注入 - -- **Objective**: `ssf inject` 命令端到端可用 -- **Inputs**: Batch 1 的 state-loader.mjs(readState) -- **Outputs**: `cmd-inject.mjs`, `PHASE_TEMPLATES`, `.claude/always/` 安装逻辑 -- **Done when**: `ssf inject` 生成 phase-guard.md + 安装到 .claude/always/; 7 个阶段模板内容正确; 状态文件缺失时优雅降级 -- **Tasks**: 3.1–3.6 -- **Depends on**: Batch 1 - -### Batch 4: Skill 文件更新 - -- **Objective**: 4 个 skill 支持快速路径 + 决策点引用 -- **Inputs**: Batch 2 的 guard.mjs 模式感知, Batch 3 的 inject 命令 -- **Outputs**: 更新的 workflow-orchestrator, bridge-contract, execution-governor, closure-archivist SKILL.md -- **Done when**: orchestrator 包含模式检测 + 快速路径路由 + DP 引用; bridge-contract 包含 hotfix 最小契约; execution-governor 包含 tweak 直接编辑; closure-archivist 包含轻量闭合 -- **Tasks**: 4.1–4.7 -- **Depends on**: Batch 2, Batch 3 - -### Batch 5: 集成 + 发布 - -- **Objective**: 版本号 + CHANGELOG + README + doctor 验证 -- **Inputs**: Batch 1–4 全部完成 -- **Outputs**: 0.6.0 版本,5 个 manifest 同步,CHANGELOG + README 更新 -- **Done when**: `ssf doctor` 全部通过; `ssf version 0.6.0 --dry-run` 显示 5/5 manifest 同步 -- **Tasks**: 5.1–5.5 -- **Depends on**: Batch 1, 2, 3, 4 - -### Parallelism - -``` -Batch 1 (决策点协议) - ├→ Batch 2 (Guard 模式感知) ← 可与 Batch 3 并行 - └→ Batch 3 (Inject 命令) ← 可与 Batch 2 并行 - └→ Batch 4 (Skill 更新) ← 依赖 Batch 2 + 3 - └→ Batch 5 (集成) ← 依赖全部 -``` - -## Test Obligations - -### Must Start With Failing Tests - -- `applyWorkflowMode()` 的维度过滤逻辑(hotfix 跳过 schema-valid, tweak 跳过 schema-valid + contract-fresh) -- `cmd-state.mjs` 的 `set` 子命令白名单(允许 workflow,拒绝 state) -- `cmd-inject.mjs` 的 PHASE_TEMPLATES 模板生成(7 个阶段内容正确) -- `cmd-inject.mjs` 的 `.claude/always/` 安装 + 目录自动创建 -- `cmd-inject.mjs` 的状态文件缺失优雅降级 - -### Required Edge Cases - -- guard.mjs `--workflow` 传入无效值(非 full/hotfix/tweak)→ exit 2 -- `ssf inject` 目标 `.claude/always/` 目录不存在 → 自动创建 -- `ssf inject` 二次执行 → 覆盖已有 phase-guard.md -- hotfix 模式但变更涉及 3+ 文件 → 升级为 full + 输出原因 -- tweak 模式但变更跨模块 → 升级为 full + 输出原因 -- 状态文件缺失时 `ssf inject` → 默认值 + 警告 - -### Regression-Sensitive Areas - -- guard.mjs 现有转换矩阵(full 模式行为不变) -- state-loader.mjs 现有字段(新增字段不影响已有字段的读写) -- cmd-state.mjs 现有子命令(init/check/transition/get/rebuild 不变) -- spec-superflow.mjs 现有路由(list/validate/doctor/version/sync/config/state 不变) - -## Execution Mode - -- **Mode**: `SDD` (Subagent-Driven Development) -- **Selection rationale**: 5 个 batch 中 Batch 2 和 Batch 3 可并行执行(都仅依赖 Batch 1),SDD 可分派独立子代理加速。Batch 1 以文档/配置为主,Batch 4 纯 SKILL.md 编辑,Batch 5 版本同步——均适合子代理独立执行。 - -## Review Gates - -- **Mandatory review points**: - - Batch 1 → Batch 2/3 分叉前:确认决策点文档 + set 子命令正确 - - Batch 2 + 3 → Batch 4 前:确认 guard.mjs 模式感知 + inject 命令端到端可用 - - Batch 4 → Batch 5 前:确认 4 个 skill 文件内容一致性 -- **Blocker categories**: - - guard.mjs full 模式回归(现有转换行为变化) - - state-loader.mjs 字段冲突(新字段覆盖已有字段) - - phase-guard.md 模板内容错误(允许/禁止操作与实际阶段不匹配) - -## Escalation Rules - -- **Return to `specifying` when**: 新增 workflow 模式(如 v0.7.0 的 auto-detect);phase-guard.md 注入机制变更(如支持 Cursor rules) -- **Return to `bridging` when**: guard.mjs 转换矩阵需要新增维度;决策点数量变化(新增或删除 DP) -- **Do not continue implementation if**: guard.mjs full 模式回归测试失败;state-loader.mjs 无法正确读写新增的 14 个字段;`ssf inject` 在任一阶段生成错误内容 diff --git a/changes/v0.6.0-fast-and-aware/prompt.md b/changes/v0.6.0-fast-and-aware/prompt.md deleted file mode 100644 index 7028805..0000000 --- a/changes/v0.6.0-fast-and-aware/prompt.md +++ /dev/null @@ -1,58 +0,0 @@ -# v0.6.0 启动提示语 - -复制以下内容到新会话: - ---- - -用 workflow-orchestrator 开始,我要实现 spec-superflow v0.6.0。 - -## 背景 - -v0.5.0 刚发布,增加了可靠性层(守护脚本 + 状态文件 + SHA256 哈希)。v0.6.0 在可靠地基上增加三个扩展功能。 - -仓库路径:`/Users/magebte/Documents/magebyte/open-source-plugins/spec-superflow` - -## v0.6.0 三个功能 - -### 1. 快速路径 hotfix / tweak - -workflow-orchestrator 新增两种轻量模式,跳过完整规划流程。 - -**hotfix 模式:** -- 触发:用户明确说"hotfix"或"quick fix",且 ≤3 文件、无新模块、无 schema 变更 -- 跳过:spec-explorer、spec-forger -- 走:最小 bridge-contract(只提取 intent + task list)→ inline execution → 轻量 closure -- 依赖 v0.5.0 的 `.spec-superflow.yaml` 中 `workflow` 字段区分模式 - -**tweak 模式:** -- 触发:用户明确说"tweak"或"small change",且纯配置/文档/提示词修改 -- 跳过:spec-explorer、spec-forger、完整 bridge-contract -- 走:直接编辑 → 轻量验证 - -**升级条件:** hotfix 涉及 3+ 文件或架构变更 → 升级为 full;tweak 涉及 5+ 文件或跨模块 → 升级为 full - -### 2. 阶段防漂移 Rule - -新增 `rules/phase-guard.md`,每轮注入提醒 Agent 当前阶段。 - -- 新增 `scripts/lib/cmd-inject.mjs`:`ssf inject ` 命令,读 `.spec-superflow.yaml` 生成 `phase-guard.md` -- 内容:当前变更名、当前阶段、允许操作、禁止操作 -- 安装到 Claude Code 的 `.claude/always/` 目录实现每轮注入 -- 配合 v0.5.0 的 `guard.mjs` 形成软硬双重防线 - -### 3. 决策点协议 - -新增 `docs/decision-points.md`,集中定义 7 个标准决策点,workflow-orchestrator 和各 skill 统一引用。 - -7 个决策点:需求确认 → 工件审查 → 契约批准(硬门禁)→ 执行模式选择 → 调试升级 → 验证失败 → 归档确认 - -## 设计文档 - -先读 `changes/v0.5.0-guard-and-state/design.md` 第 10 章了解 v0.6.0 概要。然后写 v0.6.0 设计文档到 `changes/v0.6.0-fast-and-aware/`。 - -## 关键约束 - -- 零外部依赖 -- 复用 v0.5.0 的 guard.mjs、state-loader.mjs、hash.mjs -- 不改动 `src/validation/validator.ts` -- 不破坏现有 9 个 skill 的核心逻辑 \ No newline at end of file diff --git a/changes/v0.6.0-fast-and-aware/proposal.md b/changes/v0.6.0-fast-and-aware/proposal.md deleted file mode 100644 index 05d6944..0000000 --- a/changes/v0.6.0-fast-and-aware/proposal.md +++ /dev/null @@ -1,70 +0,0 @@ -# Change Proposal: v0.6.0 Fast & Aware - -## Why - -v0.5.0 建立了可靠性层(guard.mjs 守护脚本 + .spec-superflow.yaml 状态文件 + SHA256 哈希),所有变更都必须走完整的 8 状态流程(exploring → specifying → bridging → approved → executing → closing)。 - -这在大型变更中保证了纪律性,但对小型变更造成了不必要的开销: - -1. **修改 1 个配置文件的 tweak** 仍需走完整规划流程(spec-explorer → spec-forger → bridge-contract),Agent 生成 5 份工件 + 执行契约,耗时远超修改本身 -2. **修复 1 个 bug 的 hotfix** 需要完整的 specs/ 目录和 design.md,对紧急修复来说是不必要的仪式 -3. **Agent 在长会话中丢失阶段上下文**——虽然有 guard.mjs 硬门禁,但 Agent 可能在压缩后忘记当前处于哪个阶段,导致"在 executing 阶段去做 specifying 的事" -4. **决策点散落各处**——契约批准在 bridge-contract、调试升级在 systematic-debugger、验证确认在 closure-archivist——没有统一的决策点清单,新 Agent 难以快速理解"何时需要停下来问用户" - -v0.6.0 在 v0.5.0 的可靠地基上增加三个扩展:快速路径让简单变更走捷径,阶段防漂移让 Agent 始终知道自己在哪,决策点协议让所有"需要用户确认"的时刻有统一标准。 - -## What Changes - -- workflow-orchestrator 新增 hotfix / tweak 两种轻量模式 -- `.spec-superflow.yaml` 的 `workflow` 字段驱动模式切换(full | hotfix | tweak) -- guard.mjs 转换矩阵根据 workflow 模式条件跳过特定检查维度 -- 新增 `ssf inject ` 子命令,生成 phase-guard.md 规则文件 -- 新增 `rules/phase-guard.md`,安装到 `.claude/always/` 实现每轮注入 -- 新增 `docs/decision-points.md`,定义 7 个标准决策点及其协议 -- 4 个 skill 文件更新(workflow-orchestrator、bridge-contract、execution-governor、closure-archivist) -- cmd-state.mjs 新增 `set` 子命令,支持设置 workflow 字段 -- 版本号 → 0.6.0 + CHANGELOG + README 更新 - -## Capabilities - -### New Capabilities - -- `fast-path` — hotfix 和 tweak 轻量工作流模式,跳过完整规划 -- `phase-drift-prevention` — 阶段防漂移规则注入,软硬双重防线 -- `decision-point-protocol` — 7 个标准决策点的集中定义和引用协议 - -### Modified Capabilities - -- workflow-orchestrator — 新增模式检测和快速路径路由逻辑 -- bridge-contract — 新增最小契约模式(hotfix 仅提取 intent + task list) -- execution-governor — tweak 模式下支持直接编辑模式 -- closure-archivist — 新增轻量闭合验证路径 - -## Scope - -### In Scope - -- 三种 workflow 模式(full / hotfix / tweak)的检测条件和跳过规则 -- hotfix 升级条件:≥3 文件或架构变更 → 升级为 full -- tweak 升级条件:≥5 文件或跨模块 → 升级为 full -- `ssf inject` CLI 子命令 + phase-guard.md 生成逻辑 -- 7 个决策点定义文档(需求确认、工件审查、契约批准、执行模式选择、调试升级、验证失败、归档确认) -- guard.mjs 模式感知转换矩阵 -- cmd-state.mjs `set` 子命令 -- 4 个 skill 文件更新 -- 版本号同步到 0.6.0 - -### Out of Scope - -- 日文 tokenizer(v0.7.0) -- 多平台适配器扩展(v0.7.0) -- skill-creator 工具包(v0.7.0) -- 新增 skill(保持 9 个 skill 不变) -- 修改 src/validation/validator.ts -- CI/CD 流程变更 - -## Impact - -- **Affected code areas**: `scripts/guard/guard.mjs`(模式感知转换矩阵), `scripts/lib/state-loader.mjs`(workflow 字段支持), `scripts/lib/cmd-state.mjs`(新增 set 子命令), `scripts/spec-superflow.mjs`(新增 inject 路由) -- **Affected APIs or interfaces**: 新增 `ssf inject ` CLI 子命令, `ssf state set workflow ` 子命令, guard.mjs 接受 workflow 参数 -- **Dependencies or systems touched**: Claude Code `.claude/always/` 目录(规则注入目标), 4 个 skill 文件(workflow-orchestrator, bridge-contract, execution-governor, closure-archivist) diff --git a/changes/v0.6.0-fast-and-aware/specs/decision-point-protocol/spec.md b/changes/v0.6.0-fast-and-aware/specs/decision-point-protocol/spec.md deleted file mode 100644 index 7d47662..0000000 --- a/changes/v0.6.0-fast-and-aware/specs/decision-point-protocol/spec.md +++ /dev/null @@ -1,84 +0,0 @@ -## ADDED Requirements - -### Requirement: Seven standard decision points - -`docs/decision-points.md` SHALL 定义 7 个标准决策点,每个决策点包含:编号、名称、触发条件、所需输入、预期输出、关联 skill。 - -7 个决策点为: -1. DP-1 需求确认 — spec-explorer 完成前,用户确认 scope 和 capabilities -2. DP-2 工件审查 — spec-forger 完成后,用户审查 proposal/specs/design/tasks -3. DP-3 契约批准 — bridge-contract 完成后,用户明确批准 execution-contract.md(硬门禁) -4. DP-4 执行模式选择 — execution-governor 启动前,用户选择 TDD 或 SDD 模式 -5. DP-5 调试升级 — systematic-debugger 3+ 修复失败后,用户决定继续或放弃 -6. DP-6 验证失败 — closure-archivist 验证未通过时,用户决定修复或放弃 -7. DP-7 归档确认 — closure-archivist 完成前,用户确认归档和 delta spec 合并 - -#### Scenario: decision-points.md contains all 7 decision points - -- **WHEN** 读取 `docs/decision-points.md` -- **THEN** 文件 SHALL 包含 DP-1 到 DP-7 共 7 个决策点的完整定义 - -#### Scenario: each decision point has required fields - -- **WHEN** 读取任一决策点定义 -- **THEN** 该决策点 SHALL 包含编号、名称、触发条件、所需输入、预期输出、关联 skill 六个字段 - -### Requirement: Decision point reference in workflow-orchestrator - -workflow-orchestrator SKILL.md SHALL 在路由规则中引用对应的决策点编号。当路由到需要用户确认的 skill 时,输出 SHALL 包含决策点编号和简要说明。 - -#### Scenario: orchestrator references DP-3 before bridge-contract - -- **WHEN** workflow-orchestrator 路由到 bridge-contract -- **THEN** 输出 SHALL 包含 `DP-3: 契约批准 — 用户需明确批准 execution-contract.md` - -#### Scenario: orchestrator references DP-4 before execution-governor - -- **WHEN** workflow-orchestrator 路由到 execution-governor -- **THEN** 输出 SHALL 包含 `DP-4: 执行模式选择 — 用户选择 TDD 或 SDD` - -### Requirement: Decision point reference in skills - -以下 skill SHALL 在对应决策点触发时引用决策点编号: -- bridge-contract: DP-3(契约批准) -- execution-governor: DP-4(执行模式选择)、DP-5(调试升级) -- systematic-debugger: DP-5(调试升级) -- closure-archivist: DP-6(验证失败)、DP-7(归档确认) - -#### Scenario: bridge-contract references DP-3 - -- **WHEN** bridge-contract 生成 execution-contract.md 后等待用户批准 -- **THEN** 输出 SHALL 包含 `DP-3` 决策点编号 - -#### Scenario: systematic-debugger references DP-5 - -- **WHEN** systematic-debugger 连续 3+ 次修复失败,需要升级决策 -- **THEN** 输出 SHALL 包含 `DP-5: 调试升级` 决策点编号 - -### Requirement: Decision point escalation - -当 skill 到达决策点且用户未给出明确选择时,skill SHALL 暂停并等待用户确认,不得自动跳过。这是 v0.5.0 硬门禁的延伸——guard.mjs 在代码层面阻止跳过,决策点协议在交互层面确保用户知情。 - -#### Scenario: skill pauses at decision point - -- **WHEN** skill 到达决策点(如 bridge-contract 到达 DP-3) -- **THEN** skill SHALL 输出决策点信息并暂停,等待用户明确输入 `approve` / `reject` / `revise` - -#### Scenario: skill does not auto-skip decision point - -- **WHEN** 用户在决策点未给出明确选择(如输入了无关内容) -- **THEN** skill SHALL 重新提示决策点信息,不得自动跳过或默认选择 - -### Requirement: Decision point audit trail - -每个决策点的结果 SHALL 记录到 `.spec-superflow.yaml`。记录格式:`dp__result: approved|rejected|revised`,`dp__timestamp: `。 - -#### Scenario: DP-3 result recorded to state file - -- **WHEN** 用户在 DP-3(契约批准)选择 `approve` -- **THEN** `.spec-superflow.yaml` SHALL 包含 `dp_3_result: approved` 和 `dp_3_timestamp: ` - -#### Scenario: DP-4 result recorded to state file - -- **WHEN** 用户在 DP-4(执行模式选择)选择 `sdd` -- **THEN** `.spec-superflow.yaml` SHALL 包含 `dp_4_result: sdd` 和 `dp_4_timestamp: ` diff --git a/changes/v0.6.0-fast-and-aware/specs/fast-path/spec.md b/changes/v0.6.0-fast-and-aware/specs/fast-path/spec.md deleted file mode 100644 index af1842c..0000000 --- a/changes/v0.6.0-fast-and-aware/specs/fast-path/spec.md +++ /dev/null @@ -1,103 +0,0 @@ -## ADDED Requirements - -### Requirement: Workflow mode detection — hotfix - -`.spec-superflow.yaml` 的 `workflow` 字段 SHALL 支持 `hotfix` 值。当 workflow 为 `hotfix` 时,guard.mjs 转换矩阵 SHALL 跳过以下检查维度: -- `exploring → specifying`: 跳过(允许直接进入 bridging) -- `specifying → bridging`: 跳过 `schema-valid` 检查(仅保留 `artifacts-exist`) - -#### Scenario: hotfix mode skips specifying validation - -- **WHEN** guard.mjs check 被调用,workflow 为 `hotfix`,转换为 `specifying → bridging` -- **THEN** `schema-valid` 检查维度 SHALL 被跳过,仅执行 `artifacts-exist` 检查 - -#### Scenario: hotfix mode allows direct bridging from exploring - -- **WHEN** guard.mjs check 被调用,workflow 为 `hotfix`,转换为 `exploring → bridging` -- **THEN** 转换 SHALL 被允许,仅需 `artifacts-exist` 检查通过 - -### Requirement: Workflow mode detection — tweak - -`.spec-superflow.yaml` 的 `workflow` 字段 SHALL 支持 `tweak` 值。当 workflow 为 `tweak` 时,guard.mjs 转换矩阵 SHALL 跳过以下检查维度: -- `exploring → specifying`: 跳过 -- `specifying → bridging`: 跳过 -- `bridging → approved`: 跳过 `contract-fresh` 检查 -- `approved → executing`: 跳过 `contract-fresh` 检查 - -#### Scenario: tweak mode skips bridging and contract checks - -- **WHEN** guard.mjs check 被调用,workflow 为 `tweak`,转换为 `bridging → approved` -- **THEN** `contract-fresh` 检查维度 SHALL 被跳过 - -#### Scenario: tweak mode allows direct execution without contract - -- **WHEN** guard.mjs check 被调用,workflow 为 `tweak`,转换为 `approved → executing` -- **THEN** `contract-fresh` 检查维度 SHALL 被跳过,仅需 `artifacts-exist` 通过 - -### Requirement: Hotfix upgrade condition - -workflow-orchestrator SHALL 在以下任一条件成立时,将 hotfix 升级为 full: -- 变更涉及 ≥3 个文件 -- 变更涉及新模块创建 -- 变更涉及 schema 或接口变更 - -升级 SHALL 记录到 `.spec-superflow.yaml` 的 `workflow` 字段(设为 `full`),并输出升级原因。 - -#### Scenario: hotfix upgraded to full when touching 3+ files - -- **WHEN** workflow 为 `hotfix`,用户描述的变更涉及 3 个或以上文件 -- **THEN** workflow-orchestrator SHALL 将 workflow 设为 `full` 并输出升级原因 - -#### Scenario: hotfix stays hotfix for single-file bug fix - -- **WHEN** workflow 为 `hotfix`,用户描述的变更仅涉及 1-2 个文件且无新模块 -- **THEN** workflow-orchestrator SHALL 保持 `hotfix` 模式 - -### Requirement: Tweak upgrade condition - -workflow-orchestrator SHALL 在以下任一条件成立时,将 tweak 升级为 full: -- 变更涉及 ≥5 个文件 -- 变更跨模块(修改多个 skill 或 engine 子系统) - -升级 SHALL 记录到 `.spec-superflow.yaml` 的 `workflow` 字段(设为 `full`),并输出升级原因。 - -#### Scenario: tweak upgraded to full when touching 5+ files - -- **WHEN** workflow 为 `tweak`,用户描述的变更涉及 5 个或以上文件 -- **THEN** workflow-orchestrator SHALL 将 workflow 设为 `full` 并输出升级原因 - -#### Scenario: tweak stays tweak for config-only change - -- **WHEN** workflow 为 `tweak`,用户描述的变更仅涉及配置文件修改 -- **THEN** workflow-orchestrator SHALL 保持 `tweak` 模式 - -### Requirement: Hotfix minimal bridge-contract - -bridge-contract SHALL 在 hotfix 模式下生成最小契约,仅包含: -- Intent Lock(变更意图的一句话描述) -- Task List(待完成任务的列表) -- Approval Gate(用户确认提示) - -最小契约 SHALL 不包含完整的 Scope Fence、Build Rules 或 Review Gates 部分。 - -#### Scenario: hotfix generates minimal contract - -- **WHEN** bridge-contract 在 hotfix 模式下被调用 -- **THEN** 生成的 `execution-contract.md` SHALL 仅包含 Intent Lock、Task List 和 Approval Gate 三个部分 - -### Requirement: Tweak lightweight closure - -closure-archivist SHALL 在 tweak 模式下执行轻量闭合验证: -- 验证变更文件已保存 -- 验证无语法错误(`node --check` 或等价检查) -- 跳过完整的三维验证(5-step three-dimensional verification) - -#### Scenario: tweak closure skips full verification - -- **WHEN** closure-archivist 在 tweak 模式下执行闭合 -- **THEN** SHALL 仅验证文件保存和语法正确性,跳过完整的三维验证 - -#### Scenario: tweak closure still verifies file integrity - -- **WHEN** closure-archivist 在 tweak 模式下执行闭合 -- **THEN** SHALL 验证所有变更文件存在且非空 diff --git a/changes/v0.6.0-fast-and-aware/specs/phase-drift-prevention/spec.md b/changes/v0.6.0-fast-and-aware/specs/phase-drift-prevention/spec.md deleted file mode 100644 index 214682e..0000000 --- a/changes/v0.6.0-fast-and-aware/specs/phase-drift-prevention/spec.md +++ /dev/null @@ -1,68 +0,0 @@ -## ADDED Requirements - -### Requirement: ssf inject command - -`scripts/spec-superflow.mjs` SHALL 支持 `inject ` 子命令。该命令 SHALL 读取 `/.spec-superflow.yaml` 的 `state` 和 `workflow` 字段,生成 `rules/phase-guard.md` 规则文件,并将其安装到 `.claude/always/` 目录。 - -#### Scenario: ssf inject generates phase-guard.md - -- **WHEN** 用户执行 `ssf inject changes/my-change` -- **THEN** 命令 SHALL 读取状态文件,生成 `rules/phase-guard.md`,内容包含当前变更名、当前阶段、允许操作和禁止操作 - -#### Scenario: ssf inject installs to .claude/always/ - -- **WHEN** `ssf inject` 成功生成 `rules/phase-guard.md` -- **THEN** 命令 SHALL 将文件复制/链接到 `.claude/always/phase-guard.md`,使其每轮注入到 Agent 上下文 - -#### Scenario: ssf inject reports success with state summary - -- **WHEN** `ssf inject` 完成 -- **THEN** 命令 SHALL 输出当前状态摘要(change_name, state, workflow)和安装路径 - -### Requirement: Phase-guard.md content structure - -`rules/phase-guard.md` SHALL 包含以下结构: -- 变更名(从 `change_name` 字段读取) -- 当前阶段(从 `state` 字段读取) -- 工作流模式(从 `workflow` 字段读取) -- 允许的操作列表(根据当前阶段动态生成) -- 禁止的操作列表(根据当前阶段动态生成) -- 决策点提示(如果当前阶段包含决策点) - -#### Scenario: phase-guard.md lists allowed operations for specifying - -- **WHEN** 当前阶段为 `specifying` -- **THEN** phase-guard.md SHALL 列出允许操作:创建/修改 proposal.md, specs/, design.md, tasks.md;禁止操作:修改 execution-contract.md, 执行实现代码 - -#### Scenario: phase-guard.md lists allowed operations for executing - -- **WHEN** 当前阶段为 `executing` -- **THEN** phase-guard.md SHALL 列出允许操作:按 execution-contract.md 执行任务, 运行测试, 提交代码;禁止操作:修改 proposal.md, specs/, design.md(需先回退到 specifying) - -#### Scenario: phase-guard.md includes decision point hint - -- **WHEN** 当前阶段包含决策点(如 bridging 包含"契约批准"决策点) -- **THEN** phase-guard.md SHALL 包含决策点提示,引用 docs/decision-points.md 中对应的决策点编号 - -### Requirement: Phase-guard.md regeneration behavior - -`ssf inject` SHALL 在每次执行时覆盖已有的 `rules/phase-guard.md`。workflow-orchestrator SHALL 在每次状态转换后提示用户运行 `ssf inject` 重新生成。 - -#### Scenario: inject overwrites existing phase-guard.md - -- **WHEN** `rules/phase-guard.md` 已存在,用户再次执行 `ssf inject` -- **THEN** 命令 SHALL 覆盖已有文件,内容更新为当前状态 - -#### Scenario: workflow-orchestrator prompts for re-injection - -- **WHEN** workflow-orchestrator 检测到状态转换(通过 `ssf state transition` 确认) -- **THEN** workflow-orchestrator SHALL 在路由输出中提示用户运行 `ssf inject` 更新阶段防漂移规则 - -### Requirement: Graceful fallback when state file missing - -当 `/.spec-superflow.yaml` 不存在时,`ssf inject` SHALL 生成默认的 phase-guard.md,状态为 `exploring`,workflow 为 `full`。 - -#### Scenario: inject works without state file - -- **WHEN** `/.spec-superflow.yaml` 不存在,用户执行 `ssf inject ` -- **THEN** 命令 SHALL 使用默认值(state=exploring, workflow=full)生成 phase-guard.md,并输出警告提示状态文件缺失 diff --git a/changes/v0.6.0-fast-and-aware/tasks.md b/changes/v0.6.0-fast-and-aware/tasks.md deleted file mode 100644 index 44039fe..0000000 --- a/changes/v0.6.0-fast-and-aware/tasks.md +++ /dev/null @@ -1,700 +0,0 @@ -# Implementation Tasks: v0.6.0 Fast & Aware - -## File Structure - -### Create -- `scripts/lib/cmd-inject.mjs` — `ssf inject` 子命令:读状态 → 生成 phase-guard.md → 安装到 `.claude/always/` -- `docs/decision-points.md` — 7 个标准决策点的集中定义文档 - -### Modify -- `scripts/guard/guard.mjs` — 新增 `--workflow` 参数 + `applyWorkflowMode()` 过滤 + 2 个新转换条目 -- `scripts/lib/state-loader.mjs` — BUILTIN_DEFAULTS 新增 14 个决策点审计字段 + writeState 模板更新 -- `scripts/lib/cmd-state.mjs` — 新增 `set` 子命令 + SETTABLE_FIELDS 白名单 -- `scripts/spec-superflow.mjs` — 新增 `inject` 路由 -- `skills/workflow-orchestrator/SKILL.md` — 新增模式检测 + 快速路径路由 + 决策点引用 -- `skills/bridge-contract/SKILL.md` — 新增 hotfix 最小契约模式 + DP-3 引用 -- `skills/execution-governor/SKILL.md` — 新增 tweak 直接编辑模式 + DP-4/DP-5 引用 -- `skills/closure-archivist/SKILL.md` — 新增 tweak 轻量闭合 + DP-6/DP-7 引用 -- `package.json` — 版本号 → 0.6.0 -- `CHANGELOG.md` — v0.6.0 条目 -- `README.md` — 更新架构图 + CLI 命令表 + 快速路径说明 - -## Interfaces - -### Batch 1 → Batch 2 -- **Produces**: `SETTABLE_FIELDS` 白名单 — consumed by guard.mjs to validate workflow values -- **Produces**: `dp_N_result` / `dp_N_timestamp` 字段 — consumed by cmd-inject.mjs for decision point hints - -### Batch 2 → Batch 4 -- **Produces**: `applyWorkflowMode(checks, workflow)` — consumed by workflow-orchestrator SKILL.md to document mode-aware routing - -### Batch 3 → Batch 4 -- **Produces**: `PHASE_TEMPLATES` 对象 — consumed by workflow-orchestrator to know when to prompt `ssf inject` - ---- - -## 1. Batch 1: 决策点协议基础设施 - -Depends on: (none) - -- [ ] **1.1 创建 docs/decision-points.md** - -**Files**: Create: `docs/decision-points.md` - -内容包含 7 个决策点定义,每个包含:编号、名称、触发条件、所需输入、预期输出、关联 skill。 - -```markdown -# Decision Points Protocol - -本文档集中定义 spec-superflow 工作流中的 7 个标准决策点。 -所有 skill 在对应决策点触发时 SHALL 引用本文档中的决策点编号。 - -## DP-1: 需求确认 - -- **触发条件**: spec-explorer 完成意图澄清,准备进入 spec-forger -- **所需输入**: 用户需求描述、scope 边界、capabilities 列表 -- **预期输出**: 用户确认 scope 和 capabilities,或要求进一步探索 -- **关联 skill**: spec-explorer -- **选择项**: `confirm` | `revise` | `abandon` - -## DP-2: 工件审查 -...(DP-2 到 DP-7 同理展开) -``` - -7 个决策点: -1. DP-1 需求确认(spec-explorer → spec-forger) -2. DP-2 工件审查(spec-forger 完成后) -3. DP-3 契约批准(bridge-contract → execution-governor,**硬门禁**) -4. DP-4 执行模式选择(execution-governor 启动前) -5. DP-5 调试升级(systematic-debugger 3+ 失败后) -6. DP-6 验证失败(closure-archivist 验证未通过时) -7. DP-7 归档确认(closure-archivist 完成前) - -**验证**: `wc -l docs/decision-points.md` 应 > 80 行 - -- [ ] **1.2 修改 state-loader.mjs:新增决策点审计字段** - -**Files**: Modify: `scripts/lib/state-loader.mjs` - -在 `BUILTIN_DEFAULTS` 对象中新增 14 个字段: - -```javascript -// 在 BUILTIN_DEFAULTS 末尾追加 -dp_1_result: null, -dp_1_timestamp: null, -dp_2_result: null, -dp_2_timestamp: null, -dp_3_result: null, -dp_3_timestamp: null, -dp_4_result: null, -dp_4_timestamp: null, -dp_5_result: null, -dp_5_timestamp: null, -dp_6_result: null, -dp_6_timestamp: null, -dp_7_result: null, -dp_7_timestamp: null, -``` - -在 `writeState()` 的输出模板中新增区块: - -``` -# === Decision points === -dp_1_result: ${state.dp_1_result ?? 'null'} -dp_1_timestamp: ${state.dp_1_timestamp ?? 'null'} -...(dp_2 到 dp_7 同理) -``` - -**验证**: 创建测试状态文件,确认 14 个新字段可读写 -```bash -node -e " - import('./scripts/lib/state-loader.mjs').then(m => { - const s = m.readState('/tmp/test-dp'); - console.log('dp_3_result:', s.dp_3_result); // null - m.updateField('/tmp/test-dp', 'dp_3_result', 'approved'); - const s2 = m.readState('/tmp/test-dp'); - console.log('dp_3_result:', s2.dp_3_result); // approved - }) -" -``` - -- [ ] **1.3 修改 cmd-state.mjs:新增 set 子命令** - -**Files**: Modify: `scripts/lib/cmd-state.mjs` - -新增 `SETTABLE_FIELDS` 白名单和 `set` 子命令: - -```javascript -const SETTABLE_FIELDS = ['workflow', 'execution_mode', 'test_result', - 'dp_1_result', 'dp_1_timestamp', 'dp_2_result', 'dp_2_timestamp', - 'dp_3_result', 'dp_3_timestamp', 'dp_4_result', 'dp_4_timestamp', - 'dp_5_result', 'dp_5_timestamp', 'dp_6_result', 'dp_6_timestamp', - 'dp_7_result', 'dp_7_timestamp']; -``` - -`set` 子命令逻辑: -1. 解析参数:` ` -2. 检查 field 在 SETTABLE_FIELDS 中 -3. 调用 `updateField(changeDir, field, value)` -4. 输出确认信息 - -**验证**: -```bash -node scripts/spec-superflow.mjs state set /tmp/test-dp workflow hotfix -# Expected: ✅ Set workflow = hotfix -node scripts/spec-superflow.mjs state set /tmp/test-dp state executing -# Expected: ⛔ Field 'state' is not settable (use 'transition' instead) -``` - -- [ ] **1.4 验证 Batch 1 完整性** - -**Files**: (none) - -```bash -# 1. decision-points.md 存在且包含 7 个决策点 -grep -c "^## DP-" docs/decision-points.md -# Expected: 7 - -# 2. state-loader 新字段可读写 -node -e "import('./scripts/lib/state-loader.mjs').then(m => { const s = m.readState('/tmp/test-b1'); console.log(Object.keys(s).filter(k => k.startsWith('dp_')).length) })" -# Expected: 14 - -# 3. set 子命令白名单工作 -node scripts/spec-superflow.mjs state set /tmp/test-b1 dp_3_result approved --json -# Expected: {"ok":true,"field":"dp_3_result","value":"approved"} -``` - -- [ ] **1.5 Commit Batch 1** - -```bash -git add -A -git commit -m "feat: add decision point protocol infrastructure (DP fields + set command)" -``` - ---- - -## 2. Batch 2: 快速路径 Guard 基础设施 - -Depends on: Batch 1 - -- [ ] **2.1 修改 guard.mjs:新增 --workflow 参数** - -**Files**: Modify: `scripts/guard/guard.mjs` - -在 `parseArgs` 配置中新增 `workflow` 选项: - -```javascript -const { values, positionals } = parseArgs({ - args, - options: { - json: { type: 'boolean', default: false }, - workflow: { type: 'string', default: 'full' }, // 新增 - }, - allowPositionals: true, -}); -``` - -在白名单校验中新增 workflow 值验证: - -```javascript -const VALID_WORKFLOWS = ['full', 'hotfix', 'tweak']; -if (!VALID_WORKFLOWS.includes(values.workflow)) { - console.error(`Invalid workflow: ${values.workflow}. Must be one of: ${VALID_WORKFLOWS.join(', ')}`); - process.exit(2); -} -``` - -**验证**: -```bash -node scripts/guard/guard.mjs check /tmp/test exploring specifying --workflow hotfix --json -# Expected: exit 0 or 1 (not 2) -node scripts/guard/guard.mjs check /tmp/test exploring specifying --workflow invalid --json -# Expected: exit 2 with error message -``` - -- [ ] **2.2 实现 applyWorkflowMode() 函数** - -**Files**: Modify: `scripts/guard/guard.mjs` - -在 guard.mjs 中新增函数: - -```javascript -function applyWorkflowMode(checks, workflow) { - if (workflow === 'full') return checks; - - const SKIP_DIMENSIONS = { - hotfix: ['schema-valid'], - tweak: ['schema-valid', 'contract-fresh'], - }; - - const skip = SKIP_DIMENSIONS[workflow] || []; - return checks.map(check => { - if (skip.includes(check.dimension)) { - return { ...check, pass: true, skipped: true, failures: [] }; - } - return check; - }); -} -``` - -在主流程中,执行检查后调用 `applyWorkflowMode()`: - -```javascript -let results = []; -for (const dim of dimensions) { - const checkFn = CHECK_DISPATCH[dim]; - const result = await checkFn(changeDir); - results.push({ dimension: dim, ...result }); -} -results = applyWorkflowMode(results, values.workflow); -``` - -**验证**: 在 JSON 输出中确认 hotfix 模式下 schema-valid 被标记为 `skipped: true` - -- [ ] **2.3 新增快速路径转换到 TRANSITION_CHECKS** - -**Files**: Modify: `scripts/guard/guard.mjs` - -在 `TRANSITION_CHECKS` 中新增 2 个转换条目: - -```javascript -const TRANSITION_CHECKS = { - // 现有转换不变... - 'exploring:bridging': ['artifacts-exist'], // hotfix 跳过 specifying - 'exploring:approved': ['artifacts-exist'], // tweak 跳过 specifying + bridging -}; -``` - -**验证**: -```bash -node scripts/guard/guard.mjs check /tmp/test exploring bridging --workflow hotfix --json -# Expected: {"pass":,"checks":[{"dimension":"artifacts-exist",...}]} -node scripts/guard/guard.mjs check /tmp/test exploring approved --workflow tweak --json -# Expected: {"pass":,"checks":[{"dimension":"artifacts-exist",...}]} -``` - -- [ ] **2.4 端到端验证 guard.mjs 模式感知** - -**Files**: (none) - -```bash -# 1. hotfix 模式跳过 schema-valid -node scripts/guard/guard.mjs check /tmp/test specifying bridging --workflow hotfix --json -# Expected: schema-valid 在输出中标记为 skipped - -# 2. tweak 模式跳过 schema-valid + contract-fresh -node scripts/guard/guard.mjs check /tmp/test specifying bridging --workflow tweak --json -# Expected: schema-valid 和 contract-fresh 标记为 skipped - -# 3. full 模式不变 -node scripts/guard/guard.mjs check /tmp/test specifying bridging --workflow full --json -# Expected: schema-valid 正常执行 - -# 4. 无效 workflow 报错 -node scripts/guard/guard.mjs check /tmp/test exploring specifying --workflow chaos -# Expected: exit 2 -``` - -- [ ] **2.5 Commit Batch 2** - -```bash -git add -A -git commit -m "feat: add workflow mode awareness to guard.mjs (hotfix/tweak fast paths)" -``` - ---- - -## 3. Batch 3: 阶段防漂移注入 - -Depends on: Batch 1 - -- [ ] **3.1 创建 cmd-inject.mjs:核心逻辑** - -**Files**: Create: `scripts/lib/cmd-inject.mjs` - -核心结构: -1. 导入 `readState` from `./state-loader.mjs` -2. 定义 `PHASE_TEMPLATES` 对象(7 个阶段各一个模板) -3. `generatePhaseGuard(state)` 函数:选择模板 + 替换占位符 -4. `installRule(content)` 函数:写入 `rules/phase-guard.md` + 复制到 `.claude/always/` -5. `run(args)` 导出函数:解析参数 → 读状态 → 生成 → 安装 → 输出 - -`PHASE_TEMPLATES` 中每个模板包含: -- `# Phase Guard: {{change_name}}` -- `当前阶段: {{state}} | 工作流: {{workflow}}` -- `## ✅ 允许操作` 列表 -- `## ⛔ 禁止操作` 列表 -- `## 🔔 决策点` 提示(如适用) - -**验证**: -```bash -mkdir -p /tmp/test-inject -echo "state: specifying" > /tmp/test-inject/.spec-superflow.yaml -echo "workflow: full" >> /tmp/test-inject/.spec-superflow.yaml -echo "change_name: test-inject" >> /tmp/test-inject/.spec-superflow.yaml -node scripts/spec-superflow.mjs inject /tmp/test-inject -# Expected: 生成 rules/phase-guard.md + 安装到 .claude/always/ -cat rules/phase-guard.md -# Expected: 包含 "Phase Guard: test-inject" + "specifying" + 允许/禁止操作列表 -``` - -- [ ] **3.2 实现 PHASE_TEMPLATES 模板** - -**Files**: Modify: `scripts/lib/cmd-inject.mjs` - -7 个阶段模板的核心内容: - -| 阶段 | ✅ 允许操作 | ⛔ 禁止操作 | 🔔 决策点 | -|------|-----------|-----------|----------| -| exploring | 澄清需求、比较方案 | 创建工件、执行代码 | DP-1 | -| specifying | 创建/修改 proposal、specs、design、tasks | 修改 contract、执行代码 | DP-2 | -| bridging | 生成/修改 execution-contract | 执行代码、修改 specs | DP-3 | -| approved-for-build | 选择执行模式 | 修改 contract、specs | DP-4 | -| executing | 按 contract 执行任务、运行测试 | 修改 proposal、specs、design | DP-5 | -| debugging | 分析根因、修复 bug | 修改 proposal、specs、design | — | -| closing | 验证、归档、合并 delta specs | 修改 contract、执行新任务 | DP-6, DP-7 | - -每个模板用 `{{change_name}}`、`{{state}}`、`{{workflow}}` 占位符。 - -**验证**: 检查每个阶段模板生成正确 -```bash -for state in exploring specifying bridging approved-for-build executing debugging closing; do - echo "state: $state" > /tmp/test-inject/.spec-superflow.yaml - node scripts/spec-superflow.mjs inject /tmp/test-inject 2>/dev/null - echo "=== $state ===" - head -5 rules/phase-guard.md - echo "" -done -``` - -- [ ] **3.3 实现 .claude/always/ 安装逻辑** - -**Files**: Modify: `scripts/lib/cmd-inject.mjs` - -`installRule(content)` 函数: -1. 写入 `rules/phase-guard.md` -2. 确保 `.claude/always/` 目录存在(`mkdirSync` + `recursive: true`) -3. 复制到 `.claude/always/phase-guard.md` -4. 返回安装路径 - -错误处理: -- 目录创建失败 → 输出 `⛔ Cannot create .claude/always/: ` -- 文件写入失败 → 输出 `⛔ Cannot write phase-guard.md: ` - -**验证**: -```bash -rm -rf /tmp/test-inject/.claude -node scripts/spec-superflow.mjs inject /tmp/test-inject -ls /tmp/test-inject/.claude/always/phase-guard.md -# Expected: file exists -diff rules/phase-guard.md /tmp/test-inject/.claude/always/phase-guard.md -# Expected: no diff -``` - -- [ ] **3.4 修改 spec-superflow.mjs:新增 inject 路由** - -**Files**: Modify: `scripts/spec-superflow.mjs` - -在 help 文本中新增 `inject` 命令描述: - -``` - inject Generate phase-guard.md rule and install to .claude/always/ -``` - -在路由逻辑中新增 case: - -```javascript -case 'inject': - const { run: runInject } = await import('./lib/cmd-inject.mjs'); - await runInject(rest); - break; -``` - -**验证**: -```bash -node scripts/spec-superflow.mjs --help -# Expected: inject 命令出现在帮助文本中 -node scripts/spec-superflow.mjs inject --help -# Expected: inject 子命令用法说明 -``` - -- [ ] **3.5 处理状态文件缺失的优雅降级** - -**Files**: Modify: `scripts/lib/cmd-inject.mjs` - -当 `.spec-superflow.yaml` 不存在时: -1. 输出警告:`⚠️ No .spec-superflow.yaml found in , using defaults` -2. 使用默认值:`state=exploring`, `workflow=full` -3. 仍然生成 phase-guard.md - -`readState()` 已经有默认值合并逻辑(`BUILTIN_DEFAULTS`),所以只需确认 `change_name` 从目录名推导即可。 - -**验证**: -```bash -rm -f /tmp/test-inject/.spec-superflow.yaml -node scripts/spec-superflow.mjs inject /tmp/test-inject -# Expected: ⚠️ warning + 使用默认值生成 phase-guard.md -cat rules/phase-guard.md -# Expected: state=exploring, workflow=full -``` - -- [ ] **3.6 Commit Batch 3** - -```bash -git add -A -git commit -m "feat: add ssf inject command for phase-drift prevention rules" -``` - ---- - -## 4. Batch 4: Skill 文件更新 - -Depends on: Batch 2, Batch 3 - -- [ ] **4.1 更新 workflow-orchestrator SKILL.md:模式检测** - -**Files**: Modify: `skills/workflow-orchestrator/SKILL.md` - -在 "Required Inspection" 部分后新增 "Mode Detection" 部分: - -```markdown -## Mode Detection - -Before routing, check the workflow mode: -1. Run: `ssf state get workflow` -2. If workflow is `full` or unset → standard routing (no changes) -3. If workflow is `hotfix`: - - Validate: ≤2 files? No new modules? No schema changes? - - All pass → use hotfix fast-path routing - - Any fail → upgrade to `full`, run `ssf state set workflow full`, output upgrade reason -4. If workflow is `tweak`: - - Validate: ≤4 files? Single module? Config/doc/prompt only? - - All pass → use tweak fast-path routing - - Any fail → upgrade to `full`, run `ssf state set workflow full`, output upgrade reason -``` - -**验证**: SKILL.md 语法正确,markdown 渲染无错误 - -- [ ] **4.2 更新 workflow-orchestrator SKILL.md:快速路径路由规则** - -**Files**: Modify: `skills/workflow-orchestrator/SKILL.md` - -在 "Routing Rules" 部分新增快速路径路由: - -```markdown -### Hotfix Fast-Path Routing - -When workflow is `hotfix`: -- Route to `bridge-contract` with minimal contract mode (intent + task list only) -- Skip `spec-explorer` and full `spec-forger` -- Guard check: `node scripts/guard/guard.mjs check exploring bridging --workflow hotfix --json` -- After bridge: DP-3 契约批准 -- After approval: route to `execution-governor` (inline mode) -- After execution: route to `closure-archivist` (lightweight closure) - -### Tweak Fast-Path Routing - -When workflow is `tweak`: -- Route directly to `execution-governor` (direct edit mode) -- Skip `spec-explorer`, `spec-forger`, and `bridge-contract` -- Guard check: `node scripts/guard/guard.mjs check exploring approved --workflow tweak --json` -- After execution: route to `closure-archivist` (lightweight closure: file exists + syntax check) -``` - -新增状态转换后的 inject 提示: - -```markdown -### Post-Transition Injection Prompt - -After every successful `ssf state transition`, output: -> 💡 Run `ssf inject ` to update phase-guard.md with the new state. -``` - -**验证**: 快速路径路由规则清晰,包含 guard 命令、DP 引用和 inject 提示 - -- [ ] **4.3 更新 workflow-orchestrator SKILL.md:决策点引用** - -**Files**: Modify: `skills/workflow-orchestrator/SKILL.md` - -在 "Output Standard" 部分新增决策点引用要求: - -```markdown -### Decision Point References - -When routing to a skill that has an associated decision point, include the decision point number in the output: -- Route to bridge-contract → include `DP-3: 契约批准` -- Route to execution-governor → include `DP-4: 执行模式选择` -- Route to systematic-debugger (escalation) → include `DP-5: 调试升级` -- Route to closure-archivist → include `DP-7: 归档确认` - -Reference: `docs/decision-points.md` -``` - -**验证**: 决策点引用与 docs/decision-points.md 中的编号一致 - -- [ ] **4.4 更新 bridge-contract SKILL.md:hotfix 最小契约** - -**Files**: Modify: `skills/bridge-contract/SKILL.md` - -新增 hotfix 模式部分: - -```markdown -## Hotfix Mode: Minimal Contract - -When workflow is `hotfix`, generate a minimal execution-contract.md containing only: -1. **Intent Lock** — one-sentence description of the change intent -2. **Task List** — numbered list of tasks to complete -3. **Approval Gate** — DP-3 prompt for user confirmation - -Skip: Scope Fence, Build Rules, Review Gates, Test Evidence requirements. - -The minimal contract still requires explicit user approval (DP-3) before execution begins. -``` - -**验证**: bridge-contract SKILL.md 中 hotfix 模式部分清晰 - -- [ ] **4.5 更新 execution-governor SKILL.md:tweak 直接编辑模式** - -**Files**: Modify: `skills/execution-governor/SKILL.md` - -新增 tweak 模式部分: - -```markdown -## Tweak Mode: Direct Edit - -When workflow is `tweak`, execution-governor operates in direct edit mode: -1. Skip TDD Iron Law (no test-first requirement for config/doc changes) -2. Apply changes directly to target files -3. Verify file integrity after each change (file exists, non-empty, valid syntax) -4. No batch-based execution — apply all changes in sequence -5. Reference DP-4 for execution mode confirmation -``` - -**验证**: execution-governor SKILL.md 中 tweak 模式部分清晰 - -- [ ] **4.6 更新 closure-archivist SKILL.md:轻量闭合** - -**Files**: Modify: `skills/closure-archivist/SKILL.md` - -新增 tweak/hotfix 闭合部分: - -```markdown -## Lightweight Closure (hotfix/tweak mode) - -When workflow is `hotfix` or `tweak`, closure-archivist performs lightweight verification: -1. Verify all changed files exist and are non-empty -2. Run syntax check on code files (`node --check` for .mjs/.js) -3. Skip the full 5-step three-dimensional verification -4. Still record DP-6 (验证失败) and DP-7 (归档确认) decision points -5. Delta specs are NOT generated in lightweight closure (no specs to sync) -``` - -**验证**: closure-archivist SKILL.md 中轻量闭合部分清晰,明确说明跳过哪些步骤 - -- [ ] **4.7 Commit Batch 4** - -```bash -git add -A -git commit -m "feat: update 4 skill files for fast-path routing and decision point references" -``` - ---- - -## 5. Batch 5: 集成 + 文档 + 发布准备 - -Depends on: Batch 1, Batch 2, Batch 3, Batch 4 - -- [ ] **5.1 版本号 → 0.6.0** - -**Files**: Modify: `package.json`, `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json`, `.cursor-plugin/plugin.json`, `gemini-extension.json` - -```bash -node scripts/spec-superflow.mjs version 0.6.0 -# Expected: ✅ Updated version to 0.6.0 in 5 manifests -``` - -- [ ] **5.2 更新 CHANGELOG.md** - -**Files**: Modify: `CHANGELOG.md` - -新增 v0.6.0 条目: - -```markdown -## [0.6.0] - 2026-06-29 - -### Added -- **Fast-path workflow modes**: hotfix and tweak modes skip full planning for small changes -- **Phase-drift prevention**: `ssf inject` command generates `.claude/always/phase-guard.md` -- **Decision point protocol**: `docs/decision-points.md` defines 7 standard decision points -- **Guard mode awareness**: `guard.mjs` accepts `--workflow` parameter for mode-specific checks -- **State set command**: `ssf state set` for updating workflow mode and decision point results -- **Auto-upgrade conditions**: hotfix/tweak automatically upgrade to full when thresholds exceeded - -### Changed -- 4 skill files updated with fast-path routing and decision point references -``` - -- [ ] **5.3 更新 README.md** - -**Files**: Modify: `README.md` - -更新内容: -1. 架构图:新增 phase-guard.md 和 decision-points.md -2. CLI 命令表:新增 `ssf inject` 命令 -3. 新增 "Fast-Path Workflow" 部分:说明 hotfix/tweak 模式 -4. 状态机图:新增快速路径箭头 - -- [ ] **5.4 运行 ssf doctor 验证** - -**Files**: (none) - -```bash -node scripts/spec-superflow.mjs doctor -# Expected: 所有检查通过 -# - Version: 0.6.0 (consistent) -# - Hooks: valid -# - Skills: 9/9 -# - dist/: compiled -# - Node.js: >= 22 -# - Docs: consistent -``` - -- [ ] **5.5 Commit Batch 5** - -```bash -git add -A -git commit -m "chore: bump version to 0.6.0, update CHANGELOG and README" -``` - ---- - -## 6. Closeout - -- [ ] **6.1 验证设计决策落地** - -| 设计决策 | 对应任务 | 状态 | -|---------|---------|------| -| 决策 1: 模式检测由 orchestrator 执行 | 4.1, 4.2 | — | -| 决策 2: guard.mjs 通过 --workflow 参数 | 2.1, 2.2, 2.3 | — | -| 决策 3: ssf inject 显式命令 | 3.1, 3.2, 3.3, 3.4 | — | -| 决策 4: 决策点审计在状态文件中 | 1.2, 1.3 | — | -| 决策 5: 阶段模板用 PHASE_TEMPLATES | 3.2 | — | - -- [ ] **6.2 风险确认** - -| 风险 | 缓解措施 | 已实现 | -|------|---------|--------| -| 模式检测误判 | 升级条件兜底 | — | -| phase-guard.md 过期 | inject 提示 | — | -| .claude/always/ 不存在 | mkdir -p | — | -| 决策点字段膨胀 | 独立区块 | — | -| 跳过 schema-valid 质量下降 | artifacts-exist 兜底 | — | -| 无效 workflow 值 | 白名单校验 | — | - -- [ ] **6.3 发布 v0.6.0** - -```bash -npm run build && npm test -git tag v0.6.0 && git push --tags -# CI/CD: build + test → GitHub Release + npm publish -``` diff --git a/changes/v0.7.0-aware-and-platform-fixes/.spec-superflow.yaml b/changes/v0.7.0-aware-and-platform-fixes/.spec-superflow.yaml deleted file mode 100644 index 1253f1d..0000000 --- a/changes/v0.7.0-aware-and-platform-fixes/.spec-superflow.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# .spec-superflow.yaml — lightweight state machine -# Derived data. Always rebuildable from artifacts. Lost/corrupt → fall back to content-level detection. - -# === Core state === -state: closing -workflow: full - -# === Hashes (fast staleness detection) === -artifacts_hash: sha256:263bf857edd7d9960e53524d9022af61dca7d1bd5882834e06d5cef829f6208f -contract_hash: sha256:0a295731ad031908f76f0c7967ddde12e3f41c110447ee6ba6b036122f41dbf4 - -# === Execution progress === -execution_mode: null -batches_completed: 0 -test_result: null - -# === Metadata === -change_name: v0.7.0-aware-and-platform-fixes -last_transition: 2026-06-30T14:45:42.145Z -last_transition_from: executing -last_transition_to: closing - -# === Decision points === -dp_1_result: null -dp_1_timestamp: null -dp_2_result: null -dp_2_timestamp: null -dp_3_result: approved -dp_3_timestamp: 2026-06-30T13:49:31Z -dp_4_result: SDD -dp_4_timestamp: 2026-06-30T13:55:08Z -dp_5_result: null -dp_5_timestamp: null -dp_6_result: pass -dp_6_timestamp: 2026-06-30T14:45:41Z -dp_7_result: approved -dp_7_timestamp: 2026-06-30T14:45:41Z diff --git a/changes/v0.7.0-aware-and-platform-fixes/decision-point-audit.md b/changes/v0.7.0-aware-and-platform-fixes/decision-point-audit.md deleted file mode 100644 index 661cc63..0000000 --- a/changes/v0.7.0-aware-and-platform-fixes/decision-point-audit.md +++ /dev/null @@ -1,67 +0,0 @@ -# Decision-Point Audit Report - -**变更**: v0.7.0-aware-and-platform-fixes -**生成时间**: 2026-06-30T14:45:46.321Z -**当前状态**: closing - -## 汇总表 - -| DP | 名称 | 结果 | 时间戳 | -|----|------|------|--------| -| DP-1 | 需求确认 | not recorded | — | -| DP-2 | 工件审查 | not recorded | — | -| DP-3 | 契约批准 | approved | 2026-06-30T13:49:31Z | -| DP-4 | 执行模式选择 | SDD | 2026-06-30T13:55:08Z | -| DP-5 | 调试升级 | not recorded | — | -| DP-6 | 验证失败 | pass | 2026-06-30T14:45:41Z | -| DP-7 | 归档确认 | approved | 2026-06-30T14:45:41Z | - -**统计**: 4/7 已记录,3/7 未记录。 - -## 逐决策点说明 - -### DP-1: 需求确认 - -- **结果**: not recorded -- **时间戳**: — -- **解读**: 该决策点尚未记录结果。如果工作流已经经过该阶段,请检查是否漏记。 - -### DP-2: 工件审查 - -- **结果**: not recorded -- **时间戳**: — -- **解读**: 该决策点尚未记录结果。如果工作流已经经过该阶段,请检查是否漏记。 - -### DP-3: 契约批准 - -- **结果**: approved -- **时间戳**: 2026-06-30T13:49:31Z -- **解读**: 决策点 DP-3 已记录为 "approved"。 - -### DP-4: 执行模式选择 - -- **结果**: SDD -- **时间戳**: 2026-06-30T13:55:08Z -- **解读**: 决策点 DP-4 已记录为 "SDD"。 - -### DP-5: 调试升级 - -- **结果**: not recorded -- **时间戳**: — -- **解读**: 该决策点尚未记录结果。如果工作流已经经过该阶段,请检查是否漏记。 - -### DP-6: 验证失败 - -- **结果**: pass -- **时间戳**: 2026-06-30T14:45:41Z -- **解读**: 决策点 DP-6 已记录为 "pass"。 - -### DP-7: 归档确认 - -- **结果**: approved -- **时间戳**: 2026-06-30T14:45:41Z -- **解读**: 决策点 DP-7 已记录为 "approved"。 - ---- - -*本报告由 `ssf audit` 自动生成,仅供审计与归档参考。* diff --git a/changes/v0.7.0-aware-and-platform-fixes/design.md b/changes/v0.7.0-aware-and-platform-fixes/design.md deleted file mode 100644 index b0d9d47..0000000 --- a/changes/v0.7.0-aware-and-platform-fixes/design.md +++ /dev/null @@ -1,281 +0,0 @@ -# 技术设计:v0.7.0 Aware & Multiplatform - -**Date:** 2026-06-30 -**Version:** 0.6.0 → 0.7.0 -**Goal:** 修复当前平台安装问题,补齐 v0.6.0 展望的三个 Aware 特性。 - ---- - -## 1. 背景 - -### 1.1 当前状态 - -v0.6.0 已发布: - -- `workflow-orchestrator` 支持显式 `workflow` 字段(full / hotfix / tweak)。 -- `ssf inject` 生成 `.claude/always/phase-guard.md`。 -- `.spec-superflow.yaml` 记录 14 个 DP 审计字段。 -- 支持 7 个平台:Claude Code / Cursor / Codex / OpenCode / Copilot CLI / Gemini CLI / Trae。 - -### 1.2 已知问题 - -- **Cursor**:`.cursor-plugin/plugin.json` 中的 `skills` 字段不被 Cursor 识别;Cursor 通过 `.cursor/` 目录(skills/rules/commands/hooks)加载。 -- **Copilot CLI**:根 `plugin.json` 的 `"author": "MageByte"` 是字符串,Copilot 要求 `author` 为对象。 - -### 1.3 约束 - -- 零外部 npm 依赖。 -- 不改动 `src/validation/validator.ts`。 -- 不破坏现有 9 个 skill 的核心逻辑。 -- 复用 v0.6.0 基础设施(guard.mjs、state-loader.mjs、cmd-inject.mjs、cmd-state.mjs)。 - ---- - -## 2. 目标与非目标 - -### 2.1 目标 - -1. **修复平台安装 bug** - - Cursor:提供 `.cursor/` 目录部署或安装脚本。 - - Copilot CLI:修正 `plugin.json` 的 `author` 格式。 -2. **自动模式检测**:根据变更内容自动推断 workflow 模式,减少用户显式声明。 -3. **多平台 phase-guard 注入**:一次 `ssf inject` 同时更新 `.claude/always/`、Cursor rules、Copilot instructions、Gemini `GEMINI.md`。 -4. **决策点审计报告**:新增 `ssf audit`(或 `ssf report`)子命令,生成 markdown 报告。 - -### 2.2 非目标 - -- 不新增 skill。 -- 不修改 validator.ts。 -- 不支持 7 平台以外的客户端。 -- 不改动 CI/CD 流程。 - ---- - -## 3. 架构决策 - -### 决策 1: Cursor 采用 `.cursor/` 目录本地部署 - -- **选择**:提供一个 `scripts/install-cursor.mjs`(或 bash 脚本),将 `skills/` 复制/链接到 `.cursor/skills/`,并生成 `.cursor/rules/phase-guard.mdc` 与 `.cursor/hooks.json`。 -- **理由**:Cursor 官方/社区案例(如 thrum)均采用 `.cursor/` 目录部署;`.cursor-plugin/plugin.json` 不被证明能自动加载 skills。 -- **替代方案**:继续维护 `.cursor-plugin/plugin.json` 并祈祷 Cursor 未来支持 — 不可接受。 - -### 决策 2: 自动模式检测放在 workflow-orchestrator - -- **选择**:workflow-orchestrator 在路由前读取 proposal/contract 或 git diff,计算文件数、模块、文件类型,自动设置 workflow。 -- **理由**:模式检测是路由逻辑的一部分,放在 orchestrator 最自然。 -- **替代方案**:新增独立脚本 — 增加命令复杂度。 - -### 决策 3: 多平台注入扩展 cmd-inject.mjs - -- **选择**:`cmd-inject.mjs` 维护一个 `PLATFORM_TEMPLATES` 映射,根据当前状态生成各平台需要的文件内容,分别写入 `.claude/always/phase-guard.md`、`.cursor/rules/phase-guard.mdc`、`.github/copilot-instructions.md`(或 `.copilot/`)、`GEMINI.md` 追加段。 -- **理由**:复用现有 PHASE_TEMPLATES,零依赖,集中管理。 -- **替代方案**:每个平台单独命令 — 增加 CLI 复杂度。 - -### 决策 4: DP 审计报告从状态文件生成 - -- **选择**:新增 `scripts/lib/cmd-audit.mjs`,读取 `.spec-superflow.yaml` 的 `dp_N_*` 字段,生成 `changes//decision-point-audit.md`。 -- **理由**:状态文件已是审计数据的汇总;新增独立审计日志会引入额外文件管理负担。 -- **替代方案**:新增 `.spec-superflow-audit.jsonl` — 与 v0.5.0 "状态文件可重建" 原则冲突。 - ---- - -## 4. 详细设计 - -### 4.1 平台安装修复 - -#### Cursor - -- 新增 `scripts/install-cursor.mjs`: - - 创建 `.cursor/skills/` 并把 `skills/` 下的 9 个 skill 复制/链接过去。 - - 创建 `.cursor/rules/phase-guard.mdc`(Cursor rules 格式,带 `alwaysApply: true`)。 - - 可选:创建 `.cursor/hooks.json` 用于 SessionStart 注入。 -- 更新 `INSTALL.md`:Cursor 部分改为先运行 `node scripts/install-cursor.mjs`。 -- 保留 `.cursor-plugin/plugin.json` 作为备份/未来兼容,但 INSTALL.md 不再推荐仅依赖它。 - -#### Copilot CLI - -- 修改根 `plugin.json`: - ```json - "author": { - "name": "MageByte", - "url": "https://github.com/MageByte-Zero" - } - ``` -- `ssf doctor` 增加对根 `plugin.json` 的 `author` 格式检查。 - -### 4.2 自动模式检测 - -v0.6.0 的 README 曾把部分轻微需求场景排除在外,导致用户觉得只有大型变更才值得使用 spec-superflow。v0.7.0 的自动模式检测通过把 `hotfix`/`tweak` 也纳入标准流程,让一次几行代码的修复、配置或文档调整都能自动匹配到合适的轻量模式,从而覆盖各种规模的变更。 - -workflow-orchestrator 在读取 `.spec-superflow.yaml` 的 `workflow` 字段后: - -1. 如果用户显式声明 hotfix/tweak,仍保留显式值。 -2. 如果未声明或 full: - - 读取 `proposal.md` 的 `## Scope` / `## What Changes`。 - - 读取 `tasks.md` 中的任务数量和涉及文件数。 - - 规则: - - ≤2 文件、无新模块、无 schema/API 变更 → hotfix - - ≤4 文件、纯配置/文档/markdown → tweak - - 否则 → full -3. 自动设置后输出推断结果和原因。 - -### 4.3 多平台 phase-guard 注入 - -`cmd-inject.mjs` 扩展: - -``` -export async function run(args) - ├── parseArgs: [--platforms ] [--json] - ├── readState(changeDir) - ├── 选择当前状态模板: PHASE_TEMPLATES[state] - ├── 生成各平台文件: - │ .claude/always/phase-guard.md - │ .cursor/rules/phase-guard.mdc - │ .github/copilot-instructions.md(或 .copilot/instructions.md) - │ GEMINI.md(追加或更新段) - └── 输出成功摘要 -``` - -默认注入所有已识别平台;`--platforms cursor,copilot` 可限定。 - -### 4.4 决策点审计报告 - -新增 `scripts/lib/cmd-audit.mjs`: - -``` -ssf audit [--output ] -``` - -- 读取状态文件中的 `dp_1_result` ... `dp_7_timestamp`。 -- 生成 `changes//decision-point-audit.md`,包含: - - 每个 DP 的结果、时间戳、是否缺失。 - - 一个汇总表和结论。 - -### 4.5 模板中文化 - -将 `templates/` 下的静态英文模板翻译成中文,与项目中文优先的约定一致: - -- `proposal.md`:标题、章节提示语中文化,保留结构化占位符。 -- `design.md`:章节标题和提示语中文化,便于中文用户填写技术设计。 -- `tasks.md`:任务列表提示中文化。 -- `spec.md`:需求/场景模板中文化,保留 `SHALL`/`MUST` 等英文关键字(平台规范要求)。 -- `execution-contract.md`:合同章节提示中文化。 - -原则: -- 占位符和示例保留中文自然表达。 -- 不影响 `spec-forger` 等 skill 对关键字(如 `#### Scenario:`)的解析。 -- 仅翻译模板,不强制要求历史 change 的 artifacts 回改。 - ---- - -## 5. 数据流 - -### 5.1 自动模式检测 - -``` -用户请求 → workflow-orchestrator - → 读取 state.workflow - → 未声明则读取 proposal/tasks - → 推断 workflow → ssf state set workflow - → 继续正常路由 -``` - -### 5.2 多平台注入 - -``` -ssf inject - → 读状态 - → 生成 .claude/always/phase-guard.md - → 生成 .cursor/rules/phase-guard.mdc - → 生成 .github/copilot-instructions.md - → 更新 GEMINI.md 对应段 -``` - -### 5.3 DP 审计报告 - -``` -closure-archivist 完成前 - → ssf audit - → 生成 decision-point-audit.md - → 用户确认后归档 -``` - ---- - -## 6. 风险与缓解 - -| 风险 | 缓解 | -|------|------| -| Cursor 规则格式变化 | 使用最简 `.mdc` 格式(frontmatter + markdown),便于调整 | -| Copilot 对 author 对象有其他字段要求 | 仅使用 `name` + `url`,与 Claude/Codex 保持一致 | -| 自动模式检测误判 | 输出推断原因,用户可显式覆盖 | -| 多平台注入污染项目目录 | 默认写入平台标准目录,并提供 `--platforms` 限定 | -| DP 审计字段为空 | 报告中标记为 "未记录",不中断流程 | - ---- - -## 7. 文件清单 - -### 7.1 新增文件 - -| 文件 | 用途 | 估计行数 | -|------|------|---------| -| `scripts/lib/cmd-audit.mjs` | `ssf audit` 子命令 | ~120 | -| `scripts/install-cursor.mjs` | Cursor 本地部署脚本 | ~100 | -| `.cursor/rules/phase-guard.mdc` | Cursor 阶段规则(生成) | — | -| `.github/copilot-instructions.md` | Copilot 阶段规则(生成) | — | - -### 7.2 修改文件 - -| 文件 | 改动 | 影响行数 | -|------|------|---------| -| `plugin.json` | `author` 改为对象 | ~5 | -| `scripts/lib/cmd-inject.mjs` | 扩展为多平台注入 | ~80 | -| `skills/workflow-orchestrator/SKILL.md` | 自动模式检测逻辑 | ~40 | -| `skills/closure-archivist/SKILL.md` | 引用 `ssf audit` | ~10 | -| `INSTALL.md` | Cursor/Copilot 安装说明更新 | — | -| `CHANGELOG.md` | v0.7.0 条目 | — | -| `package.json` 等 manifest | 版本 0.7.0 | 5 个文件 | - -### 7.3 不变的东西 - -- 9 个 skill 的核心逻辑不变。 -- `src/validation/validator.ts` 不变。 -- 现有 CLI 命令不变(`list/validate/doctor/version/sync/config/state/inject`)。 - ---- - -## 8. 实现顺序 - -### Batch 1: 平台安装修复(预计 0.5 天) - -- 修复根 `plugin.json` 的 `author`。 -- 创建 `scripts/install-cursor.mjs` 并验证 `.cursor/` 部署。 -- 更新 `INSTALL.md` 和 `ssf doctor`。 - -### Batch 2: 自动模式检测(预计 0.5 天) - -- workflow-orchestrator 增加推断逻辑。 -- 增加测试/示例。 - -### Batch 3: 多平台 phase-guard 注入(预计 1 天) - -- 扩展 `cmd-inject.mjs`。 -- 定义 Cursor `.mdc`、Copilot instructions、Gemini `GEMINI.md` 格式。 - -### Batch 4: 决策点审计报告(预计 0.5 天) - -- 新增 `cmd-audit.mjs`。 -- closure-archivist 引用。 - -### Batch 5: 集成 + 发布(预计 0.5 天) - -- 版本号 0.7.0、CHANGELOG、README、doctor、发布。 - ---- - -## 9. 展望 v0.8.0 - -- 更细粒度的平台配置(各平台启用/禁用哪些 skill)。 -- 插件市场自动刷新/缓存清理。 -- 更丰富的决策点审计可视化。 diff --git a/changes/v0.7.0-aware-and-platform-fixes/execution-contract.md b/changes/v0.7.0-aware-and-platform-fixes/execution-contract.md deleted file mode 100644 index 4d52f69..0000000 --- a/changes/v0.7.0-aware-and-platform-fixes/execution-contract.md +++ /dev/null @@ -1,211 +0,0 @@ -# Execution Contract: v0.7.0 Aware & Multiplatform - -## Intent Lock - -- **Change name**: `v0.7.0-aware-and-platform-fixes` -- **Problem being solved**: v0.6.0 shipped with broken or incomplete platform installation on Cursor and GitHub Copilot CLI, left three planned Aware features (auto workflow-mode detection, multi-platform phase-guard injection, decision-point audit report) unimplemented, and the README still excluded minor changes from the workflow. v0.7.0 fixes the platform issues and makes the workflow usable for changes of any size by automatically selecting `hotfix`/`tweak`/`full` mode. -- **In scope**: - - Fix Cursor installation by providing a `.cursor/` local deploy path (`scripts/install-cursor.mjs`) and updating `INSTALL.md`. - - Fix root `plugin.json` `author` field to be an object so Copilot CLI validation passes; extend `ssf doctor` to check it. - - Add automatic workflow-mode inference (`hotfix`/`tweak`/`full`) to `workflow-orchestrator`. - - Extend `ssf inject` to generate phase-guard artifacts for Claude, Cursor, Copilot, and Gemini with an optional `--platforms` flag. - - Add `ssf audit` to generate `decision-point-audit.md` from `.spec-superflow.yaml` DP fields. - - Update affected skill files (`workflow-orchestrator`, `closure-archivist`), `CHANGELOG.md`, `README.md`. - - Translate all `templates/` planning templates (`proposal.md`, `design.md`, `tasks.md`, `spec.md`, `execution-contract.md`) to Chinese. - - Bump version to `0.7.0`. -- **Out of scope**: - - No new skills (keep the existing 9 skills). - - No skill renaming — deferred to a dedicated v0.8.0 change. - - No changes to `src/validation/validator.ts`. - - No CI/CD pipeline changes. - - No clients beyond the 7 target platforms. - -## Approved Behavior - -- **Approved requirements summary**: - 1. Cursor installation works out of the box via a documented local deploy script or `.cursor/` directory copy. - 2. `ssf inject` creates/updates `.cursor/rules/phase-guard.mdc`. - 3. Root `plugin.json` uses an object for `author` and passes `ssf doctor` validation. - 4. `INSTALL.md` accurately describes Cursor and Copilot CLI installation. - 5. `workflow-orchestrator` infers `hotfix`/`tweak`/`full` from artifact content when `workflow` is not explicitly set, so changes of any size can use spec-superflow. - 6. Explicit `workflow` values are never overwritten without user request. - 7. `ssf inject` generates consistent phase-guard artifacts for all supported platforms by default and supports `--platforms cursor,copilot` style filtering. - 8. Each platform artifact uses the correct format (`.mdc` with `alwaysApply: true` for Cursor, markdown instructions for Copilot, appended section for Gemini). - 9. `ssf audit ` generates `decision-point-audit.md` listing DP-1 through DP-7 with result, timestamp, and interpretation. - 10. Missing decision points are flagged as `not recorded` rather than failing. - 11. `closure-archivist` prompts the user to run `ssf audit` before final closure. - 12. `ssf audit` is read-only and idempotent. - 13. All `templates/` planning templates are translated to Chinese while preserving required parsing markers such as `#### Scenario:`. - 14. Translating templates does not break validation of existing English specs. - -- **Key scenarios**: - - Cursor install script makes the 9 skills available under `.cursor/skills/`. - - `ssf doctor` reports the root `plugin.json` `author` field as valid. - - A ≤2-file bug fix with no schema changes is inferred as `hotfix`. - - A ≤4-file config/docs change is inferred as `tweak`. - - A ≥5-file or new-module change stays/sets `full`. - - `ssf inject changes/foo` updates `.claude/always/phase-guard.md`, `.cursor/rules/phase-guard.mdc`, Copilot instructions, and `GEMINI.md`. - - `ssf inject changes/foo --platforms cursor,copilot` only updates Cursor and Copilot artifacts. - - `ssf audit changes/foo` produces a human-readable report and leaves `.spec-superflow.yaml` unchanged. - - `templates/design.md` and `templates/proposal.md` use Chinese section headings and placeholders. - - Existing English specs in `changes/v0.6.0-*/specs/` still pass `ssf validate` after template translation. - -- **Acceptance checks**: - - Root `plugin.json` parses as JSON and `author.name` exists. - - `node scripts/spec-superflow.mjs doctor` passes with no `author`-format error. - - `node scripts/install-cursor.mjs` completes and creates `.cursor/skills/` plus `.cursor/rules/phase-guard.mdc`. - - `workflow-orchestrator/SKILL.md` contains the auto-detection rules and preserves explicit overrides. - - `ssf inject` with `--platforms` writes only the requested artifacts. - - Generated Cursor `.mdc` includes `alwaysApply: true` frontmatter. - - Generated Copilot instructions include `# Phase Guard`. - - `GEMINI.md` contains a `# Phase Guard` section after injection. - - `ssf audit` creates `decision-point-audit.md` with a summary table and per-DP sections. - - `closure-archivist/SKILL.md` references `ssf audit` at DP-7. - - `templates/*.md` are in Chinese and still produce valid artifacts when used by `spec-forger`. - - Existing English change specs continue to validate. - - `npm run build` and `npm test` pass after all changes. - - All manifest versions (`package.json`, `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json`, `.cursor-plugin/plugin.json`, `gemini-extension.json`) read `0.7.0`. - -## Design Constraints - -- **Architecture constraints**: - - Zero external runtime npm dependencies; all new code is plain Node.js ES modules. - - Reuse existing scripts (`guard.mjs`, `state-loader.mjs`, `cmd-inject.mjs`, `cmd-state.mjs`) instead of adding new command infrastructure. - - Keep the 9 skill boundaries unchanged; only add logic to existing skill files. -- **Interface constraints**: - - New `ssf inject` behavior must remain backward compatible: default behavior now produces more artifacts, but existing flags and output shape (JSON/stdout) must not break. - - New `ssf audit` subcommand must be read-only with respect to `.spec-superflow.yaml` and planning artifacts. -- **Dependency constraints**: - - Node >= 22. - - Cursor, Copilot CLI, and Gemini CLI platform conventions must be followed for generated artifacts. -- **Data constraints**: - - Decision-point audit report must derive from `dp_1_*` ... `dp_7_*` fields in `.spec-superflow.yaml` only. - - Phase-guard content must be identical across platforms for the same change state. - -## Task Batches - -### Batch 1: Platform Installation Fixes - -- **Objective**: Make Cursor and Copilot CLI installations work and validate them. -- **Inputs**: `plugin.json`, `.cursor-plugin/plugin.json`, `INSTALL.md`, `scripts/lib/cmd-doctor.mjs`. -- **Outputs**: - - Updated root `plugin.json` with object `author`. - - New `scripts/install-cursor.mjs` that deploys skills and rules to `.cursor/`. - - Updated `INSTALL.md` Cursor and Copilot CLI sections. - - Extended `ssf doctor` author-format check. -- **Done when**: - - `ssf doctor` reports root `plugin.json` author valid. - - `node scripts/install-cursor.mjs` runs without error and produces the expected `.cursor/` tree. - - `INSTALL.md` instructions match the actual mechanisms. - - `npm run build && npm test` still pass. - -### Batch 2: Auto Mode Detection - -- **Objective**: Let `workflow-orchestrator` infer workflow mode from artifact content. -- **Inputs**: `skills/workflow-orchestrator/SKILL.md`, `proposal.md`, `tasks.md`. -- **Outputs**: Updated `workflow-orchestrator/SKILL.md` with inference rules and examples. -- **Done when**: - - Skill text describes the hotfix/tweak/full inference rules. - - Skill explicitly preserves an explicit `workflow` value. - - At least one example/test case is included. - -### Batch 3: Multi-Platform Phase-Guard Injection - -- **Objective**: Extend `ssf inject` to generate phase-guard artifacts for Claude, Cursor, Copilot, and Gemini. -- **Inputs**: `scripts/lib/cmd-inject.mjs`, `GEMINI.md`, platform conventions. -- **Outputs**: - - Updated `cmd-inject.mjs` with `PLATFORM_TEMPLATES` and `--platforms` flag. - - Generated `.cursor/rules/phase-guard.mdc`, `.github/copilot-instructions.md`, and updated `GEMINI.md` section. -- **Done when**: - - Default `ssf inject` updates all platform artifacts. - - `--platforms` restricts output correctly. - - Each artifact matches its platform format and shares the same current state. - -### Batch 4: Decision-Point Audit Report - -- **Objective**: Add `ssf audit` and wire it into closure. -- **Inputs**: `scripts/lib/state-loader.mjs`, `.spec-superflow.yaml`, `skills/closure-archivist/SKILL.md`. -- **Outputs**: - - New `scripts/lib/cmd-audit.mjs`. - - `decision-point-audit.md` template. - - Updated `closure-archivist/SKILL.md` referencing `ssf audit`. -- **Done when**: - - `ssf audit ` produces the report. - - Missing DPs are marked `not recorded`. - - The command leaves state and artifacts unchanged. - -### Batch 5: Release - -- **Objective**: Bump version, translate templates to Chinese, update docs, run final validation, and prepare release. -- **Inputs**: `package.json`, plugin manifests, `templates/*.md`, `CHANGELOG.md`, `README.md`. -- **Outputs**: - - Version `0.7.0` synchronized across all manifests. - - Chinese `templates/proposal.md`, `templates/design.md`, `templates/tasks.md`, `templates/spec.md`, `templates/execution-contract.md`. - - `CHANGELOG.md` v0.7.0 entries. - - Updated `README.md` with new commands and install notes. -- **Done when**: - - `ssf doctor` and `ssf validate` pass. - - `npm run build && npm test` pass. - - All manifests show `0.7.0`. - - Templates are in Chinese and existing English specs still validate. - -## Test Obligations - -- **Behavior that must start with failing tests**: - - Root `plugin.json` author as string must fail `ssf doctor` before the fix, then pass after. - - `ssf inject --platforms invalid` must fail or be rejected. - - `ssf audit` on a change with no DP results must still produce a report marking DPs as `not recorded`. -- **Required edge cases**: - - Explicit `workflow` in state is preserved when auto-detection runs. - - `ssf inject` default writes all platforms; filtered writes only requested platforms. - - `GEMINI.md` injection appends or replaces the `# Phase Guard` section without duplicating it. -- **Regression-sensitive areas**: - - Existing `.claude/always/phase-guard.md` generation must not change format unexpectedly. - - Existing `ssf validate` and `ssf doctor` checks must continue to pass. - - Existing skill loading on Claude Code must remain unaffected. - - Existing English specs and change artifacts must still validate after templates are translated. - -## Execution Mode - -- **Mode**: `SDD` (Spec-Driven Development) -- **Selection rationale**: The change spans five batches with cross-batch dependencies (platform fix → inject → audit), explicit acceptance checks, and requires test-first validation of the `author` fix. SDD ensures each batch is verified before the next. - -## Verification Dimensions - -| Dimension | Status | Findings | -|-----------|--------|----------| -| Completeness | Pending | All 14 approved requirements mapped to batches; no unmapped requirements. | -| Correctness | Pending | Requires test evidence for `author` fix, Cursor install, inject platform filtering, and audit idempotency. | -| Coherence | Pending | Multi-platform artifacts must share identical state; workflow inference must not conflict with explicit overrides. | - -**Overall verdict**: Pending - -## Review Gates - -- **Mandatory review points**: - - End of Batch 1: confirm `ssf doctor` passes and Cursor install script output is correct. - - End of Batch 3: inspect generated artifacts for each platform side-by-side for state consistency. - - End of Batch 4: verify `ssf audit` report by running it and diffing against `.spec-superflow.yaml`. - - End of Batch 5: final `ssf validate`, `ssf doctor`, `npm run build`, `npm test`, and version-manifest sync check. -- **Blocker categories**: - - Any platform manifest becomes invalid JSON or fails its own platform validation. - - Existing tests break. - - Auto-detection overwrites an explicit `workflow` value. - - `ssf audit` mutates state or artifacts. - -## Escalation Rules - -- **Return to `specifying`** when: - - A new capability or platform is added after contract approval. - - The scope of auto-detection or multi-platform inject changes materially (e.g., new platform, new workflow mode). -- **Return to `bridging`** when: - - `proposal.md`, `design.md`, `specs/`, or `tasks.md` are updated in a way that changes intent, constraints, or batches. - - The generated contract is detected as stale by `ssf state`. -- **Do not continue implementation if**: - - `execution-contract.md` is not approved by the user (DP-3). - - Major ambiguity remains about platform artifact formats. - - Tests fail at any review gate. - -## Coverage Cross-Check - -All 14 approved requirements from the five delta specs are reflected in the Approved Behavior section and mapped to at least one execution batch or acceptance check. No requirements were dropped. diff --git a/changes/v0.7.0-aware-and-platform-fixes/proposal.md b/changes/v0.7.0-aware-and-platform-fixes/proposal.md deleted file mode 100644 index 7ac9a66..0000000 --- a/changes/v0.7.0-aware-and-platform-fixes/proposal.md +++ /dev/null @@ -1,68 +0,0 @@ -# Change Proposal: v0.7.0 Aware & Multiplatform - -## Why - -v0.6.0 发布了 Fast & Aware 的三个特性(快速路径、阶段防漂移、决策点协议),但发布后发现 **部分平台的安装没有生效**: - -1. **Cursor**:`.cursor-plugin/plugin.json` 中的 `skills` 字段不被 Cursor 识别。Cursor 实际通过 `.cursor/skills/`、`.cursor/rules/`、`.cursor/commands/` 等目录或专用安装脚本加载技能,导致用户按 INSTALL.md 操作后看不到 skill。 -2. **GitHub Copilot CLI**:根目录 `plugin.json` 中 `"author": "MageByte"` 是字符串,而 Copilot 插件清单要求 `author` 为对象(`{ "name": "..." }`),严格校验下可能导致安装失败。 - -同时,v0.6.0 design.md 的展望列出了三个方向: - -- 自动模式检测(从显式声明改为自动推断 hotfix/tweak/full) -- 多平台 phase-guard 注入(Cursor rules / Copilot instructions / Gemini GEMINI.md) -- 决策点审计报告(从 `.spec-superflow.yaml` 的 `dp_N_*` 字段生成摘要) - -v0.7.0 的目标是先修 bug,再把这三个 Aware 特性补齐,让 spec-superflow 在 7 个目标平台(Claude Code / Cursor / Codex / OpenCode / Copilot CLI / Gemini CLI / Trae)上都能一致安装和运行。 - -另外,v0.6.0 的 README 曾把部分轻微需求场景排除在外;v0.7.0 的自动模式检测正是为了让各种规模的需求都能使用 spec-superflow,无论是一次几行代码的热修复,还是跨模块的完整功能,都能自动匹配到合适的流程模式。 - -## What Changes - -- 修复 Cursor 安装:提供 Cursor 专用部署方式(`.cursor/` 目录结构或安装脚本),更新 INSTALL.md。 -- 修复 Copilot CLI 安装:把根目录 `plugin.json` 的 `author` 字段改为对象格式。 -- workflow-orchestrator 实现自动模式检测,根据变更文件数和类型推断 workflow 模式。 -- `ssf inject` 扩展为多平台注入:同时生成/更新 `.cursor/rules/`、Copilot instructions、Gemini `GEMINI.md` 等平台的阶段规则。 -- 新增 `ssf audit`(或 `ssf report`)子命令,从状态文件生成决策点审计报告。 -- 相关 skill 文件更新(workflow-orchestrator、closure-archivist 等引用新命令)。 -- 将 `templates/` 下的规划模板中文化,使设计文档与项目中文优先的约定一致。 -- 版本号 → 0.7.0 + CHANGELOG + README 更新。 - -## Capabilities - -### New Capabilities - -- `auto-mode-detection` — 自动推断 hotfix / tweak / full 模式 -- `multi-platform-phase-guard` — 一次注入,多平台阶段规则同步 -- `decision-point-audit-report` — 决策点审计报告生成 - -### Modified Capabilities - -- `platform-installation` — 修复 Cursor 和 Copilot CLI 的安装问题 -- `workflow-orchestrator` — 新增自动模式检测逻辑 -- `closure-archivist` — 支持输出/归档决策点审计报告 - -## Scope - -### In Scope - -- Cursor:`.cursor/` 目录部署或安装脚本,使 skill/rules 可被 Cursor 加载 -- Copilot CLI:根 `plugin.json` 的 `author` 格式修复 -- 自动模式检测:基于文件数、文件类型、模块变更推断 workflow -- 多平台注入:`ssf inject` 扩展生成 Cursor rules / Copilot instructions / Gemini GEMINI.md -- 决策点审计报告:读取 `dp_N_result` + `dp_N_timestamp` 生成 markdown 报告 -- 模板中文化:`templates/` 下的 `proposal.md`、`design.md`、`tasks.md`、`spec.md`、`execution-contract.md` 模板翻译成中文 -- 版本号同步到 0.7.0 - -### Out of Scope - -- 新增 skill(保持 9 个 skill 不变) -- 修改 `src/validation/validator.ts` -- CI/CD 流程变更 -- 支持 7 平台以外的客户端 - -## Impact - -- **Affected code areas**: `plugin.json`、`.cursor-plugin/`、`scripts/lib/cmd-inject.mjs`、`scripts/lib/cmd-state.mjs`(或新增 `cmd-audit.mjs`)、`skills/workflow-orchestrator/SKILL.md`、`skills/closure-archivist/SKILL.md`。 -- **Affected APIs or interfaces**: 新增/扩展 `ssf inject` 行为;可能新增 `ssf audit` 子命令;INSTALL.md 更新。 -- **Dependencies or systems touched**: Cursor 本地 `.cursor/` 目录、Copilot CLI 插件缓存、Gemini CLI 扩展上下文。 diff --git a/changes/v0.7.0-aware-and-platform-fixes/specs/auto-mode-detection/spec.md b/changes/v0.7.0-aware-and-platform-fixes/specs/auto-mode-detection/spec.md deleted file mode 100644 index ee5ada2..0000000 --- a/changes/v0.7.0-aware-and-platform-fixes/specs/auto-mode-detection/spec.md +++ /dev/null @@ -1,42 +0,0 @@ -## ADDED Requirements - -### Requirement: workflow-orchestrator auto-detects workflow mode - -`workflow-orchestrator` SHALL infer `hotfix`, `tweak`, or `full` mode when the user does not explicitly set `.spec-superflow.yaml` `workflow`. - -#### Scenario: small bug fix is detected as hotfix - -- **GIVEN** a change touches ≤2 files, does not add new modules, and does not change schemas/APIs -- **WHEN** `workflow-orchestrator` inspects the change -- **THEN** it sets `workflow: hotfix` and outputs the reason - -#### Scenario: config/doc update is detected as tweak - -- **GIVEN** a change touches ≤4 files, stays within a single module, and only modifies config, documentation, or prompts -- **WHEN** `workflow-orchestrator` inspects the change -- **THEN** it sets `workflow: tweak` and outputs the reason - -#### Scenario: larger change falls back to full - -- **GIVEN** a change touches ≥5 files or adds a new module or changes schemas/APIs -- **WHEN** `workflow-orchestrator` inspects the change -- **THEN** it keeps or sets `workflow: full` and outputs the reason - -### Requirement: explicit workflow override is preserved - -If `.spec-superflow.yaml` already has `workflow` set to a valid value, auto-detection SHALL NOT overwrite it unless the user explicitly asks to re-detect. - -#### Scenario: user sets hotfix manually - -- **GIVEN** `workflow: hotfix` is already set in state -- **WHEN** `workflow-orchestrator` runs -- **THEN** it keeps `workflow: hotfix` and skips auto-detection - -### Requirement: auto-detection inputs are content-level - -Detection SHALL use artifact content (proposal scope, task list, file paths) rather than timestamps or git status alone. - -#### Scenario: detection reads task file paths - -- **WHEN** inferring mode -- **THEN** `workflow-orchestrator` reads `tasks.md` and `proposal.md` to count scoped files diff --git a/changes/v0.7.0-aware-and-platform-fixes/specs/dp-audit-report/spec.md b/changes/v0.7.0-aware-and-platform-fixes/specs/dp-audit-report/spec.md deleted file mode 100644 index 04b53cf..0000000 --- a/changes/v0.7.0-aware-and-platform-fixes/specs/dp-audit-report/spec.md +++ /dev/null @@ -1,43 +0,0 @@ -## ADDED Requirements - -### Requirement: ssf audit generates a decision-point audit report - -A new CLI subcommand `ssf audit ` SHALL read `.spec-superflow.yaml` and produce `changes//decision-point-audit.md`. - -#### Scenario: audit report contains all 7 DPs - -- **WHEN** running `ssf audit changes/my-change` -- **THEN** the generated report lists DP-1 through DP-7 with result and timestamp - -#### Scenario: missing decision points are flagged - -- **GIVEN** a decision point has no recorded result -- **WHEN** generating the audit report -- **THEN** the report marks it as `not recorded` instead of failing - -### Requirement: Audit report format is human-readable - -The report SHALL include a summary table and a per-DP section with result, timestamp, and a brief interpretation. - -#### Scenario: report has summary table - -- **WHEN** reading `decision-point-audit.md` -- **THEN** the top of the file contains a Markdown table with DP number, name, result, timestamp - -### Requirement: closure-archivist references the audit command - -`closure-archivist` SHALL run or recommend running `ssf audit` before final closure, so the audit report is part of the archive. - -#### Scenario: closure prompts for audit - -- **WHEN** closure-archivist reaches DP-7 -- **THEN** it outputs a reminder to run `ssf audit ` and include the report in the archive - -### Requirement: Audit does not mutate state - -`ssf audit` SHALL be read-only with respect to `.spec-superflow.yaml` and planning artifacts. - -#### Scenario: audit command is safe - -- **WHEN** running `ssf audit` -- **THEN** `.spec-superflow.yaml` and all planning artifacts remain unchanged diff --git a/changes/v0.7.0-aware-and-platform-fixes/specs/multi-platform-inject/spec.md b/changes/v0.7.0-aware-and-platform-fixes/specs/multi-platform-inject/spec.md deleted file mode 100644 index 46bfe43..0000000 --- a/changes/v0.7.0-aware-and-platform-fixes/specs/multi-platform-inject/spec.md +++ /dev/null @@ -1,43 +0,0 @@ -## ADDED Requirements - -### Requirement: ssf inject supports multiple platforms - -`ssf inject ` SHALL generate phase-guard artifacts for all supported platforms by default, with an optional `--platforms` flag to limit output. - -#### Scenario: default inject updates all platforms - -- **WHEN** running `ssf inject changes/my-change` -- **THEN** `.claude/always/phase-guard.md`, `.cursor/rules/phase-guard.mdc`, `.github/copilot-instructions.md`(或 `.copilot/instructions.md`), and `GEMINI.md` 段 are all updated - -#### Scenario: limited inject updates only specified platforms - -- **WHEN** running `ssf inject changes/my-change --platforms cursor,copilot` -- **THEN** only Cursor and Copilot artifacts are updated - -### Requirement: Each platform artifact uses the correct format - -Generated files SHALL match the format expected by each platform. - -#### Scenario: Cursor rule file is .mdc with alwaysApply - -- **WHEN** `.cursor/rules/phase-guard.mdc` is generated -- **THEN** it includes frontmatter with `alwaysApply: true` and markdown body - -#### Scenario: Copilot instructions file is markdown - -- **WHEN** Copilot instructions are generated -- **THEN** the file is plain markdown with a `# Phase Guard` heading - -#### Scenario: Gemini context section is appended - -- **WHEN** Gemini context is updated -- **THEN** `GEMINI.md` contains a `# Phase Guard` section with current state - -### Requirement: Phase guard content is consistent across platforms - -All generated artifacts for the same change SHALL describe the same current state, allowed operations, forbidden operations, and active decision point. - -#### Scenario: comparing Claude and Cursor artifacts - -- **WHEN** reading `.claude/always/phase-guard.md` and `.cursor/rules/phase-guard.mdc` -- **THEN** both list the same current `state` and `workflow` diff --git a/changes/v0.7.0-aware-and-platform-fixes/specs/platform-install-fixes/spec.md b/changes/v0.7.0-aware-and-platform-fixes/specs/platform-install-fixes/spec.md deleted file mode 100644 index 525a03c..0000000 --- a/changes/v0.7.0-aware-and-platform-fixes/specs/platform-install-fixes/spec.md +++ /dev/null @@ -1,43 +0,0 @@ -## ADDED Requirements - -### Requirement: Cursor installation works out of the box - -The repository SHALL provide a Cursor-specific installation mechanism that makes the 9 skills available to Cursor Agent without relying on `.cursor-plugin/plugin.json` to auto-load skills. - -#### Scenario: user installs for Cursor - -- **WHEN** a user runs the documented Cursor install command -- **THEN** Cursor Agent can invoke `workflow-orchestrator` and the other 8 skills - -#### Scenario: Cursor rules include phase guard - -- **WHEN** `ssf inject` runs for a change -- **THEN** `.cursor/rules/phase-guard.mdc` is created/updated with the current state - -### Requirement: Copilot CLI plugin manifest is valid - -The root `plugin.json` SHALL use an object for the `author` field so that Copilot CLI strict validation does not reject the plugin. - -#### Scenario: doctor validates author field - -- **WHEN** `ssf doctor` runs -- **THEN** it reports the root `plugin.json` `author` field as valid - -#### Scenario: plugin.json author is an object - -- **WHEN** reading root `plugin.json` -- **THEN** `author.name` is present and `author` is not a string - -### Requirement: Installation docs match actual mechanism - -`INSTALL.md` SHALL describe the working installation steps for Cursor and Copilot CLI and SHALL NOT claim that unsupported auto-discovery works. - -#### Scenario: Cursor install docs mention local deploy - -- **WHEN** reading `INSTALL.md` Cursor section -- **THEN** it includes the local deploy script or manual `.cursor/` copy steps - -#### Scenario: Copilot install docs use correct marketplace path - -- **WHEN** reading `INSTALL.md` Copilot CLI section -- **THEN** it references the existing `.claude-plugin/marketplace.json` location recognized by Copilot CLI diff --git a/changes/v0.7.0-aware-and-platform-fixes/specs/template-localization/spec.md b/changes/v0.7.0-aware-and-platform-fixes/specs/template-localization/spec.md deleted file mode 100644 index c3f6e36..0000000 --- a/changes/v0.7.0-aware-and-platform-fixes/specs/template-localization/spec.md +++ /dev/null @@ -1,31 +0,0 @@ -## ADDED Requirements - -### Requirement: Planning templates are localized to Chinese - -All template files under `templates/` SHALL be provided in Chinese to match the project's Chinese-first content convention. - -#### Scenario: proposal template is Chinese - -- **WHEN** a user reads `templates/proposal.md` -- **THEN** section headings and placeholder prompts are in Chinese - -#### Scenario: design template is Chinese - -- **WHEN** a user reads `templates/design.md` -- **THEN** section headings and placeholder prompts are in Chinese - -#### Scenario: spec template remains parseable - -- **GIVEN** `templates/spec.md` is translated to Chinese -- **WHEN** `spec-forger` or `ssf validate` parses a generated spec -- **THEN** required markers such as `#### Scenario:` remain intact - -### Requirement: Localization does not break existing artifacts - -Translating the templates SHALL NOT require rewriting historical change artifacts or alter the parsing rules for `spec.md`. - -#### Scenario: historical specs still validate - -- **GIVEN** existing `changes/v0.6.0-*/specs/*/spec.md` files are in English -- **WHEN** `ssf validate` runs against them -- **THEN** they continue to pass validation diff --git a/changes/v0.7.0-aware-and-platform-fixes/tasks.md b/changes/v0.7.0-aware-and-platform-fixes/tasks.md deleted file mode 100644 index bdb59e3..0000000 --- a/changes/v0.7.0-aware-and-platform-fixes/tasks.md +++ /dev/null @@ -1,62 +0,0 @@ -# Implementation Tasks: v0.7.0 Aware & Multiplatform - -## File Structure - -``` -changes/v0.7.0-aware-and-platform-fixes/ -├── proposal.md -├── design.md -├── tasks.md -├── specs/ -│ ├── platform-install-fixes/spec.md -│ ├── auto-mode-detection/spec.md -│ ├── multi-platform-inject/spec.md -│ └── dp-audit-report/spec.md -└── execution-contract.md -``` - -## Interfaces - -- **Consumes**: `.spec-superflow.yaml`, `proposal.md`, `design.md`, specs, existing `scripts/lib/cmd-inject.mjs` template. -- **Produces**: updated `plugin.json`, `scripts/install-cursor.mjs`, `scripts/lib/cmd-inject.mjs`, `scripts/lib/cmd-audit.mjs`, updated skill files, `CHANGELOG.md`, `README.md`, version manifests. - ---- - -## Batch 1: Platform Installation Fixes - -- [x] Task 1.1: Fix root `plugin.json` `author` field from string to object. -- [x] Task 1.2: Create `scripts/install-cursor.mjs` that deploys `skills/` to `.cursor/skills/` and generates `.cursor/rules/phase-guard.mdc`. -- [x] Task 1.3: Update `INSTALL.md` Cursor and Copilot CLI sections with correct steps. -- [x] Task 1.4: Extend `ssf doctor` to validate root `plugin.json` `author` format. -- [x] Task 1.5: Run `npm run build` and `npm test` to ensure no regressions. - -## Batch 2: Auto Mode Detection - -- [x] Task 2.1: Add mode inference logic to `skills/workflow-orchestrator/SKILL.md`. -- [x] Task 2.2: Create `scripts/infer-workflow.mjs` helper to count files/modules from `proposal.md` and `tasks.md`. -- [x] Task 2.3: Add example or test case for hotfix/tweak/full inference. - -## Batch 3: Multi-Platform Phase-Guard Injection - -- [x] Task 3.1: Extend `scripts/lib/cmd-inject.mjs` with `PLATFORM_TEMPLATES`. -- [x] Task 3.2: Implement Cursor `.mdc` generation. -- [x] Task 3.3: Implement Copilot instructions generation. -- [x] Task 3.4: Implement Gemini `GEMINI.md` section update. -- [x] Task 3.5: Add `--platforms` CLI flag to `ssf inject`. -- [x] Task 3.6: Update `skills/workflow-orchestrator/SKILL.md` post-transition prompt to mention multi-platform inject. - -## Batch 4: Decision Point Audit Report - -- [x] Task 4.1: Create `scripts/lib/cmd-audit.mjs` with `ssf audit` command. -- [x] Task 4.2: Generate `decision-point-audit.md` template. -- [x] Task 4.3: Update `skills/closure-archivist/SKILL.md` to reference `ssf audit`. -- [x] Task 4.4: Ensure `ssf audit` is read-only and idempotent. - -## Batch 5: Release - -- [x] Task 5.1: Bump version to 0.7.0 in `package.json`, `plugin.json`, `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json`, `.cursor-plugin/plugin.json`, `gemini-extension.json`. -- [x] Task 5.2: Translate `templates/proposal.md`, `templates/design.md`, `templates/tasks.md`, `templates/spec.md`, `templates/execution-contract.md` to Chinese. -- [x] Task 5.3: Update `CHANGELOG.md` with v0.7.0 entries. -- [x] Task 5.4: Update `README.md` with new CLI commands and platform install notes. -- [x] Task 5.5: Run `ssf doctor` and `ssf validate`. -- [x] Task 5.6: Build, test, commit, tag `v0.7.0`, push to GitHub, refresh marketplace. diff --git a/changes/v0.8.0-intuitive-skills/.spec-superflow.yaml b/changes/v0.8.0-intuitive-skills/.spec-superflow.yaml deleted file mode 100644 index ad4ad88..0000000 --- a/changes/v0.8.0-intuitive-skills/.spec-superflow.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# .spec-superflow.yaml — lightweight state machine -# Derived data. Always rebuildable from artifacts. Lost/corrupt → fall back to content-level detection. - -# === Core state === -state: exploring -workflow: auto - -# === Hashes (fast staleness detection) === -artifacts_hash: sha256:1c80fa372fbf58106ef36e23e0360038811d80e0b4d363a8bdb3133b2a8a3dc1 -contract_hash: sha256:d198c87e703769d500075f1a40f9abf96a61e1a08341292c19c13521ea336656 - -# === Execution progress === -execution_mode: null -batches_completed: 0 -test_result: null - -# === Metadata === -change_name: v0.8.0-intuitive-skills -last_transition: 2026-06-30T15:17:45.880Z -last_transition_from: null -last_transition_to: null - -# === Decision points === -dp_1_result: null -dp_1_timestamp: null -dp_2_result: null -dp_2_timestamp: null -dp_3_result: null -dp_3_timestamp: null -dp_4_result: null -dp_4_timestamp: null -dp_5_result: null -dp_5_timestamp: null -dp_6_result: null -dp_6_timestamp: null -dp_7_result: null -dp_7_timestamp: null diff --git a/changes/v0.8.0-intuitive-skills/decision-point-audit.md b/changes/v0.8.0-intuitive-skills/decision-point-audit.md deleted file mode 100644 index eece2ec..0000000 --- a/changes/v0.8.0-intuitive-skills/decision-point-audit.md +++ /dev/null @@ -1,67 +0,0 @@ -# Decision-Point Audit Report - -**变更**: v0.8.0-intuitive-skills -**生成时间**: 2026-07-01T02:48:49.700Z -**当前状态**: exploring - -## 汇总表 - -| DP | 名称 | 结果 | 时间戳 | -|----|------|------|--------| -| DP-1 | 需求确认 | not recorded | — | -| DP-2 | 工件审查 | not recorded | — | -| DP-3 | 契约批准 | not recorded | — | -| DP-4 | 执行模式选择 | not recorded | — | -| DP-5 | 调试升级 | not recorded | — | -| DP-6 | 验证失败 | not recorded | — | -| DP-7 | 归档确认 | not recorded | — | - -**统计**: 0/7 已记录,7/7 未记录。 - -## 逐决策点说明 - -### DP-1: 需求确认 - -- **结果**: not recorded -- **时间戳**: — -- **解读**: 该决策点尚未记录结果。如果工作流已经经过该阶段,请检查是否漏记。 - -### DP-2: 工件审查 - -- **结果**: not recorded -- **时间戳**: — -- **解读**: 该决策点尚未记录结果。如果工作流已经经过该阶段,请检查是否漏记。 - -### DP-3: 契约批准 - -- **结果**: not recorded -- **时间戳**: — -- **解读**: 该决策点尚未记录结果。如果工作流已经经过该阶段,请检查是否漏记。 - -### DP-4: 执行模式选择 - -- **结果**: not recorded -- **时间戳**: — -- **解读**: 该决策点尚未记录结果。如果工作流已经经过该阶段,请检查是否漏记。 - -### DP-5: 调试升级 - -- **结果**: not recorded -- **时间戳**: — -- **解读**: 该决策点尚未记录结果。如果工作流已经经过该阶段,请检查是否漏记。 - -### DP-6: 验证失败 - -- **结果**: not recorded -- **时间戳**: — -- **解读**: 该决策点尚未记录结果。如果工作流已经经过该阶段,请检查是否漏记。 - -### DP-7: 归档确认 - -- **结果**: not recorded -- **时间戳**: — -- **解读**: 该决策点尚未记录结果。如果工作流已经经过该阶段,请检查是否漏记。 - ---- - -*本报告由 `ssf audit` 自动生成,仅供审计与归档参考。* diff --git a/changes/v0.8.0-intuitive-skills/design.md b/changes/v0.8.0-intuitive-skills/design.md deleted file mode 100644 index c751fd8..0000000 --- a/changes/v0.8.0-intuitive-skills/design.md +++ /dev/null @@ -1,145 +0,0 @@ -# 设计文档 - -## 目标 - -1. 让 9 个 skill 的名字“见名知意”,降低新用户认知成本。 -2. 解决 issue #5 中反映的小型前端类需求执行耗时过长的问题,通过“批量内联执行”减少 subagent 调度。 -3. 修复 workflow 设计缺陷:在 `specifying` 阶段前增加用户确认门禁(DP-0),避免未沟通就写方案。 -4. 同步更新各 AI 平台的插件安装说明,确保与 v0.8.0 skill 名称和安装方式一致。 - -## Skill 重命名映射 - -| 旧名称 | 新名称 | 含义 | -|--------|--------|------| -| `workflow-orchestrator` | `workflow-start` | 工作流入口,决定下一步走哪个 skill | -| `spec-explorer` | `need-explorer` | 需求探索,澄清需求、比较方案 | -| `spec-forger` | `spec-writer` | 规格撰写,产出 proposal/specs/design/tasks | -| `bridge-contract` | `contract-builder` | 契约构建,把规划工件压缩成 execution-contract | -| `execution-governor` | `build-executor` | 构建执行,按契约实现代码 | -| `systematic-debugger` | `bug-investigator` | 缺陷调查,4 阶段根因调试 | -| `code-reviewer` | `code-reviewer` | 代码审查,保持不变 | -| `closure-archivist` | `release-archivist` | 发布归档,收尾验证与归档 | -| `spec-syncer` | `spec-merger` | 规格合并,把 delta spec 合并进主规格 | - -## 命名原则 - -- 动作 + 对象:如 `spec-writer`、`contract-builder`、`bug-investigator`。 -- 保留唯一入口:`workflow-start` 直接说明它是工作流的启动入口。 -- 不出现生僻词:去掉 `orchestrator`、`forger`、`archivist` 等需要额外解释的词汇。 -- 不引入空格:所有目录名保持 kebab-case,与 Claude Code skill 加载规则兼容。 - -## 影响面 - -### 必须同步的文件 - -1. `skills/` 目录重命名。 -2. 每个 skill 的 `SKILL.md` frontmatter `name`。 -3. Skill 内部互相引用的名称,例如 `workflow-start/SKILL.md` 中的路由目标、`release-archivist/SKILL.md` 中对 `spec-merger` 的引用。 -4. `docs/state-machine.md` 各状态关联的 skill 名称。 -5. `docs/decision-points.md` 决策点映射表。 -6. `README.md`、`INSTALL.md`、`CLAUDE.md` 中所有示例和说明。 -7. `docs/examples/` 中引用旧 skill 名的 README 或说明。 -8. 新增 `docs/skill-rename-v0.8.0.md` 迁移对照表。 -9. 所有 plugin manifest: - - `.claude-plugin/plugin.json` - - `.claude-plugin/marketplace.json` - - `.cursor-plugin/plugin.json` - - `.codex-plugin/plugin.json` - - `gemini-extension.json` - - root `plugin.json` - -### 不修改的内容 - -- `src/` 引擎的 API 与类型。 -- `scripts/` 中不依赖 skill 名称的逻辑(如 `guard.mjs`、`cmd-*.mjs`)。 - -## 用户确认门禁(DP-0)设计 - -### 问题 - -当前 `workflow-start` 在检测到需求不清时才会提问,一旦需求明确就直接路由到 `spec-writer` 生成工件。这导致 agent 可能在用户还没确认命名风格、范围取舍、兼容性策略等关键决策时,就把完整方案写好了。 - -### 方案 - -在 `workflow-start` 中增加一个**设计前确认门禁(DP-0)**: - -- 当规划工件不存在或不完整时,先向用户确认: - 1. 变更名称与范围。 - 2. 是否有已知约束(如命名风格、兼容性策略、受影响平台)。 - 3. 是否包含相关优化(如本次 issue #5 的 Batch Inline)。 - 4. 用户偏好:是先问清楚再写方案,还是先给草案再迭代。 -- 确认结果写入 `.spec-superflow.yaml` 的 `dp_0_decisions`、`dp_0_confirmed`、`dp_0_timestamp`。 -- `spec-writer` 在生成工件前读取 `dp_0_*`,尊重已确认决策;遇到未覆盖决策时暂停并提问。 - -### 需要修改的工件 - -- `skills/workflow-start/SKILL.md`:增加 DP-0 检查与提问流程。 -- `skills/spec-writer/SKILL.md`:增加读取 `dp_0_*` 的约束。 -- `specs/user-confirmation-gate/spec.md`:规范 DP-0 行为。 -- `scripts/lib/state-loader.mjs`:确保 `dp_0_decisions`、`dp_0_confirmed`、`dp_0_timestamp` 在 `SETTABLE_FIELDS` 中。 - -## 各 AI 平台安装说明同步 - -### 需要更新的文件 - -- `README.md`:skill 列表、入口命令、版本号、平台表格。 -- `INSTALL.md`:Claude Code、Cursor、Copilot CLI、Gemini CLI 的安装步骤,需使用新的 skill 名称和 v0.8.0 安装脚本。 -- `docs/skill-rename-v0.8.0.md`:迁移文档中包含各平台重新安装或刷新插件的说明。 - -### 注意事项 - -- `.cursor/` 目录是 `scripts/install-cursor.mjs` 在用户本地生成的运行时配置,已加入 `.gitignore`,不应提交到仓库。 -- 各平台 manifest 中的 `skills` 字段必须指向新的目录名,否则客户端无法加载。 - -## 批量内联执行(Batch Inline)设计 - -### 问题 - -Issue #5 中,light/dark 模式这类单模块、低风险的前端需求被拆成过多细小任务,每个任务都走“dispatch implementer → review → fix”的 SDD 流程,subagent 往返开销占比过高。 - -### 方案 - -在 `build-executor` 中增加 `Batch Inline` 模式: - -- 当任务数量超过 `Inline` 阈值(3 个),但所有任务都在同一模块、风险低、总预估 ≤ 15 分钟时,直接在当前会话按批次执行。 -- 不 dispatch 单个 task subagent,由当前 agent 顺序完成一批任务。 -- 仍然遵守 TDD:先写/改失败测试,再实现,再跑绿。 -- 批次结束后做一次轻量 checkpoint:文件存在、无占位符、测试通过、无越界修改。 - -### 触发条件 - -自动选择优先级: - -1. 用户显式选择 `Inline` / `Batch Inline` / `SDD` → 尊重用户。 -2. 任务 ≤ 3 且无跨模块依赖 → `Inline`。 -3. 任务 > 3、全部同模块、无 schema/API/配置变更、总预估 ≤ 15 分钟 → `Batch Inline`。 -4. 其他 → `SDD`。 - -### 与现有 Inline 模式的区别 - -| 维度 | Inline | Batch Inline | SDD | -|------|--------|--------------|-----| -| 任务数 | ≤ 3 | > 3 但同模块 | 任意 | -| 执行会话 | 当前会话 | 当前会话 | subagent | -| subagent 数 | 0 | 0 | 每任务/每批次 | -| TDD | 每任务 | 批次内保持 | 每任务 | -| 适用场景 | 极小改动 | 单模块小功能 | 多模块/高风险 | - -### 需要修改的工件 - -- `skills/build-executor/SKILL.md`:增加 Batch Inline 选择逻辑与 checkpoint。 -- `templates/execution-contract.md`:Execution Mode 增加 `Batch Inline`。 -- `specs/inline-execution/spec.md`:扩展模式说明。 -- 新增 `specs/execution-lean/spec.md`:独立描述 Batch Inline 行为。 - -## 迁移兼容性 - -v0.8.0 是 breaking change:旧 skill 名称不再可用。通过新增 `docs/skill-rename-v0.8.0.md` 帮助已升级用户迁移。 - -## 测试策略 - -1. `ssf doctor` 通过:skill 目录与 manifest 一致、版本一致。 -2. `ssf validate changes/v0.8.0-intuitive-skills` 通过。 -3. `npm run build && npm test` 通过。 -4. 手动检查 `workflow-start/SKILL.md` 中所有路由引用指向新名称。 -5. 手动检查 plugin manifests 中 skill 路径正确。 diff --git a/changes/v0.8.0-intuitive-skills/execution-contract.md b/changes/v0.8.0-intuitive-skills/execution-contract.md deleted file mode 100644 index 7cd5c1c..0000000 --- a/changes/v0.8.0-intuitive-skills/execution-contract.md +++ /dev/null @@ -1,134 +0,0 @@ -# 执行合同 - -## Intent Lock - -- **变更名称**:v0.8.0 intuitive skill names + Batch Inline execution -- **要解决的问题**: - 1. 当前 skill 名字不够直观,`workflow-orchestrator` 等入口难以记忆。 - 2. issue #5 反馈的小型前端需求(light/dark 模式)执行耗时过长,subagent 调度开销大。 -- **范围内**: - - 9 个 skill 目录重命名(入口改为 `workflow-start`)。 - - 所有 `SKILL.md` frontmatter、skill 内部引用同步。 - - `docs/state-machine.md`、`docs/decision-points.md`、`README.md`、`INSTALL.md`、`CLAUDE.md` 同步。 - - 新增 `docs/skill-rename-v0.8.0.md` 迁移文档。 - - 所有 plugin manifest 更新 skill 清单并升级到 `0.8.0`。 - - `build-executor` 增加 `Batch Inline` 模式,相关 spec 与模板更新。 - - `docs/examples/` 中的旧 skill 名同步更新。 -- **范围外**: - - 修改 `src/` 引擎 API。 - - 新增 workflow state。 - - 修改 skill 核心执行逻辑(Batch Inline 选择逻辑除外)。 - -## Approved Behavior - -- **已批准需求摘要**: - - Skill 重命名:所有 skill 使用“动作+对象”风格,入口为 `workflow-start`。 - - 彻底移除旧名,不提供 alias。 - - Batch Inline:对同模块、低风险、总预估 ≤15 分钟的任务批次,允许在当前会话顺序执行,不 dispatch 单任务 subagent。 -- **关键场景**: - - 用户输入 `/workflow-start` 触发入口。 - - 小型前端类需求自动或手动进入 `Batch Inline` 模式。 -- **验收检查**: - - `ssf doctor` 通过。 - - `ssf validate changes/v0.8.0-intuitive-skills` 通过。 - - `npm run build && npm test` 通过。 - - 所有 manifest 中 skill 路径正确。 - - 旧 skill 目录不存在。 - -## Design Constraints - -- **架构约束**:保持现有 7+1 state machine 不变。 -- **接口约束**:skill 名称作为客户端调用标识会改变;旧名不可用。 -- **依赖约束**:插件客户端(Claude Code / Cursor / Copilot / Gemini)通过 manifest 发现 skill,manifest 必须正确。 -- **数据约束**:现有示例变更集可同步更新旧名引用,但不改动其历史意图。 - -## Task Batches - -### Batch 1 - -- **目标**:完成 skill 目录重命名与 frontmatter 更新。 -- **输入**:当前 `skills/` 目录。 -- **输出**:`skills/workflow-start/`、`skills/need-explorer/`、`skills/spec-writer/`、`skills/contract-builder/`、`skills/build-executor/`、`skills/bug-investigator/`、`skills/release-archivist/`、`skills/spec-merger/`、`skills/code-reviewer/`。 -- **完成标准**:目录重命名完成,每个 `SKILL.md` 的 `name` frontmatter 已更新。 - -### Batch 2 - -- **目标**:更新 skill 内部互相引用的名称。 -- **输入**:Batch 1 产出的新目录。 -- **输出**:`workflow-start/SKILL.md` 等文件中的路由与引用指向新名。 -- **完成标准**:`grep` 旧名在 `skills/` 下无命中(允许历史注释除外)。 - -### Batch 3 - -- **目标**:同步文档、manifests、示例。 -- **输入**:Batch 2 产出的已更新 skill。 -- **输出**:`docs/`、`README.md`、`INSTALL.md`、`CLAUDE.md`、plugin manifests、示例全部使用新名。 -- **完成标准**:`ssf doctor` 版本与 skill 检查通过。 - -### Batch 4 - -- **目标**:实现 Batch Inline 模式并发布 v0.8.0。 -- **输入**:Batch 3 同步后的工程。 -- **输出**:`build-executor/SKILL.md` 增加 Batch Inline、`templates/execution-contract.md` 增加模式选项、新增/更新 spec、版本号 0.8.0、CHANGELOG 更新。 -- **完成标准**:`npm test` 通过,tag `v0.8.0` 已推送,GitHub Release 与 npm 发布完成。 - -### Batch 5 - -- **目标**:收尾归档。 -- **输入**:已发布版本。 -- **输出**:`decision-point-audit.md`、跨平台 phase-guard 注入。 -- **完成标准**:`ssf audit` 与 `ssf inject` 完成并提交。 - -## Test Obligations - -- **必须先从失败测试开始的行为**: - - Batch Inline 模式必须仍遵循 TDD:先写/改失败测试,再实现,再确认通过。 -- **必需的边界情况**: - - 跨模块任务不得进入 Batch Inline。 - - 用户显式选择 SDD 时不得自动降级为 Batch Inline。 - - 旧 skill 目录重命名后,manifest 中路径错误会导致 doctor 失败。 -- **回归敏感区域**: - - `skills/` 内部引用 - - plugin manifests - - `docs/decision-points.md` 映射表 - -## Execution Mode - -- **模式**:`SDD` -- **选择理由**: - - 本次变更涉及大量文件重命名、文档同步、manifest 更新,跨越多个模块(skills、docs、scripts 不直接改但 manifests 涉及)。 - - 需要多批次提交与最终发布流程,适合 SDD 的 subagent/批次审查机制。 - - Batch Inline 模式作为本次新增能力,将在测试验证阶段 itself 被使用,但不改变本次变更整体采用 SDD。 - -## Verification Dimensions - -| 维度 | 状态 | 发现 | -|------|------|------| -| Completeness | Pending | — | -| Correctness | Pending | — | -| Coherence | Pending | — | - -**总体结论**:Pending - -## Review Gates - -- **强制审查点**: - - Batch 1 完成后:确认目录重命名无遗漏。 - - Batch 2 完成后:确认 skill 内部引用已全局替换。 - - Batch 3 完成后:确认 `ssf doctor` 通过。 - - Batch 4 完成后:确认 `npm test` 与发布流程通过。 -- **阻塞类别**: - - 任何旧 skill 目录残留。 - - manifest 中 skill 路径错误。 - - 测试失败。 - -## Escalation Rules - -- **何时回退到 `specifying`**: - - 如果决定调整命名映射或新增/移除 skill。 -- **何时回退到 `bridging`**: - - 如果 Batch Inline 的触发条件或范围发生重大变化。 -- **何时不得继续实现**: - - `ssf doctor` 未通过。 - - 旧 skill 目录未完全移除。 - - 版本号未统一。 diff --git a/changes/v0.8.0-intuitive-skills/proposal.md b/changes/v0.8.0-intuitive-skills/proposal.md deleted file mode 100644 index 4dbd1e3..0000000 --- a/changes/v0.8.0-intuitive-skills/proposal.md +++ /dev/null @@ -1,62 +0,0 @@ -# 变更提案 - -## Why - -当前 9 个 skill 的名字(`workflow-orchestrator`、`spec-forger`、`bridge-contract` 等)对用户不够直观,尤其是入口 skill `workflow-orchestrator`,用户很难从名字判断它是工作流的触发入口。名字晦涩增加了学习成本,也削弱了“看到名字就知道作用”的目标。 - -另外,GitHub issue #5 反馈:给一个 demo 前端项目增加 light/dark 模式,整个工作流跑了约 4 小时,主要原因是执行阶段频繁调用自定义 subagent 完成 plan 中的任务。对于类似的小型、单模块、前端类需求,subagent 调度开销过大,需要一种更轻量的执行方式来减少往返耗时。 - -v0.8.0 把这几个问题放在一起解决: -1. 重命名全部 skill,使名字“见名知意”。 -2. 引入“批量内联执行”优化,降低小型变更的 subagent 调用次数。 -3. 修复 workflow 设计缺陷:在 `specifying` 阶段前增加用户确认门禁,避免未沟通就写方案。 -4. 同步更新各 AI 平台(Claude Code / Cursor / Copilot CLI / Gemini CLI 等)的插件安装说明,确保与 v0.8.0 skill 名称和安装方式一致。 - -## What Changes - -- 重命名 `skills/` 下所有 skill 目录;入口 skill 由 `workflow-orchestrator` 改为 `workflow-start`。 -- 更新所有 skill 的 `SKILL.md` frontmatter 中的 `name` 字段。 -- 更新 `workflow-start` 等 skill 内部相互引用的 skill 名称。 -- 更新 `docs/state-machine.md`、`docs/decision-points.md`、`README.md`、`INSTALL.md`、`CLAUDE.md` 中对这些 skill 的引用。 -- 更新 `.claude-plugin/plugin.json`、`.cursor-plugin/plugin.json`、`.codex-plugin/plugin.json`、root `plugin.json`、`gemini-extension.json` 中的 skill 清单。 -- 在 `workflow-start` 和 `spec-writer` 中增加“用户确认门禁”:进入设计前必须确认关键决策(命名、范围、兼容性、沟通方式等)。 -- 新增 `specs/user-confirmation-gate/spec.md`,规范 DP-0 / 设计前确认步骤。 -- 更新 `INSTALL.md` 与 `README.md` 中 Claude Code、Cursor、Copilot CLI、Gemini CLI 等平台的安装说明,确保与 v0.8.0 的 skill 名称和实际安装脚本一致。 -- 在 `build-executor` 中新增“批量内联执行(Batch Inline)”模式:当任务属于同一模块、风险低、且用户未强制要求 SDD 时,可把一批任务合并为一次当前会话执行,避免每个任务都 dispatch subagent。 -- 更新 `specs/inline-execution/spec.md`,加入 Batch Inline 的触发条件与约束。 -- 新增 `specs/execution-lean/spec.md`,规范批量执行行为。 -- 更新 `templates/execution-contract.md`,增加 Execution Mode 选项:`Inline`、`Batch Inline`、`SDD`。 - -## 能力(Capabilities) - -### 新增能力 - -- batch-inline-execution — 对同模块、低风险的多个任务进行批量当前会话执行,减少 subagent 调度。 -- user-confirmation-gate — 进入设计前强制确认关键决策,避免未沟通就写方案。 - -### 修改能力 - -- skill-discovery — skill 目录与 frontmatter 名称全部改为直观名称,降低认知负担。 - -## 范围(Scope) - -### 范围内(In Scope) - -- 9 个 skill 的目录重命名与内部引用同步。 -- 文档、manifest、模板中的 skill 名称同步。 -- `build-executor` 增加 Batch Inline 模式及相关 spec 更新。 -- workflow 用户确认门禁(DP-0)纳入 `workflow-start` 与 `spec-writer`。 -- 各 AI 平台安装说明(`README.md` / `INSTALL.md`)同步到 v0.8.0。 -- 版本号统一升级到 `0.8.0`。 - -### 范围外(Out of Scope) - -- 修改 skill 的核心执行逻辑(除 Batch Inline 外)。 -- 新增新的 workflow state。 -- 修改 OpenSpec 引擎(`src/`)的 API。 - -## 影响(Impact) - -- 影响的代码区域:`skills/`、plugin manifests、`docs/`、`templates/`、`README.md`、`INSTALL.md`、`CLAUDE.md`。 -- 影响的 API 或接口:skill 名称作为 Claude Code / Cursor / Copilot 等客户端的调用标识会改变;旧名称不再可用。 -- 依赖或涉及的外部系统:Claude Code plugin market、Cursor plugin、npm 包(通过 manifest 引用 skill 路径)。 diff --git a/changes/v0.8.0-intuitive-skills/specs/execution-lean/spec.md b/changes/v0.8.0-intuitive-skills/specs/execution-lean/spec.md deleted file mode 100644 index 86a03fd..0000000 --- a/changes/v0.8.0-intuitive-skills/specs/execution-lean/spec.md +++ /dev/null @@ -1,90 +0,0 @@ -# 能力规格 - -## ADDED Requirements - -### Requirement: Batch Inline Execution Mode - -`execution-governor` SHALL support a `Batch Inline` execution mode for low-risk, same-module tasks so that multiple small tasks can be completed in the current session without dispatching one subagent per task. - -#### Scenario: Activation conditions - -- **WHEN** the execution contract specifies `Execution Mode: Batch Inline` or the governor auto-selects it -- **AND** all tasks in the batch modify files within the same module or directory -- **AND** no task introduces a new public API, schema, or cross-module interface -- **AND** the total estimated effort of the batch is ≤ 15 minutes -- **THEN** `execution-governor` SHALL execute the entire batch in the current session -- **AND** SHALL NOT dispatch an implementer subagent for each individual task - -#### Scenario: User override - -- **WHEN** the user explicitly says "use SDD" or "use Inline" -- **THEN** `execution-governor` SHALL respect the override and SHALL NOT select Batch Inline - -### Requirement: Batch Inline Preserves TDD Iron Law - -Even in Batch Inline mode, every code-producing task SHALL follow the TDD cycle. - -#### Scenario: Batch-level TDD - -- **WHEN** executing a batch of tasks in Batch Inline mode -- **THEN** the governor SHALL write or update failing tests for the first code change in the batch -- **AND** run tests to confirm failure -- **AND** implement the minimal changes across the batch to make tests pass -- **AND** run the full relevant test suite to confirm green -- **AND** SHALL NOT treat the absence of per-task subagent as an excuse to skip RED/GREEN/REFACTOR - -### Requirement: Batch Inline Checkpoint - -After a Batch Inline batch completes, the governor SHALL perform a lightweight checkpoint review before moving to the next batch or closure. - -#### Scenario: Checkpoint content - -- **WHEN** a Batch Inline batch finishes -- **THEN** the governor SHALL verify: - 1. All files declared in the batch exist and are non-empty. - 2. No placeholder markers remain in modified files. - 3. At least one relevant test was run and passed. - 4. No unintended files were modified. -- **AND** SHALL report the checkpoint result to the user - -### Requirement: Batch Inline Boundaries - -Batch Inline SHALL NOT be used when risk indicators are present. - -#### Scenario: Risk escalation - -- **WHEN** any task in the planned batch touches more than one module -- **OR** any task involves schema, API, or configuration changes -- **OR** any task has open questions or dependencies on unimplemented behavior -- **THEN** `execution-governor` SHALL downgrade to `Inline` or `SDD` mode -- **AND** SHALL report the reason for not using Batch Inline - -## MODIFIED Requirements - -### Requirement: Execution Mode Selection Criteria - -The automatic mode selection in `execution-governor` SHALL consider Batch Inline as an intermediate option between Inline and SDD. - -#### Scenario: Auto-selection with batch inline - -- **WHEN** `execution-governor` receives an approved contract -- **THEN** it SHALL analyze task count, module boundaries, and risk indicators -- **AND** select modes as follows: - - Tasks ≤ 3 and no cross-module dependencies → **Inline** - - Tasks > 3 but all within same module, low risk, total estimated ≤ 15 min → **Batch Inline** - - Cross-module dependencies or high-risk changes → **SDD** -- **AND** SHALL report selected mode and reasoning before execution - -### Requirement: execution-contract.md Mode Field - -The `Execution Mode` field in `execution-contract.md` SHALL accept `Batch Inline` in addition to `Inline` and `SDD`. - -#### Scenario: Contract validation - -- **WHEN** `bridge-contract` generates or updates `execution-contract.md` -- **THEN** it SHALL allow `Execution Mode: Batch Inline` -- **AND** it SHALL include a note explaining why Batch Inline is or is not selected - -## REMOVED Requirements - -None. diff --git a/changes/v0.8.0-intuitive-skills/specs/skill-rename/spec.md b/changes/v0.8.0-intuitive-skills/specs/skill-rename/spec.md deleted file mode 100644 index 050d8c6..0000000 --- a/changes/v0.8.0-intuitive-skills/specs/skill-rename/spec.md +++ /dev/null @@ -1,80 +0,0 @@ -# 能力规格 - -## ADDED Requirements - -### Requirement: Intuitive Skill Names - -All 9 skills SHALL have directory names and `SKILL.md` frontmatter `name` values that describe their role at a glance. - -#### Scenario: Skill name mapping - -- **WHEN** a user or script looks at `skills/` -- **THEN** each directory name SHALL clearly indicate its workflow role -- **AND** the mapping from old names to new names SHALL be documented in `docs/skill-rename-v0.8.0.md` - -#### Scenario: Old names removed - -- **WHEN** a user invokes a skill by its old name -- **THEN** the invocation SHALL fail (no alias retained) -- **AND** the error or documentation SHALL point to the new name - -### Requirement: Manifest Skill List Synchronization - -Every plugin manifest that lists skills SHALL use the new names and paths. - -#### Scenario: Claude plugin manifest - -- **WHEN** `.claude-plugin/plugin.json` and `.claude-plugin/marketplace.json` are loaded -- **THEN** they SHALL reference the new skill directory names under `skills/` -- **AND** no reference to the old names SHALL remain - -#### Scenario: Cursor / Copilot / Gemini manifests - -- **WHEN** `.cursor-plugin/plugin.json`, `.codex-plugin/plugin.json`, `gemini-extension.json`, and root `plugin.json` are loaded -- **THEN** they SHALL reference the new skill directory names -- **AND** the `version` field SHALL be bumped to `0.8.0` - -## MODIFIED Requirements - -### Requirement: Internal Skill Cross-References - -Skill `SKILL.md` files that route to other skills SHALL use the new names. - -#### Scenario: workflow-start routing references - -- **WHEN** `workflow-start` (formerly `workflow-orchestrator`) routes to the next skill -- **THEN** it SHALL reference the new names such as `spec-superflow:need-explorer`, `spec-superflow:spec-writer`, `spec-superflow:contract-builder`, etc. - -#### Scenario: closure-archivist spec-syncer reference - -- **WHEN** `release-archivist` (formerly `closure-archivist`) invokes the spec merge step -- **THEN** it SHALL reference `spec-superflow:spec-merger` - -### Requirement: Documentation Name Consistency - -All documentation that names a skill SHALL use the new names. - -#### Scenario: state-machine.md - -- **WHEN** `docs/state-machine.md` describes which skill is active in each state -- **THEN** it SHALL use the new names - -#### Scenario: decision-points.md - -- **WHEN** `docs/decision-points.md` lists associated skills in the mapping table -- **THEN** it SHALL use the new names - -#### Scenario: README and INSTALL - -- **WHEN** `README.md` and `INSTALL.md` mention skill names or usage examples -- **THEN** they SHALL use the new names - -## REMOVED Requirements - -### Requirement: Legacy skill directory names - -The old skill directory names SHALL no longer exist. - -**Reason**: They are replaced by intuitive names that reduce cognitive load. - -**Migration**: See `docs/skill-rename-v0.8.0.md` for the full old→new mapping. diff --git a/changes/v0.8.0-intuitive-skills/specs/user-confirmation-gate/spec.md b/changes/v0.8.0-intuitive-skills/specs/user-confirmation-gate/spec.md deleted file mode 100644 index f0665f0..0000000 --- a/changes/v0.8.0-intuitive-skills/specs/user-confirmation-gate/spec.md +++ /dev/null @@ -1,75 +0,0 @@ -# 能力规格 - -## ADDED Requirements - -### Requirement: User Confirmation Gate Before Design - -`workflow-start` SHALL require user confirmation of key decisions before routing to `spec-writer` for artifact generation. - -#### Scenario: First contact with a new change - -- **WHEN** `workflow-start` detects that planning artifacts do not exist or are incomplete -- **AND** the user has not yet confirmed scope and key decisions -- **THEN** `workflow-start` SHALL pause routing -- **AND** SHALL ask the user at least the following: - 1. What is the change name / scope? - 2. Are there any known constraints (e.g., naming style, compatibility policy, platforms affected)? - 3. Should this change include related optimizations (e.g., issue #5 Batch Inline) or stay focused? - 4. Does the user prefer to be asked before each design decision, or receive a draft for review? -- **AND** SHALL record confirmed decisions in `.spec-superflow.yaml` under `dp_0_*` fields or equivalent notes -- **AND** SHALL NOT route to `spec-writer` until the user explicitly confirms - -#### Scenario: Resuming an existing change - -- **WHEN** `workflow-start` detects that `dp_0_confirmed` is `true` in `.spec-superflow.yaml` -- **THEN** it SHALL skip the confirmation gate -- **AND** proceed with normal state detection and routing - -### Requirement: Spec-Writer Honors Confirmed Decisions - -`spec-writer` SHALL read confirmed decisions from the state file before generating or revising artifacts. - -#### Scenario: Generating proposal.md - -- **WHEN** `spec-writer` begins writing `proposal.md` -- **THEN** it SHALL first read `.spec-superflow.yaml` for `dp_0_*` notes -- **AND** SHALL respect confirmed constraints (e.g., naming style, scope inclusions) -- **AND** SHALL NOT silently expand scope beyond what was confirmed - -#### Scenario: Detecting unconfirmed decisions - -- **WHEN** `spec-writer` encounters a decision that was not covered by the confirmation gate -- **THEN** it SHALL pause artifact generation -- **AND** SHALL ask the user the specific question before continuing - -### Requirement: State Fields for DP-0 - -`.spec-superflow.yaml` SHALL support a `dp_0` section to record the design-confirmation gate. - -#### Scenario: State initialization - -- **WHEN** `ssf state init ` runs -- **THEN** it SHALL create empty `dp_0_decisions` and `dp_0_confirmed` fields - -#### Scenario: Confirming the gate - -- **WHEN** the user confirms the design-preparation questions -- **THEN** `workflow-start` SHALL run `ssf state set dp_0_confirmed true` -- **AND** SHALL run `ssf state set dp_0_decisions ""` -- **AND** SHALL run `ssf state set dp_0_timestamp ` - -## MODIFIED Requirements - -### Requirement: Workflow Routing Updated - -`workflow-start/SKILL.md` SHALL include the confirmation gate in its routing rules. - -#### Scenario: Routing to spec-writer - -- **WHEN** `workflow-start` would normally route to `spec-writer` -- **THEN** it SHALL first check `dp_0_confirmed` -- **AND** if not confirmed, ask the user the required questions - -## REMOVED Requirements - -None. diff --git a/changes/v0.8.0-intuitive-skills/tasks.md b/changes/v0.8.0-intuitive-skills/tasks.md deleted file mode 100644 index 88b0089..0000000 --- a/changes/v0.8.0-intuitive-skills/tasks.md +++ /dev/null @@ -1,260 +0,0 @@ -# 实现任务 - -## 文件结构 - -- `Modify: skills/workflow-start/SKILL.md` — 更新 frontmatter name、内部引用,并增加 DP-0 用户确认门禁 -- `Modify: skills/spec-writer/SKILL.md` — 读取 `dp_0_*` 约束 -- `Create: specs/user-confirmation-gate/spec.md` — DP-0 规范 -- `Modify: scripts/lib/state-loader.mjs` — 加入 `dp_0_*` 可设置字段 -- `Modify: docs/state-machine.md` — 同步 skill 名称 -- `Modify: docs/decision-points.md` — 同步决策点映射表 -- `Create: docs/skill-rename-v0.8.0.md` — 迁移对照表 -- `Modify: README.md`、`INSTALL.md`、`CLAUDE.md` — 同步引用、示例与各 AI 平台安装说明 -- `Modify: .claude-plugin/plugin.json`、`.claude-plugin/marketplace.json`、`.cursor-plugin/plugin.json`、`.codex-plugin/plugin.json`、`gemini-extension.json`、root `plugin.json` — 更新 skill 清单与版本号 -- `Modify: skills/build-executor/SKILL.md` — 增加 Batch Inline 模式 -- `Modify: templates/execution-contract.md` — 增加 Batch Inline 选项 -- `Modify: specs/inline-execution/spec.md` — 扩展模式说明 -- `Create: specs/execution-lean/spec.md` — Batch Inline 规范 -- `Modify: docs/examples/*/README.md`(如含旧 skill 名) — 同步更新 - -## 接口 - -### Batch 1 → Batch 2 -- **Produces**: 已重命名的 skill 目录与 frontmatter — 被 Batch 2 用于更新内部引用。 - -### Batch 2 → Batch 3 -- **Produces**: 所有 skill 内部引用已更新 — 被 Batch 3 用于更新文档与 manifests。 - -### Batch 3 → Batch 4 -- **Produces**: 文档与 manifests 已同步 — 被 Batch 4 用于实现 Batch Inline 与版本发布。 - -## 1. Batch 1: 重命名 skill 目录并更新 frontmatter - -- [ ] **1.1 重命名目录** - -```bash -mv skills/workflow-orchestrator skills/workflow-start -mv skills/spec-explorer skills/need-explorer -mv skills/spec-forger skills/spec-writer -mv skills/bridge-contract skills/contract-builder -mv skills/execution-governor skills/build-executor -mv skills/systematic-debugger skills/bug-investigator -# code-reviewer 保持不变 -mv skills/closure-archivist skills/release-archivist -mv skills/spec-syncer skills/spec-merger -``` - -**Files**: `Rename: skills/*` - -- [ ] **1.2 更新每个 SKILL.md 的 name frontmatter** - -将每个 `skills//SKILL.md` 首行的 `name: ` 改为 `name: `。 - -**Files**: `Modify: skills/*/SKILL.md` - -- [ ] **1.3 提交 Batch 1** - -```bash -git add skills/ -git commit -m "refactor(skills): rename 8 skills to intuitive action-object names" -``` - -## 2. Batch 2: 更新 skill 内部相互引用 - -- [ ] **2.1 更新 workflow-start 中的路由引用** - -在 `skills/workflow-start/SKILL.md` 中: -- 将路由目标中的 `spec-explorer` → `need-explorer` -- `spec-forger` → `spec-writer` -- `bridge-contract` → `contract-builder` -- `execution-governor` → `build-executor` -- `systematic-debugger` → `bug-investigator` -- `closure-archivist` → `release-archivist` -- `spec-syncer` → `spec-merger` - -**Files**: `Modify: skills/workflow-start/SKILL.md` - -- [ ] **2.2 更新 release-archivist 中对 spec-merger 的引用** - -在 `skills/release-archivist/SKILL.md` 中: -- `spec-syncer` → `spec-merger` - -**Files**: `Modify: skills/release-archivist/SKILL.md` - -- [ ] **2.3 在 workflow-start 中增加 DP-0 用户确认门禁** - -在 `skills/workflow-start/SKILL.md` 中: -- 在路由到 `spec-writer` 之前检查 `dp_0_confirmed`。 -- 若未确认,向用户提问:变更范围、约束、是否包含相关优化、沟通偏好。 -- 确认后写入 `.spec-superflow.yaml` 的 `dp_0_decisions`、`dp_0_confirmed`、`dp_0_timestamp`。 - -**Files**: `Modify: skills/workflow-start/SKILL.md` - -- [ ] **2.4 在 spec-writer 中读取 dp_0_* 约束** - -在 `skills/spec-writer/SKILL.md` 中: -- 生成或修订工件前读取 `dp_0_*`。 -- 尊重已确认决策;遇到未覆盖决策时暂停并提问。 - -**Files**: `Modify: skills/spec-writer/SKILL.md` - -- [ ] **2.5 全局搜索并替换剩余旧名引用** - -```bash -grep -R "workflow-orchestrator\|spec-explorer\|spec-forger\|bridge-contract\|execution-governor\|systematic-debugger\|closure-archivist\|spec-syncer" skills/ --include="*.md" -``` - -修复任何遗漏。 - -**Files**: `Modify: skills/*/*.md` - -- [ ] **2.6 提交 Batch 2** - -```bash -git add skills/ -git commit -m "docs(skills): update internal cross-references and add DP-0 confirmation gate" -``` - -## 3. Batch 3: 同步文档、manifests、示例 - -- [ ] **3.1 更新 docs/state-machine.md 和 docs/decision-points.md** - -将所有旧 skill 名替换为新名。 - -**Files**: `Modify: docs/state-machine.md`, `docs/decision-points.md` - -- [ ] **3.2 创建迁移文档 docs/skill-rename-v0.8.0.md** - -包含旧→新映射表、为什么重命名、用户迁移步骤。 - -**Files**: `Create: docs/skill-rename-v0.8.0.md` - -- [ ] **3.3 更新 README.md、INSTALL.md、CLAUDE.md** - -替换所有旧 skill 名,更新 skill 列表表格,必要时调整示例命令。 - -**重点更新 `INSTALL.md` 中各 AI 平台的安装说明**: -- Claude Code:通过 plugin / skill 系统加载,入口改为 `/workflow-start`。 -- Cursor:使用 `scripts/install-cursor.mjs` 生成本地 `.cursor/skills/` 与 `.cursor/rules/`,并说明 `.cursor/` 不提交仓库。 -- Copilot CLI:通过 root `plugin.json` 安装,注意 `author` 必须为对象。 -- Gemini CLI:通过 `gemini-extension.json` 与 `GEMINI.md` 加载。 - -**Files**: `Modify: README.md`, `INSTALL.md`, `CLAUDE.md` - -- [ ] **3.4 更新 plugin manifests 中的 skill 清单与版本号** - -涉及文件: -- `.claude-plugin/plugin.json` -- `.claude-plugin/marketplace.json` -- `.cursor-plugin/plugin.json` -- `.codex-plugin/plugin.json` -- `gemini-extension.json` -- root `plugin.json` - -将 `skills/` 下的旧目录名改为新目录名,并将 `version` 改为 `0.8.0`。 - -**Files**: `Modify: *.json` - -- [ ] **3.5 同步 docs/examples/ 中的旧名称引用** - -如果示例 README 或 artifact 中引用了旧 skill 名,一并替换。 - -**Files**: `Modify: docs/examples/**/README.md` 等 - -- [ ] **3.6 提交 Batch 3** - -```bash -git add docs/ README.md INSTALL.md CLAUDE.md *.json .claude-plugin/ .cursor-plugin/ .codex-plugin/ -git commit -m "docs(manifests): sync docs and manifests for v0.8.0 skill rename" -``` - -## 4. Batch 4: 实现 Batch Inline 模式并发布 - -- [ ] **4.1 修改 build-executor SKILL.md** - -在 `skills/build-executor/SKILL.md` 中: -- 增加 `Batch Inline` 作为可选执行模式 -- 明确自动选择规则:Inline ≤3 tasks → Batch Inline(同模块、低风险、≤15min)→ SDD -- 增加 Batch Inline 的 TDD 与 checkpoint 要求 - -**Files**: `Modify: skills/build-executor/SKILL.md` - -- [ ] **4.2 修改 templates/execution-contract.md** - -在 Execution Mode 字段中增加 `Batch Inline` 选项。 - -**Files**: `Modify: templates/execution-contract.md` - -- [ ] **4.3 更新 specs/inline-execution/spec.md 并创建 specs/execution-lean/spec.md** - -扩展 inline-execution 规范,新增 execution-lean 规范文件。 - -**Files**: `Modify: specs/inline-execution/spec.md`, `Create: specs/execution-lean/spec.md` - -- [ ] **4.4 版本号统一升级到 0.8.0** - -```bash -node scripts/spec-superflow.mjs version 0.8.0 -``` - -**Files**: `Modify: package.json`, `plugin.json`, `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json`, `.cursor-plugin/plugin.json`, `gemini-extension.json` - -- [ ] **4.5 更新 CHANGELOG.md** - -新增 v0.8.0 条目:skill 重命名 + Batch Inline 优化。 - -**Files**: `Modify: CHANGELOG.md` - -- [ ] **4.6 运行验证与测试** - -```bash -node scripts/spec-superflow.mjs doctor -node scripts/spec-superflow.mjs validate changes/v0.8.0-intuitive-skills -npm run build -npm test -``` - -**Files**: `Modify: dist/`(由 build 生成) - -- [ ] **4.7 提交 Batch 4** - -```bash -git add -A -git commit -m "feat(execution): add Batch Inline mode and bump to v0.8.0" -``` - -- [ ] **4.8 合并到 main 并打 tag** - -```bash -git checkout main -git merge --no-ff release-v0.8.0 -m "Merge branch 'release-v0.8.0' into main" -git tag v0.8.0 -git push origin main v0.8.0 -``` - -## 5. Batch 5: 收尾归档 - -- [ ] **5.1 运行 ssf audit 生成决策点审计报告** - -```bash -node scripts/spec-superflow.mjs audit changes/v0.8.0-intuitive-skills -``` - -**Files**: `Create: changes/v0.8.0-intuitive-skills/decision-point-audit.md` - -- [ ] **5.2 运行 ssf inject 更新跨平台 phase-guard** - -```bash -node scripts/spec-superflow.mjs inject changes/v0.8.0-intuitive-skills -``` - -**Files**: `Modify: .claude/always/phase-guard.md`, `.cursor/rules/phase-guard.mdc`, `.github/copilot-instructions.md`, `GEMINI.md` - -- [ ] **5.3 最终检查并提交** - -```bash -node scripts/spec-superflow.mjs doctor -npm test -git add -A -git commit -m "chore(closure): audit and phase-guard for v0.8.0" -``` diff --git a/changes/v0.8.1-auto-latest-install/.spec-superflow.yaml b/changes/v0.8.1-auto-latest-install/.spec-superflow.yaml deleted file mode 100644 index 4431805..0000000 --- a/changes/v0.8.1-auto-latest-install/.spec-superflow.yaml +++ /dev/null @@ -1,40 +0,0 @@ -# .spec-superflow.yaml — lightweight state machine -# Derived data. Always rebuildable from artifacts. Lost/corrupt → fall back to content-level detection. - -# === Core state === -state: exploring -workflow: auto - -# === Hashes (fast staleness detection) === -artifacts_hash: sha256:04ef28aa9f3a0628688a8728b48f04d39c9f97196a3dfae24518fc926797c6dc -contract_hash: sha256:3d3e8671a42904cd2d718335de69504e9cb30772f587770961e144a55287b62e - -# === Execution progress === -execution_mode: null -batches_completed: 0 -test_result: null - -# === Metadata === -change_name: v0.8.1-auto-latest-install -last_transition: 2026-07-01T03:00:40.825Z -last_transition_from: null -last_transition_to: null - -# === Decision points === -dp_0_decisions: null -dp_0_confirmed: null -dp_0_timestamp: null -dp_1_result: null -dp_1_timestamp: null -dp_2_result: null -dp_2_timestamp: null -dp_3_result: null -dp_3_timestamp: null -dp_4_result: null -dp_4_timestamp: null -dp_5_result: null -dp_5_timestamp: null -dp_6_result: null -dp_6_timestamp: null -dp_7_result: null -dp_7_timestamp: null diff --git a/changes/v0.8.1-auto-latest-install/decision-point-audit.md b/changes/v0.8.1-auto-latest-install/decision-point-audit.md deleted file mode 100644 index 42b462a..0000000 --- a/changes/v0.8.1-auto-latest-install/decision-point-audit.md +++ /dev/null @@ -1,67 +0,0 @@ -# Decision-Point Audit Report - -**变更**: v0.8.1-auto-latest-install -**生成时间**: 2026-07-01T03:10:35.859Z -**当前状态**: exploring - -## 汇总表 - -| DP | 名称 | 结果 | 时间戳 | -|----|------|------|--------| -| DP-1 | 需求确认 | not recorded | — | -| DP-2 | 工件审查 | not recorded | — | -| DP-3 | 契约批准 | not recorded | — | -| DP-4 | 执行模式选择 | not recorded | — | -| DP-5 | 调试升级 | not recorded | — | -| DP-6 | 验证失败 | not recorded | — | -| DP-7 | 归档确认 | not recorded | — | - -**统计**: 0/7 已记录,7/7 未记录。 - -## 逐决策点说明 - -### DP-1: 需求确认 - -- **结果**: not recorded -- **时间戳**: — -- **解读**: 该决策点尚未记录结果。如果工作流已经经过该阶段,请检查是否漏记。 - -### DP-2: 工件审查 - -- **结果**: not recorded -- **时间戳**: — -- **解读**: 该决策点尚未记录结果。如果工作流已经经过该阶段,请检查是否漏记。 - -### DP-3: 契约批准 - -- **结果**: not recorded -- **时间戳**: — -- **解读**: 该决策点尚未记录结果。如果工作流已经经过该阶段,请检查是否漏记。 - -### DP-4: 执行模式选择 - -- **结果**: not recorded -- **时间戳**: — -- **解读**: 该决策点尚未记录结果。如果工作流已经经过该阶段,请检查是否漏记。 - -### DP-5: 调试升级 - -- **结果**: not recorded -- **时间戳**: — -- **解读**: 该决策点尚未记录结果。如果工作流已经经过该阶段,请检查是否漏记。 - -### DP-6: 验证失败 - -- **结果**: not recorded -- **时间戳**: — -- **解读**: 该决策点尚未记录结果。如果工作流已经经过该阶段,请检查是否漏记。 - -### DP-7: 归档确认 - -- **结果**: not recorded -- **时间戳**: — -- **解读**: 该决策点尚未记录结果。如果工作流已经经过该阶段,请检查是否漏记。 - ---- - -*本报告由 `ssf audit` 自动生成,仅供审计与归档参考。* diff --git a/changes/v0.8.1-auto-latest-install/design.md b/changes/v0.8.1-auto-latest-install/design.md deleted file mode 100644 index 8ab5112..0000000 --- a/changes/v0.8.1-auto-latest-install/design.md +++ /dev/null @@ -1,72 +0,0 @@ -# 设计文档 - -## 目标 - -让用户安装/升级 spec-superflow 时不需要手动指定版本号: -1. Cursor 本地部署脚本默认从 GitHub latest release 自动拉取。 -2. 启动 workflow 时自动检查版本,若落后则提示升级。 - -## Cursor 脚本设计 - -### 当前行为 - -`scripts/install-cursor.mjs` 要求用户先 `git clone` 仓库,然后运行脚本,脚本从本地仓库复制 `skills/` 并生成 `.cursor/rules/phase-guard.mdc`。 - -### 新行为 - -默认无参数运行时: -1. 调用 GitHub API `GET https://api.github.com/repos/MageByte-Zero/spec-superflow/releases/latest` 获取 `tag_name`。 -2. 下载 `https://github.com/MageByte-Zero/spec-superflow/archive/refs/tags/{tag}.tar.gz` 到 `/tmp`。 -3. 解压到临时目录。 -4. 从解压目录部署: - - 复制 `skills/*` → `.cursor/skills/` - - 读取 `scripts/lib/cmd-inject.mjs` 或复用现有 phase-guard 生成逻辑创建 `.cursor/rules/phase-guard.mdc` -5. 清理临时目录。 -6. 输出安装版本。 - -### 参数 - -- `--local `:使用本地仓库路径,跳过下载。 -- `--tag `(可选):指定 release tag,用于测试旧版本或预发布。 - -### 网络失败处理 - -- 任何网络/解压错误都打印明确错误并退出码 1。 -- 部署前先把现有 `.cursor/skills/spec-superflow*` 移到临时备份,失败时回滚。 - -## 版本检查设计 - -### `scripts/check-update.mjs` - -- 读取本地版本:优先 `package.json` 的 `version`;如果不存在,读 `plugin.json` 的 `version`。 -- 读取远程版本:`npm view spec-superflow version`。 -- 比较: - - 本地 == 远程 → 输出 `✅ spec-superflow is up to date (x.y.z)`,退出码 0。 - - 本地 < 远程 → 输出 `⚠️ spec-superflow x.y.z is available (current: a.b.c). Upgrade: /plugin install spec-superflow@x.y.z`,退出码 1。 - - 无法比较 → 输出警告,退出码 2。 - -### `workflow-start` 集成 - -- 在 `workflow-start/SKILL.md` 的启动流程中增加一步: - - Run: `node "${CLAUDE_PLUGIN_ROOT}/scripts/check-update.mjs"` - - If exit code 1, prepend a one-line reminder to the response. -- 不阻塞工作流:即使用户未升级,也继续检测状态和路由。 - -## 文档更新 - -- `INSTALL.md` Cursor 部分改为默认一键安装最新版: - ```bash - npx spec-superflow/install-cursor - # 或 - node <(tmp path)>/install-cursor.mjs - ``` - 实际仍需要用户下载脚本?如果脚本本身能从 GitHub 拉取,可以先提供一个 curl 命令下载脚本再执行。 -- `README.md` 同步版本说明到 v0.8.1,增加“自动升级”卖点。 - -## 测试策略 - -1. `ssf validate changes/v0.8.1-auto-latest-install` 通过。 -2. `node scripts/install-cursor.mjs --local .` 在本地仓库路径下仍能正确部署(回归)。 -3. `node scripts/check-update.mjs` 在本地 0.8.1 与 npm 0.8.0/0.8.1 比较时输出正确。 -4. `npm run build && npm test` 通过。 -5. `ssf doctor` 通过。 diff --git a/changes/v0.8.1-auto-latest-install/execution-contract.md b/changes/v0.8.1-auto-latest-install/execution-contract.md deleted file mode 100644 index 7ef7e24..0000000 --- a/changes/v0.8.1-auto-latest-install/execution-contract.md +++ /dev/null @@ -1,97 +0,0 @@ -# 执行合同 - -## Intent Lock - -- **变更名称**:v0.8.1 auto-latest install + update reminder -- **要解决的问题**:安装/升级 spec-superflow 时需要手动指定版本号,容易遗漏最新版。 -- **范围内**: - - `scripts/install-cursor.mjs` 默认从 GitHub latest release 下载。 - - 新增 `scripts/check-update.mjs`。 - - `workflow-start` 启动时版本检查提示。 - - `INSTALL.md` / `README.md` / `CHANGELOG.md` 更新。 - - 版本号升级到 `0.8.1`。 -- **范围外**: - - 修改 Claude Code `/plugin` 客户端升级机制。 - - 修改其他平台安装脚本。 - - 自动静默升级。 - -## Approved Behavior - -- **已批准需求摘要**: - - Cursor 安装脚本默认自动安装 GitHub latest release。 - - 保留 `--local` 参数用于本地开发部署。 - - workflow 启动时检查版本并提示升级。 -- **关键场景**: - - 用户在新项目中运行 Cursor 安装脚本,无需 clone 仓库即可获得最新版。 - - 用户启动 workflow 时收到升级提醒。 -- **验收检查**: - - `ssf doctor` 通过。 - - `npm test` 通过。 - - `--local` 路径部署仍工作。 - - `check-update.mjs` 能正确比较版本。 - -## Design Constraints - -- **架构约束**:不破坏现有安装脚本行为,仅扩展默认行为。 -- **接口约束**:`install-cursor.mjs` 新增可选参数。 -- **依赖约束**:需要 GitHub API 和 npm registry 网络访问。 -- **数据约束**:临时下载文件必须清理,失败必须回滚。 - -## Task Batches - -### Batch 1 - -- **目标**:改造 Cursor 安装脚本支持 latest release。 -- **输入**:当前 `scripts/install-cursor.mjs`。 -- **输出**:支持 `--local`、默认下载 latest release、错误回滚的脚本。 -- **完成标准**:`--local .` 路径部署成功,默认路径至少 dry-run 逻辑正确。 - -### Batch 2 - -- **目标**:新增版本检查脚本并集成到 workflow-start。 -- **输入**:Batch 1 产出的脚本基础。 -- **输出**:`scripts/check-update.mjs` 和集成后的 `workflow-start/SKILL.md`。 -- **完成标准**:`check-update.mjs` 返回正确退出码,workflow-start 能提示升级。 - -### Batch 3 - -- **目标**:文档、版本号、发布。 -- **输入**:Batch 2 产出的功能。 -- **输出**:更新后的 README/INSTALL/CHANGELOG、版本号 0.8.1、tag v0.8.1。 -- **完成标准**:npm/GH release 完成。 - -## Test Obligations - -- **必须先从失败测试开始的行为**: - - `--local` 路径下找不到 source 时应失败。 -- **必需的边界情况**: - - GitHub API 失败。 - - npm 不可达。 - - 本地版本等于/高于远程版本。 -- **回归敏感区域**: - - `scripts/install-cursor.mjs` 原有本地部署路径。 - -## Execution Mode - -- **模式**:`Inline` -- **选择理由**:变更范围小(2 个脚本 + 文档),无跨模块依赖,适合当前会话直接实现。 - -## Verification Dimensions - -| 维度 | 状态 | 发现 | -|------|------|------| -| Completeness | Pending | — | -| Correctness | Pending | — | -| Coherence | Pending | — | - -**总体结论**:Pending - -## Review Gates - -- Batch 1 后:确认 `--local` 行为未破坏。 -- Batch 2 后:确认 `check-update.mjs` 输出正确。 -- Batch 3 后:确认发布成功。 - -## Escalation Rules - -- 如果 GitHub API 限流或不稳定,可降级为文档说明手动下载。 diff --git a/changes/v0.8.1-auto-latest-install/proposal.md b/changes/v0.8.1-auto-latest-install/proposal.md deleted file mode 100644 index 0d7d0b3..0000000 --- a/changes/v0.8.1-auto-latest-install/proposal.md +++ /dev/null @@ -1,44 +0,0 @@ -# 变更提案 - -## Why - -当前安装/升级 spec-superflow 时,用户需要手动指定版本号(如 `/plugin install spec-superflow@0.8.0` 或 `node scripts/install-cursor.mjs` 依赖本地仓库)。这容易遗漏最新版本,也增加心智负担。用户希望安装脚本能自动拉取并安装最新版本。 - -## What Changes - -- 改造 `scripts/install-cursor.mjs`:默认从 GitHub latest release 下载 source tarball,解压后部署到 `.cursor/skills/` 和 `.cursor/rules/`。 -- 保留 `--local ` 参数,允许从本地仓库部署(兼容现有用法)。 -- 新增 `scripts/check-update.mjs`:比较本地版本与 npm latest,输出是否需要升级。 -- 在 `workflow-start/SKILL.md` 中增加启动时版本检查:运行 `scripts/check-update.mjs`,若落后则提示用户升级命令。 -- 更新 `INSTALL.md` 与 `README.md` 中 Claude Code 升级说明:Claude Code marketplace 中已安装插件需用 `/plugin update spec-superflow@spec-superflow` 升级到最新版。 -- 更新 `INSTALL.md` 中 Cursor 安装说明,改为“自动拉最新版”。 -- 版本号升级到 `0.8.1`。 - -## Capabilities - -### 新增能力 - -- cursor-auto-latest-install — Cursor 本地部署脚本默认安装 GitHub latest release。 -- update-check-reminder — workflow 启动时检测版本并提示升级。 - -## Scope - -### In Scope - -- `scripts/install-cursor.mjs` 改造。 -- `scripts/check-update.mjs` 新增。 -- `workflow-start/SKILL.md` 增加版本检查提示。 -- `INSTALL.md` / `README.md` 安装说明更新。 -- 版本号同步到 `0.8.1`。 - -### Out of Scope - -- 修改 Claude Code `/plugin` 客户端本身的升级行为(不可控)。 -- 修改其他平台(Copilot/Gemini)的安装脚本(它们本身支持 `@latest` 或 marketplace)。 -- 自动静默升级(只提示,不替用户执行)。 - -## Impact - -- 影响的代码区域:`scripts/`、`skills/workflow-start/SKILL.md`、文档。 -- 影响的 API 或接口:无破坏性变更,`install-cursor.mjs` 新增可选参数。 -- 依赖或涉及的外部系统:GitHub Release API、npm registry。 diff --git a/changes/v0.8.1-auto-latest-install/specs/cursor-auto-update/spec.md b/changes/v0.8.1-auto-latest-install/specs/cursor-auto-update/spec.md deleted file mode 100644 index 1d7e2f9..0000000 --- a/changes/v0.8.1-auto-latest-install/specs/cursor-auto-update/spec.md +++ /dev/null @@ -1,85 +0,0 @@ -# 能力规格 - -## ADDED Requirements - -### Requirement: Cursor Install Script Defaults to Latest Release - -`scripts/install-cursor.mjs` SHALL, by default, download and install the latest GitHub release of `spec-superflow` into the current project's `.cursor/` directory. - -#### Scenario: Default latest release install - -- **WHEN** a user runs `node /absolute/path/to/install-cursor.mjs` in their project root -- **AND** no `--local` argument is provided -- **THEN** the script SHALL fetch the latest release tag from GitHub -- **AND** download the corresponding source tarball -- **AND** extract the tarball to a temporary directory -- **AND** copy `skills/` to `.cursor/skills/` -- **AND** create `.cursor/rules/phase-guard.mdc` -- **AND** report the installed version - -#### Scenario: Local deployment override - -- **WHEN** a user runs `node install-cursor.mjs --local /path/to/spec-superflow` -- **THEN** the script SHALL skip GitHub download -- **AND** use the provided local repository path as the source -- **AND** deploy skills and rules from that path - -#### Scenario: Network failure fallback - -- **WHEN** the GitHub API or tarball download fails -- **THEN** the script SHALL print a clear error message -- **AND** exit with a non-zero code -- **AND** SHALL NOT leave a partially populated `.cursor/skills/` directory - -### Requirement: Update Check Script - -`scripts/check-update.mjs` SHALL compare the local plugin version with the latest version published to npm and report whether an upgrade is available. - -#### Scenario: Local version is latest - -- **WHEN** `check-update.mjs` runs in a project with `spec-superflow` installed -- **AND** the local version equals npm latest -- **THEN** it SHALL output that the installation is up to date -- **AND** exit with code 0 - -#### Scenario: Local version is outdated - -- **WHEN** `check-update.mjs` runs and the local version is lower than npm latest -- **THEN** it SHALL output the current and latest versions -- **AND** provide platform-appropriate upgrade commands: - - Claude Code: `/plugin update spec-superflow@spec-superflow` - - Cursor: re-run the install script - - npm: `npm install -g spec-superflow@latest` -- **AND** exit with code 1 - -#### Scenario: Cannot determine version - -- **WHEN** the local version cannot be read or npm is unreachable -- **THEN** it SHALL output a warning and exit with code 2 - -### Requirement: Workflow Start Checks for Updates - -`workflow-start` SHALL run the update check during startup and surface any available upgrade to the user. - -#### Scenario: Starting a new or existing change - -- **WHEN** `workflow-start` is invoked -- **THEN** it SHALL run `node scripts/check-update.mjs` -- **AND** if exit code is 1, prepend a non-blocking upgrade reminder to its response -- **AND** continue with normal state detection - -## MODIFIED Requirements - -### Requirement: INSTALL.md Cursor Section - -The Cursor installation section in `INSTALL.md` SHALL describe the new default behavior of `install-cursor.mjs`. - -#### Scenario: User reads Cursor install instructions - -- **WHEN** a user reads `INSTALL.md` under the Cursor section -- **THEN** they SHALL see a one-liner command that installs the latest release automatically -- **AND** they SHALL see the `--local` option documented for development/testing - -## REMOVED Requirements - -None. diff --git a/changes/v0.8.1-auto-latest-install/specs/update-check/spec.md b/changes/v0.8.1-auto-latest-install/specs/update-check/spec.md deleted file mode 100644 index 4f4a379..0000000 --- a/changes/v0.8.1-auto-latest-install/specs/update-check/spec.md +++ /dev/null @@ -1,33 +0,0 @@ -# 能力规格 - -## ADDED Requirements - -### Requirement: Update Check Reminder on Workflow Start - -`workflow-start` SHALL compare the locally installed `spec-superflow` version against the latest npm version and remind the user to upgrade if behind. - -#### Scenario: Outdated plugin - -- **WHEN** `workflow-start` starts -- **AND** `scripts/check-update.mjs` reports an outdated version -- **THEN** `workflow-start` SHALL display a reminder with the current version, latest version, and upgrade command -- **AND** SHALL still proceed with normal workflow routing - -#### Scenario: Up-to-date plugin - -- **WHEN** `workflow-start` starts -- **AND** `scripts/check-update.mjs` reports up to date -- **THEN** no reminder is shown - -#### Scenario: Check script unavailable - -- **WHEN** `scripts/check-update.mjs` does not exist or fails -- **THEN** `workflow-start` SHALL silently skip the check - -## MODIFIED Requirements - -None. - -## REMOVED Requirements - -None. diff --git a/changes/v0.8.1-auto-latest-install/tasks.md b/changes/v0.8.1-auto-latest-install/tasks.md deleted file mode 100644 index 01b4c76..0000000 --- a/changes/v0.8.1-auto-latest-install/tasks.md +++ /dev/null @@ -1,147 +0,0 @@ -# 实现任务 - -## 文件结构 - -- `Modify: scripts/install-cursor.mjs` — 默认从 GitHub latest release 下载,支持 `--local` 覆盖 -- `Create: scripts/check-update.mjs` — 本地 vs npm latest 版本检查 -- `Modify: skills/workflow-start/SKILL.md` — 启动时调用版本检查并提示 -- `Modify: INSTALL.md` — Cursor 一键安装最新版说明 -- `Modify: README.md` — 版本历史与卖点同步 -- `Modify: CHANGELOG.md` — v0.8.1 条目 -- `Modify: package.json` / manifests — 版本号 `0.8.1` - -## 1. Batch 1: Cursor 脚本改造 - -- [ ] **1.1 解析命令行参数** - -在 `scripts/install-cursor.mjs` 中: -- 使用 `node:util.parseArgs` 解析 `--local` 和 `--tag`。 -- 默认行为:从 GitHub latest release 下载。 - -**Files**: `Modify: scripts/install-cursor.mjs` - -- [ ] **1.2 实现 latest release 下载与部署** - -- 调用 GitHub API 获取 latest tag。 -- 下载 tarball 到 `/tmp`。 -- 解压。 -- 复制 `skills/` → `.cursor/skills/`。 -- 生成 `.cursor/rules/phase-guard.mdc`(可复用现有生成逻辑或调用 `ssf inject`)。 -- 清理临时目录。 - -**Files**: `Modify: scripts/install-cursor.mjs` - -- [ ] **1.3 实现 `--local` 兼容路径** - -- 如果传了 `--local `,从该路径复制 skills 并生成 rules,与旧行为一致。 - -**Files**: `Modify: scripts/install-cursor.mjs` - -- [ ] **1.4 错误处理与回滚** - -- 下载/解压失败时退出码 1。 -- 部署失败时回滚备份。 - -**Files**: `Modify: scripts/install-cursor.mjs` - -- [ ] **1.5 提交 Batch 1** - -```bash -git add scripts/install-cursor.mjs -git commit -m "feat(cursor): install-cursor.mjs defaults to GitHub latest release" -``` - -## 2. Batch 2: 版本检查脚本与 workflow 集成 - -- [ ] **2.1 创建 scripts/check-update.mjs** - -- 读取本地 `package.json` / `plugin.json` version。 -- 调用 `npm view spec-superflow version`。 -- 输出结果并返回 0/1/2。 - -**Files**: `Create: scripts/check-update.mjs` - -- [ ] **2.2 集成到 workflow-start** - -在 `skills/workflow-start/SKILL.md` 中: -- 启动时运行 `node "${CLAUDE_PLUGIN_ROOT}/scripts/check-update.mjs"`。 -- 退出码 1 时,在响应顶部加一行升级提示。 - -**Files**: `Modify: skills/workflow-start/SKILL.md` - -- [ ] **2.3 提交 Batch 2** - -```bash -git add scripts/check-update.mjs skills/workflow-start/SKILL.md -git commit -m "feat(workflow): add update check reminder on workflow start" -``` - -## 3. Batch 3: 文档、版本号与发布 - -- [ ] **3.1 更新 INSTALL.md** - -- Cursor 部分写默认一键安装最新版命令。 -- 保留 `--local` 说明。 - -**Files**: `Modify: INSTALL.md` - -- [ ] **3.2 更新 README.md** - -- 版本历史增加 v0.8.1。 -- 版本号改为 v0.8.1。 - -**Files**: `Modify: README.md` - -- [ ] **3.3 更新 CHANGELOG.md** - -- 增加 v0.8.1 条目。 - -**Files**: `Modify: CHANGELOG.md` - -- [ ] **3.4 版本号升级到 0.8.1** - -```bash -node scripts/spec-superflow.mjs version 0.8.1 -``` - -**Files**: `Modify: package.json`, `plugin.json`, `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json`, `.cursor-plugin/plugin.json`, `.codex-plugin/plugin.json`, `gemini-extension.json` - -- [ ] **3.5 验证与测试** - -```bash -node scripts/spec-superflow.mjs doctor -node scripts/spec-superflow.mjs validate changes/v0.8.1-auto-latest-install -npm run build -npm test -node scripts/install-cursor.mjs --local . --dry-run # 如果支持 -node scripts/check-update.mjs -``` - -**Files**: `Modify: dist/` - -- [ ] **3.6 提交并发布** - -```bash -git add -A -git commit -m "chore(release): bump to v0.8.1 with auto-latest install" -git tag v0.8.1 -git push origin main v0.8.1 -``` - -## 4. Batch 4: 收尾 - -- [ ] **4.1 生成 audit 与 phase-guard** - -```bash -node scripts/spec-superflow.mjs audit changes/v0.8.1-auto-latest-install -node scripts/spec-superflow.mjs inject changes/v0.8.1-auto-latest-install -``` - -**Files**: `Create: changes/v0.8.1-auto-latest-install/decision-point-audit.md` - -- [ ] **4.2 最终提交** - -```bash -git add -A -git commit -m "chore(closure): audit and phase-guard for v0.8.1" -``` diff --git a/changes/v0.8.4-quality-audit/.spec-superflow.yaml b/changes/v0.8.4-quality-audit/.spec-superflow.yaml deleted file mode 100644 index 2a0177f..0000000 --- a/changes/v0.8.4-quality-audit/.spec-superflow.yaml +++ /dev/null @@ -1,40 +0,0 @@ -# .spec-superflow.yaml — lightweight state machine -# Derived data. Always rebuildable from artifacts. Lost/corrupt → fall back to content-level detection. - -# === Core state === -state: exploring -workflow: full - -# === Hashes (fast staleness detection) === -artifacts_hash: null -contract_hash: null - -# === Execution progress === -execution_mode: null -batches_completed: 0 -test_result: null - -# === Metadata === -change_name: v0.8.4-quality-audit -last_transition: 2026-07-03T02:15:02.441Z -last_transition_from: null -last_transition_to: null - -# === Decision points === -dp_0_decisions: Scope: 全仓库审计(skills/ scripts/ src/ hooks/ templates/ docs/),零依赖不变,skill名和API稳定。优先级: C 并行(bug审计+token优化同步)。沟通: 打包审查——全面扫描后产出报告,一次性review后动手修。 -dp_0_confirmed: true -dp_0_timestamp: 2026-07-03T02:15:07Z -dp_1_result: null -dp_1_timestamp: null -dp_2_result: null -dp_2_timestamp: null -dp_3_result: null -dp_3_timestamp: null -dp_4_result: null -dp_4_timestamp: null -dp_5_result: null -dp_5_timestamp: null -dp_6_result: null -dp_6_timestamp: null -dp_7_result: null -dp_7_timestamp: null diff --git a/changes/v0.8.4-quality-audit/audit-report.md b/changes/v0.8.4-quality-audit/audit-report.md deleted file mode 100644 index d3b5ed2..0000000 --- a/changes/v0.8.4-quality-audit/audit-report.md +++ /dev/null @@ -1,384 +0,0 @@ -# v0.8.4 质量审计报告 - -> 审计日期:2026-07-03 | 全仓库扫描 | 3 个并行 Agent - ---- - -## 总览 - -| 维度 | Critical | High | Medium | Low | 合计 | -|------|----------|------|--------|-----|------| -| Bug(逻辑/路径/兼容) | 3 | 8 | 12 | 8 | **31** | -| Token 优化 | — | — | 4 | 2 | **6** | - ---- - -## 一、Critical(必须修,阻断正常工作) - -### C-1:中文模板与 Validator 引擎不兼容 - -**文件**:`templates/proposal.md:3,8` ← vs → `src/validation/validator.ts:29,202,226` - -模板用中文标题 `## 背景(Why)` 和 `## 变更内容(What Changes)`,但 Validator 的正则是 `/^##\s+Why\s*$/i` 和 `/^##\s+What\s+Changes\s*$/i`——**精确匹配英文标题**。`spec-writer` 按模板生成 proposal 后,`schema-valid` guard 检查直接报错「## Why 缺失」→ 阻塞 `specifying→bridging` 转换。 - -**修复**:Validator regex 改为 `/^##\s+(背景()?Why())?\s*$/i`(兼容中英文),或模板改回纯英文标题(`## Why` / `## What Changes`)。 - ---- - -### C-2:guard.mjs 存在死 transition `bridging:approved` - -**文件**:`scripts/guard/guard.mjs:14` - -```js -'bridging:approved': ['artifacts-exist', 'schema-valid', 'contract-fresh'], -``` - -状态名是 `approved-for-build`(全仓库统一),没有 `approved` 这个短名。此 transition key 永远不会被匹配到,**`bridging → approved-for-build` 的 guard 检查实际从未执行**。 - -**修复**:`s/approved/approved-for-build/`。 - ---- - -### C-3:Cursor workflow-orchestrator 给 guard 传了错误的状态名 - -**文件**:`.cursor/skills/workflow-orchestrator/SKILL.md:145` - -```bash -node scripts/guard/guard.mjs check approved executing --json -``` - -同上——guard 里只有 `approved-for-build:executing`,`approved:executing` 不存在 → guard 报 `Unknown transition` → Cursor 用户无法启动执行。 - -**修复**:`s/approved/approved-for-build/`。 - ---- - -## 二、High(会导致实际使用失败) - -### H-1:guard.mjs 缺少 6 个合法 transition - -**文件**:`scripts/guard/guard.mjs:11-21` - -Transition matrix 只定义了 9 个 transition,以下合法回退全部缺失: - -| 缺失 transition | 场景 | -|----------------|------| -| `specifying:exploring` | 需求变更,回退探索 | -| `bridging:specifying` | 契约漂移,重新规格 | -| `approved-for-build:bridging` | 契约需返工 | -| `executing:specifying` | 执行中发现需求变更 | -| `executing:bridging` | 执行中发现契约过期 | -| `closing:specifying` | 验证失败需重新规划 | - -缺失 = guard 对合法回退报 `Unknown transition` 并 exit 1 → **正常回退被硬阻断**。 - -**修复**:补全 transition matrix。 - ---- - -### H-2:Guard 可被完全绕过 - -**文件**:`scripts/lib/cmd-state.mjs:73-91`(transition 不调用 guard) - -`ssf state transition ` 直接写状态文件,不检查任何 guard 维度。skill 调了 `guard.mjs check`,但用户或脚本直接跑 `ssf state transition` 就能跳过所有门禁。 - -**修复**:`cmd-state.mjs` 的 `transition` 在写文件前调用 `guard.mjs check`。 - ---- - -### H-3:tasks-complete.mjs 不认大写 `[X]` - -**文件**:`scripts/guard/checks/tasks-complete.mjs:25` - -```js -const hasAny = content.match(/^- \[x\]/gm); // 只匹配小写 x -``` - -Markdown 工具(GitHub、VS Code)自动生成的任务列表常用大写 `[X]`。全部任务完成但用了大写 X → guard 报「no completed tasks found」→ **阻塞 closing transition**。 - -**修复**:`/^- \[[xX]\]/gm`。 - ---- - -### H-4:build-executor 在 worktree 场景下脚本路径全断 - -**文件**:`skills/build-executor/SKILL.md:220,236,247` - -该 skill 第 194 行指导 `cd ../-` 进入 worktree,之后的三处脚本引用全用相对路径: - -``` -scripts/task-brief ← worktree 里没有 scripts/ -scripts/review-package ← worktree 里没有 scripts/ -node scripts/spec-superflow.mjs state get ... ← 同上 -``` - -**修复**:全部改为 `${CLAUDE_PLUGIN_ROOT}/scripts/...`。 - ---- - -### H-5:spec-merger 所有路径多了不存在的 `workflow/` 前缀 - -**文件**:`skills/spec-merger/SKILL.md:48,64,133,134,138` - -用 `workflow/changes//specs/` 和 `workflow/specs//spec.md`,但实际目录结构没有 `workflow/` 层: - -``` -实际:changes//specs/ 和 specs//spec.md -``` - -**修复**:删除 `workflow/` 前缀。 - ---- - -### H-6:infer-workflow.mjs 相对路径调用静默失败 - -**文件**:`scripts/infer-workflow.mjs:120` - -```js -if (import.meta.url === `file://${process.argv[1]}`) { main(); } -``` - -`import.meta.url` 是 `file:///abs/path`(三斜杠),`process.argv[1]` 是 `scripts/infer-workflow.mjs`(相对路径)→ 永远不匹配 → `main()` 永远不执行 → 脚本静默无输出。 - -**修复**:用 `path.resolve()` 归一化再比较,或用 `import.meta.filename`(Node 22+)。 - ---- - -### H-7:cmd-state.mjs 接受任意 state 名,不校验 - -**文件**:`scripts/lib/cmd-state.mjs:81` - -```js -state.state = toState; // 无校验 -``` - -打错字如 `ssf state transition ... executin`(少 g)→ 状态被写为 `executin` → 后续所有 guard 调用报 `Unknown transition` → 状态机不可恢复。 - -**修复**:加 VALID_STATES 白名单校验。 - ---- - -### H-8:Cursor 3 个 skill 缺失决策点协议 - -| Skill | 缺失 | 影响 | -|-------|------|------| -| `.cursor/skills/spec-explorer/SKILL.md` | 无 DP-1(需求确认) | Cursor 用户跳过需求确认 | -| `.cursor/skills/spec-forger/SKILL.md` | 无 DP-2(工件审查) | Cursor 用户跳过工件审查 | -| `.cursor/skills/workflow-orchestrator/SKILL.md` | 无 DP-0(设计前确认) | Cursor 用户跳过设计前门禁 | - -**修复**:从 `skills/` 的对应文件同步 DP 章节到 `.cursor/skills/`。 - ---- - -## 三、Medium(功能降级/数据风险) - -### M-1:6 个 skill 的 H1 标题仍是 v0.7 旧名 - -| 文件 | 当前 H1 | 应为 | 行号 | -|------|---------|------|------| -| `skills/need-explorer/SKILL.md` | Spec Explorer | Need Explorer | 6 | -| `skills/contract-builder/SKILL.md` | Bridge Contract | Contract Builder | 6 | -| `skills/build-executor/SKILL.md` | Execution Governor | Build Executor | 6 | -| `skills/bug-investigator/SKILL.md` | Systematic Debugger | Bug Investigator | 6 | -| `skills/release-archivist/SKILL.md` | Closure Archivist | Release Archivist | 6 | -| `skills/spec-merger/SKILL.md` | Spec Syncer | Spec Merger | 6 | - -不影响功能(H1 不作为路由依据),但用户看到旧名会困惑。 - ---- - -### M-2:state-loader.mjs 的 `||` vs `??` 导致空字符串数据丢失 - -**文件**:`scripts/lib/state-loader.mjs:71-76` - -```js -`execution_mode: ${state.execution_mode || 'null'}` // '' → 'null' -`dp_0_decisions: ${state.dp_0_decisions ?? 'null'}` // '' → '' (正确) -``` - -用 `||` 的字段(execution_mode, test_result, change_name)中,空字符串是合法值,但会被序列化为 `'null'` → 下次读回变成 JS `null` → 数据丢失。 - -**修复**:统一用 `??`。 - ---- - -### M-3:hash.mjs 把 specs 目录下所有 .md 都纳入哈希 - -**文件**:`scripts/lib/hash.mjs:22-30` - -`walkDir` 递归收集 specs/ 下所有 `.md` 文件参与哈希。如果有人在 specs/ 下放了 `README.md` 或 `design-notes.md`,修改它会导致「artifacts_hash mismatch」→ 误报 contract stale。 - -**修复**:只 hash `spec.md` 文件。 - ---- - -### M-4:schema-valid.mjs 丢弃所有 WARNING 级别问题 - -**文件**:`scripts/guard/checks/schema-valid.mjs:33,52` - -只收集 ERROR,WARNING 全丢弃。Validator 返回的预警信息(如 requirements 无 Scenario 但未到 ERROR 阈值)被静默忽略。 - -**修复**:WARNING 也应包含在输出中(不阻塞,但展示)。 - ---- - -### M-5:schema-valid.mjs 不验证 design.md 和 tasks.md - -**文件**:`scripts/guard/checks/schema-valid.mjs:26-58` - -只验证 `proposal.md` + `specs/*/spec.md`,不验证 design 和 tasks。命名暗示全面验证,实际只覆盖一半。 - -**修复**:要么补全验证,要么重命名为 `proposal-and-specs-valid`。 - ---- - -### M-6:schema-valid.mjs 的 dynamic import 无错误处理 - -**文件**:`scripts/guard/checks/schema-valid.mjs:11` - -`dist/index.js` 不存在(未 build)→ `import()` 直接 crash,无提示。 - -**修复**:try/catch + 提示「请先运行 npm run build」。 - ---- - -### M-7:infer-workflow.mjs 显式 `full` 被覆盖 - -**文件**:`scripts/infer-workflow.mjs:40-46` - -只有 `hotfix` 和 `tweak` 作为显式覆盖——如果用户设了 `workflow: full`,自动检测仍可能推断出 hotfix/tweak 并覆盖。 - -**修复**:`if (state.workflow !== 'auto' && state.workflow != null) return ...`。 - ---- - -### M-8:workflow-start 中 8 处脚本路径用相对路径 - -**文件**:`skills/workflow-start/SKILL.md:134,211,219,229,255,279,291` - -`infer-workflow.mjs`(1 处)和 `guard.mjs`(6 处)+ `contract-builder`(1 处)用相对路径。在非插件根目录的 CWD 下失效。 - -**修复**:统一用 `${CLAUDE_PLUGIN_ROOT}/scripts/...`。 - ---- - -### M-9:SETTABLE_FIELDS 缺少多个字段 - -**文件**:`scripts/lib/cmd-state.mjs:6-13` - -缺少:`batches_completed`、`dp_0_result`、`dp_1_decisions`~`dp_7_decisions`、`dp_1_confirmed`~`dp_7_confirmed`。workflow 自动化想写这些字段时只能用 `writeFileSync`。 - -**修复**:补全 SETTABLE_FIELDS。 - ---- - -### M-10:bug-investigator 缺失 DP-5 引用 - -**文件**:`skills/bug-investigator/SKILL.md` - -`decision-points.md` 将 DP-5 关联到 `bug-investigator`,但 skill 文件中 DP-5 从未出现。 - -**修复**:在 3+ 修复失败升级处加 DP-5 记录。 - ---- - -### M-11:session-start 声称 ~50 tokens,实际 ~75-100 - -**文件**:`hooks/session-start:8-9` - -评论声称 ~50 tokens,实际 ~300 字符 ÷ 3 ≈ 100 tokens。 - -**修复**:更新注释数字。 - ---- - -### M-12:`.cursor/skills/` 有 15 个目录,`skills/` 有 9 个 - -`.cursor/skills/` 包含 v0.7 旧名和 v0.8 新名的混合(如 `spec-explorer/` 和 `need-explorer/` 同时存在),内容版本不同。Cursor 用户看到两套名字。 - -**修复**:清理 `.cursor/skills/` 只保留当前 9 个,内容与 `skills/` 对齐。 - ---- - -## 四、Token 优化(可量化收益) - -### Token 消耗全景 - -| 组件 | 当前 tokens | 触发频率 | 优化目标 | -|------|------------|----------|---------| -| **workflow-start SKILL.md** | ~4,900 | 每次手动调用 + hook 注入 | ~3,000 | -| **build-executor SKILL.md** | ~4,900 | 每次执行 | ~3,500 | -| **spec-writer SKILL.md** | ~3,200 | 每次规划 | ~2,500 | -| **bug-investigator SKILL.md** | ~3,100 | 调试时 | ~2,500 | -| **code-reviewer SKILL.md** | ~2,900 | 审查时 | ~2,300 | -| **spec-merger SKILL.md** | ~2,600 | 收口时 | ~2,200 | -| **contract-builder SKILL.md** | ~2,500 | 桥接时 | ~2,200 | -| **release-archivist SKILL.md** | ~2,500 | 收口时 | ~2,200 | -| **need-explorer SKILL.md** | ~1,800 | 探索时 | 足够精简 | -| implementer-prompt.md | ~2,000 | 每个 SDD 子代理 | ~1,500 | -| task-reviewer-prompt.md | ~2,600 | 每个 SDD 子代理 | ~2,000 | -| code-reviewer-prompt.md | ~1,800 | 每次审查 | ~1,500 | -| **session-start hook 注入** | ~100 | **每次会话** | ~50 | -| **phase-guard 重复文件** | 2 份 × N bytes | 每次 inject | 去重为 1 份 | - -### T-1:workflow-start SKILL.md 缩减(~4,900 → ~3,000,省 ~1,900 tokens/次调用) - -**分析**:362 行是最大的 skill 文件。可砍: -- 示例部分(lines 159-176)——示例可移到 docs/ -- 重复的 guard check 命令可因子化——6 处几乎相同的命令改为 1 处描述 + 引用 -- DP-0 部分(lines 84-117)可以压缩到 1/2 长度 - -**节省**:~1,900 tokens × 每次会话 = 用户每次打开 Claude Code 就省这么多。 - -### T-2:build-executor SKILL.md 缩减(~4,900 → ~3,500,省 ~1,400 tokens/次执行) - -**分析**:338 行。可砍: -- TDD/SDD/Batch Inline 三种模式的重复说明——合并为选择表 -- Law 1-5 可压缩 - -### T-3:session-start 注入精确化(~100 → ~50 tokens,省 ~50 tokens/次会话) - -`hooks/session-start:10` 当前注入 ~300 字符。可压缩为更简洁的一句话: - -``` -\nYou have spec-superflow. Use /spec-superflow:workflow-start before planning or implementing.\n -``` - -### T-4:消除重复的 phase-guard 文件 - -`rules/phase-guard.md` 和 `.claude/always/phase-guard.md` 内容相同,每次 `ssf inject` 写两份。`cmd-inject.mjs:189-196` 同时写两个路径。 - -**修复**:只写 `.claude/always/phase-guard.md`(Claude Code 实际生效的路径),删 `rules/phase-guard.md`。 - -### T-5:清理 `.cursor/skills/` 过期目录(省 ~50% 空间) - -删除 v0.7 旧名 skill,只保留 9 个与 `skills/` 对齐的目录。 - -### T-6:Sub-prompt 模板合并去重 - -implementer-prompt 和 task-reviewer-prompt 有重复的「TDD 要求」段落,可提取共用。 - ---- - -## 五、Low(建议修,不阻塞) - -| ID | 文件 | 问题 | -|----|------|------| -| L-1 | `CLAUDE.md` 状态图 | ASCII 图写 `approved` → 应为 `approved-for-build` | -| L-2 | `scripts/spec-superflow.mjs:48` | CLI help 示例用 `approved` | -| L-3 | `cmd-state.mjs:100` | `state[field]` 可读 `__proto__` | -| L-4 | `cmd-state.mjs` init | TOCTOU race | -| L-5 | `state-loader.mjs` parseYaml | 负数/浮点数当字符串 | -| L-6 | `hash.mjs` contract-fresh | 重复 YAML 解析逻辑 | -| L-7 | `docs/state-machine.md:70-83` | 缺 fast-path transition | -| L-8 | `hooks/session-start:22,25,28` | `| cat` 无操作管道 | - ---- - -## 修复优先级建议 - -``` -Phase 1(阻塞性问题): C1 C2 C3 H1 H2 H3 H4 H5 H6 H7 -Phase 2(数据/体验): M1-M12 + Token T1-T6 -Phase 3(边角): L1-L8 -``` diff --git a/changes/v0.8.4-quality-audit/proposal.md b/changes/v0.8.4-quality-audit/proposal.md deleted file mode 100644 index 166c1de..0000000 --- a/changes/v0.8.4-quality-audit/proposal.md +++ /dev/null @@ -1,30 +0,0 @@ -# v0.8.4 质量审计 & 修复 - -## 背景(Why) - -spec-superflow 已经迭代到 v0.8.3,152 个测试通过。但缺乏一次系统性的代码审查——涵盖 bug 扫描、token 消耗优化、跨平台一致性。本次审计覆盖全仓库(skills/ scripts/ src/ hooks/ templates/ docs/),目标是把质量从「能用」提升到「可靠」。 - -## 变更内容(What Changes) - -### Bug 修复(23 个) -- **Critical (3)**:模板-Validator 不兼容、dead guard transition、Cursor guard 状态名错误 -- **High (8)**:缺失 guard transition、guard 可绕过、tasks 正则、路径错误、空状态验证、worktree 路径断裂 -- **Medium (12)**:H1 标题过期、DP 引用缺失、|| vs ?? 序列化 bug、warning 丢失、hash 过度匹配等 - -### Token 优化(6 项) -- workflow-start skill 精简(~4,900 → 目标 ~3,000 tokens) -- build-executor skill 精简(~4,900 → 目标 ~3,500 tokens) -- Sub-prompt 模板合并/去重 -- phase-guard 重复文件消除 -- session-start hook token 精确化 -- `.cursor/skills/` 过期技能目录清理(15→9,与 skills/ 对齐) - -## 约束 - -- 零运行时依赖保持不变 -- Skill 名称和 API 保持不变 -- 向后兼容 - -## 审计报告 - -详见 `audit-report.md`。 \ No newline at end of file diff --git a/docs/superpowers/plans/2026-07-05-issue-15-guard-hardening.md b/docs/superpowers/plans/2026-07-05-issue-15-guard-hardening.md deleted file mode 100644 index f746e17..0000000 --- a/docs/superpowers/plans/2026-07-05-issue-15-guard-hardening.md +++ /dev/null @@ -1,415 +0,0 @@ -# Issue 15 Guard Hardening Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Ship spec-superflow `0.8.10` with guarded fast-path transitions, fail-closed state transitions, build-executor branch isolation guidance, synchronized version metadata, and a PR/tag release path. - -**Architecture:** Keep the fix small and local. `scripts/guard/guard.mjs` owns transition legality, `scripts/lib/cmd-state.mjs` owns safe state writes, `skills/build-executor/SKILL.md` owns implementation-phase process discipline, and release/version files document the patch. - -**Tech Stack:** Node.js 22 native test runner, ESM scripts, shell/git/GitHub CLI, Markdown skills/docs. - ---- - -## File Structure - -- Modify `scripts/guard/guard.mjs`: add workflow-mode constraints for fast-path transitions and return structured guard failures. -- Modify `tests/lib/guard-transitions.test.mjs`: add fast-path mode-gating regression tests. -- Modify `scripts/lib/cmd-state.mjs`: make guard execution fail closed before writing `.spec-superflow.yaml`. -- Modify `tests/lib/cmd-state.test.mjs`: add CLI-level regression tests that state is not changed on rejected fast-path transitions. -- Modify `skills/build-executor/SKILL.md`: add branch/worktree preflight before implementation. -- Modify `CHANGELOG.md`: add `0.8.10` release entry. -- Modify versioned files via `node scripts/spec-superflow.mjs version 0.8.10`: `package.json`, manifests, README/INSTALL/docs, phase guard files, hook version text. - -## Task 1: Guard Fast-Path Mode Tests - -**Files:** -- Modify: `tests/lib/guard-transitions.test.mjs` - -- [ ] **Step 1: Add failing mode-gating tests** - -Insert these tests inside the existing `describe('Fast-path validation', () => { ... })` block after the two support tests: - -```js - it('SHALL reject hotfix fast-path when workflow is full', () => { - const result = runGuard('exploring', 'bridging', dir, 'full'); - assert.equal(result.ok, false, 'exploring -> bridging must be rejected in full workflow'); - assert.match(result.stderr, /workflow-mode|fast-path|hotfix|tweak/i); - }); - - it('SHALL reject tweak fast-path when workflow is full', () => { - const result = runGuard('exploring', 'approved-for-build', dir, 'full'); - assert.equal(result.ok, false, 'exploring -> approved-for-build must be rejected in full workflow'); - assert.match(result.stderr, /workflow-mode|fast-path|tweak/i); - }); -``` - -- [ ] **Step 2: Run the focused test and verify failure** - -Run: - -```bash -node --test --experimental-strip-types tests/lib/guard-transitions.test.mjs --test-name-pattern="Fast-path validation" -``` - -Expected: the two new tests fail because both transitions currently pass in `full`. - -- [ ] **Step 3: Commit the failing tests** - -```bash -git add tests/lib/guard-transitions.test.mjs -git commit -m "test: cover fast-path workflow gating" -``` - -## Task 2: Guard Fast-Path Mode Implementation - -**Files:** -- Modify: `scripts/guard/guard.mjs` -- Test: `tests/lib/guard-transitions.test.mjs` - -- [ ] **Step 1: Add mode constraints and helper** - -In `scripts/guard/guard.mjs`, after `TRANSITION_CHECKS`, add: - -```js -const TRANSITION_WORKFLOW_REQUIREMENTS = { - 'exploring:bridging': ['hotfix', 'tweak'], - 'exploring:approved-for-build': ['tweak'], -}; - -function checkWorkflowAllowed(key, workflow) { - const allowed = TRANSITION_WORKFLOW_REQUIREMENTS[key]; - if (!allowed || allowed.includes(workflow)) { - return { pass: true, checks: [] }; - } - - return { - pass: false, - checks: [{ - dimension: 'workflow-mode', - pass: false, - failures: [ - `${key.replace(':', ' -> ')} is a fast-path transition allowed only for workflow ${allowed.join(' or ')}; current workflow is ${workflow}`, - ], - }], - }; -} -``` - -- [ ] **Step 2: Call helper after transition lookup** - -In `main()`, immediately after the `if (!dimensions) { ... }` block and before `if (dimensions.length === 0)`, add: - -```js - const workflowCheck = checkWorkflowAllowed(key, workflow); - if (!workflowCheck.pass) { - if (useJson) { - console.log(JSON.stringify(workflowCheck, null, 2)); - } else { - console.error('Guard checks failed:'); - for (const c of workflowCheck.checks) { - for (const f of c.failures) { - console.error(` [FAIL] ${c.dimension}: ${f}`); - } - } - } - process.exit(1); - } -``` - -- [ ] **Step 3: Run focused tests** - -Run: - -```bash -node --test --experimental-strip-types tests/lib/guard-transitions.test.mjs --test-name-pattern="Fast-path validation" -``` - -Expected: all Fast-path validation tests pass. - -- [ ] **Step 4: Run guard transition tests** - -Run: - -```bash -node --test --experimental-strip-types tests/lib/guard-transitions.test.mjs -``` - -Expected: all tests in this file pass. - -- [ ] **Step 5: Commit implementation** - -```bash -git add scripts/guard/guard.mjs tests/lib/guard-transitions.test.mjs -git commit -m "fix: gate fast-path transitions by workflow mode" -``` - -## Task 3: State Transition Fail-Closed Tests - -**Files:** -- Modify: `tests/lib/cmd-state.test.mjs` - -- [ ] **Step 1: Add CLI fast-path rejection tests** - -Inside `describe('cmd-state: transition', () => { ... })`, after the existing `persists state across invocations` test, add: - -```js - it('rejects exploring to approved-for-build when workflow is auto', () => { - rmSync(join(tempDir, '.spec-superflow.yaml'), { force: true }); - ssf(`state init ${tempDir}`); - - const result = ssf(`state transition ${tempDir} approved-for-build`); - assert.equal(result.exitCode, 1); - assert.match(result.stderr || result.stdout, /workflow-mode|fast-path|tweak/i); - - const check = ssf(`state get ${tempDir} state`); - assert.equal(check.stdout.trim(), 'exploring'); - }); - - it('rejects exploring to bridging when workflow is full', () => { - rmSync(join(tempDir, '.spec-superflow.yaml'), { force: true }); - ssf(`state init ${tempDir}`); - ssf(`state set ${tempDir} workflow full`); - - const result = ssf(`state transition ${tempDir} bridging`); - assert.equal(result.exitCode, 1); - assert.match(result.stderr || result.stdout, /workflow-mode|fast-path|hotfix|tweak/i); - - const check = ssf(`state get ${tempDir} state`); - assert.equal(check.stdout.trim(), 'exploring'); - }); -``` - -- [ ] **Step 2: Run focused test and verify current behavior** - -Run: - -```bash -node --test --experimental-strip-types tests/lib/cmd-state.test.mjs --test-name-pattern="cmd-state: transition" -``` - -Expected: tests fail if `cmd-state` still writes state after guard failure. If Task 2 is already implemented, the first failure may already be fixed; continue with Task 4 for fail-closed hardening. - -- [ ] **Step 3: Commit tests** - -```bash -git add tests/lib/cmd-state.test.mjs -git commit -m "test: cover state transition fast-path rejection" -``` - -## Task 4: State Transition Fail-Closed Implementation - -**Files:** -- Modify: `scripts/lib/cmd-state.mjs` -- Test: `tests/lib/cmd-state.test.mjs` - -- [ ] **Step 1: Replace fail-open guard handling** - -In `scripts/lib/cmd-state.mjs`, replace the block from `// If guard fails with exit 2...` through the closing brace before `state.state = toState;` with: - -```js - const guardOutput = guardResult.stdout.toString(); - let parsed; - try { - parsed = JSON.parse(guardOutput); - } catch { - const stderr = guardResult.stderr.toString().trim(); - console.error(`Guard check failed for ${fromState} -> ${toState}:`); - console.error(' [guard-error] Guard did not return valid JSON.'); - if (stderr) console.error(` ${stderr}`); - process.exit(1); - } - - if (guardResult.status !== 0 || !parsed.pass) { - const failures = (parsed.checks || []) - .filter(c => !c.pass) - .flatMap(c => (c.failures || []).map(f => `[${c.dimension}] ${f}`)); - console.error(`Guard check failed for ${fromState} -> ${toState}:`); - for (const f of failures) console.error(` ${f}`); - if (parsed.error) console.error(` ${parsed.error}`); - if (failures.length === 0 && !parsed.error) { - console.error(' [guard-error] Guard failed without a structured failure message.'); - } - process.exit(1); - } -``` - -This parses guard output for every transition, not only when the exit status is non-zero. - -- [ ] **Step 2: Run focused state tests** - -Run: - -```bash -node --test --experimental-strip-types tests/lib/cmd-state.test.mjs --test-name-pattern="cmd-state: transition" -``` - -Expected: all transition tests pass. - -- [ ] **Step 3: Run full state command tests** - -Run: - -```bash -node --test --experimental-strip-types tests/lib/cmd-state.test.mjs -``` - -Expected: all tests in this file pass. - -- [ ] **Step 4: Commit implementation** - -```bash -git add scripts/lib/cmd-state.mjs tests/lib/cmd-state.test.mjs -git commit -m "fix: fail closed on guard transition errors" -``` - -## Task 5: Build Executor Branch Isolation - -**Files:** -- Modify: `skills/build-executor/SKILL.md` - -- [ ] **Step 1: Add branch/worktree preflight** - -In `skills/build-executor/SKILL.md`, after the config check line in `## Required Inputs`, add: - -```markdown -Branch/worktree preflight before any implementation edit: -1. Run `git branch --show-current` and `git status --short`. -2. If the branch is `main` or `master`, create or switch to a feature branch/worktree before editing: - - Preferred: `git worktree add ../- -b ` - - Acceptable: `git switch -c ` -3. If isolation cannot be created, stop and ask the user for explicit approval before editing `main` or `master`. -4. Report the chosen branch/worktree before implementation starts. -``` - -- [ ] **Step 2: Scan for contradictory branch guidance** - -Run: - -```bash -rg -n "worktree|branch|main|master" skills/build-executor/SKILL.md docs README.md INSTALL.md -``` - -Expected: no stronger contradictory instruction says to continue silently on `main`/`master`. - -- [ ] **Step 3: Commit skill update** - -```bash -git add skills/build-executor/SKILL.md -git commit -m "docs: require branch isolation before execution" -``` - -## Task 6: Version, Changelog, Verification, PR, Tag - -**Files:** -- Modify: `CHANGELOG.md` -- Modify via script: versioned manifests/docs - -- [ ] **Step 1: Sync version to 0.8.10** - -Run: - -```bash -node scripts/spec-superflow.mjs version 0.8.10 -``` - -Expected: command reports version strings updated or already correct. - -- [ ] **Step 2: Add changelog entry** - -At the top of `CHANGELOG.md`, above `## [0.8.9] - 2026-07-04`, add: - -```markdown -## [0.8.10] - 2026-07-05 - -### Fixed -- **Guard fast-path gating** — `exploring -> bridging` now requires `hotfix` or `tweak`, and `exploring -> approved-for-build` now requires `tweak`; `full`/`auto` workflows no longer skip `contract-builder` and approval gates. -- **State transition safety** — `ssf state transition` now fails closed when guard execution fails, times out, or returns invalid output, preventing state writes after unreliable guard checks. -- **Execution branch isolation** — `build-executor` now requires branch/worktree preflight before implementation and stops for explicit approval before editing `main` or `master`. -``` - -- [ ] **Step 3: Run version consistency** - -Run: - -```bash -node scripts/check-version-consistency.mjs -``` - -Expected: pass, all files at `0.8.10`. - -- [ ] **Step 4: Run build and tests** - -Run: - -```bash -npm run build -npm test -``` - -Expected: TypeScript build passes; all tests pass. - -- [ ] **Step 5: Run doctor** - -Run: - -```bash -node scripts/spec-superflow.mjs doctor -``` - -Expected: pass or only known non-blocking warnings unrelated to this patch. - -- [ ] **Step 6: Commit release prep** - -```bash -git add -A -git commit -m "chore: prepare 0.8.10 release" -``` - -- [ ] **Step 7: Push branch** - -```bash -git push -u origin fix/issue-15-guard-hardening -``` - -Expected: branch pushed successfully. - -- [ ] **Step 8: Open PR to main** - -Run: - -```bash -gh pr create --repo MageByte-Zero/spec-superflow --base main --head fix/issue-15-guard-hardening --title "Fix issue 15 guard fast-path bypass" --body "## Summary -- Gate fast-path transitions by workflow mode -- Make state transitions fail closed on guard errors -- Add build-executor branch/worktree preflight -- Prepare 0.8.10 version and changelog - -## Verification -- npm run build -- npm test -- node scripts/check-version-consistency.mjs -- node scripts/spec-superflow.mjs doctor - -Fixes #15" -``` - -Expected: GitHub returns a PR URL. - -- [ ] **Step 9: Tag after PR merge** - -After the PR is merged and local `main` is updated: - -```bash -git switch main -git pull --ff-only origin main -git tag v0.8.10 -git push origin v0.8.10 -``` - -Expected: tag push triggers `.github/workflows/ci.yml` release job. - -## Plan Self-Review - -- Spec coverage: guard mode gating is Task 1-2, fail-closed state transition is Task 3-4, branch isolation is Task 5, release/version/PR/tag is Task 6. -- Red-flag scan: no blocked planning terms remain; commands and expected outcomes are explicit. -- Type consistency: all function and file names match existing repository paths and Node ESM style. diff --git a/docs/superpowers/plans/2026-07-09-issues-42-35-34-bugfix.md b/docs/superpowers/plans/2026-07-09-issues-42-35-34-bugfix.md deleted file mode 100644 index 3d879a0..0000000 --- a/docs/superpowers/plans/2026-07-09-issues-42-35-34-bugfix.md +++ /dev/null @@ -1,1424 +0,0 @@ -# Issues 42/35/34 Bugfix Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Ship a 0.8.17 patch that fixes canonical spec paths, safe `ssf inject` platform selection, and hotfix fast-path guard consistency. - -**Architecture:** Add small shared helpers where behavior must stay consistent: `spec-paths.mjs` for spec layout discovery and workflow-aware guard resolution in `guard.mjs` for fast-path contracts. Keep parsing and validation semantics in the existing Validator engine; the patch only fixes filesystem routing, CLI defaults, guard checks, docs, and tests. - -**Tech Stack:** Node.js 22 native test runner, zero runtime dependencies, ESM `.mjs` scripts, TypeScript build output in `dist/`, Markdown docs/skills. - -## Global Constraints - -- Target release: `0.8.17`. -- Canonical delta spec path: `specs//spec.md`. -- Flat `specs/.md` and root `specs/spec.md` must not validate silently. -- `ssf inject ` must not default to all platforms. -- `--platforms all` is the explicit escape hatch for all platform injection. -- Hotfix skips full planning artifacts but still requires a fresh minimal `execution-contract.md` and DP-3 before build. -- Do not rewrite the TypeScript parser or validator engine. -- Do not add runtime dependencies. -- Preserve full workflow strictness and tweak behavior. - ---- - -## File Structure - -- Create `scripts/lib/spec-paths.mjs`: discover canonical spec files and invalid flat/root spec files. -- Create `tests/lib/spec-paths.test.mjs`: unit tests for canonical discovery and invalid path reporting. -- Modify `scripts/validate-artifacts`: use the shared helper and fail invalid/missing canonical specs. -- Modify `scripts/lib/cmd-validate.mjs`: use the shared helper and fail invalid/missing canonical specs. -- Create `tests/lib/cmd-validate-paths.test.mjs`: CLI regressions for flat and canonical spec layouts. -- Modify `scripts/guard/checks/artifacts-exist.mjs`: require at least one canonical spec for full planning artifact checks. -- Modify `scripts/guard/checks/schema-valid.mjs`: validate canonical specs only and fail invalid/missing canonical layout. -- Modify `scripts/lib/hash.mjs`: hash canonical spec files only via the shared helper. -- Modify `scripts/lib/cmd-sync.mjs`: sync canonical specs only and fail invalid layout. -- Modify `tests/lib/hash.test.mjs`: update hash fixtures to canonical paths. -- Modify `tests/lib/guard.test.mjs`, `tests/lib/guard-transitions.test.mjs`, `tests/lib/cmd-state.test.mjs`: update fixtures and hotfix guard regressions. -- Modify `tests/e2e.test.ts`: read examples from canonical spec paths. -- Move `docs/examples/add-dark-mode/specs/ui-theme.md` to `docs/examples/add-dark-mode/specs/ui-theme/spec.md`. -- Move `docs/examples/refactor-auth-boundary/specs/auth-boundary.md` to `docs/examples/refactor-auth-boundary/specs/auth-boundary/spec.md`. -- Modify `scripts/lib/cmd-inject.mjs`: add `--platforms all`, marker-based default detection, and no-write ambiguous errors. -- Modify `tests/lib/cmd-inject.test.mjs`: cover platform resolution and CLI write behavior. -- Create `scripts/guard/checks/contract-current.mjs`: compare `.spec-superflow.yaml` `contract_hash` with current `execution-contract.md`. -- Create `scripts/guard/checks/dp3-approved.mjs`: check DP-3 independently for hotfix transitions. -- Modify `scripts/guard/guard.mjs`: resolve transition checks by workflow mode instead of broad skip lists. -- Modify `README.md`, `docs/README_en.md`, `INSTALL.md`, `docs/state-machine.md`, `docs/examples/**/README.md`, `skills/workflow-start/SKILL.md`, `skills/contract-builder/SKILL.md`: document canonical specs, inject defaults, and hotfix minimal contract. -- Modify `CHANGELOG.md`, `package.json`, `package-lock.json`, plugin manifests/docs touched by `ssf version 0.8.17`: release metadata. - -## Task 1: Spec Path Helper - -**Files:** -- Create: `scripts/lib/spec-paths.mjs` -- Create: `tests/lib/spec-paths.test.mjs` - -**Interfaces:** -- Produces: `findCanonicalSpecFiles(changeDir: string): string[]` -- Produces: `findInvalidSpecFiles(changeDir: string): Array<{ path: string, expected: string }>` -- Produces: `validateSpecPathLayout(changeDir: string, options?: { requireSpecs?: boolean }): { pass: boolean, specFiles: string[], failures: string[] }` -- Consumed by Tasks 2 and 3. - -- [ ] **Step 1: Write failing helper tests** - -Create `tests/lib/spec-paths.test.mjs`: - -```js -import { describe, it, before, after } from 'node:test'; -import assert from 'node:assert/strict'; -import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs'; -import { join } from 'node:path'; -import { tmpdir } from 'node:os'; - -let mod; -let tempDir; - -describe('spec-paths', () => { - before(async () => { - tempDir = mkdtempSync(join(tmpdir(), 'ssf-spec-paths-')); - mod = await import(join(process.cwd(), 'scripts/lib/spec-paths.mjs')); - }); - - after(() => { - if (tempDir) rmSync(tempDir, { recursive: true, force: true }); - }); - - it('finds canonical specs in sorted order', () => { - const dir = mkdtempSync(join(tempDir, 'canonical-')); - mkdirSync(join(dir, 'specs', 'z-auth'), { recursive: true }); - mkdirSync(join(dir, 'specs', 'a-ui'), { recursive: true }); - writeFileSync(join(dir, 'specs', 'z-auth', 'spec.md'), 'z'); - writeFileSync(join(dir, 'specs', 'a-ui', 'spec.md'), 'a'); - - const files = mod.findCanonicalSpecFiles(dir).map(f => f.replace(dir + '/', '')); - assert.deepEqual(files, ['specs/a-ui/spec.md', 'specs/z-auth/spec.md']); - }); - - it('reports flat capability specs with expected canonical path', () => { - const dir = mkdtempSync(join(tempDir, 'flat-')); - mkdirSync(join(dir, 'specs'), { recursive: true }); - writeFileSync(join(dir, 'specs', 'ui-theme.md'), 'flat'); - - const invalid = mod.findInvalidSpecFiles(dir); - assert.deepEqual(invalid.map(i => i.path), ['specs/ui-theme.md']); - assert.deepEqual(invalid.map(i => i.expected), ['specs/ui-theme/spec.md']); - }); - - it('reports root specs/spec.md as invalid', () => { - const dir = mkdtempSync(join(tempDir, 'root-spec-')); - mkdirSync(join(dir, 'specs'), { recursive: true }); - writeFileSync(join(dir, 'specs', 'spec.md'), 'root'); - - const invalid = mod.findInvalidSpecFiles(dir); - assert.deepEqual(invalid, [{ path: 'specs/spec.md', expected: 'specs//spec.md' }]); - }); - - it('does not reject README.md inside specs', () => { - const dir = mkdtempSync(join(tempDir, 'readme-')); - mkdirSync(join(dir, 'specs'), { recursive: true }); - writeFileSync(join(dir, 'specs', 'README.md'), 'notes'); - - assert.deepEqual(mod.findInvalidSpecFiles(dir), []); - }); - - it('fails layout validation when canonical specs are required but missing', () => { - const dir = mkdtempSync(join(tempDir, 'missing-')); - mkdirSync(join(dir, 'specs'), { recursive: true }); - - const result = mod.validateSpecPathLayout(dir, { requireSpecs: true }); - assert.equal(result.pass, false); - assert.deepEqual(result.specFiles, []); - assert.ok(result.failures.some(f => f.includes('No canonical spec files found'))); - }); -}); -``` - -- [ ] **Step 2: Run helper tests and verify failure** - -Run: - -```bash -node --test tests/lib/spec-paths.test.mjs -``` - -Expected: FAIL with module-not-found for `scripts/lib/spec-paths.mjs`. - -- [ ] **Step 3: Implement `scripts/lib/spec-paths.mjs`** - -Create `scripts/lib/spec-paths.mjs`: - -```js -import fs from 'node:fs'; -import path from 'node:path'; - -function toPosix(value) { - return value.split(path.sep).join('/'); -} - -function specsDir(changeDir) { - return path.join(changeDir, 'specs'); -} - -function walk(dir, results = []) { - if (!fs.existsSync(dir)) return results; - for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { - const full = path.join(dir, entry.name); - if (entry.isDirectory()) walk(full, results); - else if (entry.isFile()) results.push(full); - } - return results; -} - -export function findCanonicalSpecFiles(changeDir) { - const root = specsDir(changeDir); - if (!fs.existsSync(root)) return []; - - return walk(root) - .filter(file => { - if (path.basename(file) !== 'spec.md') return false; - const rel = path.relative(root, file).split(path.sep); - return rel.length >= 2; - }) - .sort(); -} - -export function findInvalidSpecFiles(changeDir) { - const root = specsDir(changeDir); - if (!fs.existsSync(root)) return []; - - const invalid = []; - for (const entry of fs.readdirSync(root, { withFileTypes: true })) { - if (!entry.isFile() || !entry.name.endsWith('.md')) continue; - - const rel = `specs/${entry.name}`; - if (entry.name === 'README.md') continue; - if (entry.name === 'spec.md') { - invalid.push({ path: rel, expected: 'specs//spec.md' }); - continue; - } - - const capability = entry.name.replace(/\.md$/, ''); - invalid.push({ path: rel, expected: `specs/${capability}/spec.md` }); - } - - return invalid.sort((a, b) => a.path.localeCompare(b.path)); -} - -export function formatSpecPathFailure(item) { - return `Invalid spec path: ${item.path}. Expected: ${item.expected}`; -} - -export function validateSpecPathLayout(changeDir, options = {}) { - const requireSpecs = options.requireSpecs === true; - const specFiles = findCanonicalSpecFiles(changeDir); - const invalid = findInvalidSpecFiles(changeDir); - const failures = invalid.map(formatSpecPathFailure); - - if (requireSpecs && specFiles.length === 0) { - failures.push('No canonical spec files found. Expected at least one specs//spec.md'); - } - - return { - pass: failures.length === 0, - specFiles, - failures, - }; -} - -export function relativeSpecPath(changeDir, file) { - return toPosix(path.relative(changeDir, file)); -} -``` - -- [ ] **Step 4: Run helper tests and verify pass** - -Run: - -```bash -node --test tests/lib/spec-paths.test.mjs -``` - -Expected: PASS. - -- [ ] **Step 5: Commit helper** - -```bash -git add scripts/lib/spec-paths.mjs tests/lib/spec-paths.test.mjs -git commit -m "test: add canonical spec path helper" -``` - -## Task 2: Validation Commands And Example Migration - -**Files:** -- Modify: `scripts/validate-artifacts` -- Modify: `scripts/lib/cmd-validate.mjs` -- Create: `tests/lib/cmd-validate-paths.test.mjs` -- Modify: `tests/e2e.test.ts` -- Move: `docs/examples/add-dark-mode/specs/ui-theme.md` -> `docs/examples/add-dark-mode/specs/ui-theme/spec.md` -- Move: `docs/examples/refactor-auth-boundary/specs/auth-boundary.md` -> `docs/examples/refactor-auth-boundary/specs/auth-boundary/spec.md` -- Modify: `docs/examples/add-dark-mode/README.md` -- Modify: `docs/examples/refactor-auth-boundary/README.md` - -**Interfaces:** -- Consumes: `validateSpecPathLayout(changeDir, { requireSpecs: true })` -- Consumes: `relativeSpecPath(changeDir, file)` -- Produces: CLI behavior where invalid/missing canonical specs exit 1. - -- [ ] **Step 1: Write failing validation CLI tests** - -Create `tests/lib/cmd-validate-paths.test.mjs`: - -```js -import { describe, it, before, after } from 'node:test'; -import assert from 'node:assert/strict'; -import { execFileSync } from 'node:child_process'; -import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs'; -import { join } from 'node:path'; -import { tmpdir } from 'node:os'; - -const CLI = join(process.cwd(), 'scripts/spec-superflow.mjs'); -const LEGACY = join(process.cwd(), 'scripts/validate-artifacts'); -let tempRoot; - -function runNode(args) { - try { - const stdout = execFileSync(process.execPath, args, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }); - return { exitCode: 0, stdout, stderr: '' }; - } catch (err) { - return { exitCode: err.status || 1, stdout: err.stdout?.toString() || '', stderr: err.stderr?.toString() || err.message }; - } -} - -function writeBaseChange(dir) { - writeFileSync(join(dir, 'proposal.md'), '## Why\nThis proposal is long enough to pass validation because it explains the user problem clearly.\n## What Changes\n- Add validated behavior'); - writeFileSync(join(dir, 'design.md'), '## Context\nValidation fixture.\n## Goals\nKeep paths canonical.\n## Decisions\n### D1\n- Choice: canonical specs\n- Rationale: one path'); - writeFileSync(join(dir, 'tasks.md'), '## File Structure\n- Modify: scripts/example.mjs\n## Tasks\n- [x] Validate paths'); -} - -function writeValidSpec(file) { - writeFileSync(file, '## ADDED Requirements\n\n### Requirement: Canonical path\n\nThe system SHALL validate canonical specs.\n\n#### Scenario: Valid spec\n- **WHEN** validation runs\n- **THEN** the spec is checked'); -} - -describe('validate commands: spec paths', () => { - before(() => { - tempRoot = mkdtempSync(join(tmpdir(), 'ssf-validate-paths-')); - }); - - after(() => { - if (tempRoot) rmSync(tempRoot, { recursive: true, force: true }); - }); - - it('ssf validate rejects flat specs/.md', () => { - const dir = mkdtempSync(join(tempRoot, 'flat-')); - writeBaseChange(dir); - mkdirSync(join(dir, 'specs'), { recursive: true }); - writeValidSpec(join(dir, 'specs', 'ui-theme.md')); - - const result = runNode([CLI, 'validate', dir]); - assert.equal(result.exitCode, 1); - assert.match(result.stdout + result.stderr, /Invalid spec path: specs\/ui-theme\.md/); - assert.match(result.stdout + result.stderr, /specs\/ui-theme\/spec\.md/); - }); - - it('validate-artifacts rejects specs/ with no canonical spec.md', () => { - const dir = mkdtempSync(join(tempRoot, 'empty-specs-')); - writeBaseChange(dir); - mkdirSync(join(dir, 'specs'), { recursive: true }); - - const result = runNode([LEGACY, dir]); - assert.equal(result.exitCode, 1); - assert.match(result.stdout + result.stderr, /No canonical spec files found/); - }); - - it('ssf validate accepts canonical specs//spec.md', () => { - const dir = mkdtempSync(join(tempRoot, 'canonical-')); - writeBaseChange(dir); - mkdirSync(join(dir, 'specs', 'ui-theme'), { recursive: true }); - writeValidSpec(join(dir, 'specs', 'ui-theme', 'spec.md')); - - const result = runNode([CLI, 'validate', dir]); - assert.equal(result.exitCode, 0, result.stdout + result.stderr); - assert.match(result.stdout, /specs\/ui-theme\/spec\.md/); - }); -}); -``` - -- [ ] **Step 2: Run validation tests and verify failure** - -Run: - -```bash -node --test tests/lib/cmd-validate-paths.test.mjs -``` - -Expected: FAIL because current validation accepts flat specs and may not print canonical paths. - -- [ ] **Step 3: Update `scripts/validate-artifacts`** - -Replace its local recursive `findFiles` use with the helper: - -```js -import { readFileSync, existsSync, statSync } from 'fs'; -import { join, basename } from 'path'; -import { Validator } from '../dist/index.js'; -import { validateSpecPathLayout, relativeSpecPath } from './lib/spec-paths.mjs'; -``` - -Replace the `specsDir` block with: - -```js - const specLayout = validateSpecPathLayout(changeDir, { requireSpecs: true }); - for (const failure of specLayout.failures) { - console.log(`\n ❌ ${failure}`); - hasErrors = true; - } - - for (const specFile of specLayout.specFiles) { - try { - const content = readFileSync(specFile, 'utf-8'); - const report = validator.validateDeltaSpec(content); - const relative = relativeSpecPath(changeDir, specFile); - printReport(`${relative} (delta spec)`, report); - if (!report.valid) hasErrors = true; - } catch (e) { - const relative = relativeSpecPath(changeDir, specFile); - console.log(`\n 📋 ${relative}`); - console.log(` ❌ Error reading file: ${e instanceof Error ? e.message : 'Unknown error'}`); - hasErrors = true; - } - } -``` - -Remove the old local `findFiles` function if it becomes unused. - -- [ ] **Step 4: Update `scripts/lib/cmd-validate.mjs`** - -Add imports: - -```js -import { validateSpecPathLayout, relativeSpecPath } from './spec-paths.mjs'; -``` - -Remove the local recursive `findFiles` function if unused. Replace the `specsDir` block with: - -```js - const specLayout = validateSpecPathLayout(changeDir, { requireSpecs: true }); - for (const failure of specLayout.failures) { - printReport('specs/', { - valid: false, - issues: [{ level: 'ERROR', path: 'specs/', message: failure }], - summary: { errors: 1, warnings: 0, info: 0 }, - }); - hasErrors = true; - } - - for (const specFile of specLayout.specFiles) { - const content = readFileSync(specFile, 'utf-8'); - const report = validator.validateDeltaSpec(content); - const rel = relativeSpecPath(changeDir, specFile); - printReport(rel, report); - if (!report.valid) hasErrors = true; - } -``` - -- [ ] **Step 5: Migrate examples and e2e paths** - -Run: - -```bash -mkdir -p docs/examples/add-dark-mode/specs/ui-theme -git mv docs/examples/add-dark-mode/specs/ui-theme.md docs/examples/add-dark-mode/specs/ui-theme/spec.md -mkdir -p docs/examples/refactor-auth-boundary/specs/auth-boundary -git mv docs/examples/refactor-auth-boundary/specs/auth-boundary.md docs/examples/refactor-auth-boundary/specs/auth-boundary/spec.md -``` - -In `tests/e2e.test.ts`, replace: - -```ts -readExample('add-dark-mode', 'specs', 'ui-theme.md') -readExample('refactor-auth-boundary', 'specs', 'auth-boundary.md') -``` - -with: - -```ts -readExample('add-dark-mode', 'specs', 'ui-theme', 'spec.md') -readExample('refactor-auth-boundary', 'specs', 'auth-boundary', 'spec.md') -``` - -In example READMEs, replace: - -```markdown -- `specs/ui-theme.md` -- `specs/auth-boundary.md` -``` - -with: - -```markdown -- `specs/ui-theme/spec.md` -- `specs/auth-boundary/spec.md` -``` - -- [ ] **Step 6: Run validation-focused tests** - -Run: - -```bash -npm run build -node --test --experimental-strip-types tests/e2e.test.ts --test-name-pattern="parseDeltaSpec|Validator.validateDeltaSpec" -node --test tests/lib/spec-paths.test.mjs tests/lib/cmd-validate-paths.test.mjs -node scripts/validate-artifacts docs/examples/add-dark-mode -node scripts/spec-superflow.mjs validate docs/examples/refactor-auth-boundary -``` - -Expected: all commands PASS. - -- [ ] **Step 7: Commit validation path changes** - -```bash -git add scripts/validate-artifacts scripts/lib/cmd-validate.mjs tests/lib/cmd-validate-paths.test.mjs tests/e2e.test.ts docs/examples -git commit -m "fix: enforce canonical spec paths in validation" -``` - -## Task 3: Guard Schema, Artifact Existence, Hash, And Sync Paths - -**Files:** -- Modify: `scripts/guard/checks/artifacts-exist.mjs` -- Modify: `scripts/guard/checks/schema-valid.mjs` -- Modify: `scripts/lib/hash.mjs` -- Modify: `scripts/lib/cmd-sync.mjs` -- Modify: `tests/lib/hash.test.mjs` -- Modify: `tests/lib/guard.test.mjs` -- Modify: `tests/lib/guard-transitions.test.mjs` -- Create: `tests/lib/cmd-sync-paths.test.mjs` - -**Interfaces:** -- Consumes: `findCanonicalSpecFiles`, `validateSpecPathLayout`, `relativeSpecPath` -- Produces: full workflow guard/hash/sync behavior that uses canonical specs only. - -- [ ] **Step 1: Write failing sync path test** - -Create `tests/lib/cmd-sync-paths.test.mjs`: - -```js -import { describe, it, before, after } from 'node:test'; -import assert from 'node:assert/strict'; -import { execFileSync } from 'node:child_process'; -import { mkdtempSync, mkdirSync, writeFileSync, readFileSync, existsSync, rmSync } from 'node:fs'; -import { join } from 'node:path'; -import { tmpdir } from 'node:os'; - -const CLI = join(process.cwd(), 'scripts/spec-superflow.mjs'); -let tempRoot; - -function runSync(cwd, changeDir) { - try { - const stdout = execFileSync(process.execPath, [CLI, 'sync', changeDir], { cwd, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }); - return { exitCode: 0, stdout, stderr: '' }; - } catch (err) { - return { exitCode: err.status || 1, stdout: err.stdout?.toString() || '', stderr: err.stderr?.toString() || err.message }; - } -} - -function writeSpec(path) { - writeFileSync(path, '## ADDED Requirements\n\n### Requirement: Sync path\n\nThe system SHALL sync canonical paths.\n\n#### Scenario: Sync\n- **WHEN** sync runs\n- **THEN** the main spec is written'); -} - -describe('cmd-sync: canonical spec paths', () => { - before(() => { - tempRoot = mkdtempSync(join(tmpdir(), 'ssf-sync-paths-')); - }); - - after(() => { - if (tempRoot) rmSync(tempRoot, { recursive: true, force: true }); - }); - - it('syncs canonical specs to main specs//spec.md', () => { - const repo = mkdtempSync(join(tempRoot, 'repo-')); - const change = join(repo, 'changes', 'canonical'); - mkdirSync(join(change, 'specs', 'ui-theme'), { recursive: true }); - writeSpec(join(change, 'specs', 'ui-theme', 'spec.md')); - - const result = runSync(repo, change); - assert.equal(result.exitCode, 0, result.stdout + result.stderr); - assert.equal(existsSync(join(repo, 'specs', 'ui-theme', 'spec.md')), true); - assert.match(readFileSync(join(repo, 'specs', 'ui-theme', 'spec.md'), 'utf-8'), /Sync path/); - }); - - it('rejects flat specs before syncing', () => { - const repo = mkdtempSync(join(tempRoot, 'repo-flat-')); - const change = join(repo, 'changes', 'flat'); - mkdirSync(join(change, 'specs'), { recursive: true }); - writeSpec(join(change, 'specs', 'ui-theme.md')); - - const result = runSync(repo, change); - assert.equal(result.exitCode, 1); - assert.match(result.stdout + result.stderr, /Invalid spec path: specs\/ui-theme\.md/); - assert.equal(existsSync(join(repo, 'specs', 'ui-theme', 'spec.md')), false); - }); -}); -``` - -- [ ] **Step 2: Update guard/hash fixtures to canonical paths** - -In `tests/lib/hash.test.mjs`, replace root/flat specs with canonical directories. Example replacement for the all-artifacts test: - -```js -mkdirSync(join(tempDir, 'specs', 'ui-theme'), { recursive: true }); -writeFileSync(join(tempDir, 'specs', 'ui-theme', 'spec.md'), '# Spec\nRequirement content'); -``` - -For deterministic ordering, use: - -```js -mkdirSync(join(tempDir, 'specs', 'z-auth'), { recursive: true }); -mkdirSync(join(tempDir, 'specs', 'a-ui'), { recursive: true }); -writeFileSync(join(tempDir, 'specs', 'z-auth', 'spec.md'), 'auth spec'); -writeFileSync(join(tempDir, 'specs', 'a-ui', 'spec.md'), 'ui spec'); -``` - -In `tests/lib/guard.test.mjs` and `tests/lib/guard-transitions.test.mjs`, replace `specs/spec.md` and `specs/test.md` fixtures with: - -```js -mkdirSync(join(tempDir, 'specs', 'test'), { recursive: true }); -writeFileSync(join(tempDir, 'specs', 'test', 'spec.md'), '## ADDED Requirements\n### Requirement: Test\nThe system SHALL work.\n#### Scenario: Test\n- **WHEN** test\n- **THEN** test'); -``` - -- [ ] **Step 3: Run focused tests and verify failure where commands still use old paths** - -Run: - -```bash -node --test tests/lib/hash.test.mjs tests/lib/guard.test.mjs tests/lib/guard-transitions.test.mjs tests/lib/cmd-sync-paths.test.mjs -``` - -Expected: at least sync or guard path assertions FAIL before implementation is wired. - -- [ ] **Step 4: Update `artifacts-exist`** - -Add import: - -```js -import { validateSpecPathLayout } from '../../lib/spec-paths.mjs'; -``` - -Replace the current `specs/` check with: - -```js - if (!skipList.includes('specs')) { - const specLayout = validateSpecPathLayout(changeDir, { requireSpecs: true }); - failures.push(...specLayout.failures); - } -``` - -- [ ] **Step 5: Update `schema-valid`** - -Add import: - -```js -import { validateSpecPathLayout, relativeSpecPath } from '../../lib/spec-paths.mjs'; -``` - -Replace its `specsDir` loop with: - -```js - const specLayout = validateSpecPathLayout(changeDir, { requireSpecs: true }); - failures.push(...specLayout.failures); - - for (const specFile of specLayout.specFiles) { - const content = fs.readFileSync(specFile, 'utf-8'); - const report = validator.validateDeltaSpec(content); - const rel = relativeSpecPath(changeDir, specFile); - for (const issue of report.issues) { - if (issue.level === 'ERROR') { - failures.push(`${rel}: ${issue.message}`); - } else if (issue.level === 'WARNING') { - warnings.push(`${rel}: ${issue.message}`); - } - } - } -``` - -- [ ] **Step 6: Update `hash.mjs`** - -Add import: - -```js -import { findCanonicalSpecFiles } from './spec-paths.mjs'; -``` - -Replace the `walkDir` spec collection in `computeArtifactsHash()` with: - -```js - for (const f of findCanonicalSpecFiles(changeDir)) { - hash.update(fs.readFileSync(f, 'utf-8')); - hasContent = true; - } -``` - -Remove `walkDir()` if unused. - -- [ ] **Step 7: Update `cmd-sync.mjs`** - -Add import: - -```js -import { validateSpecPathLayout } from './spec-paths.mjs'; -``` - -Replace `findSpecFiles()` usage for change specs with: - -```js - const layout = validateSpecPathLayout(changeDir, { requireSpecs: true }); - if (!layout.pass) { - for (const failure of layout.failures) console.error(failure); - process.exit(1); - } -``` - -Use `layout.specFiles` for sync. Keep conflict detection over all changes but route each change through `validateSpecPathLayout(dirPath, { requireSpecs: false })`; skip changes with no canonical specs and fail on invalid layout. - -For each canonical spec: - -```js - const relative = specFile.replace(changeSpecsDir + '/', ''); - const capabilityDir = relative.replace(/\/spec\.md$/, ''); -``` - -- [ ] **Step 8: Run focused tests** - -Run: - -```bash -node --test tests/lib/hash.test.mjs tests/lib/guard.test.mjs tests/lib/guard-transitions.test.mjs tests/lib/cmd-sync-paths.test.mjs -``` - -Expected: PASS. - -- [ ] **Step 9: Commit guard/hash/sync path changes** - -```bash -git add scripts/guard/checks/artifacts-exist.mjs scripts/guard/checks/schema-valid.mjs scripts/lib/hash.mjs scripts/lib/cmd-sync.mjs tests/lib/hash.test.mjs tests/lib/guard.test.mjs tests/lib/guard-transitions.test.mjs tests/lib/cmd-sync-paths.test.mjs -git commit -m "fix: use canonical spec paths in guard hash and sync" -``` - -## Task 4: Safe `ssf inject` Platform Defaults - -**Files:** -- Modify: `scripts/lib/cmd-inject.mjs` -- Modify: `tests/lib/cmd-inject.test.mjs` -- Modify: `scripts/spec-superflow.mjs` - -**Interfaces:** -- Produces: `parsePlatformList(value?: string): string[] | null` -- Produces: `detectProjectPlatforms(projectRoot: string): string[]` -- Produces: `resolvePlatforms(value: string | undefined, projectRoot: string): { ok: true, platforms: string[] } | { ok: false, message: string }` - -- [ ] **Step 1: Add failing inject platform tests** - -Append to `tests/lib/cmd-inject.test.mjs`: - -```js -import { mkdtempSync, mkdirSync, writeFileSync, existsSync, rmSync } from 'node:fs'; -import { tmpdir } from 'node:os'; -import { execFileSync } from 'node:child_process'; -``` - -If those imports already exist after editing, merge them into the existing import list. - -Add these tests: - -```js -describe('cmd-inject: platform resolution', () => { - let resolvePlatforms, detectProjectPlatforms; - - before(async () => { - const modulePath = join(process.cwd(), 'scripts/lib/cmd-inject.mjs'); - const mod = await import(modulePath); - resolvePlatforms = mod.resolvePlatforms; - detectProjectPlatforms = mod.detectProjectPlatforms; - }); - - it('resolves explicit all to all supported platforms', () => { - const result = resolvePlatforms('all', process.cwd()); - assert.deepEqual(result, { ok: true, platforms: ['claude', 'cursor', 'copilot', 'gemini'] }); - }); - - it('detects Cursor from .cursor marker', () => { - const dir = mkdtempSync(join(tmpdir(), 'ssf-inject-cursor-')); - try { - mkdirSync(join(dir, '.cursor'), { recursive: true }); - assert.deepEqual(detectProjectPlatforms(dir), ['cursor']); - assert.deepEqual(resolvePlatforms(undefined, dir), { ok: true, platforms: ['cursor'] }); - } finally { - rmSync(dir, { recursive: true, force: true }); - } - }); - - it('rejects omitted platforms when no marker exists', () => { - const dir = mkdtempSync(join(tmpdir(), 'ssf-inject-none-')); - try { - const result = resolvePlatforms(undefined, dir); - assert.equal(result.ok, false); - assert.match(result.message, /--platforms/); - } finally { - rmSync(dir, { recursive: true, force: true }); - } - }); - - it('rejects omitted platforms when multiple markers exist', () => { - const dir = mkdtempSync(join(tmpdir(), 'ssf-inject-multi-')); - try { - mkdirSync(join(dir, '.cursor'), { recursive: true }); - mkdirSync(join(dir, '.claude'), { recursive: true }); - const result = resolvePlatforms(undefined, dir); - assert.equal(result.ok, false); - assert.match(result.message, /multiple/i); - } finally { - rmSync(dir, { recursive: true, force: true }); - } - }); -}); - -describe('cmd-inject: CLI writes', () => { - const CLI = join(process.cwd(), 'scripts/spec-superflow.mjs'); - - function runInject(cwd, changeDir, extraArgs = []) { - try { - const stdout = execFileSync(process.execPath, [CLI, 'inject', changeDir, ...extraArgs], { cwd, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }); - return { exitCode: 0, stdout, stderr: '' }; - } catch (err) { - return { exitCode: err.status || 1, stdout: err.stdout?.toString() || '', stderr: err.stderr?.toString() || err.message }; - } - } - - it('cursor-only injection does not write GEMINI.md', () => { - const root = mkdtempSync(join(tmpdir(), 'ssf-inject-cli-cursor-')); - try { - const change = join(root, 'change'); - mkdirSync(change, { recursive: true }); - writeFileSync(join(change, '.spec-superflow.yaml'), 'state: exploring\nworkflow: full\nchange_name: inject-test\n'); - const result = runInject(root, change, ['--platforms', 'cursor']); - assert.equal(result.exitCode, 0, result.stdout + result.stderr); - assert.equal(existsSync(join(root, '.cursor', 'rules', 'phase-guard.mdc')), true); - assert.equal(existsSync(join(root, 'GEMINI.md')), false); - } finally { - rmSync(root, { recursive: true, force: true }); - } - }); - - it('omitted ambiguous platform exits before writing files', () => { - const root = mkdtempSync(join(tmpdir(), 'ssf-inject-cli-none-')); - try { - const change = join(root, 'change'); - mkdirSync(change, { recursive: true }); - writeFileSync(join(change, '.spec-superflow.yaml'), 'state: exploring\nworkflow: full\nchange_name: inject-test\n'); - const result = runInject(root, change); - assert.equal(result.exitCode, 2); - assert.match(result.stderr || result.stdout, /--platforms/); - assert.equal(existsSync(join(root, '.cursor')), false); - assert.equal(existsSync(join(root, 'GEMINI.md')), false); - } finally { - rmSync(root, { recursive: true, force: true }); - } - }); -}); -``` - -- [ ] **Step 2: Run inject tests and verify failure** - -Run: - -```bash -node --test tests/lib/cmd-inject.test.mjs -``` - -Expected: FAIL because `resolvePlatforms` and `detectProjectPlatforms` do not exist and default still writes all platforms. - -- [ ] **Step 3: Implement platform parsing and detection** - -In `scripts/lib/cmd-inject.mjs`, add exports near `SUPPORTED_PLATFORMS`: - -```js -function unique(values) { - return [...new Set(values)]; -} - -export function parsePlatformList(value) { - if (!value) return null; - const requested = value.split(',').map(p => p.trim().toLowerCase()).filter(Boolean); - if (requested.includes('all')) { - if (requested.length > 1) return ['__invalid_all_combo__']; - return [...SUPPORTED_PLATFORMS]; - } - return unique(requested); -} - -export function detectProjectPlatforms(projectRoot) { - const detected = []; - if (existsSync(join(projectRoot, '.claude'))) detected.push('claude'); - if (existsSync(join(projectRoot, '.cursor')) || existsSync(join(projectRoot, '.cursor', 'rules'))) detected.push('cursor'); - if (existsSync(join(projectRoot, '.github', 'copilot-instructions.md'))) detected.push('copilot'); - if (existsSync(join(projectRoot, 'GEMINI.md'))) detected.push('gemini'); - return detected; -} - -export function resolvePlatforms(value, projectRoot) { - const explicit = parsePlatformList(value); - if (explicit) { - if (explicit.includes('__invalid_all_combo__')) { - return { ok: false, message: '`all` cannot be combined with other platforms. Use --platforms all or a comma-separated platform list.' }; - } - const invalid = explicit.filter(p => !SUPPORTED_PLATFORMS.includes(p)); - if (invalid.length > 0) { - return { ok: false, message: `Unsupported platform(s): ${invalid.join(', ')}. Supported: ${SUPPORTED_PLATFORMS.join(', ')} or all` }; - } - return { ok: true, platforms: explicit }; - } - - const detected = detectProjectPlatforms(projectRoot); - if (detected.length === 1) { - return { ok: true, platforms: detected }; - } - if (detected.length === 0) { - return { ok: false, message: 'Could not detect target platform. Re-run with --platforms claude|cursor|copilot|gemini or --platforms all.' }; - } - return { ok: false, message: `Detected multiple platform markers (${detected.join(', ')}). Re-run with --platforms or --platforms all.` }; -} -``` - -In `run(args)`, replace current `requested` construction and invalid-platform block with: - -```js - const projectRoot = process.cwd(); - const resolved = resolvePlatforms(values.platforms, projectRoot); - if (!resolved.ok) { - console.error(resolved.message); - process.exit(2); - } - const requested = resolved.platforms; -``` - -Remove the later duplicate `const projectRoot = process.cwd();`. - -Update usage text: - -```js -console.error('Usage: ssf inject [--platforms claude,cursor,copilot,gemini|all] [--json]'); -``` - -- [ ] **Step 4: Update CLI help text** - -In `scripts/spec-superflow.mjs`, replace: - -```text -inject Generate phase-guard artifacts for Claude/Cursor/Copilot/Gemini -``` - -with: - -```text -inject Generate phase-guard artifacts; use --platforms when platform is ambiguous -``` - -- [ ] **Step 5: Run inject tests** - -Run: - -```bash -node --test tests/lib/cmd-inject.test.mjs -``` - -Expected: PASS. - -- [ ] **Step 6: Commit inject fix** - -```bash -git add scripts/lib/cmd-inject.mjs scripts/spec-superflow.mjs tests/lib/cmd-inject.test.mjs -git commit -m "fix: make inject platform selection explicit" -``` - -## Task 5: Hotfix Minimal Guard Contract - -**Files:** -- Create: `scripts/guard/checks/contract-current.mjs` -- Create: `scripts/guard/checks/dp3-approved.mjs` -- Modify: `scripts/guard/guard.mjs` -- Modify: `tests/lib/guard.test.mjs` -- Modify: `tests/lib/guard-transitions.test.mjs` -- Modify: `tests/lib/cmd-state.test.mjs` - -**Interfaces:** -- Produces: `checkContractCurrent(changeDir: string): { pass: boolean, failures: string[] }` -- Produces: `checkDp3Approved(changeDir: string): { pass: boolean, failures: string[] }` -- Produces: workflow-aware guard dimensions where hotfix has its own minimal contract checks. - -- [ ] **Step 1: Add failing hotfix guard tests** - -In `tests/lib/guard.test.mjs`, add a new describe block: - -```js -describe('guard: hotfix minimal contract', () => { - let dir; - - before(() => { - dir = mkdtempSync(join(tmpdir(), 'ssf-hotfix-guard-')); - writeFileSync(join(dir, '.spec-superflow.yaml'), 'state: exploring\nworkflow: hotfix\nchange_name: hotfix-test\n'); - }); - - after(() => { - if (dir) rmSync(dir, { recursive: true, force: true }); - }); - - function run(fromState, toState) { - try { - const stdout = execSync( - `node ${GUARD_PATH} check ${dir} ${fromState} ${toState} --json --workflow hotfix`, - { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] } - ); - return { exitCode: 0, output: JSON.parse(stdout.trim()) }; - } catch (err) { - if (err.stdout) { - try { return { exitCode: err.status, output: JSON.parse(err.stdout.trim()) }; } - catch { return { exitCode: err.status, output: err.stderr || err.message }; } - } - return { exitCode: err.status || 1, output: err.stderr || err.message }; - } - } - - it('allows exploring to bridging without full planning artifacts', () => { - const result = run('exploring', 'bridging'); - assert.equal(result.exitCode, 0, JSON.stringify(result.output)); - assert.deepEqual(result.output.checks, []); - }); - - it('blocks bridging to approved-for-build without execution-contract.md', () => { - const result = run('bridging', 'approved-for-build'); - assert.equal(result.exitCode, 1); - assert.ok(result.output.checks.some(c => c.dimension === 'contract-current')); - }); - - it('blocks bridging to approved-for-build without DP-3', () => { - writeFileSync(join(dir, 'execution-contract.md'), '# Execution Contract\n\n## Intent Lock\n\nHotfix contract.\n'); - execSync(`node ${join(process.cwd(), 'scripts/spec-superflow.mjs')} state init ${dir}`); - execSync(`node ${join(process.cwd(), 'scripts/spec-superflow.mjs')} state set ${dir} workflow hotfix`); - const result = run('bridging', 'approved-for-build'); - assert.equal(result.exitCode, 1); - assert.ok(result.output.checks.some(c => c.dimension === 'dp3-approved')); - }); - - it('allows bridging to approved-for-build with fresh contract and DP-3', () => { - execSync(`node ${join(process.cwd(), 'scripts/spec-superflow.mjs')} state set ${dir} dp_3_result approved`); - const result = run('bridging', 'approved-for-build'); - assert.equal(result.exitCode, 0, JSON.stringify(result.output)); - }); -}); -``` - -- [ ] **Step 2: Update transition fixtures** - -In `tests/lib/guard-transitions.test.mjs`, update fast-path expectations: - -```js -{ from: 'exploring', to: 'bridging', workflow: 'hotfix' }, -{ from: 'exploring', to: 'approved-for-build', workflow: 'tweak' }, -``` - -Keep full workflow rejection tests. Add: - -```js - it('SHALL reject tweak route to bridging', () => { - const result = runGuard('exploring', 'bridging', dir, 'tweak'); - const output = guardOutput(result); - assert.equal(result.ok, false, 'tweak should use exploring -> approved-for-build, not bridging'); - assert.match(output, /workflow-mode|hotfix/i); - }); -``` - -- [ ] **Step 3: Run guard tests and verify failure** - -Run: - -```bash -node --test tests/lib/guard.test.mjs tests/lib/guard-transitions.test.mjs --test-name-pattern="hotfix|Fast-path" -``` - -Expected: FAIL because hotfix still inherits `artifacts-exist` and no contract-current/dp3-approved checks exist. - -- [ ] **Step 4: Create `contract-current` check** - -Create `scripts/guard/checks/contract-current.mjs`: - -```js -import fs from 'node:fs'; -import path from 'node:path'; -import { readState } from '../../lib/state-loader.mjs'; -import { computeContractHash } from '../../lib/hash.mjs'; - -export function checkContractCurrent(changeDir) { - const contractPath = path.join(changeDir, 'execution-contract.md'); - if (!fs.existsSync(contractPath)) { - return { pass: false, failures: ['execution-contract.md: missing'] }; - } - - const content = fs.readFileSync(contractPath, 'utf-8').trim(); - if (content.length === 0) { - return { pass: false, failures: ['execution-contract.md: empty'] }; - } - - const state = readState(changeDir); - const current = computeContractHash(changeDir); - if (!state.contract_hash || state.contract_hash === 'null') { - return { pass: false, failures: ['execution-contract.md is not recorded in state. Run ssf state init after contract generation.'] }; - } - if (state.contract_hash !== current) { - return { pass: false, failures: ['execution-contract.md is stale: contract hash mismatch. Re-run contract-builder or ssf state rebuild.'] }; - } - - return { pass: true, failures: [] }; -} -``` - -- [ ] **Step 5: Create `dp3-approved` check** - -Create `scripts/guard/checks/dp3-approved.mjs`: - -```js -import { readState } from '../../lib/state-loader.mjs'; - -export function checkDp3Approved(changeDir) { - const state = readState(changeDir); - if (!state.dp_3_result) { - return { - pass: false, - failures: ['DP-3 (dp_3_result) is not recorded — minimal contract approval is required before hotfix build'], - }; - } - return { pass: true, failures: [] }; -} -``` - -- [ ] **Step 6: Make `guard.mjs` workflow-aware** - -In `scripts/guard/guard.mjs`, replace fast-path entries and broad skip behavior with explicit workflow resolution: - -```js -const WORKFLOW_TRANSITION_CHECKS = { - hotfix: { - 'exploring:bridging': [], - 'bridging:approved-for-build': ['contract-current', 'dp3-approved'], - 'approved-for-build:executing': ['contract-current', 'dp3-approved'], - }, - tweak: { - 'exploring:approved-for-build': [], - }, -}; - -const TRANSITION_WORKFLOW_REQUIREMENTS = { - 'exploring:bridging': ['hotfix'], - 'exploring:approved-for-build': ['tweak'], -}; - -function resolveDimensions(key, workflow) { - return WORKFLOW_TRANSITION_CHECKS[workflow]?.[key] ?? TRANSITION_CHECKS[key]; -} -``` - -Then replace: - -```js -const dimensions = TRANSITION_CHECKS[key]; -``` - -with: - -```js -const dimensions = resolveDimensions(key, workflow); -``` - -Keep `checkWorkflowAllowed()` but update its allowed map to the new `TRANSITION_WORKFLOW_REQUIREMENTS`. - -Add check runners: - -```js -'contract-current': (dir) => checkContractCurrent(dir), -'dp3-approved': (dir) => checkDp3Approved(dir), -``` - -and imports: - -```js -import { checkContractCurrent } from './checks/contract-current.mjs'; -import { checkDp3Approved } from './checks/dp3-approved.mjs'; -``` - -Remove `applyWorkflowMode()` or leave it as a no-op only if no tests depend on skipped metadata. Prefer removal and update tests to assert explicit dimensions. - -- [ ] **Step 7: Replace skip-list implementation tests** - -In `tests/lib/guard.test.mjs`, replace the existing workflow mode skipping tests that assert `skipped: true` with behavior-level tests: - -```js - it('tweak mode allows exploring to approved-for-build without artifacts', () => { - const result = runGuardWithMode('exploring', 'approved-for-build', 'tweak'); - assert.equal(result.exitCode, 0, JSON.stringify(result.output)); - assert.deepEqual(result.output.checks, []); - }); - - it('hotfix mode allows exploring to bridging without artifacts', () => { - const result = runGuardWithMode('exploring', 'bridging', 'hotfix'); - assert.equal(result.exitCode, 0, JSON.stringify(result.output)); - assert.deepEqual(result.output.checks, []); - }); - - it('full mode keeps requiring artifacts on specifying to bridging', () => { - const result = runGuardWithMode('specifying', 'bridging', 'full'); - const checks = result.output.checks; - assert.ok(checks.some(c => c.dimension === 'artifacts-exist')); - assert.ok(checks.some(c => c.dimension === 'schema-valid')); - }); -``` - -Keep the invalid workflow mode test unchanged. - -- [ ] **Step 8: Run guard/state focused tests** - -Run: - -```bash -node --test tests/lib/guard.test.mjs tests/lib/guard-transitions.test.mjs tests/lib/cmd-state.test.mjs --test-name-pattern="hotfix|Fast-path|transition" -``` - -Expected: PASS. - -- [ ] **Step 9: Commit hotfix guard** - -```bash -git add scripts/guard/guard.mjs scripts/guard/checks/contract-current.mjs scripts/guard/checks/dp3-approved.mjs tests/lib/guard.test.mjs tests/lib/guard-transitions.test.mjs tests/lib/cmd-state.test.mjs -git commit -m "fix: make hotfix guard use minimal contract" -``` - -## Task 6: Documentation, Version, And Release Metadata - -**Files:** -- Modify: `README.md` -- Modify: `docs/README_en.md` -- Modify: `INSTALL.md` -- Modify: `docs/state-machine.md` -- Modify: `skills/workflow-start/SKILL.md` -- Modify: `skills/contract-builder/SKILL.md` -- Modify: `CHANGELOG.md` -- Modify versioned manifests touched by `node scripts/spec-superflow.mjs version 0.8.17` -- Modify: `package-lock.json` - -**Interfaces:** -- Consumes: behavior implemented in Tasks 1-5. -- Produces: docs and metadata matching runtime behavior. - -- [ ] **Step 1: Update docs for canonical spec path** - -Run: - -```bash -rg -n "specs/|specs/.+\\.md|specs/.+/spec\\.md|specs/\\*" README.md docs INSTALL.md skills -``` - -Replace user-facing flat examples with: - -```text -specs//spec.md -``` - -For example, in `INSTALL.md`, ensure artifact tree examples use: - -```text -├── specs/ -│ └── / -│ └── spec.md -``` - -- [ ] **Step 2: Update docs for `ssf inject`** - -In README/INSTALL/docs CLI sections, document: - -```bash -ssf inject --platforms cursor -ssf inject --platforms all -``` - -State that omitted `--platforms` only works when exactly one project marker is detected. - -- [ ] **Step 3: Update hotfix docs and skills** - -In `docs/state-machine.md`, `README.md`, `docs/README_en.md`, and `skills/workflow-start/SKILL.md`, describe: - -```text -hotfix: exploring -> bridging -> approved-for-build -> executing -``` - -with minimal contract-builder and DP-3. Do not say hotfix requires `proposal.md`, `design.md`, `tasks.md`, or `specs/`. - -In `skills/contract-builder/SKILL.md`, update Hotfix Mode to include: - -```markdown -After writing the minimal contract, run `node "${CLAUDE_PLUGIN_ROOT}/scripts/spec-superflow.mjs" state init ` or `state rebuild` so `contract_hash` is recorded. DP-3 remains mandatory before build. -``` - -- [ ] **Step 4: Add changelog entry** - -At the top of `CHANGELOG.md`, add: - -```markdown -## 0.8.17 - -- Fixed canonical delta spec paths: validation, guard checks, hashing, sync, examples, and docs now use `specs//spec.md`. -- Fixed `ssf inject` default behavior so ambiguous projects require `--platforms` instead of writing every platform file. -- Fixed hotfix fast-path guards so hotfix can skip full planning artifacts while still requiring a fresh minimal contract and DP-3 approval. -``` - -- [ ] **Step 5: Sync version metadata** - -Run: - -```bash -node scripts/spec-superflow.mjs version 0.8.17 -npm install --package-lock-only --ignore-scripts -``` - -Expected: versioned manifests/docs align to `0.8.17`, and `package-lock.json` matches `package.json`. - -- [ ] **Step 6: Run docs consistency checks** - -Run: - -```bash -node scripts/check-version-consistency.mjs -node scripts/spec-superflow.mjs doctor -rg -n "specs/[A-Za-z0-9_-]+\\.md|specs/spec\\.md" README.md docs INSTALL.md skills scripts tests -``` - -Expected: - -- Version consistency passes. -- Doctor passes. -- Remaining flat path matches are either test fixtures intentionally asserting invalid paths or historical design/plan docs; no current install/readme/example/skill guidance uses flat paths as canonical. - -- [ ] **Step 7: Commit docs and metadata** - -```bash -git add README.md docs/README_en.md INSTALL.md docs/state-machine.md docs/examples skills/workflow-start/SKILL.md skills/contract-builder/SKILL.md CHANGELOG.md package.json package-lock.json .claude-plugin .cursor-plugin .codex-plugin .github .opencode .agents gemini-extension.json scripts/spec-superflow.mjs -git commit -m "docs: document canonical paths inject and hotfix" -``` - -## Task 7: Full Verification And Issue Closure Prep - -**Files:** -- No source edits expected unless verification exposes a defect. -- Create no release tag in this task unless the user explicitly asks to release. - -**Interfaces:** -- Consumes: all implementation tasks. -- Produces: verified local state and issue response draft. - -- [ ] **Step 1: Run full build and tests** - -Run: - -```bash -npm run build -npm test -``` - -Expected: PASS. - -- [ ] **Step 2: Run artifact validation examples** - -Run: - -```bash -node scripts/validate-artifacts docs/examples/add-dark-mode -node scripts/validate-artifacts docs/examples/refactor-auth-boundary -node scripts/spec-superflow.mjs validate docs/examples/add-dark-mode -node scripts/spec-superflow.mjs validate docs/examples/refactor-auth-boundary -``` - -Expected: all commands PASS and print canonical `specs//spec.md` paths. - -- [ ] **Step 3: Re-run bug reproductions** - -Run #42 reproduction: - -```bash -tmp=$(mktemp -d) -mkdir -p "$tmp/specs" -printf '## Why\nThis is long enough to validate the proposal section for this reproduction.\n## What Changes\n- Repro\n' > "$tmp/proposal.md" -printf '## ADDED Requirements\n\n### Requirement: Flat\n\nThe system SHALL reject flat specs.\n\n#### Scenario: Reject\n- **WHEN** validation runs\n- **THEN** it fails\n' > "$tmp/specs/ui-theme.md" -node scripts/spec-superflow.mjs validate "$tmp" -status=$? -rm -rf "$tmp" -test "$status" -eq 1 -``` - -Expected: command exits 1 and mentions `Invalid spec path`. - -Run #35 reproduction: - -```bash -tmp=$(mktemp -d) -change="$tmp/change" -mkdir -p "$change" "$tmp/.cursor" -printf 'state: exploring\nworkflow: full\nchange_name: inject-test\n' > "$change/.spec-superflow.yaml" -(cd "$tmp" && node /Users/magebte/Documents/magebyte/open-source-plugins/spec-superflow/scripts/spec-superflow.mjs inject "$change") -test -f "$tmp/.cursor/rules/phase-guard.mdc" -test ! -f "$tmp/GEMINI.md" -rm -rf "$tmp" -``` - -Expected: Cursor output exists and `GEMINI.md` does not. - -Run #34 reproduction: - -```bash -tmp=$(mktemp -d) -printf 'state: exploring\nworkflow: hotfix\nchange_name: hotfix-test\n' > "$tmp/.spec-superflow.yaml" -node scripts/guard/guard.mjs check "$tmp" exploring bridging --workflow hotfix --json -status=$? -rm -rf "$tmp" -test "$status" -eq 0 -``` - -Expected: exit 0. - -- [ ] **Step 4: Run release hygiene checks** - -Run: - -```bash -node scripts/check-version-consistency.mjs -node scripts/spec-superflow.mjs doctor -git status --short -``` - -Expected: - -- Version consistency passes. -- Doctor passes. -- `git status --short` is clean. - -- [ ] **Step 5: Prepare issue response draft** - -Draft this response for #42/#35/#34 after implementation is pushed: - -```markdown -Fixed in the 0.8.17 patch branch. - -- #42: canonical delta specs are now `specs//spec.md`; flat specs fail validation with migration hints instead of being silently skipped. -- #35: `ssf inject` no longer defaults to all platforms; Cursor-only injection does not write `GEMINI.md`, and `--platforms all` is explicit. -- #34: hotfix now enters minimal contract-builder without full planning artifacts, but still requires a fresh `execution-contract.md` and DP-3 before build. - -Verification: -- `npm run build` -- `npm test` -- example validation for `docs/examples/add-dark-mode` and `docs/examples/refactor-auth-boundary` -- `ssf doctor` -``` diff --git a/docs/superpowers/specs/2026-07-05-issue-15-guard-hardening-design.md b/docs/superpowers/specs/2026-07-05-issue-15-guard-hardening-design.md deleted file mode 100644 index bcd2bd4..0000000 --- a/docs/superpowers/specs/2026-07-05-issue-15-guard-hardening-design.md +++ /dev/null @@ -1,112 +0,0 @@ -# Issue 15 Guard Hardening Design - -Date: 2026-07-05 -Target release: 0.8.10 -Branch: fix/issue-15-guard-hardening - -## Context - -GitHub issue #15 reports that spec-superflow v0.8.8 can skip workflow stages. The reported session admitted it manually edited `.spec-superflow.yaml`, skipped `contract-builder` and `approved-for-build`, and then wrote implementation code. Local review found the report is valid: - -- The guard matrix currently defines `exploring -> bridging` and `exploring -> approved-for-build` as fast-path transitions, but does not reject those transitions when the workflow is `full` or `auto`. -- `ssf state transition` currently fails open if the guard process errors or returns non-JSON output. -- `build-executor` does not require branch/worktree isolation before implementation, so a main or master branch can be modified directly. - -The patch must fix the concrete bypasses without redesigning the full multi-platform enforcement model. - -## Goals - -- Release a narrow 0.8.10 patch that makes guard behavior match the documented state machine. -- Keep hotfix and tweak fast paths available only in their intended workflow modes. -- Ensure state transitions fail closed when guard execution is unreliable. -- Add execution-phase branch isolation instructions so main/master edits require explicit handling. -- Keep package, manifest, documentation, changelog, and phase-guard version strings consistent. -- Produce a PR to `main`; after merge, tag `v0.8.10` to trigger the release workflow. - -## Non-Goals - -- Do not build a platform-specific tool-call or file-edit interception system in this patch. -- Do not remove hotfix or tweak workflows. -- Do not change the artifact schema or rewrite the state machine. -- Do not claim that prompt-level instructions are equivalent to system-level write protection. - -## Proposed Changes - -### Guard Fast-Path Mode Gating - -Add explicit workflow-mode validation before guard checks are treated as passing: - -- `exploring -> bridging` is valid only for `hotfix` or `tweak`. -- `exploring -> approved-for-build` is valid only for `tweak`. -- `full` rejects both fast-path shortcuts. -- `auto` is normalized to `full` by `cmd-state`, so it also rejects direct fast-path shortcuts unless inference has already persisted `hotfix` or `tweak`. - -The guard output should identify this as a workflow-mode failure, not an unknown transition. - -### State Transition Fail-Closed - -`ssf state transition` must not update `.spec-superflow.yaml` unless the guard process completes successfully and returns a passing result. - -Failure cases that must block transition: - -- guard process exits non-zero -- guard stdout cannot be parsed as JSON -- guard process times out or is terminated -- guard script errors before producing a pass result - -This replaces the current warning-and-continue behavior. - -### Build Executor Branch Isolation - -Update `skills/build-executor/SKILL.md` so implementation begins with a branch/worktree preflight: - -1. Run `git branch --show-current` and inspect worktree state. -2. If current branch is `main` or `master`, create or switch to a feature branch/worktree before editing. -3. If branch/worktree creation is impossible, stop and ask the user for explicit approval before editing the protected branch. -4. Report the chosen branch/worktree before implementation. - -This is a skill-level execution requirement. It improves behavior but is not presented as a hard OS-level file-write block. - -### Tests - -Add or update regression tests for: - -- `guard.mjs` rejects `exploring -> approved-for-build` in `full`. -- `guard.mjs` rejects `exploring -> bridging` in `full`. -- `guard.mjs` still allows `exploring -> bridging` for `hotfix`. -- `guard.mjs` still allows `exploring -> approved-for-build` for `tweak`. -- `ssf state transition` rejects the fast-path transitions when workflow is `auto` or `full`. -- `ssf state transition` does not write state when guard execution fails or returns invalid output. - -Tests should be implemented in the existing `tests/lib/guard-transitions.test.mjs` and `tests/lib/cmd-state.test.mjs` style. - -## Version And Release Plan - -1. Run `node scripts/spec-superflow.mjs version 0.8.10`. -2. Add a `CHANGELOG.md` entry for `0.8.10` with: - - fast-path workflow gating - - state transition fail-closed behavior - - build-executor branch isolation preflight -3. Run verification: - - `npm run build` - - `npm test` - - `node scripts/check-version-consistency.mjs` - - `node scripts/spec-superflow.mjs doctor` -4. Commit and push the branch. -5. Open a PR to `main`. -6. After merge, create and push tag `v0.8.10` from `main` to trigger CI/CD release. - -## Risks And Mitigations - -- Existing users relying on direct `exploring -> approved-for-build` in `auto` mode will be blocked. This is intended because direct fast-path execution must require an explicit or inferred `tweak` mode. -- Branch isolation remains instruction-level. The patch should describe this honestly and avoid overstating it as an unbypassable system guard. -- Version drift is easy during release work. `ssf version 0.8.10`, `check-version-consistency`, and `doctor` are mandatory before PR. - -## Acceptance Criteria - -- The minimal reproduction from issue #15 no longer transitions from `exploring` directly to `approved-for-build` under `auto` or `full`. -- Guard failures never result in `.spec-superflow.yaml` state updates. -- Hotfix and tweak fast paths still work when their workflow modes are set. -- `build-executor` explicitly requires branch/worktree preflight before implementation. -- All versioned files report `0.8.10`. -- Build, tests, version consistency, and doctor checks pass locally before PR. diff --git a/docs/superpowers/specs/2026-07-09-issues-42-35-34-bugfix-design.md b/docs/superpowers/specs/2026-07-09-issues-42-35-34-bugfix-design.md deleted file mode 100644 index 4d13c1d..0000000 --- a/docs/superpowers/specs/2026-07-09-issues-42-35-34-bugfix-design.md +++ /dev/null @@ -1,273 +0,0 @@ -# Issues 42/35/34 Bugfix Design - -Date: 2026-07-09 -Target release: 0.8.17 -Scope: GitHub issues #42, #35, and #34 - -## Context - -This patch fixes three open bug reports that expose the same product problem: spec-superflow currently lets documented workflow contracts drift from actual CLI behavior. - -Issue #42 reports inconsistent delta spec paths. Documentation and examples use flat files such as `specs/.md`, while CLI paths such as validation, schema guard checks, hashing, and sync mostly expect `specs//spec.md`. Local reproduction confirms that `node scripts/validate-artifacts docs/examples/add-dark-mode` and `ssf validate docs/examples/add-dark-mode` exit successfully even though the example contains no canonical `spec.md` files. This can make agents believe specs were validated when they were skipped. - -Issue #35 reports that `ssf inject ` writes `GEMINI.md` in a Cursor project. Local reproduction confirms that the command defaults to `claude,cursor,copilot,gemini` and writes all four platform outputs when `--platforms` is omitted. - -Issue #34 reports that the hotfix fast path is self-contradictory. Documentation says hotfix skips the full planning bundle and enters minimal contract-builder, but guard currently runs the full `artifacts-exist` check for `exploring -> bridging --workflow hotfix`. Local reproduction confirms that an empty hotfix change with only `.spec-superflow.yaml` fails because `proposal.md`, `design.md`, `tasks.md`, and `specs/` are missing. - -## Goals - -- Make `specs//spec.md` the single canonical delta spec path across docs, examples, tests, validation, hashing, and sync. -- Fail clearly when a change uses flat `specs/.md` or root `specs/spec.md` instead of silently skipping validation. -- Make `ssf inject` platform selection explicit and safe, so Cursor users do not receive Gemini files by default. -- Make hotfix fast-path guard behavior match the intended workflow: no full planning bundle, but still a minimal execution contract and DP-3 approval before build. -- Preserve full workflow strictness and tweak behavior. -- Keep the patch self-contained in zero-runtime-dependency ESM scripts and Markdown docs. - -## Non-Goals - -- Do not support two equally valid spec path layouts long term. -- Do not rewrite the TypeScript parser or validator engine. -- Do not add runtime dependencies. -- Do not change the semantics of full planning artifacts beyond canonical path enforcement. -- Do not implement prototype, Ponytail, model profiles, or Node 20 support in this patch. - -## Recommended Approach - -Use a contract-convergence patch instead of ad hoc fixes. The code should expose shared helpers for spec path discovery and workflow-aware guard checks, then route all affected commands through those helpers. - -This is stricter than accepting both spec layouts, but it removes the ambiguity that caused the bugs. Compatibility is provided through actionable errors and migration hints, not by continuing to process two defaults. - -## Proposed Changes - -### 1. Canonical Spec Path Discovery - -Add a shared helper, tentatively `scripts/lib/spec-paths.mjs`, with these responsibilities: - -- `findCanonicalSpecFiles(changeDir)` returns sorted canonical files under `specs//spec.md`. -- `findInvalidSpecFiles(changeDir)` returns flat files such as `specs/ui-theme.md` and root `specs/spec.md`. -- `validateSpecPathLayout(changeDir)` returns structured failures with messages that name the invalid path and the expected replacement path. - -The helper should not parse Markdown. It only owns filesystem layout so callers cannot drift. - -Consumers: - -- `scripts/validate-artifacts` -- `scripts/lib/cmd-validate.mjs` -- `scripts/guard/checks/schema-valid.mjs` -- `scripts/lib/hash.mjs` -- `scripts/lib/cmd-sync.mjs` - -Validation behavior: - -- If `specs/` exists and contains invalid spec-shaped Markdown files, validation exits non-zero with a migration hint. -- If `specs/` exists but contains no canonical spec files, validation exits non-zero for full planning validation. -- `schema-valid` fails when the layout is invalid or no canonical specs are found in a context that requires specs. -- `hash` computes artifact hashes from canonical specs only. Invalid layout should not be silently hashed as if it were approved. -- `sync` syncs only canonical delta specs and fails with a clear layout error if a change uses flat specs. - -Examples and docs should be migrated from: - -```text -specs/.md -``` - -to: - -```text -specs//spec.md -``` - -### 2. Safe Platform Selection For `ssf inject` - -Change `ssf inject ` so omitted `--platforms` no longer means all supported platforms. - -Supported platform input: - -- `--platforms cursor` -- `--platforms claude,cursor` -- `--platforms all` - -Default behavior when `--platforms` is omitted: - -1. Detect project markers in the current project root. -2. If exactly one platform is detected, inject only that platform. -3. If zero or multiple platforms are detected, exit with code 2 and explain that the user must pass `--platforms ` or `--platforms all`. - -Initial marker rules: - -- `.cursor/` or `.cursor/rules/` means Cursor. -- `.claude/` means Claude. -- Existing `GEMINI.md` means Gemini. -- Existing `.github/copilot-instructions.md` means Copilot. - -This avoids surprising writes. Users who really want all platform outputs still have a stable explicit command: - -```bash -ssf inject --platforms all -``` - -Docs should recommend Cursor users run: - -```bash -ssf inject --platforms cursor -``` - -### 3. Hotfix Minimal Guard Path - -Hotfix must be treated as a separate guard contract, not as full planning with skipped schema validation. - -Guard behavior: - -- `exploring -> bridging --workflow hotfix` - - requires workflow mode to be `hotfix` - - does not require `proposal.md`, `design.md`, `tasks.md`, or `specs/` - - allows route into contract-builder Hotfix Mode - -- `bridging -> approved-for-build --workflow hotfix` - - requires non-empty `execution-contract.md` - - requires `dp_3_result` - - requires the stored `contract_hash` to match the current `execution-contract.md` hash, or an equivalent minimal-contract freshness check - - does not require full artifact hash freshness - -- `approved-for-build -> executing --workflow hotfix` - - requires DP-3 to remain recorded - - should not require full artifact existence - - may default execution mode to `Inline` if no explicit `execution_mode` is set - -Full workflow behavior remains unchanged: - -- `specifying -> bridging` requires full artifacts and schema validation. -- `bridging -> approved-for-build` requires full artifacts, schema validation, contract freshness, and DP-3. -- `approved-for-build -> executing` requires full artifacts, contract freshness, and the existing decision gate behavior. - -Tweak behavior remains direct-edit oriented: - -- `exploring -> approved-for-build --workflow tweak` continues to skip full artifacts. -- Tweak does not require contract-builder unless later docs explicitly redefine it. - -Implementation should prefer either workflow-specific transition matrices or workflow-aware check expansion over broad post-hoc skip lists. The current skip-list model made hotfix accidentally inherit `artifacts-exist`; the replacement should make each fast path's contract explicit. - -## Data Flow - -Spec layout validation flow: - -1. CLI command receives a change directory. -2. Shared spec path helper scans `specs/`. -3. Command fails fast on invalid layout. -4. Command validates, hashes, or syncs canonical files only. - -Inject flow: - -1. Parse `--platforms`. -2. If omitted, run platform marker detection. -3. Resolve requested platforms or return an actionable usage error. -4. Write only resolved platform files. - -Hotfix flow: - -1. `workflow-start` infers or confirms `hotfix`. -2. Guard permits `exploring -> bridging` without full artifacts. -3. `contract-builder` Hotfix Mode writes minimal `execution-contract.md`. -4. User records DP-3 approval. -5. State init/rebuild records contract hash. -6. Guard permits `bridging -> approved-for-build` using minimal contract checks. -7. Build starts only after the approved minimal contract is fresh. - -## Error Handling - -Spec path errors must be direct and migration-oriented: - -```text -Invalid spec path: specs/ui-theme.md -Expected: specs/ui-theme/spec.md -``` - -`ssf inject` ambiguous default errors should not write partial files. The command should exit before any writer runs. - -Hotfix guard failures should identify the missing minimal requirement, for example: - -- `execution-contract.md: missing` -- `execution-contract.md: empty` -- `DP-3 (dp_3_result) is not recorded` -- `execution-contract.md is stale: contract hash mismatch` - -## Tests - -Add or update tests in the existing Node 22 native test style. - -Spec path tests: - -- `spec-paths` unit tests discover sorted canonical specs. -- `spec-paths` reports flat `specs/.md` and root `specs/spec.md` as invalid. -- `validate-artifacts` exits 1 on flat example layout and 0 after example migration. -- `ssf validate` exits 1 on flat layout and 0 on canonical layout. -- `schema-valid` fails invalid layout instead of returning pass with no spec checks. -- `hash` includes canonical specs and ignores invalid flat files only after reporting layout errors through validation paths. -- `sync` syncs canonical specs to main `specs//spec.md`. - -Inject tests: - -- `--platforms cursor` writes `.cursor/rules/phase-guard.mdc` and does not write `GEMINI.md`. -- `--platforms all` writes Claude, Cursor, Copilot, and Gemini outputs. -- Omitted `--platforms` with `.cursor/` marker injects only Cursor. -- Omitted `--platforms` with no marker exits 2 and writes nothing. -- Omitted `--platforms` with multiple markers exits 2 and writes nothing. -- Invalid platform names remain rejected. - -Hotfix guard tests: - -- Empty hotfix change with state file passes `exploring -> bridging --workflow hotfix`. -- Empty full workflow still fails `exploring -> bridging`. -- Hotfix `bridging -> approved-for-build` fails without `execution-contract.md`. -- Hotfix `bridging -> approved-for-build` fails without DP-3. -- Hotfix `bridging -> approved-for-build` passes with non-empty fresh contract and DP-3. -- Full workflow `bridging -> approved-for-build` still requires full artifacts. -- Tweak `exploring -> approved-for-build` still passes under the existing tweak contract. - -Verification before PR: - -```bash -npm run build -npm test -npm run validate -- docs/examples/add-dark-mode -npm run validate -- docs/examples/refactor-auth-boundary -node scripts/spec-superflow.mjs doctor -``` - -## Documentation Updates - -Update these surfaces in the same implementation batch as behavior changes: - -- `README.md` -- `docs/README_en.md` -- `INSTALL.md` -- `docs/examples/**/README.md` -- `docs/state-machine.md` -- `skills/workflow-start/SKILL.md` -- `skills/contract-builder/SKILL.md` -- CLI help text for `ssf inject` - -Documentation must say: - -- Delta specs live at `specs//spec.md`. -- `ssf inject` requires explicit `--platforms` unless one platform marker is detected. -- Hotfix skips full planning artifacts but not the minimal contract or DP-3 approval. - -## Risks And Mitigations - -- Existing users with flat specs will see new validation failures. This is intentional; error messages must include the exact target path. -- Some users may expect `ssf inject` to keep writing all files. The explicit `--platforms all` escape hatch preserves that behavior without surprise writes. -- Hotfix changes can become under-specified if the minimal contract is too weak. The guard must still require a non-empty, fresh `execution-contract.md` and DP-3. -- Hash semantics can drift if full and hotfix freshness checks share unclear names. Keep artifact hash and contract hash checks separate in code and messages. - -## Acceptance Criteria - -- Flat example specs are migrated to canonical directories. -- Validation commands fail on flat spec layouts and pass on canonical layouts. -- `ssf validate` and `validate-artifacts` no longer report success when no canonical spec was validated for a full planning bundle. -- Cursor-only injection does not create `GEMINI.md`. -- Omitted inject platform is either unambiguous by marker or rejected before writing. -- Hotfix can enter bridging without full artifacts. -- Hotfix cannot enter approved-for-build without a fresh minimal contract and DP-3. -- Full workflow and tweak workflow regressions remain covered by tests. -- Build, tests, example validation, and doctor pass before implementation is considered complete. diff --git a/tests/lib/cmd-install-workbuddy.test.mjs b/tests/lib/cmd-install-workbuddy.test.mjs index 939873d..33c55f8 100644 --- a/tests/lib/cmd-install-workbuddy.test.mjs +++ b/tests/lib/cmd-install-workbuddy.test.mjs @@ -103,7 +103,9 @@ describe('cmd-install-workbuddy', () => { try { const plan = planInstall({ homeDir: join(tempDir, 'home') }); assert.equal(plan.skillNames.length, 9); - assert.ok(plan.skillsDir.endsWith('spec-superflow/skills')); + assert.equal(plan.skillsDir, join(plan.pluginRoot, 'skills')); + assert.ok(existsSync(plan.skillsDir)); + assert.notEqual(plan.skillsDir, join(tempDir, 'skills')); } finally { process.chdir(previousCwd); }