agentic-flow-kit 1.1.5 → 1.1.7

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-flow-kit",
3
- "version": "1.1.5",
3
+ "version": "1.1.7",
4
4
  "description": "AI-Native 闭环工作流 + wiki 知识层脚手架——flow-kit init 一条命令为新项目装好 .agents 工作流引擎(阶段命令/角色契约/门禁钩子/kb 检索/看板/规则面预算)+ workflow 文档闭环 + wiki 知识库,装完自包含、零运行时依赖",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -382,12 +382,17 @@ for (const plan of docFiles('plans')) {
382
382
  // 样例引用豁免(2026-10-02 caliber-convergence 假阳性消除,先例=检查 18 行尾归一):命中位于行内代码
383
383
  // (反引号包裹)或围栏代码块内 = 引用样例而非未填占位符,不报;正文裸占位符照报——真占位符均为
384
384
  // 裸文本(模板正文无反引号包裹),检测面不缩。
385
+ // 日期显示格式豁免(2026-10-06 check2-datetime-literal-exempt):`YYYY-MM-DD HH:mm(:ss)` 是功能
386
+ // 自实现的显示格式描述(文档叙述「匹配时间列显示为 YYYY-MM-DD HH:mm」属常态——cancel-export
387
+ // intent/plan 实证 2 条 advisory、2026-10-06 loop-audit intent 现场复现),非未填占位——行内剔除
388
+ // 后再判;真占位(`日期: YYYY-MM-DD`,无时间后缀)不含该形态仍拦。只豁免实证形态,变体(斜杠日期
389
+ // /十二小时制等)出现假阳性再扩。
385
390
  const stripSamples = (lines) => {
386
391
  let inFence = false;
387
392
  return lines.map((line) => {
388
393
  if (/^\s*(```|~~~)/.test(line)) { inFence = !inFence; return ''; }
389
394
  if (inFence) return '';
390
- return line.replace(/`[^`]*`/g, '');
395
+ return line.replace(/`[^`]*`/g, '').replace(/YYYY-MM-DD\s+HH:mm(:ss)?/g, '');
391
396
  });
392
397
  };
393
398
  const groups = new Map(); // file -> [ "行号:内容" ](首现序)
@@ -515,7 +520,12 @@ for (const inc of docFiles('incidents')) {
515
520
  {
516
521
  const cmdFiles = () => (readdirOrNull(path.join(ROOT, '.agents', 'commands')) || [])
517
522
  .filter((f) => f.endsWith('.md')).map((f) => `.agents/commands/${f}`);
518
- const textOf = (rel) => linesOf(path.join(ROOT, rel)) || [];
523
+ // existsSync 守卫(2026-10-06-check19-entry-enoent 同类):AGENTS.md 等可合法缺失(调用方按空数组
524
+ // 判定本就预期缺失态),fail-loud fs 读下按缺省跳过、不再响亮出账;其余调用方路径另有上游守卫
525
+ const textOf = (rel) => {
526
+ const p = path.join(ROOT, rel);
527
+ return fs.existsSync(p) ? (linesOf(p) || []) : [];
528
+ };
519
529
  for (const role of ['implementer', 'independent-reviewer', 'ui-verifier']) {
520
530
  const rolePath = `.agents/roles/${role}.md`;
521
531
  if (!fs.existsSync(path.join(ROOT, rolePath))) {
@@ -567,7 +577,10 @@ for (const inc of docFiles('incidents')) {
567
577
  // --- 6. 阶段索引同步 [warning] ---
568
578
  for (const cmd of ['plan', 'design', 'build', 'test', 'deploy', 'maintain', 'review']) {
569
579
  for (const doc of ['AGENTS.md', '.agents/commands/new-task.md']) {
570
- const text = linesOf(path.join(ROOT, doc));
580
+ // existsSync 守卫(2026-10-06-check19-entry-enoent 同类):两文件可合法缺失(下方 text 判空本就
581
+ // 预期缺失态),fail-loud fs 读下按空跳过、不再响亮出账
582
+ const docPath = path.join(ROOT, doc);
583
+ const text = fs.existsSync(docPath) ? linesOf(docPath) : null;
571
584
  if (text && !text.some((l) => l.includes(`.agents/commands/${cmd}.md`))) {
572
585
  warnings.push(`- [WARN 阶段索引漂移] ${doc} 缺 ${cmd} 指令索引(两处阶段表须同步维护)`);
573
586
  }
@@ -1204,7 +1217,12 @@ runCheck16({ ROOT, ENUMS, docFiles, fmGet, inSet, isTracked, linesOf, readdirOrN
1204
1217
  // 协作道豁免(2026-09-30 hybrid-governance-risk-lanes):入口 L0/L1 的审批顺序倒置(如 plan 先于
1205
1218
  // intent approved——「动手后确认」)是异步审计泳道语义,非流程违规;入口文件缺失(纯台账历史行 /
1206
1219
  // incident 侧)不豁免,维持既有判据。
1207
- const ilvlB = fmGet(path.join(ROOT, WF, 'intents', `${base}.md`), '级别');
1220
+ // existsSync 守卫(2026-10-06-check19-entry-enoent):incident 闭环主题无同名 intent,「读空判级」
1221
+ // 惯用法(缺文件→级别空→不豁免,判定面不变)在 fail-loud fs 读(2026-10-05-gitout-fail-open)下
1222
+ // 每次推送响亮出账 N 条 ENOENT 噪声——守卫跳过读取,语义与上注释一致;同款先例 entryConfirmed19
1223
+ // 与下方 spec 读取。
1224
+ const iabsB = path.join(ROOT, WF, 'intents', `${base}.md`);
1225
+ const ilvlB = fs.existsSync(iabsB) ? fmGet(iabsB, '级别') : '';
1208
1226
  if (ilvlB === 'L0' || ilvlB === 'L1') continue;
1209
1227
  const earliest = seq.map((k) => rec[k]).sort()[0];
1210
1228
  if (!(earliest.slice(0, 10) >= since)) continue;
@@ -813,6 +813,28 @@ check('检查2 plan 真实未填占位(日期: YYYY-MM-DD)→ 仍报模板
813
813
  r2.status === 0 && outOf(r2).includes('模板未填'), `exit=${r2.status}\n${outOf(r2)}`);
814
814
  rmfix(T);
815
815
  }
816
+ // ---- 场景 45c:检查 2——日期显示格式字面量豁免;纯占位仍报(2026-10-06 check2-datetime-literal-exempt)----
817
+ // 日期取 2026-09-26(< 确认门 v1 锚 2026-09-27,豁免检查 15 存量面——沿 5x 块先例),避免 hard 干扰本断言
818
+ {
819
+ const T = mkfix();
820
+ w(T, 'workflow/intents/2026-09-26-dt1.md', INTENT('dt1', '状态: done\n级别: L1\n日期: 2026-09-26',
821
+ '\n匹配时间列格式简化为 YYYY-MM-DD HH:mm;同款括号形态(YYYY-MM-DD HH:mm)与秒级 YYYY-MM-DD HH:mm:ss 均为格式描述。\n'));
822
+ w(T, 'workflow/plans/2026-09-26-dt1.md', PLAN('dt1', '状态: done\n级别: L1'));
823
+ const r1 = run(T);
824
+ check('检查2 裸写 YYYY-MM-DD HH:mm(:ss) 显示格式描述 → 不报模板未填',
825
+ r1.status === 0 && !outOf(r1).includes('模板未填'), `exit=${r1.status}\n${outOf(r1)}`);
826
+ rmfix(T);
827
+ }
828
+ {
829
+ const T = mkfix();
830
+ w(T, 'workflow/intents/2026-09-26-dt2.md', INTENT('dt2', '状态: done\n级别: L1\n日期: 2026-09-26',
831
+ '\n匹配时间列格式简化为 YYYY-MM-DD HH:mm(合法格式描述);另有真占位 日期: YYYY-MM-DD 在同文档。\n'));
832
+ w(T, 'workflow/plans/2026-09-26-dt2.md', PLAN('dt2', '状态: done\n级别: L1', '\n- 日期: YYYY-MM-DD\n'));
833
+ const r2 = run(T);
834
+ check('检查2 同文档混真占位(无时间后缀)→ 格式描述豁免不吞真占位,仍报',
835
+ r2.status === 0 && outOf(r2).includes('模板未填'), `exit=${r2.status}\n${outOf(r2)}`);
836
+ rmfix(T);
837
+ }
816
838
  // ---- 场景 46:检查 6——薄适配正文含 .agents/roles/<role>.md 引用 → 不报 Adapter 断线 ----
817
839
  {
818
840
  const T = mkfix();
@@ -2614,5 +2636,31 @@ w(T, 'workflow/intents/2026-09-12-deep.md', INTENT('deep', '状态: draft\n级
2614
2636
  rmfix(T);
2615
2637
  }
2616
2638
 
2639
+ // ---- 场景:检查 19 判据 B——台账 approved 行在、入口 intent 缺件(incident 闭环主题)→ 无 ENOENT 出账,顺序判定不放松(2026-10-06-check19-entry-enoent)----
2640
+ {
2641
+ const ledgerRows = (specTs, planTs) => [
2642
+ { doc: 'workflow/specs/2026-10-06-noent.md', stage: 'approved', ts: specTs },
2643
+ { doc: 'workflow/plans/2026-10-06-noent.md', stage: 'approved', ts: planTs },
2644
+ ];
2645
+ // ① 顺序合规(specs 先于 plans):exit 0,且裸 fixture 全程无「文档读取异常(ENOENT)」出账——
2646
+ // 修复前「读空判级」惯用法在 fail-loud fs 读下对缺件主题每次响亮出账(实仓 12 条/推送);
2647
+ // 同类读空点(AGENTS.md / new-task.md,检查 6)一并被裸 fixture 钉住
2648
+ const T = mkfix();
2649
+ w(T, '.agents/kit.json', JSON.stringify({ policyVersion: 2 }));
2650
+ writeLedger(T, ledgerRows('2026-10-06T10:00:00Z', '2026-10-06T11:00:00Z'));
2651
+ let r = run(T);
2652
+ check('检查 19 判据 B:入口 intent 缺件 → 无 ENOENT 噪声且 exit 0',
2653
+ r.status === 0 && !outOf(r).includes('文档读取异常'), `exit=${r.status}\n${outOf(r)}`);
2654
+ rmfix(T);
2655
+ // ② 顺序倒置(plans 先于 specs):入口缺件不豁免,照报「审批顺序倒置」——守卫不放松判定
2656
+ const T2 = mkfix();
2657
+ w(T2, '.agents/kit.json', JSON.stringify({ policyVersion: 2 }));
2658
+ writeLedger(T2, ledgerRows('2026-10-06T11:00:00Z', '2026-10-06T10:00:00Z'));
2659
+ r = run(T2);
2660
+ check('检查 19 判据 B:入口 intent 缺件 → 顺序倒置照报(守卫不放松判定)',
2661
+ r.status === 0 && outOf(r).includes('审批顺序倒置'), `exit=${r.status}\n${outOf(r)}`);
2662
+ rmfix(T2);
2663
+ }
2664
+
2617
2665
  console.log(`\n合计: PASS ${pass} / FAIL ${fail}`);
2618
2666
  process.exit(fail ? 1 : 0);