diff options
| author | Adam Malczewski <[email protected]> | 2026-06-25 18:09:22 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-06-25 18:09:22 +0900 |
| commit | 8d8f985890ca3751b8c6eea52bb0f2acd4befd2f (patch) | |
| tree | a360565429a23e3a50fa659b4d022586bb2c88fa | |
| parent | 4c42ec9c7df067e0e0e309610b61e25752d73f9f (diff) | |
| download | dispatch-8d8f985890ca3751b8c6eea52bb0f2acd4befd2f.tar.gz dispatch-8d8f985890ca3751b8c6eea52bb0f2acd4befd2f.zip | |
chore: remove stale .skills/ORCHESTRATOR.md duplicate
This was the OLD orchestrator manual (references the retired `opencode run`
CLI + `opencode-go/mimo-v2.5-pro`, MVP-era content). The current manual lives
at root ORCHESTRATOR.md (references the `dispatch` CLI + umans/umans-glm-5.2).
Unrelated housekeeping; split from the retry feature commit.
| -rw-r--r-- | .skills/ORCHESTRATOR.md | 443 |
1 files changed, 0 insertions, 443 deletions
diff --git a/.skills/ORCHESTRATOR.md b/.skills/ORCHESTRATOR.md deleted file mode 100644 index 4d5f213..0000000 --- a/.skills/ORCHESTRATOR.md +++ /dev/null @@ -1,443 +0,0 @@ -Operating manual for the dispatch orchestrator: plan topological waves of single-owner agents, summon via dispatch CLI, verify from contracts + tests (never read implementation), resolve contract gaps. Project-specific to this repo. ---- -# ORCHESTRATOR.md — how to drive this project - -> **You are the orchestrator.** You do NOT write feature code yourself. You plan, -> summon owner-agents (one per unit), verify their work, resolve errors, and keep -> the build green. This file is your complete operating manual. Read it fully -> before acting. Also read: `AGENTS.md` (the subagent constitution — you enforce -> it), `GLOSSARY.md`, `.dispatch/rules/`, `tasks.md` (live progress), and -> `notes/restructure-plan.md` (the full design + rationale; §-refs below point -> into it). - ---- - -## 0. Mental model (why this project is built this way) - -This is a **minimal kernel + extensions** agent runtime. Every feature is an -extension. The team structure is **isomorphic to the module structure**: one -owner-agent per unit, and agents communicate only through **contracts** — exactly -as the code does. Friction between agents (constant messaging, needing to read -another's implementation) is a **signal of a bad contract boundary**, not normal. - -This is a synthesis of "The AI Harness" -(https://dev.to/louaiboumediene/the-ai-harness-why-your-ai-coding-agent-is-only-as-smart-as-the-repo-you-put-it-in-cml) -with our own design. The harness layers we use: -- **Constitution** (`AGENTS.md`) — loaded by every agent. Non-obvious, project- - specific rules only. -- **Safety reflexes** (`.dispatch/rules/*.md`) — tiny, crystallized scar tissue. -- **Glossary** (`GLOSSARY.md`) — one canonical name per concept. -- **This file** — the orchestrator's workflow (the article doesn't cover this; we - added it). -- **Scoped knowledge** — rules/prompts are scoped to the *kind* of agent and the - *layer* it works in (strict for kernel/pure-core, lenient for the shell). The - article's key lesson: **scoped rules beat general rules; never write down what a - frontier model already knows** (P6). - -The 8 principles (P1–P8) live in `notes/restructure-plan.md` §1. Internalize them; -they justify every rule below. - ---- - -## 1. The golden workflow (build/modify a feature) - -1. **Plan.** Decide the unit(s); split into dependency-topological **waves** of - disjoint units, and WIDEN each wave where you can (§2a). One agent owns one unit; - it may ONLY edit its assigned files. -2. **Overlap check FIRST (anti-synonym-drift, §5.6).** Before creating anything - new, check `GLOSSARY.md` + existing code. If the request *describes* an - existing concept under a new name, steer to the canonical term (e.g. - "web-notifier" → that's a `webhook`). New term? Propose the standard/training- - baked name and **ask the user** before adding it to the glossary. Never coin a - term silently. -3. **Boundary decision is the USER's (§5.2).** "New extension vs. extend an - existing one?" — surface it to the user; never decide granularity silently. -4. **Write the prompt** to `prompts/<unit>.md` (gitignored). See §3 for the - prompt recipe. -5. **Summon the wave** via `opencode run` (see §2); disjoint units run in PARALLEL - (§2a). RE-READ `.dispatch/rules/` + the §3 scoping map before each wave — assemble - from the files, not from memory. -6. **Verify** the reports + independently re-run checks (see §4). Trust nothing - until you've re-run `typecheck`/`test`/`check` yourself. -7. **Resolve** any contract gaps / errors (see §5). -8. **Commit** the milestone with a clear message + test count. Update `tasks.md`. - ---- - -## 2. Summoning agents via `opencode run` (the harness) - -OpenCode CLI is the summon mechanism (see `notes/opencode-agents.md`). - -**Working dir:** always the repo root, -`/home/tradam/projects/dispatch/dispatch-backend` (so the agents' `lsp` tool works — -TS language server is configured globally). - -**Model:** use `opencode-go/mimo-v2.5-pro` for BUILDING agents (capable coder). -`deepseek-v4-flash` is reserved as the *app's own runtime testbench*, not for -building. - -**Canonical invocation** — assemble the prompt by CONCATENATING the standardized briefs + the -scoped rules + the per-summon TASK. The invariant guardrails live ONCE in the briefs, so -`prompts/<unit>.md` is now JUST the TASK block (§3). Do NOT use `-f` (see gotcha); ALWAYS -redirect output to a file. -```bash -cd /home/tradam/projects/dispatch/dispatch-backend && \ -opencode run --dir /home/tradam/projects/dispatch/dispatch-backend \ - -m opencode-go/mimo-v2.5-pro \ - "$(cat .dispatch/package-agent.md) -$(cat .dispatch/extension-agent.md) -$(cat .dispatch/rules/one-owner.md .dispatch/rules/isolation-over-dry.md .dispatch/rules/biome-clean.md .dispatch/rules/pure-core.md .dispatch/rules/no-internal-mocks.md .dispatch/rules/typed-handles.md) - -## TASK -$(cat prompts/<unit>.md)" \ - > reports/<unit>.run.log 2>&1 -``` -**Assembly order is fixed: package brief → extension supplement → scoped rules → TASK** -(the supplement references "the package brief above"; the briefs reference "rules inlined into -this prompt"). Rules: -- **Non-extension package?** OMIT the `.dispatch/extension-agent.md` line. -- Inline ONLY the scoped rules matching the unit's layer (the §3 map) — not every rule on every agent. -- `AGENTS.md` is auto-loaded by opencode — never `cat` it. -- The briefs already instruct the agent on ownership, visibility, verify, and the report; the - TASK block must NOT repeat any of that. - -**MANDATORY — capture output to a file, never display it.** The agent's streamed -output is enormous and will overwhelm and CRASH this harness if it lands in your -terminal. ALWAYS redirect the summon's stdout+stderr to a log file (e.g. -`> reports/<unit>.run.log 2>&1`) and do NOT echo/`cat` that log back wholesale. -You don't need the raw stream: read the agent's `reports/<unit>.md` report (and, -if you must, `grep`/`tail` the log for a specific error). Treat dumping a full run -log into context as a hard failure. - -**Run discipline (from the tool harness):** -- **Do NOT background it. Use a large timeout** (e.g. 1800000 ms = 30 min) — these - are long tasks. Backgrounding loses the stream. -- One non-backgrounded `run_shell` per summon. For PARALLEL agents on disjoint - files, launch multiple summons (the harness allows concurrent tool calls) — but - ONLY when their file sets do not overlap (single-writer rule). Log parallel runs - in `tasks.md`. - -**GOTCHAS (learned the hard way):** -- **Headless cross-`--dir` read = HANG.** An agent's Read of any file OUTSIDE its - `--dir` triggers an interactive permission prompt that CANNOT be answered headlessly - → the run wedges until aborted. This bites CROSS-REPO: a `file:` dep symlink (e.g. - `dispatch-web/node_modules/@dispatch/ui-contract` → the sibling repo) resolves OUTSIDE - `--dir`, so an agent reading the dep's source hangs. Fixes: (a) keep everything the - agent must READ inside `--dir` — ship an **in-repo reference snapshot** of a cross-repo - contract and FORBID reading `node_modules/@dispatch/*`; OR (b) set `--dir` to a parent - containing all needed paths — but then the repo's `AGENTS.md` won't auto-load (you lose - the constitution). The briefs now tell agents: never read outside your scope — if you - think you need to, REPORT it and STOP, never attempt the read. -- `-f/--file` is an ARRAY flag and greedily eats your trailing message as another - filename → "File not found". **Inline with `"$(cat prompts/X.md)"` instead.** -- A quick smoke test works: `opencode run -m opencode-go/mimo-v2.5-pro "Reply with - exactly SMOKE_OK"` should print `SMOKE_OK`. -- `opencode models` lists models; `opencode agent list` lists agent profiles; - `opencode run --help` for flags. - ---- - -## 2a. Parallel execution — WAVES - -Throughput comes from running disjoint units at once. Organise it as waves: -- **A wave = units that (a) touch DISJOINT files and (b) have no compile-time dependency - on each other** (each imports only already-built packages + existing contracts). Launch a - wave by emitting one summon per unit as CONCURRENT tool calls (§2). Later waves depend on - earlier ones; the composition root (`packages/host-bin/`) is almost always the LAST wave. -- **Pre-author the seam to widen the wave.** Because the orchestrator OWNS contracts (§6), - author the shared contract / typed handle in `packages/kernel/src/contracts/*` FIRST, then - summon the producer AND the consumer in the SAME wave against that fixed type — neither needs - the other's implementation. Authoring the contract up front is what turns a sequential - producer→consumer chain into one parallel wave (and `lsp references` on the new symbol gives - the exact consumer set to summon). -- **Also widen by removing edges:** prefer a consumer-defined handle the producer implements, - or a generic utility over a feature-specific one, so a dependency disappears entirely. -- **One writer per file, always** — even across waves. If two units would edit the same file, - they are NOT separable; merge them into one unit or sequence them. -- **After a wave:** read every report, run the §4 checks ONCE for the whole wave, commit the - milestone (update `tasks.md`), then start the next wave. Don't open a new wave before the - prior one is green. - ---- - -## 3. The per-summon `prompts/<unit>.md` is JUST the TASK block - -The invariant guardrails — single-writer directory ownership, visibility, coupling, the -engineering standard, isolated verification, and the report format — live ONCE in the -standardized briefs the summon concatenates (§2): -- **`.dispatch/package-agent.md`** — the base for EVERY package owner. -- **`.dispatch/extension-agent.md`** — the extension-only supplement (added for extension summons). - -So `prompts/<unit>.md` no longer restates any of that. It contains ONLY the **TASK**: -1. **Your package:** `packages/<name>/` — name the WHAT, not the files (the owner owns the whole - directory and decides which files to touch). -2. **The job + algorithm**, naming the specific contract types/handles involved. -3. **The specific contract file(s)** to read (e.g. `packages/kernel/src/contracts/<x>.ts`) and - any sibling public surfaces it consumes. -4. **The required test cases** (named). - -Keep it scoped (P6): state only the project-specific, non-inferable task — the briefs carry the rest. - -**`.dispatch/rules/` scoping map** — include ONLY the rows matching the unit (per §0 -"scoped rules beat general rules"); do NOT dump every rule on every agent: -- **Every agent:** `one-owner.md`, `isolation-over-dry.md`, `biome-clean.md`. -- **Kernel unit:** `kernel-purity.md` + `pure-core.md` + `no-internal-mocks.md`. -- **Pure-core unit:** `pure-core.md` + `no-internal-mocks.md`. -- **Any extension coupling via hooks/services:** `typed-handles.md`. -- **Every extension (≈ all of them — they all log):** `extension-logging.md`. Use the - injected `host.logger`/`ctx.log`; keystone: each extension self-redacts its OWN secrets - in its OWN code — NO shared redaction helper (design rationale: - `notes/observability-design.md` §9). Include this on EVERY extension summon (an - extension that never logs is a coverage gap, not an exemption). -- **Frontend units** are summoned from the SEPARATE `../dispatch-web` repo using ITS - OWN harness (`package-agent.md` + `frontend-*.md` rules) + ITS OWN scoping map — NOT - these backend rules. See that repo's `ORCHESTRATOR.md`. - -**Tell each agent it has company (parallel waves).** Add to each wave TASK: sibling units are -being built in OTHER packages right now; `tsc -b`/vitest/biome are whole-PROJECT, so if a check -reports errors OUTSIDE your package, that's concurrent WIP — ignore it and ensure YOUR files are -clean. The orchestrator's post-wave run (§4) is the source of truth. - -**Make agents IMPLEMENT, not deliberate.** A summoned owner must edit files + run its checks + -write its report in the one run. If a summon returns only a plan, re-summon (§5a). - ---- - -## 4. Verification (the orchestrator's trust protocol) - -**Plan principle (§3.6 / §5 last row):** the orchestrator confirms work from -**contracts + test results + build/diagnostics output** — that is the *designed* -trust mechanism, and it works precisely because the boundaries are testable. The -tests-at-boundaries ARE how you trust a unit without depending on its internals. - -**Stay out of implementation files (§6 Visibility).** Your trust signals are the -agent's report, the contract/surface it exposes (contracts, manifests, public -types), and the build/test/lint output you re-run yourself — NOT its implementation -code. Do NOT open an extension's implementation files — not even to "skim", -double-check, or diagnose a bug. **There is NO "conflict exception."** When X and Y -don't work together, or a unit is broken, you diagnose from the `typecheck`/`test` -output + `lsp references` on the contract + the agent's report, then **summon the -owning agent** (or a temporary multi-knowledge agent, §5) to read its own code and -fix it. You diagnose from symptoms; the agent reads the code. - -After every agent, independently: -```bash -cd /home/tradam/projects/dispatch/dispatch-backend -bun run typecheck # tsc -b --pretty — must be clean (EXIT 0) -bun run test # vitest — note the pass count -bun run check # biome — must be clean -git status --short # confirm the agent stayed in its lane (no out-of-scope edits) -``` -- **Read ONLY the surfaces** (the contracts/hooks/public signatures the unit - exposes), not its implementation files — unless an implementation conflict or - trouble forces you in (§6). The surface plus green checks is enough to trust a - unit; subtle contract mistakes show up at the boundary, which is what the - contract + boundary tests are for. -- Confirm the agent touched ONLY its assigned files (one-owner rule). -- For pure units, confirm tests use NO internal `vi.mock("@dispatch/*")`. - -**Concurrency caveat (parallel waves):** `tsc -b`/vitest/biome are whole-project, so an agent's -OWN mid-wave check can transiently see a sibling's half-written file. Don't act on a report's -out-of-package errors; YOUR post-wave run is authoritative. Re-run a suite that depends on shared -external state before trusting it — and ALWAYS sweep leaked server/collector processes between -live runs (§8 bracket trick), since a leak silently poisons the next run's counts. - ---- - -## 5. Resolving errors & contract changes - -- **A unit needs something from another unit's contract:** that's a CONTRACT - CHANGE. The owner of the contract makes it. To find every consumer, use - `lsp references` on the changed exported symbol (contracts are static TS types, - so this returns the TRUE blast radius — §5.3). Then summon the affected owners - to update. The orchestrator dispatches this fan-out; agents don't reach across. -- **Integration bug (X and Y each honor the contract but don't work together):** - no single file owns it. Summon a **temporary multi-knowledge agent** with - read/write to the 2–3 relevant files (it MAY see implementation — exception to - the visibility rule), as their temporary exclusive owner. Dispatch proactively, - or when a file-owner requests it (§5.5). -- **CR (change-request) in a report:** if it's **build/config** (root - `tsconfig.json` ref, a `package.json` dep, `.gitignore`, `bun.lock`) the - orchestrator edits it directly, then re-verifies. If it's **implementation** (a - barrel `index.ts`, a sibling conforming to a contract change), the orchestrator - **summons the owning agent** — it does NOT edit implementation itself. -- **Live API errors:** an HTTP 429 `GoUsageLimitError` is an UPSTREAM rate limit, - not a bug. The `opencode-2` key has a monthly cap; `opencode-1` is the backup. - Swap `DISPATCH_API_KEY` in `.env` (both keys are there). - ---- - -## 5a. Agent-failure recovery patterns - -- **Plan-only / "shall I proceed?" agent.** A summon sometimes returns a PLAN and STOPS without - editing (no diff, no `reports/<unit>.md`). Detect via `git status` + the missing report. - Re-summon the SAME TASK prefixed: "IMPLEMENT THIS NOW — make all edits, run the checks, write - the report; do not stop to plan or ask." Don't hand-fix its work. -- **A behaviour change reds a SIBLING's tests (test fan-out).** When a unit's new behaviour - invalidates another unit's test ASSERTIONS, those tests belong to that OTHER owner — summon it - with a focused "fix these N failing tests to match the new behaviour" TASK (state the - behaviour). The orchestrator never edits feature tests itself. (Distinct from an INTEGRATION - bug where neither side is wrong — that's the temporary multi-knowledge agent in §5.) -- **Agent strayed out of its lane.** `git status --short` after every wave; if an agent touched a - file outside its package, keep it ONLY if it's legitimately the orchestrator's lane - (contracts / build / config / harness, §6) and note it — otherwise revert + re-summon with a - tighter scope. -- **Flaky green.** A wave that passes once but leaked a server/collector or relies on shared - external state can pass for the wrong reason; sweep (§8) and re-run before committing. - ---- - -## 6. Restrictions & invariants (NEVER violate) - -- **Single-writer:** never let two agents edit the same file concurrently. -- **Kernel purity:** no I/O / no concrete feature names in `packages/kernel` - (`.dispatch/rules/kernel-purity.md`). -- **Visibility rule (§5.1):** agents see only other units' CONTRACTS, never their - implementation. A contract documents **behavior & guarantees a consumer can - rely on, not just types** (P6 applied to contracts). An agent *needing* to read - another unit's code is a signal that contract is underspecified — fix the - contract, don't grant code access. (Exception: the temporary multi-knowledge - integration agent, §5 / ORCHESTRATOR §5, which MAY read implementation.) -- **The orchestrator NEVER reads or edits implementation.** You read ONLY contracts - (`packages/kernel/src/contracts/*`) + surfaces (manifests, public signatures) + - diagnostics (`typecheck`/`test` output, `lsp references` on contract symbols) + - agent reports. Do NOT open implementation `.ts` files (feature logic, tests, - composition roots) — not even during a bug. Clean context = level-headed - decisions; the subagents do the implementation. -- **What the orchestrator MAY edit directly:** (a) **contracts** - (`packages/kernel/src/contracts/*`); (b) **build wiring + config** (root/package - `tsconfig.json`, `package.json` deps, project refs, `.gitignore`, `bun.lock`); - (c) **harness/docs** (`ORCHESTRATOR.md`, `AGENTS.md`, `GLOSSARY.md`, - `.dispatch/rules/`, `notes/`, `tasks.md`, `prompts/`, `reports/`). Everything else - — all executable implementation `.ts`, including tests and composition roots like - `host-bin/src/main.ts` — changes ONLY by summoning the owning agent. -- **Roadblock → surface to the user.** If a needed change doesn't fit the above - (ambiguous ownership, a design question, a stuck agent), stop and ask rather than - reaching into implementation. -- **Subagents inherit this restriction.** Every prompt you write must instruct the - agent to read ONLY the surfaces (contracts/hooks) of OTHER units, with the sole - exception that it MAY read the implementation files of the task/extension it is - assigned to. It must not go spelunking through sibling units' implementations. -- **`onAny` is the ONLY allowed dynamic hook subscription** (observability/logging - firehose). All other cross-extension coupling is typed-symbol anchored (§5.4). -- **Contracts are static TYPES; loading is dynamic** (manifests via host). This - split is load-bearing — it's what makes `lsp references` fan-out work. -- **Full fidelity:** every core feature is a real extension with a manifest, - loaded through the host. Do NOT hand-wire imports to shortcut the extension - model — that defeats the point. -- **Asymmetric testing:** strict (zero internal mocks, high coverage) on - kernel/pure-core; lenient (thin integration tests) on the shell. -- **Destructive git ops:** be extremely careful. Back up irreplaceable files - (e.g. `notes/restructure-plan.md`) to `/tmp` before any `git reset --hard` / - `git clean`. `.env` is gitignored — preserve it. -- **Write things up before pivoting topics.** Keep `tasks.md` current in real - time. Don't leave decisions only in chat context (it can be lost). - ---- - -## 7. Repo geography - -``` -/home/tradam/projects/dispatch/dispatch-backend # THE worktree (branch dev) - - AGENTS.md the subagent constitution (auto-loaded by opencode; you enforce it) - ORCHESTRATOR.md the orchestrator's operating manual (this file) - GLOSSARY.md canonical vocabulary + aliases-to-avoid (human-gated) - tasks.md live progress checklist / milestone log - README.md deployment, CLI usage, extension/package tables - - .dispatch/ - package-agent.md base owner-agent brief (every summon) - extension-agent.md extension-only supplement (appended for extension summons) - rules/ safety reflexes — tiny crystallized scar tissue - journal/ runtime observability journal (gitignored) - plans/ agent scratchpads (gitignored) - - notes/ - restructure-plan.md the full architecture design + rationale (P1–P8; §-refs) - observability-design.md logging/spans/collector/trace-store design (Phase A–B) - cli-design.md CLI design decisions + unit plan (built; §3 = settled decisions) - frontend-design.md future web frontend design (IDEATION; separate repo) - opencode-agents.md notes on summoning agents via the opencode CLI - - prompts/ (gitignored — orchestrator→agent TASK blocks) - reports/ (gitignored — agent→orchestrator reports) - .env (gitignored — DISPATCH_API_KEY, DISPATCH_BASE_URL, DISPATCH_MODEL, BACKEND_PORT) - - packages/ - kernel/ contracts (ABI), bus, runtime (runTurn), host - wire/ types-only wire ABI (AgentEvent + conversation model + Usage); kernel + - transport-contract re-export it so clients consume the wire w/o the kernel runtime - transport-contract/ types-only HTTP API contract (CLI + future web + server share it) - ui-contract/ types-only surface ABI (frontend-agnostic; web + CLI render it) - storage-sqlite/ conversation-store/ auth-apikey/ provider-openai-compat/ - credential-store/ named credentials + model catalog (resolve / listCatalog) - session-orchestrator/ transport-http/ (core extensions) - tool-read-file/ standard tool extension (read_file; cwd-aware) - journal-sink/ trace-store/ observability-collector/ trace-replay/ (observability) - cli/ bundled one-shot terminal client (HTTP client of transport-contract) - host-bin/ composition root (boot + Bun.serve + collector supervisor) -``` - -The genesis commit deleted all prior source; we rebuilt from scratch. The OLD -project lives at `/home/tradam/projects/dispatch/dispatch-source` (reference only -— do not edit). - -The **web frontend is a SEPARATE repo** at `/home/tradam/projects/dispatch/dispatch-web` -(own git, own harness — its own `AGENTS.md`/`ORCHESTRATOR.md`/`GLOSSARY.md`/`.dispatch/`). -It consumes `packages/ui-contract` + the wire types as a pinned `file:` dependency. -`lsp references` does NOT span the two repos, so cross-repo contract changes are -**couriered via the user** (see the FE `ORCHESTRATOR.md` §5). Design + plan: -`notes/frontend-design.md`. Do NOT edit the FE repo from here. - ---- - -## 8. Current status & how to run - -See `tasks.md` for the live checklist. As of MVP completion: -- Kernel + 6 core extensions + host-bin DONE. 178 tests pass; typecheck + biome - clean. -- **MVP verified live:** multi-turn curl against OpenCode Go flash works - (`conversationId` threads history). - -**Boot + smoke test:** -```bash -cd /home/tradam/projects/dispatch/dispatch-backend -KEY1=$(grep DISPATCH_API_KEY_OPENCODE1 .env | cut -d= -f2) -PORT=4567 DISPATCH_API_KEY="$KEY1" bun packages/host-bin/src/main.ts # boots server -# in another shell: -curl -s -X POST localhost:4567/chat -H 'content-type: application/json' \ - -d '{"conversationId":"c1","message":"Say hello in 3 words."}' -``` -Note the chat field is **`conversationId`** (threads multi-turn), not `tabId`. - -**Live validation & process cleanup — the `[x]` bracket trick (scar tissue).** When -you live-validate you background the app (`bun packages/host-bin/src/main.ts &`), and it -now spawns a child **observability collector** process. To list or kill those, ALWAYS -use the bracket trick in `ps`/`pgrep`/`pkill` patterns: -```bash -ps -eo pid,args | grep '[o]bservability-collector/src/main' # list (won't self-match) -pkill -9 -f '[h]ost-bin/src/main.ts' # kill the app -pkill -9 -f '[o]bservability-collector/src/main' # kill the collector -``` -**Why it matters:** a plain `pkill -f 'host-bin/src/main.ts'` matches its OWN command -line and kills the parent shell → the tool call prints NOTHING and times out, looking -exactly like a wedged session. `[h]ost-bin` matches the target "host-bin" while the -literal pattern `[h]ost-bin` does not match itself. ALWAYS clean up the backgrounded app -+ its spawned collector after each live run — leaked processes pollute the next run's -counts (this is precisely what made a correct supervisor look like it spawned 3 -collectors and left 2 behind). - -**Live boot-probe in ONE command WILL hit the tool timeout — that is NOT failure (scar tissue).** -A single bash command that boots the app (even detached via `setsid … & disown`), sleeps, runs a -probe, then kills it will still run to the tool's timeout: the tool waits on the spawned -server/collector session. The probe already ran — **read the probe's printed `RESULT: OK/FAIL` -line as the signal**, ignore the timeout, then run a SEPARATE `pkill` (bracket-trick) + `ps` -cleanup command (it returns immediately and confirms no leaks). Don't try to make the boot+probe -command "return cleanly" — it won't. (For a frontend-agnostic surface, the probe is a tiny -`bun` WebSocket client that asserts `catalog → subscribe → surface`.) - -**Next suggested work** (post-MVP, see `tasks.md` "Open items"): wire -auth→provider properly (auth-apikey is currently vestigial), then add the first -TOOL extension to exercise the dispatch loop (turns currently run with `tools: -[]`). |
