@hybridlabor-api/aos 4.7.0 → 4.7.2

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 (37) hide show
  1. package/.agents/agents.md +8 -3
  2. package/.agents/nodes.json +2 -1
  3. package/.agents/state.schema.json +24 -0
  4. package/.agents/vendor-manifest.json +6 -0
  5. package/.agents/workflows/startcycle-graph.md +2 -2
  6. package/.claude/agents/architect.md +5 -4
  7. package/.claude/agents/techlead.md +2 -0
  8. package/.claude/workflows/startcycle-dispatch.mjs +175 -17
  9. package/.opencode/agents/architect.md +5 -4
  10. package/.opencode/agents/techlead.md +2 -0
  11. package/THIRD_PARTY_NOTICES.md +9 -1
  12. package/bin/aos-doctor.mjs +386 -0
  13. package/bin/aos-store.mjs +171 -0
  14. package/docs/AUDIT_BRIEF_ECC_STORE.md +122 -0
  15. package/docs/PLAN_AOS_STORE_PHASE1.md +190 -0
  16. package/installer.js +68 -15
  17. package/lib/aos-archify-contract.mjs +277 -0
  18. package/lib/ecc-store-index.json +1 -0
  19. package/mcp_config.json +4 -0
  20. package/mcps/mcsc/packages/core/src/adapters/codex.js +160 -37
  21. package/package.json +7 -2
  22. package/scripts/build-ecc-store-index.mjs +147 -0
  23. package/skills/basic/startcycle-graph/SKILL.md +13 -0
  24. package/skills/global_config/agenttrail/bin/agenttrail.mjs +153 -42
  25. package/skills/global_config/agenttrail/public/index.html +5 -4
  26. package/skills/global_config/aos-setup/scripts/aos-doctor.mjs +8 -2
  27. package/skills/global_config/archify/examples/dataflow-product-analytics.html +15048 -0
  28. package/skills/global_config/archify/examples/lifecycle-agent-run.html +14983 -0
  29. package/skills/global_config/archify/examples/sequence-cache-miss-request.html +15063 -0
  30. package/skills/global_config/archify/examples/web-app-rendered.html +15012 -0
  31. package/skills/global_config/archify/examples/workflow-agent-tool-call-rendered.html +15054 -0
  32. package/skills/global_config/ask-tim/SKILL.md +10 -0
  33. package/skills/global_config/mcsc/SKILL.md +60 -0
  34. package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/server.js +31 -6
  35. package/skills/global_config/plan-canvas/scripts/plan-canvas.js +4 -2
  36. package/docs/handover/agenttrail-for-ao.md +0 -58
  37. package/docs/handover/deja-for-ao.md +0 -51
@@ -0,0 +1,122 @@
1
+ # Audit Brief: AOS Skill, Subagent & Extras Store (ECC Fork Integration)
2
+
3
+ **Datum:** 2026-09-24
4
+ **Projekt:** `@hybridlabor-api/aos` (AOS — Curated AI Agent OS)
5
+ **Dokumenttyp:** Architektur- & Sicherheits-Audit-Briefing für externe Reviewer- / Auditor-Agenten
6
+ **Status:** Vor Implementierung (Architektur-Review)
7
+
8
+ ---
9
+
10
+ ## 1. Executive Summary & Zielsetzung
11
+
12
+ AOS (`@hybridlabor-api/aos`) ist ein multi-harness Agenten-Betriebssystem für autonome Coding-Pipelines (unterstützt Claude Code, Google Antigravity, Codex, Cursor, Roo Code und OpenCode). Aktuell liefert AOS ca. 185 kuratierte Kern-Skills und eine 7-Node-Graph-Architektur mit deterministischen Übergängen (Architect → TechLead → Build → Reviewer → Shipping).
13
+
14
+ ### Geplante Erweiterung
15
+ Aufbau eines dezentralen **Skill-, Subagent- und Extras-Stores** als Fallback-Ebene auf Basis eines gepflegten Forks von **[affaan-m/ECC](https://github.com/affaan-m/ECC)** (Everything Claude Code, MIT-Lizenz):
16
+ 1. **Fallback in `/ask-tim`:** Wenn ein Nutzer nach einer Domäne oder einem Framework sucht (z. B. Spring Boot, Godot, Django), das nicht im 185-Skill-Kern von AOS liegt, soll `/ask-tim` automatisch passende Erweiterungen aus dem Store vorschlagen.
17
+ 2. **Fallback in `--skill=<name>`:** Bei Pipeline-Aufrufen wie `/startcycle-graph --skill=django-pro "Ziel"` soll ein lokal fehlender Skill nicht sofort hart mit einer Eskalation abbrechen, sondern im Store gesucht, validiert und on-demand geladen werden.
18
+ 3. **Subagent & Extras Katalog:** Bereitstellung von spezialisierten Auxiliary Agents, Templates, Rules und Hooks aus dem ECC-Ökosystem als modulare AOS-Erweiterungen.
19
+
20
+ ---
21
+
22
+ ## 2. Aktueller Systembestand in AOS (Ist-Zustand)
23
+
24
+ ### 2.1 Relevante Code- & Konfigurations-Pfade
25
+ - **Multi-Harness Installer:** [`installer.js`](file:///Users/timrennings/dev/bdb-dev/bdb-dev-optimized-agent-skills/installer.js) — Synchronisiert Skills, MCP-Configs und Agents nach `~/.claude/`, `~/.agents/`, `~/.codex/`, `~/.cursor/` etc.
26
+ - **Pipeline Dispatcher:** [`.claude/workflows/startcycle-dispatch.mjs`](file:///Users/timrennings/dev/bdb-dev/bdb-dev-optimized-agent-skills/.claude/workflows/startcycle-dispatch.mjs) — Verwaltet den Startcycle-Graph, GO-Gates, mandatory skills (`--skill=<name>`) und Agenten-Orchestrierung.
27
+ - **Skill Router:** [`skills/global_config/ask-tim/SKILL.md`](file:///Users/timrennings/dev/bdb-dev/bdb-dev-optimized-agent-skills/skills/global_config/ask-tim/SKILL.md) — Zentraler Einstiegspunkt für Intent-Erkennung und Skill-Auswahl.
28
+ - **Vendor Tracking:** [`~/.agents/vendor-manifest.json`](file:///Users/timrennings/.agents/vendor-manifest.json) — Pinned Git SHAs für Upstream-Repositories (z. B. `anti-slop`, `skylos`, `claude-red`).
29
+ - **Bereits portierte ECC-Komponenten:** [`THIRD_PARTY_NOTICES.md`](file:///Users/timrennings/dev/bdb-dev/bdb-dev-optimized-agent-skills/THIRD_PARTY_NOTICES.md) — 6 Auxiliary Agents (`silent-failure-hunter`, `security-reviewer`, `go-build-resolver`, `database-reviewer`, `opensource-forker`, `opensource-sanitizer`) und `plan-canvas`.
30
+
31
+ ### 2.2 Bestehende `--skill` Validierungslogik (`startcycle-dispatch.mjs:701-741`)
32
+ ```javascript
33
+ // Aktuelles Verhalten:
34
+ if (mandatorySkillNames.length > 0) {
35
+ const skillCheckResult = await agent(`Check whether each of these skill names resolves to an installed skill...`);
36
+ const missing = skillCheckResult?.missing ?? [];
37
+ if (missing.length > 0) {
38
+ // HARTES ESKALIEREN:
39
+ return await escalate(`--skill named skill(s) that could not be found: ${missing.join(', ')}...`);
40
+ }
41
+ }
42
+ ```
43
+
44
+ ---
45
+
46
+ ## 3. Geplante Soll-Architektur
47
+
48
+ ```mermaid
49
+ flowchart TD
50
+ User([Nutzer-Anfrage / Prompt]) --> Trigger{Einstiegspunkt}
51
+
52
+ Trigger -->|1. /ask-tim Suche| AskTim[ask-tim Router]
53
+ Trigger -->|2. --skill=name Flag| Dispatcher[startcycle-dispatch]
54
+
55
+ AskTim --> CheckCore1{Im 185-Skill AOS Core?}
56
+ Dispatcher --> CheckCore2{Lokal auf Disk installiert?}
57
+
58
+ CheckCore1 -->|Ja| UseCore[Empfehle/Nutze nativen AOS-Skill]
59
+ CheckCore2 -->|Ja| RunCore[Starte Pipeline mit Core-Skill]
60
+
61
+ CheckCore1 -->|Nein| QueryStore[Abfrage lokaler ecc-store-index.json]
62
+ CheckCore2 -->|Nein| QueryStore
63
+
64
+ QueryStore --> MatchFound{Match im Store?}
65
+ MatchFound -->|Nein| FinalEscalate[Eskalation / Keine Treffer]
66
+ MatchFound -->|Ja| StoreAction{Aktion}
67
+
68
+ StoreAction -->|bei /ask-tim| ShowOption[Empfehlung + 'aos store install <name>']
69
+ StoreAction -->|bei --skill| GateCheck[GO-Gate / Confirmation]
70
+
71
+ GateCheck -->|Genehmigt| FetchEngine[On-Demand Sync in ~/.agents/skills/]
72
+ FetchEngine --> ValidateHarness[POSIX & Harness-Tool Linter]
73
+ ValidateHarness --> RunPipeline[Pipeline-Start ohne Unterbrechung]
74
+ ```
75
+
76
+ ---
77
+
78
+ ## 4. Kernfragen & Prüffelder für das Audit
79
+
80
+ Der Auditor-Agent wird gebeten, folgende kritische Fragestellungen strukturiert zu beleuchten:
81
+
82
+ ### 1. GO-Gate & Sicherheit (Supply-Chain-Risiko)
83
+ * **Problem:** Dürfen externe Skills oder Agents während eines autonomen Pipeline-Laufs dynamisch aus einem Remote-Repository nachgeladen werden?
84
+ * **Audit-Frage:** Wie muss die Bestätigung strukturiert sein, damit die strikte AOS-Regel (*"read-only until literal GO"*) nicht kompromittiert wird? Genügt ein lokales, kryptografisch verifiziertes Manifest mit SHA-256 Checksummen?
85
+
86
+ ### 2. Multi-Harness Tool-Inkompatibilitäten
87
+ * **Problem:** `affaan-m/ECC` ist primär für Claude Code konzipiert und verwendet teils hardcodierte Tool-Namen wie `Bash`, `View`, `Edit`, `GlobTool`.
88
+ * **Audit-Frage:** Welche automatisierten Transformations- oder Linter-Regeln müssen beim Ingest/Installationsschritt greifen, damit importierte Skills fehlerfrei in Google Antigravity (`run_command`, `view_file`), OpenAI Codex (`exec`, `read_file`) und Cursor funktionieren?
89
+
90
+ ### 3. Context Window & Token-Budget
91
+ * **Problem:** Ein ungefilterter Import von 400+ Skills würde die Context-Limits und System-Prompts überlasten.
92
+ * **Audit-Frage:** Ist die gewählte Architektur mit einem leichtgewichtigen, lokalen Vektor- oder Metadaten-Index (`ecc-store-index.json` < 100 KB) optimal, und wie sollte das semantische Ranking bei ungenauen Begriffen erfolgen?
93
+
94
+ ### 4. Namenskonflikte & Rangfolge (Precedence)
95
+ * **Problem:** Was passiert, wenn ein ECC-Skill denselben Namen trägt wie ein existierender oder zukünftiger AOS-Kern-Skill (z. B. `tailwind-patterns` oder `tdd-workflow`)?
96
+ * **Audit-Frage:** Sollte ein striktes Namespacing (`ecc/<skill-name>` oder Tagging `origin: ecc`) erzwungen werden, um Overwrites und Seiteneffekte auszuschließen?
97
+
98
+ ### 5. Wartungs- und Sync-Strategie des Forks
99
+ * **Problem:** ECC wird kontinuierlich weiterentwickelt.
100
+ * **Audit-Frage:** Wie sieht eine nachhaltige GitHub-Action-Sync-Pipeline für den Fork `hybridlabor-api/ECC` aus, die neue Upstream-Releases verarbeitet, ohne manuell angepasste Harness-Kompatibilitäts-Fixes zu überschreiben?
101
+
102
+ ---
103
+
104
+ ## 5. Referenzierte Komponenten & Schnittstellen
105
+
106
+ | Komponente | Datei / Pfad | Relevante Zeilen / Kontext |
107
+ |---|---|---|
108
+ | **Pipeline-Dispatcher** | [`.claude/workflows/startcycle-dispatch.mjs`](file:///Users/timrennings/dev/bdb-dev/bdb-dev-optimized-agent-skills/.claude/workflows/startcycle-dispatch.mjs) | Z. 701–741 (Mandatory Skill Check & Eskalation) |
109
+ | **Skill Router** | [`skills/global_config/ask-tim/SKILL.md`](file:///Users/timrennings/dev/bdb-dev/bdb-dev-optimized-agent-skills/skills/global_config/ask-tim/SKILL.md) | Z. 1–70 (Main Flow & Intent Index) |
110
+ | **Vendor Registry** | [`~/.agents/vendor-manifest.json`](file:///Users/timrennings/.agents/vendor-manifest.json) | Vorhandene Pinned-Upstream-Repositories |
111
+ | **Lizenz- & Provenance** | [`THIRD_PARTY_NOTICES.md`](file:///Users/timrennings/dev/bdb-dev/bdb-dev-optimized-agent-skills/THIRD_PARTY_NOTICES.md) | Z. 12–50 (Bisheriger Port von ECC-Agents) |
112
+ | **AOS Installer & Sync** | [`installer.js`](file:///Users/timrennings/dev/bdb-dev/bdb-dev-optimized-agent-skills/installer.js) | Z. 110–135 (Multi-Platform Fan-out) |
113
+
114
+ ---
115
+
116
+ ## 6. Erwartetes Audit-Ergebnis
117
+
118
+ Der externe Auditor-Agent sollte am Ende einen Bericht mit folgendem Schema abliefern:
119
+ 1. **Architektur-Bewertung:** Bestätigung oder Korrektur der vorgeschlagenen Store- und Fallback-Architektur.
120
+ 2. **Identifizierte Risiken:** Kategorisiert nach *Blocker*, *Warnung*, *Empfehlung*.
121
+ 3. **Konkrete Lösungsvorschläge:** Für Tool-Mapping, Token-Schonung und GO-Gate-Integration.
122
+ 4. **Sign-Off / Freigabe-Empfehlung:** Für den Start der Implementierung von Phase 1.
@@ -0,0 +1,190 @@
1
+ # Execution Plan: AOS Skill, Subagent & Extras Store (Phase 1)
2
+
3
+ **Target Repository:** `/Users/timrennings/dev/bdb-dev/bdb-dev-optimized-agent-skills`
4
+ **Target Worktree:** `/Users/timrennings/dev/bdb-dev/aos-wt-store`
5
+ **Branch:** `feat/aos-store` (branched from `main`)
6
+ **Scope:** Phase 1 — Core Store Infrastructure, Offline Index, CLI, and Dispatcher Fallback
7
+ **Audience:** Autonomous Implementation Agent
8
+ **Upstream Source:** `https://github.com/affaan-m/ECC` (Pinned Commit, MIT License)
9
+
10
+ ---
11
+
12
+ ## 🎯 1. Mission & Architectural Invariants
13
+
14
+ You are implementing Phase 1 of the **AOS Store** (`@hybridlabor-api/aos`). This provides an on-demand fallback layer for skills and subagents sourced from `affaan-m/ECC` whenever a requested capability is not in AOS's 185-skill core.
15
+
16
+ ### ⚠️ Non-Negotiable Invariants (Audit-Mandated)
17
+ 1. **No Forks:** Do NOT fork ECC to GitHub. Pin `affaan-m/ECC` directly via Git SHA in `vendor-manifest.json` (identical to `anti-slop` and `skylos`).
18
+ 2. **No Mid-Run Downloads:** Never download or prompt to download during a `/startcycle-graph` run (violates the GO-Gate and headless guarantees). If `--skill=<name>` is missing, the dispatcher must escalate with a clear manual install instruction:
19
+ ```text
20
+ "<name> is not installed. Found in the ECC store.
21
+ Run: aos store install <name>
22
+ Then re-run your startcycle command."
23
+ ```
24
+ 3. **No File System in Dispatcher:** `.claude/workflows/startcycle-dispatch.mjs` has no direct `fs` access. The mandatory skill check is an `agent()` call (Haiku); you must extend its JSON schema with `store_matches: string[]` instead of adding `fs` calls.
25
+ 4. **Trust Anchor is AOS Package:** `lib/ecc-store-index.json` ships inside the `@hybridlabor-api/aos` npm package. Downloads from GitHub must match the SHA-256 hash in this index. Hash mismatch = hard failure.
26
+ 5. **Phase-1 Scope: Markdown Only:**
27
+ - Only import `skills/` and `agents/` (Subagents).
28
+ - **Strictly exclude** `scripts/`, `hooks/`, and `rules/` (prevents RCE and config pollution).
29
+ 6. **Collision Invariant:** AOS core skills ALWAYS take precedence. If an ECC skill shares a name with an existing AOS skill, it is skipped and logged.
30
+ 7. **Future-Proofing for Fucksaas & AO:** Every store item must contain schema fields for `tier: "free"`, `requires_auth: false`, and `origin: "ecc"` so Fucksaas PRO pay-gates and AO marketplace UI can be layered on in Phase 2 without changing the schema.
31
+
32
+ ---
33
+
34
+ ## 🛠️ 2. Worktree Initialization
35
+
36
+ Execute the following commands to create and enter the isolated worktree:
37
+
38
+ ```bash
39
+ cd /Users/timrennings/dev/bdb-dev/bdb-dev-optimized-agent-skills
40
+ git fetch origin main
41
+ git worktree add -b feat/aos-store /Users/timrennings/dev/bdb-dev/aos-wt-store main
42
+ cd /Users/timrennings/dev/bdb-dev/aos-wt-store
43
+ ```
44
+
45
+ All modifications below MUST take place inside `/Users/timrennings/dev/bdb-dev/aos-wt-store/`.
46
+
47
+ ---
48
+
49
+ ## 📋 3. Step-by-Step Implementation Checklist
50
+
51
+ ### Step 1: Upstream Pinning & Provenance
52
+ - [ ] Inspect the latest stable commit SHA of `affaan-m/ECC`:
53
+ ```bash
54
+ gh api repos/affaan-m/ECC/commits/main --jq '.sha'
55
+ ```
56
+ - [ ] Add `ecc-store` entry to `vendor-manifest.json`:
57
+ ```json
58
+ "ecc-store": {
59
+ "upstream": "https://github.com/affaan-m/ECC",
60
+ "pinned_commit": "<FULL_SHA>",
61
+ "purpose": "On-demand fallback store for skills and auxiliary subagents",
62
+ "target": "lib/ecc-store-index.json"
63
+ }
64
+ ```
65
+ - [ ] Update `THIRD_PARTY_NOTICES.md` to document the full scope of ECC components and MIT license terms.
66
+
67
+ ### Step 2: Store Index Generator (`scripts/build-ecc-store-index.mjs`)
68
+ - [ ] Create `scripts/build-ecc-store-index.mjs`. The script must:
69
+ 1. Fetch the tree from GitHub API for the pinned commit (`repos/affaan-m/ECC/git/trees/<sha>?recursive=1`) or clone to a temporary cache.
70
+ 2. Filter strictly for Markdown:
71
+ - `skills/**/SKILL.md` or `skills/**/*.md`
72
+ - `agents/*.md`
73
+ 3. Validate & sanitize frontmatter:
74
+ - Must conform to AOS standards (runnable through `scripts/validate-skills.mjs` rules).
75
+ - Compute SHA-256 for each raw file.
76
+ - Scan for forbidden tokens (hardcoded Claude-only tools like `Bash`, `View`; replace or flag compatibility).
77
+ 4. Build schema:
78
+ ```typescript
79
+ interface StoreIndex {
80
+ version: "1.0.0";
81
+ generated_at: string;
82
+ pinned_commit: string;
83
+ skills: Record<string, {
84
+ name: string;
85
+ description: string;
86
+ category: string;
87
+ tier: "free";
88
+ origin: "ecc";
89
+ requires_auth: false;
90
+ sha256: string;
91
+ upstream_path: string;
92
+ harness_support: ("claude" | "antigravity" | "codex" | "cursor" | "roo")[];
93
+ }>;
94
+ subagents: Record<string, {
95
+ name: string;
96
+ description: string;
97
+ role: string;
98
+ tier: "free";
99
+ origin: "ecc";
100
+ sha256: string;
101
+ upstream_path: string;
102
+ }>;
103
+ }
104
+ ```
105
+ 5. Check collisions against local `skills/` in AOS. Any collision is skipped.
106
+ 6. Output the compiled index to `lib/ecc-store-index.json` (keep size under 100 KB).
107
+ - [ ] Run `node scripts/build-ecc-store-index.mjs` and verify `lib/ecc-store-index.json`.
108
+
109
+ ### Step 3: CLI Implementation (`bin/aos-store.mjs` & `installer.js`)
110
+ - [ ] Create `bin/aos-store.mjs`:
111
+ - `aos store list [--type=skills|agents]` -> Formatted table of available items.
112
+ - `aos store search <query>` -> Search by name, tags, description in `lib/ecc-store-index.json`.
113
+ - `aos store install <name> [--project]` ->
114
+ 1. Look up `<name>` in `lib/ecc-store-index.json`.
115
+ 2. Check if already installed locally; collision guard against AOS core.
116
+ 3. Download raw content from `https://raw.githubusercontent.com/affaan-m/ECC/<pinned_sha>/<upstream_path>`.
117
+ 4. Compute SHA-256 and assert match with index (halt on mismatch).
118
+ 5. Write file:
119
+ - If `--project`: write to `./skills/<name>/SKILL.md`.
120
+ - If global: fan-out to all active harnesses (`~/.agents/skills/<name>/SKILL.md`, `~/.claude/skills/<name>/SKILL.md`, etc., reusing logic from `installer.js`).
121
+ 6. Log success with green checkmark.
122
+ - [ ] Make `bin/aos-store.mjs` executable (`chmod +x bin/aos-store.mjs`).
123
+ - [ ] Register in `package.json`:
124
+ ```json
125
+ "bin": {
126
+ ...
127
+ "aos-store": "bin/aos-store.mjs"
128
+ }
129
+ ```
130
+ - [ ] Wire up `aos store <args>` in `installer.js` so running `aos store search` forwards directly to `bin/aos-store.mjs`.
131
+
132
+ ### Step 4: Dispatcher Hook (`.claude/workflows/startcycle-dispatch.mjs`)
133
+ - [ ] Locate the `validate-mandatory-skills` agent call around lines 701–741.
134
+ - [ ] Update the prompt and JSON schema:
135
+ - Add `store_matches: { type: 'array', items: { type: 'string' } }` to the output schema.
136
+ - Instruct the agent to check `lib/ecc-store-index.json` for any skill not found locally on disk.
137
+ - [ ] Update escalation handling (lines 728–739):
138
+ ```javascript
139
+ const missing = skillCheckResult?.missing ?? [];
140
+ if (missing.length > 0) {
141
+ const storeMatches = skillCheckResult?.store_matches ?? [];
142
+ const suggestions = skillCheckResult?.suggestions ?? [];
143
+
144
+ let msg = `--skill named skill(s) that are not currently installed: ${missing.join(', ')}.\n`;
145
+ if (storeMatches.length > 0) {
146
+ msg += `Found in the AOS / ECC Store: ${storeMatches.join(', ')}.\n` +
147
+ `Run: aos store install ${storeMatches.join(' ')}\n` +
148
+ `Then re-run your startcycle command.\n`;
149
+ } else if (suggestions.length > 0) {
150
+ msg += `Did you mean: ${suggestions.join(', ')}?\n`;
151
+ }
152
+ return await escalate(msg);
153
+ }
154
+ ```
155
+
156
+ ### Step 5: Router Update (`skills/global_config/ask-tim/SKILL.md`)
157
+ - [ ] Add a new section in `ask-tim/SKILL.md` titled `## Outside the core: the ECC store`:
158
+ - Explain that when no native AOS skill fits (e.g. Django, Spring, Godot), the user can query the store via `aos store search <query>`.
159
+ - Document `aos store install <name>` for on-demand activation.
160
+ - Reiterate that the core remains 185 high-trust skills.
161
+
162
+ ### Step 6: Verification & Quality Gate
163
+ - [ ] Run skill validator:
164
+ ```bash
165
+ npm run test
166
+ npm run validate:strict
167
+ ```
168
+ - [ ] Test the CLI commands:
169
+ ```bash
170
+ node bin/aos-store.mjs list | head -n 20
171
+ node bin/aos-store.mjs search django
172
+ node bin/aos-store.mjs search spring
173
+ ```
174
+ - [ ] Test mock installation:
175
+ ```bash
176
+ node bin/aos-store.mjs install <test-skill> --dry-run
177
+ ```
178
+ - [ ] Ensure Git working tree is clean and commits follow Conventional Commits:
179
+ - `feat(store): add build-ecc-store-index generator and store-index.json`
180
+ - `feat(store): implement aos-store CLI and installer integration`
181
+ - `feat(dispatcher): suggest aos store install on missing mandatory skills`
182
+ - `docs(ask-tim): add ECC store fallback section`
183
+
184
+ ---
185
+
186
+ ## 🚀 4. Definition of Done
187
+ 1. `npm test` and `npm run validate` pass with zero errors.
188
+ 2. `lib/ecc-store-index.json` is generated, valid JSON, under 100 KB.
189
+ 3. `bin/aos-store.mjs` executes cleanly without unhandled rejections.
190
+ 4. Worktree is ready for review and merge into `main`.
package/installer.js CHANGED
@@ -41,7 +41,7 @@ function verifyDaemonListening(port, name, timeoutMs = 4000) {
41
41
  tryConnect();
42
42
  });
43
43
  }
44
- const { execSync, spawn, spawnSync, exec } = require('child_process');
44
+ const { execSync, spawn, spawnSync, exec, execFileSync } = require('child_process');
45
45
  const clack = require('@clack/prompts');
46
46
 
47
47
  const {
@@ -233,8 +233,12 @@ const conditionalMcpConfigKeys = [
233
233
 
234
234
  function hasExecutable(binary) {
235
235
  try {
236
- const lookup = process.platform === 'win32' ? `where ${binary}` : `command -v ${binary}`;
237
- execSync(lookup, { stdio: 'ignore' });
236
+ if (process.platform === 'win32') {
237
+ execFileSync('where.exe', [binary], { stdio: 'ignore' });
238
+ } else {
239
+ if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(binary)) return false;
240
+ execSync(`command -v ${binary}`, { stdio: 'ignore' });
241
+ }
238
242
  return true;
239
243
  } catch (e) {
240
244
  return false;
@@ -250,7 +254,7 @@ function findWindowsGoBin() {
250
254
  if (process.platform !== 'win32') return null;
251
255
  const candidates = [];
252
256
  try {
253
- const found = execSync('where.exe go', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] })
257
+ const found = execFileSync('where.exe', ['go'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] })
254
258
  .split(/\r?\n/).map(s => s.trim()).find(Boolean);
255
259
  if (found) candidates.push(path.dirname(found));
256
260
  } catch (_) { /* PATH can be stale immediately after installation */ }
@@ -2192,8 +2196,11 @@ async function installOpenWikiVisualizer() {
2192
2196
  // bin dir, so resolve the absolute binary path now instead of relying on PATH at boot.
2193
2197
  let openwikiBin = 'openwiki';
2194
2198
  try {
2195
- const lookup = process.platform === 'win32' ? 'where openwiki' : 'command -v openwiki';
2196
- openwikiBin = execSync(lookup, { encoding: 'utf8' }).split(/\r?\n/)[0].trim() || 'openwiki';
2199
+ if (process.platform === 'win32') {
2200
+ openwikiBin = execFileSync('where.exe', ['openwiki'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).split(/\r?\n/)[0].trim() || 'openwiki';
2201
+ } else {
2202
+ openwikiBin = execSync('command -v openwiki', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).split(/\r?\n/)[0].trim() || 'openwiki';
2203
+ }
2197
2204
  } catch (e) { logDebug(e, 'openwiki path lookup'); }
2198
2205
 
2199
2206
  // The openwiki CLI is a Node script (#!/usr/bin/env node shebang). Under
@@ -2202,8 +2209,11 @@ async function installOpenWikiVisualizer() {
2202
2209
  // the interpreter itself is baked in as an absolute path.
2203
2210
  let nodeBin = 'node';
2204
2211
  try {
2205
- const lookup = process.platform === 'win32' ? 'where node' : 'command -v node';
2206
- nodeBin = execSync(lookup, { encoding: 'utf8' }).split(/\r?\n/)[0].trim() || 'node';
2212
+ if (process.platform === 'win32') {
2213
+ nodeBin = execFileSync('where.exe', ['node'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).split(/\r?\n/)[0].trim() || 'node';
2214
+ } else {
2215
+ nodeBin = execSync('command -v node', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).split(/\r?\n/)[0].trim() || 'node';
2216
+ }
2207
2217
  } catch (e) { logDebug(e, 'node path lookup'); }
2208
2218
 
2209
2219
  // Which wiki :4321 serves is per-machine setup configuration, not a
@@ -2444,11 +2454,11 @@ async function installOSAgentWorkspace() {
2444
2454
  }, 'AO cannot be started without its binary.');
2445
2455
 
2446
2456
  try {
2447
- execSync(`codesign -v "${binTarget}"`, { stdio: 'ignore' });
2457
+ execFileSync('codesign', ['-v', binTarget], { stdio: 'ignore' });
2448
2458
  } catch {
2449
2459
  log.warn('The ao binary is not code-signed — AMFI will kill it at launch.');
2450
2460
  try {
2451
- execSync(`codesign -s - -f "${binTarget}"`, { stdio: 'ignore' });
2461
+ execFileSync('codesign', ['-s', '-', '-f', binTarget], { stdio: 'ignore' });
2452
2462
  log.step('Signed it ad-hoc.');
2453
2463
  } catch (e) { log.warn(`Could not sign it: ${e.message}`); }
2454
2464
  }
@@ -2463,12 +2473,12 @@ async function installOSAgentWorkspace() {
2463
2473
  // service definition changes upstream.
2464
2474
  const legacyPlist = path.join(homeDir, 'Library', 'LaunchAgents', 'com.bdb.agent-workspace.plist');
2465
2475
  if (fs.existsSync(legacyPlist)) {
2466
- try { execSync(`launchctl unload "${legacyPlist}" 2>/dev/null`, { stdio: 'ignore' }); } catch (e) { logDebug(e, 'unload legacy ao agent'); }
2476
+ try { execFileSync('launchctl', ['unload', legacyPlist], { stdio: 'ignore' }); } catch (e) { logDebug(e, 'unload legacy ao agent'); }
2467
2477
  try { fs.unlinkSync(legacyPlist); log.step('Removed the old com.bdb.agent-workspace service.'); } catch (e) { logDebug(e, 'remove legacy plist'); }
2468
2478
  }
2469
2479
 
2470
2480
  installStep('register the AO service', () => {
2471
- execSync(`"${binTarget}" service install`, { stdio: 'ignore' });
2481
+ execFileSync(binTarget, ['service', 'install'], { stdio: 'ignore' });
2472
2482
  }, 'Start it by hand with: ao service install');
2473
2483
 
2474
2484
  if (await verifyDaemonListening(3101, 'AO Orchestrator', 8000)) {
@@ -2942,8 +2952,11 @@ async function installMcpsForTarget(paths, ctx) {
2942
2952
 
2943
2953
  let uvPath = 'uv';
2944
2954
  try {
2945
- const whichCmd = process.platform === 'win32' ? 'where uv' : 'which uv';
2946
- uvPath = execSync(whichCmd, { stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim().split(/\r?\n/)[0];
2955
+ if (process.platform === 'win32') {
2956
+ uvPath = execFileSync('where.exe', ['uv'], { stdio: ['ignore', 'pipe', 'ignore'], encoding: 'utf8' }).trim().split(/\r?\n/)[0];
2957
+ } else {
2958
+ uvPath = execSync('command -v uv', { stdio: ['ignore', 'pipe', 'ignore'], encoding: 'utf8' }).trim().split(/\r?\n/)[0];
2959
+ }
2947
2960
  } catch (e) {
2948
2961
  if (fs.existsSync(path.join(homeDir, '.local', 'bin', 'uv'))) uvPath = path.join(homeDir, '.local', 'bin', 'uv');
2949
2962
  else if (fs.existsSync(path.join(homeDir, '.cargo', 'bin', 'uv'))) uvPath = path.join(homeDir, '.cargo', 'bin', 'uv');
@@ -3608,7 +3621,7 @@ function installGlobalBinaries() {
3608
3621
  }
3609
3622
 
3610
3623
  const isWin = process.platform === 'win32';
3611
- const cliBins = ['aos-config', 'aos-dashboard', 'aos-uninstall'];
3624
+ const cliBins = ['aos-config', 'aos-dashboard', 'aos-uninstall', 'aos-store', 'aos-doctor'];
3612
3625
 
3613
3626
  for (const name of cliBins) {
3614
3627
  const targetMjs = path.join(globalAgentsBin, `${name}.mjs`);
@@ -4809,7 +4822,38 @@ async function runQuickUpdate(installState) {
4809
4822
  }
4810
4823
 
4811
4824
 
4825
+ function buildAoAnnouncementBanner() {
4826
+ return [
4827
+ '\x1b[36m╭──────────────────────────────────────────────────────────────────────────────╮\x1b[0m',
4828
+ '\x1b[36m│\x1b[0m \x1b[36m│\x1b[0m',
4829
+ '\x1b[36m│\x1b[0m \x1b[1m\x1b[35m🚀 BDB AGENT ORCHESTRATOR APP — FINALE BETA JETZT VERFÜGBAR!\x1b[0m \x1b[36m│\x1b[0m',
4830
+ '\x1b[36m│\x1b[0m \x1b[36m│\x1b[0m',
4831
+ '\x1b[36m│\x1b[0m Die nächste Generation der Cross-Harness Multi-Agenten-Orchestrierung \x1b[36m│\x1b[0m',
4832
+ '\x1b[36m│\x1b[0m ist jetzt als finale Beta für alle User freigeschaltet. \x1b[36m│\x1b[0m',
4833
+ '\x1b[36m│\x1b[0m \x1b[36m│\x1b[0m',
4834
+ '\x1b[36m│\x1b[0m • \x1b[1mDashboard & WebUI:\x1b[0m http://localhost:3101 \x1b[36m│\x1b[0m',
4835
+ '\x1b[36m│\x1b[0m • \x1b[1mService-Befehl:\x1b[0m ao service install (Hintergrunddienst aktivieren) \x1b[36m│\x1b[0m',
4836
+ '\x1b[36m│\x1b[0m • \x1b[1mQuick Launch:\x1b[0m ao open oder ao service status \x1b[36m│\x1b[0m',
4837
+ '\x1b[36m│\x1b[0m • \x1b[1mFeatures:\x1b[0m Session-Telemetrie, Live-AgentTrail & Multi-Workspaces\x1b[36m│\x1b[0m',
4838
+ '\x1b[36m│\x1b[0m \x1b[36m│\x1b[0m',
4839
+ '\x1b[36m╰──────────────────────────────────────────────────────────────────────────────╯\x1b[0m\n'
4840
+ ].join('\n');
4841
+ }
4842
+
4812
4843
  async function main() {
4844
+ if (process.argv[2] === 'store') {
4845
+ const storeScript = path.join(srcDir, 'bin', 'aos-store.mjs');
4846
+ const result = spawnSync(process.execPath, [storeScript, ...process.argv.slice(3)], { stdio: 'inherit' });
4847
+ process.exitCode = result.status == null ? 1 : result.status;
4848
+ return;
4849
+ }
4850
+ if (process.argv[2] === 'doctor' || process.argv[2] === 'checkup' || process.argv.includes('--doctor')) {
4851
+ const doctorScript = path.join(srcDir, 'bin', 'aos-doctor.mjs');
4852
+ const doctorArgs = process.argv.slice(process.argv[2] === 'doctor' || process.argv[2] === 'checkup' ? 3 : 2).filter(a => a !== '--doctor');
4853
+ const result = spawnSync(process.execPath, [doctorScript, ...doctorArgs], { stdio: 'inherit' });
4854
+ process.exitCode = result.status == null ? 1 : result.status;
4855
+ return;
4856
+ }
4813
4857
  const skipIntro = isAutoYes || process.argv.includes('--no-intro') || process.argv.includes('--no-animation');
4814
4858
  await renderKineticIntro({ rotations: 1, fps: 12.5, skip: skipIntro, pkgVersion: pkg.version });
4815
4859
  console.log(buildWordmarkBanner());
@@ -4827,6 +4871,7 @@ async function main() {
4827
4871
 
4828
4872
  intro(buildHeroHeader(pkg.version));
4829
4873
  console.log(buildTelemetryCard({ installState, detections, daemonStatus }));
4874
+ console.log(buildAoAnnouncementBanner());
4830
4875
 
4831
4876
  if (DRY_RUN) {
4832
4877
  // Precise on purpose: version comparison still queries the registry, and
@@ -4869,12 +4914,14 @@ async function main() {
4869
4914
  const options = installState.updateAvailable
4870
4915
  ? [
4871
4916
  { value: 'quick', label: `⚡ Quick Update (v${installState.localVersion} ➔ v${installState.currentVersion})`, hint: 'refresh skills, templates & daemons' },
4917
+ { value: 'doctor', label: '🩺 Run System Checkup / Doctor', hint: 'verify environment, placement, daemons & AO' },
4872
4918
  { value: 'project', label: '📁 Drop Local Project Harness', hint: 'copy dispatcher contract to cwd' },
4873
4919
  { value: 'reconfigure', label: '🛠️ Reconfigure System', hint: 'change targets, tier or options' },
4874
4920
  { value: 'uninstall', label: '🗑️ Uninstall AOS', hint: 'remove what this installer placed; your data stays' },
4875
4921
  { value: 'cancel', label: '❌ Exit' }
4876
4922
  ]
4877
4923
  : [
4924
+ { value: 'doctor', label: '🩺 Run System Checkup / Doctor', hint: 'verify environment, placement, daemons & AO' },
4878
4925
  { value: 'project', label: '📁 Drop Local Project Harness', hint: 'copy dispatcher contract to cwd' },
4879
4926
  { value: 'quick', label: '🔄 Verify & Refresh All Skills', hint: 're-sync and health check' },
4880
4927
  { value: 'reconfigure', label: '🛠️ Reconfigure System', hint: 'switch tier or targets' },
@@ -4892,6 +4939,12 @@ async function main() {
4892
4939
  outro('Cancelled.');
4893
4940
  return;
4894
4941
  }
4942
+ if (action === 'doctor') {
4943
+ const doctorScript = path.join(srcDir, 'bin', 'aos-doctor.mjs');
4944
+ spawnSync(process.execPath, [doctorScript], { stdio: 'inherit' });
4945
+ outro('System Checkup complete.');
4946
+ return;
4947
+ }
4895
4948
  if (action === 'project') {
4896
4949
  installProjectHarness();
4897
4950
  outro('Project harness installation complete.');