adaptive-director-skill 0.1.0 → 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 (26) hide show
  1. package/README.md +110 -34
  2. package/package.json +8 -6
  3. package/scripts/cli.mjs +55 -0
  4. package/scripts/discover.mjs +22 -9
  5. package/scripts/doctor.mjs +141 -0
  6. package/scripts/install.mjs +97 -0
  7. package/scripts/refresh.mjs +62 -0
  8. package/scripts/setup.mjs +149 -123
  9. package/scripts/smoke-test.mjs +138 -89
  10. package/{SKILL.md → skills/adaptive-director/SKILL.md} +11 -11
  11. package/skills/adaptive-director/data/registry.json +50 -0
  12. package/skills/adaptive-director/examples/clean-run-walkthrough.md +83 -0
  13. package/skills/adaptive-director/examples/critical-fix-cycle-walkthrough.md +70 -0
  14. package/{references → skills/adaptive-director/references}/capability-registry.md +17 -10
  15. package/{scripts → skills/adaptive-director/scripts}/route.mjs +30 -21
  16. package/skills/adaptive-director/templates/fix-brief.md +27 -0
  17. package/skills/adaptive-director/templates/implement-brief.md +28 -0
  18. package/skills/adaptive-director/templates/plan-brief.md +31 -0
  19. package/skills/adaptive-director/templates/review-brief.md +42 -0
  20. package/skills/adaptive-director/templates/verify-brief.md +28 -0
  21. package/data/registry.json +0 -42
  22. /package/{references → skills/adaptive-director/references}/delegate-integration.md +0 -0
  23. /package/{references → skills/adaptive-director/references}/handoff-schema.md +0 -0
  24. /package/{references → skills/adaptive-director/references}/routing-rules.md +0 -0
  25. /package/{scripts → skills/adaptive-director/scripts}/resume.mjs +0 -0
  26. /package/{scripts → skills/adaptive-director/scripts}/run-state.mjs +0 -0
package/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # Adaptive Director Skill
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/adaptive-director-skill.svg)](https://www.npmjs.com/package/adaptive-director-skill)
3
4
  [![Node.js](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](https://nodejs.org)
4
- [![Zero Dependencies](https://img.shields.io/badge/dependencies-0%20(pure%20built--ins)-blue.svg)](#architecture)
5
+ [![Zero Dependencies](https://img.shields.io/badge/dependencies-0%20(pure%20built--ins)-blue.svg)](#core-principles)
5
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
7
 
7
8
  > **One task in. The right agents take it from there.**
@@ -58,25 +59,59 @@ flowchart LR
58
59
 
59
60
  Adaptive Director runs with **zero external npm dependencies** (pure Node.js built-ins).
60
61
 
61
- ### 1. Clone & Setup
62
+ ### 1. Install Globally
62
63
 
63
64
  ```bash
64
- git clone https://github.com/tamourax/Adaptive-Orchestrator.git
65
- cd Adaptive-Orchestrator
65
+ npm install -g adaptive-director-skill
66
+ ```
67
+
68
+ ### 2. Set Up
69
+
70
+ > `adaptive-director setup` registers the Skill with your coding-agent hosts, discovers available agents, detects optional delegate-skills integration, and creates the local Adaptive Director configuration.
71
+
72
+ ```bash
73
+ adaptive-director setup
74
+ ```
75
+
76
+ Or without a global install:
77
+
78
+ ```bash
79
+ npx adaptive-director-skill setup
80
+ ```
66
81
 
67
- # Probe local agents (Claude, Codex, Antigravity, Cursor, etc.)
68
- node scripts/setup.mjs
82
+ ### 3. Verify
83
+
84
+ ```bash
85
+ adaptive-director doctor
86
+ ```
69
87
 
70
- # Verify installation with smoke test
71
- node scripts/smoke-test.mjs
88
+ Expected output:
89
+ ```
90
+ ✓ Package installed
91
+ ✓ Skill source exists
92
+ ✓ SKILL.md exists
93
+ ✓ references/ exists
94
+ ✓ templates/ exists
95
+ ✓ examples/ exists
96
+ ✓ Registry exists
97
+ ✓ Registry valid
98
+ ✓ Config exists
99
+ ✓ Config valid
100
+ ✓ Routing script works
101
+ ✓ Run state script exists
102
+ ✓ Resume script exists
103
+ ✓ codex detected
104
+ ✓ Skill installed for codex
105
+
106
+ Ready.
72
107
  ```
73
108
 
74
- ### 2. Run with Your AI Agent
109
+ ### 4. Run with Your AI Agent
75
110
 
76
- Load `SKILL.md` into your coding agent (Claude Code, Antigravity, Codex, etc.) and prompt:
111
+ The Skill is now installed in your agent's skills directory. Prompt your agent:
77
112
 
78
113
  ```text
79
- Use $adaptive-director-skill to implement Stripe checkout in Flutter
114
+ Use $adaptive-director to implement Stripe checkout in Flutter
80
115
  ```
81
116
 
82
117
  ---
@@ -96,33 +131,50 @@ Use $adaptive-director-skill to implement Stripe checkout in Flutter
96
131
 
97
132
  ---
98
133
 
99
- ## Architecture
134
+ ## Repository Architecture
100
135
 
101
- > *"Reasoning stays with agents. Deterministic operations stay in scripts."*
136
+ The repository separates the **npm management/installer layer** from the **self-contained Agent Skill**:
137
+
138
+ - **Repository Root:** npm distribution, CLI tools, setup, host discovery, and health diagnostics (`scripts/`).
139
+ - **`skills/adaptive-director/`:** The canonical, portable Agent Skill (procedural brain, runtime scripts, templates, references, and registry data).
102
140
 
103
141
  ```text
104
- adaptive-director/
105
- ├── SKILL.md # The brain: instructions read by your AI agent
106
- ├── data/registry.json # Baseline model capability scores (1–5)
107
- ├── references/ # Handoff schemas, rules, and delegate docs
108
- └── scripts/ # Deterministic Node.js helpers (pure built-ins)
109
- ├── discover.mjs # Detects local agent CLIs
110
- ├── route.mjs # Computes agent + effort assignments
111
- ├── run-state.mjs # Manages isolated phase briefs & workspaces
112
- └── resume.mjs # Recovers interrupted runs
142
+ Adaptive-Director-Skill/
143
+ ├── scripts/ # Management & CLI layer
144
+ ├── cli.mjs # Main CLI router
145
+ ├── setup.mjs # Interactive host setup
146
+ │ ├── install.mjs # Idempotent skill copier
147
+ ├── refresh.mjs # Safe config refresher
148
+ ├── discover.mjs # Local agent discovery
149
+ ├── doctor.mjs # Installation diagnostics
150
+ └── smoke-test.mjs # Automated test suite
151
+
152
+ └── skills/adaptive-director/ # Portable Agent Skill (the brain)
153
+ ├── SKILL.md # Procedural runbook
154
+ ├── scripts/ # Runtime scripts (route, run-state, resume)
155
+ ├── references/ # Deep documentation & schemas
156
+ ├── templates/ # Standardized phase brief templates
157
+ ├── examples/ # Realistic execution walkthroughs
158
+ └── data/ # Capability registry
113
159
  ```
114
160
 
115
- ### Routing Priority Order
161
+ ---
116
162
 
117
- 1. **User Overrides:** Explicit settings in `~/.adaptive-director/config.yaml`
118
- 2. **Delegate Lanes:** Optional `delegate-skills` fleet lanes (when `--delegate` is active)
119
- 3. **Capability Registry:** Best available local model meeting phase requirements
120
- 4. **Fallback:** Default host agent
163
+ ## CLI Commands
164
+
165
+ ```bash
166
+ adaptive-director setup # Interactive: discover hosts, install Skill, create config
167
+ adaptive-director install # Re-install/update Skill in host directories
168
+ adaptive-director refresh # Re-discover hosts & update config (preserves overrides)
169
+ adaptive-director doctor # Validate installation and health
170
+ adaptive-director help # Show usage
171
+ ```
121
172
 
122
173
  ---
123
174
 
124
175
  ## Core Principles
125
176
 
177
+ - **Routing Priority:** User overrides → Delegate fleet lanes → Capability registry → Default fallback.
126
178
  - **Independent Review:** The coder never reviews its own work.
127
179
  - **Max Reasoning Opt-in:** `max` effort is locked by default; requires `--allow-max`.
128
180
  - **Runaway Loop Protection:** Maximum 1 automated fix cycle before alerting the user.
@@ -131,19 +183,43 @@ adaptive-director/
131
183
 
132
184
  ---
133
185
 
134
- ## Configuration (`~/.adaptive-director/config.yaml`)
186
+ ## Configuration (`~/.adaptive-director/config.json`)
187
+
188
+ ```json
189
+ {
190
+ "version": 1,
191
+ "defaultBudget": "balanced",
192
+ "overrides": {
193
+ "plan": "claude",
194
+ "implement": "codex"
195
+ }
196
+ }
197
+ ```
198
+
199
+ ---
200
+
201
+ ## Upgrading
135
202
 
136
- ```yaml
137
- defaultBudget: balanced # conservative | balanced | quality
203
+ After a package upgrade, re-install the Skill into your host environments:
138
204
 
139
- # Optional overrides:
140
- agentOverrides.plan: claude
141
- agentOverrides.implement: codex
142
- agentOverrides.review: claude
205
+ ```bash
206
+ npm install -g adaptive-director-skill@latest
207
+ adaptive-director install
208
+ adaptive-director doctor
143
209
  ```
144
210
 
145
211
  ---
146
212
 
213
+ ## Uninstalling
214
+
215
+ ```bash
216
+ npm uninstall -g adaptive-director-skill
217
+ ```
218
+
219
+ > **Note:** npm uninstall removes the package, but does **not** remove Skill copies that were installed into your coding-agent host directories. To clean those up, manually delete the `Adaptive-Director/` folder from each host skill directory (e.g. `~/.codex/skills/Adaptive-Director/`).
220
+
221
+ ---
222
+
147
223
  ## License
148
224
 
149
225
  MIT License © 2026 [Ahmed Tamer](https://github.com/tamourax). See [LICENSE](LICENSE) for details.
package/package.json CHANGED
@@ -1,26 +1,28 @@
1
1
  {
2
2
  "name": "adaptive-director-skill",
3
- "version": "0.1.0",
3
+ "version": "1.0.0",
4
4
  "description": "Adaptive Director Skill — Skill-first adaptive multi-agent orchestration for AI coding agents",
5
5
  "type": "module",
6
+ "bin": {
7
+ "adaptive-director": "scripts/cli.mjs"
8
+ },
6
9
  "license": "MIT",
7
10
  "author": "Ahmed Tamer",
8
11
  "repository": {
9
12
  "type": "git",
10
- "url": "https://github.com/tamourax/Adaptive-Orchestrator.git"
13
+ "url": "git+https://github.com/tamourax/Adaptive-Director-Skill.git"
11
14
  },
12
15
  "files": [
13
- "SKILL.md",
14
16
  "README.md",
15
17
  "LICENSE",
16
18
  "scripts/",
17
- "references/",
18
- "data/"
19
+ "skills/"
19
20
  ],
20
21
  "scripts": {
21
22
  "test": "node scripts/smoke-test.mjs",
22
23
  "setup": "node scripts/setup.mjs",
23
- "discover": "node scripts/discover.mjs"
24
+ "discover": "node scripts/discover.mjs",
25
+ "doctor": "node scripts/doctor.mjs"
24
26
  },
25
27
  "keywords": [
26
28
  "ai",
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { spawnSync } from 'node:child_process';
4
+ import path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import fs from 'node:fs';
7
+
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+
10
+ const args = process.argv.slice(2);
11
+ const command = args[0] || 'help';
12
+
13
+ const commands = {
14
+ setup: 'setup.mjs',
15
+ install: 'install.mjs',
16
+ refresh: 'refresh.mjs',
17
+ doctor: 'doctor.mjs',
18
+ };
19
+
20
+ if (command === 'help' || command === '--help' || command === '-h') {
21
+ console.log(`Adaptive Director Skill CLI v1.0.0
22
+
23
+ Usage:
24
+ adaptive-director <command>
25
+
26
+ Commands:
27
+ setup - Initial interactive setup and installation
28
+ install - Install/copy the Skill into supported host skill directories
29
+ refresh - Re-run discovery and update config without destroying user overrides
30
+ doctor - Validate installation and report health
31
+ help - Show this help message
32
+ `);
33
+ process.exit(0);
34
+ }
35
+
36
+ const targetScript = commands[command];
37
+
38
+ if (!targetScript) {
39
+ console.error(`Unknown command: ${command}`);
40
+ console.log(`Run 'adaptive-director help' for usage.`);
41
+ process.exit(1);
42
+ }
43
+
44
+ const scriptPath = path.join(__dirname, targetScript);
45
+
46
+ if (!fs.existsSync(scriptPath)) {
47
+ console.error(`Command not yet implemented: ${command}`);
48
+ process.exit(1);
49
+ }
50
+
51
+ const result = spawnSync('node', [scriptPath, ...args.slice(1)], {
52
+ stdio: 'inherit'
53
+ });
54
+
55
+ process.exit(result.status ?? 1);
@@ -20,15 +20,15 @@ import { homedir } from 'node:os'
20
20
  // ─── Known agents ─────────────────────────────────────────────────────────────
21
21
 
22
22
  const KNOWN_AGENTS = [
23
- { id: 'claude', bins: ['claude'], versionArgs: ['--version'] },
24
- { id: 'codex', bins: ['codex'], versionArgs: ['--version'] },
25
- { id: 'agy', bins: ['agy'], versionArgs: ['--version'] },
26
- { id: 'gemini', bins: ['gemini'], versionArgs: ['--version'] },
27
- { id: 'opencode', bins: ['opencode'], versionArgs: ['--version'] },
28
- { id: 'aider', bins: ['aider'], versionArgs: ['--version'] },
29
- { id: 'cursor', bins: ['cursor-agent'], versionArgs: ['--version'] },
30
- { id: 'cline', bins: ['cline'], versionArgs: ['--version'] },
31
- { id: 'copilot', bins: ['copilot'], versionArgs: ['--version'] },
23
+ { id: 'claude', bins: ['claude'], versionArgs: ['--version'], skillPaths: ['.claude/skills', '.config/claude/skills'] },
24
+ { id: 'codex', bins: ['codex'], versionArgs: ['--version'], skillPaths: ['.codex/skills'] },
25
+ { id: 'agy', bins: ['agy'], versionArgs: ['--version'], skillPaths: ['.gemini/antigravity/builtin/skills', '.gemini/antigravity/skills', '.gemini/antigravity-ide/skills'] },
26
+ { id: 'gemini', bins: ['gemini'], versionArgs: ['--version'], skillPaths: ['.gemini/skills'] },
27
+ { id: 'opencode', bins: ['opencode'], versionArgs: ['--version'], skillPaths: ['.opencode/skills'] },
28
+ { id: 'aider', bins: ['aider'], versionArgs: ['--version'], skillPaths: ['.aider/skills'] },
29
+ { id: 'cursor', bins: ['cursor-agent'], versionArgs: ['--version'], skillPaths: ['.cursor/skills'] },
30
+ { id: 'cline', bins: ['cline'], versionArgs: ['--version'], skillPaths: ['.cline/skills'] },
31
+ { id: 'copilot', bins: ['copilot'], versionArgs: ['--version'], skillPaths: ['.copilot/skills'] },
32
32
  ]
33
33
 
34
34
  // ─── Helpers ──────────────────────────────────────────────────────────────────
@@ -116,10 +116,23 @@ function discover() {
116
116
  }
117
117
 
118
118
  const version = getVersion(bin, desc.versionArgs)
119
+ let detectedSkillPath = null
120
+ if (desc.skillPaths) {
121
+ for (const sp of desc.skillPaths) {
122
+ const fullPath = join(homedir(), sp)
123
+ if (existsSync(fullPath)) {
124
+ detectedSkillPath = fullPath
125
+ break
126
+ }
127
+ }
128
+ }
129
+
119
130
  agents[desc.id] = {
120
131
  installed: true,
121
132
  available: version !== null,
122
133
  version: version ?? 'unknown',
134
+ skillPath: detectedSkillPath,
135
+ hasSkill: detectedSkillPath ? existsSync(join(detectedSkillPath, 'adaptive-director')) || existsSync(join(detectedSkillPath, 'Adaptive-Director')) || existsSync(join(detectedSkillPath, 'adaptive-director-skill')) : false
123
136
  }
124
137
  }
125
138
 
@@ -0,0 +1,141 @@
1
+ #!/usr/bin/env node
2
+ import { execFileSync } from 'node:child_process';
3
+ import { existsSync, readFileSync } from 'node:fs';
4
+ import { join, dirname } from 'node:path';
5
+ import { homedir } from 'node:os';
6
+ import { fileURLToPath } from 'node:url';
7
+
8
+ const __dirname = dirname(fileURLToPath(import.meta.url));
9
+
10
+ function run(script, args = []) {
11
+ try {
12
+ const out = execFileSync(process.execPath, [script, ...args], {
13
+ encoding: 'utf8', timeout: 15000,
14
+ cwd: process.cwd(),
15
+ });
16
+ return JSON.parse(out.trim());
17
+ } catch {
18
+ return null;
19
+ }
20
+ }
21
+
22
+ function check(label, condition, fix = null) {
23
+ if (condition) {
24
+ console.log(`✓ ${label}`);
25
+ return true;
26
+ } else {
27
+ console.log(`✗ ${label}`);
28
+ if (fix) console.log(` Fix: ${fix}`);
29
+ return false;
30
+ }
31
+ }
32
+
33
+ function warn(label) {
34
+ console.log(`! ${label}`);
35
+ }
36
+
37
+ const configDir = join(homedir(), '.adaptive-director');
38
+ const configPath = join(configDir, 'config.json');
39
+ const pkgRoot = join(__dirname, '..');
40
+ const skillRoot = join(pkgRoot, 'skills', 'adaptive-director');
41
+
42
+ console.log('Adaptive Director Doctor\n');
43
+
44
+ let allGood = true;
45
+
46
+ // ── Package & Skill files ──────────────────────────────────────────────────
47
+ allGood &= check('Package installed', existsSync(join(pkgRoot, 'package.json')));
48
+ allGood &= check('Skill source exists', existsSync(skillRoot));
49
+ allGood &= check('SKILL.md exists', existsSync(join(skillRoot, 'SKILL.md')));
50
+ allGood &= check('references/ exists', existsSync(join(skillRoot, 'references')));
51
+ allGood &= check('templates/ exists', existsSync(join(skillRoot, 'templates')));
52
+ allGood &= check('examples/ exists', existsSync(join(skillRoot, 'examples')));
53
+
54
+ // ── Registry ──────────────────────────────────────────────────────────────
55
+ const registryPath = join(skillRoot, 'data', 'registry.json');
56
+ if (check('Registry exists', existsSync(registryPath))) {
57
+ try {
58
+ JSON.parse(readFileSync(registryPath, 'utf8'));
59
+ check('Registry valid', true);
60
+ } catch {
61
+ allGood &= check('Registry valid', false, 'Reinstall package');
62
+ }
63
+ } else {
64
+ allGood = false;
65
+ }
66
+
67
+ // ── Config ────────────────────────────────────────────────────────────────
68
+ if (check('Config exists', existsSync(configPath), 'adaptive-director setup')) {
69
+ try {
70
+ JSON.parse(readFileSync(configPath, 'utf8'));
71
+ check('Config valid', true);
72
+ } catch {
73
+ allGood &= check('Config valid', false, 'rm ~/.adaptive-director/config.json && adaptive-director setup');
74
+ }
75
+ } else {
76
+ allGood = false;
77
+ }
78
+
79
+ // ── Runtime Skill Scripts ─────────────────────────────────────────────────
80
+ const routePath = join(skillRoot, 'scripts', 'route.mjs');
81
+ if (existsSync(routePath)) {
82
+ try {
83
+ const testPayload = JSON.stringify({ taskSize: 'small', phase: 'implement', budget: 'balanced', allowMax: false, delegateEnabled: false });
84
+ const out = execFileSync(process.execPath, [routePath, '--input', testPayload], {
85
+ encoding: 'utf8', timeout: 8000
86
+ });
87
+ const result = JSON.parse(out.trim());
88
+ const valid = result && result.agent && result.effort && result.execution;
89
+ allGood &= check('Routing script works', valid, 'Check Node version or reinstall');
90
+ } catch (e) {
91
+ allGood &= check('Routing script works', false, `Error: ${e.message}`);
92
+ }
93
+ } else {
94
+ allGood &= check('Routing script works', false, 'Script missing in skills/adaptive-director/scripts — reinstall package');
95
+ }
96
+
97
+ allGood &= check('Run state script exists', existsSync(join(skillRoot, 'scripts', 'run-state.mjs')));
98
+ allGood &= check('Resume script exists', existsSync(join(skillRoot, 'scripts', 'resume.mjs')));
99
+
100
+ // ── Host discovery ────────────────────────────────────────────────────────
101
+ console.log('');
102
+ const discovery = run(join(__dirname, 'discover.mjs'));
103
+ if (discovery) {
104
+ let anyHost = false;
105
+ for (const [id, info] of Object.entries(discovery.agents ?? {})) {
106
+ if (!info.installed) continue;
107
+ anyHost = true;
108
+ check(`${id} detected`, true);
109
+ const hostHasSkill = info.skillPath && (
110
+ existsSync(join(info.skillPath, 'adaptive-director', 'SKILL.md')) ||
111
+ existsSync(join(info.skillPath, 'Adaptive-Director', 'SKILL.md'))
112
+ );
113
+ if (hostHasSkill) {
114
+ check(`Skill installed for ${id}`, true);
115
+ } else if (info.skillPath) {
116
+ allGood &= check(`Skill installed for ${id}`, false,
117
+ `adaptive-director install ${info.skillPath}`);
118
+ } else {
119
+ warn(`Skill for ${id}: skill directory unknown (run setup after configuring host)`);
120
+ }
121
+ }
122
+ if (!anyHost) warn('No supported hosts detected');
123
+
124
+ console.log('');
125
+ const ds = discovery.delegateSkills ?? { installed: false };
126
+ if (ds.installed) {
127
+ check(`delegate-skills detected (${Object.keys(ds.lanes ?? {}).length} lane(s))`, true);
128
+ } else {
129
+ warn('delegate-skills not detected (optional)');
130
+ }
131
+ } else {
132
+ allGood &= check('Discovery script works', false, 'Check Node version or reinstall');
133
+ }
134
+
135
+ console.log('');
136
+ if (allGood) {
137
+ console.log('Ready.');
138
+ } else {
139
+ console.log('Some checks failed. Run "adaptive-director setup" to fix.');
140
+ process.exitCode = 1;
141
+ }
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env node
2
+ import { execFileSync } from 'node:child_process';
3
+ import { mkdirSync, cpSync, rmSync, existsSync } from 'node:fs';
4
+ import { join, dirname } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
+ const projectRoot = join(__dirname, '..');
9
+
10
+ const args = process.argv.slice(2);
11
+ const targets = args.filter(a => !a.startsWith('-'));
12
+
13
+ const canonicalSkillSource = join(projectRoot, 'skills', 'adaptive-director');
14
+
15
+ /**
16
+ * Copy Adaptive Director Skill files into a host skill directory.
17
+ * Idempotent: removes old copy first, then copies fresh from skills/adaptive-director.
18
+ */
19
+ function installInto(hostSkillDir) {
20
+ const dest = join(hostSkillDir, 'adaptive-director');
21
+ console.log(` Installing into ${dest}...`);
22
+ if (!existsSync(canonicalSkillSource)) {
23
+ console.error(` Error: Canonical skill source not found at ${canonicalSkillSource}`);
24
+ process.exit(1);
25
+ }
26
+ // Remove legacy title-case folder if different and present
27
+ const legacyDest = join(hostSkillDir, 'Adaptive-Director');
28
+ if (legacyDest.toLowerCase() === dest.toLowerCase() && existsSync(legacyDest)) {
29
+ rmSync(legacyDest, { recursive: true, force: true });
30
+ } else if (existsSync(dest)) {
31
+ rmSync(dest, { recursive: true, force: true });
32
+ }
33
+ mkdirSync(dest, { recursive: true });
34
+ cpSync(canonicalSkillSource, dest, { recursive: true });
35
+ console.log(` ✓ Installed successfully at ${dest}`);
36
+ }
37
+
38
+ // ─── If paths were passed as arguments, install into those directly ─────────
39
+ if (targets.length > 0) {
40
+ for (const target of targets) {
41
+ installInto(target);
42
+ }
43
+ process.exit(0);
44
+ }
45
+
46
+ // ─── No args: auto-discover hosts and install ───────────────────────────────
47
+ const discoverScript = join(__dirname, 'discover.mjs');
48
+
49
+ function runDiscover() {
50
+ try {
51
+ const out = execFileSync(process.execPath, [discoverScript], {
52
+ encoding: 'utf8', timeout: 15000, cwd: process.cwd(),
53
+ });
54
+ return JSON.parse(out.trim());
55
+ } catch {
56
+ return null;
57
+ }
58
+ }
59
+
60
+ console.log('\n Adaptive Director — Install\n');
61
+ console.log(' Discovering hosts...\n');
62
+
63
+ const discovery = runDiscover();
64
+ if (!discovery) {
65
+ console.error(' Error: discovery failed.');
66
+ process.exit(1);
67
+ }
68
+
69
+ const hostsWithSkillDir = [];
70
+ for (const [id, info] of Object.entries(discovery.agents ?? {})) {
71
+ if (info.installed && info.skillPath) {
72
+ hostsWithSkillDir.push({ id, path: info.skillPath });
73
+ } else if (info.installed) {
74
+ console.log(` ! ${id}: installed but skill directory could not be resolved. Skipping.`);
75
+ }
76
+ }
77
+
78
+ if (hostsWithSkillDir.length === 0) {
79
+ console.log(' No known host skill directories found. Nothing to install.');
80
+ process.exit(0);
81
+ }
82
+
83
+ console.log(' Installing into detected hosts:');
84
+ for (const h of hostsWithSkillDir) {
85
+ console.log(` [→] ${h.id} — ${h.path}`);
86
+ }
87
+ console.log('');
88
+
89
+ for (const h of hostsWithSkillDir) {
90
+ try {
91
+ installInto(h.path);
92
+ } catch (e) {
93
+ console.error(` ✗ Failed to install for ${h.id}: ${e.message}`);
94
+ }
95
+ }
96
+
97
+ console.log('\n Done. Run "adaptive-director doctor" to verify.\n');
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env node
2
+ import { execFileSync } from 'node:child_process';
3
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
4
+ import { join, dirname } from 'node:path';
5
+ import { homedir } from 'node:os';
6
+ import { fileURLToPath } from 'node:url';
7
+
8
+ const __dirname = dirname(fileURLToPath(import.meta.url));
9
+
10
+ function run(script, args = []) {
11
+ try {
12
+ const out = execFileSync(process.execPath, [script, ...args], {
13
+ encoding: 'utf8', timeout: 15000,
14
+ cwd: process.cwd(),
15
+ });
16
+ return JSON.parse(out.trim());
17
+ } catch (e) {
18
+ return null;
19
+ }
20
+ }
21
+
22
+ const configDir = join(homedir(), '.adaptive-director');
23
+ const configPath = join(configDir, 'config.json');
24
+
25
+ console.log('Refreshing Adaptive Director config...\n');
26
+
27
+ const discovery = run(join(__dirname, 'discover.mjs'));
28
+ if (!discovery) {
29
+ console.error('✗ Discovery failed.');
30
+ process.exit(1);
31
+ }
32
+
33
+ let existingConfig = {};
34
+ if (existsSync(configPath)) {
35
+ try {
36
+ existingConfig = JSON.parse(readFileSync(configPath, 'utf8'));
37
+ } catch {
38
+ console.warn('! Existing config is invalid, creating a new one.');
39
+ }
40
+ }
41
+
42
+ const config = {
43
+ version: 1,
44
+ defaultBudget: existingConfig.defaultBudget || 'balanced',
45
+ allowMax: existingConfig.allowMax || false,
46
+ delegateEnabled: existingConfig.delegateEnabled || false,
47
+ hosts: {},
48
+ overrides: existingConfig.overrides || {}
49
+ };
50
+
51
+ for (const [id, info] of Object.entries(discovery.agents ?? {})) {
52
+ if (info.installed) {
53
+ config.hosts[id] = {
54
+ enabled: existingConfig.hosts?.[id]?.enabled ?? true,
55
+ skillPath: info.skillPath
56
+ };
57
+ }
58
+ }
59
+
60
+ writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
61
+
62
+ console.log(`✓ Config updated successfully.`);