attacca-forge 0.5.2 → 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 (30) hide show
  1. package/package.json +2 -2
  2. package/src/commands/install.js +134 -68
  3. package/.claude-plugin/marketplace.json +0 -20
  4. /package/{plugins/attacca-forge/.claude-plugin → .claude-plugin}/plugin.json +0 -0
  5. /package/{plugins/attacca-forge/skills → skills}/agent-economics-analyzer/SKILL.md +0 -0
  6. /package/{plugins/attacca-forge/skills → skills}/agent-readiness-audit/SKILL.md +0 -0
  7. /package/{plugins/attacca-forge/skills → skills}/agent-stack-opportunity-mapper/SKILL.md +0 -0
  8. /package/{plugins/attacca-forge/skills → skills}/ai-dev-level-assessment/SKILL.md +0 -0
  9. /package/{plugins/attacca-forge/skills → skills}/ai-dev-talent-strategy/SKILL.md +0 -0
  10. /package/{plugins/attacca-forge/skills → skills}/ai-difficulty-rapid-audit/SKILL.md +0 -0
  11. /package/{plugins/attacca-forge/skills → skills}/ai-native-org-redesign/SKILL.md +0 -0
  12. /package/{plugins/attacca-forge/skills → skills}/ai-output-taste-builder/SKILL.md +0 -0
  13. /package/{plugins/attacca-forge/skills → skills}/ai-workflow-capability-map/SKILL.md +0 -0
  14. /package/{plugins/attacca-forge/skills → skills}/ai-workflow-optimizer/SKILL.md +0 -0
  15. /package/{plugins/attacca-forge/skills → skills}/build-orchestrator/SKILL.md +0 -0
  16. /package/{plugins/attacca-forge/skills → skills}/codebase-discovery/SKILL.md +0 -0
  17. /package/{plugins/attacca-forge/skills → skills}/forge-help/SKILL.md +0 -0
  18. /package/{plugins/attacca-forge/skills → skills}/forge-start/SKILL.md +0 -0
  19. /package/{plugins/attacca-forge/skills → skills}/harness-simulator/SKILL.md +0 -0
  20. /package/{plugins/attacca-forge/skills → skills}/insight-to-action-compression-map/SKILL.md +0 -0
  21. /package/{plugins/attacca-forge/skills → skills}/intent-audit/SKILL.md +0 -0
  22. /package/{plugins/attacca-forge/skills → skills}/intent-gap-diagnostic/SKILL.md +0 -0
  23. /package/{plugins/attacca-forge/skills → skills}/intent-spec/SKILL.md +0 -0
  24. /package/{plugins/attacca-forge/skills → skills}/legacy-migration-roadmap/SKILL.md +0 -0
  25. /package/{plugins/attacca-forge/skills → skills}/personal-intent-layer-builder/SKILL.md +0 -0
  26. /package/{plugins/attacca-forge/skills → skills}/problem-difficulty-decomposition/SKILL.md +0 -0
  27. /package/{plugins/attacca-forge/skills → skills}/spec-architect/SKILL.md +0 -0
  28. /package/{plugins/attacca-forge/skills → skills}/spec-writer/SKILL.md +0 -0
  29. /package/{plugins/attacca-forge/skills → skills}/stress-test/SKILL.md +0 -0
  30. /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.2",
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
- import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
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,27 +27,107 @@ 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
- marketplaces[MARKETPLACE_NAME].lastUpdated = new Date().toISOString();
30
- } else {
31
- 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] = {
32
90
  source: {
33
91
  source: 'directory',
34
92
  path: targetDir,
35
93
  },
36
- installLocation: targetDir,
37
- lastUpdated: new Date().toISOString(),
38
94
  };
95
+ changed = true;
39
96
  }
40
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);
108
+ }
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
+
41
127
  writeJsonFile(marketplacesPath, marketplaces);
42
- return true;
43
128
  }
44
129
 
130
+ // Step 4: Register in installed_plugins.json + populate cache
45
131
  function registerPlugin(claudeDir, pluginDir, version) {
46
132
  const installedPath = join(claudeDir, 'plugins', 'installed_plugins.json');
47
133
  const installed = readJsonFile(installedPath) || { version: 2, plugins: {} };
@@ -52,9 +138,18 @@ function registerPlugin(claudeDir, pluginDir, version) {
52
138
  const pluginKey = `${PLUGIN_NAME}@${MARKETPLACE_NAME}`;
53
139
  const now = new Date().toISOString();
54
140
 
55
- // Set up cache directory and copy skills there
141
+ // Copy to cache
56
142
  const cachePath = join(claudeDir, 'plugins', 'cache', MARKETPLACE_NAME, PLUGIN_NAME, version);
57
- 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
+ }
58
153
 
59
154
  const sourceSkills = join(pluginDir, 'skills');
60
155
  const cacheSkills = join(cachePath, 'skills');
@@ -62,6 +157,7 @@ function registerPlugin(claudeDir, pluginDir, version) {
62
157
  cpSync(sourceSkills, cacheSkills, { recursive: true, force: true });
63
158
  }
64
159
 
160
+ // Register
65
161
  if (installed.plugins[pluginKey]) {
66
162
  installed.plugins[pluginKey][0].version = version;
67
163
  installed.plugins[pluginKey][0].installPath = cachePath;
@@ -79,7 +175,6 @@ function registerPlugin(claudeDir, pluginDir, version) {
79
175
  }
80
176
 
81
177
  writeJsonFile(installedPath, installed);
82
- return true;
83
178
  }
84
179
 
85
180
  export default async function install({ args, cwd, rootDir }) {
@@ -98,80 +193,51 @@ export default async function install({ args, cwd, rootDir }) {
98
193
 
99
194
  console.log(' ✓ Claude Code detected');
100
195
 
101
- // Source directories (shipped with this package)
102
- // Repo layout:
103
- // .claude-plugin/marketplace.json ← marketplace descriptor
104
- // plugins/attacca-forge/ ← plugin with .claude-plugin/plugin.json + skills/
105
- const sourceMarketplace = join(rootDir, '.claude-plugin', 'marketplace.json');
106
- const sourcePlugin = join(rootDir, 'plugins', 'attacca-forge');
107
-
108
- if (!existsSync(sourcePlugin)) {
109
- 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.');
110
200
  process.exit(1);
111
201
  }
112
202
 
113
203
  // Read version from package.json
114
204
  const pkg = readJsonFile(join(rootDir, 'package.json'));
115
- const version = pkg?.version || '0.5.2';
205
+ const version = pkg?.version || '0.6.0';
116
206
 
117
- // Target: ~/.claude/plugins/local/attacca-forge/
118
- // Installed layout (mirrors nirbound-marketplace):
119
- // .claude-plugin/marketplace.json
120
- // plugins/attacca-forge/.claude-plugin/plugin.json
121
- // plugins/attacca-forge/skills/
122
207
  const claudeDir = getClaudeDir();
123
- const targetDir = getPluginDir();
124
-
125
- const existed = existsSync(targetDir);
126
- if (!existsSync(targetDir)) mkdirSync(targetDir, { recursive: true });
127
-
128
- // 1. Copy marketplace descriptor to target root
129
- const targetMarketplaceDir = join(targetDir, '.claude-plugin');
130
- if (!existsSync(targetMarketplaceDir)) mkdirSync(targetMarketplaceDir, { recursive: true });
131
- if (existsSync(sourceMarketplace)) {
132
- cpSync(sourceMarketplace, join(targetMarketplaceDir, 'marketplace.json'), { force: true });
133
- }
208
+ const targetDir = join(claudeDir, 'plugins', 'local', MARKETPLACE_NAME);
209
+ const pluginsDir = join(claudeDir, 'plugins');
210
+ if (!existsSync(pluginsDir)) mkdirSync(pluginsDir, { recursive: true });
134
211
 
135
- // 2. Copy plugin (with .claude-plugin/plugin.json + skills/) into nested directory
136
- const targetPlugin = join(targetDir, 'plugins', 'attacca-forge');
137
- if (!existsSync(targetPlugin)) mkdirSync(targetPlugin, { recursive: true });
138
- cpSync(sourcePlugin, targetPlugin, { recursive: true, force: true });
212
+ // Step 1: Build marketplace structure
213
+ const pluginDir = buildMarketplaceStructure(rootDir, targetDir, version);
139
214
 
140
215
  // Count skills
141
- const targetSkills = join(targetPlugin, 'skills');
216
+ const { readdirSync } = await import('node:fs');
217
+ const skillsDir = join(pluginDir, 'skills');
142
218
  let skillCount = 0;
143
- if (existsSync(targetSkills)) {
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
- // 3. Register marketplace in known_marketplaces.json
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
- // 4. Register plugin in installed_plugins.json + populate cache
160
- registerPlugin(claudeDir, targetPlugin, version);
236
+ // Step 4: Register plugin + populate cache
237
+ registerPlugin(claudeDir, pluginDir, version);
161
238
  console.log(' ✓ Plugin registered');
162
239
 
163
240
  console.log('');
164
241
  console.log(' Restart Claude Code to load the new skills.');
165
242
  console.log('');
166
- console.log(' Available skills:');
167
- console.log(' /spec-architect Full behavioral spec with intent contracts');
168
- console.log(' /spec-writer Streamlined spec (no intent layer)');
169
- console.log(' /stress-test Factorial stress testing (22 variation types)');
170
- console.log(' /intent-spec Agent intent specification');
171
- console.log(' /intent-audit Organizational AI maturity audit');
172
- console.log(' /codebase-discovery Brownfield codebase discovery');
173
- console.log(' /build-orchestrator Build pipeline with 4-layer eval stack');
174
- console.log(' /forge-help Phase-aware guidance ("what\'s next?")');
175
- console.log(' /forge-start IDEA phase onboarding');
176
- console.log('');
177
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.2",
13
- "author": {
14
- "name": "Attacca"
15
- },
16
- "source": "./plugins/attacca-forge",
17
- "category": "development"
18
- }
19
- ]
20
- }