agentic-flow-kit 0.2.0 → 0.2.1
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/README.md +3 -2
- package/modules/gates/dotnet-ca/check-architecture.sh +14 -10
- package/modules/hosts/trae/commands/wf-build.md +14 -14
- package/modules/hosts/trae/commands/wf-deploy.md +13 -13
- package/modules/hosts/trae/commands/wf-design.md +13 -13
- package/modules/hosts/trae/commands/wf-maintain.md +13 -13
- package/modules/hosts/trae/commands/wf-new-task.md +13 -13
- package/modules/hosts/trae/commands/wf-plan.md +13 -13
- package/modules/hosts/trae/commands/wf-review.md +13 -13
- package/modules/hosts/trae/commands/wf-test.md +14 -14
- package/modules/hosts/trae/hooks/post-edit-check.cjs +10 -0
- package/modules/hosts/trae/hooks/pre-shell-check.cjs +14 -4
- package/modules/hosts/trae/hooks/resolve-shell.cjs +30 -21
- package/modules/hosts/trae/rules/beautify-input-chinese.md +6 -6
- package/modules/hosts/trae/rules/git-commit-message.md +10 -10
- package/package.json +10 -2
- package/src/add-gate.mjs +8 -1
- package/src/add-host.mjs +4 -0
- package/src/cli.mjs +4 -3
- package/src/doctor.mjs +9 -2
- package/src/render.mjs +2 -0
- package/src/sync.mjs +20 -4
- package/src/sync.test.mjs +40 -1
- package/templates/AGENTS.md +2 -2
- package/templates/_agents/board/index.html +382 -382
- package/templates/_agents/board/marked.min.js +6 -6
- package/templates/_agents/cache/kb-index.json +1 -1
- package/templates/_agents/commands/build.md +1 -1
- package/templates/_agents/commands/design.md +1 -1
- package/templates/_agents/commands/maintain.md +1 -1
- package/templates/_agents/commands/new-task.md +73 -73
- package/templates/_agents/commands/plan.md +2 -2
- package/templates/_agents/commands/test.md +1 -1
- package/templates/_agents/hooks/check-pairing-incremental.sh +30 -29
- package/templates/_agents/hooks/commit-check.cjs +6 -1
- package/templates/_agents/scripts/agg-delegations.cjs +35 -18
- package/templates/_agents/scripts/agg-delegations.test.mjs +95 -0
- package/templates/_agents/scripts/check-loop.sh +6 -0
- package/templates/_agents/scripts/check-loop.test.sh +1042 -1042
- package/templates/_agents/scripts/commit-check-trigger.test.mjs +94 -0
- package/templates/_agents/scripts/ensure-board.ps1 +1 -1
- package/templates/_agents/scripts/gen-wiki-board.mjs +13 -3
- package/templates/_agents/scripts/gen-wiki-board.test.mjs +22 -0
- package/templates/_agents/scripts/gen-workflow-index.mjs +7 -2
- package/templates/_agents/scripts/gen-workflow-index.test.mjs +27 -0
- package/templates/_agents/scripts/gen-workflow-metrics.mjs +17 -3
- package/templates/_agents/scripts/gen-workflow-metrics.test.mjs +21 -0
- package/templates/_agents/scripts/kb-search.mjs +2 -1
- package/templates/_agents/scripts/rule-budget.sh +8 -2
- package/templates/_agents/scripts/verify-wiki-consistency.mjs +6 -1
- package/templates/_agents/scripts/workflow-board-server.mjs +245 -244
- package/templates/_githooks/commit-msg +4 -2
- package/templates/_githooks/pre-push +32 -32
- package/templates/workflow/README.md +2 -2
- package/templates/workflow/intents/_TEMPLATE.md +40 -40
- package/templates/workflow/specs/_TEMPLATE.md +41 -41
package/README.md
CHANGED
|
@@ -46,7 +46,7 @@ modules/gates/ 可选门禁模块(dotnet-ca:Clean Architecture 参考
|
|
|
46
46
|
|
|
47
47
|
**两态文件模型**:`.agents/kit.json` 记录 managed(引擎件,随包升级)与 owned(项目内容,永不覆盖)清单及 sha256;`doctor` 会校验漂移。已存在的文件 init 保守跳过(`--force` 覆盖)。
|
|
48
48
|
|
|
49
|
-
**升级语义(sync)**:managed 文件三方比对(台账 sha / 磁盘 sha / 新版渲染 sha)——未改动 → 直接覆盖新版;本地已改 → 跳过并报告(`--force` 才覆盖,git diff
|
|
49
|
+
**升级语义(sync)**:managed 文件三方比对(台账 sha / 磁盘 sha / 新版渲染 sha)——未改动 → 直接覆盖新版;本地已改 → 跳过并报告(`--force` 才覆盖,git diff 自查差异;跳过件的台账保持包侧基线,后续每次 sync 持续报告,不会在下次升级被静默覆盖——消除报告的办法:`--force` 覆盖,或把本地内容改回与新版一致);改动恰好等于新版 → 视为已最新。包内新增文件自动安装;包内已删文件仅报告不删盘;缺失的 managed 文件自动恢复。INDEX / wiki 看板等生成器目标不比对 sha,收尾重跑生成器走锚点重写。门禁模块(add-gate 装入)归项目所有,sync 永不覆盖。add-host 对已存在的宿主文件保守跳过且不入台账——后续 sync 不升级(仅报告「已存在未入台账」),要纳入包管理用 `--force` 覆盖。owned 件归项目所有、sync 永不覆盖;其台账哈希仅记账不约束,sync 每次按盘面自愈刷新(手改后无须手工对账),add-gate 接线 local-pre-commit 后同步刷新其记账。
|
|
50
50
|
|
|
51
51
|
## 设计原则
|
|
52
52
|
|
|
@@ -59,4 +59,5 @@ modules/gates/ 可选门禁模块(dotnet-ca:Clean Architecture 参考
|
|
|
59
59
|
|
|
60
60
|
- [x] v0.1.0:init(flags 模式)+ doctor + 4 宿主适配 + dotnet-ca 门禁模块
|
|
61
61
|
- [x] v0.2.0:sync 升级(未动覆盖 / 已改跳过报告 + `--force` / 生成器锚点重写)+ add-host / add-gate
|
|
62
|
-
- [
|
|
62
|
+
- [x] v0.2.0 已发布:npm view agentic-flow-kit(npx agentic-flow-kit init 即用;默认镜像源用户需等 npmmirror 同步或 --registry npmjs)
|
|
63
|
+
- [x] v0.2.1:Shipyard 回流第二笔(模板引用去死链 + owned 台账记账策略:add-gate 接线刷新 + sync 盘面自愈)+ 全项目审查修复(量化台账 fail-loud / 生成器锚点与 ENOENT 守卫 / sync 跳过件持续报告 / P4 清账 / metrics glob 词表收口)——npm publish 待执行
|
|
@@ -78,6 +78,8 @@ if [ -z "$PY_BIN" ]; then
|
|
|
78
78
|
violations="$violations
|
|
79
79
|
- 红线 4.3 无法执行:未找到 python/python3/py(Domain 导航属性扫描依赖 Python;门禁 fail-closed,不静默放行)"
|
|
80
80
|
else
|
|
81
|
+
# 2026-09-24:①python 运行期报错也 fail-closed(原只对「没装 python」兜底,脚本报错时 nav_hits 为空即放行);
|
|
82
|
+
# ②属性匹配改全文 finditer——支持「{ 换行」与 expression-bodied(=>)形态,先剥注释防误报
|
|
81
83
|
nav_hits=$(DOMAIN_ENTITIES_DIR="$DOMAIN_ENTITIES_DIR" SHARED_TYPES="$SHARED_TYPES" "$PY_BIN" - <<'PYEOF'
|
|
82
84
|
import re, glob, os
|
|
83
85
|
from os import environ
|
|
@@ -91,19 +93,20 @@ for f in files:
|
|
|
91
93
|
hits = []
|
|
92
94
|
for f in files:
|
|
93
95
|
with open(f, encoding='utf-8-sig') as fh:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
96
|
+
src = re.sub(r'/\*.*?\*/', '', fh.read(), flags=re.S)
|
|
97
|
+
src = re.sub(r'//[^\n]*', '', src)
|
|
98
|
+
for m in re.finditer(r'\bpublic\s+(?:virtual\s+)?([\w<>, \t.\?]+?)\s+(\w+)\s*(?:\{|=>)', src):
|
|
99
|
+
typ = m.group(1).strip()
|
|
100
|
+
mm = re.search(r'(?:ICollection|List|IEnumerable|IReadOnlyCollection|IReadOnlyList)<\s*(\w+)\s*>', typ)
|
|
101
|
+
core = mm.group(1) if mm else (typ.rstrip('?') if re.fullmatch(r'\w+\??', typ) else None)
|
|
102
|
+
if core and (core in names or core in shared):
|
|
103
|
+
ln = src.count('\n', 0, m.start()) + 1
|
|
104
|
+
hits.append(f"{os.path.basename(f)}:{ln} {m.group(2)} : {typ}")
|
|
103
105
|
if hits:
|
|
104
106
|
print('\n'.join(hits))
|
|
105
107
|
PYEOF
|
|
106
|
-
)
|
|
108
|
+
) || violations="$violations
|
|
109
|
+
- 红线 4.3 无法执行:python 扫描异常退出(fail-closed,不静默放行;诊断见上方 stderr)"
|
|
107
110
|
fi
|
|
108
111
|
if [ -n "$nav_hits" ]; then
|
|
109
112
|
violations="$violations
|
|
@@ -112,6 +115,7 @@ $nav_hits"
|
|
|
112
115
|
fi
|
|
113
116
|
|
|
114
117
|
# 红线 5:Controller 禁把 InnerException 原文透传进响应体(详情只许进日志)
|
|
118
|
+
# 已知天花板:grep 按整行排除 Log 调用——透传与 Log 写在同一行可绕过;语义级排除需 AST 工具,参考实现门禁按接受记录(2026-09-24)
|
|
115
119
|
inner_hits=$(grep -rn "InnerException" "$CONTROLLERS_DIR" --include="*.cs" 2>/dev/null \
|
|
116
120
|
| grep -v -e "/obj/" -e "/bin/" \
|
|
117
121
|
| grep -vE "Log(Warning|Error|Information|Debug|Trace)")
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: wf-build
|
|
3
|
-
description: Build 阶段 · 起 plan + 实现代码 + 自验(两道确认门,确认后才动代码)
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
严格按 AGENTS.md 与 .agents/commands/build.md 执行:Build 阶段 · 起 plan + 实现代码 + 自验。
|
|
7
|
-
|
|
8
|
-
先完整读取上述两个文件并完全遵循,读不到即停下报告阻塞;本文件不内联步骤副本,避免与权威版本漂移。
|
|
9
|
-
|
|
10
|
-
【Trae 宿主注记】
|
|
11
|
-
- 两道确认门:① plan 草稿确认(draft→approved)② 计划模式列改动文件清单确认——两道全过才动代码。
|
|
12
|
-
- 范围明确的工作包可委派 implementer(.trae/agents/implementer.md);子智能体未开启时按 fallback: main 由主智能体按同一角色契约执行。
|
|
13
|
-
- 实现中需偏离已确认 plan(公共接口 / 未列文件 / 新依赖 / 判据影响)→ 停下向用户说明,确认后再继续。
|
|
14
|
-
- 完成后进 wf-test。
|
|
1
|
+
---
|
|
2
|
+
name: wf-build
|
|
3
|
+
description: Build 阶段 · 起 plan + 实现代码 + 自验(两道确认门,确认后才动代码)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
严格按 AGENTS.md 与 .agents/commands/build.md 执行:Build 阶段 · 起 plan + 实现代码 + 自验。
|
|
7
|
+
|
|
8
|
+
先完整读取上述两个文件并完全遵循,读不到即停下报告阻塞;本文件不内联步骤副本,避免与权威版本漂移。
|
|
9
|
+
|
|
10
|
+
【Trae 宿主注记】
|
|
11
|
+
- 两道确认门:① plan 草稿确认(draft→approved)② 计划模式列改动文件清单确认——两道全过才动代码。
|
|
12
|
+
- 范围明确的工作包可委派 implementer(.trae/agents/implementer.md);子智能体未开启时按 fallback: main 由主智能体按同一角色契约执行。
|
|
13
|
+
- 实现中需偏离已确认 plan(公共接口 / 未列文件 / 新依赖 / 判据影响)→ 停下向用户说明,确认后再继续。
|
|
14
|
+
- 完成后进 wf-test。
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: wf-deploy
|
|
3
|
-
description: Deploy 阶段 · prod 上线清单(静态门 / 配对 / 回归 / DB / 授权 / 24h 观察;关单在 wf-test)
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
严格按 AGENTS.md 与 .agents/commands/deploy.md 执行:Deploy 阶段 · prod 上线清单(静态门 / 配对检查 / 回归 / DB / 授权 / 24h 观察;文档关单在 wf-test,本阶段不重复关单)。
|
|
7
|
-
|
|
8
|
-
先完整读取上述两个文件并完全遵循,读不到即停下报告阻塞;本文件不内联步骤副本,避免与权威版本漂移。
|
|
9
|
-
|
|
10
|
-
【Trae 宿主注记】
|
|
11
|
-
- 确认门:上线授权 = 用户对话内一句确认 + release/<日期> tag 留痕;无第二审批人,AI 不得自行上线。
|
|
12
|
-
- 本阶段不委派子智能体;回滚 SQL 等数据安全判断由主智能体做、用户拍板。
|
|
13
|
-
- 异常进 wf-maintain;用户确认无异常 = prod 闭环,AI 不得自行宣告。
|
|
1
|
+
---
|
|
2
|
+
name: wf-deploy
|
|
3
|
+
description: Deploy 阶段 · prod 上线清单(静态门 / 配对 / 回归 / DB / 授权 / 24h 观察;关单在 wf-test)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
严格按 AGENTS.md 与 .agents/commands/deploy.md 执行:Deploy 阶段 · prod 上线清单(静态门 / 配对检查 / 回归 / DB / 授权 / 24h 观察;文档关单在 wf-test,本阶段不重复关单)。
|
|
7
|
+
|
|
8
|
+
先完整读取上述两个文件并完全遵循,读不到即停下报告阻塞;本文件不内联步骤副本,避免与权威版本漂移。
|
|
9
|
+
|
|
10
|
+
【Trae 宿主注记】
|
|
11
|
+
- 确认门:上线授权 = 用户对话内一句确认 + release/<日期> tag 留痕;无第二审批人,AI 不得自行上线。
|
|
12
|
+
- 本阶段不委派子智能体;回滚 SQL 等数据安全判断由主智能体做、用户拍板。
|
|
13
|
+
- 异常进 wf-maintain;用户确认无异常 = prod 闭环,AI 不得自行宣告。
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: wf-design
|
|
3
|
-
description: Design 阶段 · 起 spec(L2/L3 强制,L1 可省略直接进 wf-build)
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
严格按 AGENTS.md 与 .agents/commands/design.md 执行:Design 阶段 · 起 spec(L2/L3 强制,L1 可省略直接进 wf-build)。
|
|
7
|
-
|
|
8
|
-
先完整读取上述两个文件并完全遵循,读不到即停下报告阻塞;本文件不内联步骤副本,避免与权威版本漂移。
|
|
9
|
-
|
|
10
|
-
【Trae 宿主注记】
|
|
11
|
-
- 确认门:spec 草稿经用户确认;L3 另有独立复核门,复核未过不得确认。
|
|
12
|
-
- L3 独立复核委派 independent-reviewer(.trae/agents/independent-reviewer.md);子智能体未开启时按 fallback: new-session 另开新会话,不得由原会话自查冒充。
|
|
13
|
-
- 确认后进 wf-build。
|
|
1
|
+
---
|
|
2
|
+
name: wf-design
|
|
3
|
+
description: Design 阶段 · 起 spec(L2/L3 强制,L1 可省略直接进 wf-build)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
严格按 AGENTS.md 与 .agents/commands/design.md 执行:Design 阶段 · 起 spec(L2/L3 强制,L1 可省略直接进 wf-build)。
|
|
7
|
+
|
|
8
|
+
先完整读取上述两个文件并完全遵循,读不到即停下报告阻塞;本文件不内联步骤副本,避免与权威版本漂移。
|
|
9
|
+
|
|
10
|
+
【Trae 宿主注记】
|
|
11
|
+
- 确认门:spec 草稿经用户确认;L3 另有独立复核门,复核未过不得确认。
|
|
12
|
+
- L3 独立复核委派 independent-reviewer(.trae/agents/independent-reviewer.md);子智能体未开启时按 fallback: new-session 另开新会话,不得由原会话自查冒充。
|
|
13
|
+
- 确认后进 wf-build。
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: wf-maintain
|
|
3
|
-
description: Maintain 阶段 · 立 incident + 复盘三件套(incident 在 L1+ 即 intent 等价物)
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
严格按 AGENTS.md 与 .agents/commands/maintain.md 执行:Maintain 阶段 · 立 incident + 复盘三件套(incident 在 L1+ 即 intent 等价物,不必另造 intent)。
|
|
7
|
-
|
|
8
|
-
先完整读取上述两个文件并完全遵循,读不到即停下报告阻塞;本文件不内联步骤副本,避免与权威版本漂移。
|
|
9
|
-
|
|
10
|
-
【Trae 宿主注记】
|
|
11
|
-
- 确认门:止血方案由用户拍板(AI 只执行选定方案);三件套草稿经用户确认后才落地。
|
|
12
|
-
- 配 plan 的时点与形态以权威文件为准——incident≡intent 免掉的是 intent,plan 不可免(commit / push 两处门禁按同名硬拦)。
|
|
13
|
-
- 复现路径与验收明确的局部热修可委派 implementer(.trae/agents/implementer.md);事故诊断、根因定性与三件套起草不委派。
|
|
1
|
+
---
|
|
2
|
+
name: wf-maintain
|
|
3
|
+
description: Maintain 阶段 · 立 incident + 复盘三件套(incident 在 L1+ 即 intent 等价物)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
严格按 AGENTS.md 与 .agents/commands/maintain.md 执行:Maintain 阶段 · 立 incident + 复盘三件套(incident 在 L1+ 即 intent 等价物,不必另造 intent)。
|
|
7
|
+
|
|
8
|
+
先完整读取上述两个文件并完全遵循,读不到即停下报告阻塞;本文件不内联步骤副本,避免与权威版本漂移。
|
|
9
|
+
|
|
10
|
+
【Trae 宿主注记】
|
|
11
|
+
- 确认门:止血方案由用户拍板(AI 只执行选定方案);三件套草稿经用户确认后才落地。
|
|
12
|
+
- 配 plan 的时点与形态以权威文件为准——incident≡intent 免掉的是 intent,plan 不可免(commit / push 两处门禁按同名硬拦)。
|
|
13
|
+
- 复现路径与验收明确的局部热修可委派 implementer(.trae/agents/implementer.md);事故诊断、根因定性与三件套起草不委派。
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: wf-new-task
|
|
3
|
-
description: 闭环总入口 · 路由判断(新需求 → wf-plan / 修复 → wf-maintain)+ 级别判断(L0-L3)
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
严格按 AGENTS.md 与 .agents/commands/new-task.md 执行:闭环总入口 · 路由判断(新需求 intent → wf-plan / 修复 incident → wf-maintain)+ 级别判断(L0-L3)。
|
|
7
|
-
|
|
8
|
-
先完整读取上述两个文件并完全遵循,读不到即停下报告阻塞;本文件不内联步骤副本,避免与权威版本漂移。
|
|
9
|
-
|
|
10
|
-
【Trae 宿主注记】
|
|
11
|
-
- 输出路由结论与级别,指明进入哪个 wf-*.md;不并阶段、不跳阶段。
|
|
12
|
-
- approval_required 阶段产出未经用户对话内一句话确认,不得进入下一阶段。
|
|
13
|
-
- 宿主级差异(规则惰性加载 / 终端 shell / 子智能体开关 / 门禁冗余)见 alwaysApply 规则 `.trae/rules/project-workflow.md`,不在此重复。
|
|
1
|
+
---
|
|
2
|
+
name: wf-new-task
|
|
3
|
+
description: 闭环总入口 · 路由判断(新需求 → wf-plan / 修复 → wf-maintain)+ 级别判断(L0-L3)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
严格按 AGENTS.md 与 .agents/commands/new-task.md 执行:闭环总入口 · 路由判断(新需求 intent → wf-plan / 修复 incident → wf-maintain)+ 级别判断(L0-L3)。
|
|
7
|
+
|
|
8
|
+
先完整读取上述两个文件并完全遵循,读不到即停下报告阻塞;本文件不内联步骤副本,避免与权威版本漂移。
|
|
9
|
+
|
|
10
|
+
【Trae 宿主注记】
|
|
11
|
+
- 输出路由结论与级别,指明进入哪个 wf-*.md;不并阶段、不跳阶段。
|
|
12
|
+
- approval_required 阶段产出未经用户对话内一句话确认,不得进入下一阶段。
|
|
13
|
+
- 宿主级差异(规则惰性加载 / 终端 shell / 子智能体开关 / 门禁冗余)见 alwaysApply 规则 `.trae/rules/project-workflow.md`,不在此重复。
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: wf-plan
|
|
3
|
-
description: Plan 阶段 · 立 intent(AI 起草、用户确认;本阶段不委派子智能体)
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
严格按 AGENTS.md 与 .agents/commands/plan.md 执行:Plan 阶段 · 立 intent(AI 起草、用户确认;本阶段不委派子智能体)。
|
|
7
|
-
|
|
8
|
-
先完整读取上述两个文件并完全遵循,读不到即停下报告阻塞;本文件不内联步骤副本,避免与权威版本漂移。
|
|
9
|
-
|
|
10
|
-
【Trae 宿主注记】
|
|
11
|
-
- 确认门:intent 草稿全文输出给用户过目,一句"可以"即确认(draft→approved),确认前不进下一阶段。
|
|
12
|
-
- 已有 approved intent 时按级别跳转:L1 → wf-build;L2/L3 → wf-design。
|
|
13
|
-
- 本阶段不委派子智能体,由主智能体起草;任务入口动作与红线勾选口径以权威文件为准。
|
|
1
|
+
---
|
|
2
|
+
name: wf-plan
|
|
3
|
+
description: Plan 阶段 · 立 intent(AI 起草、用户确认;本阶段不委派子智能体)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
严格按 AGENTS.md 与 .agents/commands/plan.md 执行:Plan 阶段 · 立 intent(AI 起草、用户确认;本阶段不委派子智能体)。
|
|
7
|
+
|
|
8
|
+
先完整读取上述两个文件并完全遵循,读不到即停下报告阻塞;本文件不内联步骤副本,避免与权威版本漂移。
|
|
9
|
+
|
|
10
|
+
【Trae 宿主注记】
|
|
11
|
+
- 确认门:intent 草稿全文输出给用户过目,一句"可以"即确认(draft→approved),确认前不进下一阶段。
|
|
12
|
+
- 已有 approved intent 时按级别跳转:L1 → wf-build;L2/L3 → wf-design。
|
|
13
|
+
- 本阶段不委派子智能体,由主智能体起草;任务入口动作与红线勾选口径以权威文件为准。
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: wf-review
|
|
3
|
-
description: Review · 代码评审(横切,合入前使用;P0/P1/P2 分级清单 + 用户定性与合入时机)
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
严格按 AGENTS.md 与 .agents/commands/review.md 执行:Review · 代码评审(横切,合入前使用;P0/P1/P2 分级清单 + 用户定性与合入时机)。
|
|
7
|
-
|
|
8
|
-
先完整读取上述两个文件并完全遵循,读不到即停下报告阻塞;本文件不内联步骤副本,避免与权威版本漂移。
|
|
9
|
-
|
|
10
|
-
【Trae 宿主注记】
|
|
11
|
-
- 顺序:机器门禁自动拦 → independent-reviewer 复核(L2/L3 强制独立,子智能体未开启时另开新会话)→ 分级清单交用户定性与决定合入时机。
|
|
12
|
-
- 确认门:P0/P1 未清回 wf-build;清零且用户确认后才可合入。
|
|
13
|
-
- finding 报告门(防误报)与机器兜底清单以权威文件为准。
|
|
1
|
+
---
|
|
2
|
+
name: wf-review
|
|
3
|
+
description: Review · 代码评审(横切,合入前使用;P0/P1/P2 分级清单 + 用户定性与合入时机)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
严格按 AGENTS.md 与 .agents/commands/review.md 执行:Review · 代码评审(横切,合入前使用;P0/P1/P2 分级清单 + 用户定性与合入时机)。
|
|
7
|
+
|
|
8
|
+
先完整读取上述两个文件并完全遵循,读不到即停下报告阻塞;本文件不内联步骤副本,避免与权威版本漂移。
|
|
9
|
+
|
|
10
|
+
【Trae 宿主注记】
|
|
11
|
+
- 顺序:机器门禁自动拦 → independent-reviewer 复核(L2/L3 强制独立,子智能体未开启时另开新会话)→ 分级清单交用户定性与决定合入时机。
|
|
12
|
+
- 确认门:P0/P1 未清回 wf-build;清零且用户确认后才可合入。
|
|
13
|
+
- finding 报告门(防误报)与机器兜底清单以权威文件为准。
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: wf-test
|
|
3
|
-
description: Test 阶段 · 静态门 + 切库冒烟 + UI 实测 + L2/L3 独立复核(关单在本阶段)
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
严格按 AGENTS.md 与 .agents/commands/test.md 执行:Test 阶段 · 静态门全过 + 切库冒烟(如触发)+ UI 实测 + L2/L3 独立复核。
|
|
7
|
-
|
|
8
|
-
先完整读取上述两个文件并完全遵循,读不到即停下报告阻塞;本文件不内联步骤副本,避免与权威版本漂移。
|
|
9
|
-
|
|
10
|
-
【Trae 宿主注记】
|
|
11
|
-
- 确认门:全过后用户确认才关单;**关单在本阶段**(勾验收 / incident 状态 / 委派留痕的口径以权威文件为准)。
|
|
12
|
-
- UI 实测委派 ui-verifier(.trae/agents/ui-verifier.md);L2/L3 独立复核委派 independent-reviewer,子智能体未开启时另开新会话。
|
|
13
|
-
- 失败项修复仍回 wf-build,不在本阶段顺手改代码。
|
|
14
|
-
- L1 到此结束;L2/L3 仅当用户确认要上 prod 才进 wf-deploy。
|
|
1
|
+
---
|
|
2
|
+
name: wf-test
|
|
3
|
+
description: Test 阶段 · 静态门 + 切库冒烟 + UI 实测 + L2/L3 独立复核(关单在本阶段)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
严格按 AGENTS.md 与 .agents/commands/test.md 执行:Test 阶段 · 静态门全过 + 切库冒烟(如触发)+ UI 实测 + L2/L3 独立复核。
|
|
7
|
+
|
|
8
|
+
先完整读取上述两个文件并完全遵循,读不到即停下报告阻塞;本文件不内联步骤副本,避免与权威版本漂移。
|
|
9
|
+
|
|
10
|
+
【Trae 宿主注记】
|
|
11
|
+
- 确认门:全过后用户确认才关单;**关单在本阶段**(勾验收 / incident 状态 / 委派留痕的口径以权威文件为准)。
|
|
12
|
+
- UI 实测委派 ui-verifier(.trae/agents/ui-verifier.md);L2/L3 独立复核委派 independent-reviewer,子智能体未开启时另开新会话。
|
|
13
|
+
- 失败项修复仍回 wf-build,不在本阶段顺手改代码。
|
|
14
|
+
- L1 到此结束;L2/L3 仅当用户确认要上 prod 才进 wf-deploy。
|
|
@@ -75,6 +75,16 @@ try {
|
|
|
75
75
|
}));
|
|
76
76
|
process.exit(0);
|
|
77
77
|
}
|
|
78
|
+
// 门禁脚本未装(未跑 add-gate dotnet-ca)≠ 发现违例——区分口径,对齐 pre-shell-check 的 ENOENT 处理(2026-09-24)
|
|
79
|
+
if (e.code === 'ENOENT') {
|
|
80
|
+
console.log(JSON.stringify({
|
|
81
|
+
hookSpecificOutput: {
|
|
82
|
+
hookEventName: 'PostToolUse',
|
|
83
|
+
additionalContext: '⚠️ 架构红线检查未执行:check-architecture.sh 未安装(flow-kit add-gate dotnet-ca 装入)——本次编辑未验证。'
|
|
84
|
+
}
|
|
85
|
+
}));
|
|
86
|
+
process.exit(0);
|
|
87
|
+
}
|
|
78
88
|
const err = String((e.stderr || '') + (e.stdout || '')).slice(0, 800);
|
|
79
89
|
console.log(JSON.stringify({
|
|
80
90
|
hookSpecificOutput: {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* 1) deny/ask 命令门禁(口径同 .agents/settings.json 的 deny/ask 策略)
|
|
5
5
|
* 2) git commit / git push 前置检查:直接调 .githooks/pre-commit / pre-push
|
|
6
6
|
*
|
|
7
|
-
* 为什么调 .githooks/*:那是项目唯一的门禁权威(pre-commit
|
|
7
|
+
* 为什么调 .githooks/*:那是项目唯一的门禁权威(pre-commit 门禁链 + pre-push 闭环断档)。
|
|
8
8
|
* 本钩子是**宿主侧冗余**——core.hooksPath 漏配时 git 侧门禁静默失效(2026-09-16 Trae 侧缺档事故),
|
|
9
9
|
* 由这里在命令执行前拦下;门禁清单只维护 .githooks/ 一份,本文件不复制。
|
|
10
10
|
*
|
|
@@ -90,13 +90,23 @@ const askList = [
|
|
|
90
90
|
{ pat: 'rm -rf', reason: '可能递归删除文件' }
|
|
91
91
|
];
|
|
92
92
|
|
|
93
|
+
// gateMatch:比裸 includes 收紧两处(2026-09-24)——
|
|
94
|
+
// ① token 边界:'git push --force' 不再误拦 '--force-with-lease'、'git commit' 不再误吃 'git commit-msg'
|
|
95
|
+
// ② 剥离 git 全局参 -c <k=v> 与 -m <msg> 后以剥后文本为准——堵 'git -c x=y push --force' 绕过,
|
|
96
|
+
// 也免得消息字样误触发;剥不出(norm===cmd)再按原文匹配
|
|
97
|
+
function gateMatch(cmd, pat) {
|
|
98
|
+
const re = new RegExp(pat.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '(?![\\w-])');
|
|
99
|
+
const norm = cmd.replace(/(^|\s)-[cm]\s+\S+(?=\s|$)/g, ' ').replace(/\s+/g, ' ').trim();
|
|
100
|
+
return norm !== cmd ? re.test(norm) : re.test(cmd);
|
|
101
|
+
}
|
|
102
|
+
|
|
93
103
|
for (const d of denyList) {
|
|
94
|
-
if (command
|
|
104
|
+
if (gateMatch(command, d.pat)) {
|
|
95
105
|
deny(`禁止执行: ${d.pat}(项目红线:${d.reason})`);
|
|
96
106
|
}
|
|
97
107
|
}
|
|
98
108
|
for (const a of askList) {
|
|
99
|
-
if (command
|
|
109
|
+
if (gateMatch(command, a.pat)) {
|
|
100
110
|
ask(`需确认: ${a.pat}(项目 ask 策略:${a.reason})`);
|
|
101
111
|
}
|
|
102
112
|
}
|
|
@@ -135,7 +145,7 @@ function runGate(scriptRelPath, label, budgetMs) {
|
|
|
135
145
|
}
|
|
136
146
|
|
|
137
147
|
if (isCommit) {
|
|
138
|
-
// pre-commit
|
|
148
|
+
// pre-commit 门禁链(通用包口径):闭环配对(增量)+ wiki 台账(增量)+ 常驻面预算 + 项目门禁(local-pre-commit)+ 敏感信息扫描与条件构建
|
|
139
149
|
// 预算 5 分钟覆盖 dotnet build / npm run build(.githooks/pre-commit 内部无超时)
|
|
140
150
|
runGate('.githooks/pre-commit', '提交前门禁', 300000);
|
|
141
151
|
}
|
|
@@ -1,21 +1,30 @@
|
|
|
1
|
-
// shell 探测(供 .trae/hooks/ 各钩子共用)
|
|
2
|
-
// Windows 下 bash 常不在 PATH:优先 Git Bash 绝对路径,回退 PATH 的 bash/sh。
|
|
3
|
-
// 返回 null 表示不可用——调用方须 fail-closed 报告「门禁未执行」,不要当成检查通过。
|
|
4
|
-
const { execFileSync } = require('child_process');
|
|
5
|
-
const fs = require('fs');
|
|
6
|
-
|
|
7
|
-
function resolveShell() {
|
|
8
|
-
const candidates = [
|
|
9
|
-
'C:\\Program Files\\Git\\bin\\bash.exe',
|
|
10
|
-
'C:\\Program Files (x86)\\Git\\bin\\bash.exe'
|
|
11
|
-
];
|
|
12
|
-
for (const p of candidates) {
|
|
13
|
-
try { fs.accessSync(p); return p; } catch { /* 尝试下一个 */ }
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
// shell 探测(供 .trae/hooks/ 各钩子共用)
|
|
2
|
+
// Windows 下 bash 常不在 PATH:优先 Git Bash 绝对路径,回退 PATH 的 bash/sh。
|
|
3
|
+
// 返回 null 表示不可用——调用方须 fail-closed 报告「门禁未执行」,不要当成检查通过。
|
|
4
|
+
const { execFileSync } = require('child_process');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
|
|
7
|
+
function resolveShell() {
|
|
8
|
+
const candidates = [
|
|
9
|
+
'C:\\Program Files\\Git\\bin\\bash.exe',
|
|
10
|
+
'C:\\Program Files (x86)\\Git\\bin\\bash.exe'
|
|
11
|
+
];
|
|
12
|
+
for (const p of candidates) {
|
|
13
|
+
try { fs.accessSync(p); return p; } catch { /* 尝试下一个 */ }
|
|
14
|
+
}
|
|
15
|
+
// PATH 回退须避开 WSL 启动器:C:\Windows\System32\bash.exe 能过 exit 0 探测,但路径/行尾语义是 Linux 侧的(2026-09-24)
|
|
16
|
+
for (const c of ['bash', 'sh']) {
|
|
17
|
+
let cand = c;
|
|
18
|
+
try {
|
|
19
|
+
const hits = execFileSync('where.exe', [c], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] })
|
|
20
|
+
.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
21
|
+
const good = hits.find((p) => !/system32/i.test(p)); // 全部命中都在 System32(纯 WSL)→ 跳过该候选
|
|
22
|
+
if (good) cand = good;
|
|
23
|
+
else continue;
|
|
24
|
+
} catch { /* where 不可用(非 Windows):按原名探测,保持旧行为 */ }
|
|
25
|
+
try { execFileSync(cand, ['-c', 'exit 0'], { stdio: 'pipe', timeout: 5000 }); return cand; } catch { /* 尝试下一个 */ }
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = { resolveShell };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: false
|
|
3
|
-
scene: beautify_input
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
请使用中文回复。所有解释、说明、注释和对话均使用中文。
|
|
1
|
+
---
|
|
2
|
+
alwaysApply: false
|
|
3
|
+
scene: beautify_input
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
请使用中文回复。所有解释、说明、注释和对话均使用中文。
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: false
|
|
3
|
-
scene: git_message
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
提交信息一律中文,遵循 Conventional Commits:`<类型>(<范围>): <说明>`,例如 `fix(采购订单): 页签切换浮层收纳`、`docs(trae): 同步工作流适配层`。
|
|
7
|
-
|
|
8
|
-
- 类型枚举:feat / fix / docs / style / refactor / perf;`.githooks/commit-msg` 按此硬校验首行,非枚举前缀会被拦下,merge / revert 提交豁免。
|
|
9
|
-
- 范围可省:`fix: 说明` 同样合法;分隔符 `:` 或 `(` 均可。
|
|
10
|
-
- 禁止 `[feat] 说明` 这类方括号写法。
|
|
1
|
+
---
|
|
2
|
+
alwaysApply: false
|
|
3
|
+
scene: git_message
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
提交信息一律中文,遵循 Conventional Commits:`<类型>(<范围>): <说明>`,例如 `fix(采购订单): 页签切换浮层收纳`、`docs(trae): 同步工作流适配层`。
|
|
7
|
+
|
|
8
|
+
- 类型枚举:feat / fix / docs / style / refactor / perf;`.githooks/commit-msg` 按此硬校验首行,非枚举前缀会被拦下,merge / revert 提交豁免。
|
|
9
|
+
- 范围可省:`fix: 说明` 同样合法;分隔符 `:` 或 `(` 均可。
|
|
10
|
+
- 禁止 `[feat] 说明` 这类方括号写法。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentic-flow-kit",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "AI-Native 闭环工作流 + wiki 知识层脚手架——flow-kit init 一条命令为新项目装好 .agents 工作流引擎(阶段命令/角色契约/门禁钩子/kb 检索/看板/规则面预算)+ workflow 文档闭环 + wiki 知识库,装完自包含、零运行时依赖",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -30,5 +30,13 @@
|
|
|
30
30
|
"closed-loop"
|
|
31
31
|
],
|
|
32
32
|
"license": "MIT",
|
|
33
|
-
"private": false
|
|
33
|
+
"private": false,
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/zerosloney/agentic-flow-kit.git"
|
|
37
|
+
},
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/zerosloney/agentic-flow-kit/issues"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://github.com/zerosloney/agentic-flow-kit#readme"
|
|
34
42
|
}
|
package/src/add-gate.mjs
CHANGED
|
@@ -52,6 +52,7 @@ export function addGate(args, pkgRoot) {
|
|
|
52
52
|
if (skipped.length) console.log(` 跳过(已存在,--force 覆盖):${skipped.join('、')}`);
|
|
53
53
|
|
|
54
54
|
// 接线 local-pre-commit(幂等:挂载行已存在不重复;旧装态尾部 exit 0 会吞掉其后门禁的失败——归一化剥掉)
|
|
55
|
+
let wiredLp = false;
|
|
55
56
|
if (wireLine) {
|
|
56
57
|
const lpPath = path.join(hooksDir, 'local-pre-commit');
|
|
57
58
|
const cur = fs.existsSync(lpPath) ? fs.readFileSync(lpPath, 'utf8') : '';
|
|
@@ -67,15 +68,21 @@ export function addGate(args, pkgRoot) {
|
|
|
67
68
|
const body = lines.length ? `${lines.join('\n')}\n` : '#!/bin/sh\nset -e\n';
|
|
68
69
|
fs.writeFileSync(lpPath, `${body}${wireLine}\n`);
|
|
69
70
|
console.log(` local-pre-commit 接线:+ ${wireLine}`);
|
|
71
|
+
wiredLp = true;
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
74
|
|
|
73
|
-
// owned 台账补记(归项目所有,sync
|
|
75
|
+
// owned 台账补记(归项目所有,sync 永不覆盖)。接线改写了 local-pre-commit(init 时按模板态记账)——
|
|
76
|
+
// 须同步刷新其 owned 哈希,否则台账停在模板态(Shipyard 回流发现的漂移根因,2026-09-24)
|
|
74
77
|
const ownedLedger = new Map((kit.owned || []).map((f) => [f.rel, f]));
|
|
75
78
|
for (const name of installed) {
|
|
76
79
|
const rel = `.agents/hooks/${name}`;
|
|
77
80
|
ownedLedger.set(rel, { rel, sha256: sha256(fs.readFileSync(path.join(hooksDir, name))) });
|
|
78
81
|
}
|
|
82
|
+
if (wiredLp) {
|
|
83
|
+
const lpRel = '.agents/hooks/local-pre-commit';
|
|
84
|
+
ownedLedger.set(lpRel, { rel: lpRel, sha256: sha256(fs.readFileSync(path.join(hooksDir, 'local-pre-commit'))) });
|
|
85
|
+
}
|
|
79
86
|
kit.owned = [...ownedLedger.values()].sort((a, b) => a.rel.localeCompare(b.rel));
|
|
80
87
|
fs.writeFileSync(kitPath, `${JSON.stringify(kit, null, 2)}\n`);
|
|
81
88
|
|
package/src/add-host.mjs
CHANGED
|
@@ -39,6 +39,10 @@ export function addHost(args, pkgRoot) {
|
|
|
39
39
|
const r = renderTree(path.join(pkgRoot, 'modules', 'hosts', host), path.join(target, HOSTS[host].dir), vars, { force });
|
|
40
40
|
if (!r.written.length && r.skipped.length) console.log(' 跳过(已存在,未覆盖):' + r.skipped.join('、'));
|
|
41
41
|
else console.log(` 安装 ${r.written.length} 份${r.skipped.length ? `,跳过已存在 ${r.skipped.length} 份` : ''}`);
|
|
42
|
+
if (r.skipped.length) {
|
|
43
|
+
// 跳过的文件不入 managed 台账(不接管既有内容)——后续 sync 只报「已存在未入台账」,永不升级;纳入包管理须 --force
|
|
44
|
+
console.log(' ⚠️ 跳过文件不入 managed 台账、后续 sync 不升级(每次仅报告);纳入包管理用 --force 覆盖');
|
|
45
|
+
}
|
|
42
46
|
|
|
43
47
|
// managed 台账按 rel 去重补记
|
|
44
48
|
const ledger = new Map((kit.managed || []).map((f) => [f.rel, f]));
|
package/src/cli.mjs
CHANGED
|
@@ -15,9 +15,10 @@ export const HELP = `flow-kit — AI-Native 闭环工作流 + wiki 知识层脚
|
|
|
15
15
|
|
|
16
16
|
用法:
|
|
17
17
|
flow-kit init 安装到当前项目(裸跑无参数 → 交互确认环节;带参数直接执行)
|
|
18
|
-
flow-kit sync 升级 managed
|
|
19
|
-
INDEX/看板等生成器目标重跑锚点重写;
|
|
20
|
-
|
|
18
|
+
flow-kit sync 升级 managed 文件(未改动→覆盖新版;本地已改→跳过并持续报告——台账不基线化,
|
|
19
|
+
不会被下次升级静默覆盖;--force 才覆盖;INDEX/看板等生成器目标重跑锚点重写;
|
|
20
|
+
owned 文件永不触碰)
|
|
21
|
+
flow-kit add-host <宿主> 后补宿主适配层:zcode | opencode | trae | omp(已存在文件跳过且不入台账,--force 接管)
|
|
21
22
|
flow-kit add-gate <门禁> 装门禁模块并接线 local-pre-commit(当前:dotnet-ca;装后归项目所有)
|
|
22
23
|
flow-kit doctor 体检:目录布局 / git 钩子 / managed 清单 / 索引漂移 / check-loop
|
|
23
24
|
|
package/src/doctor.mjs
CHANGED
|
@@ -120,6 +120,13 @@ export function doctor(args, pkgRoot) {
|
|
|
120
120
|
if (idx.status === 0) add('PASS', 'workflow/INDEX.md 无漂移');
|
|
121
121
|
else add('WARN', `workflow/INDEX.md 漂移——跑 node .agents/scripts/gen-workflow-index.mjs 重生成`);
|
|
122
122
|
|
|
123
|
+
// 6.5 delegations 台账结构(量化层非门禁:结构漂移曾静默吞掉全部记录,2026-09-24)
|
|
124
|
+
if (fs.existsSync(path.join(target, '.agents/scripts/agg-delegations.cjs'))) {
|
|
125
|
+
const agg = spawnSync(process.execPath, ['.agents/scripts/agg-delegations.cjs'], { cwd: target, encoding: 'utf8' });
|
|
126
|
+
if (agg.status === 0) add('PASS', 'delegations 台账结构有效(agg 可解析)');
|
|
127
|
+
else add('WARN', `delegations 台账结构漂移——${String(agg.stderr || agg.stdout || '').split('\n')[0]}`);
|
|
128
|
+
}
|
|
129
|
+
|
|
123
130
|
// 7. check-loop
|
|
124
131
|
const cl = spawnSync('sh', ['.agents/scripts/check-loop.sh'], { cwd: target, encoding: 'utf8' });
|
|
125
132
|
if (cl.status === 0) {
|
|
@@ -135,8 +142,8 @@ export function doctor(args, pkgRoot) {
|
|
|
135
142
|
portInUse(port).then((inUse) => {
|
|
136
143
|
print(results);
|
|
137
144
|
console.log(inUse
|
|
138
|
-
? `ℹ️ 看板端口 ${port}
|
|
139
|
-
: `ℹ️ 看板端口 ${port}
|
|
145
|
+
? `ℹ️ 看板端口 ${port} 已有监听(ensure-board 探活复用;他人进程不 kill,见 workflow/README.md)`
|
|
146
|
+
: `ℹ️ 看板端口 ${port} 空闲(看板默认不拉起;需要时手动 .agents/scripts/ensure-board.ps1 或 node .agents/scripts/workflow-board-server.mjs)`);
|
|
140
147
|
process.exit(results.some((r) => r.level === 'FAIL') ? 1 : 0);
|
|
141
148
|
});
|
|
142
149
|
}
|
package/src/render.mjs
CHANGED
|
@@ -27,6 +27,8 @@ export function renderTree(srcRoot, targetRoot, vars, { force = false } = {}) {
|
|
|
27
27
|
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
28
28
|
const abs = path.join(dir, entry.name);
|
|
29
29
|
if (entry.isDirectory()) {
|
|
30
|
+
// 运行时缓存不是模板(包源跑测试会在 templates/_agents/cache/ 落盘残留)——init/sync 一律跳过
|
|
31
|
+
if (relOf(abs, srcRoot) === '.agents/cache') continue;
|
|
30
32
|
dirs.push(relOf(abs, srcRoot));
|
|
31
33
|
walk(abs);
|
|
32
34
|
continue;
|
package/src/sync.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// flow-kit sync:按 .agents/kit.json 台账升级 managed 文件。
|
|
2
|
-
// 三态:未改动(磁盘 sha==台账)→ 覆盖新版;本地已改 → 跳过并报告(--force
|
|
2
|
+
// 三态:未改动(磁盘 sha==台账)→ 覆盖新版;本地已改 → 跳过并报告(--force 覆盖;台账保持包侧基线,
|
|
3
|
+
// 每次持续报告直至 --force 或本地对齐新版——防跳过一次后下次升级被静默覆盖,2026-09-24 语义修正);
|
|
3
4
|
// 生成器目标(INDEX.md / wiki 看板)→ 不比对,收尾重跑生成器走锚点重写。
|
|
4
5
|
// 附带:包内新增 managed 文件 → 安装;包内已删 → 仅报告不删盘、出台账;managed 缺失 → 恢复。
|
|
5
6
|
// owned 文件永不触碰(两态模型,见 profiles.isOwned)。
|
|
@@ -86,7 +87,7 @@ export function sync(args, pkgRoot) {
|
|
|
86
87
|
// 本地已改
|
|
87
88
|
if (freshFile.sha === diskSha) { unchanged++; managedNew.push({ rel, sha256: diskSha }); continue; } // 改动恰好等于新版
|
|
88
89
|
if (force) { fs.copyFileSync(freshFile.abs, disk); updated.push(`${rel}(--force 覆盖本地改动)`); managedNew.push({ rel, sha256: freshFile.sha }); }
|
|
89
|
-
else { skipped.push(rel); managedNew.push({ rel, sha256:
|
|
90
|
+
else { skipped.push(rel); managedNew.push({ rel, sha256: ledgerSha }); } // 台账保持包侧基线:持续报告「本地已改」,直到 --force 或本地对齐新版
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
// 台账外的新文件:managed 类安装;owned 类只对「盘上缺失」的起步文档报告(已装的不动不报)
|
|
@@ -109,7 +110,7 @@ export function sync(args, pkgRoot) {
|
|
|
109
110
|
list('恢复缺失', restored);
|
|
110
111
|
list('新增安装', added);
|
|
111
112
|
list('本地已改,跳过', skipped);
|
|
112
|
-
if (skipped.some((s) => !s.includes('未入台账'))) console.log(' ↑ --force 覆盖本地改动;git diff
|
|
113
|
+
if (skipped.some((s) => !s.includes('未入台账'))) console.log(' ↑ --force 覆盖本地改动;git diff 自查差异;台账保持包侧基线,后续 sync 持续报告直至处理');
|
|
113
114
|
list('包内已移除(文件保留在盘上,可手动删除)', removed);
|
|
114
115
|
list('新增 owned 起步文档(项目自持,未自动安装)', newOwned);
|
|
115
116
|
if (!updated.length && !restored.length && !added.length && !removed.length && !skipped.length && !newOwned.length) {
|
|
@@ -118,7 +119,22 @@ export function sync(args, pkgRoot) {
|
|
|
118
119
|
console.log(` 无变化 ${unchanged} 份`);
|
|
119
120
|
}
|
|
120
121
|
|
|
121
|
-
//
|
|
122
|
+
// owned 台账按盘面自愈:owned 归项目所有,哈希只是记账不是约束——手改后无须手工刷 kit.json
|
|
123
|
+
// (Shipyard 回流策略,2026-09-24:曾在消费仓被迫手工刷新 owned 哈希,根因收敛到此处)
|
|
124
|
+
let ownedRefreshed = 0;
|
|
125
|
+
if (Array.isArray(kit.owned)) {
|
|
126
|
+
kit.owned = kit.owned.map((f) => {
|
|
127
|
+
const p = path.join(target, f.rel);
|
|
128
|
+
if (!fs.existsSync(p)) return f;
|
|
129
|
+
const disk = sha256(fs.readFileSync(p));
|
|
130
|
+
if (disk === f.sha256) return f;
|
|
131
|
+
ownedRefreshed++;
|
|
132
|
+
return { ...f, sha256: disk };
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
if (ownedRefreshed) console.log(` owned 台账哈希按盘面刷新 ${ownedRefreshed} 份(owned 归项目所有,仅记账不约束)`);
|
|
136
|
+
|
|
137
|
+
// 台账重写:版本对齐当前包;removed 出册;skipped 保持包侧基线持续报告
|
|
122
138
|
kit.managed = managedNew.sort((a, b) => a.rel.localeCompare(b.rel));
|
|
123
139
|
kit.version = pkg.version;
|
|
124
140
|
fs.writeFileSync(kitPath, `${JSON.stringify(kit, null, 2)}\n`);
|