intentdna 1.7.4 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/LICENSE +201 -0
  4. package/README.md +143 -194
  5. package/dist/assets/candidates.d.ts +124 -0
  6. package/dist/assets/candidates.js +1249 -0
  7. package/dist/assets/catalog.d.ts +101 -0
  8. package/dist/assets/catalog.js +311 -0
  9. package/dist/assets/evidence.d.ts +93 -0
  10. package/dist/assets/evidence.js +391 -0
  11. package/dist/assets/index.d.ts +4 -0
  12. package/dist/assets/index.js +4 -0
  13. package/dist/assets/metadata.d.ts +19 -0
  14. package/dist/assets/metadata.js +227 -0
  15. package/dist/cli/commands/assets.d.ts +65 -0
  16. package/dist/cli/commands/assets.js +2871 -0
  17. package/dist/cli/commands/auth.d.ts +322 -0
  18. package/dist/cli/commands/auth.js +1592 -0
  19. package/dist/cli/commands/cloud-auth-guidance.d.ts +2 -0
  20. package/dist/cli/commands/cloud-auth-guidance.js +4 -0
  21. package/dist/cli/commands/cloud.d.ts +1359 -0
  22. package/dist/cli/commands/cloud.js +8364 -0
  23. package/dist/cli/commands/evolve.js +18 -2
  24. package/dist/cli/commands/generate.js +25 -2
  25. package/dist/cli/commands/guard.d.ts +1 -1
  26. package/dist/cli/commands/guard.js +1 -1
  27. package/dist/cli/commands/guide.d.ts +15 -0
  28. package/dist/cli/commands/guide.js +1747 -0
  29. package/dist/cli/commands/init.d.ts +12 -0
  30. package/dist/cli/commands/init.js +95 -60
  31. package/dist/cli/commands/org.d.ts +16 -0
  32. package/dist/cli/commands/org.js +2393 -0
  33. package/dist/cli/commands/release.d.ts +59 -0
  34. package/dist/cli/commands/release.js +716 -0
  35. package/dist/cli/commands/report.d.ts +82 -0
  36. package/dist/cli/commands/report.js +1516 -0
  37. package/dist/cli/commands/run.d.ts +6 -1
  38. package/dist/cli/commands/run.js +95 -26
  39. package/dist/cli/commands/sync.d.ts +8 -1
  40. package/dist/cli/commands/sync.js +436 -141
  41. package/dist/cli/commands/templates.d.ts +64 -0
  42. package/dist/cli/commands/templates.js +2151 -1
  43. package/dist/cli/commands/workflow.d.ts +26 -0
  44. package/dist/cli/commands/workflow.js +3053 -0
  45. package/dist/cli/index.js +719 -42
  46. package/dist/compiler/cascade.js +4 -9
  47. package/dist/compiler/compile.js +1 -0
  48. package/dist/governance/evidence-capture-attribution.d.ts +12 -0
  49. package/dist/governance/evidence-capture-attribution.js +46 -0
  50. package/dist/governance/index.d.ts +2 -0
  51. package/dist/governance/index.js +1 -0
  52. package/dist/hooks/cli.d.ts +6 -0
  53. package/dist/hooks/cli.js +168 -12
  54. package/dist/hooks/enforce.d.ts +1 -0
  55. package/dist/hooks/protocol.d.ts +1 -1
  56. package/dist/hooks/protocol.js +1 -1
  57. package/dist/hooks/state.d.ts +41 -0
  58. package/dist/hooks/state.js +126 -2
  59. package/dist/index.d.ts +3 -0
  60. package/dist/index.js +3 -0
  61. package/dist/mcp/tools-state.js +2 -0
  62. package/dist/organization/index.d.ts +121 -0
  63. package/dist/organization/index.js +413 -0
  64. package/dist/runtime/claude-sync-target.d.ts +49 -0
  65. package/dist/runtime/claude-sync-target.js +280 -0
  66. package/dist/runtime/codex-adapter.d.ts +254 -0
  67. package/dist/runtime/codex-adapter.js +1204 -0
  68. package/dist/runtime/codex-sync-target.d.ts +33 -0
  69. package/dist/runtime/codex-sync-target.js +241 -0
  70. package/dist/runtime/index.d.ts +8 -0
  71. package/dist/runtime/index.js +4 -0
  72. package/dist/runtime/output-artifact-registry.d.ts +1 -1
  73. package/dist/runtime/output-artifact-registry.js +2 -0
  74. package/dist/runtime/settings-adapter.d.ts +1 -1
  75. package/dist/runtime/settings-adapter.js +1 -1
  76. package/dist/runtime/skill-adapter.d.ts +5 -1
  77. package/dist/runtime/skill-adapter.js +120 -34
  78. package/dist/runtime/sync-artifact-registry.d.ts +99 -0
  79. package/dist/runtime/sync-artifact-registry.js +194 -0
  80. package/dist/runtime/sync-target-plan.d.ts +45 -0
  81. package/dist/runtime/sync-target-plan.js +19 -0
  82. package/dist/schema/controller-registry.d.ts +8 -1
  83. package/dist/schema/controller-registry.js +8 -0
  84. package/dist/schema/types.d.ts +35 -23
  85. package/dist/schema/types.js +10 -1
  86. package/dist/schema/validate.js +22 -22
  87. package/dist/schema/validators/controllers.js +38 -20
  88. package/dist/schema/workflow-authoring-contract.d.ts +29 -0
  89. package/dist/schema/workflow-authoring-contract.js +109 -0
  90. package/dist/schema/yaml-parser.js +18 -0
  91. package/dist/templates/api-backend.dna.yaml +19 -0
  92. package/dist/templates/brainstorming-first.dna.yaml +19 -0
  93. package/dist/templates/code-cleanup.dna.yaml +19 -0
  94. package/dist/templates/code-review-pipeline.dna.yaml +18 -0
  95. package/dist/templates/documentation-writer.dna.yaml +19 -0
  96. package/dist/templates/flutter-behavior-lock.dna.yaml +19 -0
  97. package/dist/templates/flutter-refactoring-rescue.dna.yaml +19 -0
  98. package/dist/templates/flutter-rewrite-diagnosis-review.dna.yaml +210 -0
  99. package/dist/templates/flutter-rewrite-fix-review-loop.dna.yaml +260 -0
  100. package/dist/templates/flutter-rewrite-new.dna.yaml +506 -0
  101. package/dist/templates/flutter-rewrite.dna.yaml +20 -0
  102. package/dist/templates/frontend-quality.dna.yaml +19 -0
  103. package/dist/templates/full-pipeline.dna.yaml +20 -0
  104. package/dist/templates/marketplace.d.ts +92 -0
  105. package/dist/templates/marketplace.js +502 -0
  106. package/dist/templates/metadata.d.ts +25 -0
  107. package/dist/templates/metadata.js +136 -3
  108. package/dist/templates/mobile-dev.dna.yaml +19 -0
  109. package/dist/templates/multi-agent-handoff-coordination.dna.yaml +156 -0
  110. package/dist/templates/multi-perspective-review.dna.yaml +19 -0
  111. package/dist/templates/persistent-executor.dna.yaml +19 -0
  112. package/dist/templates/qa-loop.dna.yaml +18 -0
  113. package/dist/templates/release-evidence-gate.dna.yaml +131 -0
  114. package/dist/templates/requirements-gate.dna.yaml +19 -0
  115. package/dist/templates/research-orchestration.dna.yaml +19 -0
  116. package/dist/templates/root-cause-analysis.dna.yaml +19 -0
  117. package/dist/templates/safe-refactoring.dna.yaml +321 -0
  118. package/dist/templates/secure-dev.dna.yaml +19 -0
  119. package/dist/templates/subagent-parallel.dna.yaml +19 -0
  120. package/dist/templates/systematic-debugging.dna.yaml +19 -0
  121. package/dist/templates/tdd-strict.dna.yaml +19 -0
  122. package/dist/templates/ui-visual-regression-qa.dna.yaml +133 -0
  123. package/dist/templates/workflow-author.dna.yaml +302 -0
  124. package/dist/templates/workflow-blocked-scope-triage.dna.yaml +242 -0
  125. package/dist/templates/workflow-completion-audit.dna.yaml +254 -0
  126. package/dist/templates/workflow-cross-boundary-resource-approval.dna.yaml +249 -0
  127. package/dist/templates/workflow-evidence-review.dna.yaml +198 -0
  128. package/dist/templates/workflow-module-inventory.dna.yaml +257 -0
  129. package/dist/templates/workflow-runtime-smoke-review.dna.yaml +252 -0
  130. package/dist/templates/workflow-verification-command-routing.dna.yaml +278 -0
  131. package/dist/workflow/authoring-packet.d.ts +67 -0
  132. package/dist/workflow/authoring-packet.js +218 -0
  133. package/dist/workflow/draft.d.ts +159 -0
  134. package/dist/workflow/draft.js +800 -0
  135. package/dist/workflow/index.d.ts +3 -0
  136. package/dist/workflow/index.js +3 -0
  137. package/dist/workflow/suggestion-review.d.ts +65 -0
  138. package/dist/workflow/suggestion-review.js +245 -0
  139. package/package.json +1 -1
  140. package/spec/README.md +15 -48
  141. package/spec/codex-adapter-contract.md +176 -0
  142. package/spec/sync-target-plan.md +158 -0
  143. package/spec/workflow-capability-ir.md +153 -0
  144. package/spec/agent-dispatch-fix.md +0 -116
  145. package/spec/control-plane-convergence-handoff-2026-04-24.md +0 -432
  146. package/spec/flutter-rewrite-template-optimization.md +0 -301
  147. package/spec/foundation-hardening.md +0 -178
  148. package/spec/hooks-infra-harness-hardening.md +0 -741
  149. package/spec/multi-config.md +0 -172
  150. package/spec/parallel-isolation.md +0 -268
  151. package/spec/template-version-namespace-fix.md +0 -653
  152. package/spec/workflow-pipeline.md +0 -101
@@ -1,741 +0,0 @@
1
- # Hooks 基础设施优化 + Harness 加固 — 整合实施方案
2
-
3
- ## Metadata
4
- - Generated: 2026-04-18
5
- - Status: APPROVED
6
- - 预计测试增量: +100
7
- - 预计工期: 1 周
8
- - 前置版本: v1.5.12
9
-
10
- ## 背景
11
-
12
- 两个独立方案的合并:
13
- 1. **Hooks 基础设施优化**(上次三方评审通过)— Schema validation, EnforceResult, StateManager, Integration tests
14
- 2. **Harness 加固**(本次 deep interview 产出)— Context gate, Reflection gate, Stop hook 智能编排, Workflow boundary
15
-
16
- 上层(Harness 加固)依赖底层(Hooks 基础设施)。合并后减少重复工作。
17
-
18
- ## 依赖图
19
-
20
- ```
21
- Phase 0 (模板修复) ← 立即可做,无依赖
22
-
23
- Phase 1A (Schema) ──→ Phase 1B (EnforceResult) ──→ Phase 2B (Gates)
24
-
25
- Phase 2A (StateManager) ────────────────────────→ Phase 2B (Gates)
26
-
27
- Phase 3 (Stop hook + Integration)
28
-
29
- Phase 4 (Dogfood)
30
-
31
- 可并行:1A + 2A
32
- 必须串行:1B 依赖 1A;2B 依赖 1B + 2A;3 依赖 2B;4 依赖 3
33
- ```
34
-
35
- ---
36
-
37
- ## Phase 0: 模板即时修复
38
-
39
- **目标**: 修复当前模板的 3 个已知缺陷,零风险
40
- **文件**: `src/templates/flutter-rewrite.dna.yaml`
41
- **测试**: +0(模板内容变更不影响单测,dna validate 验证)
42
- **破坏性**: 无
43
-
44
- ### 0.1 Surgeon instructions 加必读清单
45
-
46
- 找到 `roles.surgeon.instructions`,在现有 instructions 列表**最前面**插入一行:
47
-
48
- ```yaml
49
- instructions:
50
- - "REQUIRED FIRST: Read context files — CLAUDE.md, docs/refactoring-workflow-v2.md, v2/docs/PROVIDER_DESIGN.md, and the diagnosis spec (.omc/specs/diagnosis-$ARGUMENTS.md). Then read v1 corresponding file before any Edit. Hook will block Edit if context files are not read."
51
- # ... 保留所有现有 instructions
52
- ```
53
-
54
- ### 0.2 Fix workflow experience chain 自读
55
-
56
- 找到 `workflows.fix.steps` 中 `id: fix_bugs` 的 step,在 prompt 最前面加:
57
-
58
- ```
59
- Read .dna/state/workflow/experience.md first if it exists.
60
- It contains previous failed approaches — do NOT repeat them.
61
- ```
62
-
63
- ### 0.3 Behavior-lock 全量回归
64
-
65
- 找到 `workflows.behavior-lock.steps` 中 `id: write_tests` 的 step prompt,场景 2 (re-run) 部分,替换测试执行逻辑为:
66
-
67
- ```
68
- Scenario 2 (re-run/incremental):
69
- - Read the incremental diff from behavior doc
70
- - Update existing tests incrementally — do NOT rewrite all tests
71
- - Run ALL tests (do NOT skip previously green tests)
72
- - Compare with previous baseline:
73
- GREEN→RED = REGRESSION (mark HIGH_PRIORITY — v2 broke something)
74
- RED→GREEN = FIXED
75
- NEW = new coverage
76
- REMOVED = coverage shrunk (verify intentional)
77
- - Update baseline with complete results
78
- - Git commit includes regression count if any
79
- ```
80
-
81
- ### 0.4 验证
82
-
83
- ```bash
84
- dna validate src/templates/flutter-rewrite.dna.yaml
85
- npm test
86
- ```
87
-
88
- ---
89
-
90
- ## Phase 1A: Boundary Schema + Contract Tests
91
-
92
- **目标**: CC ↔ dna-hook 边界的显式 schema 验证,防止 session_id 类 boundary bug
93
- **测试**: +20
94
- **破坏性**: 无(纯增量)
95
-
96
- **实施状态(2026-04-20 更新)**: 与 Phase 1B 合并完成,产出 +108 测试(schema+contract ≈18 属 1A,其余属 1B 断言重写)。评审 GO with reservations。未提交,3 个 blocker 待修(见本 spec 末尾"Phase 1A+1B 合并 Followup"章节)。
97
-
98
- ### 1A.1 新建 src/hooks/schema.ts
99
-
100
- ```typescript
101
- /**
102
- * Hook input validation — CC protocol boundary.
103
- * Zero external dependencies. Hand-written validators.
104
- * Fail-open: invalid input → log warning + return { valid: false, ... }
105
- */
106
-
107
- export interface ValidationResult {
108
- valid: boolean;
109
- errors: string[];
110
- normalized?: Record<string, unknown>; // camelCase 归一化后的输入
111
- }
112
-
113
- export function validateHookInput(event: string, raw: unknown): ValidationResult
114
- // 对每种 event 类型验证必填字段:
115
- // PreToolUse: tool_name, tool_input 必须存在
116
- // PostToolUse: tool_name, tool_output 必须存在
117
- // SessionStart: session_id (camelCase 归一化)
118
- // SubagentStop: agent_type
119
- // UserPromptSubmit: (minimal)
120
- // Notification: title, message
121
- // PreCompact: (minimal)
122
- // Stop: (minimal)
123
-
124
- export function normalizeSessionId(input: Record<string, unknown>): string | undefined
125
- // 处理 session_id / sessionId / CLAUDE_SESSION_ID 的归一化
126
- ```
127
-
128
- ### 1A.2 修复 enforce.ts:38-42 snake_case bug
129
-
130
- 找到 `SessionStartInput` 接口定义(enforce.ts 约 38 行),确认字段用 camelCase(和其他 Input 类型一致)。如果有 `session_id`(snake_case),改为 `sessionId`。
131
-
132
- ### 1A.3 新建 test/fixtures/cc-hook-inputs/
133
-
134
- 从 lwk_flutter_v2-rewrite 的 `.dna/state/trace/trace-2026-04-17.jsonl` 中提取 8 个真实 CC hook input fixture:
135
-
136
- ```
137
- pre-tool-use-edit.json — Edit 工具调用
138
- pre-tool-use-bash.json — Bash 工具调用
139
- pre-tool-use-read.json — Read 工具调用
140
- post-tool-use-bash-test.json — Bash 跑 flutter test 的输出
141
- session-start.json — SessionStart 事件
142
- subagent-stop-surgeon.json — surgeon subagent 停止
143
- subagent-stop-investigator.json — investigator subagent 停止
144
- stop-event.json — Stop 事件
145
- ```
146
-
147
- ### 1A.4 新建 test/contract/hook-contract.test.ts
148
-
149
- 对每个 fixture:`fixture → validateHookInput() → enforce*() → 验证输出格式`
150
-
151
- 全链路 contract test:确保真实 CC 输入能正确通过验证 + enforce 链。
152
-
153
- ### 1A.5 验证
154
-
155
- ```bash
156
- npm test # 全绿,+20 新测试
157
- ```
158
-
159
- ---
160
-
161
- ## Phase 1B: EnforceResult 类型
162
-
163
- **目标**: enforce 函数返回结构化结果,消除 cli.ts 的 decision 猜测逻辑
164
- **测试**: +15(改约 30 处现有断言)
165
- **破坏性**: 是(限定在此 phase)
166
- **依赖**: Phase 1A
167
-
168
- **实施状态(2026-04-20 更新)**: 与 Phase 1A 一起完成(autopilot 超范围)。类型/签名/断言重写都到位,未提交。
169
-
170
- ### 1B.1 protocol.ts 新增类型
171
-
172
- ```typescript
173
- export interface TraceMetadata {
174
- matched_rule: MatchedRule;
175
- gene_id?: string;
176
- step_id?: string;
177
- role?: string;
178
- }
179
-
180
- export type MatchedRule =
181
- | "scope"
182
- | "filter"
183
- | "gate"
184
- | "schema"
185
- | "handoff"
186
- | "step_rule"
187
- | "output_schema"
188
- // Phase 2B 新增(先定义,后实现):
189
- | "context_gate"
190
- | "reflection_gate"
191
- | "workflow_boundary";
192
-
193
- export interface EnforceResult {
194
- output: HookOutput;
195
- trace?: TraceMetadata;
196
- }
197
- ```
198
-
199
- ### 1B.2 更新 enforce.ts 的 8 个函数
200
-
201
- 每个 enforce* 函数的返回类型从 `HookOutput | null` 改为 `EnforceResult | null`。
202
-
203
- ```typescript
204
- // 之前
205
- export function enforcePreToolUse(...): HookOutput | null {
206
- return { decision: "block", reason: "..." };
207
- }
208
-
209
- // 之后
210
- export function enforcePreToolUse(...): EnforceResult | null {
211
- return {
212
- output: { decision: "block", reason: "..." },
213
- trace: { matched_rule: "scope", gene_id: "scan_read_only", role: "scanner" }
214
- };
215
- }
216
- ```
217
-
218
- **注意**: trace metadata 不进入 HookOutput(CC 协议边界不该混入内部 metadata)。trace 由 cli.ts 读取后写入 trace log,不返回给 CC。
219
-
220
- ### 1B.3 新增 3 个 enforce 纯函数
221
-
222
- ```typescript
223
- // 已在 v1.5.12 实现 checkReflectionLimit,确认返回 EnforceResult
224
- export function checkReflectionLimit(
225
- failCount: number, maxAttempts: number,
226
- handoffCount: number, maxHandoffs: number
227
- ): EnforceResult
228
-
229
- // 已在 v1.5.12 实现 checkContextReadiness,确认返回 EnforceResult
230
- export function checkContextReadiness(
231
- sessionReads: string[], required: string[]
232
- ): EnforceResult
233
-
234
- // 新增
235
- export function checkWorkflowBoundary(
236
- workflowCompleted: boolean, targetSkill: string
237
- ): EnforceResult
238
- ```
239
-
240
- ### 1B.4 更新 cli.ts
241
-
242
- cli.ts 从 enforce 结果中提取 trace metadata,写入 trace log:
243
-
244
- ```typescript
245
- const result = enforcePreToolUse(ir, input, state);
246
- if (result) {
247
- // 返回 HookOutput 给 CC
248
- writeOutput(result.output);
249
- // trace metadata 写 trace log(不返回给 CC)
250
- if (result.trace) appendTrace({ ...result.trace, timestamp: now() });
251
- }
252
- ```
253
-
254
- ### 1B.5 更新 src/mcp/tools-enforce.ts
255
-
256
- 检查 MCP enforce 工具是否调用 enforce 函数。如果调用了,同步更新返回类型处理。
257
-
258
- ### 1B.6 更新测试
259
-
260
- 约 30 处现有断言需要从 `expect(result).toEqual({ decision: "block", ... })` 改为 `expect(result.output).toEqual({ decision: "block", ... })`。
261
-
262
- ```bash
263
- npm test # 全绿,+15 新测试
264
- ```
265
-
266
- ---
267
-
268
- ## Phase 2A: DNAStateManager ✓ (2026-04-21)
269
-
270
- **目标**: 统一所有 state 操作,支持 session reads + surgeon attempts + experience chain
271
- **测试**: +21 (state-manager.test.ts)
272
- **破坏性**: 无(旧函数 @deprecated 保留)
273
- **可与 Phase 1A 并行**
274
-
275
- **实施**: `src/hooks/state-manager.ts` — 类 facade 封装 workflow / audit / surgeon / session reads,新增 experience chain (json + markdown dual-write) 和 init/cleanup/isStale 生命周期。state.ts 全部被 manager 替代的函数加 `@deprecated`。1076 tests pass (1055 existing + 21 new)。
276
-
277
- ### 2A.1 新建 src/hooks/state-manager.ts
278
-
279
- ```typescript
280
- export class DNAStateManager {
281
- constructor(private stateDir: string, private sessionId?: string) {}
282
-
283
- // ── 现有 state 操作封装 ──
284
- readWorkflowState(): WorkflowState | null
285
- writeWorkflowState(state: WorkflowState): void
286
- readAuditLog(): AuditEntry[]
287
- appendAudit(entry: AuditEntry): void
288
-
289
- // ── 新增: Session reads 追踪 ──
290
- appendSessionRead(filePath: string): void
291
- getSessionReads(): string[]
292
- // 路径: .dna/state/workflow/session-reads.json
293
-
294
- // ── 新增: Surgeon attempts 追踪 ──
295
- readSurgeonAttempts(): SurgeonAttemptState
296
- writeSurgeonAttempts(state: SurgeonAttemptState): void
297
- // 路径: .dna/state/workflow/surgeon-attempts.json
298
-
299
- // ── 新增: Experience chain ──
300
- appendExperience(entry: ExperienceEntry): void
301
- readExperienceChain(): ExperienceEntry[]
302
- writeExperienceChain(chain: ExperienceEntry[]): void
303
- // 路径: .dna/state/workflow/experience.md (markdown)
304
- // + .dna/state/workflow/experience.json (structured)
305
-
306
- // ── 生命周期 ──
307
- init(): void // 创建 session 目录结构
308
- cleanup(): void // 先算 summary(读 trace),再 rotate/clean
309
- isStale(): boolean // >2h 判定为 stale
310
- }
311
-
312
- export interface SurgeonAttemptState {
313
- round: number;
314
- edit_count: number;
315
- bash_test_count: number;
316
- last_green_count: number;
317
- current_green_count: number;
318
- fail_count: number;
319
- handoff_count: number;
320
- baseline_established: boolean;
321
- }
322
-
323
- export interface ExperienceEntry {
324
- round: number;
325
- analysis: string;
326
- attempt: string;
327
- result: string;
328
- lesson: string;
329
- timestamp: string;
330
- }
331
- ```
332
-
333
- ### 2A.2 保留 state.ts 向后兼容
334
-
335
- 在现有 state.ts 函数上加 `@deprecated` 注释,内部改为调用 StateManager:
336
-
337
- ```typescript
338
- /** @deprecated Use DNAStateManager instead */
339
- export function readWorkflowState(stateDir: string): WorkflowState | null {
340
- return new DNAStateManager(stateDir).readWorkflowState();
341
- }
342
- ```
343
-
344
- ### 2A.3 测试
345
-
346
- ```bash
347
- npm test # 全绿,+20 新测试
348
- ```
349
-
350
- ---
351
-
352
- ## Phase 2B: Context Gate + Reflection Gate + Workflow Boundary ✓ (2026-04-21)
353
-
354
- **目标**: 3 个核心 Harness 加固机制
355
- **测试**: +18 (hooks-harness.test.ts)
356
- **破坏性**: 无
357
- **依赖**: Phase 1B (EnforceResult) + Phase 2A (StateManager)
358
-
359
- **实施**: `src/hooks/cli.ts:handlePreToolGates()` — PreToolUse 前置门,按优先级评估 workflow_boundary 和 context_gate。Context gate 已从 v1.5.12 的 PostToolUse warn 模式迁移到 PreToolUse block 模式(spec 已确认去掉 warn 过渡期)。Reflection gate 保持 v1.5.10 PostToolUse 实现。Session-read 追踪由 PostToolUse Read 路径写入 `.dna/state/sessions/<id>/workflow/session-reads.json`。1094 tests pass (1076 + 18 new)。
360
-
361
- ### 2B.1 Context Gate — src/hooks/cli.ts
362
-
363
- 在 PreToolUse 处理中新增:
364
-
365
- ```typescript
366
- function handleContextGate(
367
- input: PreToolUseInput,
368
- ir: ConstraintIR,
369
- stateManager: DNAStateManager,
370
- ): EnforceResult | null {
371
- // 只对 Edit/Write/Bash 触发
372
- if (!["Edit", "Write", "Bash"].includes(input.tool_name)) return null;
373
-
374
- // 获取当前角色的必读文件列表
375
- const role = getCurrentRole(ir, input);
376
- if (!role) return null;
377
-
378
- const required = getRoleContextFiles(ir, role);
379
- if (required.length === 0) return null;
380
-
381
- // 检查 session reads
382
- const reads = stateManager.getSessionReads();
383
- const result = checkContextReadiness(reads, required);
384
-
385
- if (!result.output.decision || result.output.decision === "allow") return null;
386
-
387
- // Block — 返回缺失文件清单
388
- return result;
389
- }
390
- ```
391
-
392
- **注意:直接 block,不是 warn。** 之前讨论的 Phase 1 warn 已取消,直接上 block。
393
-
394
- ### 2B.2 Reflection Gate — src/hooks/cli.ts
395
-
396
- 在 PostToolUse 处理中新增:
397
-
398
- ```typescript
399
- function handleSurgeonReflection(
400
- input: PostToolUseInput,
401
- stepDef: WorkflowStepDef | null,
402
- stateManager: DNAStateManager,
403
- ): EnforceResult | null {
404
- if (!stepDef?.max_attempts) return null;
405
-
406
- const attempts = stateManager.readSurgeonAttempts();
407
-
408
- // 追踪 Edit/Bash 调用
409
- if (input.tool_name === "Edit") {
410
- attempts.edit_count++;
411
- }
412
-
413
- if (input.tool_name === "Bash" && looksLikeTestOutput(input.tool_output)) {
414
- attempts.bash_test_count++;
415
- const greenCount = parseGreenCount(input.tool_output);
416
- if (greenCount !== null) {
417
- attempts.current_green_count = greenCount;
418
- if (!attempts.baseline_established) {
419
- attempts.baseline_established = true;
420
- attempts.last_green_count = greenCount;
421
- }
422
- }
423
- }
424
-
425
- // 判定进展(只在有 baseline 后)
426
- if (attempts.baseline_established &&
427
- attempts.edit_count >= 2 &&
428
- attempts.bash_test_count >= 1) {
429
- if (attempts.current_green_count <= attempts.last_green_count) {
430
- // 无进展
431
- const result = checkReflectionLimit(
432
- attempts.fail_count + 1, stepDef.max_attempts,
433
- attempts.handoff_count, stepDef.max_handoffs ?? 3
434
- );
435
- attempts.fail_count++;
436
- stateManager.writeSurgeonAttempts(attempts);
437
-
438
- if (result.output.decision !== "allow") {
439
- return result; // warn / handoff / skip
440
- }
441
- } else {
442
- // 有进展,重置计数
443
- attempts.last_green_count = attempts.current_green_count;
444
- attempts.edit_count = 0;
445
- attempts.bash_test_count = 0;
446
- }
447
- }
448
-
449
- stateManager.writeSurgeonAttempts(attempts);
450
- return null;
451
- }
452
-
453
- function parseGreenCount(output: string): number | null {
454
- // 匹配 flutter test 输出格式
455
- // "00:05 +23: All tests passed!" → 23
456
- // "00:05 +23 -5: Some tests failed." → 23
457
- // "5 passed, 3 failed" → 5
458
- const patterns = [
459
- /\+(\d+)(?:\s|:)/, // flutter test format: +N
460
- /(\d+)\s+passed/i, // generic: N passed
461
- /(\d+)\s+tests?\s+passed/i, // verbose: N tests passed
462
- ];
463
- for (const p of patterns) {
464
- const m = output.match(p);
465
- if (m) return parseInt(m[1], 10);
466
- }
467
- return null; // 解析失败 → fail-open
468
- }
469
- ```
470
-
471
- ### 2B.3 Workflow Boundary — src/hooks/cli.ts
472
-
473
- 在 PreToolUse 处理中新增:
474
-
475
- ```typescript
476
- function handleWorkflowBoundary(
477
- input: PreToolUseInput,
478
- stateManager: DNAStateManager,
479
- ): EnforceResult | null {
480
- // 只检测 Skill 工具调用
481
- if (input.tool_name !== "Skill") return null;
482
-
483
- const wfState = stateManager.readWorkflowState();
484
- if (!wfState?.completed) return null;
485
-
486
- return checkWorkflowBoundary(true, input.tool_input?.skill ?? "unknown");
487
- }
488
- ```
489
-
490
- ### 2B.4 PostToolUse 追踪
491
-
492
- ```typescript
493
- // 在 PostToolUse 处理中,所有 Read 调用记录到 session reads
494
- if (input.tool_name === "Read" && input.tool_input?.file_path) {
495
- stateManager.appendSessionRead(input.tool_input.file_path);
496
- }
497
- ```
498
-
499
- ### 2B.5 测试
500
-
501
- ```
502
- test/hooks-harness.test.ts 新增:
503
- - context gate: 未读必需文件 + Edit → block
504
- - context gate: 已读必需文件 + Edit → allow
505
- - reflection gate: 3 次无进展 → warn(handoff)
506
- - reflection gate: 有进展 → 不触发
507
- - reflection gate: parseGreenCount 解析 3 种格式
508
- - workflow boundary: completed + Skill → block
509
- - workflow boundary: not completed + Skill → allow
510
- - session reads 追踪正确
511
- ```
512
-
513
- ```bash
514
- npm test # 全绿,+15 新测试
515
- ```
516
-
517
- ---
518
-
519
- ## Phase 3: Stop Hook 智能编排 + Property Tests ✓ (2026-04-21)
520
-
521
- **目标**: Stop hook 从"继续工作"升级为"输出下一步 Agent 调用";property-based 不变量验证
522
- **测试**: +22 (9 stop-guidance + 13 property)
523
- **破坏性**: 无
524
- **依赖**: Phase 2B
525
-
526
- **实施**:
527
- - `src/hooks/cli.ts:buildWorkflowGuidance()` — Stop hook 读 workflow state + reflection-config sidecar + surgeon attempts,按 (完成 / surgeon 停滞 / 正常) 三种情况输出 STOP 指令或 `Agent(subagent_type=..., prompt=...)` 调用模板。
528
- - `test/property/enforce-invariants.test.ts` — fast-check 属性测试 13 条,覆盖 checkContextReadiness 幂等性、checkReflectionLimit 三种分支边界、checkWorkflowBoundary completed=true/false 对偶、extractBashWritePaths / validateHookInput 不抛错 + 归一化一致性。
529
- - **跳过**: subprocess integration tests(`spawn dist/hooks/cli.js` 全链路)— 需要预先 `npm run build`,留待后续补充。不影响 gate 逻辑验证,因为 buildWorkflowGuidance / handlePreToolGates 都是可直接导入的纯/半纯函数,已有完整单测。
530
-
531
- 1116 tests pass.
532
-
533
- ### 3.1 Stop Hook 智能编排 — src/hooks/cli.ts
534
-
535
- 在 enforceStop 中,读 workflow state 后输出明确的下一步指令:
536
-
537
- ```typescript
538
- function buildWorkflowGuidance(
539
- ir: ConstraintIR,
540
- stateManager: DNAStateManager,
541
- ): string | null {
542
- const wfState = stateManager.readWorkflowState();
543
- if (!wfState) return null;
544
-
545
- const attempts = stateManager.readSurgeonAttempts();
546
- const stepDef = getStepDef(ir, wfState.current_step);
547
-
548
- // 情况 1: surgeon 无进展,需要重新分析
549
- if (wfState.current_step === "fix_bugs" &&
550
- stepDef?.max_attempts &&
551
- attempts.fail_count >= stepDef.max_attempts) {
552
- const experience = stateManager.readExperienceChain();
553
- return `[DNA WORKFLOW] Surgeon 已无进展 ${attempts.fail_count} 次。
554
- 下一步: 重新分析。执行:
555
- Agent(subagent_type="dna-frw-analyzer", prompt="重新分析 module,
556
- 读 .dna/state/workflow/experience.md 了解 ${experience.length} 次历史失败")`;
557
- }
558
-
559
- // 情况 2: workflow 完成
560
- if (wfState.completed) {
561
- return `[DNA WORKFLOW] Workflow "${wfState.workflow}" 完成。
562
- 输出最终报告并停止。不要启动其他 workflow。`;
563
- }
564
-
565
- // 情况 3: 正常继续
566
- return null;
567
- }
568
- ```
569
-
570
- 在 enforceStop 的 reason 中追加 workflow guidance(如果有)。
571
-
572
- ### 3.2 Integration Tests — test/integration/
573
-
574
- 新建 test/integration/hook-lifecycle.test.ts:
575
-
576
- ```typescript
577
- // spawn 真实 dna-hook 进程,通过 stdin/stdout 模拟完整 workflow
578
-
579
- describe("hook lifecycle integration", () => {
580
- it("context gate blocks Edit before reading context files", async () => {
581
- // stdin: PreToolUse Edit event (surgeon, no prior reads)
582
- // expected stdout: { decision: "block", reason: "...Missing: CLAUDE.md..." }
583
- });
584
-
585
- it("context gate allows Edit after reading required files", async () => {
586
- // stdin: PostToolUse Read CLAUDE.md → PostToolUse Read workflow.md → PreToolUse Edit
587
- // expected stdout: (no block)
588
- });
589
-
590
- it("reflection gate triggers after 3 no-progress cycles", async () => {
591
- // stdin: sequence of Edit + Bash(test, same green count) × 3
592
- // expected: warn with handoff message
593
- });
594
-
595
- it("stop hook injects workflow guidance", async () => {
596
- // setup workflow state with fail_count >= max
597
- // stdin: Stop event
598
- // expected: reason contains "[DNA WORKFLOW]" + Agent() call
599
- });
600
- });
601
- ```
602
-
603
- ### 3.3 Property Tests — test/property/
604
-
605
- 新建 test/property/enforce-invariants.test.ts(使用 fast-check):
606
-
607
- ```typescript
608
- import fc from "fast-check";
609
-
610
- // 不变量 1: fail-open — 任何无效输入都不 throw
611
- // 不变量 2: scope 一致性 — deny 的 tool 永远 block
612
- // 不变量 3: context gate 幂等 — 同一输入多次调用结果相同
613
- // 不变量 4: reflection limit 单调 — fail_count 只增不减(除非 reset)
614
- // 不变量 5: parseGreenCount null 安全 — 任意字符串不 throw
615
- // 不变量 6: checkReflectionLimit 边界 — maxAttempts=0 时总是 handoff
616
- // 不变量 7: workflow boundary 完成判定 — completed=false 时总是 allow
617
- ```
618
-
619
- ### 3.4 验证
620
-
621
- ```bash
622
- npm test # 全绿,+25 新测试
623
- ```
624
-
625
- ---
626
-
627
- ## Phase 4: Dogfood + Cleanup
628
-
629
- **目标**: 真实项目验证 + 清理
630
- **测试**: +5
631
- **依赖**: Phase 3
632
-
633
- ### 4.1 intentdna 项目验证
634
-
635
- ```bash
636
- dna verify --health # 7 项检查全通过
637
- dna sync # 无报错
638
- npm test # 全绿
639
- ```
640
-
641
- ### 4.2 lwk_flutter_v2-rewrite 验证
642
-
643
- ```bash
644
- cd /Users/samuel/lawark/lwk_flutter_v2-rewrite
645
- dna sync # 新 agent/skill 生成
646
- /dna-frw-diagnosis home # 验证: analyzer 不跑 Bash, 输出 diagnosis spec
647
- # 验证: context gate block 生效
648
- # 验证: analysis_reviewer 审查
649
- /dna-frw-fix home # 验证: surgeon 先读 context 再 Edit
650
- # 验证: reflection gate 触发
651
- # 验证: workflow boundary 阻止跨 workflow
652
- ```
653
-
654
- ### 4.3 清理
655
-
656
- 如果 StateManager 稳定,考虑移除 state.ts 中 @deprecated 函数。
657
-
658
- ### 4.4 发版
659
-
660
- ```bash
661
- /dna-release patch "hooks infra + harness hardening — schema validation, EnforceResult, StateManager, context/reflection/boundary gates"
662
- ```
663
-
664
- ---
665
-
666
- ## 验收清单
667
-
668
- ### Phase 0
669
- - [ ] surgeon instructions 第一行是 REQUIRED FIRST
670
- - [ ] fix_bugs prompt 包含读 experience.md
671
- - [ ] behavior-lock 场景 2 全量回归
672
-
673
- ### Phase 1A
674
- - [ ] schema.ts validateHookInput() 实现
675
- - [ ] 8 个真实 CC fixture 文件
676
- - [ ] contract tests 全链路通过
677
- - [ ] SessionStartInput snake_case bug 已修
678
-
679
- ### Phase 1B
680
- - [ ] EnforceResult + TraceMetadata 类型定义
681
- - [ ] matched_rule 包含 context_gate / reflection_gate / workflow_boundary
682
- - [ ] 8 个 enforce 函数返回 EnforceResult
683
- - [ ] cli.ts 不再猜 decision
684
- - [ ] trace metadata 不进入 HookOutput(CC 协议边界)
685
- - [ ] mcp/tools-enforce.ts 同步更新
686
-
687
- ### Phase 2A ✓
688
- - [x] DNAStateManager class 实现
689
- - [x] Session reads 追踪
690
- - [x] Surgeon attempts 追踪
691
- - [x] Experience chain 读写(json + markdown dual-write)
692
- - [x] init/cleanup/isStale 生命周期
693
- - [x] state.ts 旧函数 @deprecated 保留
694
-
695
- ### Phase 2B ✓
696
- - [x] Context gate: block Edit/Bash/Write if context files not read (PreToolUse, block mode)
697
- - [x] Reflection gate: detect no-progress, warn/handoff/skip (PostToolUse, v1.5.10+)
698
- - [x] Workflow boundary: block Skill() after workflow completed (wfState.active=false)
699
- - [x] PostToolUse Read → appendSessionRead
700
- - [x] parseGreenCount 支持 3 种格式 + null 安全 (v1.5.10+ TEST_PASSED_RE)
701
-
702
- ### Phase 3 ✓ (partial — integration tests deferred)
703
- - [x] Stop hook 读 workflow state 输出 Agent() 调用指令 (buildWorkflowGuidance)
704
- - [ ] Integration tests: spawn dna-hook 全链路 (deferred — 需 build 先行)
705
- - [x] Property tests: 13 个不变量 (fast-check)
706
-
707
- ### Phase 4
708
- - [ ] dna verify --health 通过
709
- - [ ] lwk_flutter diagnosis → fix 流程验证
710
- - [ ] 发版
711
-
712
- ---
713
-
714
- ## Phase 1A+1B 合并 Followup(2026-04-20 评审产出 → 2026-04-21 已修)
715
-
716
- autopilot 超范围将 1A+1B 一并完成,3 个 blocker 均已修复:
717
-
718
- ### Blocker 1: schema.ts 接入 cli.ts ✓
719
-
720
- **实施**: `src/hooks/cli.ts:24,125-137` — 在 `readStdin` 后、任何业务逻辑前调用 `validateHookInput(event, rawStdin)`;无效输入 fail-open(stderr 警告 + silent exit),有效输入使用 `validation.normalized` 作为后续 `rawInput`(session_id 已归一化为 sessionId)。
721
-
722
- ### Blocker 2: matched_rule 语义修正 ✓
723
-
724
- **实施**: `src/hooks/protocol.ts:100` — MatchedRule 枚举新增 `"validator"`;`src/hooks/enforce.ts:155-160` — audit-only 路径使用 `"validator"`,bash scope 违规仍用 `"scope"`(真实路径匹配)。
725
-
726
- ### Blocker 3: commit 信息如实 ✓
727
-
728
- **实施**: commit message 明确标注 "Phase 1A+1B 合并(autopilot 超范围)+ 3 blocker 修复"。
729
-
730
- ### Phase 1A/1B 验收全 PASS
731
-
732
- - [x] schema.ts validateHookInput() 实现 + 接入 cli.ts
733
- - [x] 8 个真实 CC fixture 文件 + contract tests 全链路通过
734
- - [x] SessionStartInput snake_case bug 已修
735
- - [x] EnforceResult + TraceMetadata 类型定义
736
- - [x] matched_rule 包含 context_gate / reflection_gate / workflow_boundary / validator
737
- - [x] 8 个 enforce 函数返回 EnforceResult
738
- - [x] cli.ts 不再猜 decision(读 `result.output`)
739
- - [x] trace metadata 不进入 HookOutput(CC 协议边界)
740
- - [x] mcp/tools-enforce.ts 同步更新
741
- - [x] 全量测试 1055 passed