@givolt/i3-composer-agent 2.3.1 → 2.3.3
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/.agents/plugins/marketplace.json +1 -1
- package/.claude/commands/i3-prototype.md +5 -7
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.gemini/commands/i3-prototype.toml +5 -7
- package/README.md +16 -7
- package/bin/agent-targets.json +4 -2
- package/bin/i3-composer-agent.cjs +74 -7
- package/bin/install.cjs +16 -1
- package/bin/native-layout.cjs +1 -1
- package/bin/native-migration.cjs +27 -3
- package/bin/tool-selector.cjs +24 -7
- package/bin/wizard.cjs +89 -15
- package/commands/i3-prototype.toml +5 -7
- package/docs/codebuddy-setup.md +91 -3
- package/docs/codex-setup.md +6 -0
- package/docs/other-hosts.md +1 -1
- package/docs/ui-prototype-native/MAIN-SESSION-REPORT.md +66 -0
- package/docs/ui-prototype-native/USAGE.md +93 -0
- package/docs/workbuddy-setup.md +6 -0
- package/evals/cases/i3-frontend-ui-engineering.json +16 -0
- package/evals/cases/i3-ui-prototype.json +109 -0
- package/evals/cases/i3-using-agent-skills.json +28 -0
- package/evals/fixtures/i3-ui-prototype/admin-list/assets/reference.css +3 -0
- package/evals/fixtures/i3-ui-prototype/admin-list/assets/reference.js +8 -0
- package/evals/fixtures/i3-ui-prototype/admin-list/capability-definition.json +67 -0
- package/evals/fixtures/i3-ui-prototype/admin-list/index.html +89 -0
- package/evals/fixtures/i3-ui-prototype/admin-list/readme.md +52 -0
- package/evals/fixtures/i3-ui-prototype/admin-list/template.json +8 -0
- package/evals/zh-CN/cases/i3-frontend-ui-engineering.json +17 -0
- package/evals/zh-CN/cases/i3-ui-prototype.json +115 -0
- package/evals/zh-CN/cases/i3-using-agent-skills.json +30 -0
- package/hooks/codebuddy-upstream.cjs +93 -0
- package/hooks/i3-prototype.cjs +12 -0
- package/hooks/manage.cjs +162 -0
- package/package.json +61 -1
- package/plugin.json +1 -1
- package/scripts/design-provider-test.js +7 -0
- package/scripts/enterprise-template-test.js +27 -1
- package/scripts/lib/prototype-fixture.cjs +17 -0
- package/scripts/prototype-cache-test.js +55 -0
- package/scripts/prototype-generation-entry-test.js +6 -0
- package/scripts/prototype-generation-evidence-test.js +10 -0
- package/scripts/prototype-generation-native-test.js +78 -0
- package/scripts/prototype-generation-test.js +99 -0
- package/scripts/prototype-inventory-test.js +43 -0
- package/scripts/prototype-locations-test.js +79 -0
- package/scripts/prototype-project-test.js +183 -0
- package/scripts/ui-prototype-codebuddy-hook-test.js +106 -0
- package/scripts/ui-prototype-content-test.js +123 -0
- package/scripts/ui-prototype-dependencies-test.js +213 -0
- package/scripts/ui-prototype-devtools-test.js +53 -0
- package/scripts/ui-prototype-execution-evidence-test.js +62 -0
- package/scripts/ui-prototype-execution-gates-test.js +66 -0
- package/scripts/ui-prototype-execution-policy-test.js +42 -0
- package/scripts/ui-prototype-execution-runtime-test.js +27 -0
- package/scripts/ui-prototype-ide-source-test.js +73 -0
- package/scripts/ui-prototype-native-test.js +504 -0
- package/scripts/ui-prototype-registration-test.js +53 -0
- package/scripts/ui-prototype-template-test.js +261 -0
- package/scripts/ui-prototype-test.js +10 -0
- package/scripts/ui-prototype-transcript-auto-test.js +67 -0
- package/skills/i3-frontend-ui-engineering/SKILL.md +1 -1
- package/skills/i3-incremental-implementation/SKILL.md +1 -1
- package/skills/i3-ui-prototype/SKILL.md +158 -19
- package/skills/i3-ui-prototype/assets/capabilities/generation.json +833 -0
- package/skills/i3-ui-prototype/assets/capabilities/management.json +294 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/acceptance.json +51 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/component-map.json +13 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/generation-component-map.json +300 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/legacy-starter/index.html +11 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/legacy-starter/package-lock.json +2298 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/legacy-starter/package.json +22 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/legacy-starter/public/prototype-config.json +6 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/legacy-starter/src/App.vue +136 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/legacy-starter/src/components/DeviceEditor.vue +111 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/legacy-starter/src/config.ts +19 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/legacy-starter/src/content.ts +28 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/legacy-starter/src/domain/devices.ts +50 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/legacy-starter/src/domain/theme.ts +25 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/legacy-starter/src/main.ts +18 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/legacy-starter/src/style.css +50 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/legacy-starter/src/useDevices.ts +66 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/legacy-starter/tests/devices.test.ts +44 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/legacy-starter/tests/theme.test.ts +26 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/legacy-starter/tsconfig.json +15 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/legacy-starter/vite.config.ts +4 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/profile.json +174 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/readme.md +61 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/starter/index.html +11 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/starter/package-lock.json +2298 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/starter/package.json +22 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/starter/public/prototype-config.json +21 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/starter/src/App.vue +62 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/starter/src/PrototypeShell.vue +59 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/starter/src/config.ts +23 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/starter/src/domain/presentation.ts +29 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/starter/src/domain/theme.ts +25 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/starter/src/main.ts +18 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/starter/src/style.css +26 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/starter/tests/presentation.test.ts +23 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/starter/tests/theme.test.ts +26 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/starter/tsconfig.json +15 -0
- package/skills/i3-ui-prototype/assets/frameworks/vue-antdv-next/starter/vite.config.ts +4 -0
- package/skills/i3-ui-prototype/assets/hosts/codebuddy/profile.json +13 -0
- package/skills/i3-ui-prototype/assets/optional-skills/host-targets.json +739 -0
- package/skills/i3-ui-prototype/assets/optional-skills/sources.json +27 -0
- package/skills/i3-ui-prototype/assets/templates/catalog.js +149 -0
- package/skills/i3-ui-prototype/assets/templates/catalog.json +2 -1
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/capability-definition.json +294 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/component-inventory.json +707 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/generation.json +49 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/index.html +507 -2
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/offline-build.json +265 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/offline.js +8888 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/template-inventory.json +28791 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/template.json +9 -0
- package/skills/i3-ui-prototype/assets/templates/gallery/index.html +5 -5
- package/skills/i3-ui-prototype/assets/templates/generation-options.js +42 -0
- package/skills/i3-ui-prototype/assets/templates/index.html +3 -0
- package/skills/i3-ui-prototype/assets/templates/presentation.html +17 -0
- package/skills/i3-ui-prototype/references/artifact-contract.md +26 -1
- package/skills/i3-ui-prototype/references/content-template.md +81 -0
- package/skills/i3-ui-prototype/references/enterprise-admin.md +6 -0
- package/skills/i3-ui-prototype/references/entry-contract.md +71 -0
- package/skills/i3-ui-prototype/references/execution-evidence.md +66 -0
- package/skills/i3-ui-prototype/references/expert-adapter.md +33 -5
- package/skills/i3-ui-prototype/references/framework-contract.md +76 -0
- package/skills/i3-ui-prototype/references/generation-contract.md +122 -0
- package/skills/i3-ui-prototype/references/interaction-acceptance.md +169 -0
- package/skills/i3-ui-prototype/references/legacy-native.md +58 -0
- package/skills/i3-ui-prototype/references/optional-skills.md +63 -0
- package/skills/i3-ui-prototype/references/project-layout.md +92 -0
- package/skills/i3-ui-prototype/references/template-adapters.md +7 -1
- package/skills/i3-ui-prototype/references/workflow-contract.md +62 -4
- package/skills/i3-ui-prototype/scripts/adapters/easel-html.cjs +1 -1
- package/skills/i3-ui-prototype/scripts/browser-workspace.cjs +72 -0
- package/skills/i3-ui-prototype/scripts/codebuddy-context.cjs +75 -0
- package/skills/i3-ui-prototype/scripts/codebuddy-hook.cjs +157 -0
- package/skills/i3-ui-prototype/scripts/codebuddy-ide-source.cjs +69 -0
- package/skills/i3-ui-prototype/scripts/codebuddy-registration.cjs +123 -0
- package/skills/i3-ui-prototype/scripts/content-template.cjs +98 -0
- package/skills/i3-ui-prototype/scripts/enterprise-template.cjs +13 -6
- package/skills/i3-ui-prototype/scripts/execution-assertions.cjs +43 -0
- package/skills/i3-ui-prototype/scripts/execution-evidence.cjs +146 -0
- package/skills/i3-ui-prototype/scripts/execution-gates.cjs +147 -0
- package/skills/i3-ui-prototype/scripts/execution-policy.cjs +41 -0
- package/skills/i3-ui-prototype/scripts/execution-runtime.cjs +60 -0
- package/skills/i3-ui-prototype/scripts/generation-assets.cjs +18 -0
- package/skills/i3-ui-prototype/scripts/generation-contract.cjs +214 -0
- package/skills/i3-ui-prototype/scripts/generation-evidence.cjs +50 -0
- package/skills/i3-ui-prototype/scripts/generation-replan.cjs +34 -0
- package/skills/i3-ui-prototype/scripts/hosts/codebuddy.cjs +16 -0
- package/skills/i3-ui-prototype/scripts/manage-baseline.cjs +1 -1
- package/skills/i3-ui-prototype/scripts/native-browser.cjs +785 -0
- package/skills/i3-ui-prototype/scripts/native-build.cjs +91 -0
- package/skills/i3-ui-prototype/scripts/native-delivery.cjs +103 -0
- package/skills/i3-ui-prototype/scripts/native-devtools.cjs +92 -0
- package/skills/i3-ui-prototype/scripts/native-files.cjs +35 -0
- package/skills/i3-ui-prototype/scripts/native-pilot-lib.cjs +292 -0
- package/skills/i3-ui-prototype/scripts/native-pilot.cjs +50 -0
- package/skills/i3-ui-prototype/scripts/optional-skill-install.cjs +203 -0
- package/skills/i3-ui-prototype/scripts/project-registry.cjs +126 -0
- package/skills/i3-ui-prototype/scripts/prototype-dependencies.cjs +81 -0
- package/skills/i3-ui-prototype/scripts/prototype-hooks.cjs +87 -0
- package/skills/i3-ui-prototype/scripts/prototype-lib.cjs +31 -13
- package/skills/i3-ui-prototype/scripts/prototype-locations.cjs +69 -0
- package/skills/i3-ui-prototype/scripts/sync-template.cjs +19 -0
- package/skills/i3-ui-prototype/scripts/template-contract.cjs +407 -0
- package/skills/i3-ui-prototype/scripts/template-inventory.cjs +78 -0
- package/skills/i3-ui-prototype/scripts/validate-result.cjs +117 -0
- package/skills/i3-using-agent-skills/SKILL.md +2 -5
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "
|
|
3
|
-
# i3-description-source: "description: Create,
|
|
2
|
+
description: "在主会话中分析、创建、检查与迭代 UI 交互原型。"
|
|
3
|
+
# i3-description-source: "description: Create, analyze, inspect and iterate UI prototypes in the main session"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
<!-- i3:zh-CN:start -->
|
|
@@ -11,13 +11,11 @@ description: "选择模板并生成、评审和迭代交互原型,维护已确
|
|
|
11
11
|
Skill/Command/Agent 标识、文件路径、命令参数、代码/API 名称、工具调用参数、JSON 键/类型/枚举、机器状态、测试期望字面量及引用原文保持原样。生成文档正文用中文,SPEC.md、tasks/plan.md、tasks/todo.md、CONSTRAINTS.md 等约定路径不改名。
|
|
12
12
|
严重程度按原规则判断,面向用户可写“严重(Critical)”“必须修复(Required)”“小问题(Nit)”“可选(Optional)”“建议考虑(Consider)”“仅供参考(FYI)”;High/Medium/Low、APPROVE/REQUEST CHANGES 和 GO/NO-GO 保留其原始语义与机器值。不得因翻译降低门槛,角色不能互相委派。
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
适用说明:在主会话中分析、创建、检查与迭代 UI 交互原型。
|
|
15
15
|
<!-- i3:zh-CN:end -->
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Use the i3-ui-prototype skill in the main session for the user's request below. Follow its shared preflight, operation boundaries and applicable runtime workflow.
|
|
18
18
|
|
|
19
19
|
$ARGUMENTS
|
|
20
20
|
|
|
21
|
-
With no arguments
|
|
22
|
-
Default to professional enhancement mode. Detect UI/UX Pro Max in the current host; if unavailable, offer installation or explicit template mode. Never silently downgrade.
|
|
23
|
-
Use the skill workflow for template selection, business mapping, professional advice, real browser verification and version-specific human confirmation. Preserve approved snapshots during iteration.
|
|
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.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
description = "
|
|
2
|
-
# i3-description-source: "description = \"Create,
|
|
1
|
+
description = "在主会话中分析、创建、检查与迭代 UI 交互原型。"
|
|
2
|
+
# i3-description-source: "description = \"Create, analyze, inspect and iterate UI prototypes in the main session\""
|
|
3
3
|
|
|
4
4
|
prompt = """
|
|
5
5
|
<!-- i3:zh-CN:start -->
|
|
@@ -10,14 +10,12 @@ prompt = """
|
|
|
10
10
|
Skill/Command/Agent 标识、文件路径、命令参数、代码/API 名称、工具调用参数、JSON 键/类型/枚举、机器状态、测试期望字面量及引用原文保持原样。生成文档正文用中文,SPEC.md、tasks/plan.md、tasks/todo.md、CONSTRAINTS.md 等约定路径不改名。
|
|
11
11
|
严重程度按原规则判断,面向用户可写“严重(Critical)”“必须修复(Required)”“小问题(Nit)”“可选(Optional)”“建议考虑(Consider)”“仅供参考(FYI)”;High/Medium/Low、APPROVE/REQUEST CHANGES 和 GO/NO-GO 保留其原始语义与机器值。不得因翻译降低门槛,角色不能互相委派。
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
适用说明:在主会话中分析、创建、检查与迭代 UI 交互原型。
|
|
14
14
|
<!-- i3:zh-CN:end -->
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Use the i3-ui-prototype skill in the main session for the user's request below. Follow its shared preflight, operation boundaries and applicable runtime workflow.
|
|
17
17
|
|
|
18
18
|
$ARGUMENTS
|
|
19
19
|
|
|
20
|
-
With no arguments
|
|
21
|
-
Default to professional enhancement mode. Detect UI/UX Pro Max in the current host; if unavailable, offer installation or explicit template mode. Never silently downgrade.
|
|
22
|
-
Use the skill workflow for template selection, business mapping, professional advice, real browser verification and version-specific human confirmation. Preserve approved snapshots during iteration.
|
|
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.
|
|
23
21
|
"""
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# i3 Composer Agent v2.3.
|
|
1
|
+
# i3 Composer Agent v2.3.3
|
|
2
2
|
|
|
3
3
|
**Intelligence. Integration. Innovation.**
|
|
4
4
|
|
|
@@ -25,6 +25,8 @@ 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 可选择安装两项、单项或跳过,之后也可补装。
|
|
29
|
+
|
|
28
30
|
全部目标均安装 26 个技能、共享参考资料,以及完整评测/Hook/脚本配套。
|
|
29
31
|
全部目标同时提供 10 个命令和 4 个 Agent 角色提示。
|
|
30
32
|
CodeBuddy、WorkBuddy、Claude Code 使用原生命令入口;其他工具通过 Skills 机制使用,
|
|
@@ -161,7 +163,7 @@ CodeBuddy、WorkBuddy、Claude Code 原生安装使用 `/i3-spec`、`/i3-plan`
|
|
|
161
163
|
| /i3-composer-agent:i3-code-simplify | 简化代码,降低复杂度,提高可读性与维护性,并保持既有行为不变。 |
|
|
162
164
|
| /i3-composer-agent:i3-constraints | 访谈并定义项目质量门槛,提供合理默认值,写入 CONSTRAINTS.md 并落实约束。 |
|
|
163
165
|
| /i3-composer-agent:i3-plan | 把工作拆成带验收标准、验证步骤和依赖顺序的小任务。 |
|
|
164
|
-
| /i3-composer-agent:i3-prototype |
|
|
166
|
+
| /i3-composer-agent:i3-prototype | 在主会话中分析、创建、检查与迭代 UI 交互原型。 |
|
|
165
167
|
| /i3-composer-agent:i3-review | 从正确性、可读性、架构、安全和性能五个维度审查代码。 |
|
|
166
168
|
| /i3-composer-agent:i3-ship | 并行调用三个专业角色执行发布前检查,主会话汇总 GO/NO-GO 决策与回滚计划。 |
|
|
167
169
|
| /i3-composer-agent:i3-spec | 先编写结构化规格、目标、范围与验收标准,再进入实现。 |
|
|
@@ -176,10 +178,15 @@ CodeBuddy、WorkBuddy、Claude Code 原生安装使用 `/i3-spec`、`/i3-plan`
|
|
|
176
178
|
由主会话汇总 GO/NO-GO 决策,回滚计划必需。代码审查使用 Critical、Required、Optional、Nit
|
|
177
179
|
四级;Critical 和 Required 问题默认阻止发布,各专业角色仍保留自己的报告字段和判断规则。
|
|
178
180
|
|
|
179
|
-
`/i3-prototype`
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
181
|
+
`/i3-prototype` 在主会话调用 `i3-ui-prototype` 技能,按需求使用前端与浏览器技能完成原型。
|
|
182
|
+
完整企业后台 HTML 内容模板可双击 index.html 离线查看与修改;生成的 Vue 3+antDv-next 工程
|
|
183
|
+
使用真实组件,支持明亮、暗黑、清新、科技四主题,默认明亮。已有原型按原合同继续使用。
|
|
184
|
+
模板在 Skill 源码中维护并随版本发布,生成时只读引用;业务直接修改原型工程,不默认创建项目 ui-templates。
|
|
185
|
+
UI/UX Pro Max 与 antDv 官方 Skill 可通过 `--prototype-skills uiux,antdv` 明确选择安装,
|
|
186
|
+
也可稍后检测/补装;工具随所选宿主和范围存入 `tools/i3-prototype/`,旧路径继续兼容。
|
|
187
|
+
默认采用专业增强模式,UIUX 不可用时提示修复或由用户明确选择模板模式继续。
|
|
188
|
+
两项外部能力不计入本包技能数量。AI 工作台、数字孪生大屏和移动端模板仍在规划中。
|
|
189
|
+
每个生成原型仍需独立的交互验收和用户评审;本包尚未实现企业 SOP 自动编排。
|
|
183
190
|
|
|
184
191
|
## Skills
|
|
185
192
|
|
|
@@ -209,7 +216,7 @@ UI/UX Pro Max 是需要单独安装的外部设计能力,不计入本包的技
|
|
|
209
216
|
| [i3-source-driven-development](skills/i3-source-driven-development/SKILL.md) | 以官方文档和权威来源支撑实现决策。适用于核对框架/库用法、验证方案、查证 API 和避免过时实现,并保留来源证据。 |
|
|
210
217
|
| [i3-spec-driven-development](skills/i3-spec-driven-development/SKILL.md) | 在实现前形成结构化规格。适用于新项目、功能或重大改动、PRD、需求澄清、目标与范围、场景和验收标准,以及将需求拆为独立可测试能力。 |
|
|
211
218
|
| [i3-test-driven-development](skills/i3-test-driven-development/SKILL.md) | 执行测试先行的红绿重构循环。适用于实现逻辑、修复缺陷、修改行为、复现报错及证明改动有效;也用于为函数补测试、修复或修改直接粘贴的代码,即使请求未提到测试;缺陷修复使用先证明失败的 Prove-It 模式。 |
|
|
212
|
-
| [i3-ui-prototype](skills/i3-ui-prototype/SKILL.md) |
|
|
219
|
+
| [i3-ui-prototype](skills/i3-ui-prototype/SKILL.md) | 将 HTML 内容模板、业务需求与目标组件框架组合为可操作 UI 原型。适用于原型分析、原型候选生成、原型交互验证和已确认原型基线维护;生产页面实现使用工程流程。 |
|
|
213
220
|
| [i3-using-agent-skills](skills/i3-using-agent-skills/SKILL.md) | 发现并调用合适的工程技能。适用于开始会话、判断任务意图、选择技能或工作流;作为元技能协调其他技能的发现和调用。 |
|
|
214
221
|
|
|
215
222
|
## Agent 角色
|
|
@@ -234,3 +241,5 @@ npx @givolt/i3-composer-agent --codebuddy --dir /path/to/plugin --force
|
|
|
234
241
|
仓库维护用的 AGENTS.md、CLAUDE.md 不复制进业务项目。
|
|
235
242
|
Codex 通过 `$i3-spec-driven-development` 等技能名调用;其原生 `/plan` 是宿主计划模式。
|
|
236
243
|
中文语言策略、工程方法、审批要求与工具限制在各入口独立生效。
|
|
244
|
+
|
|
245
|
+
原型共享资料统一在项目 prototypes/:新索引 prototypes/index.json,准备范围 prototypes/.preparation/<id>/scope.json。新原生 scope.moduleIds 自动生成 appliesTo;旧索引、输入和实例保持兼容,安装升级不自动迁移。工具及运行缓存使用所选宿主基址;全局浏览器缓存按业务项目身份隔离。详细规则和只读查询/显式迁移命令见 i3-ui-prototype/references/project-layout.md。
|
package/bin/agent-targets.json
CHANGED
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
"label": "CodeBuddy",
|
|
9
9
|
"projectSkillsDir": ".codebuddy/skills",
|
|
10
10
|
"globalSkillsDir": {
|
|
11
|
-
"base": "
|
|
12
|
-
"
|
|
11
|
+
"base": "env",
|
|
12
|
+
"env": "CODEBUDDY_CONFIG_DIR",
|
|
13
|
+
"fallback": ".codebuddy",
|
|
14
|
+
"path": "skills"
|
|
13
15
|
}
|
|
14
16
|
},
|
|
15
17
|
{
|
|
@@ -21,6 +21,10 @@ ${pkg.name}
|
|
|
21
21
|
npx ${pkg.name} --workbuddy --scope global
|
|
22
22
|
npx ${pkg.name} --agents codebuddy,workbuddy --scope global --yes
|
|
23
23
|
npx ${pkg.name} --agents codebuddy,codex --scope project --yes
|
|
24
|
+
npx ${pkg.name} --codebuddy --scope project --yes --prototype-skills uiux,antdv
|
|
25
|
+
npx ${pkg.name} prototype-deps check --host codex --scope project --project <project>
|
|
26
|
+
npx ${pkg.name} prototype-deps install --host workbuddy --scope global --skills uiux,antdv
|
|
27
|
+
npx ${pkg.name} hooks list --host codebuddy --scope project --project <project>
|
|
24
28
|
npx ${pkg.name} --prepare --claude --dir <directory>
|
|
25
29
|
npx ${pkg.name} --extract --dir <directory>
|
|
26
30
|
|
|
@@ -32,6 +36,15 @@ ${pkg.name}
|
|
|
32
36
|
--claude 预选 Claude Code
|
|
33
37
|
--scope <scope> project 项目 / global 全局(也可 --global / --local)
|
|
34
38
|
--project-dir <dir> 项目安装根目录,默认当前目录
|
|
39
|
+
--prototype-skills <ids> 可选原型依赖:none、uiux、antdv、uiux,antdv;向导数字选择,--yes 未指定时跳过
|
|
40
|
+
--migrate-tools 显式迁移有 i3 来源记录的旧独立 antDv 工具;仅项目范围且需选择 antdv
|
|
41
|
+
--hooks <action> CodeBuddy 统一 Hooks:keep(非交互默认)/ enable / list / check / disable
|
|
42
|
+
--hook-groups <ids> session-start,sdd-cache,simplify-ignore,prototype 或 all;启停默认 prototype
|
|
43
|
+
--codebuddy-skill-routing <mode> hook(明确需要会话注入)/ native(已有原生路由)
|
|
44
|
+
--prototype-hooks <action> 旧参数保留,仅管理 prototype 组
|
|
45
|
+
--codebuddy-product <form> 启用时明确 ide 或 cli;CLI 注册后需在 /hooks 审核
|
|
46
|
+
--codebuddy-transcript-root <dir|auto> 默认自动识别;可选手动原生日志限制,auto 切回自动
|
|
47
|
+
--codebuddy-version <version> 实际宿主版本,便于核验记录
|
|
35
48
|
--yes 确认明确指定的非交互安装
|
|
36
49
|
--list-agents 列出全部支持的工具目录
|
|
37
50
|
--prepare 另行导出插件目录并显示宿主注册步骤
|
|
@@ -43,13 +56,14 @@ ${pkg.name}
|
|
|
43
56
|
--help 显示帮助
|
|
44
57
|
|
|
45
58
|
终端向导先显示常用工具,WorkBuddy 在第 2 项;选择“更多”可分页/搜索全部工具。
|
|
46
|
-
|
|
59
|
+
输入工具编号(如 1,2)后回车,或上下键移动/跨页、空格勾选、回车确认;q/Esc 退出。
|
|
60
|
+
范围、Hooks、IDE/CLI、可选原型依赖和最终确认使用数字选择,Hook 组支持逗号分隔数字多选。
|
|
47
61
|
CodeBuddy、WorkBuddy、Claude Code 同时安装短命令和 Agent 角色。
|
|
48
62
|
其他工具通过 Skills 调用,短命令支持取决于宿主。
|
|
49
63
|
所有工具默认安装单份 skills、commands、agents;配套资料集中在 i3-composer-agent/。
|
|
50
64
|
评测、脚本和 Hook 读取同一份已安装技能。--prepare 用于另行导出标准插件并按宿主方式注册。
|
|
51
65
|
WorkBuddy 桌面版建议全局安装,便于技能列表和输入补全发现。
|
|
52
|
-
|
|
66
|
+
评测需主动运行;向导可注册 CodeBuddy Hooks,实际生效仍需宿主审核/重载和回调验证。
|
|
53
67
|
--prepare 仅供插件管理器安装方式使用,不自动注册插件或启用 Hook。
|
|
54
68
|
`;
|
|
55
69
|
|
|
@@ -154,6 +168,15 @@ function prepare() {
|
|
|
154
168
|
async function main() {
|
|
155
169
|
if (args.includes('--help') || (!args.length && !process.stdin.isTTY)) { console.log(help); return; }
|
|
156
170
|
if (args.length === 1 && args[0] === '--version') { console.log(pkg.version); return; }
|
|
171
|
+
if (args[0] === 'prototype-deps') {
|
|
172
|
+
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
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (['hooks','prototype-hooks'].includes(args[0])) {
|
|
177
|
+
const result=require('../hooks/manage.cjs').main([...args.slice(1),...(args[0]==='prototype-hooks'?['--groups','prototype']:[])]);
|
|
178
|
+
console.log(JSON.stringify(result,null,2));if(result.status==='failed')process.exitCode=1;return;
|
|
179
|
+
}
|
|
157
180
|
if (args.some(arg => ['--extract', '--prepare', '--dir'].includes(arg))) { prepare(); return; }
|
|
158
181
|
const installer = require('./install.cjs');
|
|
159
182
|
if (args.length === 1 && args[0] === '--list-agents') {
|
|
@@ -164,11 +187,22 @@ async function main() {
|
|
|
164
187
|
for (let i = 0; i < args.length; i++) {
|
|
165
188
|
const arg = args[i];
|
|
166
189
|
if (['--codebuddy', '--workbuddy', '--codex', '--claude'].includes(arg)) options.agents.push(arg.slice(2));
|
|
167
|
-
else if (['--agents', '--scope', '--project-dir'].includes(arg)) {
|
|
190
|
+
else if (['--agents', '--scope', '--project-dir', '--prototype-skills','--prototype-hooks','--hooks','--hook-groups','--codebuddy-skill-routing','--codebuddy-product','--codebuddy-transcript-root','--codebuddy-version'].includes(arg)) {
|
|
168
191
|
if (!args[i + 1] || args[i + 1].startsWith('--')) throw new Error(`${arg} 需要指定值。`);
|
|
169
192
|
const value = args[++i];
|
|
170
193
|
if (arg === '--agents') options.agents.push(value);
|
|
171
194
|
else if (arg === '--scope') { if (options.scope && options.scope !== value) throw new Error('请选择一个安装范围。'); options.scope = value; }
|
|
195
|
+
else if (arg === '--prototype-skills') {
|
|
196
|
+
require('../skills/i3-ui-prototype/scripts/optional-skill-install.cjs').selection(value);
|
|
197
|
+
options.prototypeSkills = value;
|
|
198
|
+
}
|
|
199
|
+
else if (arg === '--prototype-hooks') {if(!['keep','enable','check','disable'].includes(value))throw new Error('原型 Hooks 请选择 keep / enable / check / disable');options.prototypeHooks=value;}
|
|
200
|
+
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
|
+
else if (arg === '--hook-groups') {require('../hooks/manage.cjs').selection(value);options.hookGroups=value;}
|
|
202
|
+
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-transcript-root') options.codebuddyTranscriptRoot=value==='auto'?'auto':path.resolve(value);
|
|
205
|
+
else if (arg === '--codebuddy-version') options.codebuddyVersion=value;
|
|
172
206
|
else options.projectDir = path.resolve(value);
|
|
173
207
|
} else if (arg === '--global' || arg === '--local') {
|
|
174
208
|
const scope = arg === '--global' ? 'global' : 'project';
|
|
@@ -177,9 +211,18 @@ async function main() {
|
|
|
177
211
|
} else if (arg === '--yes') options.yes = true;
|
|
178
212
|
else if (arg === '--force') options.force = true;
|
|
179
213
|
else if (arg === '--dry-run') options.dryRun = true;
|
|
214
|
+
else if (arg === '--migrate-tools') options.migrateTools = true;
|
|
180
215
|
else throw new Error(`未知选项: ${arg}`);
|
|
181
216
|
}
|
|
182
217
|
options.agents = installer.selectAgents(options.agents);
|
|
218
|
+
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
|
+
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
|
+
const manager=require('../hooks/manage.cjs');
|
|
223
|
+
const result=['list','check'].includes(hookOptions().action)?manager.check(hookOptions()):manager.configure({...hookOptions(),preview:!!options.dryRun});
|
|
224
|
+
console.log(JSON.stringify(result,null,2));if(result.status==='failed')process.exitCode=1;return;
|
|
225
|
+
}
|
|
183
226
|
if (process.stdin.isTTY && process.stdout.isTTY && !options.yes && !options.dryRun) {
|
|
184
227
|
const selection = await require('./wizard.cjs').choose(options, identity);
|
|
185
228
|
if (!selection) { console.log('安装已取消,未修改文件。'); return; }
|
|
@@ -187,17 +230,26 @@ async function main() {
|
|
|
187
230
|
} else if (!options.agents.length || !options.scope || (!options.yes && !options.dryRun)) {
|
|
188
231
|
throw new Error('请在交互终端使用向导,或明确指定 --agents <ids> --scope project|global --yes。');
|
|
189
232
|
}
|
|
233
|
+
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 hookManager=require('../hooks/manage.cjs');
|
|
236
|
+
const hookChange=options.agents.includes('codebuddy')?hookManager.prepare(hookOptions()):null;
|
|
190
237
|
const plan = installer.planInstallation(options);
|
|
191
238
|
if (options.dryRun) {
|
|
192
|
-
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
|
|
239
|
+
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));
|
|
193
241
|
return;
|
|
194
242
|
}
|
|
195
243
|
if (!options.yes) {
|
|
196
|
-
const confirmed = await require('./wizard.cjs').confirm(plan);
|
|
244
|
+
const confirmed = await require('./wizard.cjs').confirm(plan, { prototypeSkills: options.prototypeSkills, hooks: hookChange?.summary });
|
|
197
245
|
if (!confirmed) { console.log('安装已取消,未修改文件。'); return; }
|
|
198
246
|
options.force = plan.conflicts.length > 0;
|
|
199
247
|
}
|
|
200
248
|
installer.executeInstallation(plan, { force: options.force });
|
|
249
|
+
if(hookChange?.summary.changed) {
|
|
250
|
+
try {console.log(JSON.stringify({hooks:hookManager.apply(hookChange)},null,2));}
|
|
251
|
+
catch(error){throw new Error(`核心文件已安装,Hooks 注册未完成;请保留当前配置并重试或提供错误。${error.message}`);}
|
|
252
|
+
}
|
|
201
253
|
console.log(identity);
|
|
202
254
|
if (plan.reused.length) console.log(`已复用同版本的 ${plan.reused.length} 个未修改内容。`);
|
|
203
255
|
for (const target of plan.targets) {
|
|
@@ -207,11 +259,26 @@ async function main() {
|
|
|
207
259
|
console.log(`评测资料:${target.evalsDirectory}`);
|
|
208
260
|
console.log(`完整校验:进入 "${target.toolkitDirectory}" 后运行 npm test`);
|
|
209
261
|
console.log(`中文评测:node "${path.join(target.scriptsDirectory, 'run-evals.js')}" --locale zh-CN --min-rank1 95`);
|
|
210
|
-
console.log(`
|
|
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+'"':';按宿主协议手动配置'}`);
|
|
211
263
|
}
|
|
212
264
|
for (const file of plan.preserved || []) console.log(`保留了用户文件:${file}`);
|
|
213
265
|
console.log('请重新加载 IDE 窗口或新建宿主会话以发现安装内容。');
|
|
214
266
|
if (plan.agents.some(id => !['codebuddy', 'workbuddy', 'claude-code'].includes(id))) console.log('这些工具通过技能 ID 调用;生命周期短命令支持取决于宿主。');
|
|
215
|
-
console.log('
|
|
267
|
+
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 检查当前状态。');
|
|
269
|
+
if (options.prototypeSkills !== undefined && options.prototypeSkills !== 'none') {
|
|
270
|
+
try {
|
|
271
|
+
// Shared project targets (for example CodeBuddy + WorkBuddy) prepare once.
|
|
272
|
+
for (const target of plan.targets) {
|
|
273
|
+
const result = await require('../skills/i3-ui-prototype/scripts/optional-skill-install.cjs').install({ project: options.projectDir,
|
|
274
|
+
host: target.agents[0], scope: plan.scope, skills: options.prototypeSkills, migrateTools: !!options.migrateTools });
|
|
275
|
+
console.log(JSON.stringify({ optionalPrototypeDependencies: result }, null, 2));
|
|
276
|
+
}
|
|
277
|
+
} catch (error) {
|
|
278
|
+
throw new Error(`i3 核心已安装成功;可选原型依赖未完成,可稍后用 prototype-deps install 重试。${error.message}`);
|
|
279
|
+
}
|
|
280
|
+
} else {
|
|
281
|
+
console.log('UIUX / antDv 独立依赖未自动安装。可随时用 prototype-deps check 检测,或 prototype-deps install --skills uiux,antdv 按需准备。');
|
|
282
|
+
}
|
|
216
283
|
}
|
|
217
284
|
main().catch(error => { console.error(`${name}: ${error.message}`); process.exitCode = 1; });
|
package/bin/install.cjs
CHANGED
|
@@ -29,6 +29,7 @@ function globalSkillsDir(agent, home, env) {
|
|
|
29
29
|
let base = home;
|
|
30
30
|
if (config.base === 'config') base = env.XDG_CONFIG_HOME && path.isAbsolute(env.XDG_CONFIG_HOME) ? env.XDG_CONFIG_HOME : path.join(home, '.config');
|
|
31
31
|
if (config.base === 'env') base = env[config.env]?.trim() || path.join(home, config.fallback);
|
|
32
|
+
if (config.env === 'CODEBUDDY_CONFIG_DIR' && (!path.isAbsolute(base) || /[\x00\r\n]/.test(base))) throw new Error('CODEBUDDY_CONFIG_DIR must be an absolute safe directory');
|
|
32
33
|
if (config.alternatives && !fs.existsSync(path.join(home, path.dirname(config.path)))) {
|
|
33
34
|
const alternative = config.alternatives.find(relative => fs.existsSync(path.join(home, path.dirname(relative))));
|
|
34
35
|
if (alternative) return path.join(home, alternative);
|
|
@@ -51,7 +52,7 @@ function checkDestination(file) {
|
|
|
51
52
|
function assetPath(base, file) { return path.relative(base, file).split(path.sep).join('/'); }
|
|
52
53
|
function manifestContent(plan, asset) {
|
|
53
54
|
return JSON.stringify({ name, version, layoutVersion: 3, entryPrefix: 'i3-', scope: plan.scope, agents: asset.target.agents,
|
|
54
|
-
capabilities: { nativeCommands: !!asset.target.nativeCommands, nativeAgents: !!asset.target.nativeCommands, hooks: 'manual' },
|
|
55
|
+
capabilities: { nativeCommands: !!asset.target.nativeCommands, nativeAgents: !!asset.target.nativeCommands, hooks: asset.target.agents.includes('codebuddy')?'codebuddy-managed':'manual' },
|
|
55
56
|
catalog: asset.target.catalog, resources: asset.target.resources,
|
|
56
57
|
assets: plan.assets.filter(item => item.base === asset.base && !['legacy', 'result'].includes(item.kind)).map(item => assetPath(asset.base, item.destination)) }, null, 2) + '\n';
|
|
57
58
|
}
|
|
@@ -98,6 +99,7 @@ function planInstallation({ agents, scope, projectDir = process.cwd(), home = os
|
|
|
98
99
|
const additions = nativeAssets(root, target, pluginFiles, version);
|
|
99
100
|
const current = new Set(additions.map(asset => asset.relative));
|
|
100
101
|
assets.push(...additions, ...migrationAssets(target, owned ? previous : undefined, current));
|
|
102
|
+
target.retiredEntryRuleAbsent = target.agents.includes('codebuddy') && !exists(path.join(target.base, 'rules/i3-prototype-entry.md'));
|
|
101
103
|
for (const asset of additions) {
|
|
102
104
|
// A new grouped resource must not take ownership of an unrelated file,
|
|
103
105
|
// even when --force confirms replacement of a previous installation.
|
|
@@ -147,7 +149,14 @@ function executeInstallation(plan, { force = false } = {}) {
|
|
|
147
149
|
fs.mkdirSync(directory);
|
|
148
150
|
createdDirectories.push(directory);
|
|
149
151
|
}
|
|
152
|
+
function checkRetiredEntryRules() {
|
|
153
|
+
for (const target of plan.targets) {
|
|
154
|
+
const file = path.join(target.base, 'rules/i3-prototype-entry.md');
|
|
155
|
+
if (target.retiredEntryRuleAbsent && exists(file)) throw new Error(`安装期间出现未归属的旧原型入口,保留文件并停止安装:${file}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
150
158
|
try {
|
|
159
|
+
checkRetiredEntryRules();
|
|
151
160
|
// Stage every target before replacing the first installed asset.
|
|
152
161
|
for (const [index, asset] of plan.assets.entries()) {
|
|
153
162
|
if (!contexts.has(asset.base)) {
|
|
@@ -176,6 +185,9 @@ function executeInstallation(plan, { force = false } = {}) {
|
|
|
176
185
|
}
|
|
177
186
|
if (asset.kind === 'result' && fingerprint(asset.source) !== asset.expectedFingerprint) throw new Error(`安装期间评测结果已改变:${asset.source}`);
|
|
178
187
|
if (asset.kind === 'result' && asset.existing && fingerprint(asset.destination) !== asset.expectedFingerprint) throw new Error(`安装期间目标评测结果已改变:${asset.destination}`);
|
|
188
|
+
if (asset.retiredFingerprint && fingerprint(asset.destination) !== asset.retiredFingerprint) {
|
|
189
|
+
throw new Error(`安装期间旧原型入口已改变,保留文件并停止自动退出:${asset.destination}`);
|
|
190
|
+
}
|
|
179
191
|
if (asset.reusable) {
|
|
180
192
|
const unchanged = fingerprint(asset.destination) === asset.expectedFingerprint
|
|
181
193
|
&& fingerprint(asset.staged) === asset.expectedFingerprint;
|
|
@@ -198,6 +210,7 @@ function executeInstallation(plan, { force = false } = {}) {
|
|
|
198
210
|
change.written = true;
|
|
199
211
|
}
|
|
200
212
|
}
|
|
213
|
+
checkRetiredEntryRules();
|
|
201
214
|
pruneRetiredDirectories(plan.assets);
|
|
202
215
|
completed = true;
|
|
203
216
|
const ownedPaths = new Set(plan.assets.filter(asset => asset.kind !== 'legacy').map(asset => asset.destination));
|
|
@@ -213,6 +226,8 @@ function executeInstallation(plan, { force = false } = {}) {
|
|
|
213
226
|
for (const target of plan.targets) {
|
|
214
227
|
findUserFiles(path.join(target.base, name));
|
|
215
228
|
for (const category of ['references', 'evals', 'hooks', 'scripts', 'docs']) findUserFiles(path.join(target.base, category, name));
|
|
229
|
+
const userPrototypeAgent = path.join(target.base, 'agents', 'prototype-specialist.md');
|
|
230
|
+
if (exists(userPrototypeAgent) && !ownedPaths.has(userPrototypeAgent)) plan.preserved.push(userPrototypeAgent);
|
|
216
231
|
}
|
|
217
232
|
return [];
|
|
218
233
|
} catch (error) {
|
package/bin/native-layout.cjs
CHANGED
|
@@ -78,7 +78,7 @@ function renderAsset(buffer, asset) {
|
|
|
78
78
|
'本目录提供评测、校验、回归测试、Hook、共享参考资料和使用指南。技能、命令和 Agent 位于上一级的对应目录,只有一份;这里的评测读取宿主实际安装的内容。\n\n' +
|
|
79
79
|
'进入本目录后运行:\n\n```bash\nnpm test\nnode scripts/run-evals.js --locale zh-CN --min-rank1 95\n```\n\n' +
|
|
80
80
|
'`npm test` 执行内容校验、中英文确定性评测及全部脚本回归测试,不需要 npm install。模型行为评测需要另行配置执行宿主;详见 [evals/README.md](evals/README.md)。\n\n' +
|
|
81
|
-
'`adapters/` 保留其他命令格式和插件清单,供原版一致性校验与回归测试使用,不自动注册或启用插件。
|
|
81
|
+
'`adapters/` 保留其他命令格式和插件清单,供原版一致性校验与回归测试使用,不自动注册或启用插件。CodeBuddy 通过 `hooks/manage.cjs` 统一管理原版三组和新增原型审计,默认不启用;其他宿主仍按各自协议配置。缓存与代码块保护分别详见 [hooks/SDD-CACHE.md](hooks/SDD-CACHE.md) 和 [hooks/SIMPLIFY-IGNORE.md](hooks/SIMPLIFY-IGNORE.md),CodeBuddy 管理见 [docs/codebuddy-setup.md](docs/codebuddy-setup.md)。\n');
|
|
82
82
|
if (asset.kind === 'runtime') return Buffer.from(text.replace('__I3_INSTALL_VERSION__', asset.version));
|
|
83
83
|
if (asset.kind === 'script') return Buffer.from(nativeScript(text, relative));
|
|
84
84
|
if (relative === 'hooks/session-start.sh') {
|
package/bin/native-migration.cjs
CHANGED
|
@@ -6,6 +6,13 @@ const { fingerprint } = require('./asset-fingerprint.cjs');
|
|
|
6
6
|
const inventory = require('./legacy-native-files.json').files;
|
|
7
7
|
const name = 'i3-composer-agent';
|
|
8
8
|
const publishedFiles = new Set(inventory);
|
|
9
|
+
// Reviewed native bytes from the 99b5eae / 521c958 pilot package. Earlier or
|
|
10
|
+
// edited variants have no reliable content record in layout-3 manifests, so
|
|
11
|
+
// they require manual handling rather than trusting a path-only ownership claim.
|
|
12
|
+
const retiredPrototypeAssets = {
|
|
13
|
+
'rules/i3-prototype-entry.md': '1c89ad58619968e1826cab31b9f6de29ac04d5fc5b8b1c2a2e1a1b64ec9449af',
|
|
14
|
+
'agents/prototype-specialist.md': '4d1aa1c6c913694e8a1c7d3373245377899f9cf3f08ec410b40814fa7cda541f',
|
|
15
|
+
};
|
|
9
16
|
|
|
10
17
|
function ownsAsset(previous, relative) {
|
|
11
18
|
return previous.assets.some(file => file === relative
|
|
@@ -15,7 +22,8 @@ function ownsAsset(previous, relative) {
|
|
|
15
22
|
function allowed(relative) {
|
|
16
23
|
return typeof relative === 'string' && !relative.includes('\0') && !relative.includes(':') && !relative.includes('\\')
|
|
17
24
|
&& !relative.split('/').some(part => ['', '.', '..'].includes(part))
|
|
18
|
-
&& (
|
|
25
|
+
&& (relative === 'rules/i3-prototype-entry.md'
|
|
26
|
+
|| /^(skills|commands|agents|references|evals|hooks|scripts|docs)\//.test(relative)
|
|
19
27
|
|| relative.startsWith(`${name}/`) || [`${name}-LICENSE`, `${name}-NOTICE.md`].includes(relative));
|
|
20
28
|
}
|
|
21
29
|
|
|
@@ -31,17 +39,33 @@ function fileAt(base, relative) {
|
|
|
31
39
|
}
|
|
32
40
|
|
|
33
41
|
function migrationAssets(target, previous, current) {
|
|
34
|
-
if (!previous) return [];
|
|
35
42
|
const assets = [];
|
|
36
43
|
const oldFiles = new Set();
|
|
37
44
|
const retired = new Set();
|
|
38
45
|
const base = target.base;
|
|
46
|
+
for (const [relative, expectedFingerprint] of Object.entries(retiredPrototypeAssets)) {
|
|
47
|
+
if (current.has(relative)) continue;
|
|
48
|
+
const file = fileAt(base, relative);
|
|
49
|
+
let present;
|
|
50
|
+
try { present = fs.lstatSync(path.join(base, relative)); }
|
|
51
|
+
catch (error) { if (error.code === 'ENOENT') continue; throw error; }
|
|
52
|
+
const owned = previous?.assets.includes(relative);
|
|
53
|
+
// Keep the existing protection for unowned CodeBuddy rules. A user-created
|
|
54
|
+
// Agent with this name is outside our catalog and must not be claimed.
|
|
55
|
+
if (!owned && relative.startsWith('agents/')) continue;
|
|
56
|
+
if (!owned && !target.agents?.includes('codebuddy')) continue;
|
|
57
|
+
if (!owned || !file || !present.isFile() || fingerprint(file) !== expectedFingerprint) {
|
|
58
|
+
throw new Error(`保留了已修改、未知或未归属本包的旧原型入口,不能自动退出;请先检查并手动处理后重试:${path.join(base, relative)}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (!previous) return [];
|
|
39
62
|
function retire(relative) {
|
|
40
63
|
if (retired.has(relative) || current.has(relative)) return;
|
|
41
64
|
const file = fileAt(base, relative);
|
|
42
65
|
if (!file || !fs.statSync(file).isFile()) return;
|
|
43
66
|
retired.add(relative);
|
|
44
|
-
assets.push({ base, destination: file, relative, kind: 'legacy'
|
|
67
|
+
assets.push({ base, destination: file, relative, kind: 'legacy',
|
|
68
|
+
...(retiredPrototypeAssets[relative] ? { retiredFingerprint: retiredPrototypeAssets[relative] } : {}) });
|
|
45
69
|
}
|
|
46
70
|
for (const relative of previous.assets) {
|
|
47
71
|
const file = fileAt(base, relative);
|
package/bin/tool-selector.cjs
CHANGED
|
@@ -42,7 +42,7 @@ function wrap(text, columns) {
|
|
|
42
42
|
function selectTools(initialSelection, input = process.stdin, output = process.stdout) {
|
|
43
43
|
const selected = new Set(initialSelection);
|
|
44
44
|
let view = 'common', cursor = 0, commonCursor = 0, query = '', searching = false, message = '';
|
|
45
|
-
let frame = [], pageSize = 10, finished = false;
|
|
45
|
+
let frame = [], pageSize = 10, finished = false, numberInput = '';
|
|
46
46
|
const wasRaw = Boolean(input.isRaw), wasFlowing = input.readableFlowing;
|
|
47
47
|
const choices = () => view === 'common' ? [...orderedAgents.slice(0, commonIds.length), null]
|
|
48
48
|
: view === 'more' ? orderedAgents.slice(commonIds.length)
|
|
@@ -71,8 +71,8 @@ function selectTools(initialSelection, input = process.stdin, output = process.s
|
|
|
71
71
|
}
|
|
72
72
|
const hints = searching
|
|
73
73
|
? ['输入关键词实时搜索', 'Enter/↓ 浏览结果 · Esc返回 · Ctrl-C取消']
|
|
74
|
-
: ['
|
|
75
|
-
const footer = ['', ...summary, ...hints.flatMap(line => wrap(line, columns)), message];
|
|
74
|
+
: ['数字+Enter指定工具 · ↑↓/空格勾选', 'm 更多 · / 搜索 · b/← 返回 · q/Esc取消'];
|
|
75
|
+
const footer = ['', ...summary, ...hints.flatMap(line => wrap(line, columns)), numberInput ? `编号:${numberInput}(逗号多选,Enter确认)` : message];
|
|
76
76
|
const searchLine = view === 'search' ? [`搜索:${query}${searching ? '|' : ''}`] : [];
|
|
77
77
|
pageSize = Math.max(1, Math.min(10, rows - footer.length - searchLine.length - 2));
|
|
78
78
|
const page = Math.floor(cursor / pageSize), pages = Math.max(1, Math.ceil(entries.length / pageSize));
|
|
@@ -130,19 +130,36 @@ function selectTools(initialSelection, input = process.stdin, output = process.s
|
|
|
130
130
|
if (view === 'search') back(); else { cancel(); return; }
|
|
131
131
|
} else if (text === 'q') { cancel(); return; }
|
|
132
132
|
else if (['return', 'enter'].includes(key.name)) {
|
|
133
|
+
if (numberInput) {
|
|
134
|
+
if (numberInput === '0') { cancel(); return; }
|
|
135
|
+
const numbers = numberInput.split(/[,,]/).map(Number);
|
|
136
|
+
if (numbers.every(number => Number.isInteger(number) && number >= 1 && number <= orderedAgents.length)) {
|
|
137
|
+
selected.clear();
|
|
138
|
+
for (const number of numbers) selected.add(orderedAgents[number - 1].id);
|
|
139
|
+
finish([...selected]); return;
|
|
140
|
+
}
|
|
141
|
+
numberInput = ''; message = `请输入 1–${orderedAgents.length} 的编号(逗号多选),0 取消。`;
|
|
142
|
+
render(); return;
|
|
143
|
+
}
|
|
133
144
|
if (selected.size) { finish([...selected]); return; }
|
|
134
|
-
message = '
|
|
145
|
+
message = '请用数字编号或空格选择工具,再按 Enter。';
|
|
146
|
+
} else if (text && /^[0-9,,]$/.test(text)) {
|
|
147
|
+
if (numberInput.length < 255) numberInput += text;
|
|
148
|
+
} else if (key.name === 'backspace') {
|
|
149
|
+
numberInput = numberInput.slice(0, -1);
|
|
135
150
|
} else if (key.name === 'space' || text === ' ') {
|
|
151
|
+
if (numberInput) { render(); return; }
|
|
136
152
|
const entry = choices()[cursor];
|
|
137
153
|
if (entry) { if (selected.has(entry.id)) selected.delete(entry.id); else selected.add(entry.id); }
|
|
138
154
|
else if (view === 'common') openMore();
|
|
139
155
|
} else if (['up', 'down', 'pageup', 'pagedown'].includes(key.name) || ['n', 'p'].includes(text)) {
|
|
156
|
+
numberInput = '';
|
|
140
157
|
const direction = ['up', 'pageup'].includes(key.name) || text === 'p' ? -1 : 1;
|
|
141
158
|
const step = ['pageup', 'pagedown'].includes(key.name) || ['n', 'p'].includes(text) ? pageSize : 1;
|
|
142
159
|
cursor = Math.max(0, Math.min(choices().length - 1, cursor + direction * step));
|
|
143
|
-
} else if (text === 'm' || (key.name === 'right' && view === 'common')) openMore();
|
|
144
|
-
else if (text === 'b' || key.name === 'left') back();
|
|
145
|
-
else if (text === '/') { if (view === 'common') commonCursor = cursor; view = 'search'; query = ''; cursor = 0; searching = true; }
|
|
160
|
+
} else if (text === 'm' || (key.name === 'right' && view === 'common')) { numberInput = ''; openMore(); }
|
|
161
|
+
else if (text === 'b' || key.name === 'left') { numberInput = ''; back(); }
|
|
162
|
+
else if (text === '/') { numberInput = ''; if (view === 'common') commonCursor = cursor; view = 'search'; query = ''; cursor = 0; searching = true; }
|
|
146
163
|
render();
|
|
147
164
|
} catch (error) { fail(error); }
|
|
148
165
|
}
|