@givolt/i3-composer-agent 2.3.3 → 2.3.5

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 (49) hide show
  1. package/.agents/plugins/marketplace.json +1 -1
  2. package/.claude/commands/i3-prototype.md +2 -0
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/.claude-plugin/plugin.json +1 -1
  5. package/.codex-plugin/plugin.json +1 -1
  6. package/.gemini/commands/i3-prototype.toml +2 -0
  7. package/README.md +2 -2
  8. package/bin/i3-composer-agent.cjs +18 -15
  9. package/bin/wizard.cjs +12 -52
  10. package/commands/i3-prototype.toml +2 -0
  11. package/docs/codebuddy-setup.md +21 -7
  12. package/docs/codex-setup.md +1 -1
  13. package/docs/other-hosts.md +1 -1
  14. package/docs/workbuddy-setup.md +18 -2
  15. package/hooks/manage.cjs +22 -14
  16. package/package.json +7 -1
  17. package/plugin.json +1 -1
  18. package/scripts/ui-prototype-binding-recovery-test.js +84 -0
  19. package/scripts/ui-prototype-buddy-lifecycle-test.js +97 -0
  20. package/scripts/ui-prototype-codebuddy-hook-test.js +3 -3
  21. package/scripts/ui-prototype-dependencies-test.js +13 -0
  22. package/scripts/ui-prototype-execution-gates-test.js +27 -2
  23. package/scripts/ui-prototype-execution-policy-test.js +12 -1
  24. package/scripts/ui-prototype-recovery-test.js +72 -0
  25. package/skills/i3-ui-prototype/SKILL.md +7 -3
  26. package/skills/i3-ui-prototype/assets/hosts/codebuddy/profile.json +10 -6
  27. package/skills/i3-ui-prototype/references/entry-contract.md +1 -1
  28. package/skills/i3-ui-prototype/references/execution-evidence.md +31 -8
  29. package/skills/i3-ui-prototype/references/interaction-acceptance.md +1 -1
  30. package/skills/i3-ui-prototype/references/project-layout.md +1 -1
  31. package/skills/i3-ui-prototype/scripts/buddy-host.cjs +40 -0
  32. package/skills/i3-ui-prototype/scripts/codebuddy-context.cjs +14 -14
  33. package/skills/i3-ui-prototype/scripts/codebuddy-hook.cjs +90 -36
  34. package/skills/i3-ui-prototype/scripts/codebuddy-ide-source.cjs +3 -3
  35. package/skills/i3-ui-prototype/scripts/codebuddy-registration.cjs +7 -5
  36. package/skills/i3-ui-prototype/scripts/execution-assertions.cjs +1 -1
  37. package/skills/i3-ui-prototype/scripts/execution-evidence.cjs +45 -14
  38. package/skills/i3-ui-prototype/scripts/execution-gates.cjs +30 -5
  39. package/skills/i3-ui-prototype/scripts/execution-policy.cjs +28 -7
  40. package/skills/i3-ui-prototype/scripts/execution-recovery.cjs +57 -0
  41. package/skills/i3-ui-prototype/scripts/execution-runtime.cjs +8 -3
  42. package/skills/i3-ui-prototype/scripts/hosts/codebuddy.cjs +9 -5
  43. package/skills/i3-ui-prototype/scripts/native-command.cjs +35 -0
  44. package/skills/i3-ui-prototype/scripts/native-pilot-lib.cjs +2 -4
  45. package/skills/i3-ui-prototype/scripts/native-pilot.cjs +5 -1
  46. package/skills/i3-ui-prototype/scripts/native-tool-name.cjs +5 -0
  47. package/skills/i3-ui-prototype/scripts/prototype-dependencies.cjs +28 -6
  48. package/skills/i3-ui-prototype/scripts/prototype-hooks.cjs +13 -13
  49. package/skills/i3-ui-prototype/scripts/prototype-locations.cjs +1 -1
@@ -6,7 +6,7 @@
6
6
  "plugins": [
7
7
  {
8
8
  "name": "i3-composer-agent",
9
- "version": "2.3.3",
9
+ "version": "2.3.5",
10
10
  "description": "覆盖需求、计划、开发、测试、审查与发布的软件工程技能,默认使用简体中文。",
11
11
  "source": {
12
12
  "source": "local",
@@ -19,3 +19,5 @@ Use the i3-ui-prototype skill in the main session for the user's request below.
19
19
  $ARGUMENTS
20
20
 
21
21
  With no arguments use create; explicit analysis or read-only limits take precedence. Preserve the user's scope, manual edits, fixed inputs and approved baselines. Use supporting engineering, framework, design and browser skills as the working skill requires; keep its workflow and evidence requirements there.
22
+
23
+ For a managed Buddy implementation, execute the Skill's printed absolute execution-begin command on its own and wait for status=bound before writing UI. Follow immediate recovery feedback and retry the blocked operation; an outer tool success does not override an inner stage failure.
@@ -8,7 +8,7 @@
8
8
  "plugins": [
9
9
  {
10
10
  "name": "i3-composer-agent",
11
- "version": "2.3.3",
11
+ "version": "2.3.5",
12
12
  "source": "./",
13
13
  "description": "覆盖需求、计划、开发、测试、审查与发布的软件工程技能,默认使用简体中文。",
14
14
  "homepage": "https://github.com/49780522/i3-composer-agent",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i3-composer-agent",
3
- "version": "2.3.3",
3
+ "version": "2.3.5",
4
4
  "description": "覆盖需求、计划、开发、测试、审查与发布的软件工程技能,默认使用简体中文。",
5
5
  "author": {
6
6
  "name": "Givolt"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i3-composer-agent",
3
- "version": "2.3.3",
3
+ "version": "2.3.5",
4
4
  "description": "覆盖需求、计划、开发、测试、审查与发布的软件工程技能,默认使用简体中文。",
5
5
  "author": {
6
6
  "name": "Givolt"
@@ -18,4 +18,6 @@ Use the i3-ui-prototype skill in the main session for the user's request below.
18
18
  $ARGUMENTS
19
19
 
20
20
  With no arguments use create; explicit analysis or read-only limits take precedence. Preserve the user's scope, manual edits, fixed inputs and approved baselines. Use supporting engineering, framework, design and browser skills as the working skill requires; keep its workflow and evidence requirements there.
21
+
22
+ For a managed Buddy implementation, execute the Skill's printed absolute execution-begin command on its own and wait for status=bound before writing UI. Follow immediate recovery feedback and retry the blocked operation; an outer tool success does not override an inner stage failure.
21
23
  """
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # i3 Composer Agent v2.3.3
1
+ # i3 Composer Agent v2.3.5
2
2
 
3
3
  **Intelligence. Integration. Innovation.**
4
4
 
@@ -25,7 +25,7 @@ WorkBuddy 在第 2 项。上下键移动,空格勾选/取消,回车确认;
25
25
  搜索、翻页和命令参数预选均保留选择。搜索外 `q`、Esc 或 Ctrl-C 取消。
26
26
  确认工具后选择项目/全局范围并确认安装。
27
27
 
28
- 可直接输入工具编号,例如 `1` 选择 CodeBuddy,或 `1,2` 多选,再按回车。CodeBuddy 的安装范围、Hooks、启用组、IDE/CLI、路由、UIUX/antDv 及最终确认均支持数字选择。新范围推荐启用 Hooks,已有安装默认保留现状;升级时要启用 Hooks 请明确选“启用”。UIUX/antDv 可选择安装两项、单项或跳过,之后也可补装。
28
+ 可直接输入工具编号,例如 `1` 选择 CodeBuddy,或 `1,2` 多选,再按回车。安装范围、UIUX/antDv 及最终确认支持数字选择。CodeBuddy/WorkBuddy 默认注册原型审计 Hooks,保留明确禁用状态;无需选择 Hook 组或 IDE/CLI。其他原版 Hook 脚本随包交付,按需通过统一管理器另行启用。UIUX/antDv 可选择安装两项、单项或跳过,之后也可补装。
29
29
 
30
30
  全部目标均安装 26 个技能、共享参考资料,以及完整评测/Hook/脚本配套。
31
31
  全部目标同时提供 10 个命令和 4 个 Agent 角色提示。
@@ -23,6 +23,7 @@ ${pkg.name}
23
23
  npx ${pkg.name} --agents codebuddy,codex --scope project --yes
24
24
  npx ${pkg.name} --codebuddy --scope project --yes --prototype-skills uiux,antdv
25
25
  npx ${pkg.name} prototype-deps check --host codex --scope project --project <project>
26
+ npx ${pkg.name} prototype-deps query --host codebuddy --scope project --project <project> --kind info --component Table
26
27
  npx ${pkg.name} prototype-deps install --host workbuddy --scope global --skills uiux,antdv
27
28
  npx ${pkg.name} hooks list --host codebuddy --scope project --project <project>
28
29
  npx ${pkg.name} --prepare --claude --dir <directory>
@@ -38,11 +39,11 @@ ${pkg.name}
38
39
  --project-dir <dir> 项目安装根目录,默认当前目录
39
40
  --prototype-skills <ids> 可选原型依赖:none、uiux、antdv、uiux,antdv;向导数字选择,--yes 未指定时跳过
40
41
  --migrate-tools 显式迁移有 i3 来源记录的旧独立 antDv 工具;仅项目范围且需选择 antdv
41
- --hooks <action> CodeBuddy 统一 Hooks:keep(非交互默认)/ enable / list / check / disable
42
+ --hooks <action> 默认注册原型 Hooks;keep 保留 / enable / list / check / disable
42
43
  --hook-groups <ids> session-start,sdd-cache,simplify-ignore,prototype 或 all;启停默认 prototype
43
44
  --codebuddy-skill-routing <mode> hook(明确需要会话注入)/ native(已有原生路由)
44
45
  --prototype-hooks <action> 旧参数保留,仅管理 prototype 组
45
- --codebuddy-product <form> 启用时明确 ide 或 cli;CLI 注册后需在 /hooks 审核
46
+ --codebuddy-product <form> 旧版 ide / cli 参数兼容;新注册默认 auto 自动识别
46
47
  --codebuddy-transcript-root <dir|auto> 默认自动识别;可选手动原生日志限制,auto 切回自动
47
48
  --codebuddy-version <version> 实际宿主版本,便于核验记录
48
49
  --yes 确认明确指定的非交互安装
@@ -57,13 +58,13 @@ ${pkg.name}
57
58
 
58
59
  终端向导先显示常用工具,WorkBuddy 在第 2 项;选择“更多”可分页/搜索全部工具。
59
60
  输入工具编号(如 1,2)后回车,或上下键移动/跨页、空格勾选、回车确认;q/Esc 退出。
60
- 范围、Hooks、IDE/CLI、可选原型依赖和最终确认使用数字选择,Hook 组支持逗号分隔数字多选。
61
+ 范围、可选原型依赖和最终确认使用数字选择;默认注册原型 Hooks,不再选择 IDE/CLI 或 Hook 组。
61
62
  CodeBuddy、WorkBuddy、Claude Code 同时安装短命令和 Agent 角色。
62
63
  其他工具通过 Skills 调用,短命令支持取决于宿主。
63
64
  所有工具默认安装单份 skills、commands、agents;配套资料集中在 i3-composer-agent/。
64
65
  评测、脚本和 Hook 读取同一份已安装技能。--prepare 用于另行导出标准插件并按宿主方式注册。
65
66
  WorkBuddy 桌面版建议全局安装,便于技能列表和输入补全发现。
66
- 评测需主动运行;向导可注册 CodeBuddy Hooks,实际生效仍需宿主审核/重载和回调验证。
67
+ 评测需主动运行;CodeBuddy/WorkBuddy 默认注册原型 Hooks,保留明确禁用状态。实际生效需宿主审核/重载和回调验证。
67
68
  --prepare 仅供插件管理器安装方式使用,不自动注册插件或启用 Hook。
68
69
  `;
69
70
 
@@ -170,7 +171,7 @@ async function main() {
170
171
  if (args.length === 1 && args[0] === '--version') { console.log(pkg.version); return; }
171
172
  if (args[0] === 'prototype-deps') {
172
173
  const dependencies = require('../skills/i3-ui-prototype/scripts/prototype-dependencies.cjs');
173
- console.log(JSON.stringify(await dependencies.main(args.slice(1)), null, 2));
174
+ const result=await dependencies.main(args.slice(1));console.log(JSON.stringify(result, null, 2));if(result.status==='failed')process.exitCode=1;
174
175
  return;
175
176
  }
176
177
  if (['hooks','prototype-hooks'].includes(args[0])) {
@@ -200,7 +201,7 @@ async function main() {
200
201
  else if (arg === '--hooks') {if(!['keep','enable','disable','list','check'].includes(value))throw new Error('Hooks 请选择 keep / enable / disable / list / check');options.hooks=value;}
201
202
  else if (arg === '--hook-groups') {require('../hooks/manage.cjs').selection(value);options.hookGroups=value;}
202
203
  else if (arg === '--codebuddy-skill-routing') {if(!['native','hook'].includes(value))throw new Error('请选择 native 或 hook');options.codebuddySkillRouting=value;}
203
- else if (arg === '--codebuddy-product') {if(!['ide','cli'].includes(value))throw new Error('CodeBuddy 形态请选择 ide 或 cli');options.codebuddyProduct=value;}
204
+ else if (arg === '--codebuddy-product') {if(!['auto','ide','cli'].includes(value))throw new Error('CodeBuddy 形态请选择 auto、ide 或 cli');options.codebuddyProduct=value;}
204
205
  else if (arg === '--codebuddy-transcript-root') options.codebuddyTranscriptRoot=value==='auto'?'auto':path.resolve(value);
205
206
  else if (arg === '--codebuddy-version') options.codebuddyVersion=value;
206
207
  else options.projectDir = path.resolve(value);
@@ -216,9 +217,9 @@ async function main() {
216
217
  }
217
218
  options.agents = installer.selectAgents(options.agents);
218
219
  if(options.prototypeHooks!==undefined&&(options.hooks!==undefined||options.hookGroups!==undefined))throw new Error('--prototype-hooks 旧参数不可与 --hooks / --hook-groups 混用');
219
- const hookOptions=()=>({action:options.hooks||options.prototypeHooks||'keep',groups:options.hookGroups||(options.prototypeHooks!==undefined?'prototype':undefined),skillRouting:options.codebuddySkillRouting,host:'codebuddy',scope:options.scope,project:options.projectDir,product:options.codebuddyProduct,transcriptRoot:options.codebuddyTranscriptRoot,productVersion:options.codebuddyVersion,agents:options.agents});
220
+ const hookOptions=(host=options.agents.find(id=>['codebuddy','workbuddy'].includes(id))||'codebuddy')=>({action:options.hooks||options.prototypeHooks||'default',groups:options.hookGroups||(options.prototypeHooks!==undefined?'prototype':undefined),skillRouting:options.codebuddySkillRouting,host,scope:options.scope,project:options.projectDir,product:options.codebuddyProduct,transcriptRoot:options.codebuddyTranscriptRoot,productVersion:options.codebuddyVersion,agents:options.agents});
220
221
  if(['list','check','disable'].includes(hookOptions().action)) {
221
- if(options.agents.length!==1||options.agents[0]!=='codebuddy'||!options.scope)throw new Error('Hooks check / disable 需明确 --codebuddy --scope project|global,不执行安装');
222
+ if(options.agents.length!==1||!['codebuddy','workbuddy'].includes(options.agents[0])||!options.scope)throw new Error('Hooks check / disable 需明确一个 Buddy 宿主和 --scope project|global,不执行安装');
222
223
  const manager=require('../hooks/manage.cjs');
223
224
  const result=['list','check'].includes(hookOptions().action)?manager.check(hookOptions()):manager.configure({...hookOptions(),preview:!!options.dryRun});
224
225
  console.log(JSON.stringify(result,null,2));if(result.status==='failed')process.exitCode=1;return;
@@ -231,22 +232,24 @@ async function main() {
231
232
  throw new Error('请在交互终端使用向导,或明确指定 --agents <ids> --scope project|global --yes。');
232
233
  }
233
234
  if (options.migrateTools && (options.scope !== 'project' || !options.prototypeSkills?.split(',').includes('antdv'))) throw new Error('--migrate-tools requires project scope and selected antdv');
234
- if(hookOptions().action!=='keep'&&!options.agents.includes('codebuddy'))throw new Error('首期统一 Hooks 仅适配 CodeBuddy');
235
+ const buddyHosts=options.agents.filter(id=>['codebuddy','workbuddy'].includes(id));
236
+ if(!['keep','default'].includes(hookOptions().action)&&!buddyHosts.length)throw new Error('原型 Hooks 当前适配 CodeBuddy 和 WorkBuddy');
235
237
  const hookManager=require('../hooks/manage.cjs');
236
- const hookChange=options.agents.includes('codebuddy')?hookManager.prepare(hookOptions()):null;
238
+ const hookChanges=(options.scope==='project'?buddyHosts.slice(0,1):buddyHosts).map(host=>hookManager.prepare(hookOptions(host)));
239
+ const hookSummary=hookChanges.length===1?hookChanges[0].summary:hookChanges.map(change=>change.summary);
237
240
  const plan = installer.planInstallation(options);
238
241
  if (options.dryRun) {
239
242
  console.log(JSON.stringify({ name, version: pkg.version, mode: plan.mode, scope: plan.scope, agents: plan.agents, targets: plan.targets, conflicts: plan.conflicts, reused: plan.reused,
240
- ...(options.prototypeSkills !== undefined ? { optionalPrototypeSkills: options.prototypeSkills, migrateTools: !!options.migrateTools } : {}),...(hookChange?{hooks:hookChange.summary}:{}) }, null, 2));
243
+ ...(options.prototypeSkills !== undefined ? { optionalPrototypeSkills: options.prototypeSkills, migrateTools: !!options.migrateTools } : {}),...(hookChanges.length?{hooks:hookSummary}:{}) }, null, 2));
241
244
  return;
242
245
  }
243
246
  if (!options.yes) {
244
- const confirmed = await require('./wizard.cjs').confirm(plan, { prototypeSkills: options.prototypeSkills, hooks: hookChange?.summary });
247
+ const confirmed = await require('./wizard.cjs').confirm(plan, { prototypeSkills: options.prototypeSkills, hooks: hookChanges.length?hookSummary:null });
245
248
  if (!confirmed) { console.log('安装已取消,未修改文件。'); return; }
246
249
  options.force = plan.conflicts.length > 0;
247
250
  }
248
251
  installer.executeInstallation(plan, { force: options.force });
249
- if(hookChange?.summary.changed) {
252
+ for(const hookChange of hookChanges)if(hookChange.summary.changed) {
250
253
  try {console.log(JSON.stringify({hooks:hookManager.apply(hookChange)},null,2));}
251
254
  catch(error){throw new Error(`核心文件已安装,Hooks 注册未完成;请保留当前配置并重试或提供错误。${error.message}`);}
252
255
  }
@@ -259,13 +262,13 @@ async function main() {
259
262
  console.log(`评测资料:${target.evalsDirectory}`);
260
263
  console.log(`完整校验:进入 "${target.toolkitDirectory}" 后运行 npm test`);
261
264
  console.log(`中文评测:node "${path.join(target.scriptsDirectory, 'run-evals.js')}" --locale zh-CN --min-rank1 95`);
262
- console.log(`Hooks:${target.hooksDirectory}${target.agents.includes('codebuddy')?';统一检查:node "'+path.join(target.hooksDirectory,'manage.cjs')+'" check --host codebuddy --scope '+plan.scope+' --project "'+options.projectDir+'"':';按宿主协议手动配置'}`);
265
+ console.log(`Hooks:${target.hooksDirectory}${target.agents.some(id=>['codebuddy','workbuddy'].includes(id))?';统一检查:node "'+path.join(target.hooksDirectory,'manage.cjs')+'" check --host '+target.agents.find(id=>['codebuddy','workbuddy'].includes(id))+' --scope '+plan.scope+' --project "'+options.projectDir+'"':';按宿主协议手动配置'}`);
263
266
  }
264
267
  for (const file of plan.preserved || []) console.log(`保留了用户文件:${file}`);
265
268
  console.log('请重新加载 IDE 窗口或新建宿主会话以发现安装内容。');
266
269
  if (plan.agents.some(id => !['codebuddy', 'workbuddy', 'claude-code'].includes(id))) console.log('这些工具通过技能 ID 调用;生命周期短命令支持取决于宿主。');
267
270
  console.log('核心安装完成。评测说明见 i3-composer-agent/evals/README.md。');
268
- if (hookChange) console.log(hookChange.summary.action === 'enable' ? `Hooks 已注册:${hookChange.summary.enabledGroups.join('、')}。${hookChange.summary.product === 'cli' ? '请在 CodeBuddy Code /hooks 审核并开启新会话。' : '请重载 CodeBuddy 窗口。'}实际触发另行检查。` : 'Hooks 保留现状;文件已提供不代表启用,请使用 hooks check 检查当前状态。');
271
+ for(const hookChange of hookChanges)console.log(hookChange.summary.enabledGroups.length?`Hooks 已注册:${hookChange.summary.enabledGroups.join('、')};${hookChange.summary.host},IDE/CLI 自动识别。桌面端重载;CodeBuddy CLI 在 /hooks 审核。实际调用与补调另行验证。`:'Hooks 保留禁用或未启用状态;使用 hooks check 检查。');
269
272
  if (options.prototypeSkills !== undefined && options.prototypeSkills !== 'none') {
270
273
  try {
271
274
  // Shared project targets (for example CodeBuddy + WorkBuddy) prepare once.
package/bin/wizard.cjs CHANGED
@@ -1,8 +1,6 @@
1
1
  'use strict';
2
2
 
3
3
  const readline = require('node:readline');
4
- const fs = require('node:fs');
5
- const path = require('node:path');
6
4
  const { selectAgents } = require('./install.cjs');
7
5
  const { selectTools } = require('./tool-selector.cjs');
8
6
 
@@ -33,12 +31,7 @@ async function menu(ask, prompt, values, fallback) {
33
31
  console.log(`请选择数字 ${Object.keys(values).join('、')},或 0 取消。`);
34
32
  }
35
33
  }
36
- function existingInstallation(options, scope) {
37
- const { base } = require('../hooks/manage.cjs').location({ scope, project: options.projectDir });
38
- return ['.i3-composer-agent.json', 'settings.json', 'settings.local.json', 'state/i3-prototype/installation.json', 'state/i3-composer-agent/hooks.json']
39
- .some(file => fs.existsSync(path.join(base, file)));
40
- }
41
- async function chooseSettings(options, agents, ask, services = {}) {
34
+ async function chooseSettings(options, agents, ask) {
42
35
  let scope = options.scope;
43
36
  while (!scope) {
44
37
  const input = await ask('安装范围:1. 项目(当前项目),2. 全局(所有项目)[1](0/q/取消退出): ');
@@ -47,48 +40,13 @@ async function chooseSettings(options, agents, ask, services = {}) {
47
40
  else if (['2', 'global', '全局'].includes(input)) scope = 'global';
48
41
  else console.log('请选择 1(项目)或 2(全局)。');
49
42
  }
50
- let hooks=options.hooks||options.prototypeHooks||'keep',hookGroups=options.hookGroups||(options.prototypeHooks!==undefined?'prototype':undefined),codebuddyProduct=options.codebuddyProduct,codebuddyTranscriptRoot=options.codebuddyTranscriptRoot,codebuddySkillRouting=options.codebuddySkillRouting;
51
- if (agents.includes('codebuddy') && agents.includes('workbuddy') && options.hooks === undefined && options.prototypeHooks === undefined) {
52
- console.log('CodeBuddy 与 WorkBuddy 本次共享目录,保留现有 Hooks;需要启用时请在 CodeBuddy 独立范围配置。');
53
- } else if (agents.includes('codebuddy')) {
54
- if (options.hooks === undefined && options.prototypeHooks === undefined) {
55
- const existing = (services.existingInstallation || existingInstallation)(options, scope);
56
- const unsupported = process.platform === 'win32';
57
- if (unsupported) console.log('Windows Hooks 引用尚未完成宿主验证,默认保留;核心技能仍可安装。');
58
- const fallback = existing || unsupported ? '2' : '1';
59
- hooks = await menu(ask, `CodeBuddy 统一 Hooks:1. 选择启用${existing || unsupported ? '' : '(首次安装推荐)'},2. 保留现状${existing ? '(已有配置,推荐)' : ''} [${fallback}](0 取消): `, { '1': 'enable', '2': 'keep' }, fallback);
60
- if (hooks === null) return null;
61
- }
62
- if (hooks === 'enable' && !hookGroups) {
63
- console.log('Hook 组:1. 原型执行审计;2. Skill 发现与路由;3. 官方文档请求缓存;4. 代码块简化保护;5. 全部。');
64
- while (!hookGroups) {
65
- const answer = await ask('启用组:输入数字,可多选(例如 1,3,4)[1](0 取消): ');
66
- if (cancelled(answer)) return null;
67
- const numbers = (answer || '1').split(/[,,]/).map(x => x.trim());
68
- if (numbers.every(x => ['1', '2', '3', '4'].includes(x))) hookGroups = [...new Set(numbers)].map(x => ({ '1': 'prototype', '2': 'session-start', '3': 'sdd-cache', '4': 'simplify-ignore' })[x]).join(',');
69
- else if (numbers.length === 1 && numbers[0] === '5') hookGroups = 'all';
70
- else console.log('请选择 1、2、3、4(可逗号多选),或 5(全部)。');
71
- }
72
- }
73
- const chosen=require('../hooks/manage.cjs').selection(hookGroups,hooks);
74
- if (hooks === 'enable' && !codebuddyProduct) {
75
- codebuddyProduct = await menu(ask, 'CodeBuddy 形态:1. 桌面 IDE,2. CodeBuddy Code CLI [1](0 取消): ', { '1': 'ide', '2': 'cli' }, '1');
76
- if (codebuddyProduct === null) return null;
77
- }
78
- if (hooks === 'enable' && chosen.includes('session-start')) {
79
- if (!codebuddySkillRouting) {
80
- codebuddySkillRouting = await menu(ask, 'Skill 路由:1. 需要 Hook 会话提示,2. 已有原生路由(自动去除 Skill 发现组)[1](0 取消): ', { '1': 'hook', '2': 'native' }, '1');
81
- if (codebuddySkillRouting === null) return null;
82
- }
83
- if (codebuddySkillRouting === 'native') {
84
- const remaining = chosen.filter(id => id !== 'session-start');
85
- hookGroups = remaining.length ? remaining.join(',') : undefined;
86
- if (!remaining.length) hooks = 'keep';
87
- console.log('已选择原生路由,本次不新增 session-start;其余所选组保留,已有配置不会被移除。');
88
- }
89
- }
90
- if(hooks==='enable'&&chosen.includes('prototype')&&!codebuddyTranscriptRoot)console.log('新启用的原型审计默认从 Hook 自动识别会话日志;升级保留已有手动限制。特殊环境可使用 --codebuddy-transcript-root <目录|auto>。');
91
- }
43
+ const supported=agents.some(host=>['codebuddy','workbuddy'].includes(host));
44
+ let hooks=options.hooks||options.prototypeHooks||(supported?'default':'keep');
45
+ const hookGroups=options.hookGroups||'prototype',codebuddyProduct=options.codebuddyProduct,
46
+ codebuddyTranscriptRoot=options.codebuddyTranscriptRoot,codebuddySkillRouting=options.codebuddySkillRouting;
47
+ if(process.platform==='win32'&&hooks==='default'){
48
+ hooks='keep';console.log('Windows 原型 Hooks 尚待实机验证,本次保留设置。');
49
+ }else if(supported&&hooks==='default')console.log('默认注册原型审计 Hooks;保留明确禁用状态。IDE/CLI 运行时自动识别,其他 Hook 组不新增注册。');
92
50
  let prototypeSkills = options.prototypeSkills;
93
51
  if (prototypeSkills === undefined) {
94
52
  console.log('可选原型依赖:所选项将联网下载官方固定版本,安装到本次宿主范围;已有可用内容复用。');
@@ -116,8 +74,10 @@ async function confirm(plan, selection = {}) {
116
74
  if (plan.conflicts.length) console.log(`将替换 ${plan.conflicts.length} 个已有内容;安装成功后清理旧文件,失败则恢复。`);
117
75
  if (plan.reused.length) console.log(`将复用同版本的 ${plan.reused.length} 个未修改内容。`);
118
76
  if (selection.hooks) {
119
- console.log(`CodeBuddy Hooks:${selection.hooks.action === 'enable' ? '启用 ' + selection.hooks.groups.join('、') : '保留现状'}${selection.hooks.product ? ';' + (selection.hooks.product === 'ide' ? '桌面 IDE' : 'CLI') : ''}。`);
120
- if (selection.hooks.action === 'enable') console.log(selection.hooks.product === 'cli' ? '注册后仍需在 CodeBuddy Code /hooks 审核并开启新会话。' : '注册后请重载 CodeBuddy 窗口验证实际回调。');
77
+ for(const hook of Array.isArray(selection.hooks)?selection.hooks:[selection.hooks]){
78
+ console.log(`${hook.host} Hooks:${hook.action==='enable'?'注册 '+hook.groups.join('、'):'保留现状'};IDE/CLI 自动识别。`);
79
+ console.log('桌面端重载;CodeBuddy CLI 在 /hooks 审核。真实调用和补调须在宿主验证。');
80
+ }
121
81
  }
122
82
  if (selection.prototypeSkills !== undefined) console.log(`可选依赖:${selection.prototypeSkills === 'none' ? '跳过' : selection.prototypeSkills.split(',').map(id => id === 'uiux' ? 'UIUX Pro Max' : 'antDv 官方 Skill 与工具').join('、')}。`);
123
83
  console.log('包含技能、共享资料和完整评测/Hook/脚本配套。安装不执行评测。');
@@ -18,4 +18,6 @@ Use the i3-ui-prototype skill in the main session for the user's request below.
18
18
  $ARGUMENTS
19
19
 
20
20
  With no arguments use create; explicit analysis or read-only limits take precedence. Preserve the user's scope, manual edits, fixed inputs and approved baselines. Use supporting engineering, framework, design and browser skills as the working skill requires; keep its workflow and evidence requirements there.
21
+
22
+ For a managed Buddy implementation, execute the Skill's printed absolute execution-begin command on its own and wait for status=bound before writing UI. Follow immediate recovery feedback and retry the blocked operation; an outer tool success does not override an inner stage failure.
21
23
  """
@@ -48,7 +48,7 @@ CodeBuddy 与 WorkBuddy 项目共用 `.codebuddy/`;同版本追加客户端会
48
48
  npx @givolt/i3-composer-agent --codebuddy --scope project --yes --prototype-skills uiux,antdv
49
49
  ```
50
50
 
51
- 值为 none、uiux、antdv 或 uiux,antdv;默认 none。可选工具跟随宿主和项目/全局范围,位于基址下 `tools/i3-prototype/`;旧项目 `.prototype-tools` 保持读取兼容。需要固定本次版本时使用 `npx @givolt/i3-composer-agent@2.3.3`。已安装后可随时单独检测/补装,无需重装 i3:
51
+ 值为 none、uiux、antdv 或 uiux,antdv;默认 none。可选工具跟随宿主和项目/全局范围,位于基址下 `tools/i3-prototype/`;旧项目 `.prototype-tools` 保持读取兼容。需要固定本次版本时使用 `npx @givolt/i3-composer-agent@2.3.5`。已安装后可随时单独检测/补装,无需重装 i3:
52
52
 
53
53
  ```bash
54
54
  node .codebuddy/skills/i3-ui-prototype/scripts/prototype-dependencies.cjs check --host codebuddy --scope project --project .
@@ -86,7 +86,7 @@ node .codebuddy/skills/i3-ui-prototype/scripts/prototype-dependencies.cjs instal
86
86
 
87
87
  工具前置使用依赖检测返回的实际 Node 入口,也兼容已有 `.prototype-tools/node_modules` 布局或宿主明确的绝对入口;缺失时只读分析报告未决项,不以 npm exec/npx 下载或补缓存。工具准备须有明确选择,写范围仅指定工具目录,不含业务内容或 SDK。analyze 只交覆盖、选型、验收计划和缺口,不套用创建阶段的 UIUX 采纳、构建或浏览器门禁。
88
88
 
89
- 本轮新原生流程还要求执行者真实调用 `i3-browser-testing-with-devtools` Skill,并使用 Chrome DevTools MCP 对当前构建取得 DOM/计算样式、截图、console、network、可访问性和性能观测。只读取 Skill 文件或运行 Playwright 脚本都不等于调用该 Skill;Playwright 保留为原型专项补充。缺可调用 Skill 或 MCP 时整链不 complete,按已授权范围准备宿主工具后再验;analyze 不启动或安装浏览器。具体工具接入以实际宿主暴露为准,不能从其他会话或维护 smoke 推断当前执行环境可用。旧实例按固定合同保留,其他宿主等效结果单列。
89
+ 本轮新原生流程还要求执行者真实调用 `i3-browser-testing-with-devtools` Skill,并使用 Chrome DevTools MCP 对当前构建取得 DOM/计算样式、截图、console、network、可访问性和性能观测。只读取 Skill 文件或运行 Playwright 脚本都不等于调用该 Skill;Playwright 仅保留给历史设备列表固定合同作专项补充。缺可调用 Skill 或 MCP 时整链不 complete,按已授权范围准备宿主工具后再验;analyze 不启动或安装浏览器。具体工具接入以实际宿主暴露为准,不能从其他会话或维护 smoke 推断当前执行环境可用。旧实例按固定合同保留,其他宿主等效结果单列。
90
90
 
91
91
  新完整模板原生流程默认包含明亮、暗黑、清新、科技,首次默认明亮,菜单无编号;生成工程用原生框架主题,验证四预设、刷新记忆、实例隔离及业务状态保留。旧实例继续按原有固定合同,不隐式增加能力;步骤见首期指南。
92
92
 
@@ -106,7 +106,7 @@ node .codebuddy/skills/i3-ui-prototype/scripts/native-pilot.cjs preview prototyp
106
106
 
107
107
  在业务项目运行 `node .codebuddy/i3-composer-agent/scripts/run-evals.js --min-rank1 95`,
108
108
  可检查中英文触发,不调用模型;进入 `.codebuddy/i3-composer-agent/` 可运行 `npm test` 和 `node scripts/run-evals.js --locale zh-CN --min-rank1 95`。全局安装使用脚本的全局绝对路径。五项校验、行为评测和样例用法见
109
- [评测说明](../evals/README.md)。Hooks 默认只分发,统一管理如下。
109
+ [评测说明](../evals/README.md)。CodeBuddy/WorkBuddy 默认注册原型审计 Hooks,其他组按需管理。
110
110
 
111
111
  ## CodeBuddy 统一 Hooks 管理
112
112
 
@@ -121,13 +121,13 @@ node .codebuddy/i3-composer-agent/hooks/manage.cjs enable --host codebuddy --sco
121
121
  node .codebuddy/i3-composer-agent/hooks/manage.cjs disable --host codebuddy --scope project --project . --groups sdd-cache
122
122
  ```
123
123
 
124
- 全局改用 `~/.codebuddy/i3-composer-agent/hooks/manage.cjs` 和 `--scope global`,继续指定测试项目来判断有效来源。发行 CLI 可用 `hooks list|check|enable|disable` 子命令;安装时使用 `--hooks enable --hook-groups <ids>`,默认 keep 保留既有开关。启停不指定组时兼容旧用法仅针对 prototype,list/check 默认全部。
124
+ 全局改用 `~/.codebuddy/i3-composer-agent/hooks/manage.cjs` 和 `--scope global`,继续指定测试项目来判断有效来源。发行 CLI 可用 `hooks list|check|enable|disable` 子命令;安装时使用 `--hooks enable --hook-groups <ids>`,默认注册 prototype 并保留明确禁用,显式 keep 保留全部既有开关。启停不指定组时兼容旧用法仅针对 prototype,list/check 默认全部。
125
125
 
126
- `session-start` 需要明确 `--skill-routing hook`,已有原生路由时不选该组;安装器对应 `--codebuddy-skill-routing hook`。上游三组需要 Bash、jq 和相应 SHA 工具,缓存另需 curl,缺依赖会在启用前拒绝;不自动安装。prototype 需要真实 `--product ide|cli`;项目/全局新启用默认从 Hook 自动识别当前会话日志,可选 `--transcript-root <实际目录|auto>`。已有手动限制保留,首次尚无原生事件显示 awaiting-native-event,不能当成已验收。全局跟随绝对 CODEBUDDY_CONFIG_DIR,默认 ~/.codebuddy;不移动原生日志。原型严格证据规则见 Skill 的 execution-evidence 参考资料。
126
+ `session-start` 需要明确 `--skill-routing hook`,已有原生路由时不选该组;安装器对应 `--codebuddy-skill-routing hook`。上游三组需要 Bash、jq 和相应 SHA 工具,缓存另需 curl,缺依赖会在启用前拒绝;不自动安装。prototype 新注册默认 auto 自动识别;旧 `--product ide|cli` 兼容。项目/全局新启用默认从 Hook 自动识别当前会话日志,可选 `--transcript-root <实际目录|auto>`。已有手动限制保留,首次尚无原生事件显示 awaiting-native-event,不能当成已验收。全局跟随绝对 CODEBUDDY_CONFIG_DIR,默认 ~/.codebuddy;不移动原生日志。原型严格证据规则见 Skill 的 execution-evidence 参考资料。
127
127
 
128
128
  配置合并到所选范围 `settings.json`,通用归属在 `state/i3-composer-agent/hooks.json`,原型归属保持 `state/i3-prototype/installation.json`。上游适配缓存在 `<host-base>/cache/i3-composer-agent/hooks/<projectKey>/`;全局按项目隔离。已识别的手动原版注册只报告,不自动接管或重复注册。代码块保护运行时会临时替换文件内容,存在未恢复备份时拒绝移除该组,先结束会话恢复。
129
129
 
130
- IDE 项目设置覆盖全局;CLI 合并后按组选择有效来源避免同组重复执行。CLI 变更后在原生 `/hooks` 审核并新建会话,IDE 重载。文件存在、注册、回调观察与业务验收分别显示;原版 triggered 不表示已验证模型行为。首期仍待用户实际宿主验收,Windows Hooks 未验证,默认不启用的核心安装不受此限制。
130
+ IDE 项目设置覆盖全局;CLI 合并后按组选择有效来源避免同组重复执行。CLI 变更后在原生 `/hooks` 审核并新建会话,IDE 重载。文件存在、注册、回调观察与业务验收分别显示;原版 triggered 不表示已验证模型行为。首期仍待用户实际宿主验收,Windows Hooks 未验证,Windows 默认保留设置并提示尚待实机验证。
131
131
 
132
132
  依据:[CodeBuddy IDE Hooks](https://www.codebuddy.cn/docs/ide/Features/Hooks)、[CodeBuddy CLI Hooks](https://www.codebuddy.cn/docs/cli/hooks)。
133
133
 
@@ -150,7 +150,7 @@ npx @givolt/i3-composer-agent --prepare --codebuddy
150
150
  按宿主选择范围并启用后新建会话。兼容清单声明 `.claude/commands/` 与 `commands/`。
151
151
  插件命令示例为 `/i3-composer-agent:i3-spec`、`/i3-composer-agent:i3-plan`、
152
152
  `/i3-composer-agent:i3-build auto` 和 `/i3-composer-agent:i3-ship`。
153
- 默认安装和导出均包含完整评测、Hook 与脚本;Hook 不自动启用。
153
+ 默认原生安装和导出均包含完整评测、Hook 与脚本;原生安装默认注册 prototype,插件导出不自动启用 Hook。
154
154
  文件落盘、宿主发现和模型实际执行应分别验证。
155
155
 
156
156
  目录遵循 [配置目录参考](https://www.codebuddy.cn/docs/cli/codebuddy-dir),可参照
@@ -158,3 +158,17 @@ npx @givolt/i3-composer-agent --prepare --codebuddy
158
158
  [自定义命令](https://www.codebuddy.cn/docs/ide/User-guide/Slash-Commands) 检查发现与调用。
159
159
 
160
160
  原型共享资料统一在项目 prototypes/:新索引 prototypes/index.json,准备范围 prototypes/.preparation/<id>/scope.json。新原生 scope.moduleIds 自动生成 appliesTo;旧索引、输入和实例保持兼容,安装升级不自动迁移。工具及运行缓存使用所选宿主基址;全局浏览器缓存按业务项目身份隔离。详细规则和只读查询/显式迁移命令见 i3-ui-prototype/references/project-layout.md。
161
+
162
+
163
+ ## 默认原型 Hooks、自动识别与补调
164
+
165
+ 首次项目/全局安装默认注册 prototype,无需选择 IDE 或 CLI,其他上游 Hook 组不新增注册。已有明确禁用保留,显式 --hooks keep 可以跳过;升级保留用户设置与已有其他组。注册不代表已触发;桌面重载、CLI 在 /hooks 审核后按实际项目检查。
166
+
167
+ ```bash
168
+ node .codebuddy/i3-composer-agent/hooks/manage.cjs check --host codebuddy --scope project --project .
169
+ node .codebuddy/i3-composer-agent/hooks/manage.cjs enable --host codebuddy --scope project --project . --groups prototype
170
+ node .codebuddy/i3-composer-agent/hooks/manage.cjs disable --host codebuddy --scope project --project . --groups prototype
171
+ node .codebuddy/skills/i3-ui-prototype/scripts/prototype-dependencies.cjs query --host codebuddy --scope project --project . --kind info --component Table --version 1.5.2
172
+ ```
173
+
174
+ query 使用已准备的本地 Node/CLI,不能代替 antDv Skill 加载;知识版本与目标组件版本分别核对。新实例使用 buddy-ab-v2,旧实例保留原合同。漏调 Skill 后受管写入被拒,反馈具体调用名,成功加载后重试;每缺项最多两次、任务最多六次自动纠正,持续失败如实阻塞。记录包含补调和成功重试的原生引用,不能用模型自述或文件读取代替。
@@ -37,6 +37,6 @@ Codex 已有原生技能路由,勿把元技能全文预加载为常驻上下
37
37
 
38
38
  ## 可选原型工具
39
39
 
40
- 原型辅助工具位于本宿主基址的 `tools/i3-prototype/`,支持项目和全局范围;旧项目 `.prototype-tools` 继续读取兼容。项目安装可使用 `npx @givolt/i3-composer-agent@2.3.3 --codex --scope project --yes --prototype-skills uiux,antdv`;全局安装将 scope 改为 global。可选依赖默认 none,后续也可使用已安装 Skill 的 prototype-dependencies.cjs 单独检测/补装。完整用法见原型 Skill 的 references/optional-skills.md。
40
+ 原型辅助工具位于本宿主基址的 `tools/i3-prototype/`,支持项目和全局范围;旧项目 `.prototype-tools` 继续读取兼容。项目安装可使用 `npx @givolt/i3-composer-agent@2.3.5 --codex --scope project --yes --prototype-skills uiux,antdv`;全局安装将 scope 改为 global。可选依赖默认 none,后续也可使用已安装 Skill 的 prototype-dependencies.cjs 单独检测/补装。完整用法见原型 Skill 的 references/optional-skills.md。
41
41
 
42
42
  原型共享资料统一在项目 prototypes/:新索引 prototypes/index.json,准备范围 prototypes/.preparation/<id>/scope.json。新原生 scope.moduleIds 自动生成 appliesTo;旧索引、输入和实例保持兼容,安装升级不自动迁移。工具及运行缓存使用所选宿主基址;全局浏览器缓存按业务项目身份隔离。详细规则和只读查询/显式迁移命令见 i3-ui-prototype/references/project-layout.md。
@@ -6,7 +6,7 @@
6
6
 
7
7
  ## 使用本地分发目录
8
8
 
9
- 以下命令使用完整分发包解压目录里的 CLI,适用于本地测试和离线接入。`/absolute/path/to/package` 均替换为实际解压目录;已发布版本也可使用 `npx @givolt/i3-composer-agent@2.3.3` 的对应入口。
9
+ 以下命令使用完整分发包解压目录里的 CLI,适用于本地测试和离线接入。`/absolute/path/to/package` 均替换为实际解压目录;已发布版本也可使用 `npx @givolt/i3-composer-agent@2.3.5` 的对应入口。
10
10
 
11
11
  ### fx
12
12
 
@@ -27,7 +27,7 @@ WorkBuddy 的目录选择使用自己的配置,不借用 `CODEBUDDY_CONFIG_DIR
27
27
 
28
28
  运行 `node ~/.workbuddy/i3-composer-agent/scripts/run-evals.js --min-rank1 95`,检查实际安装技能的中英文触发,
29
29
  不会调用模型。进入 `~/.workbuddy/i3-composer-agent/` 运行 `npm test` 可检查完整内容、两种语言及全部脚本回归;原 `.js` 入口保留。项目安装将 `~/.workbuddy/` 换成 `.codebuddy/`。五项校验、行为评测用例、样例和
30
- 脚本用法见 [评测说明](../evals/README.md)。Hook 文件默认提供,启用需适配宿主事件协议。
30
+ 脚本用法见 [评测说明](../evals/README.md)。原型审计 Hooks 默认注册,其他原版 Hook 文件保留但不新增注册;实际回调和补调仍需本机验收。
31
31
 
32
32
  ## 发现和调用
33
33
 
@@ -85,6 +85,22 @@ npx @givolt/i3-composer-agent --workbuddy --scope global --yes --force
85
85
 
86
86
  ## 可选原型工具
87
87
 
88
- 原型辅助工具位于本宿主基址的 `tools/i3-prototype/`,支持项目和全局范围;旧项目 `.prototype-tools` 继续读取兼容。推荐使用 `npx @givolt/i3-composer-agent@2.3.3 --workbuddy --scope global --yes --prototype-skills uiux,antdv`;项目安装将 scope 改为 project。可选依赖默认 none,后续也可使用已安装 Skill 的 prototype-dependencies.cjs 单独检测/补装。完整用法见原型 Skill 的 references/optional-skills.md。
88
+ 原型辅助工具位于本宿主基址的 `tools/i3-prototype/`,支持项目和全局范围;旧项目 `.prototype-tools` 继续读取兼容。推荐使用 `npx @givolt/i3-composer-agent@2.3.5 --workbuddy --scope global --yes --prototype-skills uiux,antdv`;项目安装将 scope 改为 project。可选依赖默认 none,后续也可使用已安装 Skill 的 prototype-dependencies.cjs 单独检测/补装。完整用法见原型 Skill 的 references/optional-skills.md。
89
89
 
90
90
  原型共享资料统一在项目 prototypes/:新索引 prototypes/index.json,准备范围 prototypes/.preparation/<id>/scope.json。新原生 scope.moduleIds 自动生成 appliesTo;旧索引、输入和实例保持兼容,安装升级不自动迁移。工具及运行缓存使用所选宿主基址;全局浏览器缓存按业务项目身份隔离。详细规则和只读查询/显式迁移命令见 i3-ui-prototype/references/project-layout.md。
91
+
92
+
93
+ ## 原型 Hooks 与本地 antDv
94
+
95
+ 项目安装注册到 .codebuddy/settings.json,全局注册到 WORKBUDDY_CONFIG_DIR 或 ~/.workbuddy/settings.json。与 CodeBuddy 共用项目目录时,每事件只有一个原型入口;各宿主允许范围、明确禁用和运行状态分别记录。重载 WorkBuddy 后验证,不因文件存在宣称生效。
96
+
97
+ ```bash
98
+ node ~/.workbuddy/i3-composer-agent/hooks/manage.cjs check --host workbuddy --scope global --project "/业务项目"
99
+ node ~/.workbuddy/i3-composer-agent/hooks/manage.cjs enable --host workbuddy --scope global --project "/业务项目" --groups prototype
100
+ node ~/.workbuddy/i3-composer-agent/hooks/manage.cjs disable --host workbuddy --scope global --project "/业务项目" --groups prototype
101
+ node ~/.workbuddy/skills/i3-ui-prototype/scripts/prototype-dependencies.cjs query --host workbuddy --scope global --project "/业务项目" --kind info --component Table --version 1.5.2
102
+ ```
103
+
104
+ 项目范围将入口改为 .codebuddy 并使用 --scope project。只读 query 解析本宿主 Node/CLI 入口,不要求全局 antdv 命令;它不代替实际 antDv Skill 调用。新实例使用 --host workbuddy --execution-policy buddy-ab-v2,按 Skill 合同先加载前端/适用专业技能,再实施。
105
+
106
+ 当前适配依据官方插件 Hooks 文档及 WorkBuddy 5.8.3 随包 CLI 源代码核对。六组宿主/范围的文件级集成测试使用合成日志,实际宿主执行状态仍 pending-user。手测须看到漏调拒绝、当前主会话真实成功加载和重试成功;持续失败到预算上限后如实报告阻塞,不能用只读文件或自述代替调用证据。
package/hooks/manage.cjs CHANGED
@@ -8,7 +8,7 @@ const catalog=[
8
8
  {id:'session-start',name:'Skill 发现与路由',origin:'upstream',files:['session-start.sh'],events:['SessionStart'],dependencies:['bash','jq'],condition:'明确 skill-routing=hook;原生路由使用 native,避免重复注入'},
9
9
  {id:'sdd-cache',name:'官方文档请求缓存',origin:'upstream',files:['sdd-cache-pre.sh','sdd-cache-post.sh'],events:['PreToolUse','PostToolUse'],dependencies:['bash','jq','curl','sha256'],condition:'实际 WebFetch;仅源站 304 复用'},
10
10
  {id:'simplify-ignore',name:'代码块简化保护',origin:'upstream',files:['simplify-ignore.sh'],events:['PreToolUse','PostToolUse','Stop'],dependencies:['bash','jq','sha1'],condition:'使用 simplify-ignore 标记;会在运行期间替换标记块并在 Stop 恢复'},
11
- {id:'prototype',name:'原型执行审计',origin:'i3',events:['SessionStart','UserPromptSubmit','PreToolUse','PostToolUse','Stop'],dependencies:['node'],condition:'真实 CodeBuddy IDE/CLI;默认从原生 Hook 自动识别日志,支持手动目录限制'},
11
+ {id:'prototype',name:'原型执行审计',origin:'i3',events:['SessionStart','UserPromptSubmit','PreToolUse','PostToolUse','Stop'],dependencies:['node'],condition:'CodeBuddy IDE/CLI 与 WorkBuddy;原生回调识别身份和日志,有限补调;真实宿主验收另记'},
12
12
  ];
13
13
  const digest=value=>crypto.createHash('sha256').update(JSON.stringify(value)).digest('hex');
14
14
  const sha=bytes=>crypto.createHash('sha256').update(bytes).digest('hex');
@@ -82,7 +82,7 @@ function executable(name,env=process.env) {
82
82
  }
83
83
  function dependencies(){return Object.fromEntries(['bash','jq','curl','shasum','sha256sum','sha1sum'].map(name=>[name,executable(name)]));}
84
84
  function location(options) {
85
- assert.equal(options.host||'codebuddy','codebuddy','Unified Hooks currently support CodeBuddy only');assert.ok(['project','global'].includes(options.scope),'Specify project or global scope');
85
+ assert.ok(['codebuddy','workbuddy'].includes(options.host||'codebuddy'),'Unified prototype Hooks support CodeBuddy and WorkBuddy');assert.ok(['project','global'].includes(options.scope),'Specify project or global scope');
86
86
  const project=fs.realpathSync(path.resolve(options.project||'.'));assert.ok(fs.statSync(project).isDirectory(),'Project must be a directory');
87
87
  return {project,base:options.scope==='project'?path.join(project,'.codebuddy'):modules().P.globalBase(options)};
88
88
  }
@@ -102,30 +102,38 @@ function pendingSimplify(base) {
102
102
  });
103
103
  }
104
104
  function prepare(options,runtime={}) {
105
- const {P,R}=runtime.modules||modules(),{project,base}=runtime.location||location(options),io=R.fileIO,action=options.action||'keep',ids=selection(options.groups,action);
105
+ const {P,R}=runtime.modules||modules(),{project,base}=runtime.location||location(options),io=R.fileIO,requested=options.action||'keep',ids=selection(options.groups,requested),host=options.host||'codebuddy';
106
106
  const settingsPath=path.join(base,'settings.json'),recordPath=path.join(base,'state/i3-composer-agent/hooks.json'),prototypePath=path.join(base,'state/i3-prototype/installation.json');
107
107
  const before=io.read(settingsPath),recordText=io.read(recordPath),record=recordText?JSON.parse(recordText):null,prototypeText=io.read(prototypePath),prototype=prototypeText?JSON.parse(prototypeText):null;
108
- if(action!=='disable'&&(action!=='keep'||record||prototype))assert.ok(process.platform!=='win32','CodeBuddy Hook quoting on Windows has not been validated; default installation without Hooks remains available');
109
- const product=options.product||record?.product||prototype?.product,settings=config(before);
108
+ const requestedHosts=[...new Set(options.scope==='project'?(options.agents||[host]).filter(h=>['codebuddy','workbuddy'].includes(h)):[host])];
109
+ const disabled=new Set(record?.prototypeDisabledHosts||[]);
110
+ if(requested==='enable'&&ids.includes('prototype'))for(const h of requestedHosts)disabled.delete(h);
111
+ if(requested==='disable'&&ids.includes('prototype'))for(const h of requestedHosts)disabled.add(h);
112
+ const selectedHosts=requested==='default'?requestedHosts.filter(h=>!disabled.has(h)):requestedHosts;
113
+ const action=requested==='default'?(selectedHosts.length&&process.platform!=='win32'?'enable':'keep'):requested;
114
+ const activeHosts=prototype?.hosts||(prototype?['codebuddy']:[]);
115
+ const hosts=action==='disable'?activeHosts.filter(h=>!requestedHosts.includes(h)):[...new Set([...activeHosts,...selectedHosts])].sort();
116
+ if(action!=='disable'&&(action!=='keep'||record||prototype))assert.ok(process.platform!=='win32','Buddy Hook quoting on Windows has not been validated; explicit keep remains available');
117
+ const product='auto',settings=config(before);
110
118
  if(action!=='disable'&&(action!=='keep'||record||prototype)) {
111
119
  assert.ok(!settings.disableAllHooks&&!settings.allowManagedHooksOnly,'Host policy prevents automatic Hooks; preserve the policy');
112
- const manifest=io.read(path.join(base,'.i3-composer-agent.json'));if(manifest)assert.ok(!JSON.parse(manifest).agents?.includes('workbuddy'),'Shared WorkBuddy scope cannot identify CodeBuddy safely');
113
- assert.ok(!options.agents?.includes('workbuddy'),'Use an exclusive CodeBuddy scope for Hooks');
114
120
  }
121
+ if(host==='workbuddy')assert.ok(ids.every(id=>id==='prototype')||['check','list','keep'].includes(action),'WorkBuddy currently registers the prototype group only; upstream adapters remain CodeBuddy-specific');
115
122
  if(action==='enable')for(const id of ids)assert.ok(!unmanaged(settings).some(item=>item.id===id),`Unmanaged ${id} Hook already exists; preserve it and resolve the duplicate before enabling`);
116
123
  if(ids.includes('simplify-ignore')&&['enable','disable'].includes(action)) {
117
124
  for(const candidate of [...new Set([base,path.join(project,'.codebuddy'),P.globalBase?P.globalBase(options):path.join(options.home||os.homedir(),'.codebuddy')])])assert.equal((runtime.pendingSimplify||pendingSimplify)(candidate).length,0,'Simplify protection is still active; finish the session and restore blocks before changing Hooks');
118
125
  }
119
- const prototypeAction=ids.includes('prototype')?action:'keep';
120
- const prototypeChange=action==='disable'&&!ids.includes('prototype')?{unchanged:true}:P.prepare({...options,project,product,action:prototypeAction,entryPath:path.join(base,'i3-composer-agent/hooks/i3-prototype.cjs'),entrySource:path.join(__dirname,'i3-prototype.cjs')});
121
- const upstream=planUpstream({...options,base,product,action,record,settingsText:prototypeChange.unchanged?before:prototypeChange.afterText,nodePath:process.execPath,
126
+ const prototypeAction=ids.includes('prototype')?(action==='disable'&&hosts.length?'keep':action):'keep';
127
+ const prototypeChange=action==='disable'&&!ids.includes('prototype')?{unchanged:true}:P.prepare({...options,project,product,hosts,action:prototypeAction,entryPath:path.join(base,'i3-composer-agent/hooks/i3-prototype.cjs'),entrySource:path.join(__dirname,'i3-prototype.cjs')});
128
+ const upstream=planUpstream({...options,base,product:record?.product||options.product,action,record,settingsText:prototypeChange.unchanged?before:prototypeChange.afterText,nodePath:process.execPath,
122
129
  hookDirectory:path.join(base,'i3-composer-agent/hooks'),scriptDigest:runtime.scriptDigest||require('./codebuddy-upstream.cjs').bundle(),dependencies:runtime.dependencies||dependencies()});
130
+ if(disabled.size)upstream.recordAfter={...(upstream.recordAfter||{schemaVersion:1,owner:OWNER,base,scope:options.scope,product:record?.product||'auto',groups:{}}),prototypeDisabledHosts:[...disabled].sort()};
123
131
  const changes=[{file:settingsPath,before,after:upstream.afterText},{file:recordPath,before:recordText,after:upstream.recordAfter?json(upstream.recordAfter):null},
124
132
  {file:prototypePath,before:prototypeText,after:prototypeChange.unchanged?prototypeText:prototypeChange.recordAfter?json(prototypeChange.recordAfter):null}];
125
- return {changes,summary:{host:'codebuddy',scope:options.scope,base,product:product||null,action,groups:ids,changed:changes.some(item=>item.before!==item.after),
133
+ return {changes,summary:{host,scope:options.scope,base,product,action,requestedAction:requested,groups:ids,enabledHosts:prototypeChange.unchanged?activeHosts:prototypeChange.recordAfter?.hosts||[],disabledHosts:[...disabled].sort(),changed:changes.some(item=>item.before!==item.after),
126
134
  enabledGroups:[...Object.keys(upstream.recordAfter?.groups||{}),...((prototypeChange.unchanged?prototype:prototypeChange.recordAfter)?['prototype']:[])],
127
135
  ...(prototypeChange.summary?.transcript?{transcript:prototypeChange.summary.transcript}:{}),
128
- next:product==='cli'?'Review /hooks in CodeBuddy Code and start a new session.':'Reload CodeBuddy and verify actual Hook events. Registration is not activation.'}};
136
+ next:'Desktop: reload; CodeBuddy CLI: review /hooks. Host identity, actual Skill invocation and recovery require native validation.'}};
129
137
  }
130
138
  function check(options) {
131
139
  const {P,R}=modules(),{project,base}=location(options),io=R.fileIO,ids=selection(options.groups,options.action||'check'),settingsText=io.read(path.join(base,'settings.json')),settings=config(settingsText),deps=dependencies(),items=[];
@@ -146,12 +154,12 @@ function check(options) {
146
154
  }catch(e){row.status='failed';row.reason=e.message;}
147
155
  items.push(row);
148
156
  }
149
- return {host:'codebuddy',scope:options.scope,base,readOnly:true,changed:false,status:items.some(item=>item.status==='failed')?'failed':'checked',hooks:items,unmanagedHooks:unmanaged(settings),
157
+ return {host:options.host||'codebuddy',scope:options.scope,base,readOnly:true,changed:false,status:items.some(item=>item.status==='failed')?'failed':'checked',hooks:items,unmanagedHooks:unmanaged(settings),
150
158
  next:'files-present is not enabled; registered is not triggered; triggered is not business acceptance. CLI: review /hooks; IDE: reload.'};
151
159
  }
152
160
  function configure(options){const change=prepare(options);return options.preview?change.summary:apply(change);}
153
161
  function main(argv=process.argv.slice(2)) {
154
- if(argv.includes('--help'))return {usage:'node manage.cjs list|check|enable|disable --host codebuddy --scope project|global --project <directory> [--groups <ids>|all] [--product ide|cli] [--skill-routing hook] [--transcript-root <native-directory>|auto]',hooks:catalog,default:'keep; enable/disable default prototype; list/check default all; transcripts auto for new registrations',nativeValidation:'pending-user'};
162
+ if(argv.includes('--help'))return {usage:'node manage.cjs list|check|enable|disable --host codebuddy|workbuddy --scope project|global --project <directory> [--groups <ids>|all] [--product auto|ide|cli] [--skill-routing hook] [--transcript-root <native-directory>|auto]',hooks:catalog,default:'Installer defaults prototype, preserving explicit disable; management enable/disable default prototype; list/check default all; identity/transcripts auto for new registrations',nativeValidation:'pending-user'};
155
163
  const options={action:argv.shift()||'list',host:'codebuddy',project:process.cwd()};
156
164
  assert.ok(['list','check','enable','disable','keep'].includes(options.action),'Choose list, check, enable or disable');
157
165
  while(argv.length){const arg=argv.shift();assert.ok(arg.startsWith('--')&&argv[0]&&!argv[0].startsWith('--'),'Hook option needs a value');const key=arg.slice(2).replace(/-([a-z])/g,(_,c)=>c.toUpperCase());assert.ok(['host','scope','project','product','productVersion','transcriptRoot','groups','skillRouting'].includes(key),'Unknown Hook option');options[key]=argv.shift();}
package/package.json CHANGED
@@ -195,6 +195,8 @@
195
195
  "scripts/run-evals.js",
196
196
  "scripts/run-regressions.js",
197
197
  "scripts/template-adapter-test.js",
198
+ "scripts/ui-prototype-binding-recovery-test.js",
199
+ "scripts/ui-prototype-buddy-lifecycle-test.js",
198
200
  "scripts/ui-prototype-codebuddy-hook-test.js",
199
201
  "scripts/ui-prototype-content-test.js",
200
202
  "scripts/ui-prototype-dependencies-test.js",
@@ -205,6 +207,7 @@
205
207
  "scripts/ui-prototype-execution-runtime-test.js",
206
208
  "scripts/ui-prototype-ide-source-test.js",
207
209
  "scripts/ui-prototype-native-test.js",
210
+ "scripts/ui-prototype-recovery-test.js",
208
211
  "scripts/ui-prototype-registration-test.js",
209
212
  "scripts/ui-prototype-template-test.js",
210
213
  "scripts/ui-prototype-test.js",
@@ -413,6 +416,8 @@
413
416
  "scripts/run-evals.js",
414
417
  "scripts/run-regressions.js",
415
418
  "scripts/template-adapter-test.js",
419
+ "scripts/ui-prototype-binding-recovery-test.js",
420
+ "scripts/ui-prototype-buddy-lifecycle-test.js",
416
421
  "scripts/ui-prototype-codebuddy-hook-test.js",
417
422
  "scripts/ui-prototype-content-test.js",
418
423
  "scripts/ui-prototype-dependencies-test.js",
@@ -423,6 +428,7 @@
423
428
  "scripts/ui-prototype-execution-runtime-test.js",
424
429
  "scripts/ui-prototype-ide-source-test.js",
425
430
  "scripts/ui-prototype-native-test.js",
431
+ "scripts/ui-prototype-recovery-test.js",
426
432
  "scripts/ui-prototype-registration-test.js",
427
433
  "scripts/ui-prototype-template-test.js",
428
434
  "scripts/ui-prototype-test.js",
@@ -438,7 +444,7 @@
438
444
  "scripts/validate-versions.js"
439
445
  ]
440
446
  },
441
- "version": "2.3.3",
447
+ "version": "2.3.5",
442
448
  "repository": {
443
449
  "type": "git",
444
450
  "url": "https://github.com/49780522/i3-composer-agent.git"
package/plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i3-composer-agent",
3
- "version": "2.3.3",
3
+ "version": "2.3.5",
4
4
  "description": "覆盖需求、计划、开发、测试、审查与发布的软件工程技能,默认使用简体中文。",
5
5
  "homepage": "https://github.com/49780522/i3-composer-agent",
6
6
  "repository": "https://github.com/49780522/i3-composer-agent"