@dommaker/harness 1.8.1 → 1.9.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 (59) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +1 -1
  3. package/dist/cli/commands/sync-docs/capabilities-syncer.d.ts +22 -0
  4. package/dist/cli/commands/sync-docs/capabilities-syncer.d.ts.map +1 -1
  5. package/dist/cli/commands/sync-docs/capabilities-syncer.js +113 -8
  6. package/dist/cli/commands/sync-docs/capabilities-syncer.js.map +1 -1
  7. package/dist/cli/commands/sync-docs/index.d.ts.map +1 -1
  8. package/dist/cli/commands/sync-docs/index.js +36 -4
  9. package/dist/cli/commands/sync-docs/index.js.map +1 -1
  10. package/dist/hooks/bootstrap.d.ts +9 -12
  11. package/dist/hooks/bootstrap.d.ts.map +1 -1
  12. package/dist/hooks/bootstrap.js +9 -31
  13. package/dist/hooks/bootstrap.js.map +1 -1
  14. package/dist/hooks/index.d.ts +5 -7
  15. package/dist/hooks/index.d.ts.map +1 -1
  16. package/dist/hooks/index.js +4 -10
  17. package/dist/hooks/index.js.map +1 -1
  18. package/dist/index.d.ts +2 -2
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +3 -7
  21. package/dist/index.js.map +1 -1
  22. package/package.json +1 -1
  23. package/src/CONTEXT.md +1 -1
  24. package/src/__tests__/public-exports.test.ts +30 -4
  25. package/src/__tests__/public-type-surface.test.ts +0 -8
  26. package/src/cli/commands/CONTEXT.md +3 -0
  27. package/src/cli/commands/__tests__/registry.test.ts +39 -3
  28. package/src/cli/commands/__tests__/sync-docs-table-layout.test.ts +259 -0
  29. package/src/cli/commands/sync-docs/capabilities-syncer.ts +139 -9
  30. package/src/cli/commands/sync-docs/index.ts +41 -4
  31. package/src/hooks/CONTEXT.md +12 -22
  32. package/src/hooks/__tests__/bootstrap.test.ts +21 -70
  33. package/src/hooks/bootstrap.ts +9 -48
  34. package/src/hooks/index.ts +5 -20
  35. package/src/index.ts +1 -13
  36. package/dist/hooks/config.d.ts +0 -30
  37. package/dist/hooks/config.d.ts.map +0 -1
  38. package/dist/hooks/config.js +0 -34
  39. package/dist/hooks/config.js.map +0 -1
  40. package/dist/hooks/pipeline.d.ts +0 -54
  41. package/dist/hooks/pipeline.d.ts.map +0 -1
  42. package/dist/hooks/pipeline.js +0 -173
  43. package/dist/hooks/pipeline.js.map +0 -1
  44. package/dist/hooks/registry.d.ts +0 -70
  45. package/dist/hooks/registry.d.ts.map +0 -1
  46. package/dist/hooks/registry.js +0 -141
  47. package/dist/hooks/registry.js.map +0 -1
  48. package/dist/hooks/types.d.ts +0 -113
  49. package/dist/hooks/types.d.ts.map +0 -1
  50. package/dist/hooks/types.js +0 -9
  51. package/dist/hooks/types.js.map +0 -1
  52. package/src/__tests__/hooks-pipeline.test.ts +0 -201
  53. package/src/hooks/__tests__/config.test.ts +0 -19
  54. package/src/hooks/__tests__/pipeline.test.ts +0 -195
  55. package/src/hooks/__tests__/registry.test.ts +0 -115
  56. package/src/hooks/config.ts +0 -33
  57. package/src/hooks/pipeline.ts +0 -202
  58. package/src/hooks/registry.ts +0 -166
  59. package/src/hooks/types.ts +0 -120
@@ -1,12 +1,10 @@
1
1
  /**
2
2
  * Hooks 模块
3
3
  *
4
- * 通用 hook 管线:注册 排序 → 错误隔离 → 采样执行。
5
- * 无业务逻辑,consumer 自行定义 hook 名称和语义。
4
+ * ADR-0027(#170)起本层只剩 `bootstrap.ts` 一个面:通用 hook 管线
5
+ * (registry / pipeline / config / types 四文件)双仓零生产消费者,整体删除。
6
+ * 目录名沿用历史,职责是 harness 运行环境的组合根。
6
7
  */
7
- export type { HookPhase, HookErrorStrategy, HookConfig, HookDefinition, EffectiveHook, HookResult, HookExecutionRecord, PipelineResult, } from './types';
8
- export { HookRegistry, assertHookRegistryClosed } from './registry';
9
- export { HookPipeline } from './pipeline';
10
- export { toErrorStrategy } from './config';
11
- export { bootstrapHarness, bootstrapHarnessSync, type HarnessBootstrap, } from './bootstrap';
8
+ export { bootstrapHarness, bootstrapHarnessSync } from './bootstrap';
9
+ export type { HarnessBootstrap } from './bootstrap';
12
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EACV,SAAS,EACT,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,aAAa,EACb,UAAU,EACV,mBAAmB,EACnB,cAAc,GACf,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,YAAY,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,KAAK,gBAAgB,GACtB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACrE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC"}
@@ -2,18 +2,12 @@
2
2
  /**
3
3
  * Hooks 模块
4
4
  *
5
- * 通用 hook 管线:注册 排序 → 错误隔离 → 采样执行。
6
- * 无业务逻辑,consumer 自行定义 hook 名称和语义。
5
+ * ADR-0027(#170)起本层只剩 `bootstrap.ts` 一个面:通用 hook 管线
6
+ * (registry / pipeline / config / types 四文件)双仓零生产消费者,整体删除。
7
+ * 目录名沿用历史,职责是 harness 运行环境的组合根。
7
8
  */
8
9
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.bootstrapHarnessSync = exports.bootstrapHarness = exports.toErrorStrategy = exports.HookPipeline = exports.assertHookRegistryClosed = exports.HookRegistry = void 0;
10
- var registry_1 = require("./registry");
11
- Object.defineProperty(exports, "HookRegistry", { enumerable: true, get: function () { return registry_1.HookRegistry; } });
12
- Object.defineProperty(exports, "assertHookRegistryClosed", { enumerable: true, get: function () { return registry_1.assertHookRegistryClosed; } });
13
- var pipeline_1 = require("./pipeline");
14
- Object.defineProperty(exports, "HookPipeline", { enumerable: true, get: function () { return pipeline_1.HookPipeline; } });
15
- var config_1 = require("./config");
16
- Object.defineProperty(exports, "toErrorStrategy", { enumerable: true, get: function () { return config_1.toErrorStrategy; } });
10
+ exports.bootstrapHarnessSync = exports.bootstrapHarness = void 0;
17
11
  var bootstrap_1 = require("./bootstrap");
18
12
  Object.defineProperty(exports, "bootstrapHarness", { enumerable: true, get: function () { return bootstrap_1.bootstrapHarness; } });
19
13
  Object.defineProperty(exports, "bootstrapHarnessSync", { enumerable: true, get: function () { return bootstrap_1.bootstrapHarnessSync; } });
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAYH,uCAAoE;AAA3D,wGAAA,YAAY,OAAA;AAAE,oHAAA,wBAAwB,OAAA;AAC/C,uCAA0C;AAAjC,wGAAA,YAAY,OAAA;AACrB,mCAA2C;AAAlC,yGAAA,eAAe,OAAA;AACxB,yCAIqB;AAHnB,6GAAA,gBAAgB,OAAA;AAChB,iHAAA,oBAAoB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAEH,yCAAqE;AAA5D,6GAAA,gBAAgB,OAAA;AAAE,iHAAA,oBAAoB,OAAA"}
package/dist/index.d.ts CHANGED
@@ -56,8 +56,8 @@ export type { CheckerVerdict, CommitVerdict, CommitInput, CommitFileClassificati
56
56
  export { getRegistryPath, getToolsDir } from './tools';
57
57
  export { getCriticalArtifacts, verifyReleaseArtifacts } from './release';
58
58
  export type { ArtifactIntegrityResult } from './release';
59
- export { HookRegistry, assertHookRegistryClosed, HookPipeline, toErrorStrategy, bootstrapHarness, bootstrapHarnessSync, } from './hooks';
60
- export type { HookDefinition, HookConfig, EffectiveHook, HookErrorStrategy, HookExecutionRecord, HookPhase, HookResult, PipelineResult, HarnessBootstrap, } from './hooks';
59
+ export { bootstrapHarness, bootstrapHarnessSync, } from './hooks';
60
+ export type { HarnessBootstrap, } from './hooks';
61
61
  export { AgentLifecycle, } from './agents';
62
62
  export type { AgentConfig, AgentEvent, AgentState, AgentStatus, EventHandler, FallbackStrategy, } from './agents';
63
63
  export type { ProjectConfig, MergedConstraintsConfig, CustomConstraintDefinition, GovernanceConfig, CapabilitiesConfig, ChangelogConfig, ChangelogVersionCheck, TestingGovernanceConfig, ContextFilesConfig, ContextDocsCheck, DocsSyncConfig, DocFreshnessConfig, DocFreshnessCheck, DocDirCheck, DocRegexCountCheck, ConstCountActual, DirCountActual, GrepCountActual, } from './types/project-config';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -23,8 +23,8 @@
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.TraceCollector = exports.DEFAULT_TRACE_FILE = exports.createCheckerGate = exports.runGates = exports.assertGateRegistryClosed = exports.registeredGateCount = exports.listRegisteredGates = exports.getGate = exports.GATE_DEFINITIONS = exports.decisionFromResult = exports.createSpecAcceptanceGate = exports.createContractGate = exports.createPerformanceGate = exports.createSecurityGate = exports.createReviewGate = exports.DEFAULT_COMMAND_BLACKLIST = exports.getCommandRiskLevel = exports.isCommandAllowed = exports.getCommandGate = exports.createCommandGate = exports.CommandGate = exports.SpecAcceptanceGate = exports.ContractGate = exports.PerformanceGate = exports.SecurityGate = exports.ReviewGate = exports.validateAllSpecs = exports.validateSpec = exports.SpecValidator = exports.CSOValidator = exports.createPassesGate = exports.PassesGate = exports.CheckpointValidator = exports.renderConstraintsSection = exports.CONSTRAINTS_END_MARKER = exports.CONSTRAINTS_START_MARKER = exports.renderConstraintsByTrigger = exports.CheckCache = exports.checkBeforeExecution = exports.checkConstraints = exports.checkConstraint = exports.lintEffectiveConfig = exports.getEffectiveConstraints = exports.findConstraintsByTrigger = exports.getConstraint = exports.getAllConstraints = exports.PROMPTS = exports.GUIDELINES = exports.IRON_LAWS = exports.ConstraintViolationError = void 0;
26
- exports.HookRegistry = exports.verifyReleaseArtifacts = exports.getCriticalArtifacts = exports.getToolsDir = exports.getRegistryPath = exports.verifyContractPresence = exports.PHASE_SUBJECT_RE = exports.verifyPhaseFormat = exports.TESTS_NONE_RE = exports.TESTED_BY_RE = exports.verifyTddChain = exports.resolveGlobs = exports.classifyCommitFiles = exports.matchAnyGlob = exports.matchGlob = exports.DEFAULT_NONCODE_GLOBS = exports.DEFAULT_TEST_GLOBS = exports.DEFAULT_DECAY_CONFIG = exports.extractCodeStructure = exports.migrateKnowledgeEntries = exports.KnowledgeAudit = exports.KnowledgeHealthScorer = exports.ColdStartImporter = exports.KnowledgeLinter = exports.ReferenceTracker = exports.sanitizeExternalContent = exports.KnowledgeIngest = exports.KnowledgeLifecycle = exports.KnowledgeQuery = exports.FileKnowledgeStore = exports.KnowledgeInjector = exports.SessionManager = exports.TokenEstimator = exports.TokenBudget = exports.createFailureRecorder = exports.FailureRecorder = exports.getFailureLevel = exports.classifyError = exports.createErrorClassifier = exports.ErrorClassifier = exports.DEFAULT_LEVEL_MAPPING = exports.DEFAULT_CLASSIFICATION_RULES = exports.DEFAULT_FAILURE_LOG_FILE = exports.FailureLevel = exports.ErrorType = exports.ContextTracker = exports.createAnalyzer = exports.TraceAnalyzer = exports.configureTraceCollector = exports.getTraceCollector = void 0;
27
- exports.AgentLifecycle = exports.bootstrapHarnessSync = exports.bootstrapHarness = exports.toErrorStrategy = exports.HookPipeline = exports.assertHookRegistryClosed = void 0;
26
+ exports.bootstrapHarness = exports.verifyReleaseArtifacts = exports.getCriticalArtifacts = exports.getToolsDir = exports.getRegistryPath = exports.verifyContractPresence = exports.PHASE_SUBJECT_RE = exports.verifyPhaseFormat = exports.TESTS_NONE_RE = exports.TESTED_BY_RE = exports.verifyTddChain = exports.resolveGlobs = exports.classifyCommitFiles = exports.matchAnyGlob = exports.matchGlob = exports.DEFAULT_NONCODE_GLOBS = exports.DEFAULT_TEST_GLOBS = exports.DEFAULT_DECAY_CONFIG = exports.extractCodeStructure = exports.migrateKnowledgeEntries = exports.KnowledgeAudit = exports.KnowledgeHealthScorer = exports.ColdStartImporter = exports.KnowledgeLinter = exports.ReferenceTracker = exports.sanitizeExternalContent = exports.KnowledgeIngest = exports.KnowledgeLifecycle = exports.KnowledgeQuery = exports.FileKnowledgeStore = exports.KnowledgeInjector = exports.SessionManager = exports.TokenEstimator = exports.TokenBudget = exports.createFailureRecorder = exports.FailureRecorder = exports.getFailureLevel = exports.classifyError = exports.createErrorClassifier = exports.ErrorClassifier = exports.DEFAULT_LEVEL_MAPPING = exports.DEFAULT_CLASSIFICATION_RULES = exports.DEFAULT_FAILURE_LOG_FILE = exports.FailureLevel = exports.ErrorType = exports.ContextTracker = exports.createAnalyzer = exports.TraceAnalyzer = exports.configureTraceCollector = exports.getTraceCollector = void 0;
27
+ exports.AgentLifecycle = exports.bootstrapHarnessSync = void 0;
28
28
  // ========================================
29
29
  // 约束类型(三层体系 + kind 二元)
30
30
  // ========================================
@@ -186,13 +186,9 @@ var release_1 = require("./release");
186
186
  Object.defineProperty(exports, "getCriticalArtifacts", { enumerable: true, get: function () { return release_1.getCriticalArtifacts; } });
187
187
  Object.defineProperty(exports, "verifyReleaseArtifacts", { enumerable: true, get: function () { return release_1.verifyReleaseArtifacts; } });
188
188
  // ========================================
189
- // Hooks 管线
189
+ // Harness 运行环境引导(bootstrap 单面;hooks 管线面已随 ADR-0027 删除)
190
190
  // ========================================
191
191
  var hooks_1 = require("./hooks");
192
- Object.defineProperty(exports, "HookRegistry", { enumerable: true, get: function () { return hooks_1.HookRegistry; } });
193
- Object.defineProperty(exports, "assertHookRegistryClosed", { enumerable: true, get: function () { return hooks_1.assertHookRegistryClosed; } });
194
- Object.defineProperty(exports, "HookPipeline", { enumerable: true, get: function () { return hooks_1.HookPipeline; } });
195
- Object.defineProperty(exports, "toErrorStrategy", { enumerable: true, get: function () { return hooks_1.toErrorStrategy; } });
196
192
  Object.defineProperty(exports, "bootstrapHarness", { enumerable: true, get: function () { return hooks_1.bootstrapHarness; } });
197
193
  Object.defineProperty(exports, "bootstrapHarnessSync", { enumerable: true, get: function () { return hooks_1.bootstrapHarnessSync; } });
198
194
  // ========================================
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dommaker/harness",
3
- "version": "1.8.1",
3
+ "version": "1.9.0",
4
4
  "description": "通用工程约束框架 - 铁律系统、检查点验证、测试门控",
5
5
  "keywords": [
6
6
  "harness",
package/src/CONTEXT.md CHANGED
@@ -34,7 +34,7 @@
34
34
 
35
35
  | 术语 | 定义 |
36
36
  |------|------|
37
- | 插件 | harness 扩展点统称 = hook / checker / 门禁(Gate) / 命令(CLI);非运行时插件容器——harness 是文件驱动 CLI、无常驻进程 |
37
+ | 插件 | harness 扩展点统称 = checker / 门禁(Gate) / 命令(CLI);非运行时插件容器——harness 是文件驱动 CLI、无常驻进程。hook 一族已退出扩展点统称(ADR-0027/#170 删 hooks 管线面,`src/hooks/` 只剩 bootstrap 组合根) |
38
38
  | Gate(门禁) | 统一守卫接口 `Gate{id, order, evaluate(ctx)}` → `GateDecision`;统一的是决策协议(id/order/三态),执行细节私有 |
39
39
  | GateDecision | 三态决策 `deny \| abstain \| ask`;deny 单调(下游不可改回 allow)、ask 枚举预留 fail-closed = deny |
40
40
  | GateResult | 报告结构(gate/passed/message/details/timestamp/duration),保留为报告层,不作决策 |
@@ -44,8 +44,6 @@ const EXPECTED_RUNTIME_EXPORTS = [
44
44
  'FileKnowledgeStore',
45
45
  'GATE_DEFINITIONS',
46
46
  'GUIDELINES',
47
- 'HookPipeline',
48
- 'HookRegistry',
49
47
  'IRON_LAWS',
50
48
  'KnowledgeAudit',
51
49
  'KnowledgeHealthScorer',
@@ -71,7 +69,6 @@ const EXPECTED_RUNTIME_EXPORTS = [
71
69
  'TraceAnalyzer',
72
70
  'TraceCollector',
73
71
  'assertGateRegistryClosed',
74
- 'assertHookRegistryClosed',
75
72
  'bootstrapHarness',
76
73
  'bootstrapHarnessSync',
77
74
  'checkBeforeExecution',
@@ -117,7 +114,6 @@ const EXPECTED_RUNTIME_EXPORTS = [
117
114
  'resolveGlobs',
118
115
  'runGates',
119
116
  'sanitizeExternalContent',
120
- 'toErrorStrategy',
121
117
  'validateAllSpecs',
122
118
  'validateSpec',
123
119
  'verifyContractPresence',
@@ -189,4 +185,34 @@ describe('包根类型面(ADR-0022 关联类型随迁)', () => {
189
185
  expect(liveCheck.allowed).toBe(true);
190
186
  expect(liveTask.command).toBe('npm test');
191
187
  });
188
+
189
+ /**
190
+ * ADR-0027(#170)管线面删除的可达性负钉:4 值符号 + 8 类型。
191
+ *
192
+ * 两道全量清单闸钉的是「码与名单不符」,本钉直接钉「barrel 源里不再出现这些名字」——
193
+ * 回灌时红名指到 barrel 本身,不必从清单 diff 反推。barrel 源形状即全可达面:
194
+ * `export *` 已被 `sub-barrels-explicit.test.ts` 禁到 src 下全部目录 barrel,
195
+ * 且 `./hooks` 不在 `package.json` 的 `exports` 内(无子路径入口可绕)。
196
+ */
197
+ const ADR0027_DELETED_SYMBOLS = [
198
+ 'HookRegistry',
199
+ 'HookPipeline',
200
+ 'assertHookRegistryClosed',
201
+ 'toErrorStrategy',
202
+ 'HookDefinition',
203
+ 'HookConfig',
204
+ 'EffectiveHook',
205
+ 'HookErrorStrategy',
206
+ 'HookExecutionRecord',
207
+ 'HookPhase',
208
+ 'HookResult',
209
+ 'PipelineResult',
210
+ ];
211
+
212
+ for (const rel of ['../hooks/index.ts', '../index.ts']) {
213
+ it(`${rel} 不再提及 ADR-0027 已删的管线面符号(保留面 bootstrapHarness* 不受影响)`, () => {
214
+ const source = fs.readFileSync(path.join(__dirname, rel), 'utf-8');
215
+ expect(ADR0027_DELETED_SYMBOLS.filter((name) => source.includes(name))).toEqual([]);
216
+ });
217
+ }
192
218
  });
@@ -170,7 +170,6 @@ const PUBLISHED_ENTRY_TYPES: Record<string, string[]> = {
170
170
  'DocRegexCountCheck',
171
171
  'DocsSyncConfig',
172
172
  'EffectiveConfigLint',
173
- 'EffectiveHook',
174
173
  'ErrorClassificationRule',
175
174
  'ErrorClassifierConfig',
176
175
  'EventHandler',
@@ -189,12 +188,6 @@ const PUBLISHED_ENTRY_TYPES: Record<string, string[]> = {
189
188
  'GovernanceConfig',
190
189
  'GrepCountActual',
191
190
  'HarnessBootstrap',
192
- 'HookConfig',
193
- 'HookDefinition',
194
- 'HookErrorStrategy',
195
- 'HookExecutionRecord',
196
- 'HookPhase',
197
- 'HookResult',
198
191
  'ImportInfo',
199
192
  'IndexEntry',
200
193
  'IngestOptions',
@@ -217,7 +210,6 @@ const PUBLISHED_ENTRY_TYPES: Record<string, string[]> = {
217
210
  'PerformanceGateConfig',
218
211
  'PerformanceThresholds',
219
212
  'PhaseFormatResult',
220
- 'PipelineResult',
221
213
  'ProjectConfig',
222
214
  'QueryBudget',
223
215
  'QueryFilter',
@@ -47,6 +47,8 @@ H5(#44)起:
47
47
  - **一次命令运行内,同一份数据至多取一次(harness#146,#140 A 票;与 ADR-0023 同族,但不扩 `RunEnv` 公共面)**:`spec-baseline-check` 的三条验证路径(文件存在性 / 依赖 / 代码模式)一律从命令级共享索引 `createBaselineIndex(projectPath)` 取数,不再各自裸调 `fs`——全仓 `.ts`/`.js` 内容扫描一遍建成 `路径 → 内容` 表、`package.json` 读解析一次(**读取失败态同样入库**,不逐条重试)、同一落点的存在性探测只 stat 一次;逐条前置与每个关键词只在索引上重放判定。索引**懒建**(没有前置需要某类数据时该类读取一次都不发生)、**运行结束即弃**(不跨命令复用:本命令是独立命令而非 `harness check` 的子步骤,「同一口径取一次」命令内自足即够,#140 triage 裁决 5)。改前代价 = 前置条件数 × 关键词数 × 源文件数,改后与条数无关,判定/证据文案/stdout/退出码逐字不变。**驻留上界(harness#162)**:索引容量有双上限 `SOURCE_INDEX_MAX_ENTRIES = 5000` / `SOURCE_INDEX_MAX_BYTES = 64MB`——超任一上限即放弃驻留、**回落逐文件流式读**(每个关键词重扫一遍,读完即弃),峰值内存由 O(全仓源码) 回到 O(单文件),正常规模仓保留「一次遍历」收益;取数面相应由 `sourceContents(): Map` 改为 `countFilesContaining(keyword)`,容量策略全部收在索引内部。机器可检:`__tests__/spec-baseline-read-count.test.ts`(形状照 `check-read-count.test.ts`:`readFileSync`·只读 `openSync`·`existsSync`·`readdirSync` 记件 + 整张读取表与目录扫描表逐条冻结 + 「同一份数据的同一口径至多取一次」+ N×K 缩放不变式 + 懒建不扫 + 失败态入库)+ `__tests__/spec-baseline-index-cap.test.ts`(驻留上界闸:上限内每文件至多读一遍、超条目/字节上限回落流式且判定不变)
48
48
  - **先判定「本次要什么」再决定「读什么」,且清单顺序是对外面(harness#147,#140 B 票)**:`sync-docs/index.ts` 把 CAPABILITIES.md 的**格式判定放在源码扫描之前**——capability-listing 格式的判定面是计数、不做条目级比对,模块清单在本次运行里无人消费,于是整棵源码树**一份 `.ts` 内容都不读**(改造前是无条件全树逐文件 `await readFile`,只为首行注释)。要描述的分支(file-table)照旧取描述,但 `project-reader.ts` 分两步:先按目录遍历序定清单,再经 `extractFileDescriptions()` **并发**取数(上限固定 16,按票下裁决不做成配置面)并**按原索引回填**。清单顺序对外可见(`--check` 逐行比对生成的表格、人看 diff),票下裁决是「顺序逐字保持现状、不改字典序」,故「按并发完成顺序 append」属行为漂移而非优化。读盘次数之外一切不变:判定、漂移检测、写回内容逐字保持。机器可检:`__tests__/sync-docs-read-count.test.ts`(形状照 `check-read-count.test.ts`——listing 模式 `.ts` 内容读 = 0 + file-table 反证每份文件恰读一次 + 整张读取表冻结)、`sync-docs/__tests__/module-descriptions.test.ts`(替身把「起始序」与「完成序」刻意错开:串位或重排即红,另钉上限)、`__tests__/sync-docs-module-order.test.ts`(生成表格行序 = 目录遍历序、两次运行逐字复现)
49
49
 
50
+ - **撤登记要整行删,排版判定与修复共用一份正本(harness#171)**:`capabilities-syncer.ts` 删幽灵行此前是 `content.replace(/^\|…$/gm, '')`——`m` 下 `^…$` 只框住行内容、**不含行尾换行**,删完留一个空行;CommonMark 以空行断表,于是每撤一次登记就把一张能力表多切一刀(studio 存量攒到 40 处)。同函数末尾的 `\n{3,}→\n\n` 救不了它:删一行只产两个换行,够不着阈值(删相邻两行也不变好——只是把两刀并成一刀)。现行形状:① 删除按行 split/filter/join,行尾随之消失(CRLF 一并处理,正则尾上加 `\r?` 保持与旧 `m` 相同的匹配面);② 排版收拢正本是 `normalizeCapabilitiesTableLayout(content)`——规则①删两侧都是表格行的空行段、规则②收掉无数据行的表头/分隔行,**表格外的段落空行不动**,且**两条规则互相制造触发点**(①吃掉两张空表之间那个空行后,②在同一轮只收得掉后一张),故**跑到不动点**:一次 `sync-docs` 必须把 `--check` 报出来的全清掉,否则下游 CI 修完还红;③ 原有的一处 `\n{3,}→\n\n` 由「增删之后」移到**收拢之后**(收掉一张夹在两段散文之间的空表本身会新产 `\n\n\n`,留在前面就漏折叠),并删掉增删分支内那份重复折叠。围栏代码块(``` / ~~~)内的行在**排版收拢一侧整体豁免**(CAPABILITIES.md 是手写文档,块内长得像表格的示例行不是脏行:不给豁免时一块「表头+分隔行」示例被判空表删掉正文、`--check` 还为此判红)——但**幽灵行删除一侧刻意不豁免**,两侧口径故意不同:登记条目由 `core/constraints/capabilities-parser` 全文扫描得出(ADR-0009),围栏内的行同样算登记项,只让删除认围栏而条目不认,块内示例引用的已删文件会永远报成幽灵条目且 `--check` 修不掉(机器可检:「围栏内示例行引用已删文件」用例同时钉收敛与「只吃掉那一行、块内其余正文留着」)。让两侧同认围栏 = 改 ADR-0009 的登记面并连带影响 docs_freshness 判定,另票裁决。`--check` 的判定面就是「它返回的内容与入参是否不同」,写模式在**增删之后**调用收拢(先收拢会误删「本轮要往空表里补新行」的表头),故 check 报得出、fix 必清得掉(不重演 2026-08-04 studio PR #44 的「check 永不收敛」)。机器可检:`__tests__/sync-docs-table-layout.test.ts`(13 例:中间行/末行/目录条目行/CRLF 四种撤登形状 + 存量脏行 check 判红后写模式转绿 + 空表收掉 + 两张空表相邻一次收干净 + 收拢后不留三连换行 + 四条反向闸「有新行不误删表头」「表格外空行不动」「代码块内空表不被收」「代码块内表格样式行不被收拢」)
51
+
50
52
  ## 注意事项
51
53
  - 新增命令需同步更新 CLAUDE.md / CAPABILITIES.md / src/CONTEXT.md
52
54
  - **scaffold 三态模型(harness#132 已落地)**:init/validate 的「目标在不在场→写或告知」判定(9 站点 = init 7 + validate 2,#132 收口时 8 处)收口为 scaffold 模块。术语:**managed file**(受管文件)= harness 模板拥有正本、用户可持有的落盘文件;三态 = `created`(不在场→落盘)/ `exists`(在场→告知跳过,**不细分内容是否等于模板**,内容比较是独立特性)/ `manual`(在场→打印片段请用户手工合并)。纪律:scaffold 不持有覆盖/跳过策略(`--no-git-hooks`/`--no-github-actions` 由命令层翻成 plan 列表,scaffold 只见 plan);模板留代码内住 `scaffold-templates.ts`,不落 `templates/`(其无运行时消费者、integrity 清单不覆盖);**打印给用户的片段必须是落盘正文的一部分**(GH Actions 站点冲突分支打印完整 workflow 全文而非 job 片段,#103 判据);`--print-snippets` 的片段视图同判据且**由正本裁剪派生**(harness#153:`GITHUB_ACTIONS_SNIPPET` = `HARNESS_CHECK_WORKFLOW` 的 `jobs:` 段之后,形状与 GitLab 侧「打印的是落盘正文的尾巴」对仗。它曾是手抄的第二份文本,比落盘正本少 `validate` / `passes-gate` 两道门禁——照抄的用户拿到比同版本 `harness init` 弱一半的 CI;引导语随之改准为「以下正文取自 harness-check.yml 的 job 段」,`--print-snippets` 旗帜本身保留);gitlab 形同判据由 harness#157 补齐——`printSnippets` 收 `governanceLevel`、打 `renderGitLabCiJobs(governanceLevel)`,与落盘 / 冲突分支同一个正本函数(此前打无 level 的 `GITLAB_CI_SNIPPET`,`-g` 档照抄的用户静默少拿治理与 docs 新鲜度两个任务);CLAUDE.md/AGENTS.md 标记化幂等写(读-改-写形状)不纳入 scaffold;死选项 `-t/--type` 已随本票删除。GitLab CI 接线决议见下条;pre-push 站点已随 harness#144 落地,见「本地防线两道」条
@@ -76,3 +78,4 @@ H5(#44)起:
76
78
  - **本目录零 `process.exit` / `process.exitCode`**:kind → 退出码的唯一映射在 `bin/harness.js`(`ok`/`skip` → 0,`fail`/`usage-error` → 1,未知 kind fail-closed)。历史上两处条件式(`command --level` 按严重级、门禁按 passed)已由命令侧译成 kind;`sync-docs --check` 的漂移改由实现返回 `fail`(定义表的 `afterRun` 逃生门随之废除)
77
79
  - **输出不得直接用 console**:流式打印走 `log(io, …)` / `logError(io, …)`(`util.format` + 换行,与 console 逐字节等价,见 `src/cli/__tests__/command-contract.test.ts`);测试断言输出用 `captureIO()`,不再 `spyOn(process, 'exit')`;`--json` 输出断言用 `lastJsonOutput(io)`(JSON.parse 正本,harness#108)。例外:`constraints retire` 交互正文仍走 console(其 `RetireIO` 只注入 readline 流),退役结果打印已接注入流
78
80
  - **#95 同型扫荡结论**:两门禁站点已修(`passes-gate` 执行/证据落 projectPath、`acceptance` 去掉 `tasksPath: './tasks.yml'` 相对默认值)。逐点判定后的豁免四处,理由与站点原文一起冻结在 `__tests__/project-path-convention.test.ts` 的豁免表:`release` 的 `pkgPath`(定义表本无 `-p`,pkgPath 就是该命令唯一的根且已逐个传给每条 `run(cmd, pkgPath)`,不构成半失效;给发布流水线新增 `-p` 属新能力)、`command` 的 `evaluate({ projectPath: process.cwd(), … })`(`CommandGate` 只做命令串正则判定、零文件读写,且该命令定义表里没有 `-p`,取 cwd 仅为满足 `GateContext` 形状,架构评审候选1)、`constraints` 的 `join(process.cwd(), 'package.json')`(报的是 harness 自身包版本,主锚 `__dirname`,cwd 仅兜底)、`core/spec/validator.ts` 的 `schemaPath: './specs/schemas'`(**确是同型病灶**:`validateAll(projectPath)` 用 projectPath 找 spec 文件、却用 cwd 找 schema;但 `validateFile`/`loadSchema` 签名里没有根,补齐要穿透整个 spec 域,留待 spec 单票收口)
81
+ - **另知:CAPABILITIES.md 排版面两处已知限制(harness#171 未修)**:① 收拢的围栏豁免只认 ` ``` ` / `~~~` 标记行,**4 空格以上缩进的代码块不豁免**(触发条件:手写 CAPABILITIES.md 用缩进而非围栏放表格示例,块内空行会被当排版脏行收掉)——缩进 ≥4 在 CommonMark 里与「缩进表格」本身歧义,现有豁免取保守侧(宁可少动),要收口得连 `TABLE_ROW_REGEX` 的缩进上界一起定;② **module 模式下整张表被收空后,下一次写会走「无表格」分支自动补一整张目录表**(`updateCapabilitiesFile` 的 `existingFiles.length === 0` else 分支),与同文件「目录条目需人工策划登记」的约定冲突——非 #171 引入(撤登记前留下的「空行 + 表头」形状经 `parseCapabilitiesFiles` 同样解析为空集,实测两版行为一致),且登记面认不认围栏要连 ADR-0009 一起裁决,另票。
@@ -15,6 +15,7 @@ import * as path from 'path';
15
15
  import { spawnSync } from 'child_process';
16
16
  import { COMMAND_DEFINITIONS, type CommandDefinition, type CommandImplRef } from '../definitions';
17
17
  import { GATE_DEFINITIONS } from '../../../gates/definitions';
18
+ import { FileKnowledgeStore } from '../../../knowledge/store';
18
19
 
19
20
  function collectRefs(defs: CommandDefinition[]): CommandImplRef[] {
20
21
  const refs: CommandImplRef[] = [];
@@ -189,8 +190,17 @@ const hasDist = fs.existsSync(distCommands);
189
190
  * 经 NODE_OPTIONS=--require 预加载探针 spawn bin(进程退出时打印加载的
190
191
  * 命令实现模块清单)。不用 node -e(commander 在 -e 下走 eval 分支,
191
192
  * argv 解析不同,会误判位置参数)。
193
+ *
194
+ * env 用于把命令指向临时夹具(见「别名子命令」用例),第二参随调用方并入。
195
+ * maxBuffer 显式抬高:spawnSync 缺省 1MB,子进程 stdout 超限是被 ENOBUFS **杀掉**
196
+ * 而非报错——status 变 null、stderr 一句解释都没有,看着像路由崩了。2026-09-20 本机
197
+ * 发版即以此形状暴露(真实库 221 条 / 1.35MB JSON)。抬高上限只是别再吞掉诊断信息,
198
+ * **数据面隔离仍由各用例的夹具负责**,不拿它当免罪符。
192
199
  */
193
- function runWithModuleProbe(argv: string[]): { status: number | null; implModules: string[]; stdout: string; stderr: string } {
200
+ function runWithModuleProbe(
201
+ argv: string[],
202
+ extraEnv: Record<string, string> = {},
203
+ ): { status: number | null; implModules: string[]; stdout: string; stderr: string } {
194
204
  const probeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-lazy-probe-'));
195
205
  const probeFile = path.join(probeDir, 'probe.js');
196
206
  fs.writeFileSync(probeFile, [
@@ -204,7 +214,8 @@ function runWithModuleProbe(argv: string[]): { status: number | null; implModule
204
214
  cwd: repoRoot,
205
215
  encoding: 'utf-8',
206
216
  timeout: 30000,
207
- env: { ...process.env, NODE_OPTIONS: `--require ${probeFile}` },
217
+ maxBuffer: 32 * 1024 * 1024,
218
+ env: { ...process.env, NODE_OPTIONS: `--require ${probeFile}`, ...extraEnv },
208
219
  });
209
220
  const match = r.stderr.match(/IMPL_MODULES=(.*)/);
210
221
  return {
@@ -270,7 +281,32 @@ smoke('bin/harness.js 端到端(dist 存在时)', () => {
270
281
  });
271
282
 
272
283
  it('别名子命令解析到同一实现(knowledge ls = list,候选7)', () => {
273
- const r = runWithModuleProbe(['knowledge', 'ls', '--json']);
284
+ // 数据面隔离:本用例判的是**路由**(别名 ls 与主名 list 命中同一实现、只加载 knowledge
285
+ // 侧两个模块),知识库内容纯属旁证。不指夹具时它读的是操作机的真实库(本机实测 221 条 /
286
+ // 1.35MB JSON),而 CI 全新 checkout 上该库为空——两侧取数规模差三个数量级,大的一侧
287
+ // stdout 越过 spawnSync 缺省缓冲直接被杀掉(形状见 runWithModuleProbe 注释)。
288
+ // 夹具目录由 src/test-setup/mkdtemp-cleanup.ts 在 afterAll 统一回收。
289
+ const kbDir = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-smoke-kb-'));
290
+ new FileKnowledgeStore({ baseDir: kbDir }).save({
291
+ id: 'SMOKE-001',
292
+ type: 'guideline',
293
+ title: 'Smoke Fixture Entry',
294
+ content: '别名路由用例的夹具条目,只为了让 --json 出口有真实记录可数',
295
+ maturity: 'verified',
296
+ layer: 'project',
297
+ created: new Date().toISOString(),
298
+ lastReferenced: new Date().toISOString(),
299
+ contributors: ['tester'],
300
+ projects: ['smoke'],
301
+ tags: [],
302
+ applicablePhases: [],
303
+ sourceReferences: [],
304
+ referencedBy: [],
305
+ executionResults: [],
306
+ consumptionMode: 'reference',
307
+ origin: 'system',
308
+ });
309
+ const r = runWithModuleProbe(['knowledge', 'ls', '--json'], { KNOWLEDGE_BASE_DIR: kbDir });
274
310
  expect(r.status).toBe(0);
275
311
  expect(JSON.parse(r.stdout)).toHaveProperty('total');
276
312
  expect(r.implModules).toEqual([
@@ -0,0 +1,259 @@
1
+ /**
2
+ * sync-docs 表格排版回归测试(harness#171)
3
+ *
4
+ * 症状:撤下 CAPABILITIES.md 的模块登记行时清空该行而非删行,残留空行把
5
+ * CommonMark 表格切断。判定面 = 「上一行与下一行都是 `|` 表格行、本行为空」不得存在。
6
+ * 正本修复在写路径(整行删除 + 存量收拢 + 空表收掉),--check 侧必须报待清理
7
+ * (check/fix 同规则才收敛,ADR-0009 口径)。
8
+ */
9
+ import * as fs from 'fs';
10
+ import * as os from 'os';
11
+ import * as path from 'path';
12
+ import { captureIO, type CapturingIO } from '../../command-contract';
13
+ import { normalizeCapabilitiesTableLayout } from '../sync-docs/capabilities-syncer';
14
+ import { syncDocs } from '../sync-docs';
15
+
16
+ let io: CapturingIO;
17
+ beforeEach(() => {
18
+ io = captureIO();
19
+ });
20
+
21
+ const HEADER = '| 模块 | 文件 | 说明 |\n|------|------|------|\n';
22
+
23
+ /** 「上一行与下一行都是表格行、本行为空」的行数 —— 本票的判定面 */
24
+ function countBlankRowsInsideTable(content: string): number {
25
+ const lines = content.split('\n');
26
+ let n = 0;
27
+ for (let i = 1; i < lines.length - 1; i++) {
28
+ if (
29
+ lines[i].trim() === '' &&
30
+ /^\s*\|/.test(lines[i - 1]) &&
31
+ /^\s*\|/.test(lines[i + 1])
32
+ ) {
33
+ n++;
34
+ }
35
+ }
36
+ return n;
37
+ }
38
+
39
+ /** 建一个 file 模式的最小工程:srcFiles 存在,CAPABILITIES.md 由 rows 拼出 */
40
+ function makeProject(
41
+ name: string,
42
+ srcFiles: string[],
43
+ doc: string
44
+ ): string {
45
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), `sync-docs-layout-${name}-`));
46
+ fs.mkdirSync(path.join(dir, 'src'), { recursive: true });
47
+ for (const f of srcFiles) {
48
+ const file = path.join(dir, 'src', f);
49
+ fs.mkdirSync(path.dirname(file), { recursive: true });
50
+ fs.writeFileSync(file, 'export const x = 1;\n');
51
+ }
52
+ fs.writeFileSync(path.join(dir, 'CAPABILITIES.md'), doc);
53
+ return dir;
54
+ }
55
+ const read = (dir: string) => fs.readFileSync(path.join(dir, 'CAPABILITIES.md'), 'utf-8');
56
+ const dataRow = (name: string, file: string, desc = 'D') => `| ${name} | ${file} | ${desc} |`;
57
+
58
+ describe('sync-docs CAPABILITIES.md 表格排版(#171)', () => {
59
+ it('撤中间登记行:整行删除,表格保持连续', async () => {
60
+ const dir = makeProject(
61
+ 'middle',
62
+ ['a.ts', 'c.ts'],
63
+ `# Capabilities\n\n${HEADER}${dataRow('a', 'src/a.ts')}\n${dataRow('b', 'src/b.ts')}\n${dataRow('c', 'src/c.ts')}\n`
64
+ );
65
+
66
+ await syncDocs({ projectPath: dir }, io);
67
+
68
+ const out = read(dir);
69
+ expect(out).not.toContain('src/b.ts');
70
+ expect(countBlankRowsInsideTable(out)).toBe(0);
71
+ expect(out).toBe(`# Capabilities\n\n${HEADER}${dataRow('a', 'src/a.ts')}\n${dataRow('c', 'src/c.ts')}\n`);
72
+ fs.rmSync(dir, { recursive: true, force: true });
73
+ });
74
+
75
+ it('撤目录条目行(studio 撤登记形状):同样整行删除', async () => {
76
+ const dir = makeProject(
77
+ 'dir-entry',
78
+ ['cli/cli.ts', 'harness/h.ts'],
79
+ `# Capabilities\n\n${HEADER}` +
80
+ `${dataRow('cli', 'src/cli/', 'C')}\n` +
81
+ `${dataRow('hooks', 'src/hooks/', 'H')}\n` +
82
+ `${dataRow('harness', 'src/harness/', 'A')}\n`
83
+ );
84
+
85
+ await syncDocs({ projectPath: dir }, io);
86
+
87
+ const out = read(dir);
88
+ expect(out).not.toContain('src/hooks/');
89
+ expect(countBlankRowsInsideTable(out)).toBe(0);
90
+ expect(out).toContain(`${dataRow('cli', 'src/cli/', 'C')}\n${dataRow('harness', 'src/harness/', 'A')}`);
91
+ fs.rmSync(dir, { recursive: true, force: true });
92
+ });
93
+
94
+ it('撤最后一行:不留文件末尾空行', async () => {
95
+ const dir = makeProject(
96
+ 'last',
97
+ ['a.ts'],
98
+ `# Capabilities\n\n${HEADER}${dataRow('a', 'src/a.ts')}\n${dataRow('gone', 'src/gone.ts')}\n`
99
+ );
100
+
101
+ await syncDocs({ projectPath: dir }, io);
102
+
103
+ expect(read(dir)).toBe(`# Capabilities\n\n${HEADER}${dataRow('a', 'src/a.ts')}\n`);
104
+ fs.rmSync(dir, { recursive: true, force: true });
105
+ });
106
+
107
+ it('存量脏行(无其它漂移):--check 报待清理,写模式收拢且收拢后 check 转绿', async () => {
108
+ const dirty = `# Capabilities\n\n${HEADER}${dataRow('a', 'src/a.ts')}\n\n${dataRow('z', 'src/z.ts')}\n`;
109
+ const dir = makeProject('legacy', ['a.ts', 'z.ts'], dirty);
110
+
111
+ expect(countBlankRowsInsideTable(read(dir))).toBe(1);
112
+ const check = await syncDocs({ projectPath: dir, check: true }, io);
113
+ expect(check).toEqual({ kind: 'fail', reason: expect.stringContaining('表格') });
114
+
115
+ await syncDocs({ projectPath: dir }, io);
116
+ const out = read(dir);
117
+ expect(countBlankRowsInsideTable(out)).toBe(0);
118
+ expect(out).toContain('src/a.ts');
119
+ expect(out).toContain('src/z.ts');
120
+ expect(await syncDocs({ projectPath: dir, check: true }, io)).toEqual({ kind: 'ok' });
121
+ fs.rmSync(dir, { recursive: true, force: true });
122
+ });
123
+
124
+ it('表格被撤空:连表头/分隔行一起收掉', async () => {
125
+ const dir = makeProject(
126
+ 'empty-table',
127
+ [],
128
+ `# Capabilities\n\n${HEADER}${dataRow('gone1', 'src/gone1.ts')}\n${dataRow('gone2', 'src/gone2.ts')}\n`
129
+ );
130
+
131
+ await syncDocs({ projectPath: dir }, io);
132
+
133
+ const out = read(dir);
134
+ expect(out).not.toContain('|------|');
135
+ expect(out).not.toContain('模块 | 文件');
136
+ expect(out).not.toMatch(/\n{3,}/);
137
+ expect(await syncDocs({ projectPath: dir, check: true }, io)).toEqual({ kind: 'ok' });
138
+ fs.rmSync(dir, { recursive: true, force: true });
139
+ });
140
+
141
+ it('撤登同时有新增:不得把仍要使用的表头收掉', async () => {
142
+ const dir = makeProject(
143
+ 'remove-and-add',
144
+ ['b.ts', 'fresh.ts'],
145
+ `# Capabilities\n\n${HEADER}${dataRow('a', 'src/gone.ts')}\n${dataRow('b', 'src/b.ts')}\n`
146
+ );
147
+
148
+ await syncDocs({ projectPath: dir }, io);
149
+
150
+ const out = read(dir);
151
+ expect(out).toContain('模块 | 文件 | 说明');
152
+ expect(out).toContain('fresh.ts');
153
+ expect(countBlankRowsInsideTable(out)).toBe(0);
154
+ fs.rmSync(dir, { recursive: true, force: true });
155
+ });
156
+
157
+ it('表格外的空行不动(段落分隔不是脏行)', async () => {
158
+ const doc = `# Capabilities\n\n${HEADER}${dataRow('a', 'src/a.ts')}\n\n## 说明\n\n散文。\n`;
159
+ const dir = makeProject('prose', ['a.ts'], doc);
160
+
161
+ const check = await syncDocs({ projectPath: dir, check: true }, io);
162
+ expect(check).toEqual({ kind: 'ok' });
163
+ expect(read(dir)).toBe(doc);
164
+ fs.rmSync(dir, { recursive: true, force: true });
165
+ });
166
+
167
+ it('代码块内「表头+分隔行无数据行」的示例不被收掉', async () => {
168
+ const doc =
169
+ `# Capabilities\n\n${HEADER}${dataRow('a', 'src/a.ts')}\n\n` +
170
+ `登记格式:\n\n\`\`\`markdown\n| 模块 | 文件 | 说明 |\n|------|------|------|\n\`\`\`\n\n散文。\n`;
171
+ const dir = makeProject('fenced-empty-table', ['a.ts'], doc);
172
+
173
+ expect(await syncDocs({ projectPath: dir, check: true }, io)).toEqual({ kind: 'ok' });
174
+
175
+ await syncDocs({ projectPath: dir }, io);
176
+ expect(read(dir)).toBe(doc);
177
+ fs.rmSync(dir, { recursive: true, force: true });
178
+ });
179
+
180
+ it('代码块内的表格样式行不被收拢(含块内空行)', async () => {
181
+ const doc =
182
+ `# Capabilities\n\n${HEADER}${dataRow('a', 'src/a.ts')}\n\n` +
183
+ `示例:\n\n\`\`\`\n| x | y |\n\n| z | w |\n\`\`\`\n`;
184
+ const dir = makeProject('fenced-blank-row', ['a.ts'], doc);
185
+
186
+ expect(await syncDocs({ projectPath: dir, check: true }, io)).toEqual({ kind: 'ok' });
187
+
188
+ await syncDocs({ projectPath: dir }, io);
189
+ expect(read(dir)).toBe(doc);
190
+ fs.rmSync(dir, { recursive: true, force: true });
191
+ });
192
+
193
+ it('两张空表相邻:一次收拢即干净(规则互相制造触发点,须跑到不动点)', () => {
194
+ // 规则①先吃掉两张空表之间的那个空行(两侧都是表格行),规则②在同一轮里
195
+ // 只看得到「表头+分隔行后面还有表格行」的前一张,收得掉后一张。不迭代就收不干净。
196
+ const first = normalizeCapabilitiesTableLayout(`${HEADER}\n${HEADER}`);
197
+
198
+ expect(first).toEqual({ content: '', blankLines: 1, emptyTables: 2 });
199
+ // 不动点:再跑一次零改动,`--check` 才不会修完还红
200
+ expect(normalizeCapabilitiesTableLayout(first.content)).toEqual({
201
+ content: '',
202
+ blankLines: 0,
203
+ emptyTables: 0,
204
+ });
205
+ });
206
+
207
+ it('收掉空表后不留三个以上连续换行(写模式收干净)', async () => {
208
+ const dir = makeProject(
209
+ 'no-triple-newline',
210
+ [],
211
+ `# Capabilities\n\n${HEADER}${dataRow('gone', 'src/gone.ts')}\n\n## 说明\n\n散文。\n`
212
+ );
213
+
214
+ await syncDocs({ projectPath: dir }, io);
215
+
216
+ const out = read(dir);
217
+ expect(out).not.toMatch(/\n{3,}/);
218
+ expect(out).toContain('## 说明');
219
+ expect(out).toContain('散文。');
220
+ expect(await syncDocs({ projectPath: dir, check: true }, io)).toEqual({ kind: 'ok' });
221
+ fs.rmSync(dir, { recursive: true, force: true });
222
+ });
223
+
224
+ it('围栏内示例行引用已删文件:随幽灵行一起删掉,且 check 收敛(取舍见实现注释)', async () => {
225
+ // 登记条目由 capabilities-parser 全文扫描得出(ADR-0009),块内行也算登记项;
226
+ // 只让幽灵行删除豁免围栏,这个示例会永远被报成已删模块且修不掉。
227
+ const doc =
228
+ `# Capabilities\n\n${HEADER}${dataRow('a', 'src/a.ts')}\n\n` +
229
+ `登记格式示例:\n\n\`\`\`markdown\n${HEADER}${dataRow('gone', 'src/gone.ts')}\n\`\`\`\n`;
230
+ const dir = makeProject('fenced-ghost-entry', ['a.ts'], doc);
231
+
232
+ expect(await syncDocs({ projectPath: dir, check: true }, io)).toMatchObject({ kind: 'fail' });
233
+ expect(io.outText()).toContain('src/gone.ts');
234
+
235
+ await syncDocs({ projectPath: dir }, io);
236
+
237
+ const out = read(dir);
238
+ expect(out).not.toContain('src/gone.ts');
239
+ expect(out).toContain(dataRow('a', 'src/a.ts'));
240
+ // 只吃掉引用已删文件的那一行,块内其余正文留着(不是「把围栏里所有行一起删」)
241
+ expect(out).toContain('```markdown\n' + HEADER);
242
+ expect(countBlankRowsInsideTable(out)).toBe(0);
243
+ expect(await syncDocs({ projectPath: dir, check: true }, io)).toEqual({ kind: 'ok' });
244
+ fs.rmSync(dir, { recursive: true, force: true });
245
+ });
246
+
247
+ it('CRLF 文档撤行:整行连行尾一起删除', async () => {
248
+ const doc = `# Capabilities\r\n\r\n${HEADER.replace(/\n/g, '\r\n')}${dataRow('a', 'src/a.ts')}\r\n${dataRow('gone', 'src/gone.ts')}\r\n`;
249
+ const dir = makeProject('crlf', ['a.ts'], doc);
250
+
251
+ await syncDocs({ projectPath: dir }, io);
252
+
253
+ const out = read(dir);
254
+ expect(out).not.toContain('src/gone.ts');
255
+ expect(out.endsWith(`${dataRow('a', 'src/a.ts')}\r\n`)).toBe(true);
256
+ expect(countBlankRowsInsideTable(out)).toBe(0);
257
+ fs.rmSync(dir, { recursive: true, force: true });
258
+ });
259
+ });