@olives/devos 2.1.1 → 4.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 (45) hide show
  1. package/.agents/AGENTS.md +59 -0
  2. package/.agents/agents/dba.md +1 -0
  3. package/.agents/agents/developer.md +1 -0
  4. package/.agents/agents/eval-engineer.md +26 -0
  5. package/.agents/agents/executive-proxy.md +60 -0
  6. package/.agents/agents/orchestrator.md +30 -5
  7. package/.agents/agents/qa.md +9 -4
  8. package/.agents/agents/release-manager.md +5 -0
  9. package/.agents/agents/telemetry.md +36 -0
  10. package/.agents/agents/tester.md +3 -0
  11. package/.agents/agents/ui-designer.md +46 -0
  12. package/.agents/commands/auto.md +18 -0
  13. package/.agents/commands/design.md +15 -0
  14. package/.agents/commands/humanize.md +19 -0
  15. package/.agents/commands/task.md +16 -0
  16. package/.agents/commands/telemetry.md +14 -0
  17. package/.agents/hooks/pre-tool-use.sh +93 -0
  18. package/.agents/hooks/session-end.sh +28 -0
  19. package/.agents/hooks/session-start.sh +30 -0
  20. package/.agents/manifest.json +20 -0
  21. package/.agents/memory/context.json +7 -0
  22. package/.agents/memory/decisions/ADR-000-template.md +34 -0
  23. package/.agents/memory/handoffs/handoff-template.md +27 -0
  24. package/.agents/packs.json +118 -0
  25. package/.agents/scripts/humanize-check.sh +86 -0
  26. package/.agents/skills/autonomous-sdlc/SKILL.md +102 -0
  27. package/.agents/skills/humanizer/SKILL.md +135 -0
  28. package/.agents/skills/shared-memory/SKILL.md +38 -0
  29. package/.agents/skills/task-board/SKILL.md +26 -0
  30. package/.agents/skills/telemetry/SKILL.md +81 -0
  31. package/.agents/skills/testing-guide/SKILL.md +105 -0
  32. package/.agents/telemetry/.gitkeep +0 -0
  33. package/VERSION +1 -1
  34. package/bin/devos.js +1048 -74
  35. package/docs/2026-09-03-devos-ecc-gap-analysis.md +187 -0
  36. package/docs/2026-09-12-devos-v4-roadmap-research.md +314 -0
  37. package/docs/ARCHITECTURE.md +88 -6
  38. package/docs/CHANGELOG.md +13 -0
  39. package/docs/CURRENT_STATE.md +29 -23
  40. package/docs/PLAN_RUNTIME_HARNESS_PACKS.md +71 -0
  41. package/docs/SLASH_COMMANDS.md +35 -0
  42. package/docs/TASK_BOARD.md +50 -0
  43. package/docs/TUTORIAL.md +1 -1
  44. package/package.json +4 -1
  45. package/scripts/smoke-test.js +103 -0
package/bin/devos.js CHANGED
@@ -14,9 +14,11 @@ const readline = require('readline');
14
14
  const TEMPLATE_DIR = path.resolve(__dirname, '..');
15
15
  const TARGET_DIR = process.cwd();
16
16
  const PKG_PATH = path.join(TEMPLATE_DIR, 'package.json');
17
- const PKG = fs.existsSync(PKG_PATH) ? JSON.parse(fs.readFileSync(PKG_PATH, 'utf8')) : { version: '2.1.0' };
17
+ const PKG = fs.existsSync(PKG_PATH) ? JSON.parse(fs.readFileSync(PKG_PATH, 'utf8')) : { version: '3.0.0' };
18
18
 
19
19
  const STACKS = ['nextjs', 'laravel', 'django', 'react-native', 'express', 'fastapi', 'universal'];
20
+ const HARNESSES = ['claude', 'cursor', 'opencode', 'antigravity', 'gemini', 'codex'];
21
+ const PLATFORMS = ['claude', 'antigravity', 'cursor', 'opencode', 'codex', 'all'];
20
22
 
21
23
  // ANSI color formatting — disabled when piped, in CI, or when NO_COLOR is set
22
24
  const useColor = Boolean(process.stdout.isTTY) && !process.env.NO_COLOR && process.env.TERM !== 'dumb';
@@ -36,17 +38,51 @@ Object.keys(PALETTE).forEach((k) => { colors[k] = useColor ? PALETTE[k] : ''; })
36
38
  const BANNER_WIDTH = 48;
37
39
  const RULE = '─'.repeat(BANNER_WIDTH);
38
40
 
41
+ // Core Rules and Protocols
42
+ const DEVOS_RULES_DIGEST = [
43
+ '1. Zero Destructive Actions: Never delete, drop, or truncate without an approved dry-run plan.',
44
+ '2. Zero Secrets Stored or Logged: API keys & credentials must NEVER be hardcoded. Use `process.env.*`.',
45
+ '3. Mechanical Commit Gate: Raw `git commit` is BLOCKED. Always commit via `.agents/scripts/commit.sh`.',
46
+ '4. Staged Review: Agents write code but NEVER auto-commit. Present summaries for human review first.',
47
+ '5. Circuit Breaker: Halt after 3 failed agent loop iterations and escalate to the human.',
48
+ '6. Verify Before Implementing: Confirm actual library APIs and patterns before authoring code.',
49
+ '7. No Heavy Dependencies: Packages >5MB or >50 dependencies require explicit human approval.',
50
+ '8. Documentation in /docs: All plans, PRDs, architecture notes, and reports belong in `/docs/`.',
51
+ '9. Session-Start Freshness: Run `git fetch --all --prune` and check `git status -sb` before scoping work.',
52
+ '10. Session-End State Obligation: Update `docs/CURRENT_STATE.md` before concluding any session modifying code.',
53
+ '11. Shared Memory Synchronization: Maintain architectural records in `.agents/memory/` (ADRs & handoffs).',
54
+ '12. Task Board Governance: Keep task states in `docs/TASK_BOARD.md` aligned with current execution.'
55
+ ];
56
+
57
+ const SOLO_SESSION_PROTOCOL = [
58
+ '- Step 1: Check freshness via `git fetch --all --prune` and `git status -sb`.',
59
+ '- Step 2: Implement following `CODING_STANDARDS.md`.',
60
+ '- Step 3: Self-verify with typecheck (`tsc --noEmit` or equivalent) and automated tests.',
61
+ '- Step 4: Present staged review summary to human.',
62
+ '- Step 5: Route commit through `.agents/scripts/commit.sh`.',
63
+ '- Step 6: Update `docs/CURRENT_STATE.md` and log incidents in `docs/LESSONS.md`.',
64
+ '- Escalation: DB schema changes (DBA), security alterations (Security), or loops exceeding 3 attempts must escalate to human.'
65
+ ];
66
+
39
67
  // Flags parser helper
40
68
  function parseArgs(args) {
41
69
  const flags = {
42
70
  stack: null,
71
+ platform: null,
43
72
  fresh: false,
44
73
  existing: false,
45
74
  json: false,
46
75
  quiet: false,
47
76
  claude: true,
48
77
  help: false,
49
- version: false
78
+ version: false,
79
+ allSkills: false,
80
+ allHarnesses: false,
81
+ harness: null,
82
+ hooks: true,
83
+ telemetry: true,
84
+ mode: null,
85
+ skills: false
50
86
  };
51
87
 
52
88
  const positional = [];
@@ -67,6 +103,27 @@ function parseArgs(args) {
67
103
  flags.quiet = true;
68
104
  } else if (arg === '--no-claude') {
69
105
  flags.claude = false;
106
+ } else if (arg === '--no-hooks') {
107
+ flags.hooks = false;
108
+ } else if (arg === '--all-skills') {
109
+ flags.allSkills = true;
110
+ } else if (arg === '--all-harnesses') {
111
+ flags.allHarnesses = true;
112
+ } else if (arg === '--no-telemetry') {
113
+ flags.telemetry = false;
114
+ } else if (arg === '--telemetry') {
115
+ flags.telemetry = true;
116
+ } else if (arg === '--skills') {
117
+ flags.skills = true;
118
+ } else if (arg === '--mode' || arg === '-m') {
119
+ flags.mode = args[i + 1] || null;
120
+ i++;
121
+ } else if (arg === '--platform' || arg === '-p') {
122
+ flags.platform = args[i + 1] || null;
123
+ i++;
124
+ } else if (arg === '--harness') {
125
+ flags.harness = args[i + 1] || null;
126
+ i++;
70
127
  } else if (arg === '--stack' || arg === '-s') {
71
128
  flags.stack = args[i + 1] || null;
72
129
  i++;
@@ -114,15 +171,28 @@ function printHelp() {
114
171
 
115
172
  console.log(`${colors.bold}CORE COMMANDS${colors.reset}`);
116
173
  console.log(` ${colors.green}init${colors.reset}, ${colors.green}setup${colors.reset} Initialize Dev-OS multi-agent environment in target project`);
117
- console.log(` ${colors.green}update${colors.reset}, ${colors.green}upgrade${colors.reset} Safely refresh .agents/, skills, commands, and hooks`);
118
- console.log(` ${colors.green}doctor${colors.reset}, ${colors.green}check${colors.reset} Diagnose project setup, permissions, commit script, and health`);
174
+ console.log(` ${colors.green}update${colors.reset}, ${colors.green}upgrade${colors.reset} Safely refresh .agents/, skills, commands, harnesses, and hooks`);
175
+ console.log(` ${colors.green}run${colors.reset}, ${colors.green}auto${colors.reset} Launch autonomous hands-off SDLC mode (devos run "<product idea>")`);
176
+ console.log(` ${colors.green}telemetry${colors.reset} Manage anonymous failure telemetry (status, report, enable, disable)`);
177
+ console.log(` ${colors.green}doctor${colors.reset}, ${colors.green}check${colors.reset} Diagnose setup, hooks, memory vault, task board, and health`);
178
+ console.log(` ${colors.green}pack${colors.reset}, ${colors.green}packs${colors.reset} Manage composable capability packs (pack list, pack add <name>)`);
179
+ console.log(` ${colors.green}skill${colors.reset}, ${colors.green}skills${colors.reset} Manage agent skills from skills.sh (skill list, add <repo>, update, find)`);
180
+ console.log(` ${colors.green}memory${colors.reset} Shared memory vault operations (memory list, memory handoff, memory doctor)`);
119
181
  console.log(` ${colors.green}list${colors.reset}, ${colors.green}agents${colors.reset} Display active agent personas and installed specialist skills`);
120
182
  console.log(` ${colors.green}status${colors.reset} Show active project configuration, detected stack, and health summary`);
121
183
  console.log(` ${colors.green}version${colors.reset} Print Dev-OS CLI version, Node runtime, and environment information`);
122
184
  console.log(` ${colors.green}help${colors.reset} Display this command reference\n`);
123
185
 
124
186
  console.log(`${colors.bold}FLAGS${colors.reset}`);
125
- console.log(` ${colors.cyan}-s, --stack <name>${colors.reset} Target stack (${STACKS.join(', ')})`);
187
+ console.log(` ${colors.cyan}-s, --stack <name>${colors.reset} Target stack (${STACKS.join(', ')})`);
188
+ console.log(` ${colors.cyan}-p, --platform <name>${colors.reset} Target AI platform (${PLATFORMS.join(', ')})`);
189
+ console.log(` ${colors.cyan}-m, --mode <name>${colors.reset} SDLC execution mode (interactive, guided, auto, audit)`);
190
+ console.log(` ${colors.cyan}--telemetry / --no-telemetry${colors.reset} Enable or disable anonymous failure telemetry (default: on)`);
191
+ console.log(` ${colors.cyan}--harness <list>${colors.reset} Target AI harnesses: ${HARNESSES.join(', ')}`);
192
+ console.log(` ${colors.cyan}--all-harnesses${colors.reset} Generate configurations for all supported AI harnesses`);
193
+ console.log(` ${colors.cyan}--all-skills${colors.reset} Install all skills instead of lean stack pack`);
194
+ console.log(` ${colors.cyan}--skills${colors.reset} Update or sync installed skills from upstream registry`);
195
+ console.log(` ${colors.cyan}--no-hooks${colors.reset} Skip wiring runtime lifecycle hooks (.claude/hooks.json)`);
126
196
  console.log(` ${colors.cyan}--fresh${colors.reset} Non-interactive fresh project initialization`);
127
197
  console.log(` ${colors.cyan}--existing${colors.reset} Non-interactive existing project initialization`);
128
198
  console.log(` ${colors.cyan}--no-claude${colors.reset} Skip generating .claude/ (Claude Code commands & agents)`);
@@ -134,8 +204,9 @@ function printHelp() {
134
204
  console.log(`${colors.bold}EXAMPLES${colors.reset}`);
135
205
  console.log(` $ ${colors.cyan}npx @olives/devos init${colors.reset}`);
136
206
  console.log(` $ ${colors.cyan}npx @olives/devos init --stack nextjs --existing${colors.reset}`);
137
- console.log(` $ ${colors.cyan}npx @olives/devos doctor${colors.reset}`);
138
- console.log(` $ ${colors.cyan}npx @olives/devos list${colors.reset}\n`);
207
+ console.log(` $ ${colors.cyan}npx @olives/devos pack list${colors.reset}`);
208
+ console.log(` $ ${colors.cyan}npx @olives/devos memory handoff${colors.reset}`);
209
+ console.log(` $ ${colors.cyan}npx @olives/devos doctor${colors.reset}\n`);
139
210
 
140
211
  console.log(`${colors.gray}Documentation & Guides: https://github.com/olitech1010/dev-os${colors.reset}\n`);
141
212
  }
@@ -206,11 +277,23 @@ function hintFor(err) {
206
277
  async function promptInitOptions(flags) {
207
278
  let isFresh = false;
208
279
  let stack = flags.stack || 'universal';
280
+ let platform = flags.platform || flags.harness || (flags.allHarnesses ? 'all' : null);
209
281
 
210
282
  if (flags.stack && !STACKS.includes(flags.stack.toLowerCase())) {
211
283
  throw new Error(`Unknown stack '${flags.stack}'. Valid stacks: ${STACKS.join(', ')}`);
212
284
  }
213
285
 
286
+ if (platform && platform !== 'all') {
287
+ const list = platform.split(',').map((s) => s.trim().toLowerCase());
288
+ for (let item of list) {
289
+ if (item === 'gemini') item = 'antigravity';
290
+ if (item === 'windsurf') item = 'codex';
291
+ if (!HARNESSES.includes(item) && !PLATFORMS.includes(item)) {
292
+ throw new Error(`Unknown platform/harness '${item}'. Valid options: ${PLATFORMS.join(', ')}`);
293
+ }
294
+ }
295
+ }
296
+
214
297
  if (flags.fresh) {
215
298
  isFresh = true;
216
299
  } else if (flags.existing) {
@@ -250,14 +333,66 @@ async function promptInitOptions(flags) {
250
333
  default: stack = 'universal'; break;
251
334
  }
252
335
  }
336
+
337
+ if (!platform) {
338
+ console.log(`\n${colors.bold}Step 3 · AI Coding Platform / Harness${colors.reset}`);
339
+ console.log(` 1) Claude Code (Anthropic Claude CLI, .claude/ commands & agents)`);
340
+ console.log(` 2) Google Antigravity / Gemini (ANTIGRAVITY.md, GEMINI.md)`);
341
+ console.log(` 3) Cursor (.cursor/rules/devos.mdc, .cursorrules)`);
342
+ console.log(` 4) OpenCode (.opencode/rules/, OPENCODE.md)`);
343
+ console.log(` 5) Codex / Windsurf (.codex/instructions.md, .windsurfrules)`);
344
+ console.log(` 6) All Platforms (Universal Multi-Platform Setup) [Default]`);
345
+
346
+ const platAns = await ask(`\n${colors.cyan}Select option [1-6] (default 6): ${colors.reset}`);
347
+ switch (platAns.trim()) {
348
+ case '1': platform = 'claude'; break;
349
+ case '2': platform = 'antigravity'; break;
350
+ case '3': platform = 'cursor'; break;
351
+ case '4': platform = 'opencode'; break;
352
+ case '5': platform = 'codex'; break;
353
+ default: platform = 'all'; break;
354
+ }
355
+ }
356
+
357
+ let telemetry = flags.telemetry;
358
+ if (flags.telemetry === undefined || flags.telemetry === null) {
359
+ console.log(`\n${colors.bold}Step 4 · Anonymous Failure Telemetry${colors.reset}`);
360
+ console.log(` 1) On (Recommended) — Anonymously captures execution errors & RCA reports to improve Dev-OS`);
361
+ console.log(` 2) Off — Completely disable anonymous failure logging`);
362
+ const telemAns = await ask(`\n${colors.cyan}Select option [1-2] (default 1): ${colors.reset}`);
363
+ telemetry = telemAns.trim() !== '2';
364
+ }
365
+
366
+ let mode = flags.mode || 'interactive';
367
+ if (!flags.mode) {
368
+ console.log(`\n${colors.bold}Step 5 · Default SDLC Execution Mode${colors.reset}`);
369
+ console.log(` 1) Interactive (Default pair-programming with staged human reviews)`);
370
+ console.log(` 2) Guided (Step-by-step confirmation checkpoints at each SDLC stage)`);
371
+ console.log(` 3) Auto (Hands-off MVP builder for founders/CEOs — idea to full working MVP)`);
372
+ console.log(` 4) Audit (Read-only security, architecture, and code health evaluation)`);
373
+ const modeAns = await ask(`\n${colors.cyan}Select option [1-4] (default 1): ${colors.reset}`);
374
+ switch (modeAns.trim()) {
375
+ case '2': mode = 'guided'; break;
376
+ case '3': mode = 'auto'; break;
377
+ case '4': mode = 'audit'; break;
378
+ default: mode = 'interactive'; break;
379
+ }
380
+ }
381
+
253
382
  rl.close();
254
383
  }
255
384
 
256
- return { isFresh, stack: stack.toLowerCase() };
385
+ return {
386
+ isFresh,
387
+ stack: stack.toLowerCase(),
388
+ platform: (platform || 'all').toLowerCase(),
389
+ telemetry: flags.telemetry !== false,
390
+ mode: (flags.mode || 'interactive').toLowerCase()
391
+ };
257
392
  }
258
393
 
259
394
  // ---------------------------------------------------------------------------
260
- // Claude Code integration — generate .claude/ from the .agents/ sources
395
+ // Multi-Harness Generators
261
396
  // ---------------------------------------------------------------------------
262
397
 
263
398
  const AGENT_DESCRIPTIONS = {
@@ -271,7 +406,11 @@ const AGENT_DESCRIPTIONS = {
271
406
  architect: 'Dev-OS system architect. Runs project inception (grill-me), designs architecture, and produces requirements documents.',
272
407
  researcher: 'Dev-OS research specialist. Investigates libraries, APIs, compatibility, and best practices; returns concise verdicts.',
273
408
  'memory-manager': 'Dev-OS memory custodian. Maintains docs/CURRENT_STATE.md and docs/LESSONS.md, compacts context, and manages session handoffs.',
274
- 'release-manager': 'Dev-OS release specialist. Owns semantic versioning, changelog entries, and release notes.'
409
+ 'release-manager': 'Dev-OS release specialist. Owns semantic versioning, changelog entries, and release notes.',
410
+ 'ui-designer': 'Dev-OS UI/UX design specialist. Formulates design systems, extracts tokens from ui-ux-pro-max, and authors docs/DESIGN.md to satisfy the Mandatory Design Gate.',
411
+ 'executive-proxy': 'Dev-OS autonomous tech lead proxy. Oversees hands-off MVP delivery from idea to working software across all 10 SDLC stages.',
412
+ telemetry: 'Dev-OS observability specialist. Tracks runtime errors, failure logs in .agents/telemetry/, and drafts RCA reports.',
413
+ 'eval-engineer': 'Dev-OS evaluation engineer. Measures capability benchmarks, pass@k, and prevents workflow regressions.'
275
414
  };
276
415
 
277
416
  function generateClaudeCommands(destAgents, destClaude) {
@@ -352,29 +491,16 @@ function bootstrapClaudeMd(targetDir) {
352
491
  'This project uses Dev-OS by Olives Technologies.',
353
492
  '',
354
493
  '### Hard Rules Digest (Must be strictly obeyed at all times)',
355
- '1. Zero Destructive Actions: Never delete, drop, or truncate without an approved dry-run plan.',
356
- '2. Zero Secrets Stored or Logged: API keys & credentials must NEVER be hardcoded. Use `process.env.*`.',
357
- '3. Mechanical Commit Gate: Raw `git commit` is BLOCKED. Always commit via `.agents/scripts/commit.sh`.',
358
- '4. Staged Review: Agents write code but NEVER auto-commit. Present summaries for human review first.',
359
- '5. Circuit Breaker: Halt after 3 failed agent loop iterations and escalate to the human.',
360
- '6. Verify Before Implementing: Confirm actual library APIs and patterns before authoring code.',
361
- '7. No Heavy Dependencies: Packages >5MB or >50 dependencies require explicit human approval.',
362
- '8. Documentation in /docs: All plans, PRDs, architecture notes, and reports belong in `/docs/`.',
363
- '9. Session-Start Freshness: Run `git fetch --all --prune` and check `git status -sb` before scoping work.',
364
- '10. Session-End State Obligation: Update `docs/CURRENT_STATE.md` before concluding any session modifying code.',
494
+ ...DEVOS_RULES_DIGEST,
365
495
  '',
366
496
  '### Solo Session Protocol (Single-Agent Work)',
367
- '- Step 1: Check freshness via `git fetch --all --prune` and `git status -sb`.',
368
- '- Step 2: Implement following `CODING_STANDARDS.md`.',
369
- '- Step 3: Self-verify with typecheck (`tsc --noEmit` or equivalent) and automated tests.',
370
- '- Step 4: Present staged review summary to human.',
371
- '- Step 5: Route commit through `.agents/scripts/commit.sh`.',
372
- '- Step 6: Update `docs/CURRENT_STATE.md` and log incidents in `docs/LESSONS.md`.',
373
- '- Escalation: DB schema changes (DBA), security alterations (Security), or loops exceeding 3 attempts must escalate to human.',
497
+ ...SOLO_SESSION_PROTOCOL,
374
498
  '',
375
499
  '### Tooling & Personas',
376
500
  '- Slash commands: `.claude/commands/` (generated from `.agents/commands/` — refresh with `devos update`).',
377
501
  '- Agent personas: `.claude/agents/` (generated from `.agents/agents/`).',
502
+ '- Task Board: `docs/TASK_BOARD.md` (active DAG state).',
503
+ '- Memory Vault: `.agents/memory/` (ADRs in `decisions/`, handoffs in `handoffs/`).',
378
504
  '- Coding standards: `CODING_STANDARDS.md`.',
379
505
  '- Master roster & full rules: `.agents/AGENTS.md`.',
380
506
  endMarker,
@@ -396,6 +522,245 @@ function bootstrapClaudeMd(targetDir) {
396
522
  return 'created';
397
523
  }
398
524
 
525
+ function generateCursorConfig(targetDir) {
526
+ const cursorDir = path.join(targetDir, '.cursor', 'rules');
527
+ fs.mkdirSync(cursorDir, { recursive: true });
528
+ const mdcPath = path.join(cursorDir, 'devos.mdc');
529
+ const mdcContent = [
530
+ '---',
531
+ 'description: Dev-OS Autonomous Multi-Agent Engineering rules, Hard Rules, and solo session protocols',
532
+ 'globs: *',
533
+ 'alwaysApply: true',
534
+ '---',
535
+ '',
536
+ '# Dev-OS — Multi-Agent Engineering OS (Cursor Rules)',
537
+ '',
538
+ 'This project uses Dev-OS by Olives Technologies.',
539
+ '',
540
+ '### Hard Rules Digest (Must be strictly obeyed at all times)',
541
+ ...DEVOS_RULES_DIGEST,
542
+ '',
543
+ '### Solo Session Protocol',
544
+ ...SOLO_SESSION_PROTOCOL,
545
+ '',
546
+ '### Mechanical Commit Gate',
547
+ 'Raw `git commit` is strictly blocked. Always commit through `.agents/scripts/commit.sh`.',
548
+ ''
549
+ ].join('\n');
550
+ fs.writeFileSync(mdcPath, mdcContent, 'utf8');
551
+
552
+ const cursorrulesPath = path.join(targetDir, '.cursorrules');
553
+ const cursorrulesContent = [
554
+ '# Dev-OS Cursor Rules',
555
+ 'Follow all Hard Rules defined in .agents/AGENTS.md and .cursor/rules/devos.mdc.',
556
+ 'Always use .agents/scripts/commit.sh for committing changes.',
557
+ ''
558
+ ].join('\n');
559
+ fs.writeFileSync(cursorrulesPath, cursorrulesContent, 'utf8');
560
+
561
+ return 'rules/devos.mdc + .cursorrules';
562
+ }
563
+
564
+ function generateOpenCodeConfig(targetDir) {
565
+ const opencodeDir = path.join(targetDir, '.opencode');
566
+ const rulesDir = path.join(opencodeDir, 'rules');
567
+ fs.mkdirSync(rulesDir, { recursive: true });
568
+
569
+ const rulesPath = path.join(rulesDir, 'devos-rules.md');
570
+ const rulesContent = [
571
+ '# OpenCode Dev-OS Rules',
572
+ '',
573
+ '## Hard Rules Digest',
574
+ ...DEVOS_RULES_DIGEST,
575
+ '',
576
+ '## Solo Session Protocol',
577
+ ...SOLO_SESSION_PROTOCOL,
578
+ '',
579
+ '## Team Roster & Routing',
580
+ 'Read `.agents/AGENTS.md` for agent roles (Orchestrator, Developer, QA, Tester, Security, DevOps, etc.).',
581
+ 'Route all git commits through `.agents/scripts/commit.sh`.',
582
+ ''
583
+ ].join('\n');
584
+ fs.writeFileSync(rulesPath, rulesContent, 'utf8');
585
+
586
+ const openCodeMdPath = path.join(targetDir, 'OPENCODE.md');
587
+ const openCodeMdContent = [
588
+ '# Dev-OS — OpenCode Instructions',
589
+ '',
590
+ 'This project uses Dev-OS by Olives Technologies.',
591
+ '',
592
+ '### Hard Rules Digest',
593
+ ...DEVOS_RULES_DIGEST,
594
+ '',
595
+ '### Solo Session Protocol',
596
+ ...SOLO_SESSION_PROTOCOL,
597
+ '',
598
+ '### Core Resources',
599
+ '- Personas: `.agents/agents/`',
600
+ '- Skills: `.agents/skills/`',
601
+ '- Task Board: `docs/TASK_BOARD.md`',
602
+ '- Memory Vault: `.agents/memory/`',
603
+ '- Commit Gate: `.agents/scripts/commit.sh`',
604
+ ''
605
+ ].join('\n');
606
+ fs.writeFileSync(openCodeMdPath, openCodeMdContent, 'utf8');
607
+
608
+ const configPath = path.join(opencodeDir, 'opencode.json');
609
+ const configContent = JSON.stringify({
610
+ name: 'Dev-OS',
611
+ version: PKG.version,
612
+ rules: ['.opencode/rules/devos-rules.md'],
613
+ manifest: '.agents/manifest.json'
614
+ }, null, 2) + '\n';
615
+ fs.writeFileSync(configPath, configContent, 'utf8');
616
+
617
+ return 'OPENCODE.md + .opencode/rules/devos-rules.md';
618
+ }
619
+
620
+ function generateAntigravityConfig(targetDir) {
621
+ const antigravityMdPath = path.join(targetDir, 'ANTIGRAVITY.md');
622
+ const geminiMdPath = path.join(targetDir, 'GEMINI.md');
623
+ const content = [
624
+ '# Dev-OS — Google Antigravity & Gemini Instructions',
625
+ '',
626
+ 'This project uses Dev-OS by Olives Technologies.',
627
+ '',
628
+ '### Hard Rules Digest (Must be strictly obeyed at all times)',
629
+ ...DEVOS_RULES_DIGEST,
630
+ '',
631
+ '### Solo Session Protocol',
632
+ ...SOLO_SESSION_PROTOCOL,
633
+ '',
634
+ '### Core Resources',
635
+ '- Personas: `.agents/agents/`',
636
+ '- Specialist Skills: `.agents/skills/`',
637
+ '- Task Board: `docs/TASK_BOARD.md`',
638
+ '- Shared Memory Vault: `.agents/memory/`',
639
+ '',
640
+ '### Mechanical Commit Gate',
641
+ 'Never execute raw `git commit`. Always commit through `.agents/scripts/commit.sh`.',
642
+ ''
643
+ ].join('\n');
644
+ fs.writeFileSync(antigravityMdPath, content, 'utf8');
645
+ fs.writeFileSync(geminiMdPath, content, 'utf8');
646
+ return 'ANTIGRAVITY.md + GEMINI.md';
647
+ }
648
+
649
+ function generateGeminiConfig(targetDir) {
650
+ return generateAntigravityConfig(targetDir);
651
+ }
652
+
653
+ function generateCodexConfig(targetDir) {
654
+ const codexDir = path.join(targetDir, '.codex');
655
+ fs.mkdirSync(codexDir, { recursive: true });
656
+ const instructionsPath = path.join(codexDir, 'instructions.md');
657
+ const content = [
658
+ '# Dev-OS — Codex Instructions',
659
+ '',
660
+ '### Hard Rules Digest',
661
+ ...DEVOS_RULES_DIGEST,
662
+ '',
663
+ '### Solo Session Protocol',
664
+ ...SOLO_SESSION_PROTOCOL,
665
+ '',
666
+ 'Always use `.agents/scripts/commit.sh` for commits.',
667
+ ''
668
+ ].join('\n');
669
+ fs.writeFileSync(instructionsPath, content, 'utf8');
670
+
671
+ const windsurfPath = path.join(targetDir, '.windsurfrules');
672
+ fs.writeFileSync(windsurfPath, '# Dev-OS Windsurf Rules\nFollow rules in .agents/AGENTS.md and .codex/instructions.md.\n', 'utf8');
673
+ return '.codex/instructions.md + .windsurfrules';
674
+ }
675
+
676
+ function wireHooks(destAgents, destClaude) {
677
+ const hooksDir = path.join(destAgents, 'hooks');
678
+ if (fs.existsSync(hooksDir)) {
679
+ fs.readdirSync(hooksDir).forEach((file) => {
680
+ if (file.endsWith('.sh')) {
681
+ fs.chmodSync(path.join(hooksDir, file), '755');
682
+ }
683
+ });
684
+ }
685
+
686
+ if (destClaude) {
687
+ fs.mkdirSync(destClaude, { recursive: true });
688
+ const claudeHooksPath = path.join(destClaude, 'hooks.json');
689
+ const hooksConfig = {
690
+ hooks: {
691
+ SessionStart: [{ command: '.agents/hooks/session-start.sh' }],
692
+ PreToolUse: [{ matcher: 'bash', command: '.agents/hooks/pre-tool-use.sh' }],
693
+ SessionEnd: [{ command: '.agents/hooks/session-end.sh' }]
694
+ }
695
+ };
696
+ fs.writeFileSync(claudeHooksPath, JSON.stringify(hooksConfig, null, 2) + '\n', 'utf8');
697
+ return 'executable hooks + .claude/hooks.json';
698
+ }
699
+ return 'executable hooks (.agents/hooks/)';
700
+ }
701
+
702
+ // ---------------------------------------------------------------------------
703
+ // Capability Packs & Skills Copying Helper
704
+ // ---------------------------------------------------------------------------
705
+
706
+ function installSkillsAndPacks(srcAgents, destAgents, stack, allSkills, telemetry = true, mode = 'interactive') {
707
+ const srcSkills = path.join(srcAgents, 'skills');
708
+ const destSkills = path.join(destAgents, 'skills');
709
+ const packsPath = path.join(srcAgents, 'packs.json');
710
+ const manifestPath = path.join(destAgents, 'manifest.json');
711
+ fs.mkdirSync(destSkills, { recursive: true });
712
+
713
+ const packsData = fs.existsSync(packsPath) ? JSON.parse(fs.readFileSync(packsPath, 'utf8')) : null;
714
+
715
+ if (allSkills || !packsData) {
716
+ copyRecursiveSync(srcSkills, destSkills);
717
+ const installed = packsData ? Object.keys(packsData.packs) : ['all'];
718
+ const manifest = {
719
+ version: PKG.version,
720
+ installedPacks: installed,
721
+ hooksEnabled: true,
722
+ telemetry: telemetry ? 'on' : 'off',
723
+ mode: mode || 'interactive',
724
+ updatedAt: new Date().toISOString()
725
+ };
726
+ fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n', 'utf8');
727
+ return { count: countSkills(destSkills), packs: installed };
728
+ }
729
+
730
+ // Lean pack installation
731
+ const installedPacks = ['core'];
732
+ const skillsToInstall = new Set(packsData.packs.core ? packsData.packs.core.skills : []);
733
+
734
+ // Check if stack matches a pack
735
+ Object.keys(packsData.packs).forEach((pKey) => {
736
+ const p = packsData.packs[pKey];
737
+ if (p.stack === stack || pKey === stack) {
738
+ installedPacks.push(pKey);
739
+ p.skills.forEach((s) => skillsToInstall.add(s));
740
+ }
741
+ });
742
+
743
+ skillsToInstall.forEach((skillName) => {
744
+ const src = path.join(srcSkills, skillName);
745
+ const dest = path.join(destSkills, skillName);
746
+ if (fs.existsSync(src)) {
747
+ copyRecursiveSync(src, dest);
748
+ }
749
+ });
750
+
751
+ const manifest = {
752
+ version: PKG.version,
753
+ installedPacks,
754
+ hooksEnabled: true,
755
+ telemetry: telemetry ? 'on' : 'off',
756
+ mode: mode || 'interactive',
757
+ updatedAt: new Date().toISOString()
758
+ };
759
+ fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n', 'utf8');
760
+
761
+ return { count: countSkills(destSkills), packs: installedPacks };
762
+ }
763
+
399
764
  // ---------------------------------------------------------------------------
400
765
  // init
401
766
  // ---------------------------------------------------------------------------
@@ -408,11 +773,39 @@ async function runInit(flags) {
408
773
  console.log(`${colors.yellow}[ WARN ] You are running init inside the Dev-OS source repository itself. Template copy steps will be skipped.${colors.reset}\n`);
409
774
  }
410
775
 
411
- const { isFresh, stack } = await promptInitOptions(flags);
776
+ const { isFresh, stack, platform, telemetry, mode } = await promptInitOptions(flags);
777
+
778
+ // Determine target AI harnesses
779
+ const selectedHarnesses = new Set();
780
+ const rawChoice = flags.harness || flags.platform || platform || (flags.allHarnesses ? 'all' : null);
781
+
782
+ if (rawChoice === 'all' || flags.allHarnesses) {
783
+ selectedHarnesses.add('claude');
784
+ selectedHarnesses.add('antigravity');
785
+ selectedHarnesses.add('cursor');
786
+ selectedHarnesses.add('opencode');
787
+ selectedHarnesses.add('codex');
788
+ } else if (rawChoice) {
789
+ rawChoice.split(',').map((h) => h.trim().toLowerCase()).forEach((h) => {
790
+ if (h === 'gemini') h = 'antigravity';
791
+ if (h === 'windsurf') h = 'codex';
792
+ if (h === 'all') {
793
+ ['claude', 'antigravity', 'cursor', 'opencode', 'codex'].forEach((p) => selectedHarnesses.add(p));
794
+ } else if (HARNESSES.includes(h) || PLATFORMS.includes(h)) {
795
+ selectedHarnesses.add(h);
796
+ }
797
+ });
798
+ } else {
799
+ ['claude', 'antigravity', 'cursor', 'opencode', 'codex'].forEach((p) => selectedHarnesses.add(p));
800
+ }
801
+
802
+ if (flags.claude === false) {
803
+ selectedHarnesses.delete('claude');
804
+ }
412
805
 
413
806
  console.log(`\n${colors.cyan}[ INFO ] Initializing Dev-OS in target directory...${colors.reset}`);
414
807
  console.log(`${colors.gray}Target Path: ${TARGET_DIR}${colors.reset}`);
415
- console.log(`${colors.gray}Mode: ${isFresh ? 'Fresh Project' : 'Existing Project'} | Stack: [${stack.toUpperCase()}]${colors.reset}\n`);
808
+ console.log(`${colors.gray}Mode: ${isFresh ? 'Fresh Project' : 'Existing Project'} | Stack: [${stack.toUpperCase()}] | Platform: [${platform.toUpperCase()}]${colors.reset}\n`);
416
809
 
417
810
  const srcAgents = path.join(TEMPLATE_DIR, '.agents');
418
811
  const destAgents = path.join(TARGET_DIR, '.agents');
@@ -429,7 +822,8 @@ async function runInit(flags) {
429
822
  }
430
823
  };
431
824
 
432
- // Step 1: Back up any existing .agents/, then copy the template
825
+ // Step 1: Back up any existing .agents/, then copy components
826
+ let packSummary = null;
433
827
  if (!insideSource) {
434
828
  if (fs.existsSync(destAgents)) {
435
829
  step('Backing up existing .agents/ to .agents/_backup/', () => {
@@ -439,14 +833,34 @@ async function runInit(flags) {
439
833
  return `saved (${path.relative(TARGET_DIR, backupDir)})`;
440
834
  });
441
835
  }
442
- step('Installing agent roster and skills into .agents/', () => {
443
- copyRecursiveSync(srcAgents, destAgents);
836
+
837
+ step('Installing agent roster, hooks, and memory templates', () => {
838
+ // Copy core structure excluding skills
839
+ const subdirs = ['agents', 'commands', 'hooks', 'memory', 'scripts', 'templates'];
840
+ subdirs.forEach((dir) => {
841
+ const src = path.join(srcAgents, dir);
842
+ const dest = path.join(destAgents, dir);
843
+ if (fs.existsSync(src)) copyRecursiveSync(src, dest);
844
+ });
845
+ ['AGENTS.md', 'README.md', 'packs.json'].forEach((file) => {
846
+ const src = path.join(srcAgents, file);
847
+ const dest = path.join(destAgents, file);
848
+ if (fs.existsSync(src)) fs.copyFileSync(src, dest);
849
+ });
850
+ });
851
+
852
+ step('Installing specialist skills and capability packs', () => {
853
+ packSummary = installSkillsAndPacks(srcAgents, destAgents, stack, flags.allSkills, telemetry, mode);
854
+ return `${packSummary.count} skills (packs: ${packSummary.packs.join(', ')})`;
444
855
  });
445
856
  }
446
857
 
447
- // Step 2: Ensure script permissions (commit gate + hook installer)
448
- step('Configuring commit gate scripts (commit.sh, install-hooks.sh)', () => {
449
- const scripts = ['commit.sh', 'install-hooks.sh'];
858
+ // Ensure telemetry buffer directory exists
859
+ fs.mkdirSync(path.join(destAgents, 'telemetry'), { recursive: true });
860
+
861
+ // Step 2: Ensure script permissions (commit gate, hook installer, humanizer check)
862
+ step('Configuring commit gate and verification scripts', () => {
863
+ const scripts = ['commit.sh', 'install-hooks.sh', 'humanize-check.sh'];
450
864
  const missing = [];
451
865
  scripts.forEach((name) => {
452
866
  const scriptPath = path.join(destAgents, 'scripts', name);
@@ -456,11 +870,19 @@ async function runInit(flags) {
456
870
  missing.push(name);
457
871
  }
458
872
  });
459
- if (missing.length === scripts.length) throw new Error('commit gate scripts are missing from .agents/scripts/');
873
+ if (missing.length === scripts.length) throw new Error('critical scripts are missing from .agents/scripts/');
460
874
  return missing.length ? `partial (missing: ${missing.join(', ')})` : 'executable (755)';
461
875
  });
462
876
 
463
- // Step 2b: Install git pre-commit hook automatically if inside a git repository
877
+ // Step 2b: Wire runtime lifecycle hooks
878
+ if (flags.hooks) {
879
+ step('Wiring runtime lifecycle hooks (.agents/hooks/)', () => {
880
+ const claudeDest = selectedHarnesses.has('claude') ? path.join(TARGET_DIR, '.claude') : null;
881
+ return wireHooks(destAgents, claudeDest);
882
+ });
883
+ }
884
+
885
+ // Step 2c: Install git pre-commit hook automatically if inside a git repository
464
886
  const gitDir = path.join(TARGET_DIR, '.git');
465
887
  if (fs.existsSync(gitDir)) {
466
888
  step('Installing mechanical pre-commit hook (.git/hooks/pre-commit)', () => {
@@ -475,14 +897,22 @@ async function runInit(flags) {
475
897
  });
476
898
  }
477
899
 
478
- // Step 3: Copy docs directory if fresh or missing
900
+ // Step 3: Copy docs directory and TASK_BOARD.md if fresh or missing
479
901
  const destDocs = path.join(TARGET_DIR, 'docs');
480
902
  if (!insideSource && (isFresh || !fs.existsSync(destDocs))) {
481
903
  step('Installing project documentation into docs/', () => {
482
904
  copyRecursiveSync(path.join(TEMPLATE_DIR, 'docs'), destDocs);
483
905
  });
484
906
  } else {
485
- console.log(`${colors.gray}Preserving existing docs/ directory${colors.reset}`);
907
+ // Ensure docs/TASK_BOARD.md exists
908
+ const srcBoard = path.join(TEMPLATE_DIR, 'docs', 'TASK_BOARD.md');
909
+ const destBoard = path.join(destDocs, 'TASK_BOARD.md');
910
+ if (fs.existsSync(srcBoard) && !fs.existsSync(destBoard)) {
911
+ step('Installing deterministic task board (docs/TASK_BOARD.md)', () => {
912
+ fs.mkdirSync(destDocs, { recursive: true });
913
+ fs.copyFileSync(srcBoard, destBoard);
914
+ });
915
+ }
486
916
  }
487
917
 
488
918
  // Step 4: Handle CODING_STANDARDS.md
@@ -499,13 +929,11 @@ async function runInit(flags) {
499
929
  if (!fs.existsSync(srcStandards)) return 'skipped (template not found)';
500
930
  fs.copyFileSync(srcStandards, targetStandards);
501
931
  });
502
- } else {
503
- console.log(`${colors.gray}Preserving existing CODING_STANDARDS.md${colors.reset}`);
504
932
  }
505
933
 
506
- // Step 5: Claude Code integration (.claude/commands, .claude/agents, CLAUDE.md)
934
+ // Step 5: Multi-Harness Integration (Claude Code, Antigravity/Gemini, Cursor, OpenCode, Codex)
507
935
  let claudeSummary = null;
508
- if (flags.claude) {
936
+ if (selectedHarnesses.has('claude')) {
509
937
  step('Wiring Claude Code integration (.claude/, CLAUDE.md)', () => {
510
938
  const destClaude = path.join(TARGET_DIR, '.claude');
511
939
  const cmdCount = generateClaudeCommands(destAgents, destClaude);
@@ -514,27 +942,59 @@ async function runInit(flags) {
514
942
  claudeSummary = { cmdCount, agentCount, claudeMd };
515
943
  return `${cmdCount} commands, ${agentCount} agents (CLAUDE.md ${claudeMd})`;
516
944
  });
517
- } else {
518
- console.log(`${colors.gray}Skipping Claude Code integration (--no-claude)${colors.reset}`);
945
+ }
946
+
947
+ if (selectedHarnesses.has('antigravity') || selectedHarnesses.has('gemini')) {
948
+ step('Wiring Google Antigravity / Gemini integration (ANTIGRAVITY.md, GEMINI.md)', () => {
949
+ return generateAntigravityConfig(TARGET_DIR);
950
+ });
951
+ }
952
+
953
+ if (selectedHarnesses.has('cursor')) {
954
+ step('Wiring Cursor integration (.cursor/rules/devos.mdc, .cursorrules)', () => {
955
+ return generateCursorConfig(TARGET_DIR);
956
+ });
957
+ }
958
+
959
+ if (selectedHarnesses.has('opencode')) {
960
+ step('Wiring OpenCode integration (OPENCODE.md, .opencode/)', () => {
961
+ return generateOpenCodeConfig(TARGET_DIR);
962
+ });
963
+ }
964
+
965
+ if (selectedHarnesses.has('codex')) {
966
+ step('Wiring Codex / Windsurf integration (.codex/, .windsurfrules)', () => {
967
+ return generateCodexConfig(TARGET_DIR);
968
+ });
519
969
  }
520
970
 
521
971
  // Step 6: Update .gitignore
522
972
  step('Updating .gitignore rules', () => {
523
973
  const gitignorePath = path.join(TARGET_DIR, '.gitignore');
524
974
  let gitignoreContent = fs.existsSync(gitignorePath) ? fs.readFileSync(gitignorePath, 'utf8') : '';
525
- if (gitignoreContent.includes('.agents/_backup')) return 'already up to date';
526
- gitignoreContent += `\n# Dev-OS temporary backups\n.agents/_backup/\n`;
527
- fs.writeFileSync(gitignorePath, gitignoreContent.trim() + '\n', 'utf8');
528
- return 'updated';
975
+ let updated = false;
976
+ if (!gitignoreContent.includes('.agents/_backup')) {
977
+ gitignoreContent += `\n# Dev-OS temporary backups\n.agents/_backup/\n`;
978
+ updated = true;
979
+ }
980
+ if (updated) {
981
+ fs.writeFileSync(gitignorePath, gitignoreContent.trim() + '\n', 'utf8');
982
+ return 'updated';
983
+ }
984
+ return 'already up to date';
529
985
  });
530
986
 
531
987
  // Summary card
532
988
  const agentCount = countAgents(path.join(destAgents, 'agents'));
533
989
  const skillCount = countSkills(path.join(destAgents, 'skills'));
990
+ const harnessesList = Array.from(selectedHarnesses);
534
991
 
535
992
  const rows = [
536
993
  ['.agents/agents/', `${agentCount} Agent Personas (Orchestrator, Developer, QA, DBA, Security...)`],
537
- ['.agents/skills/', `${skillCount} Specialist Engineering Skills`],
994
+ ['.agents/skills/', `${skillCount} Specialist Skills (Packs: ${(packSummary ? packSummary.packs : ['core']).join(', ')})`],
995
+ ['.agents/hooks/', 'Runtime Lifecycle Hooks (SessionStart, PreToolUse, SessionEnd)'],
996
+ ['.agents/memory/', 'Shared Memory Vault (ADRs in decisions/, session handoffs)'],
997
+ ['docs/TASK_BOARD.md', 'Deterministic Task Board & DAG Workflow State'],
538
998
  ['.agents/scripts/', 'Commit Checkpoint Gate (commit.sh) + Hook Installer'],
539
999
  ['.agents/AGENTS.md', 'Team Roster & Triage Rules'],
540
1000
  ['CODING_STANDARDS.md', `Stack Standards [${stack.toUpperCase()}]`]
@@ -542,6 +1002,7 @@ async function runInit(flags) {
542
1002
  if (claudeSummary) {
543
1003
  rows.push(['.claude/', `${claudeSummary.cmdCount} Slash Commands + ${claudeSummary.agentCount} Subagents (Claude Code)`]);
544
1004
  }
1005
+ rows.push(['Harnesses', harnessesList.join(', ')]);
545
1006
 
546
1007
  console.log(`\n${colors.green}${colors.bold}[ OK ] Dev-OS Environment Initialized Successfully${colors.reset}\n`);
547
1008
  const labelWidth = Math.max(...rows.map((r) => r[0].length)) + 2;
@@ -559,9 +1020,9 @@ async function runInit(flags) {
559
1020
 
560
1021
  if (!flags.quiet) {
561
1022
  console.log(`\n${colors.bold}NEXT STEPS${colors.reset}`);
562
- console.log(` 1. Install the mechanical pre-commit gate: ${colors.cyan}./.agents/scripts/install-hooks.sh${colors.reset}`);
563
- console.log(` 2. Open your AI engineering environment (Claude Code, Antigravity, Cursor, etc.).`);
564
- console.log(` 3. Prompt the Orchestrator: ${colors.yellow}"Use your grill-me skill to brainstorm our project requirements."${colors.reset}`);
1023
+ console.log(` 1. Open your AI engineering environment (${harnessesList.join(', ')}).`);
1024
+ console.log(` 2. Prompt the Orchestrator: ${colors.yellow}"Use your grill-me skill to brainstorm our project requirements."${colors.reset}`);
1025
+ console.log(` 3. Track tasks with: ${colors.cyan}/task${colors.reset} or inspect ${colors.cyan}docs/TASK_BOARD.md${colors.reset}.`);
565
1026
  console.log(` 4. Run ${colors.cyan}devos doctor${colors.reset} anytime to verify system health.\n`);
566
1027
  }
567
1028
  }
@@ -607,34 +1068,91 @@ async function runUpdate(flags) {
607
1068
  return `saved (${path.relative(TARGET_DIR, backupDir)})`;
608
1069
  });
609
1070
 
610
- // 2. Refresh .agents/
611
- step('Refreshing agent personas, skills, and scripts', () => {
612
- copyRecursiveSync(srcAgents, destAgents);
1071
+ // 2. Refresh .agents/ subdirectories
1072
+ step('Refreshing agent personas, hooks, memory, and scripts', () => {
1073
+ ['agents', 'commands', 'hooks', 'scripts', 'templates'].forEach((dir) => {
1074
+ const src = path.join(srcAgents, dir);
1075
+ const dest = path.join(destAgents, dir);
1076
+ if (fs.existsSync(src)) copyRecursiveSync(src, dest);
1077
+ });
1078
+ // Refresh memory templates without deleting user ADRs
1079
+ const srcMemDec = path.join(srcAgents, 'memory', 'decisions', 'ADR-000-template.md');
1080
+ const destMemDec = path.join(destAgents, 'memory', 'decisions');
1081
+ fs.mkdirSync(destMemDec, { recursive: true });
1082
+ if (fs.existsSync(srcMemDec)) fs.copyFileSync(srcMemDec, path.join(destMemDec, 'ADR-000-template.md'));
1083
+
1084
+ const srcMemHand = path.join(srcAgents, 'memory', 'handoffs', 'handoff-template.md');
1085
+ const destMemHand = path.join(destAgents, 'memory', 'handoffs');
1086
+ fs.mkdirSync(destMemHand, { recursive: true });
1087
+ if (fs.existsSync(srcMemHand)) fs.copyFileSync(srcMemHand, path.join(destMemHand, 'handoff-template.md'));
1088
+
1089
+ ['AGENTS.md', 'README.md', 'packs.json'].forEach((file) => {
1090
+ const src = path.join(srcAgents, file);
1091
+ const dest = path.join(destAgents, file);
1092
+ if (fs.existsSync(src)) fs.copyFileSync(src, dest);
1093
+ });
613
1094
  });
614
1095
  }
615
1096
 
616
- // 3. Ensure executable permissions
617
- step('Verifying script permissions (commit.sh, install-hooks.sh)', () => {
618
- const scripts = ['commit.sh', 'install-hooks.sh'];
1097
+ // 3. Ensure executable script permissions
1098
+ step('Verifying script permissions (commit.sh, install-hooks.sh, humanize-check.sh, hooks/*.sh)', () => {
1099
+ const scripts = ['commit.sh', 'install-hooks.sh', 'humanize-check.sh'];
619
1100
  scripts.forEach((name) => {
620
1101
  const p = path.join(destAgents, 'scripts', name);
621
1102
  if (fs.existsSync(p)) fs.chmodSync(p, '755');
622
1103
  });
1104
+ const hooksDir = path.join(destAgents, 'hooks');
1105
+ if (fs.existsSync(hooksDir)) {
1106
+ fs.readdirSync(hooksDir).forEach((file) => {
1107
+ if (file.endsWith('.sh')) fs.chmodSync(path.join(hooksDir, file), '755');
1108
+ });
1109
+ }
623
1110
  return 'executable (755)';
624
1111
  });
625
1112
 
626
- // 4. Claude Code integration
627
- if (flags.claude) {
628
- step('Refreshing Claude Code commands and subagents', () => {
629
- const destClaude = path.join(TARGET_DIR, '.claude');
630
- const cmdCount = generateClaudeCommands(destAgents, destClaude);
631
- const agentCount = generateClaudeAgents(destAgents, destClaude);
632
- const claudeMd = bootstrapClaudeMd(TARGET_DIR);
633
- return `${cmdCount} commands, ${agentCount} agents (CLAUDE.md ${claudeMd})`;
1113
+ // 4. Update runtime lifecycle hooks
1114
+ if (flags.hooks) {
1115
+ step('Refreshing runtime lifecycle hooks', () => {
1116
+ return wireHooks(destAgents, path.join(TARGET_DIR, '.claude'));
634
1117
  });
635
1118
  }
636
1119
 
637
- // 5. Pre-commit hook
1120
+ // 5. Multi-Harness refresh
1121
+ step('Refreshing AI harness configurations (Claude Code, Cursor, OpenCode, Antigravity, Codex)', () => {
1122
+ const destClaude = path.join(TARGET_DIR, '.claude');
1123
+ generateClaudeCommands(destAgents, destClaude);
1124
+ generateClaudeAgents(destAgents, destClaude);
1125
+ bootstrapClaudeMd(TARGET_DIR);
1126
+ generateCursorConfig(TARGET_DIR);
1127
+ generateOpenCodeConfig(TARGET_DIR);
1128
+ generateAntigravityConfig(TARGET_DIR);
1129
+ generateCodexConfig(TARGET_DIR);
1130
+ return 'Claude Code, Cursor, OpenCode, Antigravity/Gemini, Codex synchronized';
1131
+ });
1132
+
1133
+ // 5b. Refresh skills if requested
1134
+ if (flags.skills || flags.allSkills) {
1135
+ step('Refreshing specialist skills and capability packs', () => {
1136
+ const srcSkills = path.join(srcAgents, 'skills');
1137
+ const destSkills = path.join(destAgents, 'skills');
1138
+ let msg = 'skipped';
1139
+ if (fs.existsSync(srcSkills)) {
1140
+ copyRecursiveSync(srcSkills, destSkills);
1141
+ msg = `${countSkills(destSkills)} skills synchronized`;
1142
+ }
1143
+ try {
1144
+ const { spawnSync } = require('child_process');
1145
+ spawnSync('npx', ['skills', 'update', '-y'], {
1146
+ cwd: TARGET_DIR,
1147
+ stdio: 'ignore',
1148
+ env: { ...process.env, CI: '1' }
1149
+ });
1150
+ } catch (e) {}
1151
+ return msg;
1152
+ });
1153
+ }
1154
+
1155
+ // 6. Pre-commit hook
638
1156
  const gitDir = path.join(TARGET_DIR, '.git');
639
1157
  if (fs.existsSync(gitDir)) {
640
1158
  step('Updating mechanical pre-commit hook', () => {
@@ -652,6 +1170,180 @@ async function runUpdate(flags) {
652
1170
  console.log(`\n${colors.green}${colors.bold}[ OK ] Dev-OS updated to v${PKG.version} successfully.${colors.reset}\n`);
653
1171
  }
654
1172
 
1173
+ // ---------------------------------------------------------------------------
1174
+ // pack
1175
+ // ---------------------------------------------------------------------------
1176
+
1177
+ function runPack(flags, positional) {
1178
+ const subCmd = positional[0] || 'list';
1179
+ const manifestPath = path.join(TARGET_DIR, '.agents', 'manifest.json');
1180
+ const packsPath = path.join(TEMPLATE_DIR, '.agents', 'packs.json');
1181
+ if (!fs.existsSync(packsPath)) {
1182
+ console.error(`${colors.red}[ FAIL ] Capability packs registry (.agents/packs.json) not found.${colors.reset}`);
1183
+ process.exit(1);
1184
+ }
1185
+ const packsData = JSON.parse(fs.readFileSync(packsPath, 'utf8'));
1186
+ const manifest = fs.existsSync(manifestPath) ? JSON.parse(fs.readFileSync(manifestPath, 'utf8')) : { installedPacks: [] };
1187
+
1188
+ if (subCmd === 'list') {
1189
+ if (!flags.quiet && !flags.json) printBanner();
1190
+ if (flags.json) {
1191
+ console.log(JSON.stringify({ availablePacks: packsData.packs, installedPacks: manifest.installedPacks || [] }, null, 2));
1192
+ return;
1193
+ }
1194
+ console.log(`${colors.bold}DEV-OS CAPABILITY PACKS${colors.reset}`);
1195
+ console.log(`${colors.gray}${RULE}${colors.reset}\n`);
1196
+ Object.keys(packsData.packs).forEach((key) => {
1197
+ const p = packsData.packs[key];
1198
+ const isInstalled = (manifest.installedPacks || []).includes(key);
1199
+ const tag = isInstalled ? `${colors.green}[installed]${colors.reset}` : `${colors.gray}[available]${colors.reset}`;
1200
+ console.log(` ${colors.cyan}${colors.bold}${key.padEnd(12)}${colors.reset} ${tag} ${p.name}`);
1201
+ console.log(` ${colors.gray}${p.description}${colors.reset}`);
1202
+ console.log(` ${colors.dim}Skills (${p.skills.length}): ${p.skills.join(', ')}${colors.reset}\n`);
1203
+ });
1204
+ console.log(`Add a pack: ${colors.cyan}devos pack add <name>${colors.reset}\n`);
1205
+ return;
1206
+ }
1207
+
1208
+ if (subCmd === 'add') {
1209
+ const packName = positional[1];
1210
+ if (!packName || !packsData.packs[packName]) {
1211
+ console.error(`${colors.red}[ FAIL ] Unknown pack '${packName}'. Available: ${Object.keys(packsData.packs).join(', ')}${colors.reset}`);
1212
+ process.exit(1);
1213
+ }
1214
+ const pack = packsData.packs[packName];
1215
+ const destSkills = path.join(TARGET_DIR, '.agents', 'skills');
1216
+ fs.mkdirSync(destSkills, { recursive: true });
1217
+
1218
+ let addedCount = 0;
1219
+ pack.skills.forEach((skillName) => {
1220
+ const srcSkill = path.join(TEMPLATE_DIR, '.agents', 'skills', skillName);
1221
+ const destSkill = path.join(destSkills, skillName);
1222
+ if (fs.existsSync(srcSkill)) {
1223
+ copyRecursiveSync(srcSkill, destSkill);
1224
+ addedCount++;
1225
+ }
1226
+ });
1227
+
1228
+ if (!manifest.installedPacks) manifest.installedPacks = [];
1229
+ if (!manifest.installedPacks.includes(packName)) manifest.installedPacks.push(packName);
1230
+ manifest.updatedAt = new Date().toISOString();
1231
+ fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n', 'utf8');
1232
+
1233
+ console.log(`${colors.green}[ OK ] Pack '${packName}' added successfully (${addedCount} skills installed).${colors.reset}`);
1234
+ return;
1235
+ }
1236
+
1237
+ console.error(`${colors.red}[ FAIL ] Unknown pack subcommand '${subCmd}'. Use 'devos pack list' or 'devos pack add <name>'.${colors.reset}`);
1238
+ process.exit(1);
1239
+ }
1240
+
1241
+ // ---------------------------------------------------------------------------
1242
+ // memory
1243
+ // ---------------------------------------------------------------------------
1244
+
1245
+ function runMemory(flags, positional) {
1246
+ const subCmd = positional[0] || 'list';
1247
+ const memoryDir = path.join(TARGET_DIR, '.agents', 'memory');
1248
+
1249
+ if (subCmd === 'list') {
1250
+ if (!flags.quiet && !flags.json) printBanner();
1251
+ const decisionsDir = path.join(memoryDir, 'decisions');
1252
+ const handoffsDir = path.join(memoryDir, 'handoffs');
1253
+ const adrs = fs.existsSync(decisionsDir) ? fs.readdirSync(decisionsDir).filter((f) => f.endsWith('.md')) : [];
1254
+ const handoffs = fs.existsSync(handoffsDir) ? fs.readdirSync(handoffsDir).filter((f) => f.endsWith('.md')) : [];
1255
+ const contextPath = path.join(memoryDir, 'context.json');
1256
+ const context = fs.existsSync(contextPath) ? JSON.parse(fs.readFileSync(contextPath, 'utf8')) : null;
1257
+
1258
+ if (flags.json) {
1259
+ console.log(JSON.stringify({ adrs, handoffs, context }, null, 2));
1260
+ return;
1261
+ }
1262
+
1263
+ console.log(`${colors.bold}DEV-OS SHARED MEMORY VAULT${colors.reset} ${colors.gray}(Target: ${TARGET_DIR})${colors.reset}`);
1264
+ console.log(`${colors.gray}${RULE}${colors.reset}\n`);
1265
+ if (context) {
1266
+ console.log(`${colors.bold}Active Context:${colors.reset} Milestone: ${colors.cyan}${context.currentMilestone || 'N/A'}${colors.reset} | Branch: ${colors.yellow}${context.activeBranch || 'N/A'}${colors.reset}\n`);
1267
+ }
1268
+ console.log(`${colors.bold}Architecture Decision Records (${adrs.length}):${colors.reset}`);
1269
+ if (adrs.length === 0) {
1270
+ console.log(` ${colors.gray}No ADRs recorded yet.${colors.reset}`);
1271
+ } else {
1272
+ adrs.forEach((f) => console.log(` ${colors.green}• ${f}${colors.reset}`));
1273
+ }
1274
+ console.log(`\n${colors.bold}Session Handoffs (${handoffs.length}):${colors.reset}`);
1275
+ if (handoffs.length === 0) {
1276
+ console.log(` ${colors.gray}No session handoffs recorded yet.${colors.reset}`);
1277
+ } else {
1278
+ handoffs.slice(-5).forEach((f) => console.log(` ${colors.cyan}• ${f}${colors.reset}`));
1279
+ }
1280
+ console.log();
1281
+ return;
1282
+ }
1283
+
1284
+ if (subCmd === 'handoff') {
1285
+ const handoffsDir = path.join(memoryDir, 'handoffs');
1286
+ fs.mkdirSync(handoffsDir, { recursive: true });
1287
+ const now = new Date();
1288
+ const dateStr = now.toISOString().slice(0, 10);
1289
+ const timeStr = now.toISOString().slice(11, 16).replace(':', '');
1290
+ const filename = `handoff-${dateStr}-${timeStr}.md`;
1291
+ const targetFile = path.join(handoffsDir, filename);
1292
+
1293
+ let branch = 'unknown';
1294
+ let gitStatus = 'clean';
1295
+ try {
1296
+ const { execSync } = require('child_process');
1297
+ branch = execSync('git branch --show-current', { encoding: 'utf8', cwd: TARGET_DIR }).trim();
1298
+ gitStatus = execSync('git status -s', { encoding: 'utf8', cwd: TARGET_DIR }).trim() || 'clean';
1299
+ } catch (e) {}
1300
+
1301
+ const template = [
1302
+ `# Session Handoff: ${dateStr} ${timeStr}`,
1303
+ '',
1304
+ '## Executive Summary',
1305
+ `- **Active Branch:** \`${branch}\``,
1306
+ `- **Git Status:** ${gitStatus === 'clean' ? 'Clean' : 'Modified files present'}`,
1307
+ '- **Status:** [IN_PROGRESS | READY_FOR_REVIEW | DONE]',
1308
+ '',
1309
+ '## Completed in This Session',
1310
+ '- [ ] Summary of completed items',
1311
+ '',
1312
+ '## In-Progress / Blockers',
1313
+ '- [ ] Unfinished work',
1314
+ '',
1315
+ '## Immediate Next Steps',
1316
+ '1. Resume item 1',
1317
+ ''
1318
+ ].join('\n');
1319
+
1320
+ fs.writeFileSync(targetFile, template, 'utf8');
1321
+ console.log(`${colors.green}[ OK ] Created session handoff template: ${colors.cyan}${path.relative(TARGET_DIR, targetFile)}${colors.reset}`);
1322
+ return;
1323
+ }
1324
+
1325
+ if (subCmd === 'doctor') {
1326
+ const checks = [
1327
+ { name: 'Memory directory (.agents/memory/)', ok: fs.existsSync(memoryDir) },
1328
+ { name: 'Decisions folder (.agents/memory/decisions/)', ok: fs.existsSync(path.join(memoryDir, 'decisions')) },
1329
+ { name: 'Handoffs folder (.agents/memory/handoffs/)', ok: fs.existsSync(path.join(memoryDir, 'handoffs')) },
1330
+ { name: 'Context manifest (.agents/memory/context.json)', ok: fs.existsSync(path.join(memoryDir, 'context.json')) }
1331
+ ];
1332
+ let allOk = true;
1333
+ console.log(`${colors.bold}MEMORY VAULT HEALTH${colors.reset}`);
1334
+ console.log(`${colors.gray}${RULE}${colors.reset}`);
1335
+ checks.forEach((c) => {
1336
+ if (c.ok) console.log(` [ ${colors.green}PASS${colors.reset} ] ${c.name}`);
1337
+ else { console.log(` [ ${colors.red}FAIL${colors.reset} ] ${c.name}`); allOk = false; }
1338
+ });
1339
+ if (!allOk) process.exit(1);
1340
+ return;
1341
+ }
1342
+
1343
+ console.error(`${colors.red}[ FAIL ] Unknown memory subcommand '${subCmd}'. Use 'list', 'handoff', or 'doctor'.${colors.reset}`);
1344
+ process.exit(1);
1345
+ }
1346
+
655
1347
  // ---------------------------------------------------------------------------
656
1348
  // list
657
1349
  // ---------------------------------------------------------------------------
@@ -696,7 +1388,7 @@ function runList(flags) {
696
1388
  console.log(` ${colors.cyan}• ${agent.padEnd(16)}${colors.reset} ${colors.gray}(.agents/agents/${agent}.md)${colors.reset}`);
697
1389
  });
698
1390
 
699
- console.log(`\n${colors.bold}SPECIALIST SKILLS (${skills.length})${colors.reset}`);
1391
+ console.log(`\n${colors.bold}INSTALLED SPECIALIST SKILLS (${skills.length})${colors.reset}`);
700
1392
  console.log(`${colors.gray}${RULE}${colors.reset}`);
701
1393
  const columns = 3;
702
1394
  let line = '';
@@ -710,6 +1402,225 @@ function runList(flags) {
710
1402
  console.log();
711
1403
  }
712
1404
 
1405
+ // ---------------------------------------------------------------------------
1406
+ // skill / skills
1407
+ // ---------------------------------------------------------------------------
1408
+
1409
+ function runSkill(flags, positional) {
1410
+ const subCmd = positional[0] || 'list';
1411
+ const { spawnSync } = require('child_process');
1412
+
1413
+ if (subCmd === 'list') {
1414
+ runList(flags);
1415
+ return;
1416
+ }
1417
+
1418
+ if (subCmd === 'add' || subCmd === 'install') {
1419
+ const pkg = positional[1];
1420
+ if (!pkg) {
1421
+ console.error(`${colors.red}[ FAIL ] Missing skill package or repository name.${colors.reset}`);
1422
+ console.log(`\nUsage: ${colors.cyan}devos skill add <owner/repo>${colors.reset}`);
1423
+ console.log(`Example: ${colors.cyan}devos skill add vercel-labs/agent-skills${colors.reset}`);
1424
+ console.log(`Browse skills: https://skills.sh\n`);
1425
+ process.exit(1);
1426
+ }
1427
+ console.log(`${colors.bold}INSTALLING AGENT SKILL${colors.reset}`);
1428
+ console.log(`${colors.gray}${RULE}${colors.reset}\n`);
1429
+ console.log(`Fetching from skills.sh / GitHub (${colors.cyan}npx skills add ${pkg}${colors.reset})...\n`);
1430
+ const res = spawnSync('npx', ['skills', 'add', pkg, '--yes'], {
1431
+ cwd: TARGET_DIR,
1432
+ stdio: 'inherit',
1433
+ env: { ...process.env, CI: '1' }
1434
+ });
1435
+ if (res.status !== 0) {
1436
+ console.error(`\n${colors.red}[ FAIL ] Failed to install skill '${pkg}'. Check package name or network connectivity.${colors.reset}`);
1437
+ process.exit(res.status || 1);
1438
+ }
1439
+ console.log(`\n${colors.green}[ OK ] Skill '${pkg}' successfully installed into .agents/skills/.${colors.reset}\n`);
1440
+ return;
1441
+ }
1442
+
1443
+ if (subCmd === 'update' || subCmd === 'upgrade') {
1444
+ console.log(`${colors.bold}UPDATING AGENT SKILLS${colors.reset}`);
1445
+ console.log(`${colors.gray}${RULE}${colors.reset}\n`);
1446
+ console.log(`Checking upstream repositories (${colors.cyan}npx skills update${colors.reset})...\n`);
1447
+ const res = spawnSync('npx', ['skills', 'update', '-y'], {
1448
+ cwd: TARGET_DIR,
1449
+ stdio: 'inherit',
1450
+ env: { ...process.env, CI: '1' }
1451
+ });
1452
+ if (res.status === 0) {
1453
+ console.log(`\n${colors.green}[ OK ] Upstream skills updated successfully.${colors.reset}`);
1454
+ }
1455
+
1456
+ const srcSkills = path.join(TEMPLATE_DIR, '.agents', 'skills');
1457
+ const destSkills = path.join(TARGET_DIR, '.agents', 'skills');
1458
+ if (fs.existsSync(srcSkills)) {
1459
+ copyRecursiveSync(srcSkills, destSkills);
1460
+ console.log(`${colors.green}[ OK ] Dev-OS core skills synchronized (${countSkills(destSkills)} total).${colors.reset}\n`);
1461
+ }
1462
+ return;
1463
+ }
1464
+
1465
+ if (subCmd === 'find' || subCmd === 'search') {
1466
+ const query = positional.slice(1).join(' ');
1467
+ console.log(`${colors.bold}SEARCHING AGENT SKILLS (skills.sh)${colors.reset}`);
1468
+ console.log(`${colors.gray}${RULE}${colors.reset}\n`);
1469
+ const args = ['skills', 'find'];
1470
+ if (query) args.push(query);
1471
+ spawnSync('npx', args, {
1472
+ cwd: TARGET_DIR,
1473
+ stdio: 'inherit',
1474
+ env: process.env
1475
+ });
1476
+ return;
1477
+ }
1478
+
1479
+ if (subCmd === 'check') {
1480
+ console.log(`${colors.bold}CHECKING SKILL UPDATES${colors.reset}`);
1481
+ console.log(`${colors.gray}${RULE}${colors.reset}\n`);
1482
+ spawnSync('npx', ['skills', 'check'], {
1483
+ cwd: TARGET_DIR,
1484
+ stdio: 'inherit',
1485
+ env: { ...process.env, CI: '1' }
1486
+ });
1487
+ return;
1488
+ }
1489
+
1490
+ console.error(`${colors.red}[ FAIL ] Unknown skill subcommand '${subCmd}'. Use 'list', 'add', 'update', 'check', or 'find'.${colors.reset}`);
1491
+ process.exit(1);
1492
+ }
1493
+
1494
+ // ---------------------------------------------------------------------------
1495
+ // run / auto
1496
+ // ---------------------------------------------------------------------------
1497
+
1498
+ function runAuto(flags, positional) {
1499
+ if (!flags.quiet && !flags.json) printBanner();
1500
+ const idea = positional.join(' ').trim();
1501
+
1502
+ console.log(`${colors.bold}AUTONOMOUS SDLC RUNNER (devos run / devos auto)${colors.reset}`);
1503
+ console.log(`${colors.gray}${RULE}${colors.reset}`);
1504
+ console.log(` Execution Mode: ${colors.green}Autonomous (Founder / Executive Proxy)${colors.reset}`);
1505
+ if (idea) {
1506
+ console.log(` Target Goal: ${colors.cyan}"${idea}"${colors.reset}\n`);
1507
+ } else {
1508
+ console.log(` Target Goal: ${colors.cyan}Continuous Autonomous Delivery${colors.reset}\n`);
1509
+ }
1510
+
1511
+ console.log(`${colors.bold}10-Stage Professional SDLC Execution Pipeline:${colors.reset}`);
1512
+ console.log(` ${colors.cyan}1. Inception:${colors.reset} Architect (grill-me) → docs/PROJECT_REQUIREMENTS.md`);
1513
+ console.log(` ${colors.cyan}2. Design Gate:${colors.reset} UI Designer (ui-ux-pro-max) → docs/DESIGN.md`);
1514
+ console.log(` ${colors.cyan}3. Architecture & DB:${colors.reset} DBA → Migrations + Seed Fixtures (test password: devos123)`);
1515
+ console.log(` ${colors.cyan}4. Task Decomposition:${colors.reset} Orchestrator → docs/TASK_BOARD.md DAG`);
1516
+ console.log(` ${colors.cyan}5. Implementation:${colors.reset} Developer → Code authoring (dynamic subagents)`);
1517
+ console.log(` ${colors.cyan}6. Test Suite:${colors.reset} Tester → Automated unit & integration tests`);
1518
+ console.log(` ${colors.cyan}7. Testing Guide:${colors.reset} Tester → Interactive docs/TESTING_GUIDE.md`);
1519
+ console.log(` ${colors.cyan}8. Quality Assurance:${colors.reset} QA → Lint, types, standards & Design Gate audit`);
1520
+ console.log(` ${colors.cyan}9. Security Audit:${colors.reset} Security → OWASP, auth & secret scan`);
1521
+ console.log(` ${colors.cyan}10. Humanizer Audit:${colors.reset} Release Manager → Scrub AI tells from docs & copy\n`);
1522
+
1523
+ console.log(`${colors.bold}Next Action:${colors.reset}`);
1524
+ console.log(` To trigger this autonomous run in your AI coding harness, use:`);
1525
+ console.log(` $ ${colors.green}/auto ${idea || '<your product idea>'}${colors.reset}`);
1526
+ console.log(` Or hand off to the Executive Proxy:`);
1527
+ console.log(` "Executive Proxy, run autonomous SDLC mode for: ${idea || '<your product idea>'}"\n`);
1528
+ }
1529
+
1530
+ // ---------------------------------------------------------------------------
1531
+ // telemetry
1532
+ // ---------------------------------------------------------------------------
1533
+
1534
+ function runTelemetry(flags, positional) {
1535
+ if (!flags.quiet && !flags.json) printBanner();
1536
+ const sub = positional[0] || 'status';
1537
+ const manifestPath = path.join(TARGET_DIR, '.agents', 'manifest.json');
1538
+ const manifest = fs.existsSync(manifestPath) ? JSON.parse(fs.readFileSync(manifestPath, 'utf8')) : { telemetry: 'on' };
1539
+ const telemetryDir = path.join(TARGET_DIR, '.agents', 'telemetry');
1540
+ const eventsPath = path.join(telemetryDir, 'events.jsonl');
1541
+
1542
+ if (sub === 'enable') {
1543
+ manifest.telemetry = 'on';
1544
+ fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n', 'utf8');
1545
+ console.log(`${colors.green}[ OK ] Anonymous failure telemetry enabled.${colors.reset}\n`);
1546
+ return;
1547
+ }
1548
+
1549
+ if (sub === 'disable') {
1550
+ manifest.telemetry = 'off';
1551
+ fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n', 'utf8');
1552
+ console.log(`${colors.yellow}[ OK ] Anonymous failure telemetry disabled.${colors.reset}\n`);
1553
+ return;
1554
+ }
1555
+
1556
+ if (sub === 'clear') {
1557
+ if (fs.existsSync(eventsPath)) {
1558
+ fs.writeFileSync(eventsPath, '', 'utf8');
1559
+ }
1560
+ console.log(`${colors.green}[ OK ] Telemetry event buffer cleared.${colors.reset}\n`);
1561
+ return;
1562
+ }
1563
+
1564
+ const isEnabled = manifest.telemetry !== 'off';
1565
+ let eventCount = 0;
1566
+ let lines = [];
1567
+ if (fs.existsSync(eventsPath)) {
1568
+ const raw = fs.readFileSync(eventsPath, 'utf8').trim();
1569
+ if (raw.length > 0) {
1570
+ lines = raw.split('\n').filter(Boolean);
1571
+ eventCount = lines.length;
1572
+ }
1573
+ }
1574
+
1575
+ if (sub === 'report') {
1576
+ console.log(`${colors.bold}TELEMETRY & ROOT CAUSE ANALYSIS (RCA) REPORT${colors.reset}`);
1577
+ console.log(`${colors.gray}${RULE}${colors.reset}`);
1578
+ console.log(` Status: ${isEnabled ? colors.green + 'Enabled (on)' : colors.yellow + 'Disabled (off)'}${colors.reset}`);
1579
+ console.log(` Event Buffer: ${colors.cyan}${eventCount} events recorded${colors.reset}\n`);
1580
+
1581
+ if (eventCount === 0) {
1582
+ console.log(` ${colors.green}✓ Zero failure events recorded. All runtime hooks and gates are operating cleanly.${colors.reset}\n`);
1583
+ return;
1584
+ }
1585
+
1586
+ const rules = {};
1587
+ lines.forEach((l) => {
1588
+ try {
1589
+ const parsed = JSON.parse(l);
1590
+ const rule = parsed.rule || parsed.eventType || 'UNKNOWN';
1591
+ rules[rule] = (rules[rule] || 0) + 1;
1592
+ } catch (e) {}
1593
+ });
1594
+
1595
+ console.log(`${colors.bold}Failure Breakdown:${colors.reset}`);
1596
+ Object.keys(rules).forEach((r) => {
1597
+ console.log(` - ${colors.yellow}${r}${colors.reset}: ${rules[r]} occurrences`);
1598
+ });
1599
+
1600
+ console.log(`\n${colors.bold}Recent Events (Last 3):${colors.reset}`);
1601
+ lines.slice(-3).forEach((l) => {
1602
+ try {
1603
+ const p = JSON.parse(l);
1604
+ console.log(` ${colors.gray}[${p.timestamp || 'N/A'}]${colors.reset} ${colors.cyan}${p.rule || p.eventType}${colors.reset} — ${p.detail || ''}`);
1605
+ } catch (e) {}
1606
+ });
1607
+ console.log(`\nTo clear the buffer: ${colors.cyan}devos telemetry clear${colors.reset}\n`);
1608
+ return;
1609
+ }
1610
+
1611
+ // default 'status'
1612
+ console.log(`${colors.bold}DEV-OS TELEMETRY STATUS${colors.reset}`);
1613
+ console.log(`${colors.gray}${RULE}${colors.reset}`);
1614
+ console.log(` Status: ${isEnabled ? colors.green + 'Enabled (on - recommended)' : colors.yellow + 'Disabled (off)'}${colors.reset}`);
1615
+ console.log(` Log Buffer: ${path.relative(TARGET_DIR, eventsPath)}`);
1616
+ console.log(` Total Events: ${eventCount}`);
1617
+ console.log(`\nCommands:`);
1618
+ console.log(` $ ${colors.cyan}devos telemetry report${colors.reset} View RCA failure breakdown`);
1619
+ console.log(` $ ${colors.cyan}devos telemetry enable${colors.reset} Enable anonymous failure logging`);
1620
+ console.log(` $ ${colors.cyan}devos telemetry disable${colors.reset} Disable failure logging`);
1621
+ console.log(` $ ${colors.cyan}devos telemetry clear${colors.reset} Clear local event buffer\n`);
1622
+ }
1623
+
713
1624
  // ---------------------------------------------------------------------------
714
1625
  // doctor
715
1626
  // ---------------------------------------------------------------------------
@@ -723,11 +1634,23 @@ function runDoctor(flags) {
723
1634
  { name: 'Specialist skills (.agents/skills/)', path: path.join(TARGET_DIR, '.agents', 'skills'), type: 'dir' },
724
1635
  { name: 'Human commit script (.agents/scripts/commit.sh)', path: path.join(TARGET_DIR, '.agents', 'scripts', 'commit.sh'), type: 'file', exec: true },
725
1636
  { name: 'Hook installer (.agents/scripts/install-hooks.sh)', path: path.join(TARGET_DIR, '.agents', 'scripts', 'install-hooks.sh'), type: 'file', exec: true },
1637
+ { name: 'Humanizer scanner (.agents/scripts/humanize-check.sh)', path: path.join(TARGET_DIR, '.agents', 'scripts', 'humanize-check.sh'), type: 'file', exec: true },
1638
+ { name: 'Runtime lifecycle hooks (.agents/hooks/)', path: path.join(TARGET_DIR, '.agents', 'hooks'), type: 'dir', optional: true },
1639
+ { name: 'Shared memory vault (.agents/memory/)', path: path.join(TARGET_DIR, '.agents', 'memory'), type: 'dir', optional: true },
1640
+ { name: 'Task board (docs/TASK_BOARD.md)', path: path.join(TARGET_DIR, 'docs', 'TASK_BOARD.md'), type: 'file', optional: true },
1641
+ { name: 'Telemetry buffer (.agents/telemetry/)', path: path.join(TARGET_DIR, '.agents', 'telemetry'), type: 'dir', optional: true },
1642
+ { name: 'Mandatory Design Gate (docs/DESIGN.md)', path: path.join(TARGET_DIR, 'docs', 'DESIGN.md'), type: 'file', optional: true },
1643
+ { name: 'Interactive Testing Guide (docs/TESTING_GUIDE.md)', path: path.join(TARGET_DIR, 'docs', 'TESTING_GUIDE.md'), type: 'file', optional: true },
726
1644
  { name: 'Team roster (.agents/AGENTS.md)', path: path.join(TARGET_DIR, '.agents', 'AGENTS.md'), type: 'file' },
727
1645
  { name: 'Coding standards (CODING_STANDARDS.md)', path: path.join(TARGET_DIR, 'CODING_STANDARDS.md'), type: 'file' },
728
1646
  { name: 'Documentation (docs/)', path: path.join(TARGET_DIR, 'docs'), type: 'dir' },
729
1647
  { name: 'Claude Code commands (.claude/commands/)', path: path.join(TARGET_DIR, '.claude', 'commands'), type: 'dir', optional: true },
730
1648
  { name: 'Claude Code agents (.claude/agents/)', path: path.join(TARGET_DIR, '.claude', 'agents'), type: 'dir', optional: true },
1649
+ { name: 'Claude Code hooks (.claude/hooks.json)', path: path.join(TARGET_DIR, '.claude', 'hooks.json'), type: 'file', optional: true },
1650
+ { name: 'Cursor rules (.cursor/rules/devos.mdc)', path: path.join(TARGET_DIR, '.cursor', 'rules', 'devos.mdc'), type: 'file', optional: true },
1651
+ { name: 'OpenCode rules (.opencode/rules/devos-rules.md)', path: path.join(TARGET_DIR, '.opencode', 'rules', 'devos-rules.md'), type: 'file', optional: true },
1652
+ { name: 'Antigravity / Gemini instructions (ANTIGRAVITY.md)', path: path.join(TARGET_DIR, 'ANTIGRAVITY.md'), type: 'file', optional: true },
1653
+ { name: 'Codex instructions (.codex/instructions.md)', path: path.join(TARGET_DIR, '.codex', 'instructions.md'), type: 'file', optional: true },
731
1654
  { name: 'Mechanical pre-commit hook (.git/hooks/pre-commit)', path: path.join(TARGET_DIR, '.git', 'hooks', 'pre-commit'), type: 'file', optional: true }
732
1655
  ];
733
1656
 
@@ -787,7 +1710,7 @@ function runDoctor(flags) {
787
1710
  console.log(`${colors.green}${colors.bold}[ OK ] Dev-OS environment is fully operational.${colors.reset}`);
788
1711
  const warns = results.filter((r) => r.status === 'WARN');
789
1712
  if (warns.length) {
790
- console.log(`${colors.yellow}[ WARN ] ${warns.length} optional item(s) not set up (Claude Code integration / pre-commit hook).${colors.reset}`);
1713
+ console.log(`${colors.yellow}[ WARN ] ${warns.length} optional item(s) not set up.${colors.reset}`);
791
1714
  if (warns.some((w) => w.name.includes('pre-commit'))) {
792
1715
  console.log(`${colors.gray} Install the commit gate: ./.agents/scripts/install-hooks.sh${colors.reset}`);
793
1716
  }
@@ -811,6 +1734,16 @@ function runStatus(flags) {
811
1734
  const hasCommitScript = fs.existsSync(path.join(TARGET_DIR, '.agents', 'scripts', 'commit.sh'));
812
1735
  const hasHook = fs.existsSync(path.join(TARGET_DIR, '.git', 'hooks', 'pre-commit'));
813
1736
  const hasClaude = fs.existsSync(path.join(TARGET_DIR, '.claude', 'commands'));
1737
+ const hasCursor = fs.existsSync(path.join(TARGET_DIR, '.cursor', 'rules', 'devos.mdc'));
1738
+ const hasOpenCode = fs.existsSync(path.join(TARGET_DIR, 'OPENCODE.md'));
1739
+ const hasAntigravity = fs.existsSync(path.join(TARGET_DIR, 'ANTIGRAVITY.md')) || fs.existsSync(path.join(TARGET_DIR, 'GEMINI.md'));
1740
+ const hasCodex = fs.existsSync(path.join(TARGET_DIR, '.codex', 'instructions.md')) || fs.existsSync(path.join(TARGET_DIR, '.windsurfrules'));
1741
+ const hasMemory = fs.existsSync(path.join(TARGET_DIR, '.agents', 'memory'));
1742
+ const hasTaskBoard = fs.existsSync(path.join(TARGET_DIR, 'docs', 'TASK_BOARD.md'));
1743
+ const hasDesign = fs.existsSync(path.join(TARGET_DIR, 'docs', 'DESIGN.md'));
1744
+ const hasTestingGuide = fs.existsSync(path.join(TARGET_DIR, 'docs', 'TESTING_GUIDE.md'));
1745
+ const manifestPath = path.join(TARGET_DIR, '.agents', 'manifest.json');
1746
+ const manifest = fs.existsSync(manifestPath) ? JSON.parse(fs.readFileSync(manifestPath, 'utf8')) : null;
814
1747
 
815
1748
  if (flags.json) {
816
1749
  console.log(JSON.stringify({
@@ -819,7 +1752,18 @@ function runStatus(flags) {
819
1752
  standards: hasStandards,
820
1753
  commitGate: hasCommitScript,
821
1754
  preCommitHook: hasHook,
822
- claudeIntegration: hasClaude
1755
+ memoryVault: hasMemory,
1756
+ taskBoard: hasTaskBoard,
1757
+ designGate: hasDesign,
1758
+ testingGuide: hasTestingGuide,
1759
+ manifest,
1760
+ harnesses: {
1761
+ claude: hasClaude,
1762
+ antigravity: hasAntigravity,
1763
+ cursor: hasCursor,
1764
+ openCode: hasOpenCode,
1765
+ codex: hasCodex
1766
+ }
823
1767
  }, null, 2));
824
1768
  return;
825
1769
  }
@@ -828,10 +1772,19 @@ function runStatus(flags) {
828
1772
  console.log(`${colors.gray}${RULE}${colors.reset}`);
829
1773
  console.log(` Target Path: ${colors.cyan}${TARGET_DIR}${colors.reset}`);
830
1774
  console.log(` Dev-OS Status: ${hasAgents ? colors.green + 'Initialized' : colors.yellow + 'Not Initialized'}${colors.reset}`);
1775
+ console.log(` Telemetry: ${manifest && manifest.telemetry === 'off' ? colors.gray + 'Off' : colors.green + 'Active (on - recommended)'}${colors.reset}`);
1776
+ console.log(` SDLC Mode: ${manifest && manifest.mode ? colors.cyan + manifest.mode : colors.cyan + 'interactive'}${colors.reset}`);
1777
+ console.log(` Design Gate: ${hasDesign ? colors.green + 'Ready (docs/DESIGN.md)' : colors.yellow + 'Pending docs/DESIGN.md'}${colors.reset}`);
1778
+ console.log(` Testing Guide: ${hasTestingGuide ? colors.green + 'Ready (docs/TESTING_GUIDE.md)' : colors.gray + 'None'}${colors.reset}`);
831
1779
  console.log(` Standards: ${hasStandards ? colors.green + 'Present' : colors.gray + 'None'}${colors.reset}`);
832
1780
  console.log(` Commit Gate: ${hasCommitScript ? colors.green + 'Active' : colors.gray + 'Disabled'}${colors.reset}`);
833
1781
  console.log(` Git Hook: ${hasHook ? colors.green + 'Installed' : colors.gray + 'Not Installed'}${colors.reset}`);
834
- console.log(` Claude Code: ${hasClaude ? colors.green + 'Wired (.claude/)' : colors.gray + 'Not Wired'}${colors.reset}\n`);
1782
+ console.log(` Memory Vault: ${hasMemory ? colors.green + 'Active (.agents/memory/)' : colors.gray + 'None'}${colors.reset}`);
1783
+ console.log(` Task Board: ${hasTaskBoard ? colors.green + 'Active (docs/TASK_BOARD.md)' : colors.gray + 'None'}${colors.reset}`);
1784
+ if (manifest && manifest.installedPacks) {
1785
+ console.log(` Active Packs: ${colors.cyan}${manifest.installedPacks.join(', ')}${colors.reset}`);
1786
+ }
1787
+ console.log(` Harnesses: Claude (${hasClaude ? '✓' : '✗'}), Antigravity (${hasAntigravity ? '✓' : '✗'}), Cursor (${hasCursor ? '✓' : '✗'}), OpenCode (${hasOpenCode ? '✓' : '✗'}), Codex (${hasCodex ? '✓' : '✗'})\n`);
835
1788
 
836
1789
  if (!hasAgents) {
837
1790
  console.log(`Run ${colors.cyan}npx @olives/devos init${colors.reset} to install Dev-OS in this project.\n`);
@@ -840,7 +1793,7 @@ function runStatus(flags) {
840
1793
 
841
1794
  // Main CLI Entrypoint
842
1795
  async function main() {
843
- const { command, flags } = parseArgs(process.argv.slice(2));
1796
+ const { command, positional, flags } = parseArgs(process.argv.slice(2));
844
1797
 
845
1798
  if (flags.version) {
846
1799
  printVersion();
@@ -861,15 +1814,36 @@ async function main() {
861
1814
  case 'upgrade':
862
1815
  await runUpdate(flags);
863
1816
  break;
1817
+ case 'run':
1818
+ case 'auto':
1819
+ runAuto(flags, positional);
1820
+ break;
1821
+ case 'telemetry':
1822
+ runTelemetry(flags, positional);
1823
+ break;
864
1824
  case 'doctor':
865
1825
  case 'check':
866
1826
  runDoctor(flags);
867
1827
  break;
1828
+ case 'pack':
1829
+ case 'packs':
1830
+ runPack(flags, positional);
1831
+ break;
1832
+ case 'memory':
1833
+ runMemory(flags, positional);
1834
+ break;
868
1835
  case 'list':
869
1836
  case 'agents':
870
- case 'skills':
871
1837
  runList(flags);
872
1838
  break;
1839
+ case 'skill':
1840
+ case 'skills':
1841
+ if (positional.length > 0 && ['add', 'install', 'update', 'upgrade', 'check', 'find', 'search'].includes(positional[0])) {
1842
+ runSkill(flags, positional);
1843
+ } else {
1844
+ runList(flags);
1845
+ }
1846
+ break;
873
1847
  case 'status':
874
1848
  runStatus(flags);
875
1849
  break;