agentic-flow-kit 1.2.1 → 1.2.2

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.
@@ -7,7 +7,10 @@ description: 跨宿主适配层同步(正文段 sha 比对 + 用户拍板 +
7
7
  # Sync-Hosts · 跨宿主适配层正文段同步
8
8
 
9
9
  > 改权威源(`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 各自原描述)。
10
- > 装户视角:`flow-kit doctor` §7.x 跑同名检查(仅装户,包源环境跳过——包源下永远是 drift)。
10
+ > 装户视角:`flow-kit doctor` §7.x 跑同名检查(仅装户,包源环境跳过——包源下永远是 drift);**修漂移用同一条命令**
11
+ > `flow-kit sync-hosts --apply`——2026-10-07 起按**目标根**自动判布局(含 `templates/_agents` + `modules/hosts` → 包源:
12
+ > 比 `templates/_agents` ↔ `modules/hosts/<宿主键>/`;含 `.agents` → 装户:比 `.agents` ↔ 项目根下 `<宿主点目录>/`),
13
+ > 目标根取 `--dir <目录>` > 当前目录。
11
14
 
12
15
  ## 何时跑
13
16
 
@@ -21,8 +24,9 @@ description: 跨宿主适配层同步(正文段 sha 比对 + 用户拍板 +
21
24
  ### 默认 `--diff`(仅报告)
22
25
 
23
26
  ```
24
- node bin/flow-kit.mjs sync-hosts --diff
25
- node bin/flow-kit.mjs sync-hosts --json # 机器可读
27
+ node bin/flow-kit.mjs sync-hosts --diff # 包源仓(在包源根跑)
28
+ node bin/flow-kit.mjs sync-hosts --json # 机器可读
29
+ flow-kit sync-hosts --diff # 装户仓(在装户根跑;或用 --dir <项目根> 指定)
26
30
  ```
27
31
 
28
32
  输出三类:
@@ -56,7 +56,7 @@ node bin/flow-kit.mjs doctor # §6.5 delegations + §6.6 o
56
56
  - 输出测试报告(通过项 / 失败项)
57
57
  - 失败项已修复并复测通过
58
58
  - **关单**(日常闭环点,不依赖是否上 prod):
59
- - 关单前一键过门:`node .agents/scripts/verify.mjs`(npm test + check-loop 固定编排,任一失败非零退出,非绿不关单)
59
+ - 关单前一键过门:`node .agents/scripts/verify.mjs`(npm test + check-loop 固定编排,任一失败非零退出,非绿不关单);**装户仓**(根目录无 `package.json`,工程在子目录)默认 `npm test` 不可跑 → 脚本**显式跳过步骤 1 且不落测试绿凭证**(防假绿)并提示;此时按项目口径手工跑测试,或带 `--test-cmd "<项目测试命令>"` 指定(2026-10-07 papercut)
60
60
  - 新需求:逐条勾验入口 intent「验收标准」,每条补「证据:」(例如:粘贴 CI 运行结果、UI 截图路径、或具体的 commit SHA),intent $\rightarrow$ done;同名 spec/Quick-Plan(若有)仍 approved $\rightarrow$ done。**注意:勾选但缺证据会被 check-loop 拦截(hard-block)**
61
61
  - **approved 留痕提交**(2026-09-30 起):done 确认前确认**本次关单文档**的 approved 态已进 git 历史(越早越好——approved 后即应提交;若尚未,先补提交再 done;门为逐份校验,三件套均关单时逐份各自满足)——confirm-doc 的 done 前置门硬校验(历史未出现「状态: approved」→ 拒绝落账);done 后再提交 done 态与其余改动
62
62
  **确认落态唯一入口**(2026-09-27 起):用户在终端跑 `node .agents/scripts/confirm-doc.mjs <path>` 键入「可以」(draft→approved / approved→done;对话内明确确认后 AI 可 `--delegated "<原话>"` 代录,台账如实记 source/quote——**逐件调用 + 逐件原话**(一次一份,build.md「逐件确认」口径;多份并录被 confirm-doc 拒绝。--delegated 每次传当次实际放行的措辞,不复用同句——复用同句使台账 quote 失去分辨力))。check-loop 15 如实口径:缺记录/指纹不配对 → hard-block 拦截;伪造台账本地不可机器防,留痕供事后对质;done 内容绑定(2026-09-28 起)——**关单编辑(勾验/回填确认结果)先于 done 确认、confirm-doc 是最后一次写入**,此后修订走 superseded 或新 intent。
@@ -7,7 +7,10 @@ description: 跨宿主适配层同步(正文段 sha 比对 + 用户拍板 +
7
7
  # Sync-Hosts · 跨宿主适配层正文段同步
8
8
 
9
9
  > 改权威源(`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 各自原描述)。
10
- > 装户视角:`flow-kit doctor` §7.x 跑同名检查(仅装户,包源环境跳过——包源下永远是 drift)。
10
+ > 装户视角:`flow-kit doctor` §7.x 跑同名检查(仅装户,包源环境跳过——包源下永远是 drift);**修漂移用同一条命令**
11
+ > `flow-kit sync-hosts --apply`——2026-10-07 起按**目标根**自动判布局(含 `templates/_agents` + `modules/hosts` → 包源:
12
+ > 比 `templates/_agents` ↔ `modules/hosts/<宿主键>/`;含 `.agents` → 装户:比 `.agents` ↔ 项目根下 `<宿主点目录>/`),
13
+ > 目标根取 `--dir <目录>` > 当前目录。
11
14
 
12
15
  ## 何时跑
13
16
 
@@ -21,8 +24,9 @@ description: 跨宿主适配层同步(正文段 sha 比对 + 用户拍板 +
21
24
  ### 默认 `--diff`(仅报告)
22
25
 
23
26
  ```
24
- node bin/flow-kit.mjs sync-hosts --diff
25
- node bin/flow-kit.mjs sync-hosts --json # 机器可读
27
+ node bin/flow-kit.mjs sync-hosts --diff # 包源仓(在包源根跑)
28
+ node bin/flow-kit.mjs sync-hosts --json # 机器可读
29
+ flow-kit sync-hosts --diff # 装户仓(在装户根跑;或用 --dir <项目根> 指定)
26
30
  ```
27
31
 
28
32
  输出三类:
@@ -56,7 +56,7 @@ node bin/flow-kit.mjs doctor # §6.5 delegations + §6.6 o
56
56
  - 输出测试报告(通过项 / 失败项)
57
57
  - 失败项已修复并复测通过
58
58
  - **关单**(日常闭环点,不依赖是否上 prod):
59
- - 关单前一键过门:`node .agents/scripts/verify.mjs`(npm test + check-loop 固定编排,任一失败非零退出,非绿不关单)
59
+ - 关单前一键过门:`node .agents/scripts/verify.mjs`(npm test + check-loop 固定编排,任一失败非零退出,非绿不关单);**装户仓**(根目录无 `package.json`,工程在子目录)默认 `npm test` 不可跑 → 脚本**显式跳过步骤 1 且不落测试绿凭证**(防假绿)并提示;此时按项目口径手工跑测试,或带 `--test-cmd "<项目测试命令>"` 指定(2026-10-07 papercut)
60
60
  - 新需求:逐条勾验入口 intent「验收标准」,每条补「证据:」(例如:粘贴 CI 运行结果、UI 截图路径、或具体的 commit SHA),intent $\rightarrow$ done;同名 spec/Quick-Plan(若有)仍 approved $\rightarrow$ done。**注意:勾选但缺证据会被 check-loop 拦截(hard-block)**
61
61
  - **approved 留痕提交**(2026-09-30 起):done 确认前确认**本次关单文档**的 approved 态已进 git 历史(越早越好——approved 后即应提交;若尚未,先补提交再 done;门为逐份校验,三件套均关单时逐份各自满足)——confirm-doc 的 done 前置门硬校验(历史未出现「状态: approved」→ 拒绝落账);done 后再提交 done 态与其余改动
62
62
  **确认落态唯一入口**(2026-09-27 起):用户在终端跑 `node .agents/scripts/confirm-doc.mjs <path>` 键入「可以」(draft→approved / approved→done;对话内明确确认后 AI 可 `--delegated "<原话>"` 代录,台账如实记 source/quote——**逐件调用 + 逐件原话**(一次一份,build.md「逐件确认」口径;多份并录被 confirm-doc 拒绝。--delegated 每次传当次实际放行的措辞,不复用同句——复用同句使台账 quote 失去分辨力))。check-loop 15 如实口径:缺记录/指纹不配对 → hard-block 拦截;伪造台账本地不可机器防,留痕供事后对质;done 内容绑定(2026-09-28 起)——**关单编辑(勾验/回填确认结果)先于 done 确认、confirm-doc 是最后一次写入**,此后修订走 superseded 或新 intent。
@@ -7,7 +7,10 @@ description: 跨宿主适配层同步(正文段 sha 比对 + 用户拍板 +
7
7
  # Sync-Hosts · 跨宿主适配层正文段同步
8
8
 
9
9
  > 改权威源(`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 各自原描述)。
10
- > 装户视角:`flow-kit doctor` §7.x 跑同名检查(仅装户,包源环境跳过——包源下永远是 drift)。
10
+ > 装户视角:`flow-kit doctor` §7.x 跑同名检查(仅装户,包源环境跳过——包源下永远是 drift);**修漂移用同一条命令**
11
+ > `flow-kit sync-hosts --apply`——2026-10-07 起按**目标根**自动判布局(含 `templates/_agents` + `modules/hosts` → 包源:
12
+ > 比 `templates/_agents` ↔ `modules/hosts/<宿主键>/`;含 `.agents` → 装户:比 `.agents` ↔ 项目根下 `<宿主点目录>/`),
13
+ > 目标根取 `--dir <目录>` > 当前目录。
11
14
 
12
15
  ## 何时跑
13
16
 
@@ -21,8 +24,9 @@ description: 跨宿主适配层同步(正文段 sha 比对 + 用户拍板 +
21
24
  ### 默认 `--diff`(仅报告)
22
25
 
23
26
  ```
24
- node bin/flow-kit.mjs sync-hosts --diff
25
- node bin/flow-kit.mjs sync-hosts --json # 机器可读
27
+ node bin/flow-kit.mjs sync-hosts --diff # 包源仓(在包源根跑)
28
+ node bin/flow-kit.mjs sync-hosts --json # 机器可读
29
+ flow-kit sync-hosts --diff # 装户仓(在装户根跑;或用 --dir <项目根> 指定)
26
30
  ```
27
31
 
28
32
  输出三类:
@@ -56,7 +56,7 @@ node bin/flow-kit.mjs doctor # §6.5 delegations + §6.6 o
56
56
  - 输出测试报告(通过项 / 失败项)
57
57
  - 失败项已修复并复测通过
58
58
  - **关单**(日常闭环点,不依赖是否上 prod):
59
- - 关单前一键过门:`node .agents/scripts/verify.mjs`(npm test + check-loop 固定编排,任一失败非零退出,非绿不关单)
59
+ - 关单前一键过门:`node .agents/scripts/verify.mjs`(npm test + check-loop 固定编排,任一失败非零退出,非绿不关单);**装户仓**(根目录无 `package.json`,工程在子目录)默认 `npm test` 不可跑 → 脚本**显式跳过步骤 1 且不落测试绿凭证**(防假绿)并提示;此时按项目口径手工跑测试,或带 `--test-cmd "<项目测试命令>"` 指定(2026-10-07 papercut)
60
60
  - 新需求:逐条勾验入口 intent「验收标准」,每条补「证据:」(例如:粘贴 CI 运行结果、UI 截图路径、或具体的 commit SHA),intent $\rightarrow$ done;同名 spec/Quick-Plan(若有)仍 approved $\rightarrow$ done。**注意:勾选但缺证据会被 check-loop 拦截(hard-block)**
61
61
  - **approved 留痕提交**(2026-09-30 起):done 确认前确认**本次关单文档**的 approved 态已进 git 历史(越早越好——approved 后即应提交;若尚未,先补提交再 done;门为逐份校验,三件套均关单时逐份各自满足)——confirm-doc 的 done 前置门硬校验(历史未出现「状态: approved」→ 拒绝落账);done 后再提交 done 态与其余改动
62
62
  **确认落态唯一入口**(2026-09-27 起):用户在终端跑 `node .agents/scripts/confirm-doc.mjs <path>` 键入「可以」(draft→approved / approved→done;对话内明确确认后 AI 可 `--delegated "<原话>"` 代录,台账如实记 source/quote——**逐件调用 + 逐件原话**(一次一份,build.md「逐件确认」口径;多份并录被 confirm-doc 拒绝。--delegated 每次传当次实际放行的措辞,不复用同句——复用同句使台账 quote 失去分辨力))。check-loop 15 如实口径:缺记录/指纹不配对 → hard-block 拦截;伪造台账本地不可机器防,留痕供事后对质;done 内容绑定(2026-09-28 起)——**关单编辑(勾验/回填确认结果)先于 done 确认、confirm-doc 是最后一次写入**,此后修订走 superseded 或新 intent。
@@ -7,7 +7,10 @@ description: 跨宿主适配层同步(正文段 sha 比对 + 用户拍板 +
7
7
  # Sync-Hosts · 跨宿主适配层正文段同步
8
8
 
9
9
  > 改权威源(`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 各自原描述)。
10
- > 装户视角:`flow-kit doctor` §7.x 跑同名检查(仅装户,包源环境跳过——包源下永远是 drift)。
10
+ > 装户视角:`flow-kit doctor` §7.x 跑同名检查(仅装户,包源环境跳过——包源下永远是 drift);**修漂移用同一条命令**
11
+ > `flow-kit sync-hosts --apply`——2026-10-07 起按**目标根**自动判布局(含 `templates/_agents` + `modules/hosts` → 包源:
12
+ > 比 `templates/_agents` ↔ `modules/hosts/<宿主键>/`;含 `.agents` → 装户:比 `.agents` ↔ 项目根下 `<宿主点目录>/`),
13
+ > 目标根取 `--dir <目录>` > 当前目录。
11
14
 
12
15
  ## 何时跑
13
16
 
@@ -21,8 +24,9 @@ description: 跨宿主适配层同步(正文段 sha 比对 + 用户拍板 +
21
24
  ### 默认 `--diff`(仅报告)
22
25
 
23
26
  ```
24
- node bin/flow-kit.mjs sync-hosts --diff
25
- node bin/flow-kit.mjs sync-hosts --json # 机器可读
27
+ node bin/flow-kit.mjs sync-hosts --diff # 包源仓(在包源根跑)
28
+ node bin/flow-kit.mjs sync-hosts --json # 机器可读
29
+ flow-kit sync-hosts --diff # 装户仓(在装户根跑;或用 --dir <项目根> 指定)
26
30
  ```
27
31
 
28
32
  输出三类:
@@ -56,7 +56,7 @@ node bin/flow-kit.mjs doctor # §6.5 delegations + §6.6 o
56
56
  - 输出测试报告(通过项 / 失败项)
57
57
  - 失败项已修复并复测通过
58
58
  - **关单**(日常闭环点,不依赖是否上 prod):
59
- - 关单前一键过门:`node .agents/scripts/verify.mjs`(npm test + check-loop 固定编排,任一失败非零退出,非绿不关单)
59
+ - 关单前一键过门:`node .agents/scripts/verify.mjs`(npm test + check-loop 固定编排,任一失败非零退出,非绿不关单);**装户仓**(根目录无 `package.json`,工程在子目录)默认 `npm test` 不可跑 → 脚本**显式跳过步骤 1 且不落测试绿凭证**(防假绿)并提示;此时按项目口径手工跑测试,或带 `--test-cmd "<项目测试命令>"` 指定(2026-10-07 papercut)
60
60
  - 新需求:逐条勾验入口 intent「验收标准」,每条补「证据:」(例如:粘贴 CI 运行结果、UI 截图路径、或具体的 commit SHA),intent $\rightarrow$ done;同名 spec/Quick-Plan(若有)仍 approved $\rightarrow$ done。**注意:勾选但缺证据会被 check-loop 拦截(hard-block)**
61
61
  - **approved 留痕提交**(2026-09-30 起):done 确认前确认**本次关单文档**的 approved 态已进 git 历史(越早越好——approved 后即应提交;若尚未,先补提交再 done;门为逐份校验,三件套均关单时逐份各自满足)——confirm-doc 的 done 前置门硬校验(历史未出现「状态: approved」→ 拒绝落账);done 后再提交 done 态与其余改动
62
62
  **确认落态唯一入口**(2026-09-27 起):用户在终端跑 `node .agents/scripts/confirm-doc.mjs <path>` 键入「可以」(draft→approved / approved→done;对话内明确确认后 AI 可 `--delegated "<原话>"` 代录,台账如实记 source/quote——**逐件调用 + 逐件原话**(一次一份,build.md「逐件确认」口径;多份并录被 confirm-doc 拒绝。--delegated 每次传当次实际放行的措辞,不复用同句——复用同句使台账 quote 失去分辨力))。check-loop 15 如实口径:缺记录/指纹不配对 → hard-block 拦截;伪造台账本地不可机器防,留痕供事后对质;done 内容绑定(2026-09-28 起)——**关单编辑(勾验/回填确认结果)先于 done 确认、confirm-doc 是最后一次写入**,此后修订走 superseded 或新 intent。
@@ -8,7 +8,10 @@ description: 跨宿主适配层同步(正文段 sha 比对 + 用户拍板 +
8
8
  # Sync-Hosts · 跨宿主适配层正文段同步
9
9
 
10
10
  > 改权威源(`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 各自原描述)。
11
- > 装户视角:`flow-kit doctor` §7.x 跑同名检查(仅装户,包源环境跳过——包源下永远是 drift)。
11
+ > 装户视角:`flow-kit doctor` §7.x 跑同名检查(仅装户,包源环境跳过——包源下永远是 drift);**修漂移用同一条命令**
12
+ > `flow-kit sync-hosts --apply`——2026-10-07 起按**目标根**自动判布局(含 `templates/_agents` + `modules/hosts` → 包源:
13
+ > 比 `templates/_agents` ↔ `modules/hosts/<宿主键>/`;含 `.agents` → 装户:比 `.agents` ↔ 项目根下 `<宿主点目录>/`),
14
+ > 目标根取 `--dir <目录>` > 当前目录。
12
15
 
13
16
  ## 何时跑
14
17
 
@@ -22,8 +25,9 @@ description: 跨宿主适配层同步(正文段 sha 比对 + 用户拍板 +
22
25
  ### 默认 `--diff`(仅报告)
23
26
 
24
27
  ```
25
- node bin/flow-kit.mjs sync-hosts --diff
26
- node bin/flow-kit.mjs sync-hosts --json # 机器可读
28
+ node bin/flow-kit.mjs sync-hosts --diff # 包源仓(在包源根跑)
29
+ node bin/flow-kit.mjs sync-hosts --json # 机器可读
30
+ flow-kit sync-hosts --diff # 装户仓(在装户根跑;或用 --dir <项目根> 指定)
27
31
  ```
28
32
 
29
33
  输出三类:
@@ -57,7 +57,7 @@ node bin/flow-kit.mjs doctor # §6.5 delegations + §6.6 o
57
57
  - 输出测试报告(通过项 / 失败项)
58
58
  - 失败项已修复并复测通过
59
59
  - **关单**(日常闭环点,不依赖是否上 prod):
60
- - 关单前一键过门:`node .agents/scripts/verify.mjs`(npm test + check-loop 固定编排,任一失败非零退出,非绿不关单)
60
+ - 关单前一键过门:`node .agents/scripts/verify.mjs`(npm test + check-loop 固定编排,任一失败非零退出,非绿不关单);**装户仓**(根目录无 `package.json`,工程在子目录)默认 `npm test` 不可跑 → 脚本**显式跳过步骤 1 且不落测试绿凭证**(防假绿)并提示;此时按项目口径手工跑测试,或带 `--test-cmd "<项目测试命令>"` 指定(2026-10-07 papercut)
61
61
  - 新需求:逐条勾验入口 intent「验收标准」,每条补「证据:」(例如:粘贴 CI 运行结果、UI 截图路径、或具体的 commit SHA),intent $\rightarrow$ done;同名 spec/Quick-Plan(若有)仍 approved $\rightarrow$ done。**注意:勾选但缺证据会被 check-loop 拦截(hard-block)**
62
62
  - **approved 留痕提交**(2026-09-30 起):done 确认前确认**本次关单文档**的 approved 态已进 git 历史(越早越好——approved 后即应提交;若尚未,先补提交再 done;门为逐份校验,三件套均关单时逐份各自满足)——confirm-doc 的 done 前置门硬校验(历史未出现「状态: approved」→ 拒绝落账);done 后再提交 done 态与其余改动
63
63
  **确认落态唯一入口**(2026-09-27 起):用户在终端跑 `node .agents/scripts/confirm-doc.mjs <path>` 键入「可以」(draft→approved / approved→done;对话内明确确认后 AI 可 `--delegated "<原话>"` 代录,台账如实记 source/quote——**逐件调用 + 逐件原话**(一次一份,build.md「逐件确认」口径;多份并录被 confirm-doc 拒绝。--delegated 每次传当次实际放行的措辞,不复用同句——复用同句使台账 quote 失去分辨力))。check-loop 15 如实口径:缺记录/指纹不配对 → hard-block 拦截;伪造台账本地不可机器防,留痕供事后对质;done 内容绑定(2026-09-28 起)——**关单编辑(勾验/回填确认结果)先于 done 确认、confirm-doc 是最后一次写入**,此后修订走 superseded 或新 intent。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-flow-kit",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "AI-Native 闭环工作流 + wiki 知识层脚手架——flow-kit init 一条命令为新项目装好 .agents 工作流引擎(阶段命令/角色契约/门禁钩子/kb 检索/看板/规则面预算)+ workflow 文档闭环 + wiki 知识库,装完自包含、零运行时依赖",
5
5
  "type": "module",
6
6
  "scripts": {
package/src/cli.mjs CHANGED
@@ -52,7 +52,9 @@ init 选项(全部可选,均有默认值):
52
52
  --force 覆盖已存在的同名文件(默认保守跳过)
53
53
 
54
54
  sync / add-host 选项:--dir <目录>、--force(覆盖本地已改 / 已装内容);add-gate 选项:--dir <目录>、--force。
55
- sync-hosts 选项:--diff(默认,仅报告,不修改)/ --apply(单向同步到薄适配)/ --json(机器可读输出)。
55
+ sync-hosts 选项:--diff(默认,仅报告,不修改)/ --apply(单向同步到薄适配)/ --json(机器可读输出)/ --dir <目录>(目标项目根,默认当前目录)。
56
+ sync-hosts 双布局(2026-10-07):包源仓(含 templates/_agents + modules/hosts)比对 templates/_agents ↔ modules/hosts;
57
+ 装户仓(含 .agents)比对 .agents ↔ 各宿主目录(.opencode/.trae/.omp/.zcode…)——同一命令两处都可用。
56
58
 
57
59
  示例:
58
60
  npx agentic-flow-kit init # 交互模式:宿主 → 技术栈 → 端口 → 确认安装
@@ -45,17 +45,19 @@ function listMd(dir) {
45
45
  // pairsFor:权威源文件 → 薄适配 rel 列表(映射单源见 profiles.mjs#HOSTS.commandPrefix)
46
46
  // commands 权威源 → 带 commandPrefix 的宿主各一份(<dir>/commands/<prefix><name>.md)
47
47
  // roles 权威源 → 全部宿主 agents 各一份
48
- function pairsFor(authRel) {
48
+ // hostDirOf:宿主 → 适配目录名。包源布局 = 宿主键(modules/hosts/opencode/…);装户布局 = HOSTS[h].dir
49
+ // (项目根下 .opencode/…,带点)——2026-10-07 sync-hosts-target-fix 加装户支持时引入。
50
+ function pairsFor(authRel, hostDirOf = (h) => h) {
49
51
  const out = [];
50
52
  const norm = authRel.split(path.sep).join('/');
51
53
  if (norm.startsWith('commands/') && norm.endsWith('.md')) {
52
54
  const name = norm.slice('commands/'.length, -'.md'.length);
53
55
  for (const [h, v] of Object.entries(HOSTS)) {
54
- if (v.commandPrefix) out.push({ adapterRel: `${h}/commands/${v.commandPrefix}${name}.md` });
56
+ if (v.commandPrefix) out.push({ adapterRel: `${hostDirOf(h)}/commands/${v.commandPrefix}${name}.md` });
55
57
  }
56
58
  } else if (norm.startsWith('roles/') && norm.endsWith('.md')) {
57
59
  const name = norm.slice('roles/'.length, -'.md'.length);
58
- for (const h of Object.keys(HOSTS)) out.push({ adapterRel: `${h}/agents/${name}.md` });
60
+ for (const h of Object.keys(HOSTS)) out.push({ adapterRel: `${hostDirOf(h)}/agents/${name}.md` });
59
61
  }
60
62
  return out;
61
63
  }
@@ -63,12 +65,13 @@ function pairsFor(authRel) {
63
65
  // diffHosts:权威源正文段 vs 薄适配正文段的漂移分析(B-b 语义;pure function)。
64
66
  // authorityRoot:权威源根(含 commands/ + roles/)
65
67
  // adaptersRoot:薄适配根(含 <h>/{agents,commands}/)
68
+ // hostDirOf:宿主 → 适配目录名(默认宿主键 = 包源布局;装户布局传 (h) => HOSTS[h].dir)
66
69
  // 返回:{ drift, inSync, authorityMissing, adapterOrphans, note }
67
- // drift = 正文段 sha 不一致(权威源改 / 薄适配手改 都计入;不区分方向)
68
- // inSync = 正文段 sha 对齐的文件对数
69
- // authorityMissing = 权威源声明但薄适配文件不存在(apply 不自动创建——薄适配须经 add-host 接管)
70
- // adapterOrphans = 薄适配存在但权威源无对应文件(apply 不删——可能是宿主特化或历史残留)
71
- export function diffHosts({ authorityRoot, adaptersRoot }) {
70
+ // drift = 正文段 sha 不一致(权威源改 / 薄适配手改 都计入;不区分方向)
71
+ // inSync = 正文段 sha 对齐的文件对数
72
+ // authorityMissing = 权威源声明但薄适配文件不存在(apply 不自动创建——薄适配须经 add-host 接管)
73
+ // adapterOrphans = 薄适配存在但权威源无对应文件(apply 不删——可能是宿主特化或历史残留)
74
+ export function diffHosts({ authorityRoot, adaptersRoot, hostDirOf = (h) => h }) {
72
75
  if (!fs.existsSync(authorityRoot)) return { drift: [], inSync: 0, authorityMissing: [], adapterOrphans: [], note: `权威源根不存在:${authorityRoot}` };
73
76
 
74
77
  const drift = [];
@@ -83,14 +86,16 @@ export function diffHosts({ authorityRoot, adaptersRoot }) {
83
86
  const authRel = `${sub}/${f}`;
84
87
  const authAbs = path.join(authorityRoot, authRel);
85
88
  const authSha = bodySha(authAbs);
86
- const pairs = pairsFor(authRel);
89
+ const pairs = pairsFor(authRel, hostDirOf);
87
90
  if (pairs.length === 0) continue;
88
91
  for (const { adapterRel } of pairs) {
89
92
  adapterSeen.add(adapterRel);
90
93
  const adapterAbs = path.join(adaptersRoot, adapterRel);
91
94
  const adapterSha = bodySha(adapterAbs);
92
95
  if (adapterSha === null) {
93
- authorityMissing.push({ authRel, adapterRel });
96
+ // 未安装的宿主不算「缺失」——那是没装,不是漂移(2026-10-07:装户只装部分宿主时,
97
+ // 旧行为会把未装宿主的全部适配文件列成 authorityMissing,装户 --apply 恒 exit 1 且刷屏)
98
+ if (fs.existsSync(path.dirname(adapterAbs))) authorityMissing.push({ authRel, adapterRel });
94
99
  continue;
95
100
  }
96
101
  if (authSha === adapterSha) { inSync++; continue; }
@@ -103,9 +108,9 @@ export function diffHosts({ authorityRoot, adaptersRoot }) {
103
108
  const adapterOrphans = [];
104
109
  for (const h of Object.keys(HOSTS)) {
105
110
  for (const sub of ['agents', 'commands']) {
106
- const subAbs = path.join(adaptersRoot, h, sub);
111
+ const subAbs = path.join(adaptersRoot, hostDirOf(h), sub);
107
112
  for (const f of listMd(subAbs)) {
108
- const adapterRel = `${h}/${sub}/${f}`;
113
+ const adapterRel = `${hostDirOf(h)}/${sub}/${f}`;
109
114
  if (adapterSeen.has(adapterRel)) continue;
110
115
  let authGuess;
111
116
  const prefix = HOSTS[h] && HOSTS[h].commandPrefix;
@@ -168,24 +173,42 @@ function applyForward({ authorityRoot, adaptersRoot }, drift) {
168
173
  export function syncHosts(args, pkgRoot) {
169
174
  let apply = false;
170
175
  let json = false;
171
- for (const a of args) {
176
+ let dir = null;
177
+ for (let i = 0; i < args.length; i++) {
178
+ const a = args[i];
172
179
  if (a === '--diff') apply = false;
173
180
  else if (a === '--apply') apply = true;
174
181
  else if (a === '--json') json = true;
182
+ else if (a === '--dir') { dir = args[++i]; if (!dir) fail('--dir 缺少参数(目标项目根)'); }
175
183
  else fail(`未知选项:${a}(flow-kit sync-hosts --help)`);
176
184
  }
177
185
  if (!pkgRoot) fail('sync-hosts 缺少 pkgRoot(开发模式入口)');
178
186
 
179
- const authorityRoot = path.join(pkgRoot, 'templates', '_agents');
180
- const adaptersRoot = path.join(pkgRoot, 'modules', 'hosts');
181
- const result = diffHosts({ authorityRoot, adaptersRoot });
187
+ // 目标根:--dir > cwd > pkgRoot(兜底)。
188
+ // 2026-10-07 sync-hosts-target-fix:此前恒用 pkgRoot——装户里跑 `flow-kit sync-hosts` 时 pkgRoot
189
+ // 解析为**包安装目录**,于是 doctor §7.x 报漂移、照提示跑 `--apply` 会去改包源仓(装户自己的适配层纹丝不动)。
190
+ const target = path.resolve(dir || process.cwd() || pkgRoot);
191
+ // 布局判定(与 doctor.checkAdapterDrift 同口径):
192
+ // 包源(templates/_agents 与 modules/hosts 同时存在)→ 权威源 = <target>/templates/_agents,薄适配根 = <target>/modules/hosts
193
+ // 装户(其余)→ 权威源 = <target>/.agents,薄适配根 = <target>(宿主目录 .opencode/.trae/… 直接位于项目根)
194
+ const isSourceRepo = fs.existsSync(path.join(target, 'templates', '_agents'))
195
+ && fs.existsSync(path.join(target, 'modules', 'hosts'));
196
+ const authorityRoot = isSourceRepo ? path.join(target, 'templates', '_agents') : path.join(target, '.agents');
197
+ const adaptersRoot = isSourceRepo ? path.join(target, 'modules', 'hosts') : target;
198
+ if (!fs.existsSync(authorityRoot)) {
199
+ fail(`未找到权威源目录:${authorityRoot}——目标根 ${target} 既非包源(无 templates/_agents)也非装户(无 .agents);用 --dir <项目根> 指定`);
200
+ }
201
+ const layout = isSourceRepo ? '包源' : '装户';
202
+ // 适配目录名:包源 = 宿主键(modules/hosts/opencode/…);装户 = HOSTS[h].dir(项目根下 .opencode/…)
203
+ const hostDirOf = isSourceRepo ? (h) => h : (h) => (HOSTS[h] && HOSTS[h].dir) || h;
204
+ const result = diffHosts({ authorityRoot, adaptersRoot, hostDirOf });
182
205
 
183
206
  if (apply && result.drift.length > 0) {
184
207
  const { synced } = applyForward({ authorityRoot, adaptersRoot }, result.drift);
185
- console.log(`▶ flow-kit sync-hosts --apply → ${pkgRoot}`);
208
+ console.log(`▶ flow-kit sync-hosts --apply → ${target}(${layout}布局)`);
186
209
  console.log(` 按权威源正文覆盖薄适配正文段 ${synced.length} 份(薄适配 frontmatter 不动):`);
187
210
  for (const rel of synced) console.log(` - ${rel}`);
188
- const after = diffHosts({ authorityRoot, adaptersRoot });
211
+ const after = diffHosts({ authorityRoot, adaptersRoot, hostDirOf });
189
212
  console.log(` 同步后正文对齐:${after.inSync} 对;权威源缺失:${after.authorityMissing.length};正文漂移:${after.drift.length}`);
190
213
  return after.drift.length === 0 && after.authorityMissing.length === 0 ? 0 : 1;
191
214
  }
@@ -193,7 +216,7 @@ export function syncHosts(args, pkgRoot) {
193
216
  if (json) {
194
217
  process.stdout.write(JSON.stringify(result, null, 2) + '\n');
195
218
  } else {
196
- console.log(`▶ flow-kit sync-hosts --diff → ${pkgRoot}`);
219
+ console.log(`▶ flow-kit sync-hosts --diff → ${target}(${layout}布局)`);
197
220
  printDiff(result);
198
221
  }
199
222
  return 0;
@@ -1,9 +1,10 @@
1
1
  // sync-hosts.test.mjs — flow-kit sync-hosts B-b 语义四场景(2026-09-25)
2
2
  // 方法:迷你 fixture 包根(权威源 templates/_agents + 薄适配 modules/hosts/<h>/{agents,commands}/
3
3
  // 与权威源正文段一致,frontmatter 各异)+ 子进程 driver 调真实 sync-hosts(隔离 process.exit)
4
- // 判据:①全对齐 → inSync=28, drift 空 ②权威源改 → drift 列 ③apply → 正文一致,frontmatter 各自保留
5
- // ④薄适配 frontmatter 手改 → 不进 drift ⑤薄适配正文手改 → drift 列,apply 覆盖
6
- // ⑥薄适配缺失 → authorityMissing 列;apply 不自动创建
4
+ // 判据:①全对齐 → inSync=28, drift 空 ②权威源改 → drift 列 ③apply → 正文一致,frontmatter 各自保留
5
+ // ④薄适配 frontmatter 手改 → 不进 drift ⑤薄适配正文手改 → drift 列,apply 覆盖
6
+ // ⑥薄适配缺失 → authorityMissing 列;apply 不自动创建
7
+ // ⑦--json ⑧孤儿薄适配 ⑨装户布局(--dir / cwd 指向装户根 → 按 .agents ↔ 宿主目录比对)
7
8
  // 用法:node src/sync-hosts.test.mjs
8
9
  import fs from 'node:fs';
9
10
  import path from 'node:path';
@@ -66,13 +67,25 @@ function mkFixture() {
66
67
  }
67
68
 
68
69
  // ---- 子进程 driver:调真实 sync-hosts ----
69
- function runSyncHosts(fixtureRoot, extra = []) {
70
+ // 2026-10-07 起 sync-hosts 目标根 = --dir > cwd > pkgRoot,故测试必须用 --dir 锁定 fixture,
71
+ // 否则会落到「跑测试时所在的仓库」(实仓 = 包源,会把断言全带偏)。
72
+ function runSyncHosts(fixtureRoot, extra = [], opts = {}) {
70
73
  const driver = path.join(fixtureRoot, 'driver.mjs');
71
74
  W(driver, `import { syncHosts } from ${JSON.stringify(pathToFileURL(path.join(SRC_ROOT, 'sync-hosts.mjs')).href)};
72
75
  const root = ${JSON.stringify(fixtureRoot)};
73
76
  syncHosts(process.argv.slice(2), root);
74
77
  `);
75
- return spawnSync(process.execPath, [driver, ...extra], { encoding: 'utf8' });
78
+ return spawnSync(process.execPath, [driver, '--dir', fixtureRoot, ...extra], { encoding: 'utf8', ...opts });
79
+ }
80
+
81
+ // 不传 --dir 形态:把 cwd 设为 fixture(验「默认当前目录」解析;装户布局靠 cwd 判定)
82
+ function runSyncHostsByCwd(fixtureRoot, extra = []) {
83
+ const driver = path.join(fixtureRoot, 'driver.mjs');
84
+ W(driver, `import { syncHosts } from ${JSON.stringify(pathToFileURL(path.join(SRC_ROOT, 'sync-hosts.mjs')).href)};
85
+ const root = ${JSON.stringify(fixtureRoot)};
86
+ syncHosts(process.argv.slice(2), root);
87
+ `);
88
+ return spawnSync(process.execPath, [driver, ...extra], { encoding: 'utf8', cwd: fixtureRoot });
76
89
  }
77
90
 
78
91
  // ============ 场景 1:全对齐(正文段与权威源一致,frontmatter 各异)→ drift 空 ============
@@ -179,9 +192,44 @@ syncHosts(process.argv.slice(2), root);
179
192
  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')));
180
193
  }
181
194
 
195
+ // ============ 场景 9:装户布局(.agents 为权威源 + 宿主目录为薄适配,无 templates/modules)============
196
+ // 2026-10-07 sync-hosts-target-fix:此前目标根恒为 pkgRoot(= 包安装目录),装户跑 sync-hosts
197
+ // 会去改包源仓。本场景钉住「--dir / cwd 指向装户根 → 按装户布局比对」。
198
+ {
199
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), 'fk-synchosts-inst-'));
200
+ W(path.join(root, '.agents/commands/test.md'),
201
+ `---\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`);
206
+
207
+ // 9a:--dir 指向装户根 → 布局判定「装户」,列出 2 处漂移
208
+ const r1 = runSyncHosts(root, ['--diff']);
209
+ 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);
214
+
215
+ // 9b:不传 --dir(cwd = 装户根)→ 同样命中装户布局(旧行为会误指包源)
216
+ const r2 = runSyncHostsByCwd(root, ['--diff']);
217
+ 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}`);
228
+ }
229
+
182
230
  {
183
- const pkg = path.resolve(SRC_ROOT, '..');
184
- const r = diffHosts({
231
+ const pkg = path.resolve(SRC_ROOT, '..');
232
+ const r = diffHosts({
185
233
  authorityRoot: path.join(pkg, 'templates', '_agents'),
186
234
  adaptersRoot: path.join(pkg, 'modules', 'hosts'),
187
235
  });
@@ -20,7 +20,10 @@ next: .agents/commands/build.md(漂移属 build 改权威源未同步导致的
20
20
  # Sync-Hosts · 跨宿主适配层正文段同步
21
21
 
22
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)。
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 <目录>` > 当前目录。
24
27
 
25
28
  ## 何时跑
26
29
 
@@ -34,8 +37,9 @@ next: .agents/commands/build.md(漂移属 build 改权威源未同步导致的
34
37
  ### 默认 `--diff`(仅报告)
35
38
 
36
39
  ```
37
- node bin/flow-kit.mjs sync-hosts --diff
38
- node bin/flow-kit.mjs sync-hosts --json # 机器可读
40
+ node bin/flow-kit.mjs sync-hosts --diff # 包源仓(在包源根跑)
41
+ node bin/flow-kit.mjs sync-hosts --json # 机器可读
42
+ flow-kit sync-hosts --diff # 装户仓(在装户根跑;或用 --dir <项目根> 指定)
39
43
  ```
40
44
 
41
45
  输出三类: