@givolt/i3-composer-agent 0.6.12 → 1.0.0
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 +3 -2
- package/.claude-plugin/marketplace.json +2 -1
- package/.claude-plugin/plugin.json +3 -1
- package/.codex-plugin/plugin.json +3 -1
- package/CHANGELOG.md +23 -0
- package/README.md +77 -137
- package/bin/i3-composer-agent.cjs +6 -3
- package/docs/antigravity-setup.md +1 -1
- package/docs/comparison.md +1 -1
- package/hooks/sdd-cache-post.sh +0 -0
- package/hooks/sdd-cache-pre.sh +0 -0
- package/package.json +75 -17
- package/plugin.json +4 -2
- package/rebrand/MAINTENANCE.md +92 -31
- package/rebrand/NOTICE.md +9 -0
- package/rebrand/PR-WORKFLOW.md +34 -0
- package/rebrand/UNIFICATION-SPEC.md +33 -0
- package/rebrand/VALIDATION.md +28 -0
- package/rebrand/VERSIONING.md +32 -0
- package/rebrand/apply.cjs +80 -7
- package/rebrand/brand.json +6 -2
- package/rebrand/catalog.cjs +56 -0
- package/rebrand/fork-patches.json +12 -0
- package/rebrand/overlay/.github/workflows/test-plugin-install.yml +177 -0
- package/rebrand/overlay/CHANGELOG.md +23 -0
- package/rebrand/overlay/bin/i3-composer-agent.cjs +122 -0
- package/rebrand/overlay/scripts/validate-brand.cjs +44 -0
- package/rebrand/overlay/tests/bundle.test.cjs +85 -0
- package/rebrand/package.template.json +82 -0
- package/rebrand/rebrand.sh +4 -0
- package/rebrand/record-upstream.cjs +37 -0
- package/rebrand/templates/README.md +44 -136
- package/rebrand/tests/pipeline.test.cjs +185 -0
- package/rebrand/upstream.json +171 -0
- package/scripts/validate-brand.cjs +11 -3
- package/skills/idea-refine/scripts/idea-refine.sh +0 -0
- package/tests/bundle.test.cjs +11 -5
|
@@ -1,178 +1,86 @@
|
|
|
1
|
-
# i3 Composer Agent
|
|
1
|
+
# i3 Composer Agent v{{RELEASE_VERSION}}
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Based on agent-skills v{{UPSTREAM_VERSION}}**
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
for AI coding agents. This is the engineering-skill product in the i3 Composer
|
|
7
|
-
family; the GSD-derived workflow product is maintained separately.
|
|
5
|
+
**Intelligence. Integration. Innovation.**
|
|
8
6
|
|
|
7
|
+
Engineering skills, lifecycle commands, and specialist personas for AI coding agents.
|
|
9
8
|
Based on [Agent Skills](https://github.com/addyosmani/agent-skills) by Addy Osmani
|
|
10
|
-
(MIT). See [NOTICE.md](NOTICE.md) for attribution
|
|
9
|
+
(MIT). See [NOTICE.md](NOTICE.md) for attribution.
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
The npm package is `@givolt/i3-composer-agent`; the plugin and marketplace ID is
|
|
12
|
+
`i3-composer-agent`. Skill IDs retain their upstream names.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
`i3-composer-agent`. Skill IDs and workflow behavior retain their upstream names.
|
|
14
|
+
## Prepare the complete plugin
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
Run in the project where you want to prepare the plugin:
|
|
18
17
|
|
|
19
18
|
```bash
|
|
20
19
|
npx @givolt/i3-composer-agent --codebuddy
|
|
21
|
-
#
|
|
20
|
+
# Other hosts:
|
|
22
21
|
npx @givolt/i3-composer-agent --codex
|
|
23
22
|
npx @givolt/i3-composer-agent --claude
|
|
24
23
|
```
|
|
25
24
|
|
|
26
|
-
The
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
The command prepares a persistent `./i3-composer-agent/` directory containing
|
|
26
|
+
{{SKILL_COUNT}} skills, {{COMMAND_COUNT}} commands, {{PERSONA_COUNT}} personas,
|
|
27
|
+
and shared references. It prints native registration commands; run those in
|
|
28
|
+
the selected host to enable the plugin. Preparing files does not select a host
|
|
29
|
+
installation scope. See [CodeBuddy setup](docs/codebuddy-setup.md) and
|
|
30
|
+
[Codex setup](docs/codex-setup.md).
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
CodeBuddy / Claude Code:
|
|
31
33
|
|
|
32
34
|
```text
|
|
33
35
|
/plugin marketplace add ./i3-composer-agent
|
|
34
36
|
/plugin install i3-composer-agent@i3-composer-agent
|
|
35
37
|
```
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
working directory. See [CodeBuddy setup](docs/codebuddy-setup.md).
|
|
39
|
-
|
|
40
|
-
### Codex
|
|
39
|
+
Codex:
|
|
41
40
|
|
|
42
41
|
```bash
|
|
43
42
|
codex plugin marketplace add ./i3-composer-agent
|
|
44
43
|
codex plugin add i3-composer-agent@i3-composer-agent
|
|
45
44
|
```
|
|
46
45
|
|
|
47
|
-
Start a new
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
See [Codex setup](docs/codex-setup.md).
|
|
51
|
-
|
|
52
|
-
### Bundle options
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
npx @givolt/i3-composer-agent --extract --dir /path/to/i3-composer-agent
|
|
56
|
-
npx @givolt/i3-composer-agent --codebuddy --dir /path/to/plugin --dry-run
|
|
57
|
-
npx @givolt/i3-composer-agent --codebuddy --dir /path/to/plugin --force
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
An existing directory is refused unless `--force` targets an i3 Composer Agent
|
|
61
|
-
bundle. Replacement keeps the previous directory as a backup. No repository
|
|
62
|
-
AGENTS.md or CLAUDE.md is copied into the target project.
|
|
46
|
+
Start a new session after enabling the plugin. Codex uses the existing Skill
|
|
47
|
+
names, such as `$spec-driven-development`; lifecycle slash-command adaptation
|
|
48
|
+
is maintained separately.
|
|
63
49
|
|
|
64
50
|
## Commands
|
|
65
51
|
|
|
66
|
-
Hosts supporting Claude-compatible plugin commands load these workflows
|
|
67
|
-
Use the namespaced form, for example `/i3-composer-agent:spec`.
|
|
52
|
+
Hosts supporting Claude-compatible plugin commands load these workflows:
|
|
68
53
|
|
|
69
|
-
| Command |
|
|
54
|
+
| Command | Description |
|
|
70
55
|
| --- | --- |
|
|
71
|
-
|
|
72
|
-
| `/i3-composer-agent:plan` | Write ordered, verifiable tasks |
|
|
73
|
-
| `/i3-composer-agent:build` | Implement the next task with verification |
|
|
74
|
-
| `/i3-composer-agent:build auto` | Execute the approved plan with per-task verification |
|
|
75
|
-
| `/i3-composer-agent:test` | Test-first development and regression checks |
|
|
76
|
-
| `/i3-composer-agent:constraints` | Establish a written quality bar |
|
|
77
|
-
| `/i3-composer-agent:review` | Review code quality and correctness |
|
|
78
|
-
| `/i3-composer-agent:webperf` | Audit web performance |
|
|
79
|
-
| `/i3-composer-agent:code-simplify` | Simplify code without changing behavior |
|
|
80
|
-
| `/i3-composer-agent:ship` | Review launch readiness and rollback |
|
|
81
|
-
|
|
82
|
-
## All 25 Skills
|
|
83
|
-
|
|
84
|
-
The commands above are entry points. The pack includes 25 skills total — 24 lifecycle skills plus the `using-agent-skills` meta-skill. Each skill is a structured workflow with steps, verification gates, and anti-rationalization tables. You can also reference any skill directly.
|
|
85
|
-
|
|
86
|
-
### Meta - Discover which skill applies
|
|
87
|
-
|
|
88
|
-
| Skill | What It Does | Use When |
|
|
89
|
-
|-------|-------------|----------|
|
|
90
|
-
| [using-agent-skills](skills/using-agent-skills/SKILL.md) | Maps incoming work to the right skill workflow and defines shared operating rules | Starting a session or deciding which skill applies |
|
|
91
|
-
|
|
92
|
-
### Define - Clarify what to build
|
|
93
|
-
|
|
94
|
-
| Skill | What It Does | Use When |
|
|
95
|
-
|-------|-------------|----------|
|
|
96
|
-
| [interview-me](skills/interview-me/SKILL.md) | One-question-at-a-time interview that extracts what the user actually wants instead of what they think they should want, until ~95% confidence | The ask is underspecified, or the user invokes "interview me" / "grill me" |
|
|
97
|
-
| [idea-refine](skills/idea-refine/SKILL.md) | Structured divergent/convergent thinking to turn vague ideas into concrete proposals | You have a rough concept that needs exploration |
|
|
98
|
-
| [spec-driven-development](skills/spec-driven-development/SKILL.md) | Write a PRD covering objectives, commands, structure, code style, testing, and boundaries before any code | Starting a new project, feature, or significant change |
|
|
99
|
-
| [constraint-driven-development](skills/constraint-driven-development/SKILL.md) | Interviews you for a quality bar with sane default thresholds, writes CONSTRAINTS.md, places each check by cost, and catches agents silencing checks or skipping tests to get green | No standards are written down, or an agent is producing more than anyone reads |
|
|
56
|
+
{{COMMAND_TABLE}}
|
|
100
57
|
|
|
101
|
-
|
|
58
|
+
`/i3-composer-agent:build auto` runs the existing approved-plan workflow.
|
|
102
59
|
|
|
103
|
-
|
|
104
|
-
|-------|-------------|----------|
|
|
105
|
-
| [planning-and-task-breakdown](skills/planning-and-task-breakdown/SKILL.md) | Decompose specs into small, verifiable tasks with acceptance criteria and dependency ordering | You have a spec and need implementable units |
|
|
60
|
+
## Skills
|
|
106
61
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|-------|-------------|----------|
|
|
111
|
-
| [incremental-implementation](skills/incremental-implementation/SKILL.md) | Thin vertical slices - implement, test, verify, commit. Feature flags, safe defaults, rollback-friendly changes | Any change touching more than one file |
|
|
112
|
-
| [test-driven-development](skills/test-driven-development/SKILL.md) | Red-Green-Refactor, test pyramid (80/15/5), test sizes, DAMP over DRY, Beyonce Rule, browser testing | Implementing logic, fixing bugs, or changing behavior |
|
|
113
|
-
| [context-engineering](skills/context-engineering/SKILL.md) | Feed agents the right information at the right time - rules files, context packing, MCP integrations | Starting a session, switching tasks, or when output quality drops |
|
|
114
|
-
| [source-driven-development](skills/source-driven-development/SKILL.md) | Ground every framework decision in official documentation - verify, cite sources, flag what's unverified | You want authoritative, source-cited code for any framework or library |
|
|
115
|
-
| [doubt-driven-development](skills/doubt-driven-development/SKILL.md) | Adversarial fresh-context review of every non-trivial decision in-flight - CLAIM → EXTRACT → DOUBT → RECONCILE → STOP, with optional user-authorized cross-model escalation | Stakes are high (production, security, irreversible), working in unfamiliar code, or a confident output is cheaper to verify now than to debug later |
|
|
116
|
-
| [frontend-ui-engineering](skills/frontend-ui-engineering/SKILL.md) | Component architecture, design systems, state management, responsive design, WCAG 2.1 AA accessibility | Building or modifying user-facing interfaces |
|
|
117
|
-
| [api-and-interface-design](skills/api-and-interface-design/SKILL.md) | Contract-first design, Hyrum's Law, One-Version Rule, error semantics, boundary validation | Designing APIs, module boundaries, or public interfaces |
|
|
118
|
-
|
|
119
|
-
### Verify - Prove it works
|
|
120
|
-
|
|
121
|
-
| Skill | What It Does | Use When |
|
|
122
|
-
|-------|-------------|----------|
|
|
123
|
-
| [browser-testing-with-devtools](skills/browser-testing-with-devtools/SKILL.md) | Chrome DevTools MCP for live runtime data - DOM inspection, console logs, network traces, performance profiling | Building or debugging anything that runs in a browser |
|
|
124
|
-
| [debugging-and-error-recovery](skills/debugging-and-error-recovery/SKILL.md) | Five-step triage: reproduce, localize, reduce, fix, guard. Stop-the-line rule, safe fallbacks | Tests fail, builds break, or behavior is unexpected |
|
|
125
|
-
|
|
126
|
-
### Review - Quality gates before merge
|
|
127
|
-
|
|
128
|
-
| Skill | What It Does | Use When |
|
|
129
|
-
|-------|-------------|----------|
|
|
130
|
-
| [code-review-and-quality](skills/code-review-and-quality/SKILL.md) | Five-axis review, change sizing (~100 lines), severity labels (Nit/Optional/FYI), review speed norms, splitting strategies | Before merging any change |
|
|
131
|
-
| [code-simplification](skills/code-simplification/SKILL.md) | Chesterton's Fence, Rule of 500, reduce complexity while preserving exact behavior | Code works but is harder to read or maintain than it should be |
|
|
132
|
-
| [security-and-hardening](skills/security-and-hardening/SKILL.md) | OWASP Top 10 prevention, auth patterns, secrets management, dependency auditing, three-tier boundary system | Handling user input, auth, data storage, or external integrations |
|
|
133
|
-
| [performance-optimization](skills/performance-optimization/SKILL.md) | Measure-first approach - Core Web Vitals targets, profiling workflows, bundle analysis, anti-pattern detection | Performance requirements exist or you suspect regressions |
|
|
134
|
-
|
|
135
|
-
### Ship - Deploy with confidence
|
|
136
|
-
|
|
137
|
-
| Skill | What It Does | Use When |
|
|
138
|
-
|-------|-------------|----------|
|
|
139
|
-
| [git-workflow-and-versioning](skills/git-workflow-and-versioning/SKILL.md) | Trunk-based development, atomic commits, change sizing (~100 lines), the commit-as-save-point pattern | Making any code change (always) |
|
|
140
|
-
| [ci-cd-and-automation](skills/ci-cd-and-automation/SKILL.md) | Shift Left, Faster is Safer, feature flags, quality gate pipelines, failure feedback loops | Setting up or modifying build and deploy pipelines |
|
|
141
|
-
| [deprecation-and-migration](skills/deprecation-and-migration/SKILL.md) | Code-as-liability mindset, compulsory vs advisory deprecation, migration patterns, zombie code removal | Removing old systems, migrating users, or sunsetting features |
|
|
142
|
-
| [documentation-and-adrs](skills/documentation-and-adrs/SKILL.md) | Architecture Decision Records, API docs, inline documentation standards - document the *why* | Making architectural decisions, changing APIs, or shipping features |
|
|
143
|
-
| [observability-and-instrumentation](skills/observability-and-instrumentation/SKILL.md) | Structured logging, RED metrics, OpenTelemetry tracing, symptom-based alerting - instrument as you build | Adding telemetry, or shipping anything that runs in production |
|
|
144
|
-
| [shipping-and-launch](skills/shipping-and-launch/SKILL.md) | Pre-launch checklists, feature flag lifecycle, staged rollouts, rollback procedures, monitoring setup | Preparing to deploy to production |
|
|
145
|
-
|
|
146
|
-
---
|
|
147
|
-
|
|
148
|
-
## Personas and shared references
|
|
149
|
-
|
|
150
|
-
The four original personas remain in [agents/](agents/): code reviewer, security
|
|
151
|
-
auditor, test engineer, and web performance auditor. Shared checklists remain in [references/](references/).
|
|
152
|
-
Their relative layout is preserved across npm packaging and bundle extraction.
|
|
153
|
-
|
|
154
|
-
## Other hosts
|
|
155
|
-
|
|
156
|
-
The existing [host guides](docs/other-hosts.md) describe additional integrations.
|
|
157
|
-
Prepare the complete local bundle first and use its path in host-specific setup.
|
|
158
|
-
Per-skill installation is separate and may omit the shared references, command
|
|
159
|
-
wrappers, and personas.
|
|
62
|
+
| Skill | Description |
|
|
63
|
+
| --- | --- |
|
|
64
|
+
{{SKILL_TABLE}}
|
|
160
65
|
|
|
161
|
-
##
|
|
66
|
+
## Bundle options
|
|
162
67
|
|
|
163
68
|
```bash
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
node scripts/run-evals.js --min-rank1 95
|
|
168
|
-
npm pack --pack-destination /path/to/release-directory
|
|
69
|
+
npx @givolt/i3-composer-agent --extract --dir /path/to/plugin
|
|
70
|
+
npx @givolt/i3-composer-agent --codebuddy --dir /path/to/plugin --dry-run
|
|
71
|
+
npx @givolt/i3-composer-agent --codebuddy --dir /path/to/plugin --force
|
|
169
72
|
```
|
|
170
73
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
74
|
+
Replacement preserves the previous i3 bundle as a backup. Repository-scoped
|
|
75
|
+
AGENTS.md and CLAUDE.md are not copied into business projects.
|
|
76
|
+
|
|
77
|
+
## Maintaining this fork
|
|
175
78
|
|
|
176
|
-
|
|
79
|
+
This repository is independent of the GSD-based i3 Composer Work repository.
|
|
80
|
+
`agent/source` retains upstream source and the `rebrand/` rules; `main` contains
|
|
81
|
+
the validated branded distribution. Create release candidates from the source
|
|
82
|
+
branch, replay branding, validate, then update the release branch.
|
|
177
83
|
|
|
178
|
-
|
|
84
|
+
See [maintenance](rebrand/MAINTENANCE.md), [source PR workflow](rebrand/PR-WORKFLOW.md),
|
|
85
|
+
[versioning](rebrand/VERSIONING.md), [changelog](CHANGELOG.md),
|
|
86
|
+
and [validation contract](rebrand/VALIDATION.md).
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const test = require('node:test');
|
|
4
|
+
const assert = require('node:assert/strict');
|
|
5
|
+
const fs = require('node:fs');
|
|
6
|
+
const os = require('node:os');
|
|
7
|
+
const path = require('node:path');
|
|
8
|
+
const { spawnSync } = require('node:child_process');
|
|
9
|
+
const root = path.resolve(__dirname, '../..');
|
|
10
|
+
const baselineVersion = require('../upstream.json').upstreamVersion;
|
|
11
|
+
|
|
12
|
+
function run(directory, executable, args) {
|
|
13
|
+
return spawnSync(executable, args, { cwd: directory, encoding: 'utf8' });
|
|
14
|
+
}
|
|
15
|
+
function git(directory, args) {
|
|
16
|
+
const result = run(directory, 'git', args);
|
|
17
|
+
assert.equal(result.status, 0, result.stderr);
|
|
18
|
+
return result.stdout.trim();
|
|
19
|
+
}
|
|
20
|
+
function node(directory, file, args = []) { return run(directory, process.execPath, [file, ...args]); }
|
|
21
|
+
function fixture(t, branch = 'release/test-candidate') {
|
|
22
|
+
const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'i3-agent-replay-'));
|
|
23
|
+
t.after(() => fs.rmSync(directory, { recursive: true, force: true }));
|
|
24
|
+
for (const name of ['skills', 'references', 'agents', 'commands', '.claude', '.gemini', '.claude-plugin', '.codex-plugin', '.agents', 'hooks', 'docs', 'scripts', 'evals', 'rebrand', 'LICENSE', 'plugin.json', 'README.md']) {
|
|
25
|
+
fs.cpSync(path.join(root, name), path.join(directory, name), { recursive: true, filter: file => !file.includes(`${path.sep}results${path.sep}`) });
|
|
26
|
+
}
|
|
27
|
+
// Model an upstream source checkout, including when this suite runs in a packed branded bundle.
|
|
28
|
+
for (const name of ['plugin.json', '.claude-plugin/plugin.json', '.codex-plugin/plugin.json']) {
|
|
29
|
+
const file = path.join(directory, name);
|
|
30
|
+
const data = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
31
|
+
data.name = 'agent-skills';
|
|
32
|
+
data.version = baselineVersion;
|
|
33
|
+
fs.writeFileSync(file, JSON.stringify(data, null, 2) + '\n');
|
|
34
|
+
}
|
|
35
|
+
git(directory, ['init', '--initial-branch', branch]);
|
|
36
|
+
git(directory, ['config', 'user.name', 'Pipeline Test']);
|
|
37
|
+
git(directory, ['config', 'user.email', 'pipeline@example.test']);
|
|
38
|
+
git(directory, ['add', '.']);
|
|
39
|
+
git(directory, ['commit', '-m', 'upstream fixture']);
|
|
40
|
+
return directory;
|
|
41
|
+
}
|
|
42
|
+
function record(directory) {
|
|
43
|
+
const result = node(directory, 'rebrand/record-upstream.cjs', ['HEAD']);
|
|
44
|
+
assert.equal(result.status, 0, result.stderr);
|
|
45
|
+
}
|
|
46
|
+
function apply(directory) {
|
|
47
|
+
const result = node(directory, 'rebrand/apply.cjs', ['--apply']);
|
|
48
|
+
assert.equal(result.status, 0, result.stderr);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
test('a source checkout generates a complete, repeatable branded distribution', t => {
|
|
52
|
+
const directory = fixture(t);
|
|
53
|
+
record(directory);
|
|
54
|
+
apply(directory);
|
|
55
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(directory, 'package.json'), 'utf8'));
|
|
56
|
+
assert.equal(pkg.name, '@givolt/i3-composer-agent');
|
|
57
|
+
const brand = JSON.parse(fs.readFileSync(path.join(directory, 'rebrand/brand.json'), 'utf8'));
|
|
58
|
+
assert.equal(pkg.version, brand.releaseVersion);
|
|
59
|
+
assert.equal(fs.existsSync(path.join(directory, 'bin/i3-composer-agent.cjs')), true);
|
|
60
|
+
assert.equal(node(directory, 'scripts/validate-brand.cjs').status, 0);
|
|
61
|
+
const check = node(directory, 'rebrand/apply.cjs', ['--check']);
|
|
62
|
+
assert.equal(check.status, 0, check.stdout + check.stderr);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test('brand fixes advance independently while preserving upstream provenance', t => {
|
|
66
|
+
const directory = fixture(t);
|
|
67
|
+
record(directory);
|
|
68
|
+
const upstreamFile = path.join(directory, 'rebrand/upstream.json');
|
|
69
|
+
const originalUpstream = fs.readFileSync(upstreamFile, 'utf8');
|
|
70
|
+
const upstream = JSON.parse(originalUpstream);
|
|
71
|
+
const brandFile = path.join(directory, 'rebrand/brand.json');
|
|
72
|
+
const brand = JSON.parse(fs.readFileSync(brandFile, 'utf8'));
|
|
73
|
+
const releaseVersion = `${Number(upstream.upstreamVersion.split('.')[0]) + 1}.0.1`;
|
|
74
|
+
brand.releaseVersion = releaseVersion;
|
|
75
|
+
fs.writeFileSync(brandFile, JSON.stringify(brand, null, 2) + '\n');
|
|
76
|
+
apply(directory);
|
|
77
|
+
const packageFile = path.join(directory, 'package.json');
|
|
78
|
+
const originalPackage = fs.readFileSync(packageFile, 'utf8');
|
|
79
|
+
const pkg = JSON.parse(originalPackage);
|
|
80
|
+
assert.equal(pkg.version, releaseVersion);
|
|
81
|
+
assert.equal(pkg.i3ComposerAgent.upstreamVersion, upstream.upstreamVersion);
|
|
82
|
+
assert.equal(pkg.i3ComposerAgent.upstreamCommit, upstream.upstreamCommit);
|
|
83
|
+
assert.equal(fs.readFileSync(upstreamFile, 'utf8'), originalUpstream);
|
|
84
|
+
const releaseLabel = `i3 Composer Agent v${releaseVersion}`;
|
|
85
|
+
const upstreamLabel = `Based on agent-skills v${upstream.upstreamVersion}`;
|
|
86
|
+
for (const output of [fs.readFileSync(path.join(directory, 'README.md'), 'utf8'), node(directory, 'bin/i3-composer-agent.cjs', ['--help']).stdout]) {
|
|
87
|
+
assert.ok(output.includes(releaseLabel), output);
|
|
88
|
+
assert.ok(output.includes(upstreamLabel), output);
|
|
89
|
+
}
|
|
90
|
+
assert.equal(node(directory, 'bin/i3-composer-agent.cjs', ['--version']).stdout.trim(), releaseVersion);
|
|
91
|
+
const dryRun = node(directory, 'bin/i3-composer-agent.cjs', ['--extract', '--dry-run', '--dir', directory + '-prepared']);
|
|
92
|
+
assert.equal(dryRun.status, 0, dryRun.stderr);
|
|
93
|
+
assert.equal(JSON.parse(dryRun.stdout).upstreamVersion, upstream.upstreamVersion);
|
|
94
|
+
assert.equal(node(directory, 'scripts/validate-brand.cjs').status, 0);
|
|
95
|
+
pkg.i3ComposerAgent.upstreamVersion = releaseVersion;
|
|
96
|
+
fs.writeFileSync(packageFile, JSON.stringify(pkg));
|
|
97
|
+
assert.notEqual(node(directory, 'scripts/validate-brand.cjs').status, 0);
|
|
98
|
+
fs.writeFileSync(packageFile, originalPackage);
|
|
99
|
+
assert.equal(node(directory, 'rebrand/apply.cjs', ['--check']).status, 0);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test('writing a brand transform on the protected source branch changes nothing', t => {
|
|
103
|
+
const directory = fixture(t, 'agent/source');
|
|
104
|
+
const before = fs.readFileSync(path.join(directory, 'plugin.json'));
|
|
105
|
+
const result = node(directory, 'rebrand/apply.cjs', ['--apply']);
|
|
106
|
+
assert.notEqual(result.status, 0);
|
|
107
|
+
assert.match(result.stderr, /source branch/i);
|
|
108
|
+
assert.deepEqual(fs.readFileSync(path.join(directory, 'plugin.json')), before);
|
|
109
|
+
assert.equal(fs.existsSync(path.join(directory, 'package.json')), false);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test('a reviewed upstream catalog can grow without losing its new skill or command', t => {
|
|
113
|
+
const directory = fixture(t);
|
|
114
|
+
const skill = path.join(directory, 'skills/upstream-new-skill');
|
|
115
|
+
fs.mkdirSync(skill);
|
|
116
|
+
fs.writeFileSync(path.join(skill, 'SKILL.md'), '---\nname: upstream-new-skill\ndescription: New upstream capability.\n---\n# Upstream capability\n');
|
|
117
|
+
fs.writeFileSync(path.join(directory, '.claude/commands/upstream-new-command.md'), '---\ndescription: Invoke the new upstream capability.\n---\nUse agent-skills:upstream-new-skill.\n');
|
|
118
|
+
git(directory, ['add', 'skills', '.claude/commands']);
|
|
119
|
+
git(directory, ['commit', '-m', 'new upstream capability']);
|
|
120
|
+
record(directory);
|
|
121
|
+
apply(directory);
|
|
122
|
+
const result = node(directory, 'scripts/validate-brand.cjs');
|
|
123
|
+
assert.equal(result.status, 0, result.stderr);
|
|
124
|
+
const description = JSON.parse(fs.readFileSync(path.join(directory, '.codex-plugin/plugin.json'), 'utf8')).interface.longDescription;
|
|
125
|
+
assert.match(description, /26 engineering skills/);
|
|
126
|
+
const readme = fs.readFileSync(path.join(directory, 'README.md'), 'utf8');
|
|
127
|
+
assert.match(readme, /upstream-new-skill/);
|
|
128
|
+
assert.match(readme, /upstream-new-command/);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test('missing files and altered skill identifiers fail preservation validation', t => {
|
|
132
|
+
const directory = fixture(t);
|
|
133
|
+
record(directory);
|
|
134
|
+
apply(directory);
|
|
135
|
+
const file = path.join(directory, 'skills/using-agent-skills/SKILL.md');
|
|
136
|
+
const original = fs.readFileSync(file, 'utf8');
|
|
137
|
+
fs.writeFileSync(file, original.replace('name: using-agent-skills', 'name: renamed-meta-skill'));
|
|
138
|
+
assert.notEqual(node(directory, 'scripts/validate-brand.cjs').status, 0);
|
|
139
|
+
fs.writeFileSync(file, original);
|
|
140
|
+
fs.rmSync(file);
|
|
141
|
+
assert.notEqual(node(directory, 'scripts/validate-brand.cjs').status, 0);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test('checkout line endings do not masquerade as an upstream skill change', t => {
|
|
145
|
+
const directory = fixture(t);
|
|
146
|
+
record(directory);
|
|
147
|
+
const file = path.join(directory, 'skills/using-agent-skills/SKILL.md');
|
|
148
|
+
fs.writeFileSync(file, fs.readFileSync(file, 'utf8').replace(/\r?\n/g, '\r\n'));
|
|
149
|
+
const script = path.join(directory, 'scripts/validate-versions.js');
|
|
150
|
+
fs.writeFileSync(script, fs.readFileSync(script, 'utf8').replace(/\r?\n/g, '\r\n'));
|
|
151
|
+
apply(directory);
|
|
152
|
+
assert.equal(node(directory, 'scripts/validate-brand.cjs').status, 0);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test('a new upstream package manifest requires an explicit distribution adaptation', t => {
|
|
156
|
+
const directory = fixture(t);
|
|
157
|
+
record(directory);
|
|
158
|
+
fs.writeFileSync(path.join(directory, 'package.json'), '{"name":"agent-skills","dependencies":{"upstream-runtime":"1.0.0"}}\n');
|
|
159
|
+
const before = fs.readFileSync(path.join(directory, 'plugin.json'));
|
|
160
|
+
const result = node(directory, 'rebrand/apply.cjs', ['--apply']);
|
|
161
|
+
assert.notEqual(result.status, 0);
|
|
162
|
+
assert.match(result.stderr, /package\.json/);
|
|
163
|
+
assert.deepEqual(fs.readFileSync(path.join(directory, 'plugin.json')), before);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
test('a distribution without repository CI files remains unchanged by a replay check', t => {
|
|
167
|
+
const directory = fixture(t);
|
|
168
|
+
record(directory);
|
|
169
|
+
apply(directory);
|
|
170
|
+
fs.rmSync(path.join(directory, '.github'), { recursive: true, force: true });
|
|
171
|
+
const result = node(directory, 'rebrand/apply.cjs', ['--check']);
|
|
172
|
+
assert.equal(result.status, 0, result.stdout + result.stderr);
|
|
173
|
+
assert.equal(fs.existsSync(path.join(directory, '.github')), false);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
test('Finder metadata does not masquerade as an upstream runtime file', t => {
|
|
177
|
+
const directory = fixture(t);
|
|
178
|
+
record(directory);
|
|
179
|
+
fs.writeFileSync(path.join(directory, 'skills/.DS_Store'), 'Finder metadata');
|
|
180
|
+
fs.writeFileSync(path.join(directory, 'skills/spec-driven-development/.DS_Store'), 'Finder metadata');
|
|
181
|
+
apply(directory);
|
|
182
|
+
assert.equal(node(directory, 'scripts/validate-brand.cjs').status, 0);
|
|
183
|
+
const result = node(directory, 'rebrand/apply.cjs', ['--check']);
|
|
184
|
+
assert.equal(result.status, 0, result.stdout + result.stderr);
|
|
185
|
+
});
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
{
|
|
2
|
+
"upstreamCommit": "1401c8b8030e023baeebb31781a6653fe8e93026",
|
|
3
|
+
"upstreamVersion": "0.6.12",
|
|
4
|
+
"skills": [
|
|
5
|
+
"api-and-interface-design",
|
|
6
|
+
"browser-testing-with-devtools",
|
|
7
|
+
"ci-cd-and-automation",
|
|
8
|
+
"code-review-and-quality",
|
|
9
|
+
"code-simplification",
|
|
10
|
+
"constraint-driven-development",
|
|
11
|
+
"context-engineering",
|
|
12
|
+
"debugging-and-error-recovery",
|
|
13
|
+
"deprecation-and-migration",
|
|
14
|
+
"documentation-and-adrs",
|
|
15
|
+
"doubt-driven-development",
|
|
16
|
+
"frontend-ui-engineering",
|
|
17
|
+
"git-workflow-and-versioning",
|
|
18
|
+
"idea-refine",
|
|
19
|
+
"incremental-implementation",
|
|
20
|
+
"interview-me",
|
|
21
|
+
"observability-and-instrumentation",
|
|
22
|
+
"performance-optimization",
|
|
23
|
+
"planning-and-task-breakdown",
|
|
24
|
+
"security-and-hardening",
|
|
25
|
+
"shipping-and-launch",
|
|
26
|
+
"source-driven-development",
|
|
27
|
+
"spec-driven-development",
|
|
28
|
+
"test-driven-development",
|
|
29
|
+
"using-agent-skills"
|
|
30
|
+
],
|
|
31
|
+
"commands": [
|
|
32
|
+
"build",
|
|
33
|
+
"code-simplify",
|
|
34
|
+
"constraints",
|
|
35
|
+
"plan",
|
|
36
|
+
"review",
|
|
37
|
+
"ship",
|
|
38
|
+
"spec",
|
|
39
|
+
"test",
|
|
40
|
+
"webperf"
|
|
41
|
+
],
|
|
42
|
+
"personas": [
|
|
43
|
+
"code-reviewer",
|
|
44
|
+
"security-auditor",
|
|
45
|
+
"test-engineer",
|
|
46
|
+
"web-performance-auditor"
|
|
47
|
+
],
|
|
48
|
+
"references": [
|
|
49
|
+
"references/accessibility-checklist.md",
|
|
50
|
+
"references/definition-of-done.md",
|
|
51
|
+
"references/observability-checklist.md",
|
|
52
|
+
"references/orchestration-patterns.md",
|
|
53
|
+
"references/performance-checklist.md",
|
|
54
|
+
"references/security-checklist.md",
|
|
55
|
+
"references/testing-patterns.md"
|
|
56
|
+
],
|
|
57
|
+
"runtimeFiles": [
|
|
58
|
+
".agents/plugins/marketplace.json",
|
|
59
|
+
".claude-plugin/marketplace.json",
|
|
60
|
+
".claude-plugin/plugin.json",
|
|
61
|
+
".claude/commands/build.md",
|
|
62
|
+
".claude/commands/code-simplify.md",
|
|
63
|
+
".claude/commands/constraints.md",
|
|
64
|
+
".claude/commands/plan.md",
|
|
65
|
+
".claude/commands/review.md",
|
|
66
|
+
".claude/commands/ship.md",
|
|
67
|
+
".claude/commands/spec.md",
|
|
68
|
+
".claude/commands/test.md",
|
|
69
|
+
".claude/commands/webperf.md",
|
|
70
|
+
".codex-plugin/plugin.json",
|
|
71
|
+
".gemini/commands/build.toml",
|
|
72
|
+
".gemini/commands/code-simplify.toml",
|
|
73
|
+
".gemini/commands/constraints.toml",
|
|
74
|
+
".gemini/commands/planning.toml",
|
|
75
|
+
".gemini/commands/review.toml",
|
|
76
|
+
".gemini/commands/ship.toml",
|
|
77
|
+
".gemini/commands/spec.toml",
|
|
78
|
+
".gemini/commands/test.toml",
|
|
79
|
+
".gemini/commands/webperf.toml",
|
|
80
|
+
"LICENSE",
|
|
81
|
+
"agents/code-reviewer.md",
|
|
82
|
+
"agents/security-auditor.md",
|
|
83
|
+
"agents/test-engineer.md",
|
|
84
|
+
"agents/web-performance-auditor.md",
|
|
85
|
+
"commands/build.toml",
|
|
86
|
+
"commands/code-simplify.toml",
|
|
87
|
+
"commands/constraints.toml",
|
|
88
|
+
"commands/planning.toml",
|
|
89
|
+
"commands/review.toml",
|
|
90
|
+
"commands/ship.toml",
|
|
91
|
+
"commands/spec.toml",
|
|
92
|
+
"commands/test.toml",
|
|
93
|
+
"commands/webperf.toml",
|
|
94
|
+
"hooks/SDD-CACHE.md",
|
|
95
|
+
"hooks/SIMPLIFY-IGNORE.md",
|
|
96
|
+
"hooks/sdd-cache-post.sh",
|
|
97
|
+
"hooks/sdd-cache-pre.sh",
|
|
98
|
+
"hooks/sdd-cache-test.sh",
|
|
99
|
+
"hooks/session-start-test.sh",
|
|
100
|
+
"hooks/session-start.sh",
|
|
101
|
+
"hooks/simplify-ignore-test.sh",
|
|
102
|
+
"hooks/simplify-ignore.sh",
|
|
103
|
+
"plugin.json",
|
|
104
|
+
"references/accessibility-checklist.md",
|
|
105
|
+
"references/definition-of-done.md",
|
|
106
|
+
"references/observability-checklist.md",
|
|
107
|
+
"references/orchestration-patterns.md",
|
|
108
|
+
"references/performance-checklist.md",
|
|
109
|
+
"references/security-checklist.md",
|
|
110
|
+
"references/testing-patterns.md",
|
|
111
|
+
"skills/api-and-interface-design/SKILL.md",
|
|
112
|
+
"skills/browser-testing-with-devtools/SKILL.md",
|
|
113
|
+
"skills/ci-cd-and-automation/SKILL.md",
|
|
114
|
+
"skills/code-review-and-quality/SKILL.md",
|
|
115
|
+
"skills/code-simplification/SKILL.md",
|
|
116
|
+
"skills/constraint-driven-development/SKILL.md",
|
|
117
|
+
"skills/constraint-driven-development/references/floor-guard.md",
|
|
118
|
+
"skills/context-engineering/SKILL.md",
|
|
119
|
+
"skills/debugging-and-error-recovery/SKILL.md",
|
|
120
|
+
"skills/deprecation-and-migration/SKILL.md",
|
|
121
|
+
"skills/documentation-and-adrs/SKILL.md",
|
|
122
|
+
"skills/doubt-driven-development/SKILL.md",
|
|
123
|
+
"skills/frontend-ui-engineering/SKILL.md",
|
|
124
|
+
"skills/git-workflow-and-versioning/SKILL.md",
|
|
125
|
+
"skills/idea-refine/SKILL.md",
|
|
126
|
+
"skills/idea-refine/examples.md",
|
|
127
|
+
"skills/idea-refine/frameworks.md",
|
|
128
|
+
"skills/idea-refine/refinement-criteria.md",
|
|
129
|
+
"skills/idea-refine/scripts/idea-refine.sh",
|
|
130
|
+
"skills/incremental-implementation/SKILL.md",
|
|
131
|
+
"skills/interview-me/SKILL.md",
|
|
132
|
+
"skills/observability-and-instrumentation/SKILL.md",
|
|
133
|
+
"skills/performance-optimization/SKILL.md",
|
|
134
|
+
"skills/performance-optimization/references/optimization-patterns.md",
|
|
135
|
+
"skills/planning-and-task-breakdown/SKILL.md",
|
|
136
|
+
"skills/security-and-hardening/SKILL.md",
|
|
137
|
+
"skills/security-and-hardening/references/hardening-patterns.md",
|
|
138
|
+
"skills/shipping-and-launch/SKILL.md",
|
|
139
|
+
"skills/source-driven-development/SKILL.md",
|
|
140
|
+
"skills/spec-driven-development/SKILL.md",
|
|
141
|
+
"skills/test-driven-development/SKILL.md",
|
|
142
|
+
"skills/using-agent-skills/SKILL.md"
|
|
143
|
+
],
|
|
144
|
+
"skillFrontmatter": {
|
|
145
|
+
"api-and-interface-design": "44f904d462977e9514f439ac7c057b8691613ba8160360ad9d28b830d3a24001",
|
|
146
|
+
"browser-testing-with-devtools": "e235631718d18a0527d00eb718ecece2218bbf205d742632f8197b30c052e96b",
|
|
147
|
+
"ci-cd-and-automation": "dd73253ec445a9af27ebeab74404ee7a770919e40ec9db0b34af4fa9ec36bf7c",
|
|
148
|
+
"code-review-and-quality": "bf3dda5e08190fcf00175a5053f53550bca91ca32b0a06e4b97cd33e046e8eb7",
|
|
149
|
+
"code-simplification": "cee4dc87b4bc95d77fe646d4ab9e66c9a422dd081a833d657d618aaf2967b5a2",
|
|
150
|
+
"constraint-driven-development": "0da347bd34b155ab79cad1e0ee80238f3b4b91b1a17ca0fc2f68460c02224194",
|
|
151
|
+
"context-engineering": "f4f18514e5eeb162ef9f925dea85af2c72ba79f9b157783a06c39c0bde102d3f",
|
|
152
|
+
"debugging-and-error-recovery": "658d96f63d56946214a7ec87be0347c78d6024a18f6481dc9f7310638f403629",
|
|
153
|
+
"deprecation-and-migration": "388d5e7e549f1b728213f0f50d91e9ca96210e0cb23fd9fccd30755268dd01f9",
|
|
154
|
+
"documentation-and-adrs": "6b2a9d19ebbb81570022a89f09b4810eeb0643a48c698989ee27a224f90bc026",
|
|
155
|
+
"doubt-driven-development": "df8954091f08c14b0e91bf3bf330f43d5a8408c1efe697591b7b0e8448251c71",
|
|
156
|
+
"frontend-ui-engineering": "323624fe7ec44bdb4fad3c9488e55993119912625fffa20ee5787389da2b600d",
|
|
157
|
+
"git-workflow-and-versioning": "dd28469b0f294865dbd20d622a9fee5f05ef87ab1599e973fec6d15a16f76e15",
|
|
158
|
+
"idea-refine": "07eedcfcba98c6c8f6985917830c4b3d93d4e17af05a9b2ca1b8cb54226bc1b9",
|
|
159
|
+
"incremental-implementation": "d31e04a0d7b07fc7d01e0176aafbba5607f1cfe7a29a634498305d95c2b3bd3b",
|
|
160
|
+
"interview-me": "62700902b592a4fa28f6f71f2581d4e1dee412ff288eb156ed97fac3db8b4295",
|
|
161
|
+
"observability-and-instrumentation": "652b9724e431bd7cfd4481bbab31bb079eeab2b5f70ebc04cf66743e37028721",
|
|
162
|
+
"performance-optimization": "76befb0806caad12322de8fe372d2e984f6e07c393fd8d3658537c92c7e285cf",
|
|
163
|
+
"planning-and-task-breakdown": "c3bc139dfa7af82e2d11c7cf461bbf923add7d6494d669da98925f77a7671641",
|
|
164
|
+
"security-and-hardening": "981142e38769394e6e7760250f2dd599dff21a370040f3f141c42507f04ea540",
|
|
165
|
+
"shipping-and-launch": "02cc76557e581957cb4987a53e03a8d1aa04c72dc735390d52ae4eed3ddeddf9",
|
|
166
|
+
"source-driven-development": "233bf9f16f5fe0960c988a5feb2efc475b9b24f9e145d960f8c63e44f4f34fde",
|
|
167
|
+
"spec-driven-development": "e21f25e534ffa3e2de9ac08c40f8d1d90cef17ad55702f83301cbc2a297c2dcb",
|
|
168
|
+
"test-driven-development": "38f1489687eaa60761522a8e3efaa926b52786b0e1b3c57947a6050c0da340de",
|
|
169
|
+
"using-agent-skills": "df5d4f61855ac46da3371bad8c05edb8bc9375ba191acc82b0cca257cfec946c"
|
|
170
|
+
}
|
|
171
|
+
}
|
|
@@ -7,8 +7,16 @@ const path = require('node:path');
|
|
|
7
7
|
const root = path.resolve(__dirname, '..');
|
|
8
8
|
const brand = require('../rebrand/brand.json');
|
|
9
9
|
const pkg = require('../package.json');
|
|
10
|
+
const upstream = require('../rebrand/upstream.json');
|
|
11
|
+
const { validateCatalog } = require('../rebrand/catalog.cjs');
|
|
12
|
+
validateCatalog(root, upstream);
|
|
10
13
|
function json(relative) { return JSON.parse(fs.readFileSync(path.join(root, relative), 'utf8')); }
|
|
11
14
|
assert.equal(pkg.name, brand.npmName);
|
|
15
|
+
assert.equal(pkg.version, brand.releaseVersion);
|
|
16
|
+
assert.equal(brand.upstreamCommit, upstream.upstreamCommit);
|
|
17
|
+
assert.equal(pkg.i3ComposerAgent.upstreamVersion, upstream.upstreamVersion);
|
|
18
|
+
assert.equal(pkg.i3ComposerAgent.upstreamCommit, upstream.upstreamCommit);
|
|
19
|
+
assert.equal(pkg.i3ComposerAgent.upstreamRepository, brand.upstream);
|
|
12
20
|
assert.equal(Object.keys(pkg.bin).length, 1, 'npx must resolve one executable');
|
|
13
21
|
assert.ok(fs.existsSync(path.join(root, pkg.bin[brand.name])));
|
|
14
22
|
for (const relative of ['plugin.json', '.claude-plugin/plugin.json', '.codex-plugin/plugin.json']) {
|
|
@@ -22,10 +30,10 @@ for (const relative of ['.claude-plugin/marketplace.json', '.agents/plugins/mark
|
|
|
22
30
|
}
|
|
23
31
|
assert.ok(json('.codex-plugin/plugin.json').interface.shortDescription.length <= 30);
|
|
24
32
|
const skills = fs.readdirSync(path.join(root, 'skills')).filter(name => fs.existsSync(path.join(root, 'skills', name, 'SKILL.md')));
|
|
25
|
-
assert.equal(skills.length,
|
|
33
|
+
assert.equal(skills.length, upstream.skills.length, 'brand conversion must preserve the reviewed upstream skills');
|
|
26
34
|
assert.ok(skills.includes('using-agent-skills'), 'meta-skill ID must remain stable');
|
|
27
35
|
const commands = fs.readdirSync(path.join(root, '.claude/commands')).filter(name => name.endsWith('.md'));
|
|
28
|
-
assert.equal(commands.length,
|
|
36
|
+
assert.equal(commands.length, upstream.commands.length, 'brand conversion must preserve the reviewed upstream commands');
|
|
29
37
|
for (const command of commands) {
|
|
30
38
|
const body = fs.readFileSync(path.join(root, '.claude/commands', command), 'utf8');
|
|
31
39
|
assert.ok(!body.includes('agent-skills:'), `${command}: stale plugin namespace`);
|
|
@@ -33,4 +41,4 @@ for (const command of commands) {
|
|
|
33
41
|
}
|
|
34
42
|
for (const relative of pkg.i3ComposerAgent.pluginFiles) assert.ok(fs.existsSync(path.join(root, relative)), `bundle is missing ${relative}`);
|
|
35
43
|
assert.match(fs.readFileSync(path.join(root, 'LICENSE'), 'utf8'), /Copyright \(c\) 2025 Addy Osmani/);
|
|
36
|
-
console.log('Brand identity, package entrypoint,
|
|
44
|
+
console.log('Brand identity, package entrypoint, reviewed upstream catalog, and attribution are consistent.');
|
|
File without changes
|