feat(app): sidecar bundling pipeline — first .app builds clean (#176 ticket A) - #208
feat(app): sidecar bundling pipeline — first .app builds clean (#176 ticket A)#208Dewinator wants to merge 2 commits into
Conversation
…sub-task 3 ticket A) Schritt A of "fühlt sich nativ an": replace the launcher stub with a real sidecar bundling pipeline so `cargo tauri build` produces a working .app on the developer Mac. Locally validated: 151 MB .app under target/release/bundle/macos/mycelium.app, launches successfully, opens window at http://127.0.0.1:8787 (existing dashboard server). Tray with 4 items appears. Changes: - `scripts/bundle-sidecar.sh` (new): copies mcp-server/dist + node_modules + supabase/migrations into app/src-tauri/sidecar-payload/. Idempotent; rebuilds mcp-server/dist if stale. - `app/src-tauri/binaries/mycelium-mcp-aarch64-apple-darwin`: stub replaced by real launcher. Locates payload (dev: ../sidecar-payload/, bundled: ../Resources/sidecar-payload/), exec's `node $PAYLOAD/index.js`. Honest about prerequisites: requires Node on PATH (portable Node bundling = sub-task 8) and inherits SUPABASE_URL/SUPABASE_KEY from the user-launchd environment (PGlite-as-primary backend = next native-app PR). - `app/src-tauri/tauri.conf.json`: `bundle.resources` ships sidecar-payload/. `beforeBuildCommand` runs the bundle script via `git rev-parse --show-toplevel` (robust against Tauri 2's CWD inconsistency in beforeBuildCommand resolution). - `app/.gitignore`: ignores src-tauri/sidecar-payload/ (~150 MB tree generated at build time). - `app/README.md`: status updated for iteration A — what works, what's follow-up (portable Node, PGlite-as-primary, real icons, signing-key bootstrap). Validation: cargo check → clean cargo tauri build → builds 151 MB mycelium.app open …/mycelium.app → window + tray, dashboard visible Known gap: DMG packaging (final step of `cargo tauri build`) fails on this machine — `bundle_dmg.sh` returned non-zero. The .app itself is produced and runnable. Investigating in follow-up; not a blocker for "can run the native shell". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous "0 PRs offen" snapshot is stale: the agent itself opened a 4-PR queue in the last 4 ticks (#208 standalone + #209→#210→#211 stack). Refresh the Aktiver-Code-Bestand block to credit landed sub-tasks (#202 DATA_DIR, #203 Tauri shell, #204 CI gate, #205 migration helpers) and add a Queue-Stand note that names the open stack, the linear merge constraint, and the ~19 still-supabase-direct services that the DbClient migration sub-story will work through atomically. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Merge-readiness note — CI gap is by design, not a missing runGitHub shows on:
pull_request:
paths:
- 'mcp-server/**'
- '.github/workflows/mcp-server-tests.yml'PR #208 changes:
Zero If a future PR in the native-app track wants automated coverage of the bundling pipeline, that's out of scope here — it would be a separate workflow (e.g. 🤖 Posted by autonomous tick (mycelium 175th) |
…et, gen) PR #208's sidecar-bundling pipeline drops a 136 MB `app/src-tauri/sidecar-payload/` tree on every build, plus Rust's `target/` cache and Tauri's auto-generated `gen/`. None were ignored, so `git status` was noisy and `git add -A` would risk committing a hundred-plus MB of bundled deps. Ignore the three dirs. The committed artifact (`app/src-tauri/binaries/mycelium-mcp-aarch64-apple-darwin`) is unaffected — that path is not under any of the new patterns. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ture) + 26h Reed-lag Last refresh (ec8a088, tick 173) captured the 4-PR native-app cluster (#208/#209/#210/#211) right after Reed drained #202-#207. Tick 174 then opened PR #212 (W4.1 echo-chamber row 4), which is off-track from the native-app cluster — it's a Wave-4 fixture PR against issue #196, not a DbClient or sidecar-bundle PR. CLAUDE.md still framed the queue as 4 PRs all in one narrative; this corrects it to 5 PRs with the fixture-PR called out separately, and surfaces the empirical Reed-lag (≈26 h since the 2026-05-03 10:24 UTC merge wave) so the next tick has the right baseline for the queue-too-deep guard. Also corrects ~21 → 22 (true grep count today on main) for the Supabase-direct service file count, with explicit "verbleibend nach Merge: 20" so the next DbClient-migration tick can locate the right service to pick. No production code touched; pure CLAUDE.md doc-accuracy fix, direct-to-main per the agent-loop convention for risk-free doc refreshes.
183rd-tick — empirical local validation of
|
| Step | Result |
|---|---|
| Cold run (build + copy) | 46 s (npm run build triggered, full payload copy) |
| Idempotent re-run | 31 s (build skipped as fresh, just wipe + recopy of 136 MB) |
| Final payload size | 136 MB |
| Migrations packed | 79 (matches the 79-migration-walk that's the canonical PGlite gate) |
node --check sidecar-payload/index.js |
OK (syntax-valid module) |
| Launcher dev-layout resolution | OK — binaries/mycelium-mcp-* finds ../sidecar-payload/index.js |
Launcher command -v node |
OK on this Mac (Node v25.9.0) |
What this validates
bundle-sidecar.shruns cleanly on a developer Mac with no manual setup beyondnpmalready-installed.- The
if … -ntfreshness check actually triggers a rebuild whendist/index.jsis stale (cold run) and skips it when fresh (re-run) — idempotent as advertised. - Payload layout matches what
mycelium-mcp-aarch64-apple-darwin's "layout 1 (dev mode)" branch expects. - Bundled
index.jsis parseable Node ESM; nothing got mangled by thecp -R dist/.step.
What this does NOT validate
cargo tauri buildend-to-end — would need a clean Tauri toolchain install + ~10 min on this machine; not run this tick.- Bundled
.appactually launching — same reason. The launcher path-resolution is verified statically only. - Cross-platform — macOS arm64 only. Sub-task 8 (CI matrix) is the proper coverage.
Recommendation
PR is mergeable from a script-correctness standpoint. The "no CI" optic is a workflow-path-filter artefact, not a quality gap on this PR specifically — but worth tracking as sub-task 8 prep: once more app/**-only PRs land, a minimal app-tests.yml (even just bash scripts/bundle-sidecar.sh && node --check sidecar-payload/index.js) would re-establish the auto-gate. Filing a separate proposed-by-agent ticket for that would put us at backlog cap (currently 3 ungelabelte: #84, #90, #93), so noting it here instead of opening a fourth.
…sks 1/2/3-most/4/5/7-core landed The 09024a2 (tick 103) snapshot is two days stale: 9 of the 9 PRs in its "recommended merge order" have merged, plus #197/#198/#201/#202/#203/#204/ #205/#206/#207 landed in the same window. Refresh the doc that "is the canonical entry point for the native-app initiative" so a fresh reader does not get a 79-tick-old picture. Concrete changes: - Phase line: "spike phase complete · gated on PR-queue drain" → "implementation underway · sub-tasks 1, 2, 3 (most), 4, 5, 7 (core) landed; 5 PRs open, ~26 h Reed-lag since #202–#207". - End-state installer list: ".dmg / .msi / .AppImage" → ".pkg / .msi / .AppImage", with the 2026-05-04 epic-body decision (.pkg, not .dmg) cited. - Sub-task table: legend (✅ landed, 🔄 PR open, ⏳ spike-only) plus per-row PR status reflecting the current main: - Row 1 picks up #204 (79-migration walk as CI gate). - Row 3 picks up #202, #203, #206, #207 as landed and #208–#211 as open. Row was "_none yet_". - Row 4 / 5 reframed as "inherent" (PGlite is one WASM binary; node-llama-cpp ships per-platform bindings). - Row 7 picks up #205 (Docker → PGlite migration helpers core). - New "DbClient sub-story" subsection: 22 services touch Supabase directly on main; 2 in flight (Skills, SwarmPin); 20 remain after the open stack lands. Pattern: one service per PR. - "Recommended merge order — open PR queue (9 deep)" section replaced with "Open PR queue (5 deep, all CLEAN+MERGEABLE)" — the 9 it documented have all merged. - "Post-drain implementation gate" → "Post-stack implementation gate": parallel tracks (DbClient long-tail of 20 services + the sub-tasks 6/8/9 release-pipeline triangle on tauri-plugin-updater per #207). Doc-only, zero risk, direct-to-main per the standing rule for this file shape. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The bird's-eye doc lagged the 2026-05-03 merge wave (PRs #202–#207 landing sub-tasks 1, 2, 3-scaffold, 4, 5, 7-core) and the W3 spike chain that settled the empirical mDNS budgets on `main`. Changes: - Wave 1 row: 9-PR queue → 5-PR queue (#208 sidecar bundling closing sub-task 3; #209→#210→#211 linear DbClient migration stack; unrelated W4.1 fixture #212). Note the 22-services DbClient sub-story with 2 already in flight. - Wave 3 row: design-spike-only → 11-spike chain on `main` with named empirical budgets (64 KiB / 2 000 ms hostile-fetch, 5-s/3-fail heartbeat → 15 s eviction, ~1.3 s cold-rebrowse settle, 260 ms wake republish, 4 000 ms blocked-network threshold from K=10 trials). Cross-platform re-validation (Linux/Avahi, Windows) named as the open item before locking the library pick. - Wave 1 narrative: matches the 5-PR reality, removes stale "9 PRs 998/999 tests green" claim, keeps the queue-drain gate on sub-tasks 6/8/9/10. Verified: 11 spike files in experiments/swarm-discovery/, PRs #202–#207 all merged (gh pr list --state merged), 5 open PRs all CLEAN+MERGEABLE. Refresh date bumped to 2026-05-04. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Local validation 2026-05-04 (agent tick)Fresh worktree of 1. Empirical sanity check ✅After Payload tree matches the spec:
2. Step-ordering bug in
|
On a fresh clone (no mcp-server/node_modules), step 1 invoked `npm run build` before step 2 ensured deps were installed — `tsc` lives in node_modules/.bin so the build aborted with `sh: tsc: command not found`. The 2026-05-04 validation tick (PR #208 comment thread) flagged this as a one-line swap; this commit applies it. Pure block-swap, same logic — node_modules check moves to step 1, build check to step 2. Empirically re-validated: rm -rf mcp-server/{node_modules,dist} app/src-tauri/sidecar-payload bash scripts/bundle-sidecar.sh → npm ci (220 packages), npm run build (tsc), payload 136M ✓ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fix gepusht: step-ordering bug in
|
… 6 status The "Aktiver Code-Bestand" inventory was one merge-wave behind the canonical native-app-track.md (refreshed in d0fc6ec on 2026-05-04): - #206 (Tauri commands open_data_dir / check_for_updates / restart_app + tray menu) — landed, but missing from CLAUDE.md. - #207 (tauri-plugin-updater wired to GitHub Releases latest.json) — landed, but missing from CLAUDE.md, AND sub-task 6 was still listed as fully verbleibend even though the consumer-side updater is live. Empirical reality on main today: - Sub-tasks 1, 2, 3 (scaffold + commands), 4, 5, 6 (updater-plugin app-side), 7 (core) are implemented. - Sub-task 6 verbleibend collapses to its CI half — publishing latest.json + signed installers — which is paired with sub-task 8 per docs/native-app-track.md row 6 ("⏳ spike landed, CI release pipeline pending"). - Sub-task 3 closes fully once #208 (sidecar bundling) merges. Doc-only, zero risk, direct-to-main per the standing rule for this file shape (precedent: d0fc6ec, ec8a088, f9acd10, 1962f9d). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The sub-task 9 (update-banner refit) spike was written 2026-05-02 with approximate line ranges for the existing browser-mode update-banner code. Re-verified empirically against main — banner JS is at 7320–7467 (function body of `checkForUpdate()`), `/update-status` handler is at 2150–2254. Original ranges (7315–7480, 2148–2252) were within ~5/13 lines but the implementation tick will read these as exact references when sub-task 3 closes via #208 + DbClient stack, so tightening now avoids drift hunts. Also de-counted the "9 PRs in flight" justification — count drifts; what matters is the queue-full rule applies whenever the queue is full. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Schritt A of "fühlt sich nativ an" — replaces the launcher stub from PR #203 with a real sidecar bundling pipeline. After this lands,
cargo tauri buildproduces a workingmycelium.appon the developer Mac.Locally validated: 151 MB
.appundertarget/release/bundle/macos/mycelium.app, launches successfully, opens window athttp://127.0.0.1:8787(existing dashboard server). Tray with 4 items appears.Changes
scripts/bundle-sidecar.sh(new): copiesmcp-server/dist+node_modules+supabase/migrationsintoapp/src-tauri/sidecar-payload/. Idempotent; rebuildsmcp-server/distif stale.app/src-tauri/binaries/mycelium-mcp-aarch64-apple-darwin: stub replaced by real launcher. Locates payload (dev:../sidecar-payload/, bundled:../Resources/sidecar-payload/),execsnode $PAYLOAD/index.js. Honest about prerequisites:SUPABASE_URL/SUPABASE_KEYfrom the user-launchd environment (PGlite-as-primary backend = next native-app PR).app/src-tauri/tauri.conf.json:bundle.resourcesshipssidecar-payload/.beforeBuildCommandruns the bundle script viagit rev-parse --show-toplevel(robust against Tauri 2's CWD inconsistency inbeforeBuildCommandresolution).app/.gitignore: ignoressrc-tauri/sidecar-payload/(~150 MB tree generated at build time).app/README.md: status updated for iteration A — what works, what's follow-up.Validation
Known gaps (intentional, follow-up tickets)
cargo tauri build(bundle_dmg.sh) returned non-zero on this machine. The.appitself is produced and runnable; the.dmgwrapper around it isn't. Likely fix:brew install create-dmg. Investigating in follow-up; not a blocker for "can run the native shell."nodefrom PATH. Bundling a portable Node so the.dmgworks without a system Node install is sub-task 8 (CI matrix / cross-platform).mcp-server/src/index.tsstill constructs every service againstSUPABASE_URL/SUPABASE_KEY(~30 sites). Refactor to honourMYCELIUM_USE_PGLITE=1and route all services through the in-process adapter is the next big native-app PR.pubkeyremains a placeholder — seeapp/README.md"Signing-key bootstrap".Test plan
bash scripts/bundle-sidecar.sh— producesapp/src-tauri/sidecar-payload/(~136 MB)cd app/src-tauri && cargo tauri build— producestarget/release/bundle/macos/mycelium.appopen target/release/bundle/macos/mycelium.app— window opens, tray icon appears, 4 menu items, dashboard reachableRelated
🤖 Generated with Claude Code