@givolt/i3-composer-agent 1.0.0 → 2.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 +1 -1
- package/.claude/commands/{build.md → i3-build.md} +10 -10
- package/.claude/commands/{code-simplify.md → i3-code-simplify.md} +2 -2
- package/.claude/commands/{constraints.md → i3-constraints.md} +4 -4
- package/.claude/commands/{plan.md → i3-plan.md} +1 -1
- package/.claude/commands/{review.md → i3-review.md} +3 -3
- package/.claude/commands/{ship.md → i3-ship.md} +4 -4
- package/.claude/commands/{spec.md → i3-spec.md} +1 -1
- package/.claude/commands/{test.md → i3-test.md} +2 -2
- package/.claude/commands/{webperf.md → i3-webperf.md} +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.gemini/commands/{build.toml → i3-build.toml} +10 -10
- package/.gemini/commands/{code-simplify.toml → i3-code-simplify.toml} +2 -2
- package/.gemini/commands/{constraints.toml → i3-constraints.toml} +4 -4
- package/.gemini/commands/{planning.toml → i3-planning.toml} +1 -1
- package/{commands/review.toml → .gemini/commands/i3-review.toml} +3 -3
- package/.gemini/commands/{ship.toml → i3-ship.toml} +4 -4
- package/.gemini/commands/{spec.toml → i3-spec.toml} +1 -1
- package/{commands/test.toml → .gemini/commands/i3-test.toml} +2 -2
- package/.gemini/commands/{webperf.toml → i3-webperf.toml} +1 -1
- package/CHANGELOG.md +29 -1
- package/NOTICE.md +8 -2
- package/README.md +98 -54
- package/agents/code-reviewer.md +2 -2
- package/agents/security-auditor.md +1 -1
- package/agents/test-engineer.md +1 -1
- package/agents/web-performance-auditor.md +3 -3
- package/bin/agent-targets.json +726 -0
- package/bin/i3-composer-agent.cjs +84 -16
- package/bin/install.cjs +180 -0
- package/bin/skills-registry.LICENSE +21 -0
- package/bin/wizard.cjs +66 -0
- package/commands/{build.toml → i3-build.toml} +10 -10
- package/commands/{code-simplify.toml → i3-code-simplify.toml} +2 -2
- package/commands/{constraints.toml → i3-constraints.toml} +4 -4
- package/commands/{planning.toml → i3-planning.toml} +1 -1
- package/{.gemini/commands/review.toml → commands/i3-review.toml} +3 -3
- package/commands/{ship.toml → i3-ship.toml} +4 -4
- package/commands/{spec.toml → i3-spec.toml} +1 -1
- package/{.gemini/commands/test.toml → commands/i3-test.toml} +2 -2
- package/commands/{webperf.toml → i3-webperf.toml} +1 -1
- package/docs/adoption-guide.md +35 -35
- package/docs/agents.md +12 -12
- package/docs/antigravity-setup.md +14 -14
- package/docs/codebuddy-setup.md +64 -16
- package/docs/codex-setup.md +17 -6
- package/docs/commandcode-setup.md +5 -5
- package/docs/copilot-cli-setup.md +5 -5
- package/docs/copilot-setup.md +22 -22
- package/docs/cursor-setup.md +20 -20
- package/docs/developer-onboarding.md +5 -5
- package/docs/gemini-cli-setup.md +26 -26
- package/docs/getting-started.md +36 -36
- package/docs/opencode-setup.md +27 -27
- package/docs/skill-anatomy.md +3 -3
- package/docs/windsurf-setup.md +7 -7
- package/evals/cases/{api-and-interface-design.json → i3-api-and-interface-design.json} +4 -4
- package/evals/cases/{browser-testing-with-devtools.json → i3-browser-testing-with-devtools.json} +4 -4
- package/evals/cases/{ci-cd-and-automation.json → i3-ci-cd-and-automation.json} +4 -4
- package/evals/cases/{code-review-and-quality.json → i3-code-review-and-quality.json} +4 -4
- package/evals/cases/{code-simplification.json → i3-code-simplification.json} +4 -4
- package/evals/cases/{constraint-driven-development.json → i3-constraint-driven-development.json} +4 -4
- package/evals/cases/{context-engineering.json → i3-context-engineering.json} +4 -4
- package/evals/cases/{debugging-and-error-recovery.json → i3-debugging-and-error-recovery.json} +5 -5
- package/evals/cases/{deprecation-and-migration.json → i3-deprecation-and-migration.json} +4 -4
- package/evals/cases/{documentation-and-adrs.json → i3-documentation-and-adrs.json} +4 -4
- package/evals/cases/{doubt-driven-development.json → i3-doubt-driven-development.json} +3 -3
- package/evals/cases/{frontend-ui-engineering.json → i3-frontend-ui-engineering.json} +4 -4
- package/evals/cases/{git-workflow-and-versioning.json → i3-git-workflow-and-versioning.json} +3 -3
- package/evals/cases/{idea-refine.json → i3-idea-refine.json} +3 -3
- package/evals/cases/{incremental-implementation.json → i3-incremental-implementation.json} +4 -4
- package/evals/cases/{interview-me.json → i3-interview-me.json} +3 -3
- package/evals/cases/{observability-and-instrumentation.json → i3-observability-and-instrumentation.json} +3 -3
- package/evals/cases/{performance-optimization.json → i3-performance-optimization.json} +4 -4
- package/evals/cases/{planning-and-task-breakdown.json → i3-planning-and-task-breakdown.json} +4 -4
- package/evals/cases/{security-and-hardening.json → i3-security-and-hardening.json} +4 -4
- package/evals/cases/{shipping-and-launch.json → i3-shipping-and-launch.json} +4 -4
- package/evals/cases/{source-driven-development.json → i3-source-driven-development.json} +4 -4
- package/evals/cases/{spec-driven-development.json → i3-spec-driven-development.json} +5 -5
- package/evals/cases/{test-driven-development.json → i3-test-driven-development.json} +5 -5
- package/evals/cases/{using-agent-skills.json → i3-using-agent-skills.json} +4 -4
- package/evals/fixtures/{git-workflow-and-versioning → i3-git-workflow-and-versioning}/.eval/working-tree.patch +3 -3
- package/evals/plugin/code-review-fires/graders/skill-fired.md +1 -1
- package/evals/plugin/code-review-stays-quiet/graders/not-fired.md +1 -1
- package/evals/plugin/code-review-stays-quiet/graders/tdd-fired.md +1 -1
- package/evals/plugin/code-review-stays-quiet/prompt.md +2 -2
- package/evals/plugin/code-review-stays-quiet-on-commit-message/graders/not-fired.md +1 -1
- package/evals/plugin/code-review-stays-quiet-on-commit-message/prompt.md +2 -2
- package/hooks/SDD-CACHE.md +3 -3
- package/hooks/SIMPLIFY-IGNORE.md +2 -2
- package/hooks/session-start-test.sh +1 -1
- package/hooks/session-start.sh +3 -3
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/rebrand/INSTALLATION-SPEC.md +47 -0
- package/rebrand/MAINTENANCE.md +5 -3
- package/rebrand/NOTICE.md +8 -2
- package/rebrand/PREFIX-SPEC.md +16 -0
- package/rebrand/UNIFICATION-SPEC.md +2 -2
- package/rebrand/VALIDATION.md +6 -2
- package/rebrand/VERSIONING.md +8 -5
- package/rebrand/apply.cjs +33 -10
- package/rebrand/brand.json +1 -1
- package/rebrand/catalog.cjs +16 -2
- package/rebrand/fork-patches.json +15 -0
- package/rebrand/identifiers.cjs +41 -0
- package/rebrand/overlay/CHANGELOG.md +29 -1
- package/rebrand/overlay/bin/agent-targets.json +726 -0
- package/rebrand/overlay/bin/i3-composer-agent.cjs +84 -16
- package/rebrand/overlay/bin/install.cjs +180 -0
- package/rebrand/overlay/bin/skills-registry.LICENSE +21 -0
- package/rebrand/overlay/bin/wizard.cjs +66 -0
- package/rebrand/overlay/scripts/validate-brand.cjs +3 -3
- package/rebrand/overlay/tests/installer.test.cjs +241 -0
- package/rebrand/templates/README.md +62 -18
- package/rebrand/templates/codebuddy-setup.md +64 -16
- package/rebrand/templates/codex-setup.md +17 -6
- package/rebrand/tests/pipeline.test.cjs +71 -3
- package/references/accessibility-checklist.md +1 -1
- package/references/definition-of-done.md +7 -7
- package/references/observability-checklist.md +3 -3
- package/references/orchestration-patterns.md +17 -17
- package/references/performance-checklist.md +2 -2
- package/references/security-checklist.md +1 -1
- package/references/testing-patterns.md +1 -1
- package/scripts/floor-guard-reference-test.js +2 -2
- package/scripts/lib/skill-lint.js +2 -0
- package/scripts/run-evals-test.js +2 -2
- package/scripts/validate-artifact-paths-test.js +3 -3
- package/scripts/validate-artifact-paths.js +4 -2
- package/scripts/validate-brand.cjs +3 -3
- package/scripts/validate-commands.js +1 -0
- package/scripts/validate-reference-links-test.js +11 -11
- package/scripts/validate-reference-links.js +1 -1
- package/skills/{api-and-interface-design → i3-api-and-interface-design}/SKILL.md +2 -2
- package/skills/{browser-testing-with-devtools → i3-browser-testing-with-devtools}/SKILL.md +1 -1
- package/skills/{ci-cd-and-automation → i3-ci-cd-and-automation}/SKILL.md +2 -2
- package/skills/{code-review-and-quality → i3-code-review-and-quality}/SKILL.md +5 -5
- package/skills/{code-simplification → i3-code-simplification}/SKILL.md +1 -1
- package/skills/{constraint-driven-development → i3-constraint-driven-development}/SKILL.md +15 -15
- package/skills/{context-engineering → i3-context-engineering}/SKILL.md +1 -1
- package/skills/{debugging-and-error-recovery → i3-debugging-and-error-recovery}/SKILL.md +2 -2
- package/skills/{deprecation-and-migration → i3-deprecation-and-migration}/SKILL.md +2 -2
- package/skills/{documentation-and-adrs → i3-documentation-and-adrs}/SKILL.md +1 -1
- package/skills/{doubt-driven-development → i3-doubt-driven-development}/SKILL.md +8 -8
- package/skills/{frontend-ui-engineering → i3-frontend-ui-engineering}/SKILL.md +1 -1
- package/skills/{git-workflow-and-versioning → i3-git-workflow-and-versioning}/SKILL.md +4 -4
- package/skills/{idea-refine → i3-idea-refine}/SKILL.md +2 -2
- package/skills/{idea-refine → i3-idea-refine}/scripts/idea-refine.sh +1 -1
- package/skills/{incremental-implementation → i3-incremental-implementation}/SKILL.md +3 -3
- package/skills/{interview-me → i3-interview-me}/SKILL.md +12 -12
- package/skills/{observability-and-instrumentation → i3-observability-and-instrumentation}/SKILL.md +5 -5
- package/skills/{performance-optimization → i3-performance-optimization}/SKILL.md +1 -1
- package/skills/{performance-optimization → i3-performance-optimization}/references/optimization-patterns.md +1 -1
- package/skills/{planning-and-task-breakdown → i3-planning-and-task-breakdown}/SKILL.md +2 -2
- package/skills/{security-and-hardening → i3-security-and-hardening}/SKILL.md +3 -3
- package/skills/{security-and-hardening → i3-security-and-hardening}/references/hardening-patterns.md +1 -1
- package/skills/{shipping-and-launch → i3-shipping-and-launch}/SKILL.md +2 -2
- package/skills/{source-driven-development → i3-source-driven-development}/SKILL.md +2 -2
- package/skills/{spec-driven-development → i3-spec-driven-development}/SKILL.md +7 -7
- package/skills/{test-driven-development → i3-test-driven-development}/SKILL.md +2 -2
- package/skills/{using-agent-skills → i3-using-agent-skills}/SKILL.md +67 -67
- package/tests/installer.test.cjs +241 -0
- /package/evals/fixtures/{api-and-interface-design → i3-api-and-interface-design}/service-brief.md +0 -0
- /package/evals/fixtures/{browser-testing-with-devtools → i3-browser-testing-with-devtools}/README.md +0 -0
- /package/evals/fixtures/{browser-testing-with-devtools → i3-browser-testing-with-devtools}/index.html +0 -0
- /package/evals/fixtures/{browser-testing-with-devtools → i3-browser-testing-with-devtools}/server.js +0 -0
- /package/evals/fixtures/{ci-cd-and-automation → i3-ci-cd-and-automation}/package.json +0 -0
- /package/evals/fixtures/{ci-cd-and-automation → i3-ci-cd-and-automation}/src/slug.js +0 -0
- /package/evals/fixtures/{ci-cd-and-automation → i3-ci-cd-and-automation}/test/slug.test.js +0 -0
- /package/evals/fixtures/{code-review-and-quality → i3-code-review-and-quality}/user-search.diff +0 -0
- /package/evals/fixtures/{code-simplification → i3-code-simplification}/config-parser.js +0 -0
- /package/evals/fixtures/{code-simplification → i3-code-simplification}/config-parser.test.js +0 -0
- /package/evals/fixtures/{context-engineering → i3-context-engineering}/context-audit.md +0 -0
- /package/evals/fixtures/{debugging-and-error-recovery → i3-debugging-and-error-recovery}/pagination.js +0 -0
- /package/evals/fixtures/{debugging-and-error-recovery → i3-debugging-and-error-recovery}/pagination.test.js +0 -0
- /package/evals/fixtures/{debugging-and-error-recovery → i3-debugging-and-error-recovery}/time-pressure.md +0 -0
- /package/evals/fixtures/{deprecation-and-migration → i3-deprecation-and-migration}/api-inventory.md +0 -0
- /package/evals/fixtures/{documentation-and-adrs → i3-documentation-and-adrs}/decision-context.md +0 -0
- /package/evals/fixtures/{doubt-driven-development → i3-doubt-driven-development}/migration-plan.md +0 -0
- /package/evals/fixtures/{frontend-ui-engineering → i3-frontend-ui-engineering}/Button.tsx +0 -0
- /package/evals/fixtures/{frontend-ui-engineering → i3-frontend-ui-engineering}/design-system.md +0 -0
- /package/evals/fixtures/{git-workflow-and-versioning → i3-git-workflow-and-versioning}/app.js +0 -0
- /package/evals/fixtures/{git-workflow-and-versioning → i3-git-workflow-and-versioning}/app.test.js +0 -0
- /package/evals/fixtures/{incremental-implementation → i3-incremental-implementation}/reports.js +0 -0
- /package/evals/fixtures/{incremental-implementation → i3-incremental-implementation}/reports.test.js +0 -0
- /package/evals/fixtures/{incremental-implementation → i3-incremental-implementation}/tasks/plan.md +0 -0
- /package/evals/fixtures/{observability-and-instrumentation → i3-observability-and-instrumentation}/operations.md +0 -0
- /package/evals/fixtures/{observability-and-instrumentation → i3-observability-and-instrumentation}/payment-retry.js +0 -0
- /package/evals/fixtures/{performance-optimization → i3-performance-optimization}/benchmark.js +0 -0
- /package/evals/fixtures/{performance-optimization → i3-performance-optimization}/products.js +0 -0
- /package/evals/fixtures/{planning-and-task-breakdown → i3-planning-and-task-breakdown}/notifications-spec.md +0 -0
- /package/evals/fixtures/{security-and-hardening → i3-security-and-hardening}/webhook.js +0 -0
- /package/evals/fixtures/{security-and-hardening → i3-security-and-hardening}/webhook.test.js +0 -0
- /package/evals/fixtures/{shipping-and-launch → i3-shipping-and-launch}/authority-pressure.md +0 -0
- /package/evals/fixtures/{shipping-and-launch → i3-shipping-and-launch}/launch-status.md +0 -0
- /package/evals/fixtures/{source-driven-development → i3-source-driven-development}/framework-task.md +0 -0
- /package/evals/fixtures/{spec-driven-development → i3-spec-driven-development}/billing-brief.md +0 -0
- /package/evals/fixtures/{test-driven-development → i3-test-driven-development}/BUG.md +0 -0
- /package/evals/fixtures/{test-driven-development → i3-test-driven-development}/README.md +0 -0
- /package/evals/fixtures/{test-driven-development → i3-test-driven-development}/package.json +0 -0
- /package/evals/fixtures/{test-driven-development → i3-test-driven-development}/src/split.js +0 -0
- /package/evals/fixtures/{test-driven-development → i3-test-driven-development}/test/split.test.js +0 -0
- /package/evals/fixtures/{using-agent-skills → i3-using-agent-skills}/incident.md +0 -0
- /package/skills/{constraint-driven-development → i3-constraint-driven-development}/references/floor-guard.md +0 -0
- /package/skills/{idea-refine → i3-idea-refine}/examples.md +0 -0
- /package/skills/{idea-refine → i3-idea-refine}/frameworks.md +0 -0
- /package/skills/{idea-refine → i3-idea-refine}/refinement-criteria.md +0 -0
|
@@ -12,23 +12,35 @@ const identity = `i3 Composer Agent v${pkg.version}\nBased on agent-skills v${pk
|
|
|
12
12
|
const help = `${identity}
|
|
13
13
|
${pkg.name}
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Install engineering skills with a multi-tool installation wizard.
|
|
16
16
|
|
|
17
17
|
Usage:
|
|
18
|
-
npx ${pkg.name}
|
|
19
|
-
npx ${pkg.name} --
|
|
20
|
-
npx ${pkg.name} --
|
|
18
|
+
npx ${pkg.name}
|
|
19
|
+
npx ${pkg.name} --codebuddy
|
|
20
|
+
npx ${pkg.name} --agents codebuddy,codex --scope project --yes
|
|
21
|
+
npx ${pkg.name} --prepare --claude --dir <directory>
|
|
21
22
|
npx ${pkg.name} --extract --dir <directory>
|
|
22
23
|
|
|
23
24
|
Options:
|
|
24
|
-
--
|
|
25
|
-
--
|
|
26
|
-
--
|
|
27
|
-
--
|
|
28
|
-
--
|
|
25
|
+
--agents <ids> Comma-separated tool IDs; multiple tools are supported
|
|
26
|
+
--codebuddy Preselect CodeBuddy desktop IDE / CodeBuddy Code
|
|
27
|
+
--codex Preselect Codex
|
|
28
|
+
--claude Preselect Claude Code
|
|
29
|
+
--scope <scope> project or global (or use --global / --local)
|
|
30
|
+
--project-dir <dir> Project installation root (default: current directory)
|
|
31
|
+
--yes Confirm explicit noninteractive installation
|
|
32
|
+
--list-agents List all supported tool directories
|
|
33
|
+
--prepare Prepare a complete plugin for native plugin registration
|
|
34
|
+
--dir <directory> Plugin output directory; implies --prepare
|
|
35
|
+
--dry-run Show the installation or bundle plan without writing files
|
|
36
|
+
--force Replace existing assets, preserving backups
|
|
37
|
+
--version Print the package version
|
|
38
|
+
--help Show this help
|
|
29
39
|
|
|
30
|
-
|
|
31
|
-
|
|
40
|
+
The terminal wizard selects tools and scope, then installs native skill files.
|
|
41
|
+
CodeBuddy and Claude Code also receive short lifecycle commands and personas.
|
|
42
|
+
Other tools receive skills and references; command availability is host-specific.
|
|
43
|
+
Use --prepare for complete plugins, including hooks and host registration.
|
|
32
44
|
`;
|
|
33
45
|
|
|
34
46
|
function quote(value) { return "'" + value.replaceAll("'", "'\\''") + "'"; }
|
|
@@ -43,15 +55,14 @@ function realDestination(target) {
|
|
|
43
55
|
}
|
|
44
56
|
return path.join(fs.realpathSync(existing), ...suffix);
|
|
45
57
|
}
|
|
46
|
-
function
|
|
47
|
-
if (!args.length || args.includes('--help')) { console.log(help); return; }
|
|
48
|
-
if (args.length === 1 && args[0] === '--version') { console.log(pkg.version); return; }
|
|
58
|
+
function prepare() {
|
|
49
59
|
let host;
|
|
50
60
|
let directory = path.join(process.cwd(), name);
|
|
51
61
|
let dryRun = false;
|
|
52
62
|
let force = false;
|
|
53
63
|
for (let i = 0; i < args.length; i++) {
|
|
54
64
|
const arg = args[i];
|
|
65
|
+
if (arg === '--prepare') continue;
|
|
55
66
|
if (['--codebuddy', '--codex', '--claude', '--extract'].includes(arg)) {
|
|
56
67
|
if (host) throw new Error('Choose exactly one host flag or --extract.');
|
|
57
68
|
host = arg.slice(2);
|
|
@@ -116,7 +127,64 @@ function main() {
|
|
|
116
127
|
} else {
|
|
117
128
|
console.log(`/plugin marketplace add ${quote(directory)}`);
|
|
118
129
|
console.log(`/plugin install ${selector}`);
|
|
119
|
-
console.log(`Use /${name}:spec, /${name}:plan, /${name}:build, and /${name}:ship in ${host === 'claude' ? 'Claude Code' : 'CodeBuddy'}.`);
|
|
130
|
+
console.log(`Use /${name}:i3-spec, /${name}:i3-plan, /${name}:i3-build, and /${name}:i3-ship in ${host === 'claude' ? 'Claude Code' : 'CodeBuddy'}.`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async function main() {
|
|
134
|
+
if (args.includes('--help') || (!args.length && !process.stdin.isTTY)) { console.log(help); return; }
|
|
135
|
+
if (args.length === 1 && args[0] === '--version') { console.log(pkg.version); return; }
|
|
136
|
+
if (args.some(arg => ['--extract', '--prepare', '--dir'].includes(arg))) { prepare(); return; }
|
|
137
|
+
const installer = require('./install.cjs');
|
|
138
|
+
if (args.length === 1 && args[0] === '--list-agents') {
|
|
139
|
+
for (const agent of installer.registry.agents) console.log(`${agent.id.padEnd(20)} ${agent.label}${agent.globalSkillsDir ? '' : ' (project only)'}`);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const options = { agents: [], projectDir: process.cwd() };
|
|
143
|
+
for (let i = 0; i < args.length; i++) {
|
|
144
|
+
const arg = args[i];
|
|
145
|
+
if (['--codebuddy', '--codex', '--claude'].includes(arg)) options.agents.push(arg.slice(2));
|
|
146
|
+
else if (['--agents', '--scope', '--project-dir'].includes(arg)) {
|
|
147
|
+
if (!args[i + 1] || args[i + 1].startsWith('--')) throw new Error(`${arg} requires a value.`);
|
|
148
|
+
const value = args[++i];
|
|
149
|
+
if (arg === '--agents') options.agents.push(value);
|
|
150
|
+
else if (arg === '--scope') { if (options.scope && options.scope !== value) throw new Error('Choose one installation scope.'); options.scope = value; }
|
|
151
|
+
else options.projectDir = path.resolve(value);
|
|
152
|
+
} else if (arg === '--global' || arg === '--local') {
|
|
153
|
+
const scope = arg === '--global' ? 'global' : 'project';
|
|
154
|
+
if (options.scope && options.scope !== scope) throw new Error('Choose one installation scope.');
|
|
155
|
+
options.scope = scope;
|
|
156
|
+
} else if (arg === '--yes') options.yes = true;
|
|
157
|
+
else if (arg === '--force') options.force = true;
|
|
158
|
+
else if (arg === '--dry-run') options.dryRun = true;
|
|
159
|
+
else throw new Error(`Unknown option: ${arg}`);
|
|
160
|
+
}
|
|
161
|
+
options.agents = installer.selectAgents(options.agents);
|
|
162
|
+
if (process.stdin.isTTY && process.stdout.isTTY && !options.yes && !options.dryRun) {
|
|
163
|
+
const selection = await require('./wizard.cjs').choose(options, identity);
|
|
164
|
+
if (!selection) { console.log('Installation cancelled. No files changed.'); return; }
|
|
165
|
+
Object.assign(options, selection);
|
|
166
|
+
} else if (!options.agents.length || !options.scope || (!options.yes && !options.dryRun)) {
|
|
167
|
+
throw new Error('Use an interactive terminal, or specify --agents <ids> --scope project|global --yes.');
|
|
168
|
+
}
|
|
169
|
+
const plan = installer.planInstallation(options);
|
|
170
|
+
if (options.dryRun) {
|
|
171
|
+
console.log(JSON.stringify({ name, version: pkg.version, upstreamVersion: pkg.i3ComposerAgent.upstreamVersion, upstreamCommit: pkg.i3ComposerAgent.upstreamCommit, mode: plan.mode, scope: plan.scope, agents: plan.agents, targets: plan.targets, conflicts: plan.conflicts }, null, 2));
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (!options.yes) {
|
|
175
|
+
const confirmed = await require('./wizard.cjs').confirm(plan);
|
|
176
|
+
if (!confirmed) { console.log('Installation cancelled. No files changed.'); return; }
|
|
177
|
+
options.force = plan.conflicts.length > 0;
|
|
178
|
+
}
|
|
179
|
+
const backups = installer.executeInstallation(plan, { force: options.force });
|
|
180
|
+
console.log(identity);
|
|
181
|
+
for (const target of plan.targets) {
|
|
182
|
+
console.log(`Installed ${target.agents.join(', ')} skills at ${target.skillsDirectory}`);
|
|
183
|
+
if (target.commandsDirectory) console.log(`Commands: /i3-spec, /i3-plan, /i3-build, /i3-ship (all ${fs.readdirSync(target.commandsDirectory).filter(file => file.endsWith('.md')).length} workflows) at ${target.commandsDirectory}`);
|
|
120
184
|
}
|
|
185
|
+
for (const backup of backups) console.log(`Previous assets preserved at ${backup}`);
|
|
186
|
+
console.log('Reload the IDE window or start a new host session to discover installed files.');
|
|
187
|
+
if (plan.agents.some(id => !['codebuddy', 'claude-code'].includes(id))) console.log('These tools use the existing skill IDs; lifecycle slash-command support depends on the host.');
|
|
188
|
+
console.log('Native skill installation does not enable plugin hooks. Use --prepare for complete plugin registration.');
|
|
121
189
|
}
|
|
122
|
-
|
|
190
|
+
main().catch(error => { console.error(`${name}: ${error.message}`); process.exitCode = 1; });
|
package/bin/install.cjs
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const os = require('node:os');
|
|
6
|
+
const crypto = require('node:crypto');
|
|
7
|
+
const registry = require('./agent-targets.json');
|
|
8
|
+
const upstream = require('../rebrand/upstream.json');
|
|
9
|
+
const root = path.resolve(__dirname, '..');
|
|
10
|
+
const name = 'i3-composer-agent';
|
|
11
|
+
const aliases = { claude: 'claude-code', gemini: 'gemini-cli', copilot: 'github-copilot' };
|
|
12
|
+
function exists(file) {
|
|
13
|
+
try { fs.lstatSync(file); return true; }
|
|
14
|
+
catch (error) { if (error.code === 'ENOENT') return false; throw error; }
|
|
15
|
+
}
|
|
16
|
+
function selectAgents(values) {
|
|
17
|
+
const ids = [...new Set(values.flatMap(value => value.split(',')).map(id => aliases[id.trim()] || id.trim()).filter(Boolean))];
|
|
18
|
+
for (const id of ids) if (!registry.agents.some(agent => agent.id === id)) throw new Error(`Unknown tool: ${id}. Use --list-agents.`);
|
|
19
|
+
return ids;
|
|
20
|
+
}
|
|
21
|
+
function globalSkillsDir(agent, home, env) {
|
|
22
|
+
const config = agent.globalSkillsDir;
|
|
23
|
+
if (!config) throw new Error(`${agent.label} supports project installation only. Choose project scope or remove this tool.`);
|
|
24
|
+
let base = home;
|
|
25
|
+
if (config.base === 'config') base = env.XDG_CONFIG_HOME && path.isAbsolute(env.XDG_CONFIG_HOME) ? env.XDG_CONFIG_HOME : path.join(home, '.config');
|
|
26
|
+
if (config.base === 'env') base = env[config.env]?.trim() || path.join(home, config.fallback);
|
|
27
|
+
if (config.alternatives && !fs.existsSync(path.join(home, path.dirname(config.path)))) {
|
|
28
|
+
const alternative = config.alternatives.find(relative => fs.existsSync(path.join(home, path.dirname(relative))));
|
|
29
|
+
if (alternative) return path.join(home, alternative);
|
|
30
|
+
}
|
|
31
|
+
return path.resolve(base, config.path);
|
|
32
|
+
}
|
|
33
|
+
// Resolve parent aliases while keeping a leaf symlink replaceable as a link.
|
|
34
|
+
function destination(file) {
|
|
35
|
+
let parent = path.dirname(file);
|
|
36
|
+
const suffix = [path.basename(file)];
|
|
37
|
+
while (!exists(parent)) { suffix.unshift(path.basename(parent)); parent = path.dirname(parent); }
|
|
38
|
+
return path.join(fs.realpathSync(parent), ...suffix);
|
|
39
|
+
}
|
|
40
|
+
function checkDestination(file) {
|
|
41
|
+
const source = fs.realpathSync(root);
|
|
42
|
+
if (file === source || file.startsWith(source + path.sep) || source.startsWith(file + path.sep)) {
|
|
43
|
+
throw new Error('Installation destinations must be outside this package directory.');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function planInstallation({ agents, scope, projectDir = process.cwd(), home = os.homedir(), env = process.env }) {
|
|
47
|
+
agents = selectAgents(agents);
|
|
48
|
+
if (!agents.length) throw new Error('Choose at least one tool.');
|
|
49
|
+
if (!['project', 'global'].includes(scope)) throw new Error('Choose --scope project or --scope global.');
|
|
50
|
+
const targets = new Map();
|
|
51
|
+
for (const id of agents) {
|
|
52
|
+
const agent = registry.agents.find(item => item.id === id);
|
|
53
|
+
const skillsDirectory = destination(scope === 'project' ? path.resolve(projectDir, agent.projectSkillsDir) : globalSkillsDir(agent, home, env));
|
|
54
|
+
const base = path.dirname(skillsDirectory);
|
|
55
|
+
if (!targets.has(skillsDirectory)) targets.set(skillsDirectory, { agents: [], skillsDirectory, referencesDirectory: path.join(base, 'references'), base });
|
|
56
|
+
const target = targets.get(skillsDirectory);
|
|
57
|
+
target.agents.push(id);
|
|
58
|
+
if (['codebuddy', 'claude-code'].includes(id)) {
|
|
59
|
+
target.commandsDirectory = path.join(base, 'commands');
|
|
60
|
+
target.personasDirectory = path.join(base, 'agents');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const assets = [];
|
|
64
|
+
function addDirectory(sourceDirectory, destinationDirectory, kind) {
|
|
65
|
+
if (exists(destinationDirectory) && fs.lstatSync(destinationDirectory).isSymbolicLink()) {
|
|
66
|
+
throw new Error(`Installation directory is a symlink: ${destinationDirectory}. Choose its canonical location instead.`);
|
|
67
|
+
}
|
|
68
|
+
for (const entry of fs.readdirSync(path.join(root, sourceDirectory)).sort()) {
|
|
69
|
+
if (entry === '.DS_Store') continue;
|
|
70
|
+
assets.push({ source: path.join(root, sourceDirectory, entry), destination: destination(path.join(destinationDirectory, entry)), kind });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
for (const target of targets.values()) {
|
|
74
|
+
const start = assets.length;
|
|
75
|
+
addDirectory('skills', target.skillsDirectory, 'skill');
|
|
76
|
+
addDirectory('references', target.referencesDirectory, 'reference');
|
|
77
|
+
if (target.commandsDirectory) {
|
|
78
|
+
addDirectory('.claude/commands', target.commandsDirectory, 'command');
|
|
79
|
+
addDirectory('agents', target.personasDirectory, 'persona');
|
|
80
|
+
const docs = path.join(target.base, 'docs');
|
|
81
|
+
if (exists(docs) && fs.lstatSync(docs).isSymbolicLink()) throw new Error(`Installation directory is a symlink: ${docs}.`);
|
|
82
|
+
assets.push({ source: path.join(root, 'docs/agents.md'), destination: destination(path.join(target.base, 'docs/agents.md')), kind: 'documentation' });
|
|
83
|
+
}
|
|
84
|
+
assets.push({ source: path.join(root, 'LICENSE'), destination: destination(path.join(target.base, `${name}-LICENSE`)), kind: 'attribution' });
|
|
85
|
+
assets.push({ source: path.join(root, 'NOTICE.md'), destination: destination(path.join(target.base, `${name}-NOTICE.md`)), kind: 'attribution' });
|
|
86
|
+
const manifestFile = path.join(target.base, `.${name}.json`);
|
|
87
|
+
if (exists(manifestFile)) {
|
|
88
|
+
const previous = JSON.parse(fs.readFileSync(manifestFile, 'utf8'));
|
|
89
|
+
if (previous.name === name && Array.isArray(previous.assets)) {
|
|
90
|
+
const legacy = upstream.skills.map(id => `skills/${id}`);
|
|
91
|
+
if (target.commandsDirectory) legacy.push(...upstream.commands.map(id => `commands/${id}.md`));
|
|
92
|
+
for (const relative of legacy) {
|
|
93
|
+
const file = destination(path.join(target.base, relative));
|
|
94
|
+
if (previous.assets.includes(relative) && exists(file)) assets.push({ destination: file, kind: 'legacy' });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
assets.push({ target, destination: destination(manifestFile), kind: 'manifest' });
|
|
99
|
+
for (const asset of assets.slice(start)) {
|
|
100
|
+
asset.base = target.base;
|
|
101
|
+
asset.codebuddyCommand = asset.kind === 'command' && target.agents.includes('codebuddy');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
for (const asset of assets) { checkDestination(asset.destination); asset.existing = exists(asset.destination); }
|
|
105
|
+
return { mode: 'install', scope, agents, targets: [...targets.values()], assets, conflicts: assets.filter(asset => asset.existing).map(asset => asset.destination) };
|
|
106
|
+
}
|
|
107
|
+
function executeInstallation(plan, { force = false } = {}) {
|
|
108
|
+
if (plan.conflicts.length && !force) throw new Error('Existing installation assets require confirmation or --force; previous files will be backed up.');
|
|
109
|
+
const pkg = require('../package.json');
|
|
110
|
+
const contexts = new Map();
|
|
111
|
+
const createdDirectories = [];
|
|
112
|
+
const committed = [];
|
|
113
|
+
function mkdir(directory) {
|
|
114
|
+
if (exists(directory)) return;
|
|
115
|
+
mkdir(path.dirname(directory));
|
|
116
|
+
fs.mkdirSync(directory);
|
|
117
|
+
createdDirectories.push(directory);
|
|
118
|
+
}
|
|
119
|
+
function portable(file, markdown = false, codebuddyCommand = false) {
|
|
120
|
+
if (fs.statSync(file).isDirectory()) {
|
|
121
|
+
for (const entry of fs.readdirSync(file)) portable(path.join(file, entry), false, codebuddyCommand);
|
|
122
|
+
} else if (markdown || file.endsWith('.md')) {
|
|
123
|
+
let content = fs.readFileSync(file, 'utf8').replaceAll('i3-composer-agent:', '').replaceAll('agent-skills:', '');
|
|
124
|
+
if (codebuddyCommand) content = content.replaceAll('.claude/agents/', '.codebuddy/agents/');
|
|
125
|
+
fs.writeFileSync(file, content);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
// Stage every target before replacing the first installed asset.
|
|
130
|
+
for (const [index, asset] of plan.assets.entries()) {
|
|
131
|
+
if (!contexts.has(asset.base)) {
|
|
132
|
+
mkdir(asset.base);
|
|
133
|
+
contexts.set(asset.base, { staging: fs.mkdtempSync(path.join(asset.base, `.${name}-stage-`)), backup: path.join(asset.base, `.${name}-backup-${crypto.randomUUID()}`) });
|
|
134
|
+
}
|
|
135
|
+
const context = contexts.get(asset.base);
|
|
136
|
+
if (asset.kind === 'legacy') continue;
|
|
137
|
+
asset.staged = path.join(context.staging, String(index));
|
|
138
|
+
if (asset.kind === 'manifest') {
|
|
139
|
+
fs.writeFileSync(asset.staged, JSON.stringify({ name, version: pkg.version, entryPrefix: 'i3-', upstreamVersion: pkg.i3ComposerAgent.upstreamVersion, upstreamCommit: pkg.i3ComposerAgent.upstreamCommit, scope: plan.scope, agents: asset.target.agents, assets: plan.assets.filter(item => item.base === asset.base && item.kind !== 'legacy').map(item => path.relative(asset.base, item.destination)) }, null, 2) + '\n');
|
|
140
|
+
} else {
|
|
141
|
+
fs.cpSync(asset.source, asset.staged, { recursive: true, filter: file => {
|
|
142
|
+
if (fs.lstatSync(file).isSymbolicLink()) throw new Error(`Package contains a symlink: ${file}`);
|
|
143
|
+
return path.basename(file) !== '.DS_Store';
|
|
144
|
+
} });
|
|
145
|
+
portable(asset.staged, asset.source.endsWith('.md'), asset.codebuddyCommand);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
for (const asset of plan.assets) {
|
|
149
|
+
const context = contexts.get(asset.base);
|
|
150
|
+
mkdir(path.dirname(asset.destination));
|
|
151
|
+
// A destination may have appeared since planning; never replace it implicitly.
|
|
152
|
+
if (exists(asset.destination) && !force) throw new Error(`Destination appeared during installation: ${asset.destination}. Retry with confirmed replacement.`);
|
|
153
|
+
const change = { destination: asset.destination, written: false };
|
|
154
|
+
if (exists(asset.destination)) {
|
|
155
|
+
change.backup = path.join(context.backup, path.relative(asset.base, asset.destination));
|
|
156
|
+
mkdir(path.dirname(change.backup));
|
|
157
|
+
fs.renameSync(asset.destination, change.backup);
|
|
158
|
+
}
|
|
159
|
+
committed.push(change);
|
|
160
|
+
if (asset.kind !== 'legacy') {
|
|
161
|
+
fs.renameSync(asset.staged, asset.destination);
|
|
162
|
+
change.written = true;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return [...contexts.values()].map(context => context.backup).filter(exists);
|
|
166
|
+
} catch (error) {
|
|
167
|
+
for (const change of committed.reverse()) {
|
|
168
|
+
if (change.written) fs.rmSync(change.destination, { recursive: true, force: true });
|
|
169
|
+
if (change.backup) fs.renameSync(change.backup, change.destination);
|
|
170
|
+
}
|
|
171
|
+
throw error;
|
|
172
|
+
} finally {
|
|
173
|
+
for (const context of contexts.values()) fs.rmSync(context.staging, { recursive: true, force: true });
|
|
174
|
+
for (const directory of createdDirectories.reverse()) {
|
|
175
|
+
try { fs.rmdirSync(directory); }
|
|
176
|
+
catch (error) { if (!['ENOENT', 'ENOTEMPTY', 'EEXIST'].includes(error.code)) throw error; }
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
module.exports = { registry, selectAgents, planInstallation, executeInstallation, exists };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vercel, Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/bin/wizard.cjs
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const readline = require('node:readline');
|
|
4
|
+
const { registry, selectAgents } = require('./install.cjs');
|
|
5
|
+
|
|
6
|
+
async function session(action) {
|
|
7
|
+
const terminal = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
8
|
+
let closed = false;
|
|
9
|
+
terminal.on('close', () => { closed = true; });
|
|
10
|
+
terminal.on('SIGINT', () => terminal.close());
|
|
11
|
+
const ask = prompt => new Promise(resolve => {
|
|
12
|
+
if (closed) { resolve(null); return; }
|
|
13
|
+
const cancelled = () => resolve(null);
|
|
14
|
+
terminal.once('close', cancelled);
|
|
15
|
+
terminal.question(prompt, answer => {
|
|
16
|
+
terminal.off('close', cancelled);
|
|
17
|
+
resolve(answer.trim());
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
try { return await action(ask); }
|
|
21
|
+
finally { terminal.close(); }
|
|
22
|
+
}
|
|
23
|
+
async function choose(options, identity) {
|
|
24
|
+
console.log(identity);
|
|
25
|
+
console.log('\nChoose tools (multiple selections are supported):');
|
|
26
|
+
const entries = registry.agents.map((agent, index) => `${index + 1}. ${agent.label} [${agent.id}]${agent.globalSkillsDir ? '' : ' (project only)'}`);
|
|
27
|
+
for (let index = 0; index < entries.length; index += 2) console.log(entries[index].padEnd(49) + (entries[index + 1] || ''));
|
|
28
|
+
return session(async ask => {
|
|
29
|
+
let agents;
|
|
30
|
+
while (!agents) {
|
|
31
|
+
const input = await ask(`Select tools by number or ID, comma-separated${options.agents.length ? ` [${options.agents.join(',')}]` : ''} (q cancels): `);
|
|
32
|
+
if (input === null || ['q', 'cancel'].includes(input.toLowerCase())) return null;
|
|
33
|
+
try {
|
|
34
|
+
const values = input === 'all' ? registry.agents.map(agent => agent.id) : input ? input.split(',').map(value => {
|
|
35
|
+
const trimmed = value.trim();
|
|
36
|
+
return /^\d+$/.test(trimmed) ? registry.agents[Number(trimmed) - 1]?.id || trimmed : trimmed;
|
|
37
|
+
}) : options.agents;
|
|
38
|
+
agents = selectAgents(values);
|
|
39
|
+
if (!agents.length) { agents = undefined; console.log('Choose at least one tool.'); }
|
|
40
|
+
} catch (error) { console.log(error.message); }
|
|
41
|
+
}
|
|
42
|
+
let scope = options.scope;
|
|
43
|
+
while (!scope) {
|
|
44
|
+
const input = await ask('Installation scope: 1. Project (current project), 2. Global (all projects) [1] (q cancels): ');
|
|
45
|
+
if (input === null || ['q', 'cancel'].includes(input.toLowerCase())) return null;
|
|
46
|
+
if (['', '1', 'project'].includes(input)) scope = 'project';
|
|
47
|
+
else if (['2', 'global'].includes(input)) scope = 'global';
|
|
48
|
+
else console.log('Choose 1 (project) or 2 (global).');
|
|
49
|
+
}
|
|
50
|
+
return { agents, scope };
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async function confirm(plan) {
|
|
54
|
+
console.log(`\nInstallation scope: ${plan.scope}`);
|
|
55
|
+
for (const target of plan.targets) {
|
|
56
|
+
console.log(` ${target.agents.join(', ')}: ${target.skillsDirectory}`);
|
|
57
|
+
if (target.commandsDirectory) console.log(` Commands: ${target.commandsDirectory}`);
|
|
58
|
+
}
|
|
59
|
+
if (plan.conflicts.length) console.log(`${plan.conflicts.length} existing assets will be preserved in backups before replacement.`);
|
|
60
|
+
console.log('Includes all skills and shared references. Plugin hooks require native plugin registration.');
|
|
61
|
+
return session(async ask => {
|
|
62
|
+
const answer = await ask('Install these files? [y/N]: ');
|
|
63
|
+
return answer !== null && ['y', 'yes'].includes(answer.toLowerCase());
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
module.exports = { choose, confirm };
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
description = "Implement tasks incrementally — build, test, verify, commit. Add \"auto\" to run the whole plan in one approved pass."
|
|
2
2
|
|
|
3
3
|
prompt = """
|
|
4
|
-
Invoke the incremental-implementation skill alongside test-driven-development.
|
|
4
|
+
Invoke the i3-incremental-implementation skill alongside i3-test-driven-development.
|
|
5
5
|
|
|
6
6
|
## Modes
|
|
7
7
|
|
|
8
|
-
- `/build` — implement the next pending task, then stop (careful, one slice at a time).
|
|
9
|
-
- `/build auto` — generate the plan if needed, get a single approval, then implement every task without stopping between them.
|
|
8
|
+
- `/i3-build` — implement the next pending task, then stop (careful, one slice at a time).
|
|
9
|
+
- `/i3-build auto` — generate the plan if needed, get a single approval, then implement every task without stopping between them.
|
|
10
10
|
|
|
11
11
|
The arguments select the mode. Treat `auto` (canonical) or `all` as autonomous mode; anything else (or empty) is the default single-task mode. Note: autonomous mode is not faster per task — it runs the same test-driven loop — it only removes the human stepping between tasks.
|
|
12
12
|
|
|
@@ -23,21 +23,21 @@ Pick the next pending task from the plan. Then:
|
|
|
23
23
|
7. Commit with a descriptive message
|
|
24
24
|
8. Mark the task complete and stop
|
|
25
25
|
|
|
26
|
-
## Autonomous: the whole plan (`/build auto`)
|
|
26
|
+
## Autonomous: the whole plan (`/i3-build auto`)
|
|
27
27
|
|
|
28
28
|
Use this once a spec exists and you want to collapse plan + build into one run. It removes the manual stepping between tasks — not the verification. Every task still earns a passing test and its own commit.
|
|
29
29
|
|
|
30
|
-
1. Require a spec. Look only for a spec at a known path: SPEC.md at the repo root, docs/SPEC.md, or a file under spec/. A README or arbitrary doc does NOT count. If none exists, stop and tell the user to run /spec first — do not invent requirements.
|
|
30
|
+
1. Require a spec. Look only for a spec at a known path: SPEC.md at the repo root, docs/SPEC.md, or a file under spec/. A README or arbitrary doc does NOT count. If none exists, stop and tell the user to run /i3-spec first — do not invent requirements.
|
|
31
31
|
2. Establish a clean baseline. Run `git status --porcelain`. If there are uncommitted changes outside the expected planning artifacts (SPEC.md, docs/SPEC.md, spec/*, tasks/plan.md, tasks/todo.md), stop and ask the user to commit, stash, or confirm how to handle them. Autonomous per-task commits must not absorb unrelated local work, or the clean-rollback guarantee breaks.
|
|
32
|
-
3. Plan if needed. If there is no tasks/plan.md, invoke the planning-and-task-breakdown skill to generate one.
|
|
32
|
+
3. Plan if needed. If there is no tasks/plan.md, invoke the i3-planning-and-task-breakdown skill to generate one.
|
|
33
33
|
4. Single checkpoint. Present the full plan and wait for an unambiguous affirmative (e.g. "approve", "go", "yes"). Treat hedged responses ("looks reasonable", "I guess") as NOT approved. This is the only human gate — after approval, run autonomously. If you generated tasks/plan.md, commit it as a single preparatory commit now so it doesn't bleed into the first task's commit.
|
|
34
34
|
5. Execute every task in dependency order. Use each task's declared dependencies; if they aren't explicit, execute in the order the plan lists them. For each task, run the full default loop above (RED → GREEN → regression → build → commit → mark complete). Stage only the files that task touched plus its task-status update — never `git add -A` blindly — and make one commit per task so any point is a clean rollback.
|
|
35
35
|
6. Stop and ask the user (do not push through) when:
|
|
36
|
-
- a test can't be made to pass or the build breaks without an obvious fix → follow the debugging-and-error-recovery skill
|
|
36
|
+
- a test can't be made to pass or the build breaks without an obvious fix → follow the i3-debugging-and-error-recovery skill
|
|
37
37
|
- the spec is ambiguous, or a task needs a decision the spec doesn't cover
|
|
38
|
-
- a task is high-risk or irreversible — auth/permission changes, destructive data migrations, payments, deletions, deploys, anything touching secrets, or anything you can't undo with `git revert` → follow the doubt-driven-development skill and get explicit sign-off before continuing
|
|
39
|
-
After the user resolves a blocker, they re-invoke /build auto — it resumes from the next pending task.
|
|
38
|
+
- a task is high-risk or irreversible — auth/permission changes, destructive data migrations, payments, deletions, deploys, anything touching secrets, or anything you can't undo with `git revert` → follow the i3-doubt-driven-development skill and get explicit sign-off before continuing
|
|
39
|
+
After the user resolves a blocker, they re-invoke /i3-build auto — it resumes from the next pending task.
|
|
40
40
|
7. Summarize at the end: tasks completed, tests added, commits made, and anything skipped, flagged, or left for the user.
|
|
41
41
|
|
|
42
|
-
If any step fails, follow the debugging-and-error-recovery skill.
|
|
42
|
+
If any step fails, follow the i3-debugging-and-error-recovery skill.
|
|
43
43
|
"""
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
description = "Simplify code for clarity and maintainability — reduce complexity without changing behavior"
|
|
2
2
|
|
|
3
3
|
prompt = """
|
|
4
|
-
Invoke the code-simplification skill.
|
|
4
|
+
Invoke the i3-code-simplification skill.
|
|
5
5
|
|
|
6
6
|
Simplify recently changed code (or the specified scope) while preserving exact behavior:
|
|
7
7
|
|
|
@@ -18,5 +18,5 @@ Simplify recently changed code (or the specified scope) while preserving exact b
|
|
|
18
18
|
5. Apply each simplification incrementally — run tests after each change
|
|
19
19
|
6. Verify all tests pass, the build succeeds, and the diff is clean
|
|
20
20
|
|
|
21
|
-
If tests fail after a simplification, revert that change and reconsider. Use `code-review-and-quality` to review the result.
|
|
21
|
+
If tests fail after a simplification, revert that change and reconsider. Use `i3-code-review-and-quality` to review the result.
|
|
22
22
|
"""
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
description = "Define and enforce this project's quality bar — interview, sane defaults, CONSTRAINTS.md"
|
|
2
2
|
|
|
3
3
|
prompt = """
|
|
4
|
-
Invoke the constraint-driven-development skill.
|
|
4
|
+
Invoke the i3-constraint-driven-development skill.
|
|
5
5
|
|
|
6
6
|
$ARGUMENTS
|
|
7
7
|
|
|
@@ -26,7 +26,7 @@ Default behaviour with no arguments: set up constraints for this repository.
|
|
|
26
26
|
7. **Verify.** Run the constraints against the current branch. If anything fails that the user disagrees with, fix the constraint now rather than leaving a gate people will learn to ignore.
|
|
27
27
|
|
|
28
28
|
Sub-commands:
|
|
29
|
-
- `/constraints check` — run the current constraints against this branch and report
|
|
30
|
-
- `/constraints guard` — inspect the diff for a weakened bar: lowered thresholds, skipped or deleted tests, new suppression comments, unfinished stubs, new exceptions
|
|
31
|
-
- `/constraints ratchet` — record today's measured values as the floor that must not fall
|
|
29
|
+
- `/i3-constraints check` — run the current constraints against this branch and report
|
|
30
|
+
- `/i3-constraints guard` — inspect the diff for a weakened bar: lowered thresholds, skipped or deleted tests, new suppression comments, unfinished stubs, new exceptions
|
|
31
|
+
- `/i3-constraints ratchet` — record today's measured values as the floor that must not fall
|
|
32
32
|
"""
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
description = "Break work into small verifiable tasks with acceptance criteria and dependency ordering"
|
|
2
2
|
|
|
3
3
|
prompt = """
|
|
4
|
-
Invoke the planning-and-task-breakdown skill.
|
|
4
|
+
Invoke the i3-planning-and-task-breakdown skill.
|
|
5
5
|
|
|
6
6
|
Read the existing spec (SPEC.md or equivalent) and the relevant codebase sections. Then:
|
|
7
7
|
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
description = "Conduct a five-axis code review — correctness, readability, architecture, security, performance"
|
|
2
2
|
|
|
3
3
|
prompt = """
|
|
4
|
-
Invoke the code-review-and-quality skill.
|
|
4
|
+
Invoke the i3-code-review-and-quality skill.
|
|
5
5
|
|
|
6
6
|
Review the current changes (staged or recent commits) across all five axes:
|
|
7
7
|
|
|
8
8
|
1. **Correctness** — Does it match the spec? Edge cases handled? Tests adequate?
|
|
9
9
|
2. **Readability** — Clear names? Straightforward logic? Well-organized?
|
|
10
10
|
3. **Architecture** — Follows existing patterns? Clean boundaries? Right abstraction level?
|
|
11
|
-
4. **Security** — Input validated? Secrets safe? Auth checked? (Use security-and-hardening skill)
|
|
12
|
-
5. **Performance** — No N+1 queries? No unbounded ops? (Use performance-optimization skill)
|
|
11
|
+
4. **Security** — Input validated? Secrets safe? Auth checked? (Use i3-security-and-hardening skill)
|
|
12
|
+
5. **Performance** — No N+1 queries? No unbounded ops? (Use i3-performance-optimization skill)
|
|
13
13
|
|
|
14
14
|
Categorize findings as Critical, Important, or Suggestion.
|
|
15
15
|
Output a structured review with specific file:line references and fix recommendations.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
description = "Run the pre-launch checklist via parallel fan-out to specialist personas, then synthesize a go/no-go decision"
|
|
2
2
|
|
|
3
3
|
prompt = """
|
|
4
|
-
Invoke the shipping-and-launch skill.
|
|
4
|
+
Invoke the i3-shipping-and-launch skill.
|
|
5
5
|
|
|
6
|
-
`/ship` is a **fan-out orchestrator**. It runs three specialist personas in parallel against the current change, then merges their reports into a single go/no-go decision with a rollback plan. The personas operate independently — no shared state, no ordering — which is what makes parallel execution safe and useful here.
|
|
6
|
+
`/i3-ship` is a **fan-out orchestrator**. It runs three specialist personas in parallel against the current change, then merges their reports into a single go/no-go decision with a rollback plan. The personas operate independently — no shared state, no ordering — which is what makes parallel execution safe and useful here.
|
|
7
7
|
|
|
8
8
|
## Phase A — Parallel fan-out
|
|
9
9
|
|
|
@@ -22,7 +22,7 @@ Constraints (from CLI's subagent model):
|
|
|
22
22
|
- Do not let one persona delegate to another — keep the fan-out flat.
|
|
23
23
|
- For richer multi-agent collaboration where teammates talk to each other instead of just reporting back, see `references/orchestration-patterns.md`.
|
|
24
24
|
|
|
25
|
-
**Persona resolution.** If you've defined your own `code-reviewer`, `security-auditor`, or `test-engineer` in `agents/` or your global configuration, those take precedence over this plugin's versions — `/ship` picks up your customizations automatically. This is intentional: plugin subagents sit at the bottom of the CLI's scope priority table, so user-level definitions win by design.
|
|
25
|
+
**Persona resolution.** If you've defined your own `code-reviewer`, `security-auditor`, or `test-engineer` in `agents/` or your global configuration, those take precedence over this plugin's versions — `/i3-ship` picks up your customizations automatically. This is intentional: plugin subagents sit at the bottom of the CLI's scope priority table, so user-level definitions win by design.
|
|
26
26
|
|
|
27
27
|
## Phase B — Merge in main context
|
|
28
28
|
|
|
@@ -68,5 +68,5 @@ Produce a single output:
|
|
|
68
68
|
2. Personas do not call each other. The main agent merges in Phase B.
|
|
69
69
|
3. The rollback plan is mandatory before any GO decision.
|
|
70
70
|
4. If any persona returns a Critical finding, the default verdict is NO-GO unless the user explicitly accepts the risk.
|
|
71
|
-
5. **Skip the fan-out only if all of the following are true:** the change touches 2 files or fewer, the diff is under 50 lines, and it does not touch auth, payments, data access, or config/env. Otherwise, default to fan-out. `/ship` is designed for production-bound changes — when the blast radius is non-trivial, run the parallel review even if the diff looks small.
|
|
71
|
+
5. **Skip the fan-out only if all of the following are true:** the change touches 2 files or fewer, the diff is under 50 lines, and it does not touch auth, payments, data access, or config/env. Otherwise, default to fan-out. `/i3-ship` is designed for production-bound changes — when the blast radius is non-trivial, run the parallel review even if the diff looks small.
|
|
72
72
|
"""
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
description = "Start spec-driven development — write a structured specification before writing code"
|
|
2
2
|
|
|
3
3
|
prompt = """
|
|
4
|
-
Invoke the spec-driven-development skill.
|
|
4
|
+
Invoke the i3-spec-driven-development skill.
|
|
5
5
|
|
|
6
6
|
Begin by understanding what the user wants to build. Ask clarifying questions about:
|
|
7
7
|
1. The objective and target users
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
description = "Run TDD workflow — write failing tests, implement, verify. For bugs, use the Prove-It pattern."
|
|
2
2
|
|
|
3
3
|
prompt = """
|
|
4
|
-
Invoke the test-driven-development skill.
|
|
4
|
+
Invoke the i3-test-driven-development skill.
|
|
5
5
|
|
|
6
6
|
For new features:
|
|
7
7
|
1. Write tests that describe the expected behavior (they should FAIL)
|
|
@@ -15,5 +15,5 @@ For bug fixes (Prove-It pattern):
|
|
|
15
15
|
4. Confirm the test passes
|
|
16
16
|
5. Run the full test suite for regressions
|
|
17
17
|
|
|
18
|
-
For browser-related issues, also invoke browser-testing-with-devtools to verify with Chrome DevTools MCP.
|
|
18
|
+
For browser-related issues, also invoke i3-browser-testing-with-devtools to verify with Chrome DevTools MCP.
|
|
19
19
|
"""
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
description = "Run a web performance audit via the web-performance-auditor persona"
|
|
2
2
|
|
|
3
3
|
prompt = """
|
|
4
|
-
/webperf targets web applications specifically. Do not use it for utility libraries, CLIs, or server-only code with no browser-facing output.
|
|
4
|
+
/i3-webperf targets web applications specifically. Do not use it for utility libraries, CLIs, or server-only code with no browser-facing output.
|
|
5
5
|
|
|
6
6
|
## Determine the mode
|
|
7
7
|
|