agentic-flow-kit 1.4.0 → 1.5.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 (130) hide show
  1. package/modules/hosts/claude/agents/implementer.md +5 -6
  2. package/modules/hosts/claude/agents/independent-reviewer.md +6 -6
  3. package/modules/hosts/claude/agents/ui-verifier.md +5 -5
  4. package/modules/hosts/claude/commands/wf-build.md +21 -21
  5. package/modules/hosts/claude/commands/wf-deploy.md +2 -2
  6. package/modules/hosts/claude/commands/wf-design.md +8 -8
  7. package/modules/hosts/claude/commands/wf-gate-checklist.md +8 -8
  8. package/modules/hosts/claude/commands/wf-maintain.md +12 -12
  9. package/modules/hosts/claude/commands/wf-new-task.md +9 -9
  10. package/modules/hosts/claude/commands/wf-pipeline-run.md +3 -3
  11. package/modules/hosts/claude/commands/wf-plan.md +10 -11
  12. package/modules/hosts/claude/commands/wf-review.md +4 -4
  13. package/modules/hosts/claude/commands/wf-source-sync-check.md +10 -10
  14. package/modules/hosts/claude/commands/wf-sync-hosts.md +9 -9
  15. package/modules/hosts/claude/commands/wf-test.md +5 -6
  16. package/modules/hosts/codex/agents/implementer.md +5 -6
  17. package/modules/hosts/codex/agents/independent-reviewer.md +6 -6
  18. package/modules/hosts/codex/agents/ui-verifier.md +5 -5
  19. package/modules/hosts/codex/commands/wf-build.md +21 -21
  20. package/modules/hosts/codex/commands/wf-deploy.md +2 -2
  21. package/modules/hosts/codex/commands/wf-design.md +8 -8
  22. package/modules/hosts/codex/commands/wf-gate-checklist.md +8 -8
  23. package/modules/hosts/codex/commands/wf-maintain.md +12 -12
  24. package/modules/hosts/codex/commands/wf-new-task.md +9 -9
  25. package/modules/hosts/codex/commands/wf-pipeline-run.md +3 -3
  26. package/modules/hosts/codex/commands/wf-plan.md +10 -11
  27. package/modules/hosts/codex/commands/wf-review.md +4 -4
  28. package/modules/hosts/codex/commands/wf-source-sync-check.md +10 -10
  29. package/modules/hosts/codex/commands/wf-sync-hosts.md +9 -9
  30. package/modules/hosts/codex/commands/wf-test.md +5 -6
  31. package/modules/hosts/cursor/agents/implementer.md +5 -6
  32. package/modules/hosts/cursor/agents/independent-reviewer.md +6 -6
  33. package/modules/hosts/cursor/agents/ui-verifier.md +5 -5
  34. package/modules/hosts/cursor/commands/wf-build.md +21 -21
  35. package/modules/hosts/cursor/commands/wf-deploy.md +2 -2
  36. package/modules/hosts/cursor/commands/wf-design.md +8 -8
  37. package/modules/hosts/cursor/commands/wf-gate-checklist.md +8 -8
  38. package/modules/hosts/cursor/commands/wf-maintain.md +12 -12
  39. package/modules/hosts/cursor/commands/wf-new-task.md +9 -9
  40. package/modules/hosts/cursor/commands/wf-pipeline-run.md +3 -3
  41. package/modules/hosts/cursor/commands/wf-plan.md +10 -11
  42. package/modules/hosts/cursor/commands/wf-review.md +4 -4
  43. package/modules/hosts/cursor/commands/wf-source-sync-check.md +10 -10
  44. package/modules/hosts/cursor/commands/wf-sync-hosts.md +9 -9
  45. package/modules/hosts/cursor/commands/wf-test.md +5 -6
  46. package/modules/hosts/omp/agents/implementer.md +5 -6
  47. package/modules/hosts/omp/agents/independent-reviewer.md +6 -6
  48. package/modules/hosts/omp/agents/ui-verifier.md +5 -5
  49. package/modules/hosts/opencode/agents/implementer.md +5 -6
  50. package/modules/hosts/opencode/agents/independent-reviewer.md +6 -6
  51. package/modules/hosts/opencode/agents/ui-verifier.md +5 -5
  52. package/modules/hosts/opencode/commands/wf-build.md +21 -21
  53. package/modules/hosts/opencode/commands/wf-deploy.md +2 -2
  54. package/modules/hosts/opencode/commands/wf-design.md +8 -8
  55. package/modules/hosts/opencode/commands/wf-gate-checklist.md +8 -8
  56. package/modules/hosts/opencode/commands/wf-maintain.md +12 -12
  57. package/modules/hosts/opencode/commands/wf-new-task.md +9 -9
  58. package/modules/hosts/opencode/commands/wf-pipeline-run.md +3 -3
  59. package/modules/hosts/opencode/commands/wf-plan.md +10 -11
  60. package/modules/hosts/opencode/commands/wf-review.md +4 -4
  61. package/modules/hosts/opencode/commands/wf-source-sync-check.md +10 -10
  62. package/modules/hosts/opencode/commands/wf-sync-hosts.md +9 -9
  63. package/modules/hosts/opencode/commands/wf-test.md +5 -6
  64. package/modules/hosts/trae/agents/implementer.md +5 -6
  65. package/modules/hosts/trae/agents/independent-reviewer.md +6 -6
  66. package/modules/hosts/trae/agents/ui-verifier.md +5 -5
  67. package/modules/hosts/trae/commands/wf-build.md +21 -21
  68. package/modules/hosts/trae/commands/wf-deploy.md +2 -2
  69. package/modules/hosts/trae/commands/wf-design.md +8 -8
  70. package/modules/hosts/trae/commands/wf-gate-checklist.md +8 -8
  71. package/modules/hosts/trae/commands/wf-maintain.md +12 -12
  72. package/modules/hosts/trae/commands/wf-new-task.md +9 -9
  73. package/modules/hosts/trae/commands/wf-pipeline-run.md +3 -3
  74. package/modules/hosts/trae/commands/wf-plan.md +10 -11
  75. package/modules/hosts/trae/commands/wf-review.md +4 -4
  76. package/modules/hosts/trae/commands/wf-source-sync-check.md +10 -10
  77. package/modules/hosts/trae/commands/wf-sync-hosts.md +9 -9
  78. package/modules/hosts/trae/commands/wf-test.md +5 -6
  79. package/modules/hosts/zcode/agents/implementer.md +5 -6
  80. package/modules/hosts/zcode/agents/independent-reviewer.md +6 -6
  81. package/modules/hosts/zcode/agents/ui-verifier.md +5 -5
  82. package/package.json +7 -2
  83. package/src/doctor.mjs +1 -1
  84. package/src/init.test.mjs +1 -1
  85. package/src/run-tests.mjs +15 -1
  86. package/src/sync-hosts.test.mjs +4 -4
  87. package/src/sync.test.mjs +1 -1
  88. package/templates/_agents/commands/build.md +21 -21
  89. package/templates/_agents/commands/deploy.md +2 -2
  90. package/templates/_agents/commands/design.md +8 -8
  91. package/templates/_agents/commands/gate-checklist.md +8 -8
  92. package/templates/_agents/commands/maintain.md +12 -12
  93. package/templates/_agents/commands/new-task.md +9 -9
  94. package/templates/_agents/commands/pipeline-run.md +3 -3
  95. package/templates/_agents/commands/plan.md +10 -11
  96. package/templates/_agents/commands/review.md +4 -4
  97. package/templates/_agents/commands/source-sync-check.md +10 -10
  98. package/templates/_agents/commands/sync-hosts.md +9 -9
  99. package/templates/_agents/commands/test.md +5 -6
  100. package/templates/_agents/roles/implementer.md +5 -6
  101. package/templates/_agents/roles/independent-reviewer.md +6 -6
  102. package/templates/_agents/roles/ui-verifier.md +5 -5
  103. package/templates/_agents/scripts/agg-delegations.cjs +0 -1
  104. package/templates/_agents/scripts/agg-delegations.test.mjs +2 -2
  105. package/templates/_agents/scripts/check-hygiene.mjs +2 -2
  106. package/templates/_agents/scripts/check-ledger-invariant.mjs +0 -1
  107. package/templates/_agents/scripts/check-loop.mjs +33 -10
  108. package/templates/_agents/scripts/check-loop.test.mjs +1 -1
  109. package/templates/_agents/scripts/commit-check-trigger.test.mjs +0 -1
  110. package/templates/_agents/scripts/confirm-doc.mjs +0 -1
  111. package/templates/_agents/scripts/ensure-board.mjs +2 -2
  112. package/templates/_agents/scripts/fill-intent.mjs +2 -2
  113. package/templates/_agents/scripts/fill-plan.mjs +1 -2
  114. package/templates/_agents/scripts/gen-wiki-board.mjs +1 -1
  115. package/templates/_agents/scripts/gen-workflow-dashboard.test.mjs +0 -2
  116. package/templates/_agents/scripts/gen-workflow-index.test.mjs +1 -1
  117. package/templates/_agents/scripts/gen-workflow-metrics.mjs +1 -1
  118. package/templates/_agents/scripts/kb-search.mjs +1 -2
  119. package/templates/_agents/scripts/kb-search.test.mjs +1 -1
  120. package/templates/_agents/scripts/pipeline-run-docs.mjs +76 -0
  121. package/templates/_agents/scripts/pipeline-run-run.mjs +63 -0
  122. package/templates/_agents/scripts/pipeline-run.mjs +8 -128
  123. package/templates/_agents/scripts/policy.mjs +7 -1
  124. package/templates/_agents/scripts/source-sync-check.mjs +2 -2
  125. package/templates/_agents/scripts/source-sync-check.test.mjs +1 -1
  126. package/templates/_agents/scripts/verify-wiki-consistency.mjs +0 -1
  127. package/templates/_agents/scripts/verify.test.mjs +2 -2
  128. package/templates/_agents/scripts/workflow-board-server.test.mjs +0 -1
  129. package/templates/_agents/scripts/workflow-enums.test.mjs +0 -1
  130. package/templates/_agents/scripts-test-exempt.txt +4 -1
@@ -0,0 +1,63 @@
1
+ // pipeline-run-run.mjs — run 存储层(2026-10-08 engine-quality-batch,L2 自 pipeline-run.mjs 拆出)
2
+ // ctxEnv / moduleList / runFileOf / loadRun / saveRun / emit / latestRunId / newRunId + 时间工具(nowIso/today/pad)——
3
+ // run 文件(.agents/cache/pipeline-runs/<id>.json)原子读写与事件流;run schema 零变化。
4
+ // 测试注入契约原样:PIPELINE_RUN_ROOT / PIPELINE_RUN_BIN / PIPELINE_RUN_GIT_BIN(ctxEnv)与
5
+ // PIPELINE_RUN_TODAY(today——时钟依赖消除锚,spec §测试注入契约)。
6
+ import fs from 'node:fs';
7
+ import path from 'node:path';
8
+
9
+ export const nowIso = () => new Date().toISOString();
10
+ export const today = () => process.env.PIPELINE_RUN_TODAY || nowIso().slice(0, 10);
11
+ export const pad = (n) => String(n).padStart(2, '0');
12
+
13
+ // ── 环境解析(测试注入点) ─────────────────────────────────────────────
14
+ export function ctxEnv(overrideRoot) {
15
+ const root = path.resolve(overrideRoot || process.env.PIPELINE_RUN_ROOT || process.cwd());
16
+ const bin = path.resolve(process.env.PIPELINE_RUN_BIN || path.join(root, '.agents', 'scripts'));
17
+ const gitPrefix = (process.env.PIPELINE_RUN_GIT_BIN || 'git').split(/\s+/).filter(Boolean);
18
+ return { root, bin, gitPrefix, runsDir: path.join(root, '.agents', 'cache', 'pipeline-runs') };
19
+ }
20
+
21
+ export function moduleList(ctx) {
22
+ try {
23
+ return fs.readFileSync(path.join(ctx.root, '.agents', 'workflow-modules.txt'), 'utf8')
24
+ .split(/\r?\n/).map((l) => l.trim()).filter((l) => l && !l.startsWith('#'));
25
+ } catch { return ['backend', 'frontend', 'ui', 'infra', 'integration', 'pipeline', 'wiki']; } // 夹具缺表时的回退默认(warning 由调用方打)
26
+ }
27
+
28
+ // ── run 文件(原子写;事件 append-only) ──────────────────────────────
29
+ export function runFileOf(ctx, runId) { return path.join(ctx.runsDir, `${runId}.json`); }
30
+
31
+ export function loadRun(ctx, runId) {
32
+ const f = runFileOf(ctx, runId);
33
+ if (!fs.existsSync(f)) return null;
34
+ try { return JSON.parse(fs.readFileSync(f, 'utf8')); } catch { return null; }
35
+ }
36
+
37
+ export function saveRun(ctx, run) {
38
+ fs.mkdirSync(ctx.runsDir, { recursive: true });
39
+ run.updatedAt = nowIso();
40
+ const f = runFileOf(ctx, run.runId);
41
+ const tmp = f + '.tmp';
42
+ fs.writeFileSync(tmp, JSON.stringify(run, null, 2) + '\n');
43
+ fs.renameSync(tmp, f);
44
+ }
45
+
46
+ export function emit(run, ev) { run.events.push({ t: nowIso(), ...ev }); }
47
+
48
+ export function latestRunId(ctx) {
49
+ if (!fs.existsSync(ctx.runsDir)) return null;
50
+ const ids = fs.readdirSync(ctx.runsDir).filter((f) => f.endsWith('.json')).map((f) => f.slice(0, -5)).sort();
51
+ for (let i = ids.length - 1; i >= 0; i--) {
52
+ const r = loadRun(ctx, ids[i]);
53
+ if (r && !['done', 'aborted'].includes(r.stopType)) return ids[i];
54
+ }
55
+ return ids[ids.length - 1] || null;
56
+ }
57
+
58
+ export function newRunId(requirement) {
59
+ const d = new Date();
60
+ const ascii = (requirement.toLowerCase().match(/[a-z0-9]{2,}/g) || []).slice(0, 3).join('-') || 'task';
61
+ const rand = Math.random().toString(36).slice(2, 6);
62
+ return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}-${ascii}-${rand}`;
63
+ }
@@ -19,9 +19,7 @@
19
19
  import fs from 'node:fs';
20
20
  import path from 'node:path';
21
21
  import { spawnSync } from 'node:child_process';
22
- import { fileURLToPath } from 'node:url';
23
22
 
24
- const SCRIPT_DIR = path.dirname(fileURLToPath(import.meta.url));
25
23
  const KINDS = ['require', 'fix', 'verify', 'review', 'deploy'];
26
24
  const LEVELS = ['L0', 'L1', 'L2', 'L3'];
27
25
  const TERMINAL = ['done', 'superseded', 'cancelled', 'closed'];
@@ -29,61 +27,13 @@ const FIX_CAP = 3;
29
27
  const GIT_NEVER_FLAGS = ['--no-verify', '-n']; // 不变量:任何 git 调用不得携带(防御性断言,正常路径不会拼出)
30
28
 
31
29
  function fail(msg, code = 1) { console.error('❌ ' + msg); process.exit(code); }
32
- const nowIso = () => new Date().toISOString();
33
- const today = () => process.env.PIPELINE_RUN_TODAY || nowIso().slice(0, 10);
34
- const pad = (n) => String(n).padStart(2, '0');
35
-
36
- // ── 环境解析(测试注入点) ─────────────────────────────────────────────
37
- function ctxEnv(overrideRoot) {
38
- const root = path.resolve(overrideRoot || process.env.PIPELINE_RUN_ROOT || process.cwd());
39
- const bin = path.resolve(process.env.PIPELINE_RUN_BIN || path.join(root, '.agents', 'scripts'));
40
- const gitPrefix = (process.env.PIPELINE_RUN_GIT_BIN || 'git').split(/\s+/).filter(Boolean);
41
- return { root, bin, gitPrefix, runsDir: path.join(root, '.agents', 'cache', 'pipeline-runs') };
42
- }
43
-
44
- function moduleList(ctx) {
45
- try {
46
- return fs.readFileSync(path.join(ctx.root, '.agents', 'workflow-modules.txt'), 'utf8')
47
- .split(/\r?\n/).map((l) => l.trim()).filter((l) => l && !l.startsWith('#'));
48
- } catch { return ['backend', 'frontend', 'ui', 'infra', 'integration', 'pipeline', 'wiki']; } // 夹具缺表时的回退默认(warning 由调用方打)
49
- }
50
30
 
51
- // ── run 文件(原子写;事件 append-only) ──────────────────────────────
52
- function runFileOf(ctx, runId) { return path.join(ctx.runsDir, `${runId}.json`); }
53
-
54
- function loadRun(ctx, runId) {
55
- const f = runFileOf(ctx, runId);
56
- if (!fs.existsSync(f)) return null;
57
- try { return JSON.parse(fs.readFileSync(f, 'utf8')); } catch { return null; }
58
- }
59
-
60
- function saveRun(ctx, run) {
61
- fs.mkdirSync(ctx.runsDir, { recursive: true });
62
- run.updatedAt = nowIso();
63
- const f = runFileOf(ctx, run.runId);
64
- const tmp = f + '.tmp';
65
- fs.writeFileSync(tmp, JSON.stringify(run, null, 2) + '\n');
66
- fs.renameSync(tmp, f);
67
- }
68
31
 
69
- function emit(run, ev) { run.events.push({ t: nowIso(), ...ev }); }
70
-
71
- function latestRunId(ctx) {
72
- if (!fs.existsSync(ctx.runsDir)) return null;
73
- const ids = fs.readdirSync(ctx.runsDir).filter((f) => f.endsWith('.json')).map((f) => f.slice(0, -5)).sort();
74
- for (let i = ids.length - 1; i >= 0; i--) {
75
- const r = loadRun(ctx, ids[i]);
76
- if (r && !['done', 'aborted'].includes(r.stopType)) return ids[i];
77
- }
78
- return ids[ids.length - 1] || null;
79
- }
80
-
81
- function newRunId(requirement) {
82
- const d = new Date();
83
- const ascii = (requirement.toLowerCase().match(/[a-z0-9]{2,}/g) || []).slice(0, 3).join('-') || 'task';
84
- const rand = Math.random().toString(36).slice(2, 6);
85
- return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}-${ascii}-${rand}`;
86
- }
32
+ import { nowIso, today, ctxEnv, moduleList, loadRun, saveRun, emit, latestRunId, newRunId } from './pipeline-run-run.mjs';
33
+ import { fmGet, placeholdersIn, sectionBody, validateDraftContent, closeoutComplete, summarizeDoc } from './pipeline-run-docs.mjs';
34
+ // 拆分(2026-10-08 engine-quality-batch):文档纯函数层 / run 存储层迁出本文件(判据注释随函数迁走,
35
+ // 对外导出面经下行 re-export 保持不变——stageBar/parseKV 仍在本文件);本文件 = CLI 编排层 + 状态机。
36
+ export { placeholdersIn, validateDraftContent, closeoutComplete } from './pipeline-run-docs.mjs';
87
37
 
88
38
  // ── 门执行(唯一子进程出口;记录真实退出码) ──────────────────────────
89
39
  function runNode(ctx, run, script, args) {
@@ -114,78 +64,8 @@ function runGit(ctx, run, args) {
114
64
  function readDoc(ctx, rel) {
115
65
  try { return fs.readFileSync(path.join(ctx.root, rel), 'utf8'); } catch { return null; }
116
66
  }
117
- function fmGet(text, key) {
118
- const m = text.split(/\r?\n/).find((l) => l.startsWith(`${key}:`));
119
- return m ? m.slice(key.length + 1).trim() : null;
120
- }
121
67
  function docState(ctx, rel) { const t = readDoc(ctx, rel); return t ? fmGet(t, '状态') : null; }
122
68
 
123
- // 占位符判定(复核 P1-3 收窄,2026-10-02):先剔除 code span(`…`)与引号串("…")——
124
- // 正文合法的命令语法占位(如 `next --delegated "<原话>"`)几乎总在 code span 内,
125
- // 模板实占位符(如 <为什么做;写明需求来源…>)从不包 code span;再匹配剩余裸尖括号。
126
- export function placeholdersIn(text) {
127
- const stripped = String(text)
128
- .replace(/^```[\s\S]*?^```$/gm, '') // 复核 P2-B:跨行 code fence 整块剔除(围栏内命令示例占位不属模板占位符)
129
- .replace(/`[^`\n]*`/g, '')
130
- .replace(/"[^"\n]*"/g, '');
131
- const hits = [];
132
- for (const re of [/<[^>\n]{1,60}>/g, /YYYY-MM-DD 用户/g]) {
133
- let m; while ((m = re.exec(stripped))) hits.push(m[0]);
134
- }
135
- return [...new Set(hits)].slice(0, 5);
136
- }
137
-
138
- function sectionBody(text, title) {
139
- const lines = text.split(/\r?\n/);
140
- const i = lines.findIndex((l) => l.trim() === `## ${title}` || l.trim() === `## ${title}(L1 微改动无实质内容可删本节,不硬填)` || l.trim().startsWith(`## ${title}`));
141
- if (i < 0) return null;
142
- const body = [];
143
- for (let j = i + 1; j < lines.length; j++) {
144
- if (/^##\s/.test(lines[j])) break;
145
- body.push(lines[j]);
146
- }
147
- return body.join('\n').trim();
148
- }
149
-
150
- export function validateDraftContent(text, kind, level) {
151
- const problems = [];
152
- if (!text) return ['文件不存在或为空'];
153
- const state = fmGet(text, '状态');
154
- if (!state) problems.push('frontmatter 缺「状态:」行');
155
- if (kind !== 'incident' && !fmGet(text, '级别')) problems.push('frontmatter 缺「级别:」行');
156
- const ph = placeholdersIn(text);
157
- if (ph.length) problems.push(`模板占位符残留:${ph.join('、')}`);
158
- const required = {
159
- intent: level === 'L1' ? ['背景与问题', '目标', '验收标准'] : ['背景与问题', '历史教训/防复发', '目标', '非目标', '约束', '验收标准'],
160
- spec: ['功能行为', '数据流', '系统改动', '约束遵守映射'],
161
- plan: level === 'L1' ? ['改动方案', '约束与风险', '验证计划'] : ['改动方案', '任务拆解', '执行顺序', '验证计划'],
162
- incident: ['时间线', '根因', '复盘三件套'],
163
- }[kind] || [];
164
- for (const sec of required) {
165
- const b = sectionBody(text, sec);
166
- if (b === null) { if (!(level === 'L1' && ['非目标', '约束', '任务拆解', '执行顺序'].includes(sec))) problems.push(`缺节:## ${sec}`); }
167
- else if (!b) problems.push(`节为空:## ${sec}`);
168
- }
169
- return problems;
170
- }
171
-
172
- export function closeoutComplete(text) {
173
- const body = sectionBody(text, '验收标准');
174
- if (body === null) return { ok: false, problems: ['缺「## 验收标准」节'] };
175
- const lines = body.split(/\r?\n/);
176
- const open = lines.filter((l) => /^\s*-\s\[\s\]\s/.test(l));
177
- // 复核 P2-6:证据冒号后须直接跟内容(非空白、非收括号)——「(证据:)」空值不算过
178
- const checkedNoEv = lines.filter((l) => /^\s*-\s\[x\]\s/.test(l) && !/证据[::][^)\s]/.test(l));
179
- const problems = [];
180
- if (open.length) problems.push(`未勾验收 ${open.length} 条`);
181
- if (checkedNoEv.length) problems.push(`已勾缺证据 ${checkedNoEv.length} 条`);
182
- return { ok: problems.length === 0, problems };
183
- }
184
-
185
- function summarizeDoc(text) {
186
- const body = text.split(/\r?\n/).filter((l) => l.trim() && !l.startsWith('---') && !/^状态:|^级别:|^日期:|^模块:|^备注:|^risk_level:/.test(l));
187
- return body.slice(0, 3).join(' / ').slice(0, 200);
188
- }
189
69
 
190
70
  // ── 工单构建 ───────────────────────────────────────────────────────────
191
71
  function wo(run, o) {
@@ -211,7 +91,7 @@ function stopConfirm(ctx, run, docRel, points, ledger) {
211
91
  printRun(ctx, run);
212
92
  process.exit(0);
213
93
  }
214
- function stopGateFail(ctx, run, stage, problems, exitHint) {
94
+ function stopGateFail(ctx, run, stage, problems) {
215
95
  run.workOrder = null;
216
96
  run.stopType = 'gate-fail';
217
97
  run.stage = stage;
@@ -318,11 +198,11 @@ function confirmGate(ctx, run, docRel, quote, to) {
318
198
  const tail = (r.stderr || r.stdout).split(/\r?\n/).filter(Boolean).slice(-6).join(' | ');
319
199
  return { ok: false, msg: `confirm-doc exit ${r.exit}:${tail}` };
320
200
  }
321
- emit(run, { type: 'confirm', doc: docRel, to: to || nextConfirmTarget(docState(ctx, docRel), docRel), source: quote ? 'chat-delegated' : 'tty', ...(quote ? { quote } : {}) });
201
+ emit(run, { type: 'confirm', doc: docRel, to: to || nextConfirmTarget(docState(ctx, docRel)), source: quote ? 'chat-delegated' : 'tty', ...(quote ? { quote } : {}) });
322
202
  return { ok: true };
323
203
  }
324
204
  // 语义上 confirm-doc 自行决定目标态(approved/done/fixed/closed);事件里记录结果态
325
- function nextConfirmTarget(curState, docRel) { return curState || 'approved'; }
205
+ function nextConfirmTarget(curState) { return curState || 'approved'; }
326
206
 
327
207
  // managedFaceCheck(复核 P2-4 修复 A′,2026-10-02 用户拍板):提交集命中 kit.json 台账面或包源
328
208
  // templates/_agents/ 时——包源环境(bin/flow-kit.mjs 可达)自动跑 sync 刷台账并把 kit.json 与 sync
@@ -86,7 +86,13 @@ export const POLICIES = {
86
86
  stageGateSince: '2026-09-29',
87
87
  riskLevelSince: '2026-10-01',
88
88
  verifySince: '2026-10-07',
89
- verifyDocSince: '2026-10-08', // 凭证按 doc 绑定生效日;v1-v5 无此键 → 两个消费方维持 v5 全局行为
89
+ // 凭证按 doc 绑定的生效**时刻**(ISO 8601,含 T/Z);v1-v5 无此键 → 两个消费方维持 v5 全局行为。
90
+ // 2026-10-09 verifydoc-anchor:值从日期 '2026-10-08' 升级为时刻——本仓 v6 上线当日(本地 17:37 =
91
+ // 09:37Z)之前 done 的单(selfmeasure 00:22Z / gate-roi-metrics 03:25Z)在日期粒度下被误纳入精确匹配、
92
+ // 产 3 条不可消退 advisory(它们关单时 --doc 机制尚不存在,无从补证);升级为时刻后按 done ts 精确比较,
93
+ // 机制上线前的存量单退回 v5 全局布尔(不误报、不伪造),与检查 15/18 的生效日锚同构。
94
+ // 消费方:检查 8 的 verifyDocInWindow(done ts ≥ 本值才启用精确匹配)。
95
+ verifyDocSince: '2026-10-08T09:37:35Z',
90
96
  },
91
97
  };
92
98
 
@@ -112,12 +112,12 @@ function printDiff(result) {
112
112
 
113
113
  const isMain = process.argv[1] && process.argv[1].endsWith('source-sync-check.mjs');
114
114
  if (isMain) {
115
- let jsonMode = false, diffMode = false, gateMode = false;
115
+ let jsonMode = false, gateMode = false;
116
116
  let pkgRoot = null, target = null;
117
117
  for (let i = 0; i < process.argv.length - 2; i++) {
118
118
  const a = process.argv[2 + i];
119
119
  if (a === '--json') jsonMode = true;
120
- else if (a === '--diff') diffMode = true;
120
+ else if (a === '--diff') { /* diff 为默认输出模式,无需置位 */ }
121
121
  else if (a === '--gate') gateMode = true;
122
122
  else if (a === '--pkg-root') pkgRoot = process.argv[2 + i + 1];
123
123
  else if (a === '--target') target = process.argv[2 + i + 1];
@@ -125,7 +125,7 @@ if (!SRC_ROOT) {
125
125
  drift: r.drift.map((d) => ({ rel: d.rel, pkgSha: d.pkgSha.slice(0, 8), tgtSha: d.tgtSha.slice(0, 8) })),
126
126
  }, null, 2);
127
127
  let parsed = null;
128
- try { parsed = JSON.parse(jsonOut); } catch {}
128
+ try { parsed = JSON.parse(jsonOut); } catch { /* 非 JSON 输出时 parsed 保持 null,S6 判失败路径 */ }
129
129
  check('S6 --json 输出可解析', parsed && typeof parsed === 'object' && Array.isArray(parsed.missing));
130
130
  }
131
131
 
@@ -125,7 +125,6 @@ for (const line of fs.readFileSync(path.join(WIKI, 'INDEX.md'), 'utf8').split(/\
125
125
  }
126
126
 
127
127
  const diff = (a, b) => [...a].filter((x) => !b.has(x));
128
- const eq = (a, b) => a.size === b.size && diff(a, b).length === 0;
129
128
 
130
129
  // ---- 1. 文件级三方比对 ----
131
130
  for (const [label, extra] of [
@@ -162,9 +162,9 @@ const run = (argv, opts = {}) => spawnSync(process.execPath, [VERIFY, ...argv],
162
162
  const rootC = mkfix();
163
163
  const abs = path.join(rootC, rel);
164
164
  const winStyle = rel.split('/').join(path.sep);
165
- const rC1 = run(['--test-cmd', `node ${mkCmd(0)}`, '--doc', winStyle], { cwd: rootC, env: { ...process.env, CHECK_LOOP_ROOT: rootC } });
165
+ run(['--test-cmd', `node ${mkCmd(0)}`, '--doc', winStyle], { cwd: rootC, env: { ...process.env, CHECK_LOOP_ROOT: rootC } });
166
166
  const eC1 = readLast(rootC);
167
- const rC2 = run(['--test-cmd', `node ${mkCmd(0)}`, '--doc', abs], { cwd: rootC, env: { ...process.env, CHECK_LOOP_ROOT: rootC } });
167
+ run(['--test-cmd', `node ${mkCmd(0)}`, '--doc', abs], { cwd: rootC, env: { ...process.env, CHECK_LOOP_ROOT: rootC } });
168
168
  const eC2 = readLast(rootC);
169
169
  check('场景 8③:反斜杠 / posix / 绝对路径三种写法落同一 doc 值(归一是地基)',
170
170
  eC1 && eC1.doc === rel && eC2 && eC2.doc === rel, `win=${JSON.stringify(eC1 && eC1.doc)} abs=${JSON.stringify(eC2 && eC2.doc)}`);
@@ -14,7 +14,6 @@ import { spawnSync } from 'node:child_process';
14
14
  import { fileURLToPath } from 'node:url';
15
15
  import { parseLoopHardBlocks, parseAcceptance, detectAlerts, parseRunFile, runCard, safeRunPath } from './workflow-board-server.mjs';
16
16
  import { computeFingerprint } from './confirm-doc.mjs';
17
- import { stageBar } from './pipeline-run.mjs';
18
17
 
19
18
  let pass = 0;
20
19
  let fail = 0;
@@ -2,7 +2,6 @@
2
2
  // 判据:① 真实单源文件解析 + 不变量通过 ② 坏数据(坏行/重复键/重复值/缺键/子集破/重叠)fail-loud
3
3
  // ③ 缺文件 fail-loud ④ sh 消费方同口径(sed 可取到全部 8 键)
4
4
  // 用法:node templates/_agents/scripts/workflow-enums.test.mjs(npm test 随跑)
5
- import fs from 'node:fs';
6
5
  import path from 'node:path';
7
6
  import { execSync } from 'node:child_process';
8
7
  import { fileURLToPath } from 'node:url';
@@ -7,4 +7,7 @@ ensure-board.mjs | 看板启动器(需真实端口/进程环境) | 无(工
7
7
  policy.mjs | 库件 | 被 check-loop.test.mjs 直接 import 覆盖
8
8
  stage-gates.mjs | 库件 | 被 check-loop.test.mjs 直接 import 覆盖(fill-*/confirm-doc.test 消费其行为)
9
9
  verify-wiki-consistency.mjs | wiki 一致性校验工具 | 无(工具豁免,后续批次评估补测)
10
- wiki-search.mjs | 检索库件 | 无(工具豁免,后续批次评估补测)
10
+ wiki-search.mjs | 检索库件 | 无(工具豁免,后续批次评估补测)
11
+ # 2026-10-08 engine-quality-batch:pipeline-run 三层拆分的库件层——纯函数/存储层由 pipeline-run.test.mjs 全量覆盖(断言零改动全过),单建同名测试属形式主义(plan 偏离留痕 ①)
12
+ pipeline-run-docs.mjs | 库件(文档纯函数层,2026-10-08 engine-quality-batch 拆分) | 由 pipeline-run.test.mjs 全量覆盖(断言零改动 29 组全过)
13
+ pipeline-run-run.mjs | 库件(run 存储层,同上拆分) | 由 pipeline-run.test.mjs 全量覆盖(含 PIPELINE_RUN_* 注入契约场景)