@dommaker/harness 1.8.1 → 1.10.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 (299) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +10 -13
  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.js +2 -2
  20. package/dist/cli/commands/init.d.ts +0 -32
  21. package/dist/cli/commands/init.d.ts.map +1 -1
  22. package/dist/cli/commands/init.js +7 -149
  23. package/dist/cli/commands/init.js.map +1 -1
  24. package/dist/cli/commands/report.d.ts.map +1 -1
  25. package/dist/cli/commands/report.js +14 -17
  26. package/dist/cli/commands/report.js.map +1 -1
  27. package/dist/cli/commands/scaffold-templates.d.ts +0 -2
  28. package/dist/cli/commands/scaffold-templates.d.ts.map +1 -1
  29. package/dist/cli/commands/scaffold-templates.js +2 -37
  30. package/dist/cli/commands/scaffold-templates.js.map +1 -1
  31. package/dist/cli/commands/scaffold.d.ts +0 -2
  32. package/dist/cli/commands/scaffold.d.ts.map +1 -1
  33. package/dist/cli/commands/scaffold.js +0 -10
  34. package/dist/cli/commands/scaffold.js.map +1 -1
  35. package/dist/cli/commands/status.js +10 -10
  36. package/dist/cli/commands/status.js.map +1 -1
  37. package/dist/cli/commands/sync-docs/agents-syncer.d.ts +0 -2
  38. package/dist/cli/commands/sync-docs/agents-syncer.d.ts.map +1 -1
  39. package/dist/cli/commands/sync-docs/agents-syncer.js +4 -23
  40. package/dist/cli/commands/sync-docs/agents-syncer.js.map +1 -1
  41. package/dist/cli/commands/sync-docs/capabilities-syncer.d.ts +22 -0
  42. package/dist/cli/commands/sync-docs/capabilities-syncer.d.ts.map +1 -1
  43. package/dist/cli/commands/sync-docs/capabilities-syncer.js +113 -8
  44. package/dist/cli/commands/sync-docs/capabilities-syncer.js.map +1 -1
  45. package/dist/cli/commands/sync-docs/index.d.ts.map +1 -1
  46. package/dist/cli/commands/sync-docs/index.js +36 -4
  47. package/dist/cli/commands/sync-docs/index.js.map +1 -1
  48. package/dist/core/constraints/capabilities-parser.d.ts.map +1 -1
  49. package/dist/core/constraints/capabilities-parser.js +16 -4
  50. package/dist/core/constraints/capabilities-parser.js.map +1 -1
  51. package/dist/core/constraints/checker.d.ts +15 -24
  52. package/dist/core/constraints/checker.d.ts.map +1 -1
  53. package/dist/core/constraints/checker.js +33 -72
  54. package/dist/core/constraints/checker.js.map +1 -1
  55. package/dist/core/constraints/checkers/docs-freshness.js +1 -1
  56. package/dist/core/constraints/checkers/docs-freshness.js.map +1 -1
  57. package/dist/core/constraints/checkers/governance-presence.d.ts +2 -1
  58. package/dist/core/constraints/checkers/governance-presence.d.ts.map +1 -1
  59. package/dist/core/constraints/checkers/governance-presence.js +4 -3
  60. package/dist/core/constraints/checkers/governance-presence.js.map +1 -1
  61. package/dist/core/constraints/checkers/index.d.ts +1 -1
  62. package/dist/core/constraints/checkers/index.d.ts.map +1 -1
  63. package/dist/core/constraints/checkers/index.js +4 -8
  64. package/dist/core/constraints/checkers/index.js.map +1 -1
  65. package/dist/core/constraints/checkers/iron-flags.d.ts +3 -4
  66. package/dist/core/constraints/checkers/iron-flags.d.ts.map +1 -1
  67. package/dist/core/constraints/checkers/iron-flags.js +4 -5
  68. package/dist/core/constraints/checkers/iron-flags.js.map +1 -1
  69. package/dist/core/constraints/checkers/no-test-simplification.js +1 -1
  70. package/dist/core/constraints/checkers/no-test-simplification.js.map +1 -1
  71. package/dist/core/constraints/checkers/types.d.ts +1 -1
  72. package/dist/core/constraints/checkers/types.js +1 -1
  73. package/dist/core/constraints/definitions/guidelines.d.ts +4 -4
  74. package/dist/core/constraints/definitions/guidelines.d.ts.map +1 -1
  75. package/dist/core/constraints/definitions/guidelines.js +9 -25
  76. package/dist/core/constraints/definitions/guidelines.js.map +1 -1
  77. package/dist/core/constraints/definitions/iron-laws.d.ts +4 -4
  78. package/dist/core/constraints/definitions/iron-laws.d.ts.map +1 -1
  79. package/dist/core/constraints/definitions/iron-laws.js +10 -81
  80. package/dist/core/constraints/definitions/iron-laws.js.map +1 -1
  81. package/dist/core/constraints/definitions.d.ts +7 -9
  82. package/dist/core/constraints/definitions.d.ts.map +1 -1
  83. package/dist/core/constraints/definitions.js +13 -16
  84. package/dist/core/constraints/definitions.js.map +1 -1
  85. package/dist/core/constraints/index.d.ts +2 -5
  86. package/dist/core/constraints/index.d.ts.map +1 -1
  87. package/dist/core/constraints/index.js +3 -13
  88. package/dist/core/constraints/index.js.map +1 -1
  89. package/dist/core/constraints/injection-writer.d.ts +10 -38
  90. package/dist/core/constraints/injection-writer.d.ts.map +1 -1
  91. package/dist/core/constraints/injection-writer.js +17 -54
  92. package/dist/core/constraints/injection-writer.js.map +1 -1
  93. package/dist/core/constraints/run-env.d.ts +1 -10
  94. package/dist/core/constraints/run-env.d.ts.map +1 -1
  95. package/dist/core/constraints/run-env.js +1 -22
  96. package/dist/core/constraints/run-env.js.map +1 -1
  97. package/dist/core/constraints/usage-report.d.ts +5 -7
  98. package/dist/core/constraints/usage-report.d.ts.map +1 -1
  99. package/dist/core/constraints/usage-report.js +5 -10
  100. package/dist/core/constraints/usage-report.js.map +1 -1
  101. package/dist/core/effective-constraints.d.ts +12 -22
  102. package/dist/core/effective-constraints.d.ts.map +1 -1
  103. package/dist/core/effective-constraints.js +13 -30
  104. package/dist/core/effective-constraints.js.map +1 -1
  105. package/dist/core/index.d.ts +2 -2
  106. package/dist/core/index.d.ts.map +1 -1
  107. package/dist/core/index.js +3 -9
  108. package/dist/core/index.js.map +1 -1
  109. package/dist/core/project-config-loader.d.ts +4 -42
  110. package/dist/core/project-config-loader.d.ts.map +1 -1
  111. package/dist/core/project-config-loader.js +16 -125
  112. package/dist/core/project-config-loader.js.map +1 -1
  113. package/dist/core/validators/passes-gate.d.ts +2 -2
  114. package/dist/core/validators/passes-gate.js +6 -6
  115. package/dist/core/validators/passes-gate.js.map +1 -1
  116. package/dist/hooks/bootstrap.d.ts +9 -12
  117. package/dist/hooks/bootstrap.d.ts.map +1 -1
  118. package/dist/hooks/bootstrap.js +9 -31
  119. package/dist/hooks/bootstrap.js.map +1 -1
  120. package/dist/hooks/index.d.ts +5 -7
  121. package/dist/hooks/index.d.ts.map +1 -1
  122. package/dist/hooks/index.js +4 -10
  123. package/dist/hooks/index.js.map +1 -1
  124. package/dist/index.d.ts +9 -12
  125. package/dist/index.d.ts.map +1 -1
  126. package/dist/index.js +10 -23
  127. package/dist/index.js.map +1 -1
  128. package/dist/monitoring/trace-analyzer.d.ts.map +1 -1
  129. package/dist/monitoring/trace-analyzer.js +11 -12
  130. package/dist/monitoring/trace-analyzer.js.map +1 -1
  131. package/dist/monitoring/traces.d.ts +4 -4
  132. package/dist/monitoring/traces.d.ts.map +1 -1
  133. package/dist/monitoring/traces.js +8 -8
  134. package/dist/monitoring/traces.js.map +1 -1
  135. package/dist/presets/standard.d.ts +8 -10
  136. package/dist/presets/standard.d.ts.map +1 -1
  137. package/dist/presets/standard.js +10 -16
  138. package/dist/presets/standard.js.map +1 -1
  139. package/dist/types/constraint.d.ts +24 -35
  140. package/dist/types/constraint.d.ts.map +1 -1
  141. package/dist/types/constraint.js +8 -7
  142. package/dist/types/constraint.js.map +1 -1
  143. package/dist/types/passes-gate.d.ts +5 -5
  144. package/dist/types/passes-gate.d.ts.map +1 -1
  145. package/dist/types/project-config.d.ts +8 -66
  146. package/dist/types/project-config.d.ts.map +1 -1
  147. package/dist/types/project-config.js +3 -2
  148. package/dist/types/project-config.js.map +1 -1
  149. package/dist/types/trace.d.ts +8 -10
  150. package/dist/types/trace.d.ts.map +1 -1
  151. package/package.json +2 -2
  152. package/src/CONTEXT.md +3 -3
  153. package/src/__tests__/checker-extra.test.ts +37 -61
  154. package/src/__tests__/checker.test.ts +10 -115
  155. package/src/__tests__/effective-constraints.test.ts +18 -83
  156. package/src/__tests__/iron-laws.test.ts +71 -90
  157. package/src/__tests__/passes-gate-check.test.ts +2 -2
  158. package/src/__tests__/project-config-loader-extra.test.ts +22 -123
  159. package/src/__tests__/project-config-loader.test.ts +5 -33
  160. package/src/__tests__/public-exports.test.ts +31 -11
  161. package/src/__tests__/public-type-surface.test.ts +2 -13
  162. package/src/__tests__/public-value-surface.test.ts +1 -7
  163. package/src/__tests__/skip-semantics.test.ts +21 -37
  164. package/src/__tests__/trace-analyzer-extra.test.ts +14 -14
  165. package/src/__tests__/trace-analyzer.test.ts +21 -21
  166. package/src/__tests__/trace-collector.test.ts +22 -22
  167. package/src/__tests__/traces.test.ts +27 -28
  168. package/src/cli/commands/CONTEXT.md +12 -9
  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.test.ts +12 -80
  173. package/src/cli/commands/__tests__/constraints-retire.test.ts +42 -231
  174. package/src/cli/commands/__tests__/init-governance-io.test.ts +12 -58
  175. package/src/cli/commands/__tests__/init-ondisk.test.ts +12 -20
  176. package/src/cli/commands/__tests__/init.test.ts +0 -11
  177. package/src/cli/commands/__tests__/project-path-anchoring.test.ts +2 -2
  178. package/src/cli/commands/__tests__/registry.test.ts +39 -3
  179. package/src/cli/commands/__tests__/report-extra.test.ts +4 -4
  180. package/src/cli/commands/__tests__/report.test.ts +1 -1
  181. package/src/cli/commands/__tests__/scaffold.test.ts +4 -14
  182. package/src/cli/commands/__tests__/status-analysis-wiring.test.ts +3 -3
  183. package/src/cli/commands/__tests__/status-extra.test.ts +14 -14
  184. package/src/cli/commands/__tests__/status.test.ts +12 -12
  185. package/src/cli/commands/__tests__/sync-docs-agents.test.ts +1 -1
  186. package/src/cli/commands/__tests__/sync-docs-table-layout.test.ts +259 -0
  187. package/src/cli/commands/check.ts +43 -82
  188. package/src/cli/commands/constraints-report.ts +4 -59
  189. package/src/cli/commands/constraints-retire.ts +49 -154
  190. package/src/cli/commands/constraints.ts +11 -26
  191. package/src/cli/commands/definitions.ts +2 -2
  192. package/src/cli/commands/init.ts +8 -179
  193. package/src/cli/commands/report.ts +19 -23
  194. package/src/cli/commands/scaffold-templates.ts +1 -37
  195. package/src/cli/commands/scaffold.ts +0 -11
  196. package/src/cli/commands/status.ts +10 -10
  197. package/src/cli/commands/sync-docs/agents-syncer.ts +4 -25
  198. package/src/cli/commands/sync-docs/capabilities-syncer.ts +139 -9
  199. package/src/cli/commands/sync-docs/index.ts +41 -4
  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 +8 -15
  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/CONTEXT.md +12 -22
  231. package/src/hooks/__tests__/bootstrap.test.ts +24 -75
  232. package/src/hooks/bootstrap.ts +9 -48
  233. package/src/hooks/index.ts +5 -20
  234. package/src/index.ts +9 -31
  235. package/src/monitoring/__tests__/trace-file-anchoring.test.ts +1 -1
  236. package/src/monitoring/__tests__/traces.test.ts +22 -22
  237. package/src/monitoring/trace-analyzer.ts +12 -13
  238. package/src/monitoring/traces.ts +8 -8
  239. package/src/presets/__tests__/standard.test.ts +12 -16
  240. package/src/presets/standard.ts +14 -23
  241. package/src/types/__tests__/types.test.ts +3 -3
  242. package/src/types/constraint.ts +26 -40
  243. package/src/types/passes-gate.ts +5 -5
  244. package/src/types/project-config.ts +8 -77
  245. package/src/types/trace.ts +8 -11
  246. package/dist/core/constraints/agent-prompt-renderer.d.ts +0 -32
  247. package/dist/core/constraints/agent-prompt-renderer.d.ts.map +0 -1
  248. package/dist/core/constraints/agent-prompt-renderer.js +0 -55
  249. package/dist/core/constraints/agent-prompt-renderer.js.map +0 -1
  250. package/dist/core/constraints/checkers/no-bypass-checkpoint.d.ts +0 -6
  251. package/dist/core/constraints/checkers/no-bypass-checkpoint.d.ts.map +0 -1
  252. package/dist/core/constraints/checkers/no-bypass-checkpoint.js +0 -40
  253. package/dist/core/constraints/checkers/no-bypass-checkpoint.js.map +0 -1
  254. package/dist/core/constraints/definitions/prompts.d.ts +0 -12
  255. package/dist/core/constraints/definitions/prompts.d.ts.map +0 -1
  256. package/dist/core/constraints/definitions/prompts.js +0 -400
  257. package/dist/core/constraints/definitions/prompts.js.map +0 -1
  258. package/dist/core/constraints/injection-drift.d.ts +0 -61
  259. package/dist/core/constraints/injection-drift.d.ts.map +0 -1
  260. package/dist/core/constraints/injection-drift.js +0 -131
  261. package/dist/core/constraints/injection-drift.js.map +0 -1
  262. package/dist/core/constraints/injection-renderer.d.ts +0 -23
  263. package/dist/core/constraints/injection-renderer.d.ts.map +0 -1
  264. package/dist/core/constraints/injection-renderer.js +0 -44
  265. package/dist/core/constraints/injection-renderer.js.map +0 -1
  266. package/dist/hooks/config.d.ts +0 -30
  267. package/dist/hooks/config.d.ts.map +0 -1
  268. package/dist/hooks/config.js +0 -34
  269. package/dist/hooks/config.js.map +0 -1
  270. package/dist/hooks/pipeline.d.ts +0 -54
  271. package/dist/hooks/pipeline.d.ts.map +0 -1
  272. package/dist/hooks/pipeline.js +0 -173
  273. package/dist/hooks/pipeline.js.map +0 -1
  274. package/dist/hooks/registry.d.ts +0 -70
  275. package/dist/hooks/registry.d.ts.map +0 -1
  276. package/dist/hooks/registry.js +0 -141
  277. package/dist/hooks/registry.js.map +0 -1
  278. package/dist/hooks/types.d.ts +0 -113
  279. package/dist/hooks/types.d.ts.map +0 -1
  280. package/dist/hooks/types.js +0 -9
  281. package/dist/hooks/types.js.map +0 -1
  282. package/src/__tests__/hooks-pipeline.test.ts +0 -201
  283. package/src/cli/commands/__tests__/check-drift.test.ts +0 -158
  284. package/src/cli/commands/__tests__/init-injection.test.ts +0 -466
  285. package/src/core/constraints/__tests__/agent-prompt-renderer.test.ts +0 -129
  286. package/src/core/constraints/__tests__/injection-drift.test.ts +0 -247
  287. package/src/core/constraints/agent-prompt-renderer.ts +0 -67
  288. package/src/core/constraints/checkers/__tests__/no-bypass-checkpoint.test.ts +0 -76
  289. package/src/core/constraints/checkers/no-bypass-checkpoint.ts +0 -40
  290. package/src/core/constraints/definitions/prompts.ts +0 -414
  291. package/src/core/constraints/injection-drift.ts +0 -142
  292. package/src/core/constraints/injection-renderer.ts +0 -44
  293. package/src/hooks/__tests__/config.test.ts +0 -19
  294. package/src/hooks/__tests__/pipeline.test.ts +0 -195
  295. package/src/hooks/__tests__/registry.test.ts +0 -115
  296. package/src/hooks/config.ts +0 -33
  297. package/src/hooks/pipeline.ts +0 -202
  298. package/src/hooks/registry.ts +0 -166
  299. package/src/hooks/types.ts +0 -120
@@ -10,21 +10,9 @@ import * as path from 'path';
10
10
  import * as yaml from 'js-yaml';
11
11
  import { detectSourceRoots } from '../../utils/detect-source-roots';
12
12
  import { getHarnessPackageVersion } from '../../utils/package-version';
13
- import { getEffectiveConstraints } from '../../core/effective-constraints';
14
13
  import { loadRawProjectConfig } from '../../core/project-config-loader';
15
14
  import type { CiConfig, CiPlatform, GovernanceConfig } from '../../types/project-config';
16
- import {
17
- CONSTRAINTS_START_MARKER,
18
- CONSTRAINTS_END_MARKER,
19
- renderConstraintsSection,
20
- } from '../../core/constraints/injection-renderer';
21
- import {
22
- replaceStandaloneRange,
23
- replaceEnclosedRange,
24
- cutMarkerBlock,
25
- resolveGovernanceLanding,
26
- GOVERNANCE_HEADING,
27
- } from '../../core/constraints/injection-writer';
15
+ import { replaceStandaloneRange } from '../../core/constraints/injection-writer';
28
16
  import { log, logError, processIO, type CommandIO, type CommandResult } from '../command-contract';
29
17
  import {
30
18
  runPlan,
@@ -32,7 +20,6 @@ import {
32
20
  preCommitHookFile,
33
21
  prePushHookFile,
34
22
  harnessCheckCiFile,
35
- customConstraintsFile,
36
23
  changelogFile,
37
24
  contextDocFile,
38
25
  governanceWorkflowFile,
@@ -294,9 +281,9 @@ export async function init(options: InitOptions, io: CommandIO = processIO): Pro
294
281
  await fs.writeFile(configPath, configContent, 'utf-8');
295
282
  log(io, chalk.green(`✅ 已创建配置文件: ${configPath} (v${pkgVersion})`));
296
283
 
297
- // 受管示例文件:检查点 / Resolutions(RKB 狗粮)/ 自定义约束
284
+ // 受管示例文件:检查点 / Resolutions(RKB 狗粮)
298
285
  await runPlan(
299
- [checkpointsFile(projectPath), resolutionsFile(projectPath), customConstraintsFile(projectPath)],
286
+ [checkpointsFile(projectPath), resolutionsFile(projectPath)],
300
287
  io,
301
288
  );
302
289
 
@@ -322,9 +309,8 @@ export async function init(options: InitOptions, io: CommandIO = processIO): Pro
322
309
  log(io);
323
310
  log(io, chalk.gray('下一步:'));
324
311
  log(io, chalk.gray(' 1. 编辑 .harness/config.yml 自定义配置'));
325
- log(io, chalk.gray(' 2. 编辑 .harness/custom-constraints.yml 添加项目约束'));
326
- log(io, chalk.gray(' 3. 正常开发:每次 git commit 查暂存的(增量快反馈),每次 git push 查整仓的(全量兜底)——重复是设计使然'));
327
- log(io, chalk.gray(' 4. 运行 harness status 查看状态'));
312
+ log(io, chalk.gray(' 2. 正常开发:每次 git commit 查暂存的(增量快反馈),每次 git push 查整仓的(全量兜底)——重复是设计使然'));
313
+ log(io, chalk.gray(' 3. 运行 harness status 查看状态'));
328
314
  log(io);
329
315
  log(io, chalk.blue('💡 提示: 使用 harness init --print-snippets 查看配置代码片段'));
330
316
  return { kind: 'ok' };
@@ -463,7 +449,7 @@ export async function setupClaudeMdOutputStyle(projectPath: string, io: CommandI
463
449
  try {
464
450
  content = await fs.readFile(claudeMdPath, 'utf-8');
465
451
  } catch {
466
- // CLAUDE.md 不存在——setupClaudeMdConstraints 会创建它
452
+ // CLAUDE.md 不存在——无人持有该文件,跳过 Output Style 段
467
453
  return;
468
454
  }
469
455
 
@@ -512,159 +498,6 @@ export async function setupClaudeMdOutputStyle(projectPath: string, io: CommandI
512
498
  log(io, chalk.green('✅ 已在 CLAUDE.md 顶部写入 Output Style 段'));
513
499
  }
514
500
 
515
- /**
516
- * 治理契约 PRESERVE 段标记(studio #302,ADR 2026-08-21 落点模型:
517
- * 治理契约正本住 AGENTS.md 手写 PRESERVE 段,sync-docs 重新生成时原样保留)
518
- */
519
- const GOVERNANCE_PRESERVE_BEGIN = '<!-- PRESERVE:governance -->';
520
- const GOVERNANCE_PRESERVE_END = '<!-- /PRESERVE:governance -->';
521
-
522
- /**
523
- * 在 AGENTS.md 的 PRESERVE:governance 段写入/更新 Governance Rules 约束段(新落点模型)
524
- *
525
- * - AGENTS.md 不存在:创建最小骨架(标题 + 说明 + PRESERVE:governance 段),
526
- * 完整导读由 `harness sync-docs --agents` 生成,PRESERVE 段在重新生成时原样保留
527
- * - 已有 PRESERVE:governance 段:段内机器管理的只有 HARNESS_CONSTRAINTS 标记区间——
528
- * 有标记则只替换标记区间,段内其余手写内容(治理契约引言/流程/纪律等)原样保留;
529
- * 无标记(纯手写段)则在段尾追加注入段,不动手写内容
530
- * - 无该段:在文件末尾追加
531
- * - 段标记残缺(外层或段内 HARNESS_CONSTRAINTS 单边/乱序):不写入,告警交由人工修复(防二次损坏)
532
- */
533
- export async function setupAgentsMdConstraints(projectPath: string, io: CommandIO): Promise<void> {
534
- const agentsMdPath = path.join(projectPath, 'AGENTS.md');
535
- const version = getHarnessPackageVersion();
536
-
537
- const constraints = getEffectiveConstraints(projectPath);
538
- const bodyOnly = renderConstraintsSection(constraints, version);
539
- const block = `${GOVERNANCE_PRESERVE_BEGIN}\n${GOVERNANCE_HEADING}\n${bodyOnly}${GOVERNANCE_PRESERVE_END}\n`;
540
-
541
- let existingContent: string | null = null;
542
- try {
543
- existingContent = await fs.readFile(agentsMdPath, 'utf-8');
544
- } catch {
545
- // AGENTS.md 不存在
546
- }
547
-
548
- if (existingContent === null) {
549
- const skeleton = [
550
- '# AGENTS.md',
551
- '',
552
- '> 机器生成部分由 `harness sync-docs --agents` 维护;`PRESERVE:governance` 段是治理契约正本(手写/治理变更流程管控),重新生成时原样保留。',
553
- '',
554
- block,
555
- ].join('\n');
556
- await fs.writeFile(agentsMdPath, skeleton, 'utf-8');
557
- log(io, chalk.green(`✅ 已创建 AGENTS.md 并写入治理契约 PRESERVE:governance 段 (v${version})`));
558
- return;
559
- }
560
-
561
- const preserve = cutMarkerBlock(existingContent, GOVERNANCE_PRESERVE_BEGIN, GOVERNANCE_PRESERVE_END);
562
-
563
- if (preserve === 'half') {
564
- log(io, chalk.yellow('⚠️ AGENTS.md 中 PRESERVE:governance 标记残缺(只有单边),跳过治理契约写入,请人工修复'));
565
- return;
566
- }
567
-
568
- if (preserve !== 'absent') {
569
- // 段内机器管理的只有 HARNESS_CONSTRAINTS 标记区间;其余手写内容原样保留
570
- const inner = replaceEnclosedRange(preserve.inner, CONSTRAINTS_START_MARKER, CONSTRAINTS_END_MARKER, bodyOnly);
571
- if (inner.kind === 'half') {
572
- log(io, chalk.yellow('⚠️ AGENTS.md PRESERVE:governance 段内 HARNESS_CONSTRAINTS 标记残缺(单边或乱序),跳过治理契约写入,请人工修复'));
573
- return;
574
- }
575
- const newInner =
576
- inner.kind === 'updated'
577
- ? inner.content
578
- : // 纯手写段(无约束标记):段尾追加注入段,手写内容不动
579
- preserve.inner.trimEnd() + '\n\n' + GOVERNANCE_HEADING + '\n' + bodyOnly;
580
-
581
- const write = replaceStandaloneRange(
582
- existingContent,
583
- GOVERNANCE_PRESERVE_BEGIN,
584
- GOVERNANCE_PRESERVE_END,
585
- GOVERNANCE_PRESERVE_BEGIN + newInner + GOVERNANCE_PRESERVE_END + '\n'
586
- );
587
- if (write.kind === 'updated' && write.content !== existingContent) {
588
- await fs.writeFile(agentsMdPath, write.content, 'utf-8');
589
- log(io, chalk.green(`✅ 已更新 AGENTS.md 治理契约 PRESERVE:governance 段 (v${version})`));
590
- }
591
- return;
592
- }
593
-
594
- // 无该段:文件末尾追加
595
- const newContent = existingContent.trimEnd() + '\n\n' + block;
596
- await fs.writeFile(agentsMdPath, newContent, 'utf-8');
597
- log(io, chalk.green(`✅ 已追加治理契约 PRESERVE:governance 段到 AGENTS.md (v${version})`));
598
- }
599
-
600
- /**
601
- * 在 CLAUDE.md 中写入/更新 Governance Rules 约束段(旧落点模型,向后兼容保留)
602
- *
603
- * - 约束集来自 getEffectiveConstraints(ADR-0001):preset 裁剪、config.yml
604
- * 禁用、custom 追加、scenes 过滤全部反映在注入文本里
605
- * - 期望段文本由纯函数 renderConstraintsSection 渲染(P6 漂移校验复用)
606
- * - 如果 CLAUDE.md 不存在,创建并写入完整约束段
607
- * - 如果存在 HARNESS_CONSTRAINTS_START/END 标记,替换标记间内容
608
- * - 如果不存在标记,在文件末尾追加约束段
609
- */
610
- export async function setupClaudeMdConstraints(projectPath: string, io: CommandIO): Promise<void> {
611
- const claudeMdPath = path.join(projectPath, 'CLAUDE.md');
612
-
613
- const version = getHarnessPackageVersion();
614
-
615
- // 生效约束集 → 渲染期望段(纯函数,与写文件分离)
616
- const constraints = getEffectiveConstraints(projectPath);
617
- const bodyOnly = renderConstraintsSection(constraints, version);
618
- const fullSection = GOVERNANCE_HEADING + '\n' + bodyOnly;
619
-
620
- // 检查 CLAUDE.md 是否存在
621
- let existingContent: string;
622
- let fileExists = false;
623
- try {
624
- existingContent = await fs.readFile(claudeMdPath, 'utf-8');
625
- fileExists = true;
626
- } catch {
627
- existingContent = '';
628
- }
629
-
630
- if (!fileExists) {
631
- // 创建新文件
632
- await fs.writeFile(claudeMdPath, fullSection, 'utf-8');
633
- log(io, chalk.green(`✅ 已创建 CLAUDE.md 并写入治理约束 (v${version})`));
634
- return;
635
- }
636
-
637
- const write = replaceStandaloneRange(existingContent, CONSTRAINTS_START_MARKER, CONSTRAINTS_END_MARKER, bodyOnly);
638
-
639
- if (write.kind === 'updated') {
640
- // 替换标记区间含标记本身(保持包括最新版本号),尾部换行规范化在 writer 内
641
- await fs.writeFile(claudeMdPath, write.content, 'utf-8');
642
- log(io, chalk.green(`✅ 已更新 CLAUDE.md 治理约束 (v${version})`));
643
- } else if (write.kind === 'half') {
644
- log(io, chalk.yellow('⚠️ CLAUDE.md 中 HARNESS_CONSTRAINTS 标记残缺(单边或乱序),跳过治理约束注入,请人工修复'));
645
- } else {
646
- // 在文件末尾追加完整段
647
- const newContent = existingContent.trimEnd() + '\n\n' + fullSection;
648
- await fs.writeFile(claudeMdPath, newContent, 'utf-8');
649
- log(io, chalk.green(`✅ 已追加治理约束到 CLAUDE.md (v${version})`));
650
- }
651
- }
652
-
653
- /**
654
- * 治理约束段写入落点路由(studio #302,ADR 2026-08-21 落点模型)
655
- *
656
- * 判定收口在 core/constraints/injection-writer resolveGovernanceLanding:
657
- * - 旧模型仓(CLAUDE.md 已有 HARNESS_CONSTRAINTS 标记或 `## Governance Rules` 块):
658
- * 继续写 CLAUDE.md——init 幂等重跑不破坏既有仓,不制造双份约束正本
659
- * - 其余(新仓初始化):写 AGENTS.md PRESERVE:governance 段(入库公共面正本)
660
- */
661
- export async function setupGovernanceConstraints(projectPath: string, io: CommandIO): Promise<void> {
662
- const { target } = resolveGovernanceLanding(projectPath);
663
- return target === 'claude-md'
664
- ? setupClaudeMdConstraints(projectPath, io)
665
- : setupAgentsMdConstraints(projectPath, io);
666
- }
667
-
668
501
  /**
669
502
  * 设置治理相关文件
670
503
  */
@@ -686,14 +519,10 @@ async function setupGovernance(
686
519
  // 2. 在 CLAUDE.md 中写入 Output Style 段(仅在不存在时创建)
687
520
  await setupClaudeMdOutputStyle(projectPath, io);
688
521
 
689
- // 3. 写入/更新 Governance Rules 约束段(新仓 → AGENTS.md PRESERVE:governance;
690
- // 旧模型仓 → CLAUDE.md,落点路由见 setupGovernanceConstraints)
691
- await setupGovernanceConstraints(projectPath, io);
692
-
693
- // 4. 生成 CONTEXT.md 文件(预设形状即 GovernanceConfig,无需再 cast)
522
+ // 3. 生成 CONTEXT.md 文件(预设形状即 GovernanceConfig,无需再 cast)
694
523
  await runPlan(await contextDocPlan(projectPath, governance, io), io);
695
524
 
696
- // 5. 生成治理 CI 面(仅 github 形;gitlab 已并入 .gitlab-ci.yml 正文,none 不建,harness#156)
525
+ // 4. 生成治理 CI 面(仅 github 形;gitlab 已并入 .gitlab-ci.yml 正文,none 不建,harness#156)
697
526
  await setupGovernanceWorkflow(projectPath, level, io, platform);
698
527
  }
699
528
 
@@ -7,7 +7,7 @@
7
7
  import chalk from 'chalk';
8
8
  import * as fs from 'fs/promises';
9
9
  import { ConstraintChecker } from '../../core/constraints/checker';
10
- import { IRON_LAWS, GUIDELINES, PROMPTS } from '../../core/constraints/definitions';
10
+ import { CONSTRAINTS } from '../../core/constraints/definitions';
11
11
  import { TraceCollector } from '../../monitoring/traces';
12
12
  import type { ConstraintContext } from '../../types/constraint';
13
13
  import { log, processIO, type CommandIO, type CommandResult } from '../command-contract';
@@ -26,15 +26,14 @@ interface ReportData {
26
26
  projectPath: string;
27
27
  constraints: {
28
28
  total: number;
29
- ironLaws: number;
30
- guidelines: number;
31
- prompts: number;
29
+ errors: number;
30
+ warnings: number;
32
31
  passed: number;
33
32
  failed: number;
34
- warnings: number;
33
+ warningViolations: number;
35
34
  violations: Array<{
36
35
  id: string;
37
- level: string;
36
+ severity: string;
38
37
  message: string;
39
38
  }>;
40
39
  };
@@ -51,23 +50,22 @@ export async function report(options: ReportOptions, io: CommandIO = processIO):
51
50
  // #139:收集器锚根构造——不传 projectPath 时 trace 会落进调用方 cwd,B 侧读不到
52
51
  const checker = new ConstraintChecker(new TraceCollector({ projectPath }));
53
52
 
54
- const allConstraints = { ...IRON_LAWS, ...GUIDELINES, ...PROMPTS };
55
- const totalConstraints = Object.keys(allConstraints).length;
53
+ const totalConstraints = Object.keys(CONSTRAINTS).length;
56
54
 
57
55
  const context: ConstraintContext = {
58
56
  operation: 'file_modification',
59
57
  projectPath,
60
58
  };
61
59
 
62
- // 收集模式(架构评审候选1):不抛、全量收集,铁律违规如实进报告
60
+ // 收集模式(架构评审候选1):不抛、全量收集,error 级违规如实进报告
63
61
  const result = await checker.collectConstraints(context);
64
62
 
65
- const failedIronLaws = result.ironLaws.filter(r => !r.satisfied);
66
- const failedGuidelines = result.guidelines.filter(r => !r.satisfied);
63
+ const failedErrors = result.errors.filter(r => !r.satisfied);
64
+ const failedWarnings = result.warnings.filter(r => !r.satisfied);
67
65
 
68
- const violations = [...failedIronLaws, ...failedGuidelines].map(r => ({
66
+ const violations = [...failedErrors, ...failedWarnings].map(r => ({
69
67
  id: r.id,
70
- level: r.level,
68
+ severity: r.severity,
71
69
  message: r.message || '',
72
70
  }));
73
71
 
@@ -76,12 +74,11 @@ export async function report(options: ReportOptions, io: CommandIO = processIO):
76
74
  projectPath,
77
75
  constraints: {
78
76
  total: totalConstraints,
79
- ironLaws: Object.keys(IRON_LAWS).length,
80
- guidelines: Object.keys(GUIDELINES).length,
81
- prompts: Object.keys(PROMPTS).length,
77
+ errors: Object.values(CONSTRAINTS).filter(c => c.severity === 'error').length,
78
+ warnings: Object.values(CONSTRAINTS).filter(c => c.severity === 'warning').length,
82
79
  passed: result.passed ? totalConstraints : totalConstraints - violations.length,
83
- failed: failedIronLaws.length,
84
- warnings: failedGuidelines.length,
80
+ failed: failedErrors.length,
81
+ warningViolations: failedWarnings.length,
85
82
  violations,
86
83
  },
87
84
  };
@@ -122,19 +119,18 @@ function generateMarkdownReport(data: ReportData): string {
122
119
  `| 指标 | 数值 |`,
123
120
  `|------|------|`,
124
121
  `| 总约束 | ${data.constraints.total} |`,
125
- `| Iron Laws | ${data.constraints.ironLaws} |`,
126
- `| Guidelines | ${data.constraints.guidelines} |`,
127
- `| Prompts | ${data.constraints.prompts} |`,
122
+ `| error | ${data.constraints.errors} |`,
123
+ `| warning | ${data.constraints.warnings} |`,
128
124
  `| 通过 | ${data.constraints.passed} |`,
129
125
  `| 失败 (error) | ${data.constraints.failed} |`,
130
- `| 警告 (warning) | ${data.constraints.warnings} |`,
126
+ `| 警告 (warning) | ${data.constraints.warningViolations} |`,
131
127
  ``,
132
128
  ];
133
129
 
134
130
  if (data.constraints.violations.length > 0) {
135
131
  lines.push(`### 违规项`, ``);
136
132
  data.constraints.violations.forEach(v => {
137
- lines.push(`- **${v.id}** (${v.level}): ${v.message}`);
133
+ lines.push(`- **${v.id}** (${v.severity}): ${v.message}`);
138
134
  });
139
135
  lines.push(``);
140
136
  }
@@ -249,42 +249,6 @@ ${docsCheckStep}
249
249
  `;
250
250
  }
251
251
 
252
- /** custom-constraints.yml 示例正文 */
253
- export const CUSTOM_CONSTRAINTS_TEMPLATE = `# 自定义约束配置
254
- #
255
- # 此文件定义项目特定的约束,扩展或覆盖 harness 内置约束
256
-
257
- # ========================================
258
- # 自定义约束示例
259
- # ========================================
260
-
261
- custom_constraints:
262
- # 示例 1:禁止 console.log
263
- # my_project_no_console_log:
264
- # id: my_project_no_console_log
265
- # level: guideline
266
- # rule: "NO CONSOLE.LOG IN PRODUCTION CODE"
267
- # message: "生产代码禁止使用 console.log,请使用 logger 模块"
268
- # trigger: ["code_implementation"]
269
- # description: "使用项目统一的 logger 模块代替 console.log"
270
-
271
- # 示例 2:禁止特定的导入
272
- # my_project_no_moment_js:
273
- # id: my_project_no_moment_js
274
- # level: guideline
275
- # rule: "NO MOMENT.JS IMPORTS"
276
- # message: "禁止使用 moment.js,请使用 date-fns 或 dayjs"
277
- # trigger: ["code_implementation"]
278
-
279
- # 示例 3:要求特定的文件命名
280
- # my_project_component_naming:
281
- # id: my_project_component_naming
282
- # level: tip
283
- # rule: "REACT COMPONENTS SHOULD BE PASCAL CASE"
284
- # message: "React 组件文件名应使用 PascalCase"
285
- # trigger: ["file_creation"]
286
- `;
287
-
288
252
  /** CHANGELOG.md 正文(`format` 来自治理配置的 changelog.format) */
289
253
  export function renderChangelog(format: string): string {
290
254
  return format === 'keep-a-changelog'
@@ -386,7 +350,7 @@ export function renderCheckpoints(): string {
386
350
 
387
351
  /** 默认 Resolutions(RKB — 约束 → 已知解法映射) */
388
352
  const DEFAULT_RESOLUTIONS = {
389
- no_fuzzy_completion_claim: {
353
+ no_completion_without_verification: {
390
354
  title: 'commit message 缺少验证证据',
391
355
  fix: '在 commit message body 中附上验证输出:\n`npx @dommaker/harness check --staged` | `npx @dommaker/harness validate` | `npm test -- --coverage`\n确认全部通过后重新 commit。',
392
356
  },
@@ -20,7 +20,6 @@ import * as nodeFs from 'fs/promises';
20
20
  import type { CiPlatform } from '../../types/project-config';
21
21
  import { log, type CommandIO } from '../command-contract';
22
22
  import {
23
- CUSTOM_CONSTRAINTS_TEMPLATE,
24
23
  DEFAULT_CHECKPOINT_FILE,
25
24
  HARNESS_CHECK_WORKFLOW,
26
25
  PRE_COMMIT_SNIPPET,
@@ -235,16 +234,6 @@ export function harnessCheckCiFile(
235
234
  };
236
235
  }
237
236
 
238
- /** .harness/custom-constraints.yml 示例 */
239
- export function customConstraintsFile(projectPath: string): ManagedFile {
240
- return {
241
- target: path.join(projectPath, '.harness', 'custom-constraints.yml'),
242
- content: CUSTOM_CONSTRAINTS_TEMPLATE,
243
- created: '✅ 已创建自定义约束示例: custom-constraints.yml',
244
- onPresent: { outcome: 'skip', notice: 'custom-constraints.yml 已存在' },
245
- };
246
- }
247
-
248
237
  /** .harness/checkpoints.yml 示例(原住 validate.ts,路径约定与 validate 共用) */
249
238
  export function checkpointsFile(projectPath: string): ManagedFile {
250
239
  const target = path.join(projectPath, DEFAULT_CHECKPOINT_FILE);
@@ -109,11 +109,11 @@ export async function status(options: StatusOptions, io: CommandIO = processIO):
109
109
  log(io, chalk.blue('📈 约束统计:'));
110
110
  log(io);
111
111
 
112
- // Iron Laws
113
- const ironLawSummaries = summaries.filter((s: TraceSummary) => s.level === 'iron_law');
114
- if (ironLawSummaries.length > 0) {
115
- log(io, chalk.red('🔴 Iron Laws:'));
116
- ironLawSummaries.forEach((s: TraceSummary) => {
112
+ // severity='error'
113
+ const errorSummaries = summaries.filter((s: TraceSummary) => s.severity === 'error');
114
+ if (errorSummaries.length > 0) {
115
+ log(io, chalk.red('🔴 error 级约束:'));
116
+ errorSummaries.forEach((s: TraceSummary) => {
117
117
  const status = s.passRate >= 1 ? '✅' : '❌';
118
118
  log(io, ` ${status} ${s.constraintId}`);
119
119
  if (options.detail) {
@@ -123,11 +123,11 @@ export async function status(options: StatusOptions, io: CommandIO = processIO):
123
123
  log(io);
124
124
  }
125
125
 
126
- // Guidelines
127
- const guidelineSummaries = summaries.filter((s: TraceSummary) => s.level === 'guideline');
128
- if (guidelineSummaries.length > 0) {
129
- log(io, chalk.yellow('🟡 Guidelines:'));
130
- guidelineSummaries.forEach((s: TraceSummary) => {
126
+ // severity='warning'
127
+ const warningSummaries = summaries.filter((s: TraceSummary) => s.severity === 'warning');
128
+ if (warningSummaries.length > 0) {
129
+ log(io, chalk.yellow('🟡 warning 级约束:'));
130
+ warningSummaries.forEach((s: TraceSummary) => {
131
131
  const status = s.passRate >= 0.8 ? '✅' : s.passRate >= 0.5 ? '⚠️' : '❌';
132
132
  log(io, ` ${status} ${s.constraintId}`);
133
133
  if (options.detail) {
@@ -49,8 +49,6 @@ export interface GovernanceInfo {
49
49
  hasConfig: boolean;
50
50
  preset?: string;
51
51
  hasClaudeGovernance: boolean;
52
- ironLaws?: number;
53
- guidelines?: number;
54
52
  }
55
53
 
56
54
  /**
@@ -114,11 +112,7 @@ export async function buildAgentsMd(projectPath: string, srcDirs: string[]): Pro
114
112
  lines.push(`- 治理配置:\`.harness/config.yml\`${governance.preset ? `(preset: ${governance.preset})` : ''}`);
115
113
  }
116
114
  if (governance.hasClaudeGovernance) {
117
- const counts = [
118
- governance.ironLaws !== undefined ? `Iron Laws ${governance.ironLaws} 条` : null,
119
- governance.guidelines !== undefined ? `Guidelines ${governance.guidelines} 条` : null,
120
- ].filter(Boolean).join('、');
121
- lines.push(`- 约束清单:\`CLAUDE.md\` Governance Rules 块${counts ? `(${counts})` : ''}`);
115
+ lines.push('- 约束清单:`CLAUDE.md` Governance Rules 块');
122
116
  }
123
117
  if (!governance.hasConfig && !governance.hasClaudeGovernance) {
124
118
  lines.push('- 未检测到 harness 治理配置,可运行 `harness init` 初始化');
@@ -208,7 +202,7 @@ async function listWorkspaceMembers(dir: string): Promise<string[]> {
208
202
  }
209
203
  }
210
204
 
211
- /** 收集治理信息:.harness/config.yml 与 CLAUDE.md 治理块(含铁律/指南计数) */
205
+ /** 收集治理信息:.harness/config.yml 与 CLAUDE.md 治理块 */
212
206
  async function getGovernanceInfo(projectPath: string): Promise<GovernanceInfo> {
213
207
  const info: GovernanceInfo = { hasConfig: false, hasClaudeGovernance: false };
214
208
 
@@ -224,12 +218,8 @@ async function getGovernanceInfo(projectPath: string): Promise<GovernanceInfo> {
224
218
 
225
219
  try {
226
220
  const claude = await fs.readFile(path.join(projectPath, 'CLAUDE.md'), 'utf-8');
227
- // 契约在场判定收口 injection-writer.hasGovernanceContract(#83,与 presence/landing 同谓词)
228
- if (hasGovernanceContract(claude)) {
229
- info.hasClaudeGovernance = true;
230
- info.ironLaws = countConstraintBullets(claude, 'Iron Laws');
231
- info.guidelines = countConstraintBullets(claude, 'Guidelines');
232
- }
221
+ // 契约在场判定收口 injection-writer.hasGovernanceContract(#83,与 presence 同谓词)
222
+ info.hasClaudeGovernance = hasGovernanceContract(claude);
233
223
  } catch {
234
224
  // CLAUDE.md 不存在
235
225
  }
@@ -237,17 +227,6 @@ async function getGovernanceInfo(projectPath: string): Promise<GovernanceInfo> {
237
227
  return info;
238
228
  }
239
229
 
240
- /** 统计 CLAUDE.md 指定约束分节下的条目数(`- **key**:` 行),分节不存在时返回 undefined */
241
- function countConstraintBullets(content: string, section: string): number | undefined {
242
- const heading = new RegExp(`^###\\s+${section}[^\\n]*$`, 'm').exec(content);
243
- if (!heading) return undefined;
244
- const rest = content.slice(heading.index + heading[0].length);
245
- const end = rest.search(/^###\s|^\s*<!--\s*HARNESS_CONSTRAINTS_END/m);
246
- const block = end === -1 ? rest : rest.slice(0, end);
247
- const items = block.match(/^-\s+\*\*[A-Za-z0-9_]+\*\*/gm);
248
- return items ? items.length : 0;
249
- }
250
-
251
230
  /** 判断 .harness/knowledge 目录是否存在(只判存在性,不统计条数——条数易变,见 buildAgentsMd 注释) */
252
231
  async function hasKnowledgeDir(projectPath: string): Promise<boolean> {
253
232
  try {