dogfood-worktree · diff
git:20261001.d05bc2e to git:20261013.6c6e06b
7 added, 135 removed. Audit A to A.
---
name: dogfood-worktree
- description: >-
- This skill should be used when the user asks to "dogfood this change", "test this in a
- worktree", "why is the worktree using the production binary", or when capture, MCP, or the
- CLI in a git worktree behaves like production instead of the worktree build. Covers `make
- dev-link-worktree` / `make dev-unlink-worktree`, why `.myco/runtime.command` does not
- travel with `git worktree add`, why a build must happen first, the direct-CLI `MYCO_HOME`
- trap, the shared-vault schema rollup hazard across worktrees, and the vendor-asset build
- step.
+ description: Build and smoke-test Myco member or server changes from an isolated git worktree.
---
- # Dogfooding Myco in a Git Worktree
-
- This is a **dogfood-only** concern — myco using myco to build myco. A regular
- user just has one `myco` installed; their own worktrees "just work" because
- everything resolves to that single binary. The complexity here exists only
- because we run a **dev** binary (`myco-dev`) alongside the **prod** binary
- (`myco`) and need capture to keep working while we change Myco itself.
-
- ## The core gotcha: a fresh worktree is not myco-dev aware
-
- Binary resolution (global launcher `~/.myco/launcher.cjs` and `bin/myco-run`)
- walks **up from the working directory** looking for `<dir>/.myco/runtime.command`,
- then the machine pin, then the vendored binary, then PATH `myco`.
-
- `.myco/runtime.command` is **gitignored** (`.myco/.gitignore`). `git worktree add`
- only materializes *tracked* files, so a new worktree starts with **no pin**.
- With no pin:
-
- - A worktree **nested** under the main checkout (e.g. `.worktrees/foo`) walks up
- and finds the *main checkout's* pin → runs **main's `myco-dev`** (stale vs. the
- worktree's changes).
- - A **sibling** worktree (e.g. `../myco-foo`) finds nothing → hooks fall through
- to PATH `myco` = the **production** binary. Capture then hits the prod
- daemon/vault. Unacceptable for dogfooding.
-
- Either way a fresh worktree never uses **its own** build until it is pinned.
-
- ## Procedure
-
- 1. **Create the worktree** off the branch under development:
- ```bash
- git worktree add ../myco-<feature> <branch>
- cd ../myco-<feature>
- ```
-
- 2. **Pin it to its own build:**
- ```bash
- make dev-link-worktree
- ```
- This depends on `dev-build`, so it **builds the worktree's binary first**,
- then writes `<worktree>/.myco/runtime.command` → `packages/myco-<target>/bin/myco`.
- It does **not** touch the shared `~/.local/bin/myco-dev` symlink (the main
- checkout and other agents rely on it), and it does **not** write project-local
- launchers (`.agents/myco-run.cjs` is retired — the global launcher + cwd-walk
- handle routing through the pin).
-
- 3. **Verify binary routing and vault home separately:**
- ```bash
- myco --version
- myco doctor
- ```
- `make dev-link-worktree` pins the **binary** only. It writes
- `<worktree>/.myco/runtime.command` directly to
- `packages/myco-<target>/bin/myco`; it does **not** write a wrapper that exports
- `MYCO_HOME`, and adding `<worktree>/.myco/runtime.home` alone is not enough
- for direct `myco` CLI calls. A sibling worktree can therefore run the
- worktree binary while still talking to the production home/daemon
- (`~/.myco`) for `myco tool call`, `myco doctor`, plan lookups, and session
- lookups.
-
- For direct CLI calls to read or mutate the dogfood dev vault, prefix
- the command explicitly:
- ```bash
- MYCO_HOME="$HOME/.myco-dev" \
- myco tool call myco_plans --json --input '{"op":"list","limit":5}'
- ```
- Verify the result against the main checkout before mutating plan/session
- state. Do not treat `git rev-parse --git-common-dir`, a matching
- `.myco/project.toml`, or a URL/project slug as proof that the worktree is
- using the same daemon or Grove DB; `myco doctor` and a known plan/session
- lookup are the proof.
-
- 4. **Revert when done:**
- ```bash
- make dev-unlink-worktree # removes the worktree's .myco/runtime.command
- ```
- Resolution then falls back through the chain (→ prod `myco` for a sibling
- worktree), so unlink only after dogfooding that worktree is finished.
-
- ## Caveats — codified so we stop rediscovering them
-
- ### Shared-vault schema rollup (the big one)
- Every worktree **and** the main checkout resolve to the **same** Grove vault
- (`myco.db`) via `git-common-dir`. Each worktree pins to its **own** binary. So a
- worktree whose binary runs a **schema migration** mutates the *shared* DB — and
- the main checkout or another worktree on an **older** build can then break
- (missing/renamed columns, `user_version` mismatch). This is the accepted cost of
- the rollup-to-main-vault design; a per-worktree vault was rejected because it
- fragments dogfood data and contradicts "worktrees attach to the main project."
-
- - Run **one schema-changing worktree at a time**; rebuild the others to match.
- - For genuinely risky schema work, use a temp `MYCO_HOME` sandbox so the shared vault is never mutated.
-
- ### A build must succeed first
- The pin points at `packages/myco-<target>/bin/myco` *inside* the worktree, so that
- binary has to exist — `make dev-link-worktree` builds it. **Worktree builds can
- fail** when local, gitignored vendor assets (e.g.
- `packages/myco/vendor-src/libsqlite3/<target>/libsqlite3.dylib`) exist in the main
- checkout but didn't travel to the worktree. If `dev-build` fails on a missing
- vendor asset, copy/symlink it from the main checkout (or rebuild it in the
- worktree) and re-run `make dev-link-worktree`.
+ # Dogfood a worktree
- ### Daemon-side changes: dogfood from the MAIN checkout, never the worktree
- The worktree pin only routes **hooks, MCP, and CLI** to the worktree binary. The
- dev **daemon** always runs the **main dev binary** — its launchd service points at
- the main checkout's `packages/myco-<target>/bin/myco`, so a worktree pin does NOT
- change which code the daemon runs.
+ `make dev-build` builds vendor SQLite, the Deployment UI, generated bundles and the host binary. `make build` runs checks and builds without restarting a service.
- To dogfood **daemon-side** changes (schema migrations, reconcile/daemon logic):
- check out the feature branch on the **main checkout** and rebuild + restart there —
- `make dev-build && myco-dev restart`. After a worktree teardown + rebase the
- `~/.local/bin/myco-dev` symlink already points at the main binary, so **no
- `make dev-link` is needed** — only re-link if the symlink was removed or the build is
- switching which branch the daemon tracks.
+ For a project-local runtime override, `make dev-link-worktree` writes `.myco/runtime.command`, `.myco/runtime.home` and a wrapper pointing at that worktree's binary. It leaves shared command links alone. `make dev-unlink-worktree` removes those pins.
- **The worktree daemon path no longer self-isolates.** The dev daemon variant has
- no separate home — it writes to `~/.myco-dev` regardless of which binary runs it,
- so starting the daemon from a worktree binary would share state with the main
- dev daemon. **Never** `make dev-link` from a worktree, and
- **never** run the daemon or migrate the shared vault from a worktree — a worktree
- binary running a migration mutates the *shared* Grove vault and breaks the main/other
- builds (the rollup hazard above). The only isolated path is exercising the merged
- code against a **separate `MYCO_HOME`** (e.g. a temp git repo with
- `MYCO_HOME=~/.myco-sandbox`) — that does not touch the shared vault.
+ Set `HOME`, `CODEX_HOME`, `CLAUDE_CONFIG_DIR`, `XDG_CONFIG_HOME`, `MYCO_HOME` and `TMPDIR` inside your scratch directory for tests. Run any Myco command from that scratch directory. An explicit `MYCO_HOME` wins over the wrapper's default dev home; verify `myco doctor` and `myco member status` before attributing capture to a Deployment.
- > Myco is the most active source of truth: search the vault ("worktree dogfood")
- > before trusting this skill if they disagree. See also the
- > `daemon-process-lifecycle-management` skill for the canonical build/restart commands.
+ A member has no daemon or local vault. Hooks load the binary per invocation; a native Deployment and a registered runner each keep their running executable until their own process restarts. Restart only an isolated process you started. Agent work runs on registered runners.
- ## Related
- - `make dev-link` / `make dev-unlink` — the main-checkout dev pin (rewrites the
- shared `~/.local/bin/myco-dev` symlink); never run these from a worktree
+ Use injected service runners for lifecycle tests. A per-user service manager ignores `HOME`, so sandbox homes alone do not isolate service registration.