agentic-flow-kit 1.7.15 → 1.7.16

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 (101) hide show
  1. package/README.md +41 -3
  2. package/modules/hosts/claude/commands/wf-design.md +5 -4
  3. package/modules/hosts/claude/commands/wf-new-task.md +42 -21
  4. package/modules/hosts/claude/commands/wf-review.md +1 -1
  5. package/modules/hosts/claude/commands/wf-sync-hosts.md +7 -13
  6. package/modules/hosts/claude/commands/wf-test.md +1 -1
  7. package/modules/hosts/codex/commands/wf-design.md +5 -4
  8. package/modules/hosts/codex/commands/wf-new-task.md +42 -21
  9. package/modules/hosts/codex/commands/wf-review.md +1 -1
  10. package/modules/hosts/codex/commands/wf-sync-hosts.md +7 -13
  11. package/modules/hosts/codex/commands/wf-test.md +1 -1
  12. package/modules/hosts/cursor/commands/wf-design.md +5 -4
  13. package/modules/hosts/cursor/commands/wf-new-task.md +42 -21
  14. package/modules/hosts/cursor/commands/wf-review.md +1 -1
  15. package/modules/hosts/cursor/commands/wf-sync-hosts.md +7 -13
  16. package/modules/hosts/cursor/commands/wf-test.md +1 -1
  17. package/modules/hosts/opencode/commands/wf-design.md +5 -4
  18. package/modules/hosts/opencode/commands/wf-new-task.md +42 -21
  19. package/modules/hosts/opencode/commands/wf-review.md +1 -1
  20. package/modules/hosts/opencode/commands/wf-sync-hosts.md +7 -13
  21. package/modules/hosts/opencode/commands/wf-test.md +1 -1
  22. package/modules/hosts/trae/commands/wf-design.md +5 -4
  23. package/modules/hosts/trae/commands/wf-new-task.md +42 -21
  24. package/modules/hosts/trae/commands/wf-review.md +1 -1
  25. package/modules/hosts/trae/commands/wf-sync-hosts.md +7 -13
  26. package/modules/hosts/trae/commands/wf-test.md +1 -1
  27. package/package.json +1 -1
  28. package/src/cli.mjs +43 -4
  29. package/src/doctor.mjs +37 -1
  30. package/src/executor.mjs +245 -0
  31. package/src/executor.test.mjs +292 -0
  32. package/src/init.mjs +7 -0
  33. package/src/profiles.mjs +3 -0
  34. package/src/render.mjs +3 -3
  35. package/src/sync-hosts.mjs +37 -43
  36. package/src/sync-hosts.test.mjs +67 -56
  37. package/templates/.gitattributes +8 -0
  38. package/templates/AGENTS.md +1 -1
  39. package/templates/_agents/commands/design.md +5 -4
  40. package/templates/_agents/commands/new-task.md +42 -21
  41. package/templates/_agents/commands/review.md +1 -1
  42. package/templates/_agents/commands/sync-hosts.md +7 -13
  43. package/templates/_agents/commands/test.md +1 -1
  44. package/templates/_agents/control-surfaces.txt +1 -1
  45. package/templates/_agents/engine-lock.json +246 -0
  46. package/templates/_agents/lane-surfaces.txt +1 -1
  47. package/templates/_agents/level-hints.txt +30 -0
  48. package/templates/_agents/scripts/agg-delegations.test.mjs +5 -3
  49. package/templates/_agents/scripts/check-engine-integrity.mjs +55 -126
  50. package/templates/_agents/scripts/check-engine-integrity.test.mjs +33 -45
  51. package/templates/_agents/scripts/check-lane-surface.mjs +72 -23
  52. package/templates/_agents/scripts/check-lane-surface.test.mjs +66 -0
  53. package/templates/_agents/scripts/check-ledger-invariant.mjs +112 -14
  54. package/templates/_agents/scripts/check-ledger-invariant.test.mjs +5 -1
  55. package/templates/_agents/scripts/check-loop-rev.test.mjs +6 -4
  56. package/templates/_agents/scripts/check-loop.mjs +49 -41
  57. package/templates/_agents/scripts/check-loop.test.mjs +18 -13
  58. package/templates/_agents/scripts/check-metric-claims.mjs +4 -2
  59. package/templates/_agents/scripts/compact-ledgers.mjs +97 -0
  60. package/templates/_agents/scripts/compact-ledgers.test.mjs +162 -0
  61. package/templates/_agents/scripts/confirm-doc.mjs +40 -11
  62. package/templates/_agents/scripts/doctor.test.mjs +44 -1
  63. package/templates/_agents/scripts/edit-face-check.test.mjs +5 -4
  64. package/templates/_agents/scripts/fill-intent.mjs +2 -2
  65. package/templates/_agents/scripts/fixture-scripts.mjs +153 -0
  66. package/templates/_agents/scripts/fixture-scripts.test.mjs +107 -0
  67. package/templates/_agents/scripts/gate-checklist.mjs +4 -9
  68. package/templates/_agents/scripts/gate-checklist.test.mjs +2 -11
  69. package/templates/_agents/scripts/gen-workflow-dashboard.mjs +8 -11
  70. package/templates/_agents/scripts/gen-workflow-metrics.mjs +9 -33
  71. package/templates/_agents/scripts/git-merge-jsonl.mjs +63 -0
  72. package/templates/_agents/scripts/git-merge-jsonl.test.mjs +125 -0
  73. package/templates/_agents/scripts/ledger-doc-chain.test.mjs +166 -0
  74. package/templates/_agents/scripts/ledger-loader.mjs +108 -0
  75. package/templates/_agents/scripts/ledger-loader.test.mjs +131 -0
  76. package/templates/_agents/scripts/ledger-prune.mjs +96 -0
  77. package/templates/_agents/scripts/ledger-prune.test.mjs +120 -0
  78. package/templates/_agents/scripts/ledger-ts-monotonic.test.mjs +135 -0
  79. package/templates/_agents/scripts/level-criteria.mjs +232 -0
  80. package/templates/_agents/scripts/level-criteria.test.mjs +279 -0
  81. package/templates/_agents/scripts/pipeline-run.mjs +4 -2
  82. package/templates/_agents/scripts/policy.mjs +47 -0
  83. package/templates/_agents/scripts/stage-gates.mjs +4 -9
  84. package/templates/_agents/scripts/wf-journal.test.mjs +1 -1
  85. package/templates/_agents/scripts/wiki-search.test.mjs +5 -6
  86. package/templates/_agents/scripts/workflows-check.mjs +1 -1
  87. package/templates/_agents/workflows/pipeline-closing.md +4 -5
  88. package/templates/_githooks/pre-commit +3 -34
  89. package/templates/_githooks/pre-push +3 -3
  90. package/templates/workflow/README.md +11 -0
  91. package/modules/hosts/claude/commands/wf-source-sync-check.md +0 -89
  92. package/modules/hosts/codex/commands/wf-source-sync-check.md +0 -89
  93. package/modules/hosts/cursor/commands/wf-source-sync-check.md +0 -89
  94. package/modules/hosts/opencode/commands/wf-source-sync-check.md +0 -89
  95. package/modules/hosts/trae/commands/wf-source-sync-check.md +0 -90
  96. package/templates/_agents/commands/source-sync-check.md +0 -103
  97. package/templates/_agents/scripts/check-ledger.mjs +0 -109
  98. package/templates/_agents/scripts/check-ledger.test.mjs +0 -199
  99. package/templates/_agents/scripts/source-sync-check.mjs +0 -156
  100. package/templates/_agents/scripts/source-sync-check.test.mjs +0 -286
  101. package/templates/_agents/workflows/source-sync-repair.md +0 -30
@@ -47,10 +47,8 @@ function listMd(dir) {
47
47
  // pairsFor:权威源文件 → 薄适配 rel 列表(映射单源见 profiles.mjs#HOSTS.commandPrefix)
48
48
  // commands 权威源 → 带 commandPrefix 的宿主各一份(<dir>/commands/<prefix><name>.md)
49
49
  // roles 权威源 → 全部宿主 agents 各一份
50
- // hostDirOf:宿主 → 适配目录名。包源布局 = 宿主键(modules/hosts/opencode/…);装户布局 = HOSTS[h].dir
51
- // (项目根下 .opencode/…,带点)——2026-10-07 sync-hosts-target-fix 加装户支持时引入。
52
- // hostFilter(2026-10-09 sync-hosts-root-coverage):宿主级过滤(多根模式下「项目根宿主点」根只扫
53
- // 实际存在 dir 的宿主——不存在=没装该宿主点,不算缺失不算漂移)。
50
+ // hostDirOf:宿主 → 适配目录名。包源调用传入 (h) => h,配对落在 modules/hosts/<宿主键>/。
51
+ // hostFilter:宿主级过滤。调用方只扫实际存在的宿主目录时传入。
54
52
  function pairsFor(authRel, hostDirOf = (h) => h, hostFilter = null) {
55
53
  const out = [];
56
54
  const norm = authRel.split(path.sep).join('/');
@@ -74,12 +72,9 @@ function pairsFor(authRel, hostDirOf = (h) => h, hostFilter = null) {
74
72
 
75
73
  // diffHosts:权威源正文段 vs 薄适配正文段的漂移分析(B-b 语义;pure function)。
76
74
  // authorityRoot:权威源根(含 commands/ + roles/)
77
- // 多根对账(2026-10-09 sync-hosts-root-coverage):adapterRoots = [{root, hostDirOf, hostFilter?, label?}]——
78
- // 包源布局传两根(modules/hosts 宿主键形态 + 项目根 HOSTS.dir 形态宿主点);装户布局单根。
79
- // 向后兼容:旧单根入参 adaptersRoot/hostDirOf 归一为单元素数组。
80
- // 根因教训(engine-quality-round2 B1):包源布局此前只扫 modules/hosts,项目根宿主点(本仓 .zcode/)
81
- // 完全不在扫描面——bb69e19「81 对全对齐」声明漏掉 .zcode 三份(独立复核 P2-3 实证)。
82
- // hostDirOf:宿主 → 适配目录名(默认宿主键 = 包源布局;装户布局传 (h) => HOSTS[h].dir)
75
+ // adapterRoots = [{root, hostDirOf, hostFilter?, label?}]。只扫 modules/hosts。
76
+ // 向后兼容:旧单根入参 adaptersRoot/hostDirOf 归一为单元素数组。
77
+ // hostDirOf:宿主 → 适配目录名(默认宿主键)
83
78
  // 返回:{ drift, inSync, authorityMissing, adapterOrphans, faces }
84
79
  // drift 条目自带 root(applyForward 按它定位适配文件);faces = 对账面自描述行(防不可解释的「N 对」)
85
80
  export function diffHosts(opts) {
@@ -196,55 +191,35 @@ function applyForward({ authorityRoot }, drift) {
196
191
  export function syncHosts(args, pkgRoot) {
197
192
  let apply = false;
198
193
  let json = false;
194
+ let strict = false;
199
195
  let dir = null;
200
196
  for (let i = 0; i < args.length; i++) {
201
197
  const a = args[i];
202
198
  if (a === '--diff') apply = false;
203
199
  else if (a === '--apply') apply = true;
204
200
  else if (a === '--json') json = true;
201
+ else if (a === '--strict') strict = true;
205
202
  else if (a === '--dir') { dir = args[++i]; if (!dir) fail('--dir 缺少参数(目标项目根)'); }
206
203
  else fail(`未知选项:${a}(flow-kit sync-hosts --help)`);
207
204
  }
208
205
  if (!pkgRoot) fail('sync-hosts 缺少 pkgRoot(开发模式入口)');
209
206
 
210
- // 目标根:--dir > cwd > pkgRoot(兜底)。
211
- // 2026-10-07 sync-hosts-target-fix:此前恒用 pkgRoot——装户里跑 `flow-kit sync-hosts` 时 pkgRoot
212
- // 解析为**包安装目录**,于是 doctor §7.x 报漂移、照提示跑 `--apply` 会去改包源仓(装户自己的适配层纹丝不动)。
207
+ // 目标根:--dir > cwd > pkgRoot。只认包源仓(templates/_agents + modules/hosts)。
208
+ // 装户仓的宿主文件由 init / add-host 写入,不在这里把 .agents 再当成第二份权威源。
213
209
  const target = path.resolve(dir || process.cwd() || pkgRoot);
214
- // 布局判定(与 doctor.checkAdapterDrift 同口径):
215
- // 包源(templates/_agents 与 modules/hosts 同时存在)→ 权威源 = <target>/templates/_agents
216
- // 薄适配根(2026-10-09 sync-hosts-root-coverage 多根)= ① modules/hosts(宿主键形态,全宿主)
217
- // + ② 项目根 HOSTS.dir 实际存在的宿主点(如本仓 .zcode/——此前不在扫描面,bb69e19「81 对全对齐」
218
- // 漏掉其三份,独立复核 P2-3 实证);不存在 = 没装该宿主点,不算缺失。
219
- // 装户(其余)→ 权威源 = <target>/.agents,薄适配根 = <target>(宿主目录 .opencode/.trae/… 直接位于项目根)
220
- const isSourceRepo = fs.existsSync(path.join(target, 'templates', '_agents'))
221
- && fs.existsSync(path.join(target, 'modules', 'hosts'));
222
- const authorityRoot = isSourceRepo ? path.join(target, 'templates', '_agents') : path.join(target, '.agents');
223
- const adapterRoots = isSourceRepo
224
- ? [
225
- { root: path.join(target, 'modules', 'hosts'), hostDirOf: (h) => h, label: 'modules/hosts' },
226
- {
227
- root: target,
228
- hostDirOf: (h) => (HOSTS[h] && HOSTS[h].dir) || h,
229
- hostFilter: (h) => HOSTS[h] && fs.existsSync(path.join(target, HOSTS[h].dir)),
230
- label: '项目根宿主点',
231
- },
232
- ]
233
- : [{
234
- root: target,
235
- hostDirOf: (h) => (HOSTS[h] && HOSTS[h].dir) || h,
236
- hostFilter: (h) => HOSTS[h] && fs.existsSync(path.join(target, HOSTS[h].dir)),
237
- label: '项目根宿主点',
238
- }];
239
- if (!fs.existsSync(authorityRoot)) {
240
- fail(`未找到权威源目录:${authorityRoot}——目标根 ${target} 既非包源(无 templates/_agents)也非装户(无 .agents);用 --dir <项目根> 指定`);
210
+ const authorityRoot = path.join(target, 'templates', '_agents');
211
+ const hostsRoot = path.join(target, 'modules', 'hosts');
212
+ if (!fs.existsSync(authorityRoot) || !fs.existsSync(hostsRoot)) {
213
+ fail(`sync-hosts 只在包源仓运行(需要 templates/_agents 与 modules/hosts)。目标根 ${target} 不是包源仓。装户的宿主文件由 init / add-host 写入。`);
241
214
  }
242
- const layout = isSourceRepo ? '包源' : '装户';
215
+ const adapterRoots = [
216
+ { root: hostsRoot, hostDirOf: (h) => h, label: 'modules/hosts' },
217
+ ];
243
218
  const result = diffHosts({ authorityRoot, adapterRoots });
244
219
 
245
220
  if (apply && result.drift.length > 0) {
246
221
  const { synced } = applyForward({ authorityRoot }, result.drift);
247
- console.log(`▶ flow-kit sync-hosts --apply → ${target}(${layout}布局)`);
222
+ console.log(`▶ flow-kit sync-hosts --apply → ${target}(包源)`);
248
223
  console.log(` 对账面:${result.faces.join(' + ')}`);
249
224
  console.log(` 按权威源正文覆盖薄适配正文段 ${synced.length} 份(薄适配 frontmatter 不动):`);
250
225
  for (const rel of synced) console.log(` - ${rel}`);
@@ -256,8 +231,27 @@ export function syncHosts(args, pkgRoot) {
256
231
  if (json) {
257
232
  process.stdout.write(JSON.stringify(result, null, 2) + '\n');
258
233
  } else {
259
- console.log(`▶ flow-kit sync-hosts --diff → ${target}(${layout}布局)`);
234
+ console.log(`▶ flow-kit sync-hosts --diff → ${target}(包源)`);
260
235
  printDiff(result);
261
236
  }
237
+ // --strict(B4,2026-10-13):漂移**报告器**变机器门。
238
+ // 背景:source-sync-check 删除后,跨宿主正文漂移只剩人工跑一次 --diff,CI 里无任何调用点——
239
+ // 而改权威源要同步 N 份薄适配,人工 grep 易漏(本次评审前 10 份薄适配就带着漂移)。
240
+ // 默认仍返回 0(保持「报告器」语义,人工跑不因漂移而失败);CI 用 --strict 把漂移变成红。
241
+ // 口径:**只判「跑一次 --apply 就能归零」的两项**(正文漂移 + 权威源缺失)。
242
+ // 孤儿薄适配不判红——--apply 按设计不删它(可能是宿主特化/历史残留),
243
+ // 把它算红就是一条机器无法自愈的假红,按本仓「假阳性即噪声」纪律不能设成门(仍照常报告)。
244
+ if (strict) {
245
+ const fixable = result.drift.length + result.authorityMissing.length;
246
+ if (fixable > 0) {
247
+ console.error(`[跨宿主漂移 strict] 正文漂移 ${result.drift.length} · 权威源缺失 ${result.authorityMissing.length}`
248
+ + `${result.adapterOrphans.length ? `(另有孤儿薄适配 ${result.adapterOrphans.length} 份,按设计不判红)` : ''}`
249
+ + '——须先 flow-kit sync-hosts --apply 再提交');
250
+ return 1;
251
+ }
252
+ if (result.adapterOrphans.length) {
253
+ console.log(` ℹ️ 孤儿薄适配 ${result.adapterOrphans.length} 份(--apply 按设计不删,故 strict 不判红;确为残留请手工删)`);
254
+ }
255
+ }
262
256
  return 0;
263
257
  }
@@ -4,7 +4,7 @@
4
4
  // 判据:①全对齐 → inSync=28, drift 空 ②权威源改 → drift 列 ③apply → 正文一致,frontmatter 各自保留
5
5
  // ④薄适配 frontmatter 手改 → 不进 drift ⑤薄适配正文手改 → drift 列,apply 覆盖
6
6
  // ⑥薄适配缺失 → authorityMissing 列;apply 不自动创建
7
- // ⑦--json ⑧孤儿薄适配 ⑨装户布局(--dir / cwd 指向装户根 → 按 .agents ↔ 宿主目录比对)
7
+ // ⑦--json ⑧孤儿薄适配 ⑨非包源根拒绝(不把 .agents 当权威源)
8
8
  // 用法:node src/sync-hosts.test.mjs
9
9
  import fs from 'node:fs';
10
10
  import path from 'node:path';
@@ -78,7 +78,18 @@ syncHosts(process.argv.slice(2), root);
78
78
  return spawnSync(process.execPath, [driver, '--dir', fixtureRoot, ...extra], { encoding: 'utf8', ...opts });
79
79
  }
80
80
 
81
- // 不传 --dir 形态:把 cwd 设为 fixture(验「默认当前目录」解析;装户布局靠 cwd 判定)
81
+ // runSyncHostsExit:与 CLI 同口径**传播退出码**(cli.mjs 会 process.exit(syncHosts(...)))。
82
+ // 上面的 runSyncHosts driver 丢弃返回值,故退出码恒 0——不能用来断言 --strict 判红(B4)。
83
+ function runSyncHostsExit(fixtureRoot, extra = []) {
84
+ const driver = path.join(fixtureRoot, 'driver-exit.mjs');
85
+ W(driver, `import { syncHosts } from ${JSON.stringify(pathToFileURL(path.join(SRC_ROOT, 'sync-hosts.mjs')).href)};
86
+ const code = syncHosts(process.argv.slice(2), ${JSON.stringify(fixtureRoot)});
87
+ process.exit(typeof code === 'number' ? code : 0);
88
+ `);
89
+ return spawnSync(process.execPath, [driver, '--dir', fixtureRoot, ...extra], { encoding: 'utf8' });
90
+ }
91
+
92
+ // 不传 --dir 形态:把 cwd 设为 fixture(验「默认当前目录」解析)
82
93
  function runSyncHostsByCwd(fixtureRoot, extra = []) {
83
94
  const driver = path.join(fixtureRoot, 'driver.mjs');
84
95
  W(driver, `import { syncHosts } from ${JSON.stringify(pathToFileURL(path.join(SRC_ROOT, 'sync-hosts.mjs')).href)};
@@ -192,39 +203,23 @@ syncHosts(process.argv.slice(2), root);
192
203
  check('S8 apply 不删孤儿薄适配', fs.existsSync(path.join(fx, 'modules/hosts/opencode/commands/orphan.md')) && fs.existsSync(path.join(fx, 'modules/hosts/opencode/commands/wf-legacy.md')));
193
204
  }
194
205
 
195
- // ============ 场景 9:装户布局(.agents 为权威源 + 宿主目录为薄适配,无 templates/modules)============
196
- // 2026-10-07 sync-hosts-target-fix:此前目标根恒为 pkgRoot(= 包安装目录),装户跑 sync-hosts
197
- // 会去改包源仓。本场景钉住「--dir / cwd 指向装户根 → 按装户布局比对」。
206
+ // ============ 场景 9:非包源根拒绝(.agents 不再当权威源,宿主文件保持原样)============
198
207
  {
199
208
  const root = fs.mkdtempSync(path.join(os.tmpdir(), 'fk-synchosts-inst-'));
200
209
  W(path.join(root, '.agents/commands/test.md'),
201
210
  `---\ndescription: Test 阶段\n---\n\n# Test · v2\n\n权威源正文 test v2\n`);
202
- W(path.join(root, '.opencode/commands/wf-test.md'),
203
- `---\ndescription: Test · opencode\n---\n\n# Test · v1\n\n旧正文 test v1\n`);
204
- W(path.join(root, '.trae/commands/wf-test.md'),
205
- `---\nname: wf-test\ndescription: Test · trae\n---\n\n# Test · v1\n\n旧正文 test v1\n`);
211
+ const hostBody = `---\ndescription: Test · opencode\n---\n\n# Test · v1\n\n旧正文 test v1\n`;
212
+ W(path.join(root, '.opencode/commands/wf-test.md'), hostBody);
206
213
 
207
- // 9a:--dir 指向装户根 → 布局判定「装户」,列出 2 处漂移
208
214
  const r1 = runSyncHosts(root, ['--diff']);
209
215
  const out1 = r1.stdout + r1.stderr;
210
- check('S9 装户布局:--dir 指向装户根 → 头部标「装户布局」', /装户布局/.test(out1), out1);
211
- check('S9 装户布局:列出 2 处正文漂移', /正文段漂移(2/.test(out1), out1);
212
- // 未装宿主(claude/cursor/codex)目录不存在 → 不算「缺失」(否则装户刷屏 + apply 恒 exit 1)
213
- check('S9 装户布局:未装宿主不进「权威源声明但薄适配缺失」', !/权威源声明但薄适配缺失/.test(out1), out1);
216
+ check('S9 非包源根 --diff:拒绝且点明只在包源仓运行', r1.status !== 0 && /只在包源仓运行/.test(out1), out1);
217
+ check('S9 非包源根 --diff:不改宿主文件', R(path.join(root, '.opencode/commands/wf-test.md')) === hostBody, out1);
214
218
 
215
- // 9b:不传 --dir(cwd = 装户根)→ 同样命中装户布局(旧行为会误指包源)
216
- const r2 = runSyncHostsByCwd(root, ['--diff']);
219
+ const r2 = runSyncHostsByCwd(root, ['--apply']);
217
220
  const out2 = r2.stdout + r2.stderr;
218
- check('S9 cwd 默认:装户布局解析正确(不再误指包源)', /装户布局/.test(out2) && !/包源布局/.test(out2), out2);
219
-
220
- // 9c:apply → 正文段对齐、薄适配 frontmatter 保留
221
- const r3 = runSyncHosts(root, ['--apply']);
222
- const out3 = r3.stdout + r3.stderr;
223
- const bodyOf = (p) => { const t = R(p); const m = t.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/); return t.slice(m ? m[0].length : 0); };
224
- check('S9 装户布局 apply:opencode 正文段对齐', bodyOf(path.join(root, '.opencode/commands/wf-test.md')) === bodyOf(path.join(root, '.agents/commands/test.md')), out3);
225
- check('S9 装户布局 apply:trae frontmatter 保留(name: wf-test)', /^---\nname: wf-test/m.test(R(path.join(root, '.trae/commands/wf-test.md'))), out3);
226
- // 未装宿主不计缺失 → apply 摘要「权威源缺失:0」且 exit 0
227
- check('S9 装户布局 apply:未装宿主不计缺失 → 权威源缺失 0 且 exit 0', /权威源缺失:0/.test(out3) && r3.status === 0, `status=${r3.status}\n${out3}`);
221
+ check('S9 cwd 为装户根 --apply:同样拒绝', r2.status !== 0 && /只在包源仓运行/.test(out2), out2);
222
+ check('S9 cwd 为装户根 --apply:宿主文件未被改写', R(path.join(root, '.opencode/commands/wf-test.md')) === hostBody, out2);
228
223
  }
229
224
 
230
225
  {
@@ -237,43 +232,59 @@ syncHosts(process.argv.slice(2), root);
237
232
  check('实仓薄适配无缺失无正文漂移', r.authorityMissing.length === 0 && r.drift.length === 0, `missing=${r.authorityMissing.length} drift=${r.drift.length} ${sample}`);
238
233
  }
239
234
 
240
- // ============ 场景 10-12:包源布局多根对账(2026-10-09 sync-hosts-root-coverage,B1)============
241
- // 根因教训(bb69e19「81 对全对齐」漏 .zcode 三份,独立复核 P2-3):包源布局此前只扫 modules/hosts,
242
- // 项目根 HOSTS.dir 形态宿主点(本仓 .zcode/)不在扫描面。三场景钉住:漂移可检出 / apply 可修复且
243
- // frontmatter 保留 / 对账面自描述行在案。
235
+ // ============ 场景 10:包源仓不扫描项目根宿主点(.zcode 等不是第二对账面)============
244
236
  {
245
- // S10:包源 fixture + 项目根 .zcode/agents 漂移(正文旧 + frontmatter zcode 风格)→ --diff 报漂移
246
237
  const fx = mkFixture();
247
- W(path.join(fx, '.zcode/agents/implementer.md'),
248
- `---\nname: implementer\ndescription: zcode 本仓风格\n---\n\n# Implementer · v0\n\n旧版正文 implementer v0\n`);
238
+ const zcodeBody = `---\nname: implementer\ndescription: zcode 本仓风格\n---\n\n# Implementer · v0\n\n旧版正文 implementer v0\n`;
239
+ W(path.join(fx, '.zcode/agents/implementer.md'), zcodeBody);
249
240
  const r = runSyncHosts(fx, ['--diff']);
250
241
  const out = r.stdout + r.stderr;
251
- check('S10 项目根宿主点漂移:--diff 报 .zcode/agents/implementer.md',
252
- out.includes('.zcode/agents/implementer.md') && /正文段漂移/.test(out), out.slice(0, 600));
253
- check('S10 对账面自描述:含「项目根宿主点(1 宿主)」', /对账面:.*项目根宿主点(1 宿主)/.test(out), out.split('\n').slice(0, 4).join('\n'));
254
-
255
- // S11:--apply 修复项目根漂移——正文覆盖为权威源、frontmatter 保留、漂移归零
256
- const r2 = runSyncHosts(fx, ['--apply']);
257
- const out2 = r2.stdout + r2.stderr;
258
- const synced = /- \.zcode\/agents\/implementer\.md/.test(out2);
259
- const fixed = R(path.join(fx, '.zcode/agents/implementer.md'));
260
- check('S11 --apply 同步清单含 .zcode 条目', synced, out2.slice(0, 500));
261
- check('S11 --apply 正文覆盖 + frontmatter 保留',
262
- fixed.includes('权威源正文 implementer v1') && fixed.includes('description: zcode 本仓风格'),
263
- fixed.slice(0, 200));
264
- check('S11 --apply 后漂移归零', /正文漂移:\s*0/.test(out2), out2.slice(-300));
242
+ check('S10 对账面只有 modules/hosts', /对账面:modules\/hosts/.test(out) && !/项目根宿主点/.test(out), out.split('\n').slice(0, 6).join('\n'));
243
+ check('S10 项目根 .zcode 漂移不入报告', !out.includes('.zcode/agents/implementer.md'), out.slice(0, 500));
244
+ runSyncHosts(fx, ['--apply']);
245
+ check('S10 --apply 不改写项目根 .zcode', R(path.join(fx, '.zcode/agents/implementer.md')) === zcodeBody);
265
246
  }
266
247
 
248
+ // ============ 场景 11:--strict 把漂移报告器变成机器门(B4)============
249
+ // 背景:source-sync-check 删除后,跨宿主正文漂移只剩人工跑一次 --diff,CI 里无任何调用点——
250
+ // 而改权威源要同步 N 份薄适配,人工 grep 易漏(本仓评审前就带着 10 份漂移)。
251
+ // 默认 --diff 仍恒 exit 0(人工跑不因漂移失败),--strict 才判红,供 CI 当门。
267
252
  {
268
- // S12:装户布局 faces 自描述(回归钉住——装户单根 label=项目根宿主点,行为不变)
269
- const fx = fs.mkdtempSync(path.join(os.tmpdir(), 'fk-synchosts-adopter-'));
270
- W(path.join(fx, '.agents/roles/implementer.md'),
271
- `---\ndescription: Implementer 角色契约\n---\n\n# Implementer · v1\n\n权威源正文 implementer v1\n`);
272
- W(path.join(fx, '.zcode/agents/implementer.md'),
273
- `---\nname: implementer\ndescription: zcode\n---\n\n# Implementer · v1\n\n权威源正文 implementer v1\n`);
274
- const r = runSyncHostsByCwd(fx, ['--diff']);
275
- const out = r.stdout + r.stderr;
276
- check('S12 装户布局:faces 单根自描述 + 对齐 1 对', /对账面:项目根宿主点(1 宿主)/.test(out) && /正文对齐:\s*1\s*对/.test(out), out.slice(0, 400));
253
+ const fx = mkFixture();
254
+ // 先 --apply 归零:夹具出厂状态未必干净(默认就可能带孤儿/缺失),
255
+ // 「--strict 在无漂移时 exit 0」这句话得先有个干净盘面才成立。
256
+ runSyncHosts(fx, ['--apply']);
257
+ const clean = runSyncHostsExit(fx, ['--diff', '--strict']);
258
+ check('S11 无漂移 + --strict → exit 0', clean.status === 0, `status=${clean.status} ${(clean.stdout + clean.stderr).slice(0, 300)}`);
259
+
260
+ // 制造一处薄适配正文漂移
261
+ const anyAdapter = fs.readdirSync(path.join(fx, 'modules/hosts'), { withFileTypes: true })
262
+ .filter((d) => d.isDirectory()).map((d) => d.name);
263
+ let broke = null;
264
+ for (const host of anyAdapter) {
265
+ const cmdDir = path.join(fx, 'modules/hosts', host, 'commands');
266
+ if (!fs.existsSync(cmdDir)) continue;
267
+ const f = fs.readdirSync(cmdDir).find((x) => x.endsWith('.md'));
268
+ if (!f) continue;
269
+ const abs = path.join(cmdDir, f);
270
+ fs.appendFileSync(abs, '\n手改一行,权威源没有这段。\n');
271
+ broke = `${host}/commands/${f}`;
272
+ break;
273
+ }
274
+ check('S11 夹具确实制造了漂移', !!broke, '未找到可改的薄适配');
275
+
276
+ const loose = runSyncHostsExit(fx, ['--diff']);
277
+ check('S11 有漂移但默认 --diff 仍 exit 0(报告器语义不变)', loose.status === 0, `status=${loose.status}`);
278
+ check('S11 默认 --diff 仍报告漂移', (loose.stdout + loose.stderr).includes('正文段漂移'), loose.stdout.slice(0, 300));
279
+
280
+ const strict = runSyncHostsExit(fx, ['--diff', '--strict']);
281
+ const sout = strict.stdout + strict.stderr;
282
+ check('S11 有漂移 + --strict → exit 1(CI 机器门)', strict.status === 1, `status=${strict.status}`);
283
+ check('S11 strict 报错点名修法(sync-hosts --apply)', sout.includes('--apply') && sout.includes('strict'), sout.slice(-300));
284
+
285
+ runSyncHosts(fx, ['--apply']);
286
+ const after = runSyncHostsExit(fx, ['--diff', '--strict']);
287
+ check('S11 --apply 归零后 --strict 回到 exit 0', after.status === 0, `status=${after.status}`);
277
288
  }
278
289
 
279
290
  console.log(`\n合计: PASS ${pass} / FAIL ${failCount}`);
@@ -4,3 +4,11 @@
4
4
  .githooks/* text eol=lf
5
5
  .agents/hooks/local-pre-commit text eol=lf
6
6
  *.ps1 text eol=crlf
7
+
8
+ # 台账并集合并(2026-10-12 ledger-merge-driver):确认台账是「尾部追加 + 多人/多 worktree 并行」形态,
9
+ # 默认三方合并会把它当文本冲突,人工解的常见错法是「整取一侧」——静默丢掉另一侧的确认行,
10
+ # 门禁事后无从发现。本 driver 把合并降级为确定性并集去重:两侧行全保留,无冲突可解。
11
+ # 需配 driver(flow-kit init 自动配):git config merge.jsonl-union.driver "node .agents/scripts/git-merge-jsonl.mjs %O %A %B"
12
+ # **故意不加 text eol=lf**:给既有 .jsonl 加 text 规则会让下次提交时 git 重新规范化换行 → 台账 blob 字节变化
13
+ # → check-ledger-invariant 的 append-only 前缀不变量判为「台账重写」而硬拦。台账换行归一由 driver 自身负责。
14
+ .agents/*.jsonl merge=jsonl-union
@@ -23,7 +23,7 @@
23
23
 
24
24
  ### 门禁与提交
25
25
 
26
- - `.githooks/`(经 `core.hooksPath` 挂载,本地 clone 后执行 `git config core.hooksPath .githooks`):pre-commit(闭环配对 / 泳道完整性 / wiki 台账 / 规则面预算 / 双源一致性 / managed 台账快检 / 敏感信息扫描与条件构建)、pre-push(闭环断档扫描)、commit-msg、post-commit、pre-merge-commit。
26
+ - `.githooks/`(经 `core.hooksPath` 挂载,本地 clone 后执行 `git config core.hooksPath .githooks`):pre-commit(闭环配对 / 泳道完整性 / wiki 台账 / 规则面预算 / 确认台账不变量 / 敏感信息扫描与条件构建)、pre-push(闭环断档扫描)、commit-msg、post-commit、pre-merge-commit。
27
27
  - **CI 远端门(2026-10-07 起)**:`.github/workflows/kit-ci.yml`(owned)在 GitHub runner 复跑 `node .agents/scripts/verify.mjs`(云端兜底本地钩子);非 GitHub 装户可删,等价门 = 同入口命令 + 服务端分支策略(人工一次性配置,机器不校验)。
28
28
  - **`git commit` / `git merge` / `git push` 三处一律禁 `--no-verify`**——被拦说明产出不合规,按提示修完原路重试。
29
29
  - 项目专属门禁挂 `.agents/hooks/local-pre-commit`。装户五条硬规则(配对、验收、确认留痕、敏感信息、双源台账)与 `audit` 档见 `workflow/README.md`「硬规则」。
@@ -29,10 +29,11 @@ next: .agents/commands/build.md
29
29
  ## 1. 执行
30
30
 
31
31
  1. 确认同名入口文档已批准:新需求为 approved intent,修复为已确认的 incident 草稿;否则拒绝,分别回 `plan.md` / `maintain.md`(2026-09-30 起机器强制:fill-spec / confirm-doc 对前置未过直接拒绝 exit 2、不落盘不记账)。
32
- 2. 级别判断(对照 AGENTS.md 第 3 条):
33
- - **L1**(实现级改动,未命中 L2/L3)→ 走快车道,省略 spec,直接跳 `next: build.md` 起草 Quick-Plan
34
- - **L2**(改规则 / 契约:编码权威 / 共享契约 / 既有接口语义 / 全局横切口径,闭集见 `new-task.md` §级别判断)→ 必须有 spec
35
- - **L3**(数据与运行时结构:schema / 迁移 SQL / DI 链 / 认证与中间件管线)→ 必须有 spec + **新会话独立复核**
32
+ 2. 级别判断(对照 AGENTS.md 第 3 条;判据单源 = `.agents/scripts/level-criteria.mjs`,**本文件只承载流程映射,不复述判据闭集**):
33
+ - **L1**(未命中 L2/L3)→ 快车道:省略 spec,直接跳 `next: build.md` 起草 Quick-Plan
34
+ - **L2**(触达面闭集见单源 `L2_SURFACES`)→ 必须有 spec
35
+ - **L3**(结构面闭集见单源 `L3_SURFACES`)→ 必须有 spec + **新会话独立复核**
36
+ - 判哪一档:逐条对照单源的 `L2_SURFACES` / `L3_SURFACES` / `L1_NEGATIVES`,不要凭记忆——判据只读单源一处
36
37
  3. 起草 spec:
37
38
  - **填空工具先跑**:`node .agents/scripts/fill-spec.mjs --level <L1|L2|L3> --topic <主题> --output workflow/specs/<date>-<主题>.md`——输出含 frontmatter 5 字段 + 5 节正文(功能行为/数据流/系统改动/约束遵守映射/风险评估)的草稿;AI 据此填实
38
39
  - 复制 `workflow/specs/_TEMPLATE.md` → `workflow/specs/YYYY-MM-DD-<主题>.md`(与入口文档同名)
@@ -28,7 +28,21 @@ next: 按阶段路由
28
28
 
29
29
  ## 2. 风险定级(第 0 步,先定级再路由)
30
30
 
31
- 动工前先按下表定风险级 L0-L3(就高不就低;判据细则见下节「级别判断」),级别即风险级,决定走哪条泳道——确认放事前,还是审计补事后:
31
+ **第 0 步先取机器面下界(必跑,不是可选提示)**:
32
+
33
+ ```bash
34
+ flow-kit route --files <预计改动面…> --kind require|fix|verify|review|deploy
35
+ ```
36
+
37
+ - **不给 `--files` 就拿不到路径下限**——机器面此时只能按 L1 起步并在降级栏点名,等于白跑;
38
+ 故定级前先把**预计改动面**列出来(不必精确到最终 diff,给到目录/文件前缀即可)。
39
+ - 跑完**再**按 §4 逐条语义判级:机器只给「就高不就低 + 路径下限」,「一处定义、多处消费」仍要你判。
40
+ - **确实跳过**时必须写明理由(入口文档备注或当场告知用户)——判低的后果由两道门兜:
41
+ 起草面 `check-lane-surface` 命中路径下限无合格入口即拦,提交面同门再拦一次。
42
+ **诚实边界**:机器**无法**发现你没跑 route——定级发生在改动面确定之前,没有可比对的记录面,
43
+ 详见 [ARCHITECTURE §5](../ARCHITECTURE.md) 与 CHANGELOG 1.7.16 B3 条。
44
+
45
+ 动工前按下表定风险级 L0-L3(就高不就低;判据细则见下节「级别判断」),级别即风险级,决定走哪条泳道——确认放事前,还是审计补事后:
32
46
 
33
47
  | 泳道 | 级别 | 确认与审计口径 |
34
48
  |------|------|---------------|
@@ -41,6 +55,10 @@ next: 按阶段路由
41
55
 
42
56
  ## 3. 路由判断
43
57
 
58
+ <!-- route-kinds: require=plan.md | fix=maintain.md | verify=test.md | review=review.md | deploy=deploy.md -->
59
+ <!-- ↑ 本行是 kind→入口指令的**机器单源**:`flow-kit route` 读它得出「该读哪个 md」,不再在包内自带一份映射。
60
+ 增删 kind 或改入口文件名只改这一行(判据单源 level-criteria.mjs 的纪律同源)。 -->
61
+
44
62
  - **自动化驱动(并列入口,可选)**:一句话全程走 [pipeline-run.md](pipeline-run.md)——状态机驱动+工单协议+原话代录,与下述手动路由二选一,同一任务不混用
45
63
  - **新需求 / 功能**:从 `plan.md` 进,立 **intent**(`workflow/intents/`)
46
64
  - **修复类任务 / 事故**:从 `maintain.md` 进,立 **incident**(`workflow/incidents/`);incident 在 L1+ 即 **intent 等价物**(check-loop 认 incident≡intent),不必另立 intent。先检索同类历史(`node .agents/scripts/kb-search.mjs "<关键词>" --scope workflow --type incidents,plans`),有同类先读其历史三件套;再按级别走:
@@ -53,28 +71,31 @@ next: 按阶段路由
53
71
 
54
72
  ## 4. 级别判断(AGENTS.md 第 3 条)
55
73
 
56
- | 级别 | 改什么 | 流程 |
57
- |------|--------|------|
58
- | L0 | 文档/样式微调(无行为影响) | 直接 commit,豁免 intent |
59
- | L1 | **实现级改动**(未命中 L2/L3) | 快车道:液态草稿(.zcode/drafts) → 实现 → 固化(`solidify-task.mjs`)——用户确认后带 `--delegated "<原话>"` 执行;无确认来源只迁移不落账 |
60
- | L2 | **规则 / 契约**(一处改、多处依赖) | 入口文档(intent / incident) + spec + plan 三件套 |
61
- | L3 | **数据与运行时结构**(schema / 迁移 SQL / DI 链 / 认证与中间件管线) | 同 L2 + spec 新会话独立复核 |
62
-
63
- > 级别判定同上表"改什么"列;混合改动按最高档定级。
64
-
65
- **L2 触达面**(闭集,命中任一即 L2;本体不改但改其输入域 / 调用点校验同样命中):
66
-
67
- 1. **编码权威**:项目内「一处生成、多处消费」的编码 / 命名 / 取号规则(编码模板、序列发生器、命名空间与去重约束——具体清单按项目 AGENTS.md)
68
- 2. **共享契约**:跨模块共享的基类 / DTO 形状、跨模块公共接口签名
69
- 3. **既有接口语义**:既有参数或端点的行为变化(由失效变生效、默认值或钳制口径改变)
70
- 4. **全局横切口径**:错误响应出口、分页与校验口径、聚合投影键
74
+ > **判据单源 = [`.agents/scripts/level-criteria.mjs`](../scripts/level-criteria.mjs)**,本节**不复述判据**。
75
+ > 要看判据全文,或要机器可判的部分(路径下限 / 就高不就低 / 混档取高),直接:
76
+ >
77
+ > ```bash
78
+ > flow-kit route --files <改动文件…> # 定级 + 下一阶段 + 该读哪个 md
79
+ > ```
80
+ >
81
+ > 单源导出:`LEVELS` `LEVEL_MEANING`(档位语义) / `L2_SURFACES`(四类触达面闭集) / `L3_SURFACES`(结构面) /
82
+ > `L1_NEGATIVES`(判低红线) / `SELF_CHECK`(自查句) / `assessLevel` `hintLevelFor` `parseLevelHints` `routeAdvice`。
83
+ >
84
+ > 路径下限清单(装户 owned,默认空):`.agents/level-hints.txt`,每行 `L2 <ERE>` / `L3 <ERE>`,登记「哪些路径一碰就至少是此档」。
71
85
 
72
- > **负例(落 L1)**:纯页面表现 / 文案 / 布局 / 交互实现;纯新增端点或参数且既有行为不变;单模块内部重构且无对外契约变化。
73
- > **自查句**:能否列出 ≥2 个受影响的消费方(模块 / 端点 / 页面)?能 → L2。
74
- > 先例:本仓 `workflow/specs/`、`workflow/intents/` 下同类历史(kb 检索主题词)。
86
+ **本表只承载流程**(「改什么」判据以单源为准,别在本表增删判据):
75
87
 
76
- > **L1 是默认档**:红线全不勾即 L1,无需正列举——判级只回答「是否命中 L2 四类或 L3 结构面」。
77
- > **L3 的「DI 链」按组合根与运行时管线理解**:DI 注册、中间件/认证管线、服务构造器依赖变更(先例:本仓 workflow/ 留痕中无 schema 变更仍定 L3 的同类历史)。
88
+ | 级别 | 单源语义(摘要) | 流程 |
89
+ |------|-----------------|------|
90
+ | L0 | 文档/样式微调(无行为影响) | 直接 commit,豁免 intent |
91
+ | L1 | 实现级改动(未命中 L2/L3) | 快车道:液态草稿(.zcode/drafts) → 实现 → 固化(`solidify-task.mjs`)——用户确认后带 `--delegated "<原话>"` 执行;无确认来源只迁移不落账 |
92
+ | L2 | 规则 / 契约(一处改、多处依赖) | 入口文档(intent / incident) + spec + plan 三件套 |
93
+ | L3 | 数据与运行时结构(结构面闭集见单源 `L3_SURFACES`) | 同 L2 + spec 新会话独立复核 |
94
+
95
+ > 混合改动按最高档定级(就高不就低);**L1 是默认档**——判级只回答「是否命中单源 `L2_SURFACES` 或
96
+ > `L3_SURFACES`」,负例(`L1_NEGATIVES`)命中即不得升档;自查句:`SELF_CHECK`。
97
+ > 机器兜得住的只有「就高不就低」与路径下限;「一处定义、多处消费」是**语义**判定,由你按单源逐条判,
98
+ > 漏判由 lane-surface 触达面门在提交面兜。先例:`workflow/specs/`、`workflow/intents/` 下同类历史(kb 检索主题词)。
78
99
 
79
100
  ## 5. intent 豁免(避免小改动也走完整闭环)
80
101
 
@@ -45,7 +45,7 @@ next: .agents/commands/build.md(仅 P0 / P1 未清时;清零后经用户确
45
45
  - **Create/Update 校验同口径**:Create 已有校验 Update 必须同口径;被引用的标识符字段禁改
46
46
  - **查询分页与状态语义**:分页参数范围校验 + 服务层钳制;非法状态与不存在分离(按项目统一错误口径,如 400 / 404)
47
47
  - **spec 承诺的断言落地**:spec §测试列出的用例 / 断言须真落到测试或验证脚本;「写进 spec」不等于「跑得起来」,且常驻断言禁写成随时间增长的行数常量
48
- - **跨宿主薄适配正文漂移**:改 `templates/_agents/{commands,roles}/*.md` 后必须跑 `flow-kit sync-hosts --apply` 单向同步注册表内全部宿主薄适配(`modules/hosts/<h>/{agents,commands}/*.md`);装户视角由 `flow-kit doctor` §6.7 检查(包源环境 §6.7 skipped)
48
+ - **跨宿主薄适配正文漂移**:包源仓改 `templates/_agents/{commands,roles}/*.md` 后跑 `flow-kit sync-hosts --apply`,单向同步 `modules/hosts/<h>/{agents,commands}/*.md`。装户由 `flow-kit doctor` §6.7 检查(包源环境跳过);装户刷新宿主文件用 `flow-kit add-host <宿主> --force`(`sync` 不更新宿主适配,`sync-hosts` 不在装户根运行)
49
49
 
50
50
  ## 3. P2 建议(提醒,不拦合入)
51
51
 
@@ -19,27 +19,22 @@ next: .agents/commands/build.md(漂移属 build 改权威源未同步导致的
19
19
 
20
20
  # Sync-Hosts · 跨宿主适配层正文段同步
21
21
 
22
- > 改权威源(`templates/_agents/{commands,roles}/*.md`)后薄适配(`modules/hosts/<h>/{agents,commands}/*.md`)要同步——薄适配正文 = 权威源正文,frontmatter 各自保留宿主特化(commands 层文件名 = 宿主命令名,opencode / trae 同用 `wf-` 前缀,单源见 `src/profiles.mjs#HOSTS.commandPrefix`;trae 另有 `name: wf-X`,zcode/omp 各自原描述)。
23
- > 装户视角:`flow-kit doctor` §7.x 跑同名检查(仅装户,包源环境跳过——包源下永远是 drift);**修漂移用同一条命令**
24
- > `flow-kit sync-hosts --apply`——2026-10-07 起按**目标根**自动判布局(含 `templates/_agents` + `modules/hosts` → 包源:
25
- > 比 `templates/_agents` ↔ `modules/hosts/<宿主键>/`;含 `.agents` → 装户:比 `.agents` ↔ 项目根下 `<宿主点目录>/`),
26
- > 目标根取 `--dir <目录>` > 当前目录。
22
+ > 本命令只在包源仓运行(需要 `templates/_agents` 与 `modules/hosts`)。改权威源(`templates/_agents/{commands,roles}/*.md`)后薄适配(`modules/hosts/<h>/{agents,commands}/*.md`)要同步——薄适配正文 = 权威源正文,frontmatter 各自保留宿主特化(commands 层文件名 = 宿主命令名,opencode / trae 同用 `wf-` 前缀,单源见 `src/profiles.mjs#HOSTS.commandPrefix`;trae 另有 `name: wf-X`,zcode/omp 各自原描述)。
23
+ > 装户的宿主文件由 `init` / `add-host` 写入。装户漂移由 `flow-kit doctor` §6.7 报告(包源环境跳过);刷新用 `flow-kit add-host <宿主> --force`。`flow-kit sync` 不更新宿主适配。
27
24
 
28
25
  ## 1. 何时跑
29
26
 
30
27
  - 改 `templates/_agents/commands/*.md` 正文后(11 个 commands 文件)
31
28
  - 改 `templates/_agents/roles/*.md` 正文后(3 个 roles 文件)
32
- - 装户跑 `flow-kit doctor` 报"跨宿主薄适配正文漂移 N 对" WARN 时
33
- - 不跑:仅改 frontmatter;改 trae 钩子/规则;改包源其他文件
29
+ - 不跑:装户仓(本命令会拒绝);仅改 frontmatter;改 trae 钩子/规则;改包源其他文件
34
30
 
35
31
  ## 2. 怎么跑
36
32
 
37
33
  ### 2.1 默认 `--diff`(仅报告)
38
34
 
39
35
  ```
40
- node bin/flow-kit.mjs sync-hosts --diff # 包源仓(在包源根跑)
36
+ node bin/flow-kit.mjs sync-hosts --diff # 包源仓(在包源根跑,或 --dir <包源根>)
41
37
  node bin/flow-kit.mjs sync-hosts --json # 机器可读
42
- flow-kit sync-hosts --diff # 装户仓(在装户根跑;或用 --dir <项目根> 指定)
43
38
  ```
44
39
 
45
40
  输出三类:
@@ -59,9 +54,8 @@ node bin/flow-kit.mjs sync-hosts --apply
59
54
  ### 2.3 自验
60
55
 
61
56
  ```
62
- npm test # 含 sync-hosts.test.mjs 8 场景
63
- node bin/flow-kit.mjs doctor # 装户跑 §7.x PASS;包源跑 §7.x skipped
64
- sh .agents/scripts/check-loop.sh # Windows 无 sh 时 doctor 已探测分流
57
+ npm test # 含 sync-hosts.test.mjs
58
+ node bin/flow-kit.mjs doctor # 包源环境 §6.7 skipped
65
59
  ```
66
60
 
67
61
  ## 3. 边界(不要做)
@@ -76,7 +70,7 @@ sh .agents/scripts/check-loop.sh # Windows 无 sh 时 doctor 已
76
70
 
77
71
  - trae 钩子(`modules/hosts/trae/hooks/*.cjs`)— 独立演进的工程件
78
72
  - trae 规则(`modules/hosts/trae/rules/*.md`)— 同上
79
- - 包源 .agents/scripts/*.cjs(pre-commit 等钩子)— 同步由 `flow-kit sync` 走 managed 台账负责
73
+ - 门禁脚本与钩子(`templates/_agents/scripts`、`templates/_githooks`)— 由 `flow-kit sync` 按 managed 台账下发,不走 sync-hosts
80
74
 
81
75
  ## 5. 相关留痕
82
76
 
@@ -35,7 +35,7 @@ next: L1 关单结束 ;L2/L3 上 prod 时 → .agents/commands/deploy.md
35
35
  项目测试命令 # 自动化测试
36
36
  项目类型检查命令 # 前端类型检查/构建(涉及前端时跑)
37
37
  node .agents/scripts/verify-wiki-consistency.mjs # 触及 wiki/ 时跑(exit 1 即先修台账再继续:跑 gen-wiki-board.mjs 补索引/看板;pre-commit 已按增量自动拦,此行用于改完即验)
38
- npx agentic-flow-kit doctor # §6.5 delegations + §6.6 owned 漂移 + §6.7 跨宿主薄适配正文漂移(装户环境;包源环境 §6.7 skipped)
38
+ npx agentic-flow-kit doctor # §6.5 delegations + §6.6 owned 漂移 + §6.7 跨宿主薄适配正文漂移(装户环境;漂移用 add-host <宿主> --force 刷新。包源环境 §6.7 skipped)
39
39
  ```
40
40
 
41
41
  > **环境注记**:本地服务占用构建产物导致编译失败、多会话并行时「谁跑静态门 / 提交谁先停服务」等约定——如有,见项目注记 `.agents/notes/runtime-env.md` §2,跑静态门前先过一眼。
@@ -15,7 +15,7 @@
15
15
  # 不宣称关闭「刻意绕过」。事后对质面 = 台账 + git 历史 + check-engine-integrity 的基线比对。
16
16
  #
17
17
  # 覆盖哪些面(为什么各条目都在控制面上):
18
- # 引擎判据本体(包源 + 装副本两面都列——单边改动同样要过门)
18
+ # 引擎判据本体(同一份清单随模板下发:包源仓命中 templates/ 前缀,装户仓命中 .agents/ 前缀)
19
19
  ^templates/_agents/scripts/
20
20
  ^\.agents/scripts/
21
21
  # git 钩子面(本地唯一机器门的编排)与钩子内的门禁实现件