@givolt/i3-composer-agent 0.0.0-stage → 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.
Files changed (231) hide show
  1. package/.agents/plugins/marketplace.json +23 -0
  2. package/.claude/commands/build.md +44 -0
  3. package/.claude/commands/code-simplify.md +22 -0
  4. package/.claude/commands/constraints.md +32 -0
  5. package/.claude/commands/plan.md +18 -0
  6. package/.claude/commands/review.md +16 -0
  7. package/.claude/commands/ship.md +72 -0
  8. package/.claude/commands/spec.md +17 -0
  9. package/.claude/commands/test.md +19 -0
  10. package/.claude/commands/webperf.md +32 -0
  11. package/.claude-plugin/marketplace.json +27 -0
  12. package/.claude-plugin/plugin.json +19 -0
  13. package/.codex-plugin/plugin.json +28 -0
  14. package/.gemini/commands/build.toml +43 -0
  15. package/.gemini/commands/code-simplify.toml +22 -0
  16. package/.gemini/commands/constraints.toml +32 -0
  17. package/.gemini/commands/planning.toml +18 -0
  18. package/.gemini/commands/review.toml +16 -0
  19. package/.gemini/commands/ship.toml +72 -0
  20. package/.gemini/commands/spec.toml +17 -0
  21. package/.gemini/commands/test.toml +19 -0
  22. package/.gemini/commands/webperf.toml +32 -0
  23. package/CHANGELOG.md +23 -0
  24. package/LICENSE +21 -0
  25. package/NOTICE.md +9 -0
  26. package/README.md +117 -2
  27. package/agents/code-reviewer.md +102 -0
  28. package/agents/security-auditor.md +112 -0
  29. package/agents/test-engineer.md +95 -0
  30. package/agents/web-performance-auditor.md +184 -0
  31. package/bin/i3-composer-agent.cjs +122 -0
  32. package/commands/build.toml +43 -0
  33. package/commands/code-simplify.toml +22 -0
  34. package/commands/constraints.toml +32 -0
  35. package/commands/planning.toml +18 -0
  36. package/commands/review.toml +16 -0
  37. package/commands/ship.toml +72 -0
  38. package/commands/spec.toml +17 -0
  39. package/commands/test.toml +19 -0
  40. package/commands/webperf.toml +32 -0
  41. package/docs/adoption-guide.md +129 -0
  42. package/docs/advanced-per-agent-configuration.md +70 -0
  43. package/docs/agents.md +123 -0
  44. package/docs/antigravity-setup.md +128 -0
  45. package/docs/codebuddy-setup.md +41 -0
  46. package/docs/codex-setup.md +34 -0
  47. package/docs/commandcode-setup.md +69 -0
  48. package/docs/comparison.md +131 -0
  49. package/docs/copilot-cli-setup.md +64 -0
  50. package/docs/copilot-setup.md +162 -0
  51. package/docs/cursor-setup.md +225 -0
  52. package/docs/developer-onboarding.md +116 -0
  53. package/docs/gemini-cli-setup.md +133 -0
  54. package/docs/getting-started.md +208 -0
  55. package/docs/opencode-setup.md +259 -0
  56. package/docs/other-hosts.md +7 -0
  57. package/docs/skill-anatomy.md +203 -0
  58. package/docs/windsurf-setup.md +48 -0
  59. package/evals/README.md +101 -0
  60. package/evals/cases/api-and-interface-design.json +45 -0
  61. package/evals/cases/browser-testing-with-devtools.json +44 -0
  62. package/evals/cases/ci-cd-and-automation.json +45 -0
  63. package/evals/cases/code-review-and-quality.json +49 -0
  64. package/evals/cases/code-simplification.json +45 -0
  65. package/evals/cases/constraint-driven-development.json +79 -0
  66. package/evals/cases/context-engineering.json +44 -0
  67. package/evals/cases/debugging-and-error-recovery.json +58 -0
  68. package/evals/cases/deprecation-and-migration.json +52 -0
  69. package/evals/cases/documentation-and-adrs.json +44 -0
  70. package/evals/cases/doubt-driven-development.json +43 -0
  71. package/evals/cases/frontend-ui-engineering.json +52 -0
  72. package/evals/cases/git-workflow-and-versioning.json +47 -0
  73. package/evals/cases/idea-refine.json +43 -0
  74. package/evals/cases/incremental-implementation.json +57 -0
  75. package/evals/cases/interview-me.json +42 -0
  76. package/evals/cases/observability-and-instrumentation.json +44 -0
  77. package/evals/cases/performance-optimization.json +53 -0
  78. package/evals/cases/planning-and-task-breakdown.json +45 -0
  79. package/evals/cases/security-and-hardening.json +53 -0
  80. package/evals/cases/shipping-and-launch.json +56 -0
  81. package/evals/cases/source-driven-development.json +44 -0
  82. package/evals/cases/spec-driven-development.json +72 -0
  83. package/evals/cases/test-driven-development.json +73 -0
  84. package/evals/cases/using-agent-skills.json +44 -0
  85. package/evals/fixtures/api-and-interface-design/service-brief.md +19 -0
  86. package/evals/fixtures/browser-testing-with-devtools/README.md +5 -0
  87. package/evals/fixtures/browser-testing-with-devtools/index.html +24 -0
  88. package/evals/fixtures/browser-testing-with-devtools/server.js +15 -0
  89. package/evals/fixtures/ci-cd-and-automation/package.json +8 -0
  90. package/evals/fixtures/ci-cd-and-automation/src/slug.js +3 -0
  91. package/evals/fixtures/ci-cd-and-automation/test/slug.test.js +9 -0
  92. package/evals/fixtures/code-review-and-quality/user-search.diff +16 -0
  93. package/evals/fixtures/code-simplification/config-parser.js +46 -0
  94. package/evals/fixtures/code-simplification/config-parser.test.js +15 -0
  95. package/evals/fixtures/context-engineering/context-audit.md +15 -0
  96. package/evals/fixtures/debugging-and-error-recovery/pagination.js +8 -0
  97. package/evals/fixtures/debugging-and-error-recovery/pagination.test.js +9 -0
  98. package/evals/fixtures/debugging-and-error-recovery/time-pressure.md +6 -0
  99. package/evals/fixtures/deprecation-and-migration/api-inventory.md +9 -0
  100. package/evals/fixtures/documentation-and-adrs/decision-context.md +16 -0
  101. package/evals/fixtures/doubt-driven-development/migration-plan.md +19 -0
  102. package/evals/fixtures/frontend-ui-engineering/Button.tsx +7 -0
  103. package/evals/fixtures/frontend-ui-engineering/design-system.md +11 -0
  104. package/evals/fixtures/git-workflow-and-versioning/.eval/working-tree.patch +21 -0
  105. package/evals/fixtures/git-workflow-and-versioning/app.js +7 -0
  106. package/evals/fixtures/git-workflow-and-versioning/app.test.js +9 -0
  107. package/evals/fixtures/incremental-implementation/reports.js +7 -0
  108. package/evals/fixtures/incremental-implementation/reports.test.js +12 -0
  109. package/evals/fixtures/incremental-implementation/tasks/plan.md +8 -0
  110. package/evals/fixtures/incremental-implementation-pressure/draft-export.js +17 -0
  111. package/evals/fixtures/incremental-implementation-pressure/scenario.md +9 -0
  112. package/evals/fixtures/observability-and-instrumentation/operations.md +11 -0
  113. package/evals/fixtures/observability-and-instrumentation/payment-retry.js +14 -0
  114. package/evals/fixtures/performance-optimization/benchmark.js +15 -0
  115. package/evals/fixtures/performance-optimization/products.js +14 -0
  116. package/evals/fixtures/planning-and-task-breakdown/notifications-spec.md +18 -0
  117. package/evals/fixtures/security-and-hardening/webhook.js +11 -0
  118. package/evals/fixtures/security-and-hardening/webhook.test.js +13 -0
  119. package/evals/fixtures/shipping-and-launch/authority-pressure.md +6 -0
  120. package/evals/fixtures/shipping-and-launch/launch-status.md +11 -0
  121. package/evals/fixtures/source-driven-development/framework-task.md +10 -0
  122. package/evals/fixtures/spec-driven-development/billing-brief.md +16 -0
  123. package/evals/fixtures/spec-driven-development-decomposition/portal-brief.md +22 -0
  124. package/evals/fixtures/test-driven-development/BUG.md +10 -0
  125. package/evals/fixtures/test-driven-development/README.md +28 -0
  126. package/evals/fixtures/test-driven-development/package.json +9 -0
  127. package/evals/fixtures/test-driven-development/src/split.js +8 -0
  128. package/evals/fixtures/test-driven-development/test/split.test.js +13 -0
  129. package/evals/fixtures/test-driven-development-ecosystem/README.md +9 -0
  130. package/evals/fixtures/test-driven-development-ecosystem/ledger.py +15 -0
  131. package/evals/fixtures/test-driven-development-ecosystem/test_ledger.py +19 -0
  132. package/evals/fixtures/using-agent-skills/incident.md +6 -0
  133. package/evals/plugin/code-review-fires/graders/off-by-one.md +7 -0
  134. package/evals/plugin/code-review-fires/graders/severity-labels.md +4 -0
  135. package/evals/plugin/code-review-fires/graders/skill-fired.md +5 -0
  136. package/evals/plugin/code-review-fires/prompt.md +31 -0
  137. package/evals/plugin/code-review-stays-quiet/graders/not-fired.md +8 -0
  138. package/evals/plugin/code-review-stays-quiet/graders/tdd-fired.md +6 -0
  139. package/evals/plugin/code-review-stays-quiet/prompt.md +8 -0
  140. package/evals/plugin/code-review-stays-quiet-on-commit-message/graders/not-fired.md +8 -0
  141. package/evals/plugin/code-review-stays-quiet-on-commit-message/prompt.md +25 -0
  142. package/evals/skill-impact.md +6 -0
  143. package/hooks/SDD-CACHE.md +167 -0
  144. package/hooks/SIMPLIFY-IGNORE.md +91 -0
  145. package/hooks/sdd-cache-post.sh +135 -0
  146. package/hooks/sdd-cache-pre.sh +106 -0
  147. package/hooks/sdd-cache-test.sh +246 -0
  148. package/hooks/session-start-test.sh +47 -0
  149. package/hooks/session-start.sh +33 -0
  150. package/hooks/simplify-ignore-test.sh +476 -0
  151. package/hooks/simplify-ignore.sh +352 -0
  152. package/package.json +89 -4
  153. package/plugin.json +7 -0
  154. package/rebrand/MAINTENANCE.md +112 -0
  155. package/rebrand/NOTICE.md +9 -0
  156. package/rebrand/PR-WORKFLOW.md +34 -0
  157. package/rebrand/UNIFICATION-SPEC.md +33 -0
  158. package/rebrand/VALIDATION.md +28 -0
  159. package/rebrand/VERSIONING.md +32 -0
  160. package/rebrand/apply.cjs +194 -0
  161. package/rebrand/brand.json +13 -0
  162. package/rebrand/catalog.cjs +56 -0
  163. package/rebrand/fork-patches.json +12 -0
  164. package/rebrand/overlay/.github/workflows/test-plugin-install.yml +177 -0
  165. package/rebrand/overlay/CHANGELOG.md +23 -0
  166. package/rebrand/overlay/bin/i3-composer-agent.cjs +122 -0
  167. package/rebrand/overlay/scripts/validate-brand.cjs +44 -0
  168. package/rebrand/overlay/tests/bundle.test.cjs +85 -0
  169. package/rebrand/package.template.json +82 -0
  170. package/rebrand/rebrand.sh +4 -0
  171. package/rebrand/record-upstream.cjs +37 -0
  172. package/rebrand/templates/README.md +86 -0
  173. package/rebrand/templates/codebuddy-setup.md +41 -0
  174. package/rebrand/templates/codex-setup.md +34 -0
  175. package/rebrand/tests/pipeline.test.cjs +185 -0
  176. package/rebrand/upstream.json +171 -0
  177. package/references/accessibility-checklist.md +160 -0
  178. package/references/definition-of-done.md +67 -0
  179. package/references/observability-checklist.md +92 -0
  180. package/references/orchestration-patterns.md +370 -0
  181. package/references/performance-checklist.md +236 -0
  182. package/references/security-checklist.md +248 -0
  183. package/references/testing-patterns.md +235 -0
  184. package/scripts/floor-guard-reference-test.js +291 -0
  185. package/scripts/lib/skill-lint-test.js +650 -0
  186. package/scripts/lib/skill-lint.js +584 -0
  187. package/scripts/run-evals-test.js +623 -0
  188. package/scripts/run-evals.js +638 -0
  189. package/scripts/validate-artifact-paths-test.js +179 -0
  190. package/scripts/validate-artifact-paths.js +128 -0
  191. package/scripts/validate-brand.cjs +44 -0
  192. package/scripts/validate-commands-test.js +216 -0
  193. package/scripts/validate-commands.js +222 -0
  194. package/scripts/validate-reference-links-test.js +495 -0
  195. package/scripts/validate-reference-links.js +187 -0
  196. package/scripts/validate-skills.js +69 -0
  197. package/scripts/validate-versions-test.js +32 -0
  198. package/scripts/validate-versions.js +35 -0
  199. package/skills/api-and-interface-design/SKILL.md +367 -0
  200. package/skills/browser-testing-with-devtools/SKILL.md +317 -0
  201. package/skills/ci-cd-and-automation/SKILL.md +390 -0
  202. package/skills/code-review-and-quality/SKILL.md +398 -0
  203. package/skills/code-simplification/SKILL.md +331 -0
  204. package/skills/constraint-driven-development/SKILL.md +311 -0
  205. package/skills/constraint-driven-development/references/floor-guard.md +182 -0
  206. package/skills/context-engineering/SKILL.md +353 -0
  207. package/skills/debugging-and-error-recovery/SKILL.md +300 -0
  208. package/skills/deprecation-and-migration/SKILL.md +247 -0
  209. package/skills/documentation-and-adrs/SKILL.md +288 -0
  210. package/skills/doubt-driven-development/SKILL.md +243 -0
  211. package/skills/frontend-ui-engineering/SKILL.md +340 -0
  212. package/skills/git-workflow-and-versioning/SKILL.md +355 -0
  213. package/skills/idea-refine/SKILL.md +178 -0
  214. package/skills/idea-refine/examples.md +238 -0
  215. package/skills/idea-refine/frameworks.md +99 -0
  216. package/skills/idea-refine/refinement-criteria.md +113 -0
  217. package/skills/idea-refine/scripts/idea-refine.sh +15 -0
  218. package/skills/incremental-implementation/SKILL.md +249 -0
  219. package/skills/interview-me/SKILL.md +235 -0
  220. package/skills/observability-and-instrumentation/SKILL.md +238 -0
  221. package/skills/performance-optimization/SKILL.md +267 -0
  222. package/skills/performance-optimization/references/optimization-patterns.md +250 -0
  223. package/skills/planning-and-task-breakdown/SKILL.md +257 -0
  224. package/skills/security-and-hardening/SKILL.md +216 -0
  225. package/skills/security-and-hardening/references/hardening-patterns.md +324 -0
  226. package/skills/shipping-and-launch/SKILL.md +330 -0
  227. package/skills/source-driven-development/SKILL.md +216 -0
  228. package/skills/spec-driven-development/SKILL.md +259 -0
  229. package/skills/test-driven-development/SKILL.md +398 -0
  230. package/skills/using-agent-skills/SKILL.md +192 -0
  231. package/tests/bundle.test.cjs +85 -0
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const assert = require('node:assert/strict');
5
+ const fs = require('node:fs');
6
+ const path = require('node:path');
7
+ const root = path.resolve(__dirname, '..');
8
+ const brand = require('../rebrand/brand.json');
9
+ const pkg = require('../package.json');
10
+ const upstream = require('../rebrand/upstream.json');
11
+ const { validateCatalog } = require('../rebrand/catalog.cjs');
12
+ validateCatalog(root, upstream);
13
+ function json(relative) { return JSON.parse(fs.readFileSync(path.join(root, relative), 'utf8')); }
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);
20
+ assert.equal(Object.keys(pkg.bin).length, 1, 'npx must resolve one executable');
21
+ assert.ok(fs.existsSync(path.join(root, pkg.bin[brand.name])));
22
+ for (const relative of ['plugin.json', '.claude-plugin/plugin.json', '.codex-plugin/plugin.json']) {
23
+ assert.equal(json(relative).name, brand.name, `${relative}: inconsistent plugin identity`);
24
+ }
25
+ for (const relative of ['.claude-plugin/marketplace.json', '.agents/plugins/marketplace.json']) {
26
+ const marketplace = json(relative);
27
+ assert.equal(marketplace.name, brand.name);
28
+ assert.equal(marketplace.plugins[0].name, brand.name);
29
+ assert.ok(marketplace.plugins[0].source === './' || marketplace.plugins[0].source.path === './', 'marketplace must load this distribution');
30
+ }
31
+ assert.ok(json('.codex-plugin/plugin.json').interface.shortDescription.length <= 30);
32
+ const skills = fs.readdirSync(path.join(root, 'skills')).filter(name => fs.existsSync(path.join(root, 'skills', name, 'SKILL.md')));
33
+ assert.equal(skills.length, upstream.skills.length, 'brand conversion must preserve the reviewed upstream skills');
34
+ assert.ok(skills.includes('using-agent-skills'), 'meta-skill ID must remain stable');
35
+ const commands = fs.readdirSync(path.join(root, '.claude/commands')).filter(name => name.endsWith('.md'));
36
+ assert.equal(commands.length, upstream.commands.length, 'brand conversion must preserve the reviewed upstream commands');
37
+ for (const command of commands) {
38
+ const body = fs.readFileSync(path.join(root, '.claude/commands', command), 'utf8');
39
+ assert.ok(!body.includes('agent-skills:'), `${command}: stale plugin namespace`);
40
+ for (const match of body.matchAll(/i3-composer-agent:([a-z-]+)/g)) assert.ok(skills.includes(match[1]), `${command}: unknown skill ${match[1]}`);
41
+ }
42
+ for (const relative of pkg.i3ComposerAgent.pluginFiles) assert.ok(fs.existsSync(path.join(root, relative)), `bundle is missing ${relative}`);
43
+ assert.match(fs.readFileSync(path.join(root, 'LICENSE'), 'utf8'), /Copyright \(c\) 2025 Addy Osmani/);
44
+ console.log('Brand identity, package entrypoint, reviewed upstream catalog, and attribution are consistent.');
@@ -0,0 +1,85 @@
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 upstream = require('../rebrand/upstream.json');
11
+ const cli = path.join(root, 'bin/i3-composer-agent.cjs');
12
+ function run(args) { return spawnSync(process.execPath, [cli, ...args], { encoding: 'utf8' }); }
13
+ function workspace(t) {
14
+ const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'i3-agent-bundle-'));
15
+ t.after(() => fs.rmSync(directory, { recursive: true, force: true }));
16
+ return directory;
17
+ }
18
+ test('help and version identify the package without preparing files', () => {
19
+ const help = run(['--help']).stdout;
20
+ assert.match(help, /@givolt\/i3-composer-agent/);
21
+ assert.ok(help.includes(`i3 Composer Agent v${require('../package.json').version}`));
22
+ assert.ok(help.includes(`Based on agent-skills v${upstream.upstreamVersion}`));
23
+ assert.equal(run(['--version']).stdout.trim(), require('../package.json').version);
24
+ });
25
+ test('dry run and invalid arguments leave the target untouched', t => {
26
+ const target = path.join(workspace(t), 'plugin');
27
+ assert.equal(run(['--codex', '--dir', target, '--dry-run']).status, 0);
28
+ assert.equal(fs.existsSync(target), false);
29
+ assert.equal(run(['--codebuddy', '--codex', '--dir', target]).status, 1);
30
+ assert.equal(run(['--extract', '--dir']).status, 1);
31
+ assert.equal(fs.existsSync(target), false);
32
+ });
33
+ test('complete bundle preserves reference links and all host assets at a path with spaces', t => {
34
+ const target = path.join(workspace(t), 'plugin with spaces');
35
+ const result = run(['--codebuddy', '--dir', target]);
36
+ assert.equal(result.status, 0, result.stderr);
37
+ assert.ok(result.stdout.includes(`i3 Composer Agent v${require('../package.json').version}`));
38
+ assert.ok(result.stdout.includes(`Based on agent-skills v${upstream.upstreamVersion}`));
39
+ assert.match(result.stdout, /\/plugin install i3-composer-agent@i3-composer-agent/);
40
+ assert.equal(fs.readdirSync(path.join(target, 'skills')).length, upstream.skills.length);
41
+ assert.equal(fs.readdirSync(path.join(target, '.claude/commands')).length, upstream.commands.length);
42
+ assert.equal(fs.readdirSync(path.join(target, 'agents')).filter(name => name.endsWith('.md')).length, upstream.personas.length);
43
+ assert.equal(JSON.parse(fs.readFileSync(path.join(target, '.codex-plugin/plugin.json'), 'utf8')).name, 'i3-composer-agent');
44
+ const check = spawnSync(process.execPath, [path.join(target, 'scripts/validate-reference-links.js')], { cwd: target, encoding: 'utf8' });
45
+ assert.equal(check.status, 0, check.stdout + check.stderr);
46
+ assert.equal(fs.existsSync(path.join(target, 'AGENTS.md')), false);
47
+ assert.equal(fs.existsSync(path.join(target, 'CLAUDE.md')), false);
48
+ });
49
+ test('existing unrelated files cannot be replaced even with force', t => {
50
+ const target = path.join(workspace(t), 'existing');
51
+ fs.mkdirSync(target);
52
+ fs.writeFileSync(path.join(target, 'plugin.json'), '{"name":"another-plugin"}\n');
53
+ fs.writeFileSync(path.join(target, 'keep.txt'), 'business data');
54
+ assert.equal(run(['--extract', '--dir', target]).status, 1);
55
+ assert.equal(run(['--extract', '--dir', target, '--force']).status, 1);
56
+ assert.equal(fs.readFileSync(path.join(target, 'keep.txt'), 'utf8'), 'business data');
57
+ });
58
+ test('installed packages beneath node_modules remain fully extractable', t => {
59
+ const parent = workspace(t);
60
+ const installed = path.join(parent, 'node_modules', '@givolt', 'i3-composer-agent');
61
+ assert.equal(run(['--extract', '--dir', installed]).status, 0);
62
+ const target = path.join(parent, 'plugin');
63
+ const result = spawnSync(process.execPath, [path.join(installed, 'bin/i3-composer-agent.cjs'), '--extract', '--dir', target], { encoding: 'utf8' });
64
+ assert.equal(result.status, 0, result.stderr);
65
+ assert.equal(JSON.parse(fs.readFileSync(path.join(target, 'package.json'), 'utf8')).name, '@givolt/i3-composer-agent');
66
+ assert.equal(fs.readdirSync(path.join(target, 'skills')).length, upstream.skills.length);
67
+ });
68
+ test('replacement preserves the complete previous bundle in a backup', t => {
69
+ const parent = workspace(t);
70
+ const target = path.join(parent, 'plugin');
71
+ assert.equal(run(['--extract', '--dir', target]).status, 0);
72
+ fs.writeFileSync(path.join(target, 'custom-note.txt'), 'preserve me');
73
+ const result = run(['--extract', '--dir', target, '--force']);
74
+ assert.equal(result.status, 0, result.stderr);
75
+ const backups = fs.readdirSync(parent).filter(name => name.startsWith('plugin.backup-'));
76
+ assert.equal(backups.length, 1);
77
+ assert.equal(fs.readFileSync(path.join(parent, backups[0], 'custom-note.txt'), 'utf8'), 'preserve me');
78
+ assert.equal(fs.existsSync(path.join(target, 'custom-note.txt')), false);
79
+ });
80
+ test('source directories and aliases cannot be overwritten', t => {
81
+ assert.equal(run(['--extract', '--dir', root, '--force']).status, 1);
82
+ const alias = path.join(workspace(t), 'source-alias');
83
+ fs.symlinkSync(root, alias, 'dir');
84
+ assert.equal(run(['--extract', '--dir', alias, '--force']).status, 1);
85
+ });
@@ -0,0 +1,82 @@
1
+ {
2
+ "name": "@givolt/i3-composer-agent",
3
+ "description": "i3 Composer Agent: production-grade engineering skills and lifecycle commands for AI coding agents.",
4
+ "license": "MIT",
5
+ "author": "Givolt",
6
+ "contributors": [
7
+ {
8
+ "name": "Addy Osmani"
9
+ }
10
+ ],
11
+ "bin": {
12
+ "i3-composer-agent": "bin/i3-composer-agent.cjs"
13
+ },
14
+ "engines": {
15
+ "node": ">=20"
16
+ },
17
+ "publishConfig": {
18
+ "access": "public",
19
+ "registry": "https://registry.npmjs.org/"
20
+ },
21
+ "files": [
22
+ "bin/",
23
+ "skills/",
24
+ "references/",
25
+ "agents/",
26
+ "commands/",
27
+ ".claude/commands/",
28
+ ".gemini/commands/",
29
+ ".claude-plugin/",
30
+ ".codex-plugin/",
31
+ ".agents/plugins/",
32
+ "hooks/",
33
+ "docs/",
34
+ "scripts/",
35
+ "evals/",
36
+ "rebrand/",
37
+ "tests/",
38
+ "plugin.json",
39
+ "NOTICE.md",
40
+ "CHANGELOG.md"
41
+ ],
42
+ "scripts": {
43
+ "rebrand": "node rebrand/apply.cjs --apply",
44
+ "rebrand:check": "node rebrand/apply.cjs --check",
45
+ "validate": "node scripts/validate-brand.cjs && node scripts/validate-skills.js && node scripts/validate-versions.js && node scripts/validate-commands.js && node scripts/validate-reference-links.js && node scripts/validate-artifact-paths.js",
46
+ "test": "node --test scripts/*-test.js scripts/lib/*-test.js tests/*.test.cjs rebrand/tests/*.test.cjs",
47
+ "prepack": "npm run validate"
48
+ },
49
+ "keywords": [
50
+ "i3-composer",
51
+ "agent-skills",
52
+ "codebuddy",
53
+ "codex",
54
+ "claude-code"
55
+ ],
56
+ "i3ComposerAgent": {
57
+ "pluginFiles": [
58
+ "bin",
59
+ "skills",
60
+ "references",
61
+ "agents",
62
+ "commands",
63
+ ".claude/commands",
64
+ ".gemini/commands",
65
+ ".claude-plugin",
66
+ ".codex-plugin",
67
+ ".agents/plugins",
68
+ "hooks",
69
+ "docs",
70
+ "scripts",
71
+ "evals",
72
+ "rebrand",
73
+ "tests",
74
+ "plugin.json",
75
+ "package.json",
76
+ "README.md",
77
+ "LICENSE",
78
+ "NOTICE.md",
79
+ "CHANGELOG.md"
80
+ ]
81
+ }
82
+ }
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
4
+ exec node "$ROOT/rebrand/apply.cjs" "${1:---check}"
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const fs = require('node:fs');
5
+ const path = require('node:path');
6
+ const { execFileSync } = require('node:child_process');
7
+ const { describe, runtimeRoots, runtimeFiles } = require('./catalog.cjs');
8
+ const root = path.resolve(__dirname, '..');
9
+ const ref = process.argv[2];
10
+ if (!ref || ref.startsWith('-') || process.argv.length !== 3) {
11
+ console.error('Usage: node rebrand/record-upstream.cjs <reviewed upstream ref>');
12
+ process.exit(1);
13
+ }
14
+ try {
15
+ const git = args => execFileSync('git', args, { cwd: root, encoding: 'utf8', maxBuffer: 16 * 1024 * 1024 });
16
+ const commit = git(['rev-parse', '--verify', '--end-of-options', `${ref}^{commit}`]).trim();
17
+ const entries = git(['ls-tree', '-rz', commit, '--', ...runtimeRoots, ...runtimeFiles]).split('\0').filter(Boolean);
18
+ const blobs = new Map(entries.filter(line => /^100\d+ blob /.test(line)).map(line => {
19
+ const [metadata, file] = line.split('\t');
20
+ return [file, metadata.split(' ')[2]];
21
+ }));
22
+ const read = file => git(['cat-file', 'blob', blobs.get(file)]);
23
+ const snapshot = {
24
+ upstreamCommit: commit,
25
+ upstreamVersion: JSON.parse(read('plugin.json')).version,
26
+ ...describe([...blobs.keys()], read),
27
+ };
28
+ fs.writeFileSync(path.join(__dirname, 'upstream.json'), JSON.stringify(snapshot, null, 2) + '\n');
29
+ const brandFile = path.join(__dirname, 'brand.json');
30
+ const brand = JSON.parse(fs.readFileSync(brandFile, 'utf8'));
31
+ brand.upstreamCommit = commit;
32
+ fs.writeFileSync(brandFile, JSON.stringify(brand, null, 2) + '\n');
33
+ console.log(JSON.stringify({ commit, version: snapshot.upstreamVersion, skills: snapshot.skills.length, commands: snapshot.commands.length }));
34
+ } catch (error) {
35
+ console.error(error.message);
36
+ process.exitCode = 1;
37
+ }
@@ -0,0 +1,86 @@
1
+ # i3 Composer Agent v{{RELEASE_VERSION}}
2
+
3
+ **Based on agent-skills v{{UPSTREAM_VERSION}}**
4
+
5
+ **Intelligence. Integration. Innovation.**
6
+
7
+ Engineering skills, lifecycle commands, and specialist personas for AI coding agents.
8
+ Based on [Agent Skills](https://github.com/addyosmani/agent-skills) by Addy Osmani
9
+ (MIT). See [NOTICE.md](NOTICE.md) for attribution.
10
+
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
+
14
+ ## Prepare the complete plugin
15
+
16
+ Run in the project where you want to prepare the plugin:
17
+
18
+ ```bash
19
+ npx @givolt/i3-composer-agent --codebuddy
20
+ # Other hosts:
21
+ npx @givolt/i3-composer-agent --codex
22
+ npx @givolt/i3-composer-agent --claude
23
+ ```
24
+
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).
31
+
32
+ CodeBuddy / Claude Code:
33
+
34
+ ```text
35
+ /plugin marketplace add ./i3-composer-agent
36
+ /plugin install i3-composer-agent@i3-composer-agent
37
+ ```
38
+
39
+ Codex:
40
+
41
+ ```bash
42
+ codex plugin marketplace add ./i3-composer-agent
43
+ codex plugin add i3-composer-agent@i3-composer-agent
44
+ ```
45
+
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.
49
+
50
+ ## Commands
51
+
52
+ Hosts supporting Claude-compatible plugin commands load these workflows:
53
+
54
+ | Command | Description |
55
+ | --- | --- |
56
+ {{COMMAND_TABLE}}
57
+
58
+ `/i3-composer-agent:build auto` runs the existing approved-plan workflow.
59
+
60
+ ## Skills
61
+
62
+ | Skill | Description |
63
+ | --- | --- |
64
+ {{SKILL_TABLE}}
65
+
66
+ ## Bundle options
67
+
68
+ ```bash
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
72
+ ```
73
+
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
78
+
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.
83
+
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,41 @@
1
+ # Using i3 Composer Agent with CodeBuddy
2
+
3
+ Prepare the complete plugin inside the project where you want to use it:
4
+
5
+ ```bash
6
+ npx @givolt/i3-composer-agent --codebuddy
7
+ ```
8
+
9
+ In the CodeBuddy chat, register the prepared directory and install the plugin:
10
+
11
+ ```text
12
+ /plugin marketplace add ./i3-composer-agent
13
+ /plugin install i3-composer-agent@i3-composer-agent
14
+ ```
15
+
16
+ Use the absolute directory printed by the CLI if CodeBuddy has a different
17
+ working directory. Choose the intended installation scope in CodeBuddy's native
18
+ plugin manager. Reload plugins or start a new session after installation.
19
+
20
+ CodeBuddy supports the existing `.claude-plugin/plugin.json` compatibility
21
+ manifest. It declares `.claude/commands/` and `commands/`, preserving the nine
22
+ original lifecycle commands and their workflow content.
23
+
24
+ ```text
25
+ /i3-composer-agent:spec
26
+ /i3-composer-agent:plan
27
+ /i3-composer-agent:build
28
+ /i3-composer-agent:build auto
29
+ /i3-composer-agent:review
30
+ /i3-composer-agent:ship
31
+ ```
32
+
33
+ Skill IDs, persona names, artifact paths, and workflow gates retain their
34
+ upstream behavior. The plugin namespace changes to `i3-composer-agent`.
35
+
36
+ The bundle includes all skills and shared `references/`. Installing individual
37
+ skills is a different distribution method and does not install the command
38
+ wrappers or persona definitions.
39
+
40
+ The CLI prepares files and prints registration commands. Actual host discovery
41
+ and model execution should be verified after registering the plugin.
@@ -0,0 +1,34 @@
1
+ # Using i3 Composer Agent with Codex
2
+
3
+ Prepare the complete plugin inside the project where you want to use it:
4
+
5
+ ```bash
6
+ npx @givolt/i3-composer-agent --codex
7
+ ```
8
+
9
+ The CLI copies a persistent `./i3-composer-agent/` bundle and prints these
10
+ native registration commands. Run them to enable the plugin:
11
+
12
+ ```bash
13
+ codex plugin marketplace add ./i3-composer-agent
14
+ codex plugin add i3-composer-agent@i3-composer-agent
15
+ ```
16
+
17
+ Start a new Codex session after registration. All 25 existing skills keep their
18
+ original IDs. In CLI/IDE, use `/skills` or `$spec-driven-development`; in chat,
19
+ explicitly request the relevant skill from i3 Composer Agent.
20
+
21
+ The adapter in `.codex-plugin/plugin.json` points at the unchanged `skills/`
22
+ layout. Shared checklists remain under `references/`, so skill-relative links
23
+ resolve inside the complete plugin bundle.
24
+
25
+ The short lifecycle commands (`/spec`, `/plan`, `/build`, `/ship`) remain
26
+ available in hosts that load the Claude-compatible command manifest. Codex
27
+ lifecycle-command adaptation is separate from this brand conversion. Native
28
+ Codex `/plan` switches planning mode; it is not the plugin's planning wrapper.
29
+
30
+ Do not preload `using-agent-skills/SKILL.md` into always-on context: Codex routes
31
+ skills natively. The meta-skill can remain installed and explicitly invoked.
32
+
33
+ For local source testing, replace `./i3-composer-agent` above with the absolute
34
+ path to the branded checkout. The CLI does not modify existing plugin settings.
@@ -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
+ });