@c0x12c/ai-toolkit 1.15.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 (255) hide show
  1. package/.claude-plugin/marketplace.json +16 -0
  2. package/.claude-plugin/plugin.json +12 -0
  3. package/README.md +439 -0
  4. package/VERSION +1 -0
  5. package/agents/design-critic.md +127 -0
  6. package/agents/idea-killer.md +72 -0
  7. package/agents/infrastructure-expert.md +49 -0
  8. package/agents/micronaut-backend-expert.md +45 -0
  9. package/agents/phase-reviewer.md +150 -0
  10. package/agents/research-planner.md +70 -0
  11. package/agents/solution-architect-cto.md +49 -0
  12. package/agents/sre-architect.md +49 -0
  13. package/agents/team-coordinator.md +111 -0
  14. package/bin/cli.js +780 -0
  15. package/claude-md/00-header.md +39 -0
  16. package/claude-md/01-core.md +105 -0
  17. package/claude-md/05-database.md +20 -0
  18. package/claude-md/11-backend-micronaut.md +19 -0
  19. package/claude-md/20-frontend-react.md +44 -0
  20. package/claude-md/25-ux-design.md +56 -0
  21. package/claude-md/30-infrastructure.md +24 -0
  22. package/claude-md/30-project-mgmt.md +119 -0
  23. package/claude-md/40-product.md +39 -0
  24. package/claude-md/50-ops.md +34 -0
  25. package/claude-md/60-research.md +27 -0
  26. package/claude-md/90-footer.md +21 -0
  27. package/commands/spartan/brainstorm.md +134 -0
  28. package/commands/spartan/brownfield.md +157 -0
  29. package/commands/spartan/build.md +435 -0
  30. package/commands/spartan/careful.md +94 -0
  31. package/commands/spartan/commit-message.md +112 -0
  32. package/commands/spartan/content.md +17 -0
  33. package/commands/spartan/context-save.md +161 -0
  34. package/commands/spartan/contribute.md +140 -0
  35. package/commands/spartan/daily.md +42 -0
  36. package/commands/spartan/debug.md +308 -0
  37. package/commands/spartan/deep-dive.md +55 -0
  38. package/commands/spartan/deploy.md +207 -0
  39. package/commands/spartan/e2e.md +264 -0
  40. package/commands/spartan/env-setup.md +166 -0
  41. package/commands/spartan/epic.md +199 -0
  42. package/commands/spartan/fe-review.md +181 -0
  43. package/commands/spartan/figma-to-code.md +260 -0
  44. package/commands/spartan/forensics.md +46 -0
  45. package/commands/spartan/freeze.md +84 -0
  46. package/commands/spartan/fundraise.md +53 -0
  47. package/commands/spartan/gate-review.md +229 -0
  48. package/commands/spartan/gsd-upgrade.md +376 -0
  49. package/commands/spartan/guard.md +42 -0
  50. package/commands/spartan/init-project.md +178 -0
  51. package/commands/spartan/init-rules.md +298 -0
  52. package/commands/spartan/interview.md +154 -0
  53. package/commands/spartan/kickoff.md +73 -0
  54. package/commands/spartan/kotlin-service.md +109 -0
  55. package/commands/spartan/lean-canvas.md +222 -0
  56. package/commands/spartan/lint-rules.md +122 -0
  57. package/commands/spartan/map-codebase.md +124 -0
  58. package/commands/spartan/migration.md +82 -0
  59. package/commands/spartan/next-app.md +317 -0
  60. package/commands/spartan/next-feature.md +212 -0
  61. package/commands/spartan/onboard.md +326 -0
  62. package/commands/spartan/outreach.md +16 -0
  63. package/commands/spartan/phase.md +142 -0
  64. package/commands/spartan/pitch.md +18 -0
  65. package/commands/spartan/plan.md +210 -0
  66. package/commands/spartan/pr-ready.md +202 -0
  67. package/commands/spartan/project.md +106 -0
  68. package/commands/spartan/qa.md +222 -0
  69. package/commands/spartan/research.md +254 -0
  70. package/commands/spartan/review.md +132 -0
  71. package/commands/spartan/scan-rules.md +173 -0
  72. package/commands/spartan/sessions.md +143 -0
  73. package/commands/spartan/spec.md +131 -0
  74. package/commands/spartan/startup.md +257 -0
  75. package/commands/spartan/team.md +570 -0
  76. package/commands/spartan/teardown.md +161 -0
  77. package/commands/spartan/testcontainer.md +97 -0
  78. package/commands/spartan/tf-cost.md +123 -0
  79. package/commands/spartan/tf-deploy.md +116 -0
  80. package/commands/spartan/tf-drift.md +100 -0
  81. package/commands/spartan/tf-import.md +107 -0
  82. package/commands/spartan/tf-module.md +121 -0
  83. package/commands/spartan/tf-plan.md +100 -0
  84. package/commands/spartan/tf-review.md +106 -0
  85. package/commands/spartan/tf-scaffold.md +109 -0
  86. package/commands/spartan/tf-security.md +147 -0
  87. package/commands/spartan/think.md +221 -0
  88. package/commands/spartan/unfreeze.md +13 -0
  89. package/commands/spartan/update.md +134 -0
  90. package/commands/spartan/ux.md +1233 -0
  91. package/commands/spartan/validate.md +193 -0
  92. package/commands/spartan/web-to-prd.md +706 -0
  93. package/commands/spartan/workstreams.md +109 -0
  94. package/commands/spartan/write.md +16 -0
  95. package/commands/spartan.md +386 -0
  96. package/frameworks/00-framework-comparison-guide.md +317 -0
  97. package/frameworks/01-lean-canvas.md +196 -0
  98. package/frameworks/02-design-sprint.md +304 -0
  99. package/frameworks/03-foundation-sprint.md +337 -0
  100. package/frameworks/04-business-model-canvas.md +391 -0
  101. package/frameworks/05-customer-development.md +426 -0
  102. package/frameworks/06-jobs-to-be-done.md +358 -0
  103. package/frameworks/07-mom-test.md +392 -0
  104. package/frameworks/08-value-proposition-canvas.md +488 -0
  105. package/frameworks/09-javelin-board.md +428 -0
  106. package/frameworks/10-build-measure-learn.md +467 -0
  107. package/frameworks/11-mvp-approaches.md +533 -0
  108. package/frameworks/think-before-build.md +593 -0
  109. package/lib/assembler.js +197 -0
  110. package/lib/assembler.test.js +159 -0
  111. package/lib/detector.js +166 -0
  112. package/lib/detector.test.js +221 -0
  113. package/lib/packs.js +16 -0
  114. package/lib/resolver.js +272 -0
  115. package/lib/resolver.test.js +298 -0
  116. package/lib/worktree.sh +104 -0
  117. package/package.json +50 -0
  118. package/packs/backend-micronaut.yaml +35 -0
  119. package/packs/backend-nodejs.yaml +15 -0
  120. package/packs/backend-python.yaml +15 -0
  121. package/packs/core.yaml +37 -0
  122. package/packs/database.yaml +21 -0
  123. package/packs/frontend-react.yaml +24 -0
  124. package/packs/infrastructure.yaml +40 -0
  125. package/packs/ops.yaml +16 -0
  126. package/packs/packs.compiled.json +371 -0
  127. package/packs/product.yaml +22 -0
  128. package/packs/project-mgmt.yaml +24 -0
  129. package/packs/research.yaml +39 -0
  130. package/packs/shared-backend.yaml +14 -0
  131. package/packs/ux-design.yaml +21 -0
  132. package/rules/backend-micronaut/API_DESIGN.md +313 -0
  133. package/rules/backend-micronaut/BATCH_PROCESSING.md +92 -0
  134. package/rules/backend-micronaut/CONTROLLERS.md +388 -0
  135. package/rules/backend-micronaut/KOTLIN.md +414 -0
  136. package/rules/backend-micronaut/RETROFIT_PLACEMENT.md +290 -0
  137. package/rules/backend-micronaut/SERVICES_AND_BEANS.md +325 -0
  138. package/rules/core/NAMING_CONVENTIONS.md +208 -0
  139. package/rules/core/SKILL_AUTHORING.md +174 -0
  140. package/rules/core/TIMEZONE.md +316 -0
  141. package/rules/database/ORM_AND_REPO.md +289 -0
  142. package/rules/database/SCHEMA.md +146 -0
  143. package/rules/database/TRANSACTIONS.md +311 -0
  144. package/rules/frontend-react/FRONTEND.md +344 -0
  145. package/rules/infrastructure/MODULES.md +260 -0
  146. package/rules/infrastructure/NAMING.md +196 -0
  147. package/rules/infrastructure/PROVIDERS.md +309 -0
  148. package/rules/infrastructure/SECURITY.md +310 -0
  149. package/rules/infrastructure/STATE_AND_BACKEND.md +237 -0
  150. package/rules/infrastructure/STRUCTURE.md +234 -0
  151. package/rules/infrastructure/VARIABLES.md +285 -0
  152. package/rules/shared-backend/ARCHITECTURE.md +46 -0
  153. package/rules/ux-design/DESIGN_PROCESS.md +176 -0
  154. package/skills/api-endpoint-creator/SKILL.md +455 -0
  155. package/skills/api-endpoint-creator/error-handling-guide.md +244 -0
  156. package/skills/api-endpoint-creator/examples.md +522 -0
  157. package/skills/api-endpoint-creator/testing-patterns.md +302 -0
  158. package/skills/article-writing/SKILL.md +109 -0
  159. package/skills/article-writing/examples.md +59 -0
  160. package/skills/backend-api-design/SKILL.md +84 -0
  161. package/skills/backend-api-design/code-patterns.md +138 -0
  162. package/skills/brainstorm/SKILL.md +95 -0
  163. package/skills/browser-qa/SKILL.md +87 -0
  164. package/skills/browser-qa/playwright-snippets.md +110 -0
  165. package/skills/ci-cd-patterns/SKILL.md +108 -0
  166. package/skills/ci-cd-patterns/workflows.md +149 -0
  167. package/skills/competitive-teardown/SKILL.md +93 -0
  168. package/skills/competitive-teardown/example-analysis.md +50 -0
  169. package/skills/content-engine/SKILL.md +131 -0
  170. package/skills/content-engine/examples.md +72 -0
  171. package/skills/database-patterns/SKILL.md +72 -0
  172. package/skills/database-patterns/code-templates.md +114 -0
  173. package/skills/database-table-creator/SKILL.md +141 -0
  174. package/skills/database-table-creator/examples.md +552 -0
  175. package/skills/database-table-creator/kotlin-templates.md +400 -0
  176. package/skills/database-table-creator/migration-template.sql +68 -0
  177. package/skills/database-table-creator/validation-checklist.md +337 -0
  178. package/skills/deep-research/SKILL.md +80 -0
  179. package/skills/design-intelligence/SKILL.md +268 -0
  180. package/skills/design-workflow/SKILL.md +127 -0
  181. package/skills/design-workflow/checklists.md +45 -0
  182. package/skills/idea-validation/SKILL.md +129 -0
  183. package/skills/idea-validation/example-report.md +50 -0
  184. package/skills/investor-materials/SKILL.md +122 -0
  185. package/skills/investor-materials/example-outline.md +70 -0
  186. package/skills/investor-outreach/SKILL.md +112 -0
  187. package/skills/investor-outreach/examples.md +76 -0
  188. package/skills/kotlin-best-practices/SKILL.md +58 -0
  189. package/skills/kotlin-best-practices/code-patterns.md +132 -0
  190. package/skills/market-research/SKILL.md +99 -0
  191. package/skills/security-checklist/SKILL.md +65 -0
  192. package/skills/security-checklist/audit-reference.md +95 -0
  193. package/skills/service-debugging/SKILL.md +116 -0
  194. package/skills/service-debugging/common-issues.md +65 -0
  195. package/skills/startup-pipeline/SKILL.md +152 -0
  196. package/skills/terraform-best-practices/SKILL.md +244 -0
  197. package/skills/terraform-module-creator/SKILL.md +284 -0
  198. package/skills/terraform-review/SKILL.md +222 -0
  199. package/skills/terraform-security-audit/SKILL.md +280 -0
  200. package/skills/terraform-service-scaffold/SKILL.md +574 -0
  201. package/skills/testing-strategies/SKILL.md +116 -0
  202. package/skills/testing-strategies/examples.md +103 -0
  203. package/skills/testing-strategies/integration-test-setup.md +71 -0
  204. package/skills/ui-ux-pro-max/SKILL.md +238 -0
  205. package/skills/ui-ux-pro-max/data/charts.csv +26 -0
  206. package/skills/ui-ux-pro-max/data/colors.csv +97 -0
  207. package/skills/ui-ux-pro-max/data/icons.csv +101 -0
  208. package/skills/ui-ux-pro-max/data/landing.csv +31 -0
  209. package/skills/ui-ux-pro-max/data/products.csv +97 -0
  210. package/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  211. package/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  212. package/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  213. package/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  214. package/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  215. package/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  216. package/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  217. package/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  218. package/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  219. package/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  220. package/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  221. package/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  222. package/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  223. package/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  224. package/skills/ui-ux-pro-max/data/styles.csv +68 -0
  225. package/skills/ui-ux-pro-max/data/typography.csv +58 -0
  226. package/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  227. package/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  228. package/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  229. package/skills/ui-ux-pro-max/python-setup.md +146 -0
  230. package/skills/ui-ux-pro-max/scripts/core.py +253 -0
  231. package/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
  232. package/skills/ui-ux-pro-max/scripts/search.py +114 -0
  233. package/skills/web-to-prd/SKILL.md +478 -0
  234. package/templates/build-config.yaml +44 -0
  235. package/templates/commands-config.yaml +55 -0
  236. package/templates/competitor-analysis.md +60 -0
  237. package/templates/content/AGENT_TEMPLATE.md +47 -0
  238. package/templates/content/COMMAND_TEMPLATE.md +27 -0
  239. package/templates/content/RULE_TEMPLATE.md +40 -0
  240. package/templates/content/SKILL_TEMPLATE.md +41 -0
  241. package/templates/design-config.md +105 -0
  242. package/templates/design-doc.md +207 -0
  243. package/templates/epic.md +100 -0
  244. package/templates/feature-spec.md +181 -0
  245. package/templates/idea-canvas.md +47 -0
  246. package/templates/implementation-plan.md +159 -0
  247. package/templates/prd-template.md +86 -0
  248. package/templates/preamble.md +89 -0
  249. package/templates/project-readme.md +35 -0
  250. package/templates/quality-gates.md +230 -0
  251. package/templates/spartan-config.yaml +164 -0
  252. package/templates/user-interview.md +69 -0
  253. package/templates/validation-checklist.md +108 -0
  254. package/templates/workflow-backend-micronaut.md +409 -0
  255. package/templates/workflow-frontend-react.md +233 -0
@@ -0,0 +1,298 @@
1
+ // Spartan AI Toolkit — Resolver Tests
2
+ // Run: node --test toolkit/lib/resolver.test.js
3
+
4
+ import { describe, it } from 'node:test';
5
+ import assert from 'node:assert/strict';
6
+ import { resolve, detectCycles, resolveAliases, toPacks, validatePack, loadExternalPacks } from './resolver.js';
7
+ import { mkdirSync, writeFileSync, rmSync } from 'node:fs';
8
+ import { join } from 'node:path';
9
+
10
+ // Helper: create a minimal manifest map
11
+ function makeManifests(defs) {
12
+ const m = new Map();
13
+ for (const [name, opts] of Object.entries(defs)) {
14
+ m.set(name, {
15
+ name,
16
+ description: `${name} pack`,
17
+ priority: opts.priority ?? 999,
18
+ hidden: opts.hidden ?? false,
19
+ depends: opts.depends ?? [],
20
+ commands: opts.commands ?? [],
21
+ rules: opts.rules ?? [],
22
+ skills: opts.skills ?? [],
23
+ agents: opts.agents ?? [],
24
+ 'claude-sections': opts.claudeSections ?? [],
25
+ });
26
+ }
27
+ return m;
28
+ }
29
+
30
+ const testManifests = makeManifests({
31
+ core: { priority: 0 },
32
+ database: { priority: 5, hidden: true },
33
+ 'shared-backend': { priority: 6, hidden: true },
34
+ 'backend-micronaut': { priority: 11, depends: ['database', 'shared-backend'], commands: ['kotlin-service'] },
35
+ 'frontend-react': { priority: 20 },
36
+ product: { priority: 40 },
37
+ research: { priority: 60, depends: ['product'] },
38
+ });
39
+
40
+ describe('resolve', () => {
41
+ it('basic resolve — backend-micronaut includes deps + core', () => {
42
+ const result = resolve(['backend-micronaut'], testManifests);
43
+ assert.ok(result.includes('core'));
44
+ assert.ok(result.includes('database'));
45
+ assert.ok(result.includes('shared-backend'));
46
+ assert.ok(result.includes('backend-micronaut'));
47
+ });
48
+
49
+ it('no duplicates — two packs sharing a dep', () => {
50
+ // Both backend-micronaut and a hypothetical other pack could share database
51
+ const result = resolve(['backend-micronaut', 'database'], testManifests);
52
+ const counts = {};
53
+ for (const p of result) counts[p] = (counts[p] || 0) + 1;
54
+ for (const [name, count] of Object.entries(counts)) {
55
+ assert.equal(count, 1, `${name} appears ${count} times`);
56
+ }
57
+ });
58
+
59
+ it('priority ordering — resolved packs sorted by priority', () => {
60
+ const result = resolve(['backend-micronaut', 'research'], testManifests);
61
+ for (let i = 1; i < result.length; i++) {
62
+ const prevPriority = testManifests.get(result[i - 1])?.priority ?? 999;
63
+ const currPriority = testManifests.get(result[i])?.priority ?? 999;
64
+ assert.ok(prevPriority <= currPriority, `${result[i - 1]} (${prevPriority}) should come before ${result[i]} (${currPriority})`);
65
+ }
66
+ });
67
+
68
+ it('core always first — no matter what you pick', () => {
69
+ const result = resolve(['research'], testManifests);
70
+ assert.equal(result[0], 'core');
71
+ });
72
+
73
+ it('unknown pack — throws clear error', () => {
74
+ assert.throws(
75
+ () => resolve(['nonexistent'], testManifests),
76
+ { message: "Unknown pack: 'nonexistent'" }
77
+ );
78
+ });
79
+
80
+ it('research pulls product as dependency', () => {
81
+ const result = resolve(['research'], testManifests);
82
+ assert.ok(result.includes('product'));
83
+ assert.ok(result.includes('research'));
84
+ });
85
+ });
86
+
87
+ describe('detectCycles', () => {
88
+ it('no cycles — passes silently', () => {
89
+ assert.doesNotThrow(() => detectCycles(testManifests));
90
+ });
91
+
92
+ it('cycle detection — A depends on B, B depends on A', () => {
93
+ const cyclic = makeManifests({
94
+ core: { priority: 0 },
95
+ a: { priority: 1, depends: ['b'] },
96
+ b: { priority: 2, depends: ['a'] },
97
+ });
98
+ assert.throws(
99
+ () => detectCycles(cyclic),
100
+ /Cycle detected/
101
+ );
102
+ });
103
+ });
104
+
105
+ describe('resolveAliases', () => {
106
+ it('maps backend to backend-micronaut', () => {
107
+ const { resolved, warnings } = resolveAliases(['backend', 'product']);
108
+ assert.deepEqual(resolved, ['backend-micronaut', 'product']);
109
+ assert.equal(warnings.length, 1);
110
+ assert.ok(warnings[0].includes('backend-micronaut'));
111
+ });
112
+
113
+ it('maps frontend to frontend-react', () => {
114
+ const { resolved } = resolveAliases(['frontend']);
115
+ assert.deepEqual(resolved, ['frontend-react']);
116
+ });
117
+
118
+ it('passes through unknown names unchanged', () => {
119
+ const { resolved, warnings } = resolveAliases(['product', 'ops']);
120
+ assert.deepEqual(resolved, ['product', 'ops']);
121
+ assert.equal(warnings.length, 0);
122
+ });
123
+ });
124
+
125
+ describe('toPacks', () => {
126
+ it('converts manifests to PACKS format', () => {
127
+ const { PACKS, PACK_ORDER } = toPacks(testManifests);
128
+ assert.ok(PACKS.core);
129
+ assert.ok(PACKS['backend-micronaut']);
130
+ assert.equal(PACKS['backend-micronaut'].description, 'backend-micronaut pack');
131
+ assert.deepEqual(PACKS['backend-micronaut'].depends, ['database', 'shared-backend']);
132
+ assert.equal(PACK_ORDER[0], 'core');
133
+ });
134
+
135
+ it('PACK_ORDER sorted by priority', () => {
136
+ const { PACK_ORDER } = toPacks(testManifests);
137
+ assert.equal(PACK_ORDER[0], 'core');
138
+ const idx = (name) => PACK_ORDER.indexOf(name);
139
+ assert.ok(idx('database') < idx('backend-micronaut'));
140
+ assert.ok(idx('product') < idx('research'));
141
+ });
142
+ });
143
+
144
+ // ── Test fixtures for validatePack / loadExternalPacks ──────────
145
+ const TMP = join(import.meta.dirname, '..', '.test-tmp-resolver');
146
+
147
+ function setupExternal() {
148
+ rmSync(TMP, { recursive: true, force: true });
149
+ mkdirSync(TMP, { recursive: true });
150
+ }
151
+
152
+ function cleanupExternal() {
153
+ rmSync(TMP, { recursive: true, force: true });
154
+ }
155
+
156
+ describe('validatePack', () => {
157
+ it('passes for a valid manifest', () => {
158
+ const manifest = {
159
+ name: 'my-pack',
160
+ description: 'A test pack',
161
+ commands: [],
162
+ rules: [],
163
+ skills: [],
164
+ agents: [],
165
+ };
166
+ const result = validatePack(manifest, TMP, new Set());
167
+ assert.ok(result.valid, `errors: ${result.errors.join(', ')}`);
168
+ assert.equal(result.errors.length, 0);
169
+ });
170
+
171
+ it('fails when name is missing', () => {
172
+ const manifest = { description: 'No name' };
173
+ const result = validatePack(manifest, TMP, new Set());
174
+ assert.ok(!result.valid);
175
+ assert.ok(result.errors.some(e => e.includes('name')));
176
+ });
177
+
178
+ it('fails when description is missing', () => {
179
+ const manifest = { name: 'no-desc' };
180
+ const result = validatePack(manifest, TMP, new Set());
181
+ assert.ok(!result.valid);
182
+ assert.ok(result.errors.some(e => e.includes('description')));
183
+ });
184
+
185
+ it('fails when name collides with built-in pack', () => {
186
+ const manifest = { name: 'core', description: 'Fake core' };
187
+ const builtins = new Set(['core', 'backend-micronaut']);
188
+ const result = validatePack(manifest, TMP, builtins);
189
+ assert.ok(!result.valid);
190
+ assert.ok(result.errors.some(e => e.includes('collides')));
191
+ });
192
+
193
+ it('fails when name uses wrong format', () => {
194
+ const manifest = { name: 'My_Pack', description: 'Bad name' };
195
+ const result = validatePack(manifest, TMP, new Set());
196
+ assert.ok(!result.valid);
197
+ assert.ok(result.errors.some(e => e.includes('kebab-case')));
198
+ });
199
+
200
+ it('fails when dependency references unknown pack', () => {
201
+ const manifest = {
202
+ name: 'my-pack',
203
+ description: 'Has bad dep',
204
+ depends: ['nonexistent-pack'],
205
+ };
206
+ const builtins = new Set(['core']);
207
+ const result = validatePack(manifest, TMP, builtins);
208
+ assert.ok(!result.valid);
209
+ assert.ok(result.errors.some(e => e.includes('nonexistent-pack')));
210
+ });
211
+
212
+ it('allows dependency on built-in pack', () => {
213
+ const manifest = {
214
+ name: 'my-pack',
215
+ description: 'Depends on core',
216
+ depends: ['core'],
217
+ };
218
+ const builtins = new Set(['core']);
219
+ const result = validatePack(manifest, TMP, builtins);
220
+ assert.ok(result.valid, `errors: ${result.errors.join(', ')}`);
221
+ });
222
+
223
+ it('warns about missing command files', () => {
224
+ setupExternal();
225
+ try {
226
+ const packDir = join(TMP, 'my-pack');
227
+ mkdirSync(join(packDir, 'commands', 'spartan'), { recursive: true });
228
+ // command file does NOT exist
229
+ const manifest = {
230
+ name: 'my-pack',
231
+ description: 'Missing command',
232
+ commands: ['nonexistent-cmd'],
233
+ };
234
+ const result = validatePack(manifest, packDir, new Set());
235
+ assert.ok(result.warnings.some(w => w.includes('nonexistent-cmd')));
236
+ } finally {
237
+ cleanupExternal();
238
+ }
239
+ });
240
+ });
241
+
242
+ describe('loadExternalPacks', () => {
243
+ it('loads valid external pack from directory', () => {
244
+ setupExternal();
245
+ try {
246
+ const packDir = join(TMP, 'community');
247
+ mkdirSync(join(packDir, 'packs'), { recursive: true });
248
+ writeFileSync(join(packDir, 'packs', 'go-backend.yaml'), `
249
+ name: go-backend
250
+ description: "Go backend rules"
251
+ category: Backend
252
+ priority: 100
253
+ commands: []
254
+ rules: []
255
+ skills: []
256
+ agents: []
257
+ claude-sections: []
258
+ `);
259
+ const builtins = new Set(['core']);
260
+ const result = loadExternalPacks(packDir, builtins);
261
+ assert.ok(result.loaded.has('go-backend'));
262
+ assert.equal(result.errors.length, 0);
263
+ } finally {
264
+ cleanupExternal();
265
+ }
266
+ });
267
+
268
+ it('rejects external pack with name collision', () => {
269
+ setupExternal();
270
+ try {
271
+ const packDir = join(TMP, 'bad-community');
272
+ mkdirSync(join(packDir, 'packs'), { recursive: true });
273
+ writeFileSync(join(packDir, 'packs', 'core.yaml'), `
274
+ name: core
275
+ description: "Fake core"
276
+ `);
277
+ const builtins = new Set(['core']);
278
+ const result = loadExternalPacks(packDir, builtins);
279
+ assert.ok(!result.loaded.has('core'));
280
+ assert.ok(result.errors.length > 0);
281
+ } finally {
282
+ cleanupExternal();
283
+ }
284
+ });
285
+
286
+ it('returns empty when directory has no packs/', () => {
287
+ setupExternal();
288
+ try {
289
+ const packDir = join(TMP, 'empty');
290
+ mkdirSync(packDir, { recursive: true });
291
+ const result = loadExternalPacks(packDir, new Set());
292
+ assert.equal(result.loaded.size, 0);
293
+ assert.equal(result.errors.length, 0);
294
+ } finally {
295
+ cleanupExternal();
296
+ }
297
+ });
298
+ });
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env bash
2
+ # Spartan worktree manager — reusable functions for isolated builds.
3
+ # Modeled after gstack's lib/worktree.ts WorktreeManager class.
4
+ #
5
+ # Usage in build commands:
6
+ # source ~/.spartan/lib/worktree.sh (if installed)
7
+ # spartan_worktree_create "my-feature"
8
+ # spartan_worktree_guard
9
+ # spartan_worktree_cleanup "my-feature"
10
+
11
+ set -euo pipefail
12
+
13
+ # Create an isolated worktree for a feature build.
14
+ # Creates branch, symlinks planning dirs, copies .env.
15
+ #
16
+ # Args:
17
+ # $1 — slug (e.g., "user-auth-flow")
18
+ # $2 — branch prefix (default: "feature")
19
+ #
20
+ # Prints:
21
+ # WORKSPACE=<path>
22
+ # BRANCH=<name>
23
+ spartan_worktree_create() {
24
+ local slug="$1"
25
+ local prefix="${2:-feature}"
26
+ local branch="$prefix/$slug"
27
+ local main_repo
28
+ main_repo="$(git rev-parse --show-toplevel)"
29
+ local workspace="$main_repo/.worktrees/$slug"
30
+
31
+ if [ -d "$workspace" ]; then
32
+ echo "RESUMING: $workspace"
33
+ else
34
+ git worktree add "$workspace" -b "$branch" 2>/dev/null || \
35
+ git worktree add "$workspace" "$branch"
36
+ fi
37
+
38
+ # Symlink planning directories so worktree shares them with main repo
39
+ for dir in .planning .memory .handoff .spartan; do
40
+ [ -d "$main_repo/$dir" ] && [ ! -e "$workspace/$dir" ] && \
41
+ ln -s "$main_repo/$dir" "$workspace/$dir"
42
+ done
43
+
44
+ # Copy .env (not symlinked — worktree may need different values)
45
+ [ -f "$main_repo/.env" ] && [ ! -f "$workspace/.env" ] && \
46
+ cp "$main_repo/.env" "$workspace/.env"
47
+
48
+ # Ensure .worktrees/ is gitignored
49
+ grep -qxF '.worktrees/' "$main_repo/.gitignore" 2>/dev/null || \
50
+ echo '.worktrees/' >> "$main_repo/.gitignore"
51
+
52
+ echo "WORKSPACE=$workspace"
53
+ echo "BRANCH=$branch"
54
+ }
55
+
56
+ # Guard: verify we're inside a worktree, not the main repo.
57
+ # Returns 0 if OK, 1 if in main repo (should stop).
58
+ spartan_worktree_guard() {
59
+ local main_repo
60
+ main_repo="$(git worktree list | head -1 | awk '{print $1}')"
61
+ local current
62
+ current="$(git rev-parse --show-toplevel)"
63
+
64
+ if [ "$main_repo" = "$current" ]; then
65
+ echo "ERROR: Working in main repo, not a worktree. Run spartan_worktree_create first."
66
+ return 1
67
+ else
68
+ echo "OK: Worktree at $current"
69
+ return 0
70
+ fi
71
+ }
72
+
73
+ # Remove a worktree after PR is merged.
74
+ #
75
+ # Args:
76
+ # $1 — slug used during create
77
+ spartan_worktree_cleanup() {
78
+ local slug="$1"
79
+ local main_repo
80
+ main_repo="$(git worktree list | head -1 | awk '{print $1}')"
81
+
82
+ git -C "$main_repo" worktree remove ".worktrees/$slug" --force 2>/dev/null || true
83
+ git -C "$main_repo" worktree prune 2>/dev/null || true
84
+ echo "Cleaned up worktree: $slug"
85
+ }
86
+
87
+ # List all active worktrees.
88
+ spartan_worktree_list() {
89
+ git worktree list 2>/dev/null
90
+ }
91
+
92
+ # Prune stale worktrees from previous runs.
93
+ spartan_worktree_prune() {
94
+ local main_repo
95
+ main_repo="$(git rev-parse --show-toplevel)"
96
+ git worktree prune 2>/dev/null || true
97
+
98
+ local worktree_base="$main_repo/.worktrees"
99
+ if [ -d "$worktree_base" ]; then
100
+ # Remove empty directories left behind
101
+ find "$worktree_base" -maxdepth 1 -type d -empty -delete 2>/dev/null || true
102
+ fi
103
+ echo "Pruned stale worktrees"
104
+ }
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@c0x12c/ai-toolkit",
3
+ "version": "1.15.0",
4
+ "description": "Engineering discipline layer for AI coding agents — commands, rules, skills, agents, and packs for Claude Code",
5
+ "type": "module",
6
+ "bin": {
7
+ "ai-toolkit": "./bin/cli.js"
8
+ },
9
+ "files": [
10
+ "bin/",
11
+ "lib/",
12
+ "commands/",
13
+ "skills/",
14
+ "rules/",
15
+ "agents/",
16
+ "claude-md/",
17
+ "frameworks/",
18
+ "templates/",
19
+ "packs/",
20
+ "VERSION",
21
+ ".claude-plugin/"
22
+ ],
23
+ "keywords": [
24
+ "claude-code",
25
+ "ai-toolkit",
26
+ "cursor",
27
+ "windsurf",
28
+ "codex",
29
+ "copilot",
30
+ "engineering",
31
+ "agent-skills"
32
+ ],
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/c0x12c/ai-toolkit"
37
+ },
38
+ "scripts": {
39
+ "test": "node --test lib/resolver.test.js lib/assembler.test.js lib/detector.test.js",
40
+ "gen:codex": "node scripts/gen-codex-skills.js",
41
+ "check:codex": "node scripts/check-codex-skills.js",
42
+ "prepublishOnly": "node scripts/compile-packs.js && node scripts/gen-codex-skills.js"
43
+ },
44
+ "engines": {
45
+ "node": ">=18"
46
+ },
47
+ "dependencies": {
48
+ "js-yaml": "^4.1.1"
49
+ }
50
+ }
@@ -0,0 +1,35 @@
1
+ name: backend-micronaut
2
+ description: "Kotlin + Micronaut backend"
3
+ category: Backend
4
+ priority: 11
5
+ hidden: false
6
+ depends:
7
+ - database
8
+ - shared-backend
9
+
10
+ commands:
11
+ - kotlin-service
12
+ - review
13
+ - testcontainer
14
+
15
+ rules:
16
+ - backend-micronaut/KOTLIN.md
17
+ - backend-micronaut/CONTROLLERS.md
18
+ - backend-micronaut/SERVICES_AND_BEANS.md
19
+ - backend-micronaut/API_DESIGN.md
20
+ - backend-micronaut/RETROFIT_PLACEMENT.md
21
+ - backend-micronaut/BATCH_PROCESSING.md
22
+
23
+ skills:
24
+ - api-endpoint-creator
25
+ - backend-api-design
26
+ - kotlin-best-practices
27
+ - testing-strategies
28
+ - security-checklist
29
+
30
+ agents:
31
+ - micronaut-backend-expert.md
32
+ - solution-architect-cto.md
33
+
34
+ claude-sections:
35
+ - 11-backend-micronaut.md
@@ -0,0 +1,15 @@
1
+ name: backend-nodejs
2
+ description: "Node.js backend (coming soon)"
3
+ category: Backend
4
+ priority: 12
5
+ hidden: false
6
+ coming-soon: true
7
+ depends:
8
+ - database
9
+ - shared-backend
10
+
11
+ commands: []
12
+ rules: []
13
+ skills: []
14
+ agents: []
15
+ claude-sections: []
@@ -0,0 +1,15 @@
1
+ name: backend-python
2
+ description: "Python backend (coming soon)"
3
+ category: Backend
4
+ priority: 13
5
+ hidden: false
6
+ coming-soon: true
7
+ depends:
8
+ - database
9
+ - shared-backend
10
+
11
+ commands: []
12
+ rules: []
13
+ skills: []
14
+ agents: []
15
+ claude-sections: []
@@ -0,0 +1,37 @@
1
+ name: core
2
+ description: "Core workflow (always installed)"
3
+ category: Core
4
+ priority: 0
5
+ hidden: false
6
+
7
+ commands:
8
+ - spec
9
+ - plan
10
+ - build
11
+ - debug
12
+ - onboard
13
+ - daily
14
+ - context-save
15
+ - update
16
+ - pr-ready
17
+ - init-project
18
+ - init-rules
19
+ - scan-rules
20
+ - lint-rules
21
+ - careful
22
+ - freeze
23
+ - unfreeze
24
+ - guard
25
+ - sessions
26
+ - contribute
27
+ - gate-review
28
+
29
+ rules:
30
+ - core/NAMING_CONVENTIONS.md
31
+ - core/TIMEZONE.md
32
+ - core/SKILL_AUTHORING.md
33
+
34
+ skills: []
35
+ agents:
36
+ - phase-reviewer.md
37
+ claude-sections: []
@@ -0,0 +1,21 @@
1
+ name: database
2
+ description: "Database patterns, migrations, Exposed ORM"
3
+ category: Backend
4
+ priority: 5
5
+ hidden: true
6
+
7
+ commands:
8
+ - migration
9
+
10
+ rules:
11
+ - database/SCHEMA.md
12
+ - database/ORM_AND_REPO.md
13
+ - database/TRANSACTIONS.md
14
+
15
+ skills:
16
+ - database-patterns
17
+ - database-table-creator
18
+
19
+ agents: []
20
+ claude-sections:
21
+ - 05-database.md
@@ -0,0 +1,24 @@
1
+ name: frontend-react
2
+ description: "React + Next.js frontend"
3
+ category: Frontend
4
+ priority: 20
5
+ hidden: false
6
+
7
+ commands:
8
+ - next-app
9
+ - next-feature
10
+ - fe-review
11
+ - figma-to-code
12
+ - e2e
13
+ - qa
14
+
15
+ rules:
16
+ - frontend-react/FRONTEND.md
17
+
18
+ skills:
19
+ - browser-qa
20
+
21
+ agents: []
22
+
23
+ claude-sections:
24
+ - 20-frontend-react.md
@@ -0,0 +1,40 @@
1
+ name: infrastructure
2
+ description: "Terraform + AWS infrastructure"
3
+ category: Ops
4
+ priority: 30
5
+ hidden: false
6
+ depends: []
7
+
8
+ commands:
9
+ - tf-scaffold
10
+ - tf-module
11
+ - tf-review
12
+ - tf-plan
13
+ - tf-deploy
14
+ - tf-import
15
+ - tf-drift
16
+ - tf-cost
17
+ - tf-security
18
+
19
+ rules:
20
+ - infrastructure/STRUCTURE.md
21
+ - infrastructure/MODULES.md
22
+ - infrastructure/STATE_AND_BACKEND.md
23
+ - infrastructure/NAMING.md
24
+ - infrastructure/SECURITY.md
25
+ - infrastructure/VARIABLES.md
26
+ - infrastructure/PROVIDERS.md
27
+
28
+ skills:
29
+ - terraform-service-scaffold
30
+ - terraform-module-creator
31
+ - terraform-review
32
+ - terraform-security-audit
33
+ - terraform-best-practices
34
+
35
+ agents:
36
+ - infrastructure-expert.md
37
+ - sre-architect.md
38
+
39
+ claude-sections:
40
+ - 30-infrastructure.md
package/packs/ops.yaml ADDED
@@ -0,0 +1,16 @@
1
+ name: ops
2
+ description: "Deploy & infrastructure"
3
+ category: Ship
4
+ priority: 50
5
+ hidden: false
6
+
7
+ commands:
8
+ - deploy
9
+ - env-setup
10
+
11
+ rules: []
12
+ skills: []
13
+ agents: []
14
+
15
+ claude-sections:
16
+ - 50-ops.md