@hybridlabor-api/aos 4.4.2-beta.1 → 4.4.2-beta.3

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.
package/CLAUDE.md CHANGED
@@ -616,6 +616,58 @@ must not do.
616
616
 
617
617
  ## Headless timeouts
618
618
 
619
+ A trivial headless `agy` prompt was measured at **605s** in 2026-09.
620
+ `agy-delegate` defaults to `--print-timeout 5m`, so it aborts at 300s and
621
+ reports an empty body while the answer is still arriving. Pass `--timeout 15m`
622
+ for anything non-trivial. A short timeout does not read as "slow", it reads as
623
+ "broken".
624
+
625
+ # AOS — Antigravity / Gemini
626
+
627
+ **Read [AGENTS.md](AGENTS.md) first.** It holds every rule that applies to all
628
+ harnesses: the non-negotiables, the release gate, Conventional Commits, the
629
+ skill contract and category routing, the pipeline variants, and the delegation
630
+ policy. Nothing from it is repeated here — a rule that lives in two files is a
631
+ rule that will eventually disagree with itself.
632
+
633
+ This file covers only what is specific to running AOS under Antigravity.
634
+
635
+ ## Nothing enforces the gate here — you are the enforcement
636
+
637
+ `.claude/hooks/go-gate.mjs` is a Claude Code hook and does not run on this
638
+ harness. Not one of the four release commands is mechanically blocked for you,
639
+ and neither is anything else.
640
+
641
+ So the full rule in AGENTS.md applies here in its entirety, not just its
642
+ hook-enforced subset: when the user asks for a plan, review, audit or
643
+ multi-step action, you are read-only until they answer with the literal **GO**
644
+ — including file writes and `git commit`. On Claude Code a hook would catch the
645
+ four worst cases if discipline failed. Here there is no backstop, which makes
646
+ this the harness where the rule matters most, not least.
647
+
648
+ ## Model routing
649
+
650
+ The tier names in `agy-delegate` map to models that go stale — the built-in
651
+ `flash` still points at Gemini 3.7 while 3.8 ships. Re-check against
652
+ `agy models` after every upgrade; the id carries both the version and the
653
+ effort suffix.
654
+
655
+ | Work | Model |
656
+ |---|---|
657
+ | Media, fast or mechanical coding, boilerplate | `Gemini 3.8 Flash (Medium)` |
658
+ | Trivial one-liners | `Gemini 3.8 Flash (Low)` |
659
+ | Review, architecture, hard reasoning | `Claude Sonnet 4.6 (Thinking)` |
660
+
661
+ Set these once via `CLAUDE_PLUGIN_OPTION_TIER_{FLASH,FLASH_LO,PRO}` in
662
+ `~/.zshenv` — **not** `~/.zshrc`, which non-interactive tool shells never
663
+ source.
664
+
665
+ Adversarial review is the case that most repays the stronger model: a Flash
666
+ tier tends to agree with what it is shown, which is the one thing a reviewer
667
+ must not do.
668
+
669
+ ## Headless timeouts
670
+
619
671
  A trivial headless `agy` prompt was measured at **605s** in 2026-09.
620
672
  `agy-delegate` defaults to `--print-timeout 5m`, so it aborts at 300s and
621
673
  reports an empty body while the answer is still arriving. Pass `--timeout 15m`
@@ -50,8 +50,21 @@ const MODULE_DIRS = ['memB', 'bdb-synapse', 'bdb-os-remote', 'bdb-dev-creator-ex
50
50
  'bdb-dev-tool-installer',
51
51
  'bdb-agent-orchestrator', // AO
52
52
  'bdb-os-agent-workspace', // AO's archived predecessor, if still lying around
53
+ 'bdb-dev-optimized-agent-skills', // AOS's own core payload cache, when a "from source" or non-npx run left one behind
53
54
  ].map((m) => h('.agents', m));
54
55
 
56
+ // installer.js's detectInstallState() treats any of these as proof AOS is
57
+ // still installed, independently of the manifest -- a leftover copy after
58
+ // this uninstall runs was reported as "Current & Up-to-date" on the very
59
+ // next launch, with the manifest already gone. Keep this list in exact sync
60
+ // with the `legacyMarkers` array in installer.js's detectInstallState().
61
+ const LEGACY_MARKERS = [
62
+ h('.agents', 'AGENTS.md'),
63
+ h('.gemini', 'config', 'skills', 'startcycle', 'SKILL.md'),
64
+ h('.agents', 'skills', 'startcycle', 'SKILL.md'),
65
+ h('.claude', 'skills', 'startcycle', 'SKILL.md'),
66
+ ];
67
+
55
68
  const sha256 = (file) => {
56
69
  try { return createHash('sha256').update(readFileSync(file)).digest('hex'); }
57
70
  catch { return null; }
@@ -77,13 +90,14 @@ function plan() {
77
90
  .filter((a) => existsSync(a.plist));
78
91
 
79
92
  const modules = MODULE_DIRS.filter(existsSync);
93
+ const legacy = LEGACY_MARKERS.filter(existsSync);
80
94
  const data = PURGE ? DATA_PATHS.filter((d) => existsSync(d.path)) : [];
81
95
 
82
- return { manifest, ours, edited, gone, agents, modules, data };
96
+ return { manifest, ours, edited, gone, agents, modules, legacy, data };
83
97
  }
84
98
 
85
99
  function describe(p) {
86
- const { manifest, ours, edited, gone, agents, modules, data } = p;
100
+ const { manifest, ours, edited, gone, agents, modules, legacy, data } = p;
87
101
 
88
102
  if (!manifest) {
89
103
  console.log('Kein Installations-Manifest unter ' + tilde(MANIFEST) + '.');
@@ -110,6 +124,11 @@ function describe(p) {
110
124
  console.log('\nModule:');
111
125
  for (const m of modules) console.log(` ${tilde(m)}`);
112
126
  }
127
+ if (legacy.length) {
128
+ console.log(`\nInstallations-Marker (${legacy.length}) -- ohne diese hält die nächste`);
129
+ console.log(' Installation AOS für bereits aktuell installiert:');
130
+ for (const l of legacy) console.log(` ${tilde(l)}`);
131
+ }
113
132
 
114
133
  console.log('\nBleibt erhalten:');
115
134
  if (!PURGE) for (const d of DATA_PATHS.filter((d) => existsSync(d.path))) console.log(` ${tilde(d.path).padEnd(18)} ${d.what}`);
@@ -140,7 +159,7 @@ function dirSize(p) {
140
159
 
141
160
  // ------------------------------------------------------------------ execute
142
161
  function execute(p) {
143
- const { ours, edited, agents, modules, data } = p;
162
+ const { ours, edited, agents, modules, legacy, data } = p;
144
163
  const stamp = new Date().toISOString().replace(/[:.]/g, '').slice(0, 15);
145
164
  let removed = 0, backed = 0;
146
165
 
@@ -161,6 +180,9 @@ function execute(p) {
161
180
  for (const m of modules) { try { rmSync(m, { recursive: true, force: true }); } catch { /* in use */ } }
162
181
  if (modules.length) console.log(` ${modules.length} Module entfernt`);
163
182
 
183
+ for (const l of legacy) { try { rmSync(l); } catch { /* already gone */ } }
184
+ if (legacy.length) console.log(` ${legacy.length} Installations-Marker entfernt`);
185
+
164
186
  // Only the BDB hook entries leave settings.json; everything else in it is
165
187
  // the user's and must survive an uninstall exactly as it survives an install.
166
188
  const settings = h('.claude', 'settings.json');
package/installer.js CHANGED
@@ -3405,15 +3405,26 @@ function generateAndOpenLaunchpad() {
3405
3405
 
3406
3406
  const filePath = path.join(os.homedir(), '.agents', 'bdb-launchpad.html');
3407
3407
  fs.writeFileSync(filePath, html, 'utf-8');
3408
+ const warnOpenFailed = (e) => log.warn(`Could not open the dashboard automatically (${e.message}). Open it yourself: ${filePath}`);
3408
3409
  try {
3410
+ let child;
3409
3411
  if (process.platform === 'darwin') {
3410
- spawn('open', [filePath], { detached: true, stdio: 'ignore' }).unref();
3412
+ child = spawn('open', [filePath], { detached: true, stdio: 'ignore' });
3411
3413
  } else if (process.platform === 'win32') {
3412
- spawn('cmd.exe', ['/c', 'start', '""', filePath], { detached: true, stdio: 'ignore' }).unref();
3414
+ // cmd.exe /c start has a title-vs-path quoting quirk when the
3415
+ // arguments come from spawn's argv array rather than a real shell --
3416
+ // on a real Windows test run it silently opened nothing, and the
3417
+ // failure was invisible: spawn() reports a bad launch asynchronously
3418
+ // via 'error', not by throwing, so the try/catch around this call
3419
+ // could never have caught it regardless of --verbose. explorer.exe
3420
+ // on a plain file path has no title argument to misparse.
3421
+ child = spawn('explorer', [filePath], { detached: true, stdio: 'ignore' });
3413
3422
  } else {
3414
- spawn('xdg-open', [filePath], { detached: true, stdio: 'ignore' }).unref();
3423
+ child = spawn('xdg-open', [filePath], { detached: true, stdio: 'ignore' });
3415
3424
  }
3416
- } catch (e) { logDebug(e, 'launchpad open'); }
3425
+ child.on('error', warnOpenFailed);
3426
+ child.unref();
3427
+ } catch (e) { warnOpenFailed(e); }
3417
3428
  }
3418
3429
 
3419
3430
  async function universalHarnessSync(primaryMcpConfigPath) {
@@ -3662,12 +3673,14 @@ async function main() {
3662
3673
  { value: 'quick', label: `⚡ Quick Update (v${installState.localVersion} ➔ v${installState.currentVersion})`, hint: 'refresh skills, templates & daemons' },
3663
3674
  { value: 'project', label: '📁 Drop Local Project Harness', hint: 'copy dispatcher contract to cwd' },
3664
3675
  { value: 'reconfigure', label: '🛠️ Reconfigure System', hint: 'change targets, tier or options' },
3676
+ { value: 'uninstall', label: '🗑️ Uninstall AOS', hint: 'remove what this installer placed; your data stays' },
3665
3677
  { value: 'cancel', label: '❌ Exit' }
3666
3678
  ]
3667
3679
  : [
3668
3680
  { value: 'project', label: '📁 Drop Local Project Harness', hint: 'copy dispatcher contract to cwd' },
3669
3681
  { value: 'quick', label: '🔄 Verify & Refresh All Skills', hint: 're-sync and health check' },
3670
3682
  { value: 'reconfigure', label: '🛠️ Reconfigure System', hint: 'switch tier or targets' },
3683
+ { value: 'uninstall', label: '🗑️ Uninstall AOS', hint: 'remove what this installer placed; your data stays' },
3671
3684
  { value: 'cancel', label: '❌ Exit' }
3672
3685
  ];
3673
3686
 
@@ -3691,6 +3704,19 @@ async function main() {
3691
3704
  outro('Quick Update complete.');
3692
3705
  return;
3693
3706
  }
3707
+ if (action === 'uninstall') {
3708
+ // aos-uninstall.mjs is its own script, not a function of this file --
3709
+ // it is ESM (installer.js is CommonJS) and drives its own readline
3710
+ // confirmation prompt, so it runs as a real child process with
3711
+ // inherited stdio rather than being imported in-process.
3712
+ const uninstallScript = path.join(srcDir, 'bin', 'aos-uninstall.mjs');
3713
+ if (!fs.existsSync(uninstallScript)) {
3714
+ log.error(`Uninstaller not found at ${uninstallScript} -- run it directly: npx @hybridlabor-api/aos-uninstall`);
3715
+ return;
3716
+ }
3717
+ spawnSync('node', [uninstallScript], { stdio: 'inherit' });
3718
+ return;
3719
+ }
3694
3720
  }
3695
3721
 
3696
3722
  const detectedNames = detections.map(d => d.name).join(', ');
package/lib/startup-ui.js CHANGED
@@ -83,7 +83,13 @@ function buildTelemetryCard({ installState, detections, daemonStatus = [] }) {
83
83
  'Google Antigravity': 'Antigravity',
84
84
  'ChatGPT Codex CLI': 'Codex CLI',
85
85
  'Claude Code CLI': 'Claude Code',
86
- 'Roo Code / Cline / VS Code': 'Roo / Cline',
86
+ // The underlying detection (installer.js's 'vscode' evidence) fires on
87
+ // any of: the VS Code app/CLI being present, OR a Roo/Cline extension
88
+ // glob match. Those are not the same claim -- plain VS Code with no
89
+ // Roo/Cline extension installed used to display as "Roo / Cline" here,
90
+ // asserting something that was not there. "VS Code" is the one label
91
+ // that is true in all three trigger cases.
92
+ 'Roo Code / Cline / VS Code': 'VS Code',
87
93
  'Aider CLI': 'Aider',
88
94
  'OpenCode CLI': 'OpenCode',
89
95
  'Cursor / Generic IDE': 'Cursor',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hybridlabor-api/aos",
3
- "version": "4.4.2-beta.1",
3
+ "version": "4.4.2-beta.3",
4
4
  "description": "AOS — A Curated AI AGENT OS. Optimized agent skills and add-ons like memB, OpenWiki, Heimdall Token Saver, and Godmode architectures.",
5
5
  "main": "installer.js",
6
6
  "bin": {