attacca-forge 0.5.1 → 0.6.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 (31) hide show
  1. package/package.json +2 -2
  2. package/src/commands/install.js +135 -68
  3. package/.claude-plugin/marketplace.json +0 -20
  4. package/plugins/attacca-forge/.claude-plugin/marketplace.json +0 -20
  5. /package/{plugins/attacca-forge/.claude-plugin → .claude-plugin}/plugin.json +0 -0
  6. /package/{plugins/attacca-forge/skills → skills}/agent-economics-analyzer/SKILL.md +0 -0
  7. /package/{plugins/attacca-forge/skills → skills}/agent-readiness-audit/SKILL.md +0 -0
  8. /package/{plugins/attacca-forge/skills → skills}/agent-stack-opportunity-mapper/SKILL.md +0 -0
  9. /package/{plugins/attacca-forge/skills → skills}/ai-dev-level-assessment/SKILL.md +0 -0
  10. /package/{plugins/attacca-forge/skills → skills}/ai-dev-talent-strategy/SKILL.md +0 -0
  11. /package/{plugins/attacca-forge/skills → skills}/ai-difficulty-rapid-audit/SKILL.md +0 -0
  12. /package/{plugins/attacca-forge/skills → skills}/ai-native-org-redesign/SKILL.md +0 -0
  13. /package/{plugins/attacca-forge/skills → skills}/ai-output-taste-builder/SKILL.md +0 -0
  14. /package/{plugins/attacca-forge/skills → skills}/ai-workflow-capability-map/SKILL.md +0 -0
  15. /package/{plugins/attacca-forge/skills → skills}/ai-workflow-optimizer/SKILL.md +0 -0
  16. /package/{plugins/attacca-forge/skills → skills}/build-orchestrator/SKILL.md +0 -0
  17. /package/{plugins/attacca-forge/skills → skills}/codebase-discovery/SKILL.md +0 -0
  18. /package/{plugins/attacca-forge/skills → skills}/forge-help/SKILL.md +0 -0
  19. /package/{plugins/attacca-forge/skills → skills}/forge-start/SKILL.md +0 -0
  20. /package/{plugins/attacca-forge/skills → skills}/harness-simulator/SKILL.md +0 -0
  21. /package/{plugins/attacca-forge/skills → skills}/insight-to-action-compression-map/SKILL.md +0 -0
  22. /package/{plugins/attacca-forge/skills → skills}/intent-audit/SKILL.md +0 -0
  23. /package/{plugins/attacca-forge/skills → skills}/intent-gap-diagnostic/SKILL.md +0 -0
  24. /package/{plugins/attacca-forge/skills → skills}/intent-spec/SKILL.md +0 -0
  25. /package/{plugins/attacca-forge/skills → skills}/legacy-migration-roadmap/SKILL.md +0 -0
  26. /package/{plugins/attacca-forge/skills → skills}/personal-intent-layer-builder/SKILL.md +0 -0
  27. /package/{plugins/attacca-forge/skills → skills}/problem-difficulty-decomposition/SKILL.md +0 -0
  28. /package/{plugins/attacca-forge/skills → skills}/spec-architect/SKILL.md +0 -0
  29. /package/{plugins/attacca-forge/skills → skills}/spec-writer/SKILL.md +0 -0
  30. /package/{plugins/attacca-forge/skills → skills}/stress-test/SKILL.md +0 -0
  31. /package/{plugins/attacca-forge/skills → skills}/web-fork-strategic-briefing/SKILL.md +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "attacca-forge",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "description": "Spec-driven AI development toolkit — design, evaluate, stress-test, and certify autonomous agents from your terminal",
5
5
  "keywords": [
6
6
  "ai",
@@ -32,7 +32,7 @@
32
32
  "files": [
33
33
  "bin/",
34
34
  "src/",
35
- "plugins/",
35
+ "skills/",
36
36
  ".claude-plugin/",
37
37
  "docs/",
38
38
  "examples/",
@@ -1,10 +1,16 @@
1
1
  // =============================================================================
2
- // attacca-forge install — Install skills into Claude Code plugin directory
2
+ // attacca-forge install — Install as a Claude Code marketplace + plugin
3
+ //
4
+ // Registration approach (same pattern as nirbound-marketplace):
5
+ // 1. Build marketplace structure at ~/.claude/plugins/local/attacca-forge/
6
+ // 2. Register in settings.json (extraKnownMarketplaces + enabledPlugins)
7
+ // 3. Register in known_marketplaces.json
8
+ // 4. Register in installed_plugins.json + populate cache
3
9
  // =============================================================================
4
10
 
5
11
  import { cpSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
6
12
  import { join } from 'node:path';
7
- import { getClaudeDir, getPluginDir, isClaudeInstalled } from '../utils/detect-claude.js';
13
+ import { getClaudeDir, isClaudeInstalled } from '../utils/detect-claude.js';
8
14
 
9
15
  const MARKETPLACE_NAME = 'attacca-forge';
10
16
  const PLUGIN_NAME = 'attacca-forge';
@@ -21,52 +27,138 @@ function writeJsonFile(path, data) {
21
27
  writeFileSync(path, JSON.stringify(data, null, 2) + '\n', 'utf-8');
22
28
  }
23
29
 
24
- function registerMarketplace(claudeDir, targetDir) {
25
- const marketplacesPath = join(claudeDir, 'plugins', 'known_marketplaces.json');
26
- const marketplaces = readJsonFile(marketplacesPath) || {};
30
+ // Step 1: Build marketplace directory structure
31
+ function buildMarketplaceStructure(rootDir, targetDir, version) {
32
+ // Create marketplace root
33
+ mkdirSync(targetDir, { recursive: true });
34
+
35
+ // Write marketplace.json at marketplace root
36
+ const marketplaceJsonDir = join(targetDir, '.claude-plugin');
37
+ mkdirSync(marketplaceJsonDir, { recursive: true });
38
+ writeJsonFile(join(marketplaceJsonDir, 'marketplace.json'), {
39
+ $schema: 'https://anthropic.com/claude-code/marketplace.schema.json',
40
+ name: MARKETPLACE_NAME,
41
+ description:
42
+ 'Spec-driven AI development toolkit — design, evaluate, stress-test, and certify autonomous agents',
43
+ owner: { name: 'Attacca' },
44
+ plugins: [
45
+ {
46
+ name: PLUGIN_NAME,
47
+ description:
48
+ 'AI agent development methodology — design, evaluate, and align autonomous agents',
49
+ version,
50
+ author: { name: 'Attacca' },
51
+ source: `./plugins/${PLUGIN_NAME}`,
52
+ category: 'development',
53
+ },
54
+ ],
55
+ });
56
+
57
+ // Create plugin subdirectory: plugins/attacca-forge/
58
+ const pluginDir = join(targetDir, 'plugins', PLUGIN_NAME);
59
+ mkdirSync(pluginDir, { recursive: true });
60
+
61
+ // Copy plugin.json
62
+ const pluginJsonDir = join(pluginDir, '.claude-plugin');
63
+ mkdirSync(pluginJsonDir, { recursive: true });
64
+ const sourcePluginJson = join(rootDir, '.claude-plugin', 'plugin.json');
65
+ if (existsSync(sourcePluginJson)) {
66
+ cpSync(sourcePluginJson, join(pluginJsonDir, 'plugin.json'), { force: true });
67
+ }
27
68
 
28
- if (marketplaces[MARKETPLACE_NAME]) {
29
- // Update timestamp
30
- marketplaces[MARKETPLACE_NAME].lastUpdated = new Date().toISOString();
31
- } else {
32
- marketplaces[MARKETPLACE_NAME] = {
69
+ // Copy skills into the plugin subdirectory
70
+ const sourceSkills = join(rootDir, 'skills');
71
+ const targetSkills = join(pluginDir, 'skills');
72
+ if (existsSync(sourceSkills)) {
73
+ cpSync(sourceSkills, targetSkills, { recursive: true, force: true });
74
+ }
75
+
76
+ return pluginDir;
77
+ }
78
+
79
+ // Step 2: Register in settings.json
80
+ function registerInSettings(claudeDir, targetDir) {
81
+ const settingsPath = join(claudeDir, 'settings.json');
82
+ const settings = readJsonFile(settingsPath) || {};
83
+
84
+ let changed = false;
85
+
86
+ // Add to extraKnownMarketplaces
87
+ if (!settings.extraKnownMarketplaces) settings.extraKnownMarketplaces = {};
88
+ if (!settings.extraKnownMarketplaces[MARKETPLACE_NAME]) {
89
+ settings.extraKnownMarketplaces[MARKETPLACE_NAME] = {
33
90
  source: {
34
91
  source: 'directory',
35
92
  path: targetDir,
36
93
  },
37
- installLocation: targetDir,
38
- lastUpdated: new Date().toISOString(),
39
94
  };
95
+ changed = true;
96
+ }
97
+
98
+ // Add to enabledPlugins
99
+ if (!settings.enabledPlugins) settings.enabledPlugins = {};
100
+ const pluginKey = `${PLUGIN_NAME}@${MARKETPLACE_NAME}`;
101
+ if (settings.enabledPlugins[pluginKey] === undefined) {
102
+ settings.enabledPlugins[pluginKey] = true;
103
+ changed = true;
104
+ }
105
+
106
+ if (changed) {
107
+ writeJsonFile(settingsPath, settings);
40
108
  }
41
109
 
110
+ return changed;
111
+ }
112
+
113
+ // Step 3: Register in known_marketplaces.json
114
+ function registerMarketplace(claudeDir, targetDir) {
115
+ const marketplacesPath = join(claudeDir, 'plugins', 'known_marketplaces.json');
116
+ const marketplaces = readJsonFile(marketplacesPath) || {};
117
+
118
+ marketplaces[MARKETPLACE_NAME] = {
119
+ source: {
120
+ source: 'directory',
121
+ path: targetDir,
122
+ },
123
+ installLocation: targetDir,
124
+ lastUpdated: new Date().toISOString(),
125
+ };
126
+
42
127
  writeJsonFile(marketplacesPath, marketplaces);
43
- return true;
44
128
  }
45
129
 
46
- function registerPlugin(claudeDir, targetDir, version) {
130
+ // Step 4: Register in installed_plugins.json + populate cache
131
+ function registerPlugin(claudeDir, pluginDir, version) {
47
132
  const installedPath = join(claudeDir, 'plugins', 'installed_plugins.json');
48
133
  const installed = readJsonFile(installedPath) || { version: 2, plugins: {} };
49
134
 
50
- // Ensure version 2 format
51
135
  if (!installed.version) installed.version = 2;
52
136
  if (!installed.plugins) installed.plugins = {};
53
137
 
54
138
  const pluginKey = `${PLUGIN_NAME}@${MARKETPLACE_NAME}`;
55
139
  const now = new Date().toISOString();
56
140
 
57
- // Set up cache directory
141
+ // Copy to cache
58
142
  const cachePath = join(claudeDir, 'plugins', 'cache', MARKETPLACE_NAME, PLUGIN_NAME, version);
59
- if (!existsSync(cachePath)) mkdirSync(cachePath, { recursive: true });
143
+ mkdirSync(cachePath, { recursive: true });
144
+
145
+ const sourcePluginJsonDir = join(pluginDir, '.claude-plugin');
146
+ const cachePluginJsonDir = join(cachePath, '.claude-plugin');
147
+ mkdirSync(cachePluginJsonDir, { recursive: true });
148
+ if (existsSync(join(sourcePluginJsonDir, 'plugin.json'))) {
149
+ cpSync(join(sourcePluginJsonDir, 'plugin.json'), join(cachePluginJsonDir, 'plugin.json'), {
150
+ force: true,
151
+ });
152
+ }
60
153
 
61
- // Copy skills to cache
62
- const sourceSkills = join(targetDir, 'skills');
154
+ const sourceSkills = join(pluginDir, 'skills');
63
155
  const cacheSkills = join(cachePath, 'skills');
64
156
  if (existsSync(sourceSkills)) {
65
157
  cpSync(sourceSkills, cacheSkills, { recursive: true, force: true });
66
158
  }
67
159
 
160
+ // Register
68
161
  if (installed.plugins[pluginKey]) {
69
- // Update existing entry
70
162
  installed.plugins[pluginKey][0].version = version;
71
163
  installed.plugins[pluginKey][0].installPath = cachePath;
72
164
  installed.plugins[pluginKey][0].lastUpdated = now;
@@ -83,7 +175,6 @@ function registerPlugin(claudeDir, targetDir, version) {
83
175
  }
84
176
 
85
177
  writeJsonFile(installedPath, installed);
86
- return true;
87
178
  }
88
179
 
89
180
  export default async function install({ args, cwd, rootDir }) {
@@ -102,75 +193,51 @@ export default async function install({ args, cwd, rootDir }) {
102
193
 
103
194
  console.log(' ✓ Claude Code detected');
104
195
 
105
- // Source plugin directory (shipped with this package)
106
- const sourcePlugin = join(rootDir, 'plugins', 'attacca-forge');
107
- if (!existsSync(sourcePlugin)) {
108
- console.error(' ✗ Plugin source not found. Package may be corrupted.');
196
+ // Verify source skills exist
197
+ const sourceSkills = join(rootDir, 'skills');
198
+ if (!existsSync(sourceSkills)) {
199
+ console.error(' ✗ Skills directory not found. Package may be corrupted.');
109
200
  process.exit(1);
110
201
  }
111
202
 
112
203
  // Read version from package.json
113
204
  const pkg = readJsonFile(join(rootDir, 'package.json'));
114
- const version = pkg?.version || '0.5.1';
205
+ const version = pkg?.version || '0.6.0';
115
206
 
116
- // Target plugin directory
117
207
  const claudeDir = getClaudeDir();
118
- const targetDir = getPluginDir();
119
- const localDir = join(claudeDir, 'plugins', 'local');
120
-
121
- // Create directories
122
- if (!existsSync(localDir)) mkdirSync(localDir, { recursive: true });
123
-
124
- // Copy .claude-plugin/ and skills/
125
- const existed = existsSync(targetDir);
126
- if (!existsSync(targetDir)) mkdirSync(targetDir, { recursive: true });
127
-
128
- const sourceClaudePlugin = join(sourcePlugin, '.claude-plugin');
129
- const sourceSkills = join(sourcePlugin, 'skills');
130
- const targetClaudePlugin = join(targetDir, '.claude-plugin');
131
- const targetSkills = join(targetDir, 'skills');
208
+ const targetDir = join(claudeDir, 'plugins', 'local', MARKETPLACE_NAME);
209
+ const pluginsDir = join(claudeDir, 'plugins');
210
+ if (!existsSync(pluginsDir)) mkdirSync(pluginsDir, { recursive: true });
132
211
 
133
- if (existsSync(sourceClaudePlugin)) {
134
- cpSync(sourceClaudePlugin, targetClaudePlugin, { recursive: true, force: true });
135
- }
136
- if (existsSync(sourceSkills)) {
137
- cpSync(sourceSkills, targetSkills, { recursive: true, force: true });
138
- }
212
+ // Step 1: Build marketplace structure
213
+ const pluginDir = buildMarketplaceStructure(rootDir, targetDir, version);
139
214
 
140
215
  // Count skills
216
+ const { readdirSync } = await import('node:fs');
217
+ const skillsDir = join(pluginDir, 'skills');
141
218
  let skillCount = 0;
142
- if (existsSync(targetSkills)) {
143
- const { readdirSync } = await import('node:fs');
144
- skillCount = readdirSync(targetSkills).filter((f) => {
145
- return existsSync(join(targetSkills, f, 'SKILL.md'));
219
+ if (existsSync(skillsDir)) {
220
+ skillCount = readdirSync(skillsDir).filter((f) => {
221
+ return existsSync(join(skillsDir, f, 'SKILL.md'));
146
222
  }).length;
147
223
  }
148
224
 
149
- console.log(` ✓ ${existed ? 'Updated' : 'Installed'} ${skillCount} skills to Claude Code`);
150
- console.log(` Location: ${targetDir}`);
225
+ console.log(` ✓ Installed ${skillCount} skills`);
226
+ console.log(` Marketplace: ${targetDir}`);
151
227
 
152
- // Register marketplace and plugin
153
- const pluginsDir = join(claudeDir, 'plugins');
154
- if (!existsSync(pluginsDir)) mkdirSync(pluginsDir, { recursive: true });
228
+ // Step 2: Register in settings.json
229
+ const settingsChanged = registerInSettings(claudeDir, targetDir);
230
+ console.log(` ✓ Settings ${settingsChanged ? 'updated' : 'already configured'}`);
155
231
 
232
+ // Step 3: Register in known_marketplaces.json
156
233
  registerMarketplace(claudeDir, targetDir);
157
234
  console.log(' ✓ Marketplace registered');
158
235
 
159
- registerPlugin(claudeDir, targetDir, version);
236
+ // Step 4: Register plugin + populate cache
237
+ registerPlugin(claudeDir, pluginDir, version);
160
238
  console.log(' ✓ Plugin registered');
161
239
 
162
240
  console.log('');
163
241
  console.log(' Restart Claude Code to load the new skills.');
164
242
  console.log('');
165
- console.log(' Available skills:');
166
- console.log(' /spec-architect Full behavioral spec with intent contracts');
167
- console.log(' /spec-writer Streamlined spec (no intent layer)');
168
- console.log(' /stress-test Factorial stress testing (22 variation types)');
169
- console.log(' /intent-spec Agent intent specification');
170
- console.log(' /intent-audit Organizational AI maturity audit');
171
- console.log(' /codebase-discovery Brownfield codebase discovery');
172
- console.log(' /build-orchestrator Build pipeline with 4-layer eval stack');
173
- console.log(' /forge-help Phase-aware guidance ("what\'s next?")');
174
- console.log(' /forge-start IDEA phase onboarding');
175
- console.log('');
176
243
  }
@@ -1,20 +0,0 @@
1
- {
2
- "$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
3
- "name": "attacca-forge",
4
- "description": "Open-source AI agent development toolkit: spec writing, evaluation, intent engineering, and build orchestration for production-grade agents",
5
- "owner": {
6
- "name": "Attacca"
7
- },
8
- "plugins": [
9
- {
10
- "name": "attacca-forge",
11
- "description": "AI agent development methodology — design, evaluate, and align autonomous agents with production-grade specifications, factorial stress testing, and intent engineering",
12
- "version": "0.5.1",
13
- "author": {
14
- "name": "Attacca"
15
- },
16
- "source": "./plugins/attacca-forge",
17
- "category": "development"
18
- }
19
- ]
20
- }
@@ -1,20 +0,0 @@
1
- {
2
- "$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
3
- "name": "attacca-forge",
4
- "description": "Attacca Forge — AI agent development methodology: design, evaluate, align, and orchestrate autonomous agents",
5
- "owner": {
6
- "name": "Attacca"
7
- },
8
- "plugins": [
9
- {
10
- "name": "attacca-forge",
11
- "description": "AI agent development methodology — design, evaluate, and align autonomous agents. 26 skills across spec writing, stress testing, intent engineering, and build orchestration.",
12
- "version": "0.5.1",
13
- "author": {
14
- "name": "Attacca"
15
- },
16
- "source": ".",
17
- "category": "development"
18
- }
19
- ]
20
- }