@dommaker/harness 1.9.0 → 1.11.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 (285) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +9 -12
  3. package/dist/cli/commands/check.d.ts +3 -3
  4. package/dist/cli/commands/check.d.ts.map +1 -1
  5. package/dist/cli/commands/check.js +41 -78
  6. package/dist/cli/commands/check.js.map +1 -1
  7. package/dist/cli/commands/constraints-report.d.ts +2 -10
  8. package/dist/cli/commands/constraints-report.d.ts.map +1 -1
  9. package/dist/cli/commands/constraints-report.js +4 -57
  10. package/dist/cli/commands/constraints-report.js.map +1 -1
  11. package/dist/cli/commands/constraints-retire.d.ts +9 -23
  12. package/dist/cli/commands/constraints-retire.d.ts.map +1 -1
  13. package/dist/cli/commands/constraints-retire.js +39 -121
  14. package/dist/cli/commands/constraints-retire.js.map +1 -1
  15. package/dist/cli/commands/constraints.d.ts +3 -8
  16. package/dist/cli/commands/constraints.d.ts.map +1 -1
  17. package/dist/cli/commands/constraints.js +8 -23
  18. package/dist/cli/commands/constraints.js.map +1 -1
  19. package/dist/cli/commands/definitions.d.ts.map +1 -1
  20. package/dist/cli/commands/definitions.js +7 -12
  21. package/dist/cli/commands/definitions.js.map +1 -1
  22. package/dist/cli/commands/init.d.ts +0 -32
  23. package/dist/cli/commands/init.d.ts.map +1 -1
  24. package/dist/cli/commands/init.js +7 -149
  25. package/dist/cli/commands/init.js.map +1 -1
  26. package/dist/cli/commands/report.d.ts.map +1 -1
  27. package/dist/cli/commands/report.js +14 -17
  28. package/dist/cli/commands/report.js.map +1 -1
  29. package/dist/cli/commands/scaffold-templates.d.ts +1 -3
  30. package/dist/cli/commands/scaffold-templates.d.ts.map +1 -1
  31. package/dist/cli/commands/scaffold-templates.js +2 -53
  32. package/dist/cli/commands/scaffold-templates.js.map +1 -1
  33. package/dist/cli/commands/scaffold.d.ts +0 -2
  34. package/dist/cli/commands/scaffold.d.ts.map +1 -1
  35. package/dist/cli/commands/scaffold.js +0 -10
  36. package/dist/cli/commands/scaffold.js.map +1 -1
  37. package/dist/cli/commands/status.js +10 -10
  38. package/dist/cli/commands/status.js.map +1 -1
  39. package/dist/cli/commands/sync-docs/agents-syncer.d.ts +0 -2
  40. package/dist/cli/commands/sync-docs/agents-syncer.d.ts.map +1 -1
  41. package/dist/cli/commands/sync-docs/agents-syncer.js +4 -23
  42. package/dist/cli/commands/sync-docs/agents-syncer.js.map +1 -1
  43. package/dist/core/constraints/capabilities-parser.d.ts.map +1 -1
  44. package/dist/core/constraints/capabilities-parser.js +16 -4
  45. package/dist/core/constraints/capabilities-parser.js.map +1 -1
  46. package/dist/core/constraints/checker.d.ts +15 -24
  47. package/dist/core/constraints/checker.d.ts.map +1 -1
  48. package/dist/core/constraints/checker.js +33 -72
  49. package/dist/core/constraints/checker.js.map +1 -1
  50. package/dist/core/constraints/checkers/docs-freshness.js +1 -1
  51. package/dist/core/constraints/checkers/docs-freshness.js.map +1 -1
  52. package/dist/core/constraints/checkers/governance-presence.d.ts +2 -1
  53. package/dist/core/constraints/checkers/governance-presence.d.ts.map +1 -1
  54. package/dist/core/constraints/checkers/governance-presence.js +4 -3
  55. package/dist/core/constraints/checkers/governance-presence.js.map +1 -1
  56. package/dist/core/constraints/checkers/index.d.ts +1 -1
  57. package/dist/core/constraints/checkers/index.d.ts.map +1 -1
  58. package/dist/core/constraints/checkers/index.js +4 -8
  59. package/dist/core/constraints/checkers/index.js.map +1 -1
  60. package/dist/core/constraints/checkers/iron-flags.d.ts +3 -4
  61. package/dist/core/constraints/checkers/iron-flags.d.ts.map +1 -1
  62. package/dist/core/constraints/checkers/iron-flags.js +4 -5
  63. package/dist/core/constraints/checkers/iron-flags.js.map +1 -1
  64. package/dist/core/constraints/checkers/no-test-simplification.js +1 -1
  65. package/dist/core/constraints/checkers/no-test-simplification.js.map +1 -1
  66. package/dist/core/constraints/checkers/types.d.ts +1 -1
  67. package/dist/core/constraints/checkers/types.js +1 -1
  68. package/dist/core/constraints/definitions/guidelines.d.ts +4 -4
  69. package/dist/core/constraints/definitions/guidelines.d.ts.map +1 -1
  70. package/dist/core/constraints/definitions/guidelines.js +9 -25
  71. package/dist/core/constraints/definitions/guidelines.js.map +1 -1
  72. package/dist/core/constraints/definitions/iron-laws.d.ts +4 -4
  73. package/dist/core/constraints/definitions/iron-laws.d.ts.map +1 -1
  74. package/dist/core/constraints/definitions/iron-laws.js +10 -81
  75. package/dist/core/constraints/definitions/iron-laws.js.map +1 -1
  76. package/dist/core/constraints/definitions.d.ts +7 -9
  77. package/dist/core/constraints/definitions.d.ts.map +1 -1
  78. package/dist/core/constraints/definitions.js +13 -16
  79. package/dist/core/constraints/definitions.js.map +1 -1
  80. package/dist/core/constraints/index.d.ts +2 -5
  81. package/dist/core/constraints/index.d.ts.map +1 -1
  82. package/dist/core/constraints/index.js +3 -13
  83. package/dist/core/constraints/index.js.map +1 -1
  84. package/dist/core/constraints/injection-writer.d.ts +10 -38
  85. package/dist/core/constraints/injection-writer.d.ts.map +1 -1
  86. package/dist/core/constraints/injection-writer.js +17 -54
  87. package/dist/core/constraints/injection-writer.js.map +1 -1
  88. package/dist/core/constraints/run-env.d.ts +1 -10
  89. package/dist/core/constraints/run-env.d.ts.map +1 -1
  90. package/dist/core/constraints/run-env.js +1 -22
  91. package/dist/core/constraints/run-env.js.map +1 -1
  92. package/dist/core/constraints/usage-report.d.ts +6 -8
  93. package/dist/core/constraints/usage-report.d.ts.map +1 -1
  94. package/dist/core/constraints/usage-report.js +6 -11
  95. package/dist/core/constraints/usage-report.js.map +1 -1
  96. package/dist/core/effective-constraints.d.ts +12 -22
  97. package/dist/core/effective-constraints.d.ts.map +1 -1
  98. package/dist/core/effective-constraints.js +13 -30
  99. package/dist/core/effective-constraints.js.map +1 -1
  100. package/dist/core/index.d.ts +2 -2
  101. package/dist/core/index.d.ts.map +1 -1
  102. package/dist/core/index.js +3 -9
  103. package/dist/core/index.js.map +1 -1
  104. package/dist/core/project-config-loader.d.ts +4 -42
  105. package/dist/core/project-config-loader.d.ts.map +1 -1
  106. package/dist/core/project-config-loader.js +16 -125
  107. package/dist/core/project-config-loader.js.map +1 -1
  108. package/dist/core/validators/passes-gate.d.ts +2 -2
  109. package/dist/core/validators/passes-gate.js +6 -6
  110. package/dist/core/validators/passes-gate.js.map +1 -1
  111. package/dist/index.d.ts +9 -10
  112. package/dist/index.d.ts.map +1 -1
  113. package/dist/index.js +21 -18
  114. package/dist/index.js.map +1 -1
  115. package/dist/knowledge/lint.d.ts +17 -0
  116. package/dist/knowledge/lint.d.ts.map +1 -1
  117. package/dist/knowledge/lint.js +52 -0
  118. package/dist/knowledge/lint.js.map +1 -1
  119. package/dist/knowledge/store.d.ts +7 -0
  120. package/dist/knowledge/store.d.ts.map +1 -1
  121. package/dist/knowledge/store.js +48 -13
  122. package/dist/knowledge/store.js.map +1 -1
  123. package/dist/knowledge/types.d.ts +5 -1
  124. package/dist/knowledge/types.d.ts.map +1 -1
  125. package/dist/knowledge/types.js +5 -1
  126. package/dist/knowledge/types.js.map +1 -1
  127. package/dist/monitoring/trace-analyzer.d.ts.map +1 -1
  128. package/dist/monitoring/trace-analyzer.js +11 -12
  129. package/dist/monitoring/trace-analyzer.js.map +1 -1
  130. package/dist/monitoring/traces.d.ts +4 -4
  131. package/dist/monitoring/traces.d.ts.map +1 -1
  132. package/dist/monitoring/traces.js +8 -8
  133. package/dist/monitoring/traces.js.map +1 -1
  134. package/dist/presets/standard.d.ts +8 -10
  135. package/dist/presets/standard.d.ts.map +1 -1
  136. package/dist/presets/standard.js +10 -16
  137. package/dist/presets/standard.js.map +1 -1
  138. package/dist/types/constraint.d.ts +24 -35
  139. package/dist/types/constraint.d.ts.map +1 -1
  140. package/dist/types/constraint.js +8 -7
  141. package/dist/types/constraint.js.map +1 -1
  142. package/dist/types/passes-gate.d.ts +5 -5
  143. package/dist/types/passes-gate.d.ts.map +1 -1
  144. package/dist/types/project-config.d.ts +8 -66
  145. package/dist/types/project-config.d.ts.map +1 -1
  146. package/dist/types/project-config.js +3 -2
  147. package/dist/types/project-config.js.map +1 -1
  148. package/dist/types/trace.d.ts +8 -10
  149. package/dist/types/trace.d.ts.map +1 -1
  150. package/package.json +2 -2
  151. package/src/CONTEXT.md +2 -2
  152. package/src/__tests__/checker-extra.test.ts +37 -61
  153. package/src/__tests__/checker.test.ts +10 -115
  154. package/src/__tests__/effective-constraints.test.ts +18 -83
  155. package/src/__tests__/iron-laws.test.ts +71 -90
  156. package/src/__tests__/passes-gate-check.test.ts +2 -2
  157. package/src/__tests__/project-config-loader-extra.test.ts +22 -123
  158. package/src/__tests__/project-config-loader.test.ts +5 -33
  159. package/src/__tests__/public-exports.test.ts +8 -7
  160. package/src/__tests__/public-type-surface.test.ts +7 -5
  161. package/src/__tests__/public-value-surface.test.ts +1 -7
  162. package/src/__tests__/skip-semantics.test.ts +21 -37
  163. package/src/__tests__/trace-analyzer-extra.test.ts +14 -14
  164. package/src/__tests__/trace-analyzer.test.ts +21 -21
  165. package/src/__tests__/trace-collector.test.ts +22 -22
  166. package/src/__tests__/traces.test.ts +27 -28
  167. package/src/__tests__/usage-report-public-export.test.ts +21 -0
  168. package/src/cli/commands/CONTEXT.md +12 -12
  169. package/src/cli/commands/__tests__/check-read-count.test.ts +4 -15
  170. package/src/cli/commands/__tests__/check-skip-output.test.ts +14 -14
  171. package/src/cli/commands/__tests__/check.test.ts +14 -31
  172. package/src/cli/commands/__tests__/constraints-report-json-flag.test.ts +101 -0
  173. package/src/cli/commands/__tests__/constraints-report.test.ts +12 -80
  174. package/src/cli/commands/__tests__/constraints-retire.test.ts +42 -231
  175. package/src/cli/commands/__tests__/init-governance-io.test.ts +12 -58
  176. package/src/cli/commands/__tests__/init-ondisk.test.ts +13 -21
  177. package/src/cli/commands/__tests__/init.test.ts +1 -16
  178. package/src/cli/commands/__tests__/numeric-flag-assembly.test.ts +1 -1
  179. package/src/cli/commands/__tests__/passes-gate-dead-options.test.ts +1 -1
  180. package/src/cli/commands/__tests__/project-path-anchoring.test.ts +2 -2
  181. package/src/cli/commands/__tests__/registry.test.ts +1 -1
  182. package/src/cli/commands/__tests__/report-extra.test.ts +4 -4
  183. package/src/cli/commands/__tests__/report.test.ts +1 -1
  184. package/src/cli/commands/__tests__/scaffold.test.ts +4 -14
  185. package/src/cli/commands/__tests__/status-analysis-wiring.test.ts +3 -3
  186. package/src/cli/commands/__tests__/status-extra.test.ts +14 -14
  187. package/src/cli/commands/__tests__/status.test.ts +12 -12
  188. package/src/cli/commands/__tests__/sync-docs-agents.test.ts +1 -1
  189. package/src/cli/commands/check.ts +43 -82
  190. package/src/cli/commands/constraints-report.ts +4 -59
  191. package/src/cli/commands/constraints-retire.ts +49 -154
  192. package/src/cli/commands/constraints.ts +11 -26
  193. package/src/cli/commands/definitions.ts +7 -12
  194. package/src/cli/commands/init.ts +8 -179
  195. package/src/cli/commands/report.ts +19 -23
  196. package/src/cli/commands/scaffold-templates.ts +1 -53
  197. package/src/cli/commands/scaffold.ts +0 -11
  198. package/src/cli/commands/status.ts +10 -10
  199. package/src/cli/commands/sync-docs/agents-syncer.ts +4 -25
  200. package/src/core/CONTEXT.md +9 -9
  201. package/src/core/constraints/__tests__/capability-counts.test.ts +5 -5
  202. package/src/core/constraints/__tests__/collect-constraints.test.ts +13 -8
  203. package/src/core/constraints/__tests__/git-evidence.test.ts +4 -7
  204. package/src/core/constraints/__tests__/injection-writer.test.ts +8 -61
  205. package/src/core/constraints/__tests__/run-env.test.ts +5 -34
  206. package/src/core/constraints/__tests__/trace-injection.test.ts +1 -1
  207. package/src/core/constraints/capabilities-parser.ts +17 -5
  208. package/src/core/constraints/checker.ts +39 -88
  209. package/src/core/constraints/checkers/__tests__/check-outcome.test.ts +5 -8
  210. package/src/core/constraints/checkers/__tests__/governance-presence.test.ts +1 -53
  211. package/src/core/constraints/checkers/__tests__/iron-flags.test.ts +5 -25
  212. package/src/core/constraints/checkers/docs-freshness.ts +1 -1
  213. package/src/core/constraints/checkers/governance-presence.ts +4 -3
  214. package/src/core/constraints/checkers/index.ts +4 -10
  215. package/src/core/constraints/checkers/iron-flags.ts +3 -12
  216. package/src/core/constraints/checkers/no-test-simplification.ts +1 -1
  217. package/src/core/constraints/checkers/types.ts +1 -1
  218. package/src/core/constraints/definitions/guidelines.ts +8 -25
  219. package/src/core/constraints/definitions/iron-laws.ts +9 -82
  220. package/src/core/constraints/definitions.ts +14 -15
  221. package/src/core/constraints/index.ts +4 -19
  222. package/src/core/constraints/injection-writer.ts +16 -61
  223. package/src/core/constraints/run-env.ts +1 -33
  224. package/src/core/constraints/usage-report.ts +9 -16
  225. package/src/core/effective-constraints.ts +14 -45
  226. package/src/core/index.ts +3 -10
  227. package/src/core/project-config-loader.ts +20 -145
  228. package/src/core/validators/passes-gate.ts +6 -6
  229. package/src/failure/CONTEXT.md +1 -1
  230. package/src/hooks/__tests__/bootstrap.test.ts +3 -5
  231. package/src/index.ts +28 -18
  232. package/src/knowledge/CONTEXT.md +4 -3
  233. package/src/knowledge/__tests__/lint.test.ts +84 -0
  234. package/src/knowledge/__tests__/store.test.ts +70 -0
  235. package/src/knowledge/lint.ts +60 -1
  236. package/src/knowledge/store.ts +48 -11
  237. package/src/knowledge/types.ts +7 -1
  238. package/src/monitoring/CONTEXT.md +1 -1
  239. package/src/monitoring/__tests__/trace-file-anchoring.test.ts +1 -1
  240. package/src/monitoring/__tests__/traces.test.ts +22 -22
  241. package/src/monitoring/trace-analyzer.ts +12 -13
  242. package/src/monitoring/traces.ts +8 -8
  243. package/src/presets/__tests__/standard.test.ts +12 -16
  244. package/src/presets/standard.ts +14 -23
  245. package/src/types/__tests__/types.test.ts +3 -3
  246. package/src/types/constraint.ts +26 -40
  247. package/src/types/passes-gate.ts +5 -5
  248. package/src/types/project-config.ts +8 -77
  249. package/src/types/trace.ts +8 -11
  250. package/dist/cli/commands/posteval-plan.d.ts +0 -15
  251. package/dist/cli/commands/posteval-plan.d.ts.map +0 -1
  252. package/dist/cli/commands/posteval-plan.js +0 -86
  253. package/dist/cli/commands/posteval-plan.js.map +0 -1
  254. package/dist/core/constraints/agent-prompt-renderer.d.ts +0 -32
  255. package/dist/core/constraints/agent-prompt-renderer.d.ts.map +0 -1
  256. package/dist/core/constraints/agent-prompt-renderer.js +0 -55
  257. package/dist/core/constraints/agent-prompt-renderer.js.map +0 -1
  258. package/dist/core/constraints/checkers/no-bypass-checkpoint.d.ts +0 -6
  259. package/dist/core/constraints/checkers/no-bypass-checkpoint.d.ts.map +0 -1
  260. package/dist/core/constraints/checkers/no-bypass-checkpoint.js +0 -40
  261. package/dist/core/constraints/checkers/no-bypass-checkpoint.js.map +0 -1
  262. package/dist/core/constraints/definitions/prompts.d.ts +0 -12
  263. package/dist/core/constraints/definitions/prompts.d.ts.map +0 -1
  264. package/dist/core/constraints/definitions/prompts.js +0 -400
  265. package/dist/core/constraints/definitions/prompts.js.map +0 -1
  266. package/dist/core/constraints/injection-drift.d.ts +0 -61
  267. package/dist/core/constraints/injection-drift.d.ts.map +0 -1
  268. package/dist/core/constraints/injection-drift.js +0 -131
  269. package/dist/core/constraints/injection-drift.js.map +0 -1
  270. package/dist/core/constraints/injection-renderer.d.ts +0 -23
  271. package/dist/core/constraints/injection-renderer.d.ts.map +0 -1
  272. package/dist/core/constraints/injection-renderer.js +0 -44
  273. package/dist/core/constraints/injection-renderer.js.map +0 -1
  274. package/src/cli/commands/__tests__/check-drift.test.ts +0 -158
  275. package/src/cli/commands/__tests__/init-injection.test.ts +0 -466
  276. package/src/cli/commands/__tests__/posteval-plan.test.ts +0 -204
  277. package/src/cli/commands/posteval-plan.ts +0 -98
  278. package/src/core/constraints/__tests__/agent-prompt-renderer.test.ts +0 -129
  279. package/src/core/constraints/__tests__/injection-drift.test.ts +0 -247
  280. package/src/core/constraints/agent-prompt-renderer.ts +0 -67
  281. package/src/core/constraints/checkers/__tests__/no-bypass-checkpoint.test.ts +0 -76
  282. package/src/core/constraints/checkers/no-bypass-checkpoint.ts +0 -40
  283. package/src/core/constraints/definitions/prompts.ts +0 -414
  284. package/src/core/constraints/injection-drift.ts +0 -142
  285. package/src/core/constraints/injection-renderer.ts +0 -44
@@ -1,13 +1,14 @@
1
1
  /**
2
- * 治理链路的 io 注入不逃逸(harness#149
2
+ * 治理链路的 io 注入不逃逸(harness#149,ADR-0029 收窄)
3
3
  *
4
- * setupGovernance 手握 io,却在两个调用点把它丢了(`setupClaudeMdOutputStyle(projectPath)`
5
- * / `setupGovernanceConstraints(projectPath)`),被调方一律 `io: CommandIO = processIO`
6
- * 兜成真实 stdout。真机输出正常,但注入面的测试看不见那 14 条提示——`⚠️ …标记残缺…`
7
- * 这类唯一提示写坏了没有测试会红。
4
+ * setupGovernance 手握 io,曾在调用点把它丢了(`setupClaudeMdOutputStyle(projectPath)`),
5
+ * 被调方一律 `io: CommandIO = processIO` 兜成真实 stdout。真机输出正常,但注入面的
6
+ * 测试看不见那些提示——`⚠️ …标记残缺…` 这类唯一提示写坏了没有测试会红。
8
7
  *
9
8
  * 本文件不 mock 任何 IO:在临时目录里真跑 init,断言治理段提示落在**注入面**。
10
- * 改造前这些断言逐条为红(文本逃到了 process.stdout)。
9
+ * ADR-0029:约束注入段 writer(setupAgentsMdConstraints / setupClaudeMdConstraints /
10
+ * setupGovernanceConstraints)已随文本注入层关停删除,相关用例移除;
11
+ * Output Style 段(通用 marker 机制)保留。
11
12
  */
12
13
 
13
14
  import * as fs from 'fs/promises';
@@ -63,49 +64,10 @@ describe('init 治理链路的提示落在注入面(harness#149)', () => {
63
64
  expect(io.outText()).toContain('✅ 已在 CLAUDE.md 顶部写入 Output Style 段');
64
65
  });
65
66
 
66
- it('治理契约追加到既有 AGENTS.md:`已追加治理契约` 进捕获 stdout', async () => {
67
- const io = await runInit({ 'AGENTS.md': '# AGENTS.md\n\n既有导读\n' });
68
- expect(io.outText()).toContain('✅ 已追加治理契约 PRESERVE:governance 段到 AGENTS.md');
69
- });
70
-
71
- it('标记残缺(唯一提示):`标记残缺…请人工修复` 进捕获 stdout', async () => {
72
- const io = await runInit({ 'AGENTS.md': '# AGENTS.md\n\n<!-- PRESERVE:governance -->\n残缺段\n' });
73
- expect(io.outText()).toContain('⚠️ AGENTS.md 中 PRESERVE:governance 标记残缺(只有单边),跳过治理契约写入,请人工修复');
74
- });
75
-
76
- // #158 补钉:这类提示在 init.ts 实测有四处,#149 只钉住上面一条——其余三处各补一条
77
- // 捕获面断言。四处分支不同文件/不同段位,fixture 各自单建,不共用残缺文件。
78
-
79
- it('标记残缺四处之二:CLAUDE.md 的 HARNESS_OUTPUT_STYLE 单边 → Output Style 注入告警', async () => {
67
+ it('标记残缺(唯一提示):HARNESS_OUTPUT_STYLE 单边 Output Style 注入告警进捕获 stdout', async () => {
80
68
  const io = await runInit({ 'CLAUDE.md': '# CLAUDE.md\n\n<!-- HARNESS_OUTPUT_STYLE_START -->\n半残段\n' });
81
69
  expect(io.outText()).toContain('⚠️ CLAUDE.md 中 HARNESS_OUTPUT_STYLE 标记残缺(单边或乱序),跳过 Output Style 注入,请人工修复');
82
70
  });
83
-
84
- it('标记残缺四处之三:AGENTS.md 的 PRESERVE 段内 HARNESS_CONSTRAINTS 单边 → 段内告警', async () => {
85
- const broken = [
86
- '# AGENTS.md',
87
- '',
88
- '<!-- PRESERVE:governance -->',
89
- '手写契约',
90
- '',
91
- '<!-- HARNESS_CONSTRAINTS_START -->',
92
- '半残注入',
93
- '<!-- /PRESERVE:governance -->',
94
- '',
95
- ].join('\n');
96
- const io = await runInit({ 'AGENTS.md': broken });
97
- expect(io.outText()).toContain('⚠️ AGENTS.md PRESERVE:governance 段内 HARNESS_CONSTRAINTS 标记残缺(单边或乱序),跳过治理契约写入,请人工修复');
98
- });
99
-
100
- it('标记残缺四处之四:CLAUDE.md 的 HARNESS_CONSTRAINTS 单边 → 治理约束注入告警(旧模型仓落点)', async () => {
101
- const io = await runInit({ 'CLAUDE.md': '# CLAUDE.md\n\n<!-- HARNESS_CONSTRAINTS_START -->\n半残段\n' });
102
- expect(io.outText()).toContain('⚠️ CLAUDE.md 中 HARNESS_CONSTRAINTS 标记残缺(单边或乱序),跳过治理约束注入,请人工修复');
103
- });
104
-
105
- it('新仓创建 AGENTS.md 治理段:创建提示进捕获 stdout', async () => {
106
- const io = await runInit({});
107
- expect(io.outText()).toContain('✅ 已创建 AGENTS.md 并写入治理契约 PRESERVE:governance 段');
108
- });
109
71
  });
110
72
 
111
73
  describe('writer 层 io 必传(源形状闸,防缺省兜底再回来)', () => {
@@ -115,17 +77,10 @@ describe('writer 层 io 必传(源形状闸,防缺省兜底再回来)', ()
115
77
  expect(sites[0]).toMatch(/^export async function init\(/);
116
78
  });
117
79
 
118
- it('三个 writer 与落点路由的 io 均为必传形参', () => {
119
- for (const writer of [
120
- 'setupClaudeMdOutputStyle',
121
- 'setupAgentsMdConstraints',
122
- 'setupClaudeMdConstraints',
123
- 'setupGovernanceConstraints',
124
- ]) {
125
- expect(INIT_SOURCE).toMatch(
126
- new RegExp(`export async function ${writer}\\(projectPath: string, io: CommandIO\\)`),
127
- );
128
- }
80
+ it('Output Style writer io 为必传形参', () => {
81
+ expect(INIT_SOURCE).toMatch(
82
+ /export async function setupClaudeMdOutputStyle\(projectPath: string, io: CommandIO\)/,
83
+ );
129
84
  });
130
85
 
131
86
  it('setupGovernance 的调用点逐个传 io(不留裸 projectPath 调用)', () => {
@@ -134,6 +89,5 @@ describe('writer 层 io 必传(源形状闸,防缺省兜底再回来)', ()
134
89
  INIT_SOURCE.indexOf('/**\n * 目录 CONTEXT.md 骨架的 plan'),
135
90
  );
136
91
  expect(governanceBody).toMatch(/await setupClaudeMdOutputStyle\(projectPath, io\)/);
137
- expect(governanceBody).toMatch(/await setupGovernanceConstraints\(projectPath, io\)/);
138
92
  });
139
93
  });
@@ -3,8 +3,10 @@
3
3
  *
4
4
  * init.test.ts 把 fs/promises 整体 mock 掉,只能看到「调过 writeFile」,看不到
5
5
  * 真写出了什么内容。本文件不 mock 任何 IO:在临时目录里真跑两遍 init——
6
- * 第一遍断言 9 个受管文件的落盘字节,第二遍(文件已在场且被用户改过)断言
7
- * 9 站点各自的第三态、用户内容一字节不动、以及「打印片段 == 真正落盘的内容」。
6
+ * 第一遍断言 8 个受管文件的落盘字节,第二遍(文件已在场且被用户改过)断言
7
+ * 8 站点各自的第三态、用户内容一字节不动、以及「打印片段 == 真正落盘的内容」。
8
+ * ADR-0029:custom-constraints.yml 示例站与 AGENTS.md 治理契约段 writer 已随
9
+ * 文本注入层关停移除,落盘集合同步收缩。
8
10
  */
9
11
 
10
12
  import * as fs from 'fs/promises';
@@ -120,9 +122,9 @@ describe('init 真落盘(无 IO mock)', () => {
120
122
 
121
123
  expect(await init({ ...INIT_OPTIONS, projectPath: root }, io)).toEqual({ kind: 'ok' });
122
124
 
123
- // 冻结的整屏 = scaffold 9 站点 + 治理段 writer 的落盘提示。#149 前 io 在
124
- // setupGovernance 两个调用点被丢,治理 writer 的提示逃到 process.stdout、不进捕获面
125
- // (本文件因此曾缺这一行);io 贯通后它回到捕获面,真机输出的字节不变。
125
+ // 冻结的整屏 = scaffold 8 站点 + 治理段 writer 的落盘提示。#149 前 io 在
126
+ // setupGovernance 调用点被丢,治理 writer 的提示逃到 process.stdout、不进捕获面;
127
+ // io 贯通后它回到捕获面,真机输出的字节不变。
126
128
  expect(normalize(io.outText(), root)).toBe(`🚀 初始化 harness 配置...
127
129
  配置目录: <P>/.harness
128
130
  预设: standard
@@ -130,14 +132,12 @@ describe('init 真落盘(无 IO mock)', () => {
130
132
  ✅ 已创建配置文件: <P>/.harness/config.yml (v*)
131
133
  ✅ 已创建示例检查点文件: <P>/.harness/checkpoints.yml
132
134
  ✅ 已创建 Resolutions 文件: <P>/.harness/resolutions.json
133
- ✅ 已创建自定义约束示例: custom-constraints.yml
134
135
  ✅ 已创建 .git/hooks/pre-commit
135
136
  ✅ 已创建 .git/hooks/pre-push
136
137
  ✅ 已创建 .github/workflows/harness-check.yml
137
138
 
138
139
  📋 设置治理文件...
139
140
  ✅ 已创建 CHANGELOG.md
140
- ✅ 已创建 AGENTS.md 并写入治理契约 PRESERVE:governance 段 (v*)
141
141
  ✅ 已创建 src/CONTEXT.md
142
142
  治理检查已由 harness-check.yml 覆盖,跳过创建 harness-governance.yml
143
143
 
@@ -145,9 +145,8 @@ describe('init 真落盘(无 IO mock)', () => {
145
145
 
146
146
  下一步:
147
147
  1. 编辑 .harness/config.yml 自定义配置
148
- 2. 编辑 .harness/custom-constraints.yml 添加项目约束
149
- 3. 正常开发:每次 git commit 查暂存的(增量快反馈),每次 git push 查整仓的(全量兜底)——重复是设计使然
150
- 4. 运行 harness status 查看状态
148
+ 2. 正常开发:每次 git commit 查暂存的(增量快反馈),每次 git push 查整仓的(全量兜底)——重复是设计使然
149
+ 3. 运行 harness status 查看状态
151
150
 
152
151
  💡 提示: 使用 harness init --print-snippets 查看配置代码片段
153
152
  `);
@@ -157,14 +156,13 @@ describe('init 真落盘(无 IO mock)', () => {
157
156
  const hook = await read('.git/hooks/pre-commit');
158
157
  expect(hook.startsWith('#!/bin/sh\n# Harness pre-commit hook\n')).toBe(true);
159
158
  expect(hook).toContain('echo "🔍 Running harness checks..."');
160
- expect(hook).toContain("grep -E 'plans/.*\\.md$|\\.plan\\.md$'");
159
+ expect(hook).toContain('npx @dommaker/harness check --staged');
161
160
  expect(hook.endsWith('echo "✅ All checks passed"\n')).toBe(true);
162
161
 
163
162
  // 第 9 站点(#144):字节级冻结,改模板必须同步改这份基线(同 GITLAB_PLAIN 手法)
164
163
  expect(await read('.git/hooks/pre-push')).toBe(PRE_PUSH_HOOK_BYTES);
165
164
 
166
165
  expect(await read('.github/workflows/harness-check.yml')).toContain('name: Harness Check');
167
- expect(await read('.harness/custom-constraints.yml')).toContain('custom_constraints:');
168
166
  expect(await read('.harness/checkpoints.yml')).toContain('id: build-success');
169
167
  expect(JSON.parse(await read('.harness/resolutions.json')).capability_sync).toBeDefined();
170
168
  expect(await read('CHANGELOG.md')).toContain('Keep a Changelog');
@@ -186,11 +184,10 @@ describe('init 真落盘(无 IO mock)', () => {
186
184
  await init({ ...INIT_OPTIONS, projectPath: root }, io);
187
185
  const lines = io.outLines();
188
186
 
189
- // 顺序 = init 的落盘顺序;harness-governance.yml(第九站)因既有 workflow 覆盖而跳过
187
+ // 顺序 = init 的落盘顺序;harness-governance.yml(末站)因既有 workflow 覆盖而跳过
190
188
  expectOrderedSubsequence(lines, [
191
189
  'checkpoints.yml 已存在,跳过',
192
190
  'resolutions.json 已存在,跳过',
193
- 'custom-constraints.yml 已存在',
194
191
  '⚠️ .git/hooks/pre-commit 已存在',
195
192
  '💡 请手动添加以下内容到文件末尾:',
196
193
  '⚠️ .git/hooks/pre-push 已存在',
@@ -223,7 +220,6 @@ describe('init 真落盘(无 IO mock)', () => {
223
220
  '.git/hooks/pre-commit': '#!/bin/sh\n# 我自己的钩子\n',
224
221
  '.git/hooks/pre-push': '#!/bin/sh\n# 我自己的推送钩子\n',
225
222
  '.github/workflows/harness-check.yml': 'name: 我自己的流水线\n',
226
- '.harness/custom-constraints.yml': 'custom_constraints: {}\n',
227
223
  '.harness/checkpoints.yml': 'checkpoints: []\n',
228
224
  '.harness/resolutions.json': '{}\n',
229
225
  'CHANGELOG.md': '# 我的更新日志\n',
@@ -274,9 +270,8 @@ describe('init 真落盘(无 IO mock)', () => {
274
270
  expect(io.outText()).not.toContain('harness-governance.yml');
275
271
  expect(await exists(path.join(root, '.github'))).toBe(false);
276
272
  expect(await exists(path.join(root, '.gitlab-ci.yml'))).toBe(false);
277
- // 治理文档面照常:CHANGELOG / 约束段 / CONTEXT.md 不受 CI 豁免影响
273
+ // 治理文档面照常:CHANGELOG / CONTEXT.md 不受 CI 豁免影响
278
274
  expect(await exists(path.join(root, 'CHANGELOG.md'))).toBe(true);
279
- expect(await exists(path.join(root, 'AGENTS.md'))).toBe(true);
280
275
  });
281
276
 
282
277
  it('无 .git 与无源码目录时仍按原措辞告知,不写任何文件', async () => {
@@ -556,9 +551,7 @@ describe('init --ci × -g 组合边界(harness#156,真落盘)', () => {
556
551
  '.git/hooks/pre-push',
557
552
  '.harness/checkpoints.yml',
558
553
  '.harness/config.yml',
559
- '.harness/custom-constraints.yml',
560
554
  '.harness/resolutions.json',
561
- 'AGENTS.md',
562
555
  'CHANGELOG.md',
563
556
  'src/CONTEXT.md',
564
557
  'src/index.ts',
@@ -591,9 +584,8 @@ harness:
591
584
  version: *
592
585
  `);
593
586
 
594
- // 治理文档面(CHANGELOG / 约束段 / CONTEXT.md)在 none 下照常生成,不受 CI 豁免影响
587
+ // 治理文档面(CHANGELOG / CONTEXT.md)在 none 下照常生成,不受 CI 豁免影响
595
588
  expect(await fs.readFile(path.join(root, 'CHANGELOG.md'), 'utf-8')).toContain('Keep a Changelog');
596
- expect(await fs.readFile(path.join(root, 'AGENTS.md'), 'utf-8')).toContain('PRESERVE:governance');
597
589
  expect(await fs.readFile(path.join(root, 'src/CONTEXT.md'), 'utf-8')).toBe(CONTEXT_MD_BYTES);
598
590
  });
599
591
 
@@ -105,8 +105,7 @@ describe('init command', () => {
105
105
  it('应该输出代码片段模式', async () => {
106
106
  await init({ preset: 'standard', printSnippets: true }, io);
107
107
  expect(io.outText()).not.toBe('');
108
- // 打印版与落盘版 plan 匹配模式须一致(#35:模板字面量 \. 运行期退化为 .)
109
- expect(io.outText()).toContain("grep -E 'plans/.*\\.md$|\\.plan\\.md$'");
108
+ expect(io.outText()).toContain('npx @dommaker/harness check --staged');
110
109
  });
111
110
  });
112
111
 
@@ -153,10 +152,7 @@ describe('init command', () => {
153
152
  const hookCall = writeCalls.find((c: any[]) => String(c[0]).includes('pre-commit'));
154
153
  expect(hookCall).toBeDefined();
155
154
  expect(hookCall![1]).toContain('npx @dommaker/harness check --staged');
156
- expect(hookCall![1]).toContain('npx @dommaker/harness posteval-plan');
157
155
  expect(hookCall![1]).not.toMatch(/npx harness /);
158
- // plan 匹配模式须为转义点(#35:模板字面量 \. 运行期退化为 .)
159
- expect(hookCall![1]).toContain("grep -E 'plans/.*\\.md$|\\.plan\\.md$'");
160
156
  });
161
157
 
162
158
  it('pre-commit 片段与落盘 hook 同源(#103:差异行并入共享片段,无第二份文本)', async () => {
@@ -308,17 +304,6 @@ describe('init command', () => {
308
304
  });
309
305
  });
310
306
 
311
- describe('custom-constraints', () => {
312
- it('应该跳过创建当已存在', async () => {
313
- mockFs.mkdir.mockResolvedValue(undefined);
314
- mockFs.writeFile.mockResolvedValue(undefined);
315
- existingFiles.add(`${PROJECT}/.harness/custom-constraints.yml`);
316
-
317
- await init({ preset: 'standard', projectPath: PROJECT }, io);
318
- expect(io.outText()).toContain('custom-constraints.yml 已存在');
319
- });
320
- });
321
-
322
307
  describe('governance', () => {
323
308
  it('应该在配置中包含 governance 段', async () => {
324
309
  mockFs.mkdir.mockResolvedValue(undefined);
@@ -57,7 +57,7 @@ const performanceCli = GATE_DEFINITIONS.find(g => g.id === 'performance')!.cli;
57
57
  const reviewCli = GATE_DEFINITIONS.find(g => g.id === 'review')!.cli;
58
58
 
59
59
  describe('constraints report 三阈值:装配点 fail-loud', () => {
60
- const valid = { json: false, zeroInterceptMin: '50', noiseFailRate: '0.8', noiseMinTotal: '20' };
60
+ const valid = { jsonOutput: false, zeroInterceptMin: '50', noiseFailRate: '0.8', noiseMinTotal: '20' };
61
61
 
62
62
  it('缺省字符串 → 数值(int/int/float 各归其形)', () => {
63
63
  expect(reportDef.mapActionArgs!([], valid)).toEqual([{
@@ -85,7 +85,7 @@ describe('passes-gate 重试选项已删除(A1)', () => {
85
85
  it('采集面确实覆盖三类命令位(前提,防空扫致闸失效)', () => {
86
86
  const rendered = ALL_CLI_SITES.map(s => `${s.slot} ${s.token}`);
87
87
  expect(rendered).toContain('passes-gate --coverage-threshold'); // 通用表叶子命令的旗帜
88
- expect(rendered).toContain('constraints report --json'); // children 递归(嵌套命令位)
88
+ expect(rendered).toContain('constraints report --json-output'); // children 递归(嵌套命令位)
89
89
  expect(rendered).toContain('acceptance --task-id'); // 门禁表命令位(GATE_DEFINITIONS.cli)
90
90
  expect(rendered).toContain('check list'); // 选项路由键(commander camelCase 键位)
91
91
  });
@@ -210,7 +210,7 @@ describe('-p 锚定:执行与 IO 必须落在 projectPath(cwd ≠ projectPat
210
210
  .slice(seeded)
211
211
  .map(l => JSON.parse(l) as { constraintId: string; projectPath?: string });
212
212
  expect(written.map(t => t.constraintId)).toEqual(
213
- expect.arrayContaining(['incremental_progress', 'no_implementation_without_requirement'])
213
+ expect.arrayContaining(['no_completion_without_verification', 'no_hardcoded_credentials'])
214
214
  );
215
215
  expect(written.every(t => t.projectPath === projectSide)).toBe(true);
216
216
  // 病灶:修复前这一支落在调用方 cwd(A),B 侧 mtime 不动
@@ -231,7 +231,7 @@ describe('-p 锚定:执行与 IO 必须落在 projectPath(cwd ≠ projectPat
231
231
  expect(await status({ projectPath: projectSide }, io)).toEqual({ kind: 'ok' });
232
232
  // 记录数取自 B 的正本行数:写侧漏到 A 就必然对不上(假绿),读到 A 也读不到 check 的落点
233
233
  expect(io.outText()).toContain(`记录数: ${traceLinesOf(projectSide).length} 条`);
234
- expect(io.outText()).toContain('no_implementation_without_requirement');
234
+ expect(io.outText()).toContain('no_completion_without_verification');
235
235
  });
236
236
 
237
237
  it('不带 --project-path 的项目内使用:落点仍是当下 cwd(存量使用者无感)', async () => {
@@ -35,7 +35,7 @@ function collectRefs(defs: CommandDefinition[]): CommandImplRef[] {
35
35
 
36
36
  const EXPECTED_TOP_LEVEL_COMMANDS = [
37
37
  'check', 'validate', 'passes-gate', 'init', 'report', 'status', 'spec',
38
- 'sync-docs', 'knowledge', 'sdd', 'failure', 'posteval-plan',
38
+ 'sync-docs', 'knowledge', 'sdd', 'failure',
39
39
  'release', 'constraints',
40
40
  'spec-baseline-check',
41
41
  // 6 门禁命令(GATE_DEFINITIONS 驱动)
@@ -46,8 +46,8 @@ describe('report command - 补充覆盖', () => {
46
46
 
47
47
  expect(output).toContain('# Harness 检查报告');
48
48
  expect(output).toContain('## 约束检查');
49
- expect(output).toContain('Iron Laws');
50
- expect(output).toContain('Guidelines');
49
+ expect(output).toContain('error ');
50
+ expect(output).toContain('warning 级');
51
51
  expect(output).toContain('@dommaker/harness');
52
52
  });
53
53
  });
@@ -71,8 +71,8 @@ describe('report command - 补充覆盖', () => {
71
71
  expect(data).toHaveProperty('timestamp');
72
72
  expect(data).toHaveProperty('constraints');
73
73
  expect(data.constraints).toHaveProperty('total');
74
- expect(data.constraints).toHaveProperty('ironLaws');
75
- expect(data.constraints).toHaveProperty('guidelines');
74
+ expect(data.constraints).toHaveProperty('errors');
75
+ expect(data.constraints).toHaveProperty('warnings');
76
76
  expect(data.constraints).toHaveProperty('violations');
77
77
  });
78
78
  });
@@ -97,7 +97,7 @@ describe('report command', () => {
97
97
  const parsed = JSON.parse(jsonStr);
98
98
  expect(parsed.constraints).toBeDefined();
99
99
  expect(parsed.constraints.total).toBeGreaterThan(0);
100
- expect(parsed.constraints.ironLaws).toBeGreaterThan(0);
100
+ expect(parsed.constraints.errors).toBeGreaterThan(0);
101
101
  expect(parsed.timestamp).toBeDefined();
102
102
  expect(parsed.projectPath).toBeDefined();
103
103
  });
@@ -26,7 +26,6 @@ import {
26
26
  preCommitHookFile,
27
27
  prePushHookFile,
28
28
  harnessCheckCiFile,
29
- customConstraintsFile,
30
29
  changelogFile,
31
30
  contextDocFile,
32
31
  governanceWorkflowFile,
@@ -72,12 +71,11 @@ class MemoryFs implements ScaffoldFileSystem {
72
71
  const PROJECT = '/srv/project';
73
72
  const USER_CONTENT = '用户自己的内容,不许覆盖\n';
74
73
 
75
- /** 全部 9 站点,顺序 = init 的落盘顺序 */
74
+ /** 全部 8 站点,顺序 = init 的落盘顺序 */
76
75
  function allSites(): ManagedFile[] {
77
76
  return [
78
77
  checkpointsFile(PROJECT),
79
78
  resolutionsFile(PROJECT),
80
- customConstraintsFile(PROJECT),
81
79
  preCommitHookFile(PROJECT),
82
80
  prePushHookFile(PROJECT),
83
81
  harnessCheckCiFile(PROJECT, 'github', ['ci.yml']),
@@ -113,7 +111,7 @@ beforeEach(() => {
113
111
 
114
112
  describe('writeManagedFile:三态判定', () => {
115
113
  it('不在场 → created:建父目录、落盘模板正文、绿字告知', async () => {
116
- const file = customConstraintsFile(PROJECT);
114
+ const file = changelogFile(PROJECT, 'keep-a-changelog');
117
115
 
118
116
  expect(await writeManagedFile(file, io, fs)).toBe('created');
119
117
 
@@ -179,7 +177,7 @@ describe('writeManagedFile:三态判定', () => {
179
177
  });
180
178
 
181
179
  it('runPlan 按顺序逐站点落盘并逐站点回报状态', async () => {
182
- const plan = [customConstraintsFile(PROJECT), changelogFile(PROJECT, 'keep-a-changelog')];
180
+ const plan = [checkpointsFile(PROJECT), changelogFile(PROJECT, 'keep-a-changelog')];
183
181
  fs.seed(plan[1].target, USER_CONTENT);
184
182
 
185
183
  expect(await runPlan(plan, io, fs)).toEqual(['created', 'exists']);
@@ -188,11 +186,10 @@ describe('writeManagedFile:三态判定', () => {
188
186
  });
189
187
 
190
188
  describe('init 的脚手架 plan 站点面', () => {
191
- it('9 站点齐备且目标路径逐字冻结(init 7 + validate 2 同源收口)', () => {
189
+ it('8 站点齐备且目标路径逐字冻结(init 6 + validate 2 同源收口)', () => {
192
190
  expect(allSites().map(f => f.target)).toEqual([
193
191
  `${PROJECT}/.harness/checkpoints.yml`,
194
192
  `${PROJECT}/.harness/resolutions.json`,
195
- `${PROJECT}/.harness/custom-constraints.yml`,
196
193
  `${PROJECT}/.git/hooks/pre-commit`,
197
194
  `${PROJECT}/.git/hooks/pre-push`,
198
195
  `${PROJECT}/.github/workflows/harness-check.yml`,
@@ -342,13 +339,6 @@ describe('对外文案逐字冻结(9 站点 × 落盘态 / 在场态)', () =
342
339
  ],
343
340
  'name: Harness Check',
344
341
  ],
345
- [
346
- 'custom-constraints.yml',
347
- () => customConstraintsFile(PROJECT),
348
- '✅ 已创建自定义约束示例: custom-constraints.yml',
349
- ['custom-constraints.yml 已存在'],
350
- '',
351
- ],
352
342
  [
353
343
  'checkpoints.yml',
354
344
  () => checkpointsFile(PROJECT),
@@ -18,8 +18,8 @@ import { status } from '../status';
18
18
  const STATUS_SOURCE = fs.readFileSync(path.join(__dirname, '..', 'status.ts'), 'utf-8');
19
19
 
20
20
  /** 1 pass + 1 fail:failRate 0.5、passRate 0.5 → 无异常;2 fail:passRate 0 → low_pass_rate */
21
- const PASS = { constraintId: 'alpha', level: 'iron_law' as const, result: 'pass' as const };
22
- const FAIL = { constraintId: 'beta', level: 'guideline' as const, result: 'fail' as const };
21
+ const PASS = { constraintId: 'alpha', severity: 'error' as const, result: 'pass' as const };
22
+ const FAIL = { constraintId: 'beta', severity: 'warning' as const, result: 'fail' as const };
23
23
 
24
24
  let io: CapturingIO;
25
25
  beforeEach(() => {
@@ -47,7 +47,7 @@ describe('status 分析接线(ADR-0020)', () => {
47
47
 
48
48
  await status({ projectPath: root, detail: true }, io);
49
49
 
50
- expect(io.outText()).toContain('🔴 Iron Laws:');
50
+ expect(io.outText()).toContain('🔴 error 级约束:');
51
51
  expect(io.outText()).toContain('alpha');
52
52
  expect(io.outText()).toContain('检查: 2 | 通过: 100% | 失败: 0%');
53
53
  expect(io.outText()).not.toContain('个异常');
@@ -34,7 +34,7 @@ const mockFs = fs as jest.Mocked<typeof fs>;
34
34
  /** trace 文件内容:一 trace 一行,缺省字段补齐成合法 ExecutionTrace(timestamp 递增) */
35
35
  function traceFile(traces: Array<Partial<ExecutionTrace>>): string {
36
36
  return traces
37
- .map((t, i) => JSON.stringify({ level: 'iron_law', timestamp: i + 1, result: 'pass', ...t }))
37
+ .map((t, i) => JSON.stringify({ severity: 'error', timestamp: i + 1, result: 'pass', ...t }))
38
38
  .join('\n');
39
39
  }
40
40
 
@@ -77,7 +77,7 @@ describe('status command - 补充覆盖', () => {
77
77
  it('有异常时应该显示详细信息和下一步建议', async () => {
78
78
  // 两个约束各自全失败 → 各自判出一枚 low_pass_rate
79
79
  mockFs.readFileSync.mockReturnValue(traceFile([
80
- ...repeats('no_bypass_checkpoint', 2, 'fail'),
80
+ ...repeats('docs_freshness', 2, 'fail'),
81
81
  ...repeats('no_completion_without_verification', 2, 'fail'),
82
82
  ]));
83
83
 
@@ -102,9 +102,9 @@ describe('status command - 补充覆盖', () => {
102
102
  });
103
103
 
104
104
  describe('约束级别统计', () => {
105
- it('应该显示 Iron Laws 统计', async () => {
105
+ it('应该显示 error 级约束统计', async () => {
106
106
  mockFs.readFileSync.mockReturnValue(traceFile([
107
- { constraintId: 'no_bypass_checkpoint' },
107
+ { constraintId: 'docs_freshness' },
108
108
  { constraintId: 'no_completion_without_verification' },
109
109
  ]));
110
110
 
@@ -112,35 +112,35 @@ describe('status command - 补充覆盖', () => {
112
112
 
113
113
  const output = io.outText();
114
114
  expect(output).toContain('📈 约束统计:');
115
- expect(output).toContain('🔴 Iron Laws:');
115
+ expect(output).toContain('🔴 error 级约束:');
116
116
  expect(output).toContain('✅ no_completion_without_verification');
117
117
  });
118
118
 
119
- it('应该显示 Guidelines 统计', async () => {
119
+ it('应该显示 warning 级约束统计', async () => {
120
120
  mockFs.readFileSync.mockReturnValue(traceFile([
121
- { constraintId: 'capability_sync', level: 'guideline', result: 'pass' },
121
+ { constraintId: 'capability_sync', severity: 'warning', result: 'pass' },
122
122
  ]));
123
123
 
124
124
  await runStatus();
125
125
 
126
- expect(io.outText()).toContain('🟡 Guidelines:');
126
+ expect(io.outText()).toContain('🟡 warning 级约束:');
127
127
  });
128
128
  });
129
129
 
130
130
  describe('详细模式扩展', () => {
131
131
  it('详细模式应该显示所有级别详情', async () => {
132
132
  mockFs.readFileSync.mockReturnValue(traceFile([
133
- { constraintId: 'no_bypass_checkpoint', level: 'iron_law' },
134
- { constraintId: 'capability_sync', level: 'guideline' },
135
- { constraintId: 'capability_sync', level: 'guideline' },
133
+ { constraintId: 'docs_freshness', severity: 'error' },
134
+ { constraintId: 'capability_sync', severity: 'warning' },
135
+ { constraintId: 'capability_sync', severity: 'warning' },
136
136
  ]));
137
137
 
138
138
  await runStatus({ detail: true });
139
139
 
140
140
  const output = io.outText();
141
141
  expect(output).toContain('📈 约束统计:');
142
- expect(output).toContain('🔴 Iron Laws:');
143
- expect(output).toContain('🟡 Guidelines:');
142
+ expect(output).toContain('🔴 error 级约束:');
143
+ expect(output).toContain('🟡 warning 级约束:');
144
144
  expect(output).toContain('检查: 2 | 通过: 100% | 失败: 0%');
145
145
  });
146
146
  });
@@ -148,7 +148,7 @@ describe('status command - 补充覆盖', () => {
148
148
  describe('JSON parse 异常处理', () => {
149
149
  it('无效 JSON 行应该被过滤', async () => {
150
150
  mockFs.readFileSync.mockReturnValue(
151
- ['invalid json', JSON.stringify({ constraintId: 'valid', level: 'iron_law', timestamp: 1, result: 'pass' }), 'also invalid'].join('\n')
151
+ ['invalid json', JSON.stringify({ constraintId: 'valid', severity: 'error', timestamp: 1, result: 'pass' }), 'also invalid'].join('\n')
152
152
  );
153
153
 
154
154
  await runStatus();
@@ -34,7 +34,7 @@ const mockFs = fs as jest.Mocked<typeof fs>;
34
34
  /** trace 文件内容:一 trace 一行,缺省字段补齐成合法 ExecutionTrace(timestamp 递增) */
35
35
  function traceFile(traces: Array<Partial<ExecutionTrace>>): string {
36
36
  return traces
37
- .map((t, i) => JSON.stringify({ level: 'iron_law', timestamp: i + 1, result: 'pass', ...t }))
37
+ .map((t, i) => JSON.stringify({ severity: 'error', timestamp: i + 1, result: 'pass', ...t }))
38
38
  .join('\n');
39
39
  }
40
40
 
@@ -99,7 +99,7 @@ describe('status command', () => {
99
99
  it('应该显示记录数', async () => {
100
100
  mockFs.readFileSync.mockReturnValue(traceFile([
101
101
  { constraintId: 'test1' },
102
- { constraintId: 'test2', level: 'guideline' },
102
+ { constraintId: 'test2', severity: 'warning' },
103
103
  ]));
104
104
 
105
105
  await runStatus();
@@ -107,14 +107,14 @@ describe('status command', () => {
107
107
  expect(io.outText()).toContain('📈 约束统计:');
108
108
  });
109
109
 
110
- it('应该显示 Iron Laws 统计', async () => {
110
+ it('应该显示 error 级约束统计', async () => {
111
111
  mockFs.readFileSync.mockReturnValue(traceFile([
112
- { constraintId: 'no_bypass_checkpoint' },
112
+ { constraintId: 'no_completion_without_verification' },
113
113
  ]));
114
114
 
115
115
  await runStatus({ detail: true });
116
- expect(io.outText()).toContain('🔴 Iron Laws:');
117
- expect(io.outText()).toContain('✅ no_bypass_checkpoint');
116
+ expect(io.outText()).toContain('🔴 error 级约束:');
117
+ expect(io.outText()).toContain('✅ no_completion_without_verification');
118
118
  expect(io.outText()).toContain('检查: 1 | 通过: 100% | 失败: 0%');
119
119
  });
120
120
  });
@@ -162,14 +162,14 @@ describe('status command', () => {
162
162
  });
163
163
  });
164
164
 
165
- describe('Guidelines 统计', () => {
166
- it('应该显示 Guidelines 统计', async () => {
165
+ describe('warning 级约束统计', () => {
166
+ it('应该显示 warning 级约束统计', async () => {
167
167
  mockFs.readFileSync.mockReturnValue(traceFile([
168
- { constraintId: 'test_guide', level: 'guideline' },
168
+ { constraintId: 'test_guide', severity: 'warning' },
169
169
  ]));
170
170
 
171
171
  await runStatus();
172
- expect(io.outText()).toContain('🟡 Guidelines:');
172
+ expect(io.outText()).toContain('🟡 warning 级约束:');
173
173
  expect(io.outText()).toContain('✅ test_guide');
174
174
  });
175
175
  });
@@ -221,11 +221,11 @@ describe('status command', () => {
221
221
  });
222
222
 
223
223
  describe('详细模式扩展', () => {
224
- it('应该显示 Guidelines 详细统计', async () => {
224
+ it('应该显示 warning 级约束详细统计', async () => {
225
225
  mockFs.readFileSync.mockReturnValue(traceFile([
226
226
  ...repeats('test_guide', 3, 'pass'),
227
227
  ...repeats('test_guide', 2, 'fail'),
228
- ].map(t => ({ ...t, level: 'guideline' as const }))));
228
+ ].map(t => ({ ...t, severity: 'warning' as const }))));
229
229
 
230
230
  await runStatus({ detail: true });
231
231
  expect(io.outText()).toContain('⚠️ test_guide');
@@ -126,7 +126,7 @@ describe('sync-docs --agents', () => {
126
126
  expect(content).not.toContain('clean');
127
127
  // 约束与治理
128
128
  expect(content).toContain('preset: standard');
129
- expect(content).toContain('Iron Laws 2 条、Guidelines 3 条');
129
+ expect(content).toContain('约束清单:`CLAUDE.md` Governance Rules ');
130
130
  // 知识入口(只写目录存在性,不写易变的条目数——避免 --check 漂移竞态)
131
131
  expect(content).toContain('项目知识库,用 `harness knowledge` 查询');
132
132
  expect(content).not.toContain('知识库(');