@givolt/i3-composer-agent 2.0.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/plugins/marketplace.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +37 -33
- package/bin/agent-targets.json +11 -0
- package/bin/asset-fingerprint.cjs +38 -0
- package/bin/cleanup-backups.cjs +16 -0
- package/bin/i3-composer-agent.cjs +28 -12
- package/bin/install.cjs +74 -28
- package/bin/native-content.cjs +29 -0
- package/bin/wizard.cjs +3 -1
- package/docs/antigravity-setup.md +1 -1
- package/docs/codebuddy-setup.md +16 -3
- package/docs/cursor-setup.md +2 -2
- package/docs/getting-started.md +0 -2
- package/docs/opencode-setup.md +4 -4
- package/docs/workbuddy-setup.md +106 -0
- package/package.json +36 -20
- package/plugin.json +1 -1
- package/CHANGELOG.md +0 -51
- package/NOTICE.md +0 -15
- package/docs/advanced-per-agent-configuration.md +0 -70
- package/docs/comparison.md +0 -131
- package/docs/developer-onboarding.md +0 -116
- package/docs/skill-anatomy.md +0 -203
- package/evals/README.md +0 -101
- package/evals/cases/i3-api-and-interface-design.json +0 -45
- package/evals/cases/i3-browser-testing-with-devtools.json +0 -44
- package/evals/cases/i3-ci-cd-and-automation.json +0 -45
- package/evals/cases/i3-code-review-and-quality.json +0 -49
- package/evals/cases/i3-code-simplification.json +0 -45
- package/evals/cases/i3-constraint-driven-development.json +0 -79
- package/evals/cases/i3-context-engineering.json +0 -44
- package/evals/cases/i3-debugging-and-error-recovery.json +0 -58
- package/evals/cases/i3-deprecation-and-migration.json +0 -52
- package/evals/cases/i3-documentation-and-adrs.json +0 -44
- package/evals/cases/i3-doubt-driven-development.json +0 -43
- package/evals/cases/i3-frontend-ui-engineering.json +0 -52
- package/evals/cases/i3-git-workflow-and-versioning.json +0 -47
- package/evals/cases/i3-idea-refine.json +0 -43
- package/evals/cases/i3-incremental-implementation.json +0 -57
- package/evals/cases/i3-interview-me.json +0 -42
- package/evals/cases/i3-observability-and-instrumentation.json +0 -44
- package/evals/cases/i3-performance-optimization.json +0 -53
- package/evals/cases/i3-planning-and-task-breakdown.json +0 -45
- package/evals/cases/i3-security-and-hardening.json +0 -53
- package/evals/cases/i3-shipping-and-launch.json +0 -56
- package/evals/cases/i3-source-driven-development.json +0 -44
- package/evals/cases/i3-spec-driven-development.json +0 -72
- package/evals/cases/i3-test-driven-development.json +0 -73
- package/evals/cases/i3-using-agent-skills.json +0 -44
- package/evals/fixtures/i3-api-and-interface-design/service-brief.md +0 -19
- package/evals/fixtures/i3-browser-testing-with-devtools/README.md +0 -5
- package/evals/fixtures/i3-browser-testing-with-devtools/index.html +0 -24
- package/evals/fixtures/i3-browser-testing-with-devtools/server.js +0 -15
- package/evals/fixtures/i3-ci-cd-and-automation/package.json +0 -8
- package/evals/fixtures/i3-ci-cd-and-automation/src/slug.js +0 -3
- package/evals/fixtures/i3-ci-cd-and-automation/test/slug.test.js +0 -9
- package/evals/fixtures/i3-code-review-and-quality/user-search.diff +0 -16
- package/evals/fixtures/i3-code-simplification/config-parser.js +0 -46
- package/evals/fixtures/i3-code-simplification/config-parser.test.js +0 -15
- package/evals/fixtures/i3-context-engineering/context-audit.md +0 -15
- package/evals/fixtures/i3-debugging-and-error-recovery/pagination.js +0 -8
- package/evals/fixtures/i3-debugging-and-error-recovery/pagination.test.js +0 -9
- package/evals/fixtures/i3-debugging-and-error-recovery/time-pressure.md +0 -6
- package/evals/fixtures/i3-deprecation-and-migration/api-inventory.md +0 -9
- package/evals/fixtures/i3-documentation-and-adrs/decision-context.md +0 -16
- package/evals/fixtures/i3-doubt-driven-development/migration-plan.md +0 -19
- package/evals/fixtures/i3-frontend-ui-engineering/Button.tsx +0 -7
- package/evals/fixtures/i3-frontend-ui-engineering/design-system.md +0 -11
- package/evals/fixtures/i3-git-workflow-and-versioning/.eval/working-tree.patch +0 -21
- package/evals/fixtures/i3-git-workflow-and-versioning/app.js +0 -7
- package/evals/fixtures/i3-git-workflow-and-versioning/app.test.js +0 -9
- package/evals/fixtures/i3-incremental-implementation/reports.js +0 -7
- package/evals/fixtures/i3-incremental-implementation/reports.test.js +0 -12
- package/evals/fixtures/i3-incremental-implementation/tasks/plan.md +0 -8
- package/evals/fixtures/i3-observability-and-instrumentation/operations.md +0 -11
- package/evals/fixtures/i3-observability-and-instrumentation/payment-retry.js +0 -14
- package/evals/fixtures/i3-performance-optimization/benchmark.js +0 -15
- package/evals/fixtures/i3-performance-optimization/products.js +0 -14
- package/evals/fixtures/i3-planning-and-task-breakdown/notifications-spec.md +0 -18
- package/evals/fixtures/i3-security-and-hardening/webhook.js +0 -11
- package/evals/fixtures/i3-security-and-hardening/webhook.test.js +0 -13
- package/evals/fixtures/i3-shipping-and-launch/authority-pressure.md +0 -6
- package/evals/fixtures/i3-shipping-and-launch/launch-status.md +0 -11
- package/evals/fixtures/i3-source-driven-development/framework-task.md +0 -10
- package/evals/fixtures/i3-spec-driven-development/billing-brief.md +0 -16
- package/evals/fixtures/i3-test-driven-development/BUG.md +0 -10
- package/evals/fixtures/i3-test-driven-development/README.md +0 -28
- package/evals/fixtures/i3-test-driven-development/package.json +0 -9
- package/evals/fixtures/i3-test-driven-development/src/split.js +0 -8
- package/evals/fixtures/i3-test-driven-development/test/split.test.js +0 -13
- package/evals/fixtures/i3-using-agent-skills/incident.md +0 -6
- package/evals/fixtures/incremental-implementation-pressure/draft-export.js +0 -17
- package/evals/fixtures/incremental-implementation-pressure/scenario.md +0 -9
- package/evals/fixtures/spec-driven-development-decomposition/portal-brief.md +0 -22
- package/evals/fixtures/test-driven-development-ecosystem/README.md +0 -9
- package/evals/fixtures/test-driven-development-ecosystem/ledger.py +0 -15
- package/evals/fixtures/test-driven-development-ecosystem/test_ledger.py +0 -19
- package/evals/plugin/code-review-fires/graders/off-by-one.md +0 -7
- package/evals/plugin/code-review-fires/graders/severity-labels.md +0 -4
- package/evals/plugin/code-review-fires/graders/skill-fired.md +0 -5
- package/evals/plugin/code-review-fires/prompt.md +0 -31
- package/evals/plugin/code-review-stays-quiet/graders/not-fired.md +0 -8
- package/evals/plugin/code-review-stays-quiet/graders/tdd-fired.md +0 -6
- package/evals/plugin/code-review-stays-quiet/prompt.md +0 -8
- package/evals/plugin/code-review-stays-quiet-on-commit-message/graders/not-fired.md +0 -8
- package/evals/plugin/code-review-stays-quiet-on-commit-message/prompt.md +0 -25
- package/evals/skill-impact.md +0 -6
- package/rebrand/INSTALLATION-SPEC.md +0 -47
- package/rebrand/MAINTENANCE.md +0 -114
- package/rebrand/NOTICE.md +0 -15
- package/rebrand/PR-WORKFLOW.md +0 -34
- package/rebrand/PREFIX-SPEC.md +0 -16
- package/rebrand/UNIFICATION-SPEC.md +0 -33
- package/rebrand/VALIDATION.md +0 -32
- package/rebrand/VERSIONING.md +0 -35
- package/rebrand/apply.cjs +0 -217
- package/rebrand/brand.json +0 -13
- package/rebrand/catalog.cjs +0 -70
- package/rebrand/fork-patches.json +0 -27
- package/rebrand/identifiers.cjs +0 -41
- package/rebrand/overlay/.github/workflows/test-plugin-install.yml +0 -177
- package/rebrand/overlay/CHANGELOG.md +0 -51
- package/rebrand/overlay/bin/agent-targets.json +0 -726
- package/rebrand/overlay/bin/i3-composer-agent.cjs +0 -190
- package/rebrand/overlay/bin/install.cjs +0 -180
- package/rebrand/overlay/bin/skills-registry.LICENSE +0 -21
- package/rebrand/overlay/bin/wizard.cjs +0 -66
- package/rebrand/overlay/scripts/validate-brand.cjs +0 -44
- package/rebrand/overlay/tests/bundle.test.cjs +0 -85
- package/rebrand/overlay/tests/installer.test.cjs +0 -241
- package/rebrand/package.template.json +0 -82
- package/rebrand/rebrand.sh +0 -4
- package/rebrand/record-upstream.cjs +0 -37
- package/rebrand/templates/README.md +0 -130
- package/rebrand/templates/codebuddy-setup.md +0 -89
- package/rebrand/templates/codex-setup.md +0 -45
- package/rebrand/tests/pipeline.test.cjs +0 -253
- package/rebrand/upstream.json +0 -171
- package/scripts/floor-guard-reference-test.js +0 -291
- package/scripts/lib/skill-lint-test.js +0 -650
- package/scripts/lib/skill-lint.js +0 -586
- package/scripts/run-evals-test.js +0 -623
- package/scripts/run-evals.js +0 -638
- package/scripts/validate-artifact-paths-test.js +0 -179
- package/scripts/validate-artifact-paths.js +0 -130
- package/scripts/validate-brand.cjs +0 -44
- package/scripts/validate-commands-test.js +0 -216
- package/scripts/validate-commands.js +0 -223
- package/scripts/validate-reference-links-test.js +0 -495
- package/scripts/validate-reference-links.js +0 -187
- package/scripts/validate-skills.js +0 -69
- package/scripts/validate-versions-test.js +0 -32
- package/scripts/validate-versions.js +0 -35
- package/tests/bundle.test.cjs +0 -85
- package/tests/installer.test.cjs +0 -241
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# Installation wizard correction
|
|
2
|
-
|
|
3
|
-
The published 1.0.0 CLI prepares plugin files but does not implement the
|
|
4
|
-
installation wizard previously described to the user. Restore the promised
|
|
5
|
-
installation flow, including the user's confirmed multiple-tool selection and
|
|
6
|
-
CodeBuddy desktop IDE target.
|
|
7
|
-
|
|
8
|
-
## Acceptance contract
|
|
9
|
-
|
|
10
|
-
- Running the package in an interactive terminal opens a tool multi-select,
|
|
11
|
-
project/global scope selection, destination summary, and confirmation.
|
|
12
|
-
- Host flags preselect tools rather than silently preparing a plugin. The tool
|
|
13
|
-
catalog preserves the installation paths from the pinned Vercel Skills CLI
|
|
14
|
-
registry; CodeBuddy, Codex, Claude Code, Cursor and other tools remain choices.
|
|
15
|
-
- Native installation copies all skills and their shared references. CodeBuddy
|
|
16
|
-
and Claude Code also receive the nine existing command workflows and personas.
|
|
17
|
-
Portable command references use the installed i3- Skill IDs. Prefix migration
|
|
18
|
-
follows PREFIX-SPEC.md, with backups and rollback for owned legacy paths.
|
|
19
|
-
- Shared destinations are installed once when several tools use the same path.
|
|
20
|
-
- Existing assets require confirmed replacement and are retained in backups.
|
|
21
|
-
Unrelated settings and project files are untouched. Failed installation rolls
|
|
22
|
-
back completed writes; cancellation and dry runs write nothing.
|
|
23
|
-
- `--prepare`, `--extract`, and existing explicit `--dir` calls retain complete
|
|
24
|
-
plugin preparation. Plain `--version` remains machine-readable.
|
|
25
|
-
- Noninteractive installation requires explicit tools, scope and `--yes`;
|
|
26
|
-
replacement additionally requires `--force`.
|
|
27
|
-
- Packaging tests exercise the shipped CLI; a real terminal session verifies
|
|
28
|
-
the wizard. File discovery and actual model execution are separate evidence.
|
|
29
|
-
|
|
30
|
-
## Implementation and verification
|
|
31
|
-
|
|
32
|
-
Keep upstream content unchanged on `agent/source`; all fork changes live under
|
|
33
|
-
`rebrand/`. Distribution modules and tests are replayed from `rebrand/overlay/`.
|
|
34
|
-
Use Node.js built-ins and the existing `node:test` conventions. No new runtime
|
|
35
|
-
dependency is required. Keep the upstream baseline at 0.6.12 and the release
|
|
36
|
-
version at 1.0.0 during development. Recommend and obtain the user's approval
|
|
37
|
-
for a new release version before changing it or publishing.
|
|
38
|
-
|
|
39
|
-
On 2026-10-07 the user accepted the recommended 1.0.1 correction release and
|
|
40
|
-
authorized publication. The upstream baseline remains 0.6.12.
|
|
41
|
-
|
|
42
|
-
Slices: first prove native multi-tool installation fails on the published CLI;
|
|
43
|
-
then implement directory planning and copying; then add the interactive flow;
|
|
44
|
-
finally verify conflicts, rollback, package extraction and terminal execution.
|
|
45
|
-
|
|
46
|
-
Commands: `node --test tests/installer.test.cjs`, `npm test`, `npm run validate`,
|
|
47
|
-
`npm run rebrand:check`, and `npm pack` in a generated branded candidate.
|
package/rebrand/MAINTENANCE.md
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
# i3 Composer Agent 仓库维护
|
|
2
|
-
|
|
3
|
-
本指南只适用于 Agent 仓库;GSD / i3 Composer Work 是另一个独立仓库。
|
|
4
|
-
这里借鉴其维护方式,不复用其源码、安装产物或 Git 分支。
|
|
5
|
-
|
|
6
|
-
## 仓库和分支
|
|
7
|
-
|
|
8
|
-
- 品牌仓库:`https://github.com/49780522/i3-composer-agent`(Private)。
|
|
9
|
-
- `origin` 指向品牌仓库;`upstream` 指向 `https://github.com/addyosmani/agent-skills.git`。
|
|
10
|
-
- `agent/source`:原始上游源码与名称,加本项目 `rebrand/` 工具和规则。
|
|
11
|
-
- `main`:经过重放与验证的品牌快照;npm 身份为 `@givolt/i3-composer-agent`。
|
|
12
|
-
- `i3-composer-agent-v0.6.12`:已经发布的首次包所对应的原始品牌提交。
|
|
13
|
-
|
|
14
|
-
源码工作树为 `/Users/howard/Workspace/composer-skills-source/agent-source`;
|
|
15
|
-
品牌工作树为 `/Users/howard/Workspace/composer-skills-source/agent-skills`。
|
|
16
|
-
旧的 Agent 本地 `i3/source` 分支已改为 `agent/source`,避免与 GSD 分支名称混淆。
|
|
17
|
-
|
|
18
|
-
## 获取源码
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
git clone https://github.com/49780522/i3-composer-agent.git
|
|
22
|
-
cd i3-composer-agent
|
|
23
|
-
git remote add upstream https://github.com/addyosmani/agent-skills.git
|
|
24
|
-
git fetch upstream --tags
|
|
25
|
-
git worktree add --track -b agent/source ../agent-source origin/agent/source
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
源分支没有发行用的根 package.json。包入口、发行测试和配置由
|
|
29
|
-
`rebrand/overlay/`、`package.template.json` 在品牌候选中生成。
|
|
30
|
-
|
|
31
|
-
## 同步上游
|
|
32
|
-
|
|
33
|
-
1. 在 Agent 源工作树获取上游,选择并审查一个明确的版本或提交。
|
|
34
|
-
2. 从 `agent/source` 创建维护分支,合并该 ref 并解决源码冲突。
|
|
35
|
-
3. 从同一 ref 记录上游目录和 Skill frontmatter;审查记录中的新增、删除和描述变化。
|
|
36
|
-
4. 调整文字补丁、分发 overlay 和品牌模板;源码分支保持原始名称。
|
|
37
|
-
5. 运行源验证,提交维护分支,通过 PR 合入 `agent/source`。
|
|
38
|
-
6. 从更新后的源分支创建独立品牌候选工作树,重放、验证和打包。
|
|
39
|
-
7. 将验证过的品牌快照通过发行 PR 更新 `main`;npm 发布单独执行。
|
|
40
|
-
|
|
41
|
-
源维护阶段示例(把示例分支和 ref 替换为实际选定值):
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
cd /Users/howard/Workspace/composer-skills-source/agent-source
|
|
45
|
-
git fetch upstream --tags
|
|
46
|
-
git switch -c sync/upstream-next agent/source
|
|
47
|
-
git merge --no-commit --no-ff upstream/main
|
|
48
|
-
# 审查并处理源码冲突后:
|
|
49
|
-
node rebrand/record-upstream.cjs upstream/main
|
|
50
|
-
node --test scripts/*-test.js scripts/lib/*-test.js rebrand/tests/*.test.cjs
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
记录工具读取 Git 对象中的上游文件,写入 `upstream.json` 和 `brand.json` 的基线。
|
|
54
|
-
它不会把任意本地新增文件认定为上游。发布版本由 `brand.json.releaseVersion`
|
|
55
|
-
控制,与 `upstream.json.upstreamVersion` 分开;按实际更改递增,保持六份清单一致。
|
|
56
|
-
|
|
57
|
-
品牌版本从 `1.0.0` 开始使用独立编号;本次仅修改 i3,上游基线保留为 `0.6.12`。
|
|
58
|
-
之后的当前基线以 `upstream.json` 记录为准。
|
|
59
|
-
仅修改 i3 的修复或分发规则时,只递增品牌版本;上游版本和提交保持原值。
|
|
60
|
-
README、CLI 帮助和准备完成提示同时显示这两个版本;`--version` 保留单一品牌版本输出。
|
|
61
|
-
具体规则与历史版本处理见 [VERSIONING.md](VERSIONING.md)。
|
|
62
|
-
|
|
63
|
-
## 创建品牌候选
|
|
64
|
-
|
|
65
|
-
从源分支创建候选,每次换一个分支名和独立目录:
|
|
66
|
-
|
|
67
|
-
```bash
|
|
68
|
-
cd /Users/howard/Workspace/composer-skills-source/agent-skills
|
|
69
|
-
git fetch origin
|
|
70
|
-
git worktree add -b release/agent-next ../agent-candidate origin/agent/source
|
|
71
|
-
cd ../agent-candidate
|
|
72
|
-
bash rebrand/rebrand.sh --apply
|
|
73
|
-
bash rebrand/rebrand.sh --check
|
|
74
|
-
npm run validate
|
|
75
|
-
npm test
|
|
76
|
-
node scripts/run-evals.js --min-rank1 95
|
|
77
|
-
bash hooks/session-start-test.sh
|
|
78
|
-
bash hooks/sdd-cache-test.sh
|
|
79
|
-
bash hooks/simplify-ignore-test.sh
|
|
80
|
-
mkdir -p ../releases/next
|
|
81
|
-
npm pack --pack-destination ../releases/next
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
在打包前先创建输出目录。对 tarball 重新解包,验证 CLI、完整文件目录及宿主清单。
|
|
85
|
-
源码分支上执行 `--apply` 会在写入前失败;不得把未经重放的源分支直接更新到 `main`。
|
|
86
|
-
源 PR 与发行 PR 的边界见 [PR-WORKFLOW.md](PR-WORKFLOW.md)。
|
|
87
|
-
|
|
88
|
-
## 审查重放规则
|
|
89
|
-
|
|
90
|
-
- `fork-patches.json`:明确的文字补丁,源文本不再匹配时失败,要求人工适配。
|
|
91
|
-
- `overlay/`:本项目的 npm CLI、发行测试、品牌校验和发行 CI;上游相关文件改变时需合并审查。
|
|
92
|
-
- `templates/`:品牌 README 和安装指南;上游对应说明改变时同步模板。
|
|
93
|
-
- 目录数量、Skill 表、命令表和插件描述由已记录的目录生成,不固定为 25/9。
|
|
94
|
-
- 源码保留上游 Skill 名称;品牌版 Skill 和命令使用 i3- 前缀,按 PREFIX-SPEC.md 重放。
|
|
95
|
-
- Skill frontmatter 只映射 name;还原 name 后比较换行规范化的上游哈希,兼容 LF/CRLF。
|
|
96
|
-
- LICENSE、NOTICE、真实上游链接、历史评估说明和标准名称保留。
|
|
97
|
-
- 如果上游新增根 package.json,重放会失败,先适配分发配置和依赖再继续。
|
|
98
|
-
|
|
99
|
-
## 发布及验收
|
|
100
|
-
|
|
101
|
-
维护流程与安装能力分开验收。默认 npm CLI 使用多工具安装向导;`--prepare`
|
|
102
|
-
保留完整插件准备和宿主注册提示。两种模式分别验收,不把准备文件等同于安装。
|
|
103
|
-
实际宿主安装范围、启用、命令执行以及交互向导仍需各自验证。
|
|
104
|
-
Codex 的生命周期斜杠命令适配是独立工作;原生 Skill 通过 $i3-<名称> 调用。
|
|
105
|
-
|
|
106
|
-
发布审核通过后,发布已经测过的 tarball,先使用试用标签,完成 registry 安装验证后再更新 latest:
|
|
107
|
-
|
|
108
|
-
```bash
|
|
109
|
-
npm publish /absolute/path/to/reviewed-package.tgz --access public --tag next
|
|
110
|
-
npm dist-tag add @givolt/i3-composer-agent@<reviewed-version> latest
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
每个已发布包名和版本只用一次。GitHub Actions 与 GSD 品牌仓库一样先保持关闭,
|
|
114
|
-
适配并验证 CI 后再启用。当前验证范围见 [VALIDATION.md](VALIDATION.md)。
|
package/rebrand/NOTICE.md
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# Attribution
|
|
2
|
-
|
|
3
|
-
i3 Composer Agent is a branded distribution of
|
|
4
|
-
[Agent Skills](https://github.com/addyosmani/agent-skills) by Addy Osmani.
|
|
5
|
-
The initial distribution is based on upstream commit `1401c8b` (version 0.6.12).
|
|
6
|
-
|
|
7
|
-
The original MIT license and copyright notice are preserved in LICENSE.
|
|
8
|
-
Givolt maintains the branding, npm distribution, and installation CLI.
|
|
9
|
-
Skill IDs and command filenames use an i3- prefix in this distribution.
|
|
10
|
-
The original command workflows and persona definitions are retained.
|
|
11
|
-
|
|
12
|
-
The tool installation directory presets in `bin/agent-targets.json` are adapted
|
|
13
|
-
from Vercel's [Skills CLI registry](https://github.com/vercel-labs/skills/blob/48dc9e8eb8aa19040e91cb90ba0b642c9cbad57e/src/agents.ts)
|
|
14
|
-
at commit `48dc9e8eb8aa19040e91cb90ba0b642c9cbad57e`. Copyright (c) 2026
|
|
15
|
-
Vercel, Inc. Its MIT license is retained in `bin/skills-registry.LICENSE`.
|
package/rebrand/PR-WORKFLOW.md
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# Agent 源码与发行 PR
|
|
2
|
-
|
|
3
|
-
此流程只操作 49780522/i3-composer-agent。GSD 仓库只是维护方法的参考。
|
|
4
|
-
|
|
5
|
-
源码、修复和重放规则的 PR 以 `agent/source` 为 base,从该分支创建维护分支。
|
|
6
|
-
保持上游文件的原始名称;本项目分发工具放在 `rebrand/`。
|
|
7
|
-
|
|
8
|
-
```bash
|
|
9
|
-
git fetch origin
|
|
10
|
-
git worktree add -b fix/my-change ../agent-fix origin/agent/source
|
|
11
|
-
cd ../agent-fix
|
|
12
|
-
node --test scripts/*-test.js scripts/lib/*-test.js rebrand/tests/*.test.cjs
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
修改重放规则后,从维护提交另建品牌候选并执行 MAINTENANCE.md 中的完整验证。
|
|
16
|
-
审查和暂存本次文件后提交,再推送并创建源码 PR:
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
git push -u origin fix/my-change
|
|
20
|
-
gh pr create --base agent/source --head fix/my-change
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
源码 PR 合入后,从最新 `agent/source` 建立候选,重放、验证、打包并提交品牌内容。
|
|
24
|
-
发行 PR 以 `main` 为 base;head 必须包含验证后的品牌快照。
|
|
25
|
-
|
|
26
|
-
当 main 和源候选历史产生合并冲突时,从 main 创建发行 PR 分支,合入已验证的
|
|
27
|
-
品牌候选并审查冲突。最终跟踪文件树必须与验证过的候选一致,然后提交:
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
git diff --cached <validated-candidate-commit>
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
上述差异应为空。若合并中需要实际代码调整,重新验证调整后的发行内容和 tarball。
|
|
34
|
-
不要把原始 agent/source 直接作为发行 PR 的 head;不向 upstream 推送品牌提交。
|
package/rebrand/PREFIX-SPEC.md
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# i3 command and Skill identifiers
|
|
2
|
-
|
|
3
|
-
The user approved applying the existing i3 naming convention on 2026-10-07.
|
|
4
|
-
This supersedes the earlier preservation of unprefixed distribution identifiers.
|
|
5
|
-
|
|
6
|
-
- `agent/source` keeps upstream files and identifiers unchanged. Changes live in `rebrand/`.
|
|
7
|
-
- Branded Skill directories and YAML `name` fields use `i3-<upstream-id>`.
|
|
8
|
-
- All three command directories use `i3-<upstream-stem>` filenames, retaining the existing `plan`/`planning` host mapping.
|
|
9
|
-
- Native commands include `/i3-spec` and `/i3-build`; plugin commands include `/i3-composer-agent:i3-spec`.
|
|
10
|
-
- Rewrite local references, hooks, routing fixtures and documentation together. Preserve external upstream links, attribution, and Skill frontmatter other than `name`.
|
|
11
|
-
- Retain helper script filenames and executable permissions when their containing Skill directory is renamed.
|
|
12
|
-
- Replay and validation accept only a complete reviewed source catalog or its mapped branded catalog. Replaying branded output is idempotent.
|
|
13
|
-
- Installation migrates only legacy Skill/command paths listed in this package's prior installation manifest. Back up retired paths and support rollback. Unowned commands and skills remain in place.
|
|
14
|
-
- Verify source tests, branded validation/tests, routing/hooks, packed CLI installation, migration, rollback and the actual project installation. IDE discovery and model execution require separate host verification.
|
|
15
|
-
|
|
16
|
-
Release 2.0.0 applies this breaking identifier change. The user authorized publication on 2026-10-07. Publish and verify the reviewed new-version tarball; previously published tarballs remain immutable. The upstream baseline stays at 0.6.12.
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# Agent 项目维护流程统一
|
|
2
|
-
|
|
3
|
-
用户已确认借鉴 GSD 项目维护方式,并要求项目互相独立。本规范只约束 Agent 仓库。
|
|
4
|
-
|
|
5
|
-
## 目标与边界
|
|
6
|
-
|
|
7
|
-
- `upstream` 指向 addyosmani/agent-skills;`origin` 指向私有品牌仓库 49780522/i3-composer-agent。
|
|
8
|
-
- `agent/source` 保留上游原始名称和源码,在 `rebrand/` 保存本项目的分发工具与转换规则。
|
|
9
|
-
- 候选从 `agent/source` 创建,在候选中重放;`main` 保存经过验证的品牌快照。
|
|
10
|
-
- GSD 仓库只读,不使用它的源码、分支或安装产物。
|
|
11
|
-
- 源码保留上游 Skill ID;品牌版按 PREFIX-SPEC.md 使用 i3- 前缀。流程内容、Persona、参考文件和 MIT 来源署名保持。
|
|
12
|
-
- 本次完善源码同步和品牌重放;交互安装向导、Codex 命令适配及新的 npm 发布独立处理。
|
|
13
|
-
|
|
14
|
-
## 实现与命令
|
|
15
|
-
|
|
16
|
-
转换入口保持 Node.js 20+ 和零依赖:`node rebrand/apply.cjs --apply|--check`;另提供与 GSD 相同形式的 `bash rebrand/rebrand.sh` 入口。
|
|
17
|
-
|
|
18
|
-
上游基线由 `node rebrand/record-upstream.cjs <明确的 ref>` 从 Git 对象记录;源码分支上运行 `node --test rebrand/tests/*.test.cjs`。候选执行 `npm run validate`、`npm test` 和既有路由/hook 检查。
|
|
19
|
-
|
|
20
|
-
代码沿用 CommonJS、Node 内置 fs/path/assert。分发专属文件放在 `rebrand/overlay/`,发行包配置由模板生成,不把 branded README 或清单混入源码分支。
|
|
21
|
-
|
|
22
|
-
## 验收条件
|
|
23
|
-
|
|
24
|
-
1. 从干净上游源码及本项目规则能生成完整品牌包,重复重放不产生差异。
|
|
25
|
-
2. 在 `agent/source` 上执行写入式重放必须失败且不修改源码。
|
|
26
|
-
3. 记录上游新增 Skill/Command 后能生成相应清单和说明;删失或改写已记录 Skill ID 时校验失败。
|
|
27
|
-
4. 品牌版的 Skill name、目录和命令文件名统一使用 i3-;frontmatter 的其他字段、Persona、共享参考和流程契约保持。
|
|
28
|
-
5. 本地候选通过完整测试,并从打包结果运行 CLI 与校验。
|
|
29
|
-
6. 独立品牌仓库中的源/发行分支及远程关系正确;首次发布标签保持原来的 0.6.12 提交。
|
|
30
|
-
|
|
31
|
-
## 执行顺序
|
|
32
|
-
|
|
33
|
-
先为源到品牌的重放、源码保护、目录增长与完整性写失败测试;实现工具及模板生成;验证真实上游归档;提交源分支;生成并审查品牌候选;最后建立远程并同步分支。
|
package/rebrand/VALIDATION.md
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# Agent 维护流程验收合同
|
|
2
|
-
|
|
3
|
-
本合同对应 UNIFICATION-SPEC.md;完整执行记录写入每次的审计或发布目录。
|
|
4
|
-
|
|
5
|
-
## 源维护
|
|
6
|
-
|
|
7
|
-
- 上游 ref 是明确的 Git 提交;目录与 frontmatter 从该 ref 的对象记录。
|
|
8
|
-
- `agent/source` 的上游文件保留原始名称与内容;本项目新增文件限定在 rebrand/。
|
|
9
|
-
- 重放在源码分支上写入前失败。
|
|
10
|
-
- 重放规则改变时,运行 rebrand/tests/pipeline.test.cjs 并验证源候选到品牌的完整路径。
|
|
11
|
-
|
|
12
|
-
## 品牌候选
|
|
13
|
-
|
|
14
|
-
- Skill 和命令路径按 PREFIX-SPEC.md 映射为 i3- 名称;其余已记录运行文件保持目录一致。
|
|
15
|
-
- Skill frontmatter 只改 name;逆向映射 name 后比较上游哈希,换行差异不作为字段变更。
|
|
16
|
-
- 新增上游 Skill/Command 能进入目录、品牌说明和打包;缺失内容会失败。
|
|
17
|
-
- 文字补丁失去匹配时必须失败,不能静默遗漏。
|
|
18
|
-
- 重放后 --check 成功,完整 Node、路由与 hook 检查通过。
|
|
19
|
-
- npm package、插件和市场身份一致;六份版本一致。
|
|
20
|
-
- 品牌修复能独立递增发行版本,保留上游目录记录原文;包来源元数据与该记录一致。
|
|
21
|
-
- README、CLI 帮助和准备提示显示品牌版本与上游基线;--version 保持单一品牌版本输出。
|
|
22
|
-
- 打包后从压缩包重新验证完整布局、CLI 和宿主清单。
|
|
23
|
-
|
|
24
|
-
## 证据边界
|
|
25
|
-
|
|
26
|
-
源或包校验不等于 registry 发布,也不等于实际宿主启用和模型执行。
|
|
27
|
-
英文确定性 TF-IDF 路由分数不能代替中文或真实模型行为验收。
|
|
28
|
-
安装向导、宿主范围、升级和移除沿用安装遗漏审计的独立验收项。
|
|
29
|
-
|
|
30
|
-
交互安装修复必须覆盖多工具选择、项目/全局目录、共享 references、命令与
|
|
31
|
-
Persona 文件、冲突保护、备份、失败回滚和取消不写入。对打包后的 CLI 运行
|
|
32
|
-
真实终端向导,不能用 bundle 准备测试代替;安装文件也不等于 IDE 或模型验收。
|
package/rebrand/VERSIONING.md
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# i3 Composer Agent 版本规则
|
|
2
|
-
|
|
3
|
-
本规则已经用户确认,仅适用于 i3 Composer Agent 仓库。
|
|
4
|
-
|
|
5
|
-
| 信息 | 权威来源 | 当前发行值 |
|
|
6
|
-
| --- | --- | --- |
|
|
7
|
-
| i3 发行版本 | brand.json 的 releaseVersion | 2.0.0 |
|
|
8
|
-
| 上游版本 | upstream.json 的 upstreamVersion | 0.6.12 |
|
|
9
|
-
| 上游提交 | upstream.json 的 upstreamCommit | 1401c8b8030e023baeebb31781a6653fe8e93026 |
|
|
10
|
-
|
|
11
|
-
品牌版本采用独立的 major.minor.patch 编号。1.0.0 是这套编号的起点;
|
|
12
|
-
兼容的 i3 修复递增 patch,兼容的新功能递增 minor,需要使用者调整用法的变更递增 major。
|
|
13
|
-
实际同步上游并审查选定提交后,才用 record-upstream.cjs 更新上游版本与提交。
|
|
14
|
-
上游版本变动不自动决定品牌版本;品牌版本根据本次发行的实际变化确定。
|
|
15
|
-
|
|
16
|
-
重放将品牌版本写入 npm 包和插件清单,把上游版本、提交及仓库写入
|
|
17
|
-
package.json 的 i3ComposerAgent 来源字段。package.template.json 不保存发行版本,
|
|
18
|
-
发行版本统一由 brand.json 生成。
|
|
19
|
-
|
|
20
|
-
README、CLI 帮助和准备完成提示显示:
|
|
21
|
-
|
|
22
|
-
```text
|
|
23
|
-
i3 Composer Agent v2.0.0
|
|
24
|
-
Based on agent-skills v0.6.12
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
在上述例子中,--version 输出 2.0.0,保留脚本使用的单一版本格式。--dry-run 的 JSON
|
|
28
|
-
分别提供 version、upstreamVersion、upstreamCommit。
|
|
29
|
-
|
|
30
|
-
已经发布的 @givolt/i3-composer-agent@0.6.12 及其 Git 标签作为历史记录保留。
|
|
31
|
-
之前的 0.6.13 是未发布候选,新的独立版本候选替代它。
|
|
32
|
-
1.0.0 已发布。1.0.1 用于修复安装向导遗漏,版本与发布已由用户确认。
|
|
33
|
-
2.0.0 为命令和 Skill 的 i3- 前缀变更;使用者需要调整调用名,因此递增 major。
|
|
34
|
-
用户于 2026-10-07 要求修改并授权发布;上游版本和提交保持不变。
|
|
35
|
-
源码与打包验证不代表 npm 发布;发布仍按 MAINTENANCE.md 单独执行。
|
package/rebrand/apply.cjs
DELETED
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
const fs = require('node:fs');
|
|
5
|
-
const path = require('node:path');
|
|
6
|
-
const { spawnSync } = require('node:child_process');
|
|
7
|
-
const { validateCatalog, frontmatter } = require('./catalog.cjs');
|
|
8
|
-
const { skillId, runtimePath, rewriteReferences } = require('./identifiers.cjs');
|
|
9
|
-
const brand = require('./brand.json');
|
|
10
|
-
const upstream = require('./upstream.json');
|
|
11
|
-
const root = path.resolve(__dirname, '..');
|
|
12
|
-
const mode = process.argv[2];
|
|
13
|
-
if (!['--apply', '--check'].includes(mode)) {
|
|
14
|
-
console.error('Usage: node rebrand/apply.cjs --apply | --check');
|
|
15
|
-
process.exit(1);
|
|
16
|
-
}
|
|
17
|
-
if (mode === '--apply') {
|
|
18
|
-
const branch = spawnSync('git', ['-C', root, 'branch', '--show-current'], { encoding: 'utf8' });
|
|
19
|
-
if (branch.status === 0 && branch.stdout.trim() === brand.sourceBranch) {
|
|
20
|
-
console.error(`Refusing to transform the source branch ${brand.sourceBranch}; create a release candidate first.`);
|
|
21
|
-
process.exit(1);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
const branded = fs.existsSync(path.join(root, 'skills', skillId(upstream.skills[0])));
|
|
25
|
-
validateCatalog(root, upstream, { branded });
|
|
26
|
-
const inventory = upstream;
|
|
27
|
-
const renames = new Map();
|
|
28
|
-
if (!branded) {
|
|
29
|
-
for (const id of inventory.skills) renames.set(`skills/${id}`, `skills/${skillId(id)}`);
|
|
30
|
-
for (const file of inventory.runtimeFiles.filter(file => /^(?:\.claude\/commands|\.gemini\/commands|commands)\/[^/]+\.(?:md|toml)$/.test(file))) renames.set(file, runtimePath(file));
|
|
31
|
-
for (const target of renames.values()) if (fs.existsSync(path.join(root, target))) throw new Error(`Brand destination already exists: ${target}`);
|
|
32
|
-
}
|
|
33
|
-
for (const id of inventory.skills) {
|
|
34
|
-
for (const file of [`evals/cases/${id}.json`, `evals/fixtures/${id}`]) {
|
|
35
|
-
if (fs.existsSync(path.join(root, file))) {
|
|
36
|
-
const target = runtimePath(file);
|
|
37
|
-
if (fs.existsSync(path.join(root, target))) throw new Error(`Brand destination already exists: ${target}`);
|
|
38
|
-
renames.set(file, target);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
const packageFile = path.join(root, 'package.json');
|
|
43
|
-
if (fs.existsSync(packageFile) && JSON.parse(fs.readFileSync(packageFile, 'utf8')).name !== brand.npmName) {
|
|
44
|
-
console.error('Upstream package.json now exists; explicitly adapt the distribution overlay before replaying.');
|
|
45
|
-
process.exit(1);
|
|
46
|
-
}
|
|
47
|
-
const changes = new Map();
|
|
48
|
-
function update(relative, content) {
|
|
49
|
-
const file = path.join(root, relative);
|
|
50
|
-
if (!fs.existsSync(file) || fs.readFileSync(file, 'utf8') !== content) changes.set(relative, content);
|
|
51
|
-
else changes.delete(relative);
|
|
52
|
-
}
|
|
53
|
-
function transform(content, relative) {
|
|
54
|
-
const head = /^skills\/[^/]+\/SKILL\.md$/.test(relative) ? frontmatter(content) : '';
|
|
55
|
-
content = content.slice(head.length);
|
|
56
|
-
// Agent Skills is also the name of an independent specification.
|
|
57
|
-
const standard = '__I3_AGENT_SKILLS_STANDARD__';
|
|
58
|
-
let result = content
|
|
59
|
-
.replace('agents working on the [`addyosmani/agent-skills`](https://github.com/addyosmani/agent-skills) repository itself',
|
|
60
|
-
'agents working on the i3 Composer Agent repository itself, derived from [`addyosmani/agent-skills`](https://github.com/addyosmani/agent-skills)')
|
|
61
|
-
.replace(/Agent Skills(?=\s+(?:specification|spec\b|format\b|standard\b))/g, standard)
|
|
62
|
-
.replaceAll('addy-agent-skills', brand.name)
|
|
63
|
-
.replaceAll('agent-skills@addy-agent-skills', `${brand.name}@${brand.name}`)
|
|
64
|
-
.replaceAll('agent-skills@agent-skills', `${brand.name}@${brand.name}`)
|
|
65
|
-
.replace(/(?<![\w-])agent-skills:/g, `${brand.name}:`)
|
|
66
|
-
.replaceAll('/path/to/agent-skills', `/path/to/${brand.name}`)
|
|
67
|
-
.replaceAll('./agent-skills', `./${brand.name}`)
|
|
68
|
-
.replace(/(?<![\w/.-])agent-skills(?![\w-])/g, brand.name)
|
|
69
|
-
.replaceAll('Agent Skills', brand.displayName)
|
|
70
|
-
.replaceAll(standard, 'Agent Skills');
|
|
71
|
-
if (relative.startsWith('docs/')) {
|
|
72
|
-
result = result.split('\n').map(line => {
|
|
73
|
-
if (/^\s*git clone https:\/\/github\.com\/addyosmani\/agent-skills(?:\.git)?\s*$/.test(line)) {
|
|
74
|
-
return `${line.match(/^\s*/)[0]}npx ${brand.npmName} --extract --dir ./${brand.name}`;
|
|
75
|
-
}
|
|
76
|
-
if (/^\s*(?:npx |codex |copilot |cmd |agy |gemini |\/plugin )/.test(line)) {
|
|
77
|
-
return line.replaceAll('https://github.com/addyosmani/agent-skills.git', `/path/to/${brand.name}`)
|
|
78
|
-
.replaceAll('https://github.com/addyosmani/agent-skills', `/path/to/${brand.name}`)
|
|
79
|
-
.replaceAll('addyosmani/agent-skills', `/path/to/${brand.name}`);
|
|
80
|
-
}
|
|
81
|
-
return line;
|
|
82
|
-
}).join('\n');
|
|
83
|
-
result = result
|
|
84
|
-
.replace(/^cmd skills add \/path\/to\/i3-composer-agent@main[^\n]*$/gm,
|
|
85
|
-
'# Branch selectors apply to Git sources; prepared npm bundles have no Git history.')
|
|
86
|
-
.replaceAll('Clone the repository', 'Prepare the plugin bundle')
|
|
87
|
-
.replaceAll('Clone this repository', 'Prepare the plugin bundle')
|
|
88
|
-
.replaceAll('Install from the remote repository', 'Install from a prepared local bundle')
|
|
89
|
-
.replaceAll('npx skills add addyosmani/agent-skills', `npx skills add /path/to/${brand.name}`)
|
|
90
|
-
.replaceAll('plugin marketplace add addyosmani/agent-skills', `plugin marketplace add /path/to/${brand.name}`)
|
|
91
|
-
.replaceAll('~/.gemini/config/plugins/agent-skills/', `~/.gemini/config/plugins/${brand.name}/`)
|
|
92
|
-
.replaceAll('.cursor/rules/agent-skills.mdc', `.cursor/rules/${brand.name}.mdc`)
|
|
93
|
-
.replace(/\[[^\]]+\]\(https:\/\/github\.com\/addyosmani\/agent-skills\/issues\/(\d+)\)/g,
|
|
94
|
-
(_, issue) => `[upstream agent-skills #${issue}](https://github.com/addyosmani/agent-skills/issues/${issue})`);
|
|
95
|
-
}
|
|
96
|
-
const name = head.match(/^name:\s*([^\s]+)\s*$/m)?.[1];
|
|
97
|
-
const brandedHead = name && inventory.skills.includes(name) ? head.replace(/^name:.*$/m, `name: ${skillId(name)}`) : head;
|
|
98
|
-
return brandedHead + rewriteReferences(result, false, inventory, !relative.startsWith('scripts/'));
|
|
99
|
-
}
|
|
100
|
-
const skipDirectories = new Set(['.git', 'node_modules', 'rebrand', 'dist', 'tests', 'bin']);
|
|
101
|
-
const skipFiles = new Set(['LICENSE', 'NOTICE.md', 'CHANGELOG.md', 'package.json', 'README.md', 'evals/README.md', 'evals/skill-impact.md', 'docs/comparison.md', 'scripts/validate-brand.cjs', 'scripts/lib/skill-lint.js', 'scripts/lib/skill-lint-test.js']);
|
|
102
|
-
function walk(directory, prefix = '') {
|
|
103
|
-
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
|
|
104
|
-
const relative = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
105
|
-
if (entry.isDirectory()) {
|
|
106
|
-
if (!skipDirectories.has(entry.name) && !relative.startsWith('evals/results')) walk(path.join(directory, entry.name), relative);
|
|
107
|
-
} else if (entry.isFile() && !skipFiles.has(relative) && /\.(?:md|js|cjs|sh|toml|yml|json|patch|diff)$/.test(entry.name)) {
|
|
108
|
-
const original = fs.readFileSync(path.join(root, relative), 'utf8');
|
|
109
|
-
update(relative, transform(original, relative));
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
walk(root);
|
|
114
|
-
for (const patch of require('./fork-patches.json')) {
|
|
115
|
-
if (path.isAbsolute(patch.file) || patch.file.split(/[\\/]/).includes('..')) throw new Error('Patch must stay inside this Agent repository.');
|
|
116
|
-
const original = (changes.get(patch.file) ?? fs.readFileSync(path.join(root, patch.file), 'utf8')).replace(/\r\n/g, '\n');
|
|
117
|
-
if (original.includes(patch.to)) continue;
|
|
118
|
-
if (!original.includes(patch.from)) throw new Error(`Upstream changed ${patch.file}; review the fork patch before proceeding.`);
|
|
119
|
-
update(patch.file, original.replace(patch.from, patch.to));
|
|
120
|
-
}
|
|
121
|
-
const comparisonPath = 'docs/comparison.md';
|
|
122
|
-
const comparison = fs.readFileSync(path.join(root, comparisonPath), 'utf8');
|
|
123
|
-
if (!comparison.includes('> **Upstream research:**')) {
|
|
124
|
-
const note = `> **Upstream research:** This comparison is retained from Addy Osmani's \`agent-skills\` at commit \`${brand.upstreamCommit}\`. Its experiments describe the upstream project; they are not independent evaluations of ${brand.displayName}.\n\n`;
|
|
125
|
-
update(comparisonPath, comparison.replace('# How agent-skills compares\n\n', '# How agent-skills compares\n\n' + note));
|
|
126
|
-
}
|
|
127
|
-
for (const relative of ['plugin.json', '.claude-plugin/plugin.json', '.codex-plugin/plugin.json']) {
|
|
128
|
-
const manifest = JSON.parse(fs.readFileSync(path.join(root, relative), 'utf8'));
|
|
129
|
-
manifest.name = brand.name;
|
|
130
|
-
manifest.version = brand.releaseVersion;
|
|
131
|
-
manifest.description = brand.description;
|
|
132
|
-
if (manifest.author) manifest.author = { name: brand.maintainer };
|
|
133
|
-
manifest.homepage = brand.repository;
|
|
134
|
-
manifest.repository = brand.repository;
|
|
135
|
-
if (manifest.interface) {
|
|
136
|
-
manifest.interface.displayName = brand.displayName;
|
|
137
|
-
manifest.interface.developerName = brand.maintainer;
|
|
138
|
-
manifest.interface.shortDescription = 'Engineering workflow skills';
|
|
139
|
-
manifest.interface.longDescription = `${brand.displayName} packages ${inventory.skills.length} engineering skills from Addy Osmani's Agent Skills, covering requirements, planning, implementation, testing, review, and shipping.`;
|
|
140
|
-
manifest.interface.defaultPrompt = manifest.interface.defaultPrompt.map(prompt => rewriteReferences(prompt.replaceAll('Agent Skills', brand.displayName)));
|
|
141
|
-
}
|
|
142
|
-
update(relative, JSON.stringify(manifest, null, 2) + '\n');
|
|
143
|
-
}
|
|
144
|
-
for (const relative of ['.claude-plugin/marketplace.json', '.agents/plugins/marketplace.json']) {
|
|
145
|
-
const manifest = JSON.parse(fs.readFileSync(path.join(root, relative), 'utf8'));
|
|
146
|
-
manifest.name = brand.name;
|
|
147
|
-
if (manifest.version) manifest.version = brand.releaseVersion;
|
|
148
|
-
if (manifest.description) manifest.description = brand.description;
|
|
149
|
-
if (manifest.owner) manifest.owner = { name: brand.maintainer };
|
|
150
|
-
if (manifest.interface) manifest.interface.displayName = brand.displayName;
|
|
151
|
-
for (const plugin of manifest.plugins) {
|
|
152
|
-
plugin.name = brand.name;
|
|
153
|
-
plugin.version = brand.releaseVersion;
|
|
154
|
-
plugin.description = brand.description;
|
|
155
|
-
plugin.source = relative.startsWith('.agents/') ? { source: 'local', path: './' } : './';
|
|
156
|
-
plugin.homepage = brand.repository;
|
|
157
|
-
}
|
|
158
|
-
update(relative, JSON.stringify(manifest, null, 2) + '\n');
|
|
159
|
-
}
|
|
160
|
-
function overlay(directory, prefix = '') {
|
|
161
|
-
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
|
|
162
|
-
const relative = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
163
|
-
if (relative === '.github' && !fs.existsSync(path.join(root, '.github'))) continue;
|
|
164
|
-
if (entry.isDirectory()) overlay(path.join(directory, entry.name), relative);
|
|
165
|
-
else if (entry.isFile()) update(relative, fs.readFileSync(path.join(directory, entry.name), 'utf8'));
|
|
166
|
-
else throw new Error(`Unsupported distribution overlay entry: ${relative}`);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
overlay(path.join(__dirname, 'overlay'));
|
|
170
|
-
const ignoreFile = path.join(root, '.gitignore');
|
|
171
|
-
if (fs.existsSync(ignoreFile)) {
|
|
172
|
-
const original = fs.readFileSync(ignoreFile, 'utf8');
|
|
173
|
-
const entries = new Set(original.split(/\r?\n/));
|
|
174
|
-
const missing = ['dist/', '*.tgz', `${brand.name}/`].filter(entry => !entries.has(entry));
|
|
175
|
-
if (missing.length) update('.gitignore', original.replace(/\n?$/, '\n') + missing.join('\n') + '\n');
|
|
176
|
-
}
|
|
177
|
-
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.template.json'), 'utf8'));
|
|
178
|
-
pkg.name = brand.npmName;
|
|
179
|
-
pkg.version = brand.releaseVersion;
|
|
180
|
-
pkg.repository = { type: 'git', url: brand.repository + '.git' };
|
|
181
|
-
pkg.homepage = brand.repository + '#readme';
|
|
182
|
-
pkg.i3ComposerAgent.upstreamVersion = upstream.upstreamVersion;
|
|
183
|
-
pkg.i3ComposerAgent.upstreamCommit = upstream.upstreamCommit;
|
|
184
|
-
pkg.i3ComposerAgent.upstreamRepository = brand.upstream;
|
|
185
|
-
update('package.json', JSON.stringify(pkg, null, 2) + '\n');
|
|
186
|
-
update('NOTICE.md', fs.readFileSync(path.join(__dirname, 'NOTICE.md'), 'utf8'));
|
|
187
|
-
function description(relative) {
|
|
188
|
-
const file = path.join(root, branded ? runtimePath(relative) : relative);
|
|
189
|
-
const head = fs.readFileSync(file, 'utf8').match(/^---\r?\n([\s\S]*?)\r?\n---/)?.[1] || '';
|
|
190
|
-
return (head.match(/^description:\s*(.*)$/m)?.[1] || '').replace(/^["']|["']$/g, '').replaceAll('|', '\\|');
|
|
191
|
-
}
|
|
192
|
-
const values = {
|
|
193
|
-
RELEASE_VERSION: brand.releaseVersion,
|
|
194
|
-
UPSTREAM_VERSION: upstream.upstreamVersion,
|
|
195
|
-
SKILL_COUNT: inventory.skills.length,
|
|
196
|
-
COMMAND_COUNT: inventory.commands.length,
|
|
197
|
-
PERSONA_COUNT: inventory.personas.length,
|
|
198
|
-
SKILL_TABLE: inventory.skills.map(id => `| [${skillId(id)}](skills/${skillId(id)}/SKILL.md) | ${description(`skills/${id}/SKILL.md`)} |`).join('\n'),
|
|
199
|
-
COMMAND_TABLE: inventory.commands.map(id => `| /${brand.name}:${skillId(id)} | ${description(`.claude/commands/${id}.md`)} |`).join('\n'),
|
|
200
|
-
};
|
|
201
|
-
for (const [relative, template] of [
|
|
202
|
-
['README.md', 'README.md'], ['docs/codex-setup.md', 'codex-setup.md'], ['docs/codebuddy-setup.md', 'codebuddy-setup.md'],
|
|
203
|
-
]) {
|
|
204
|
-
const content = fs.readFileSync(path.join(__dirname, 'templates', template), 'utf8').replace(/\{\{([A-Z_]+)\}\}/g, (_, key) => {
|
|
205
|
-
if (!(key in values)) throw new Error(`Unknown template variable: ${key}`);
|
|
206
|
-
return values[key];
|
|
207
|
-
});
|
|
208
|
-
update(relative, content);
|
|
209
|
-
}
|
|
210
|
-
if (mode === '--apply') for (const [relative, content] of changes) {
|
|
211
|
-
fs.mkdirSync(path.dirname(path.join(root, relative)), { recursive: true });
|
|
212
|
-
fs.writeFileSync(path.join(root, relative), content);
|
|
213
|
-
}
|
|
214
|
-
if (mode === '--apply') fs.chmodSync(path.join(root, 'bin/i3-composer-agent.cjs'), 0o755);
|
|
215
|
-
if (mode === '--apply') for (const [source, target] of renames) fs.renameSync(path.join(root, source), path.join(root, target));
|
|
216
|
-
console.log(JSON.stringify({ mode, changedFiles: [...changes.keys()], renamedPaths: Object.fromEntries(renames) }, null, 2));
|
|
217
|
-
if (mode === '--check' && (changes.size || renames.size)) process.exitCode = 1;
|
package/rebrand/brand.json
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "i3-composer-agent",
|
|
3
|
-
"displayName": "i3 Composer Agent",
|
|
4
|
-
"npmName": "@givolt/i3-composer-agent",
|
|
5
|
-
"maintainer": "Givolt",
|
|
6
|
-
"upstream": "https://github.com/addyosmani/agent-skills",
|
|
7
|
-
"upstreamCommit": "1401c8b8030e023baeebb31781a6653fe8e93026",
|
|
8
|
-
"description": "Production-grade engineering skills for AI coding agents covering the development lifecycle from spec to ship.",
|
|
9
|
-
"repository": "https://github.com/49780522/i3-composer-agent",
|
|
10
|
-
"sourceBranch": "agent/source",
|
|
11
|
-
"releaseBranch": "main",
|
|
12
|
-
"releaseVersion": "2.0.0"
|
|
13
|
-
}
|
package/rebrand/catalog.cjs
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const fs = require('node:fs');
|
|
4
|
-
const path = require('node:path');
|
|
5
|
-
const crypto = require('node:crypto');
|
|
6
|
-
const assert = require('node:assert/strict');
|
|
7
|
-
const { skillId, runtimePath } = require('./identifiers.cjs');
|
|
8
|
-
const runtimeRoots = ['skills', 'references', 'agents', 'commands', '.claude/commands', '.gemini/commands', 'hooks', '.claude-plugin', '.codex-plugin', '.agents/plugins'];
|
|
9
|
-
const runtimeFiles = ['plugin.json', 'LICENSE'];
|
|
10
|
-
|
|
11
|
-
function frontmatter(content) {
|
|
12
|
-
const match = content.match(/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/);
|
|
13
|
-
assert.ok(match, 'Skill must have YAML frontmatter');
|
|
14
|
-
return match[0];
|
|
15
|
-
}
|
|
16
|
-
function describe(files, read) {
|
|
17
|
-
files = files.filter(file => path.basename(file) !== '.DS_Store');
|
|
18
|
-
const select = pattern => files.filter(name => pattern.test(name)).sort();
|
|
19
|
-
const skillFiles = select(/^skills\/[^/]+\/SKILL\.md$/);
|
|
20
|
-
const skillFrontmatter = {};
|
|
21
|
-
for (const file of skillFiles) {
|
|
22
|
-
const id = file.split('/')[1];
|
|
23
|
-
const head = frontmatter(read(file));
|
|
24
|
-
const name = head.match(/^name:\s*["']?([^\s"']+)["']?\s*$/m)?.[1];
|
|
25
|
-
assert.equal(name, id, `${file}: unstable skill identifier`);
|
|
26
|
-
skillFrontmatter[id] = crypto.createHash('sha256').update(head.replace(/\r\n/g, '\n')).digest('hex');
|
|
27
|
-
}
|
|
28
|
-
return {
|
|
29
|
-
skills: skillFiles.map(file => file.split('/')[1]),
|
|
30
|
-
commands: select(/^\.claude\/commands\/[^/]+\.md$/).map(file => path.basename(file, '.md')),
|
|
31
|
-
personas: select(/^agents\/[^/]+\.md$/).map(file => path.basename(file, '.md')),
|
|
32
|
-
references: select(/^references\/[^/]+\.md$/),
|
|
33
|
-
runtimeFiles: files.filter(file => runtimeFiles.includes(file) || runtimeRoots.some(root => file.startsWith(root + '/'))).sort(),
|
|
34
|
-
skillFrontmatter,
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
function catalog(root) {
|
|
38
|
-
const files = [];
|
|
39
|
-
function walk(directory, prefix) {
|
|
40
|
-
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
|
|
41
|
-
const relative = `${prefix}/${entry.name}`;
|
|
42
|
-
if (entry.isDirectory()) walk(path.join(directory, entry.name), relative);
|
|
43
|
-
else if (entry.isFile()) files.push(relative);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
for (const name of runtimeRoots) if (fs.existsSync(path.join(root, name))) walk(path.join(root, name), name);
|
|
47
|
-
for (const name of runtimeFiles) if (fs.existsSync(path.join(root, name))) files.push(name);
|
|
48
|
-
return describe(files, file => fs.readFileSync(path.join(root, file), 'utf8'));
|
|
49
|
-
}
|
|
50
|
-
function validateCatalog(root, expected, { branded = false } = {}) {
|
|
51
|
-
const actual = catalog(root);
|
|
52
|
-
const mapped = branded ? {
|
|
53
|
-
...expected,
|
|
54
|
-
skills: expected.skills.map(skillId),
|
|
55
|
-
commands: expected.commands.map(skillId),
|
|
56
|
-
runtimeFiles: expected.runtimeFiles.map(file => runtimePath(file, false, expected)).sort(),
|
|
57
|
-
skillFrontmatter: Object.fromEntries(expected.skills.map(id => {
|
|
58
|
-
const name = skillId(id);
|
|
59
|
-
const head = frontmatter(fs.readFileSync(path.join(root, 'skills', name, 'SKILL.md'), 'utf8'));
|
|
60
|
-
const normalized = head.replace(new RegExp(`^name:.*$`, 'm'), `name: ${id}`).replace(/\r\n/g, '\n');
|
|
61
|
-
actual.skillFrontmatter[name] = crypto.createHash('sha256').update(normalized).digest('hex');
|
|
62
|
-
return [name, expected.skillFrontmatter[id]];
|
|
63
|
-
})),
|
|
64
|
-
} : expected;
|
|
65
|
-
for (const field of ['skills', 'commands', 'personas', 'references', 'runtimeFiles', 'skillFrontmatter']) {
|
|
66
|
-
assert.deepEqual(actual[field], mapped[field], `upstream preservation failed: ${field}`);
|
|
67
|
-
}
|
|
68
|
-
return actual;
|
|
69
|
-
}
|
|
70
|
-
module.exports = { runtimeRoots, runtimeFiles, frontmatter, describe, catalog, validateCatalog };
|