II.
Page JSON
Structured · livepage:docs-agent-mux-archive-comparisons-18-babysitter-sdk-parity
18 — Babysitter SDK Parity Analysis json
Inspect the normalized record payload exactly as the atlas UI reads it.
{
"id": "page:docs-agent-mux-archive-comparisons-18-babysitter-sdk-parity",
"_kind": "Page",
"_file": "wiki/docs/agent-mux/archive/comparisons/18-babysitter-sdk-parity.md",
"_cluster": "wiki",
"attributes": {
"nodeKind": "Page",
"sourcePath": "docs/agent-mux/archive/comparisons/18-babysitter-sdk-parity.md",
"sourceKind": "repo-docs",
"title": "18 — Babysitter SDK Parity Analysis",
"displayName": "18 — Babysitter SDK Parity Analysis",
"slug": "docs/agent-mux/archive/comparisons/18-babysitter-sdk-parity",
"articlePath": "wiki/docs/agent-mux/archive/comparisons/18-babysitter-sdk-parity.md",
"article": "\n# 18 — Babysitter SDK Parity Analysis\n\n> Archived parity document. Preserved for historical context; not part of the current normative `reference/` contract.\n\n**Date:** 2026-04-12\n**Upstream:** github.com/a5c-ai/babysitter @ `staging` — `packages/sdk/src/harness/*`\n**Local:** `C:/work/agent-mux/packages/adapters/src/*-adapter.ts`\n\n> Note on scope: babysitter's `HarnessAdapter` and agent-mux's `AgentAdapter` are **not the same contract**. babysitter adapters are *orchestration-loop controllers* (session-binding, stop-hook decisions, iteration caps, inactive retained-state exits, completion-proof matching) that live next to an external harness. agent-mux adapters are *subprocess adapters* (spawn args, JSONL event parsing, auth, config, sessions on disk). Still, several generic features from babysitter are directly portable and close real gaps.\n\n---\n\n## 1. Per-Adapter Gap Table\n\n| Adapter | babysitter file | agent-mux file | Babysitter-only features (gaps in agent-mux) |\n|---|---|---|---|\n| **claude** | `harness/claudeCode.ts` | `claude-adapter.ts` | PID-scoped session marker (`~/.a5c/state/current-session-pid-{PID}`); `CLAUDE_ENV_FILE` last-match resolution; `bindSession` with re-entrancy guard; `handleStopHook` (iteration cap 65000, inactive retained-state exits, breakpoint-only gating, promise-tag `<promise>VALUE</promise>` completion proof, density-filter prompt compression, processLibraryCache pre-warming); `STOP_HOOK_INVOKED` journal telemetry; process-tree ancestor walk (wmic/PowerShell on Windows); atomic tmp→target env file writes. |\n| **codex** | `harness/codex.ts` | `codex-adapter.ts` | Session ID cascade (`CODEX_THREAD_ID`, `CODEX_SESSION_ID`); stop-hook delegates to claude adapter (shared loop logic); snake_case/camelCase input normalization; synthetic stdin injection for delegated hooks. |\n| **cursor** | `harness/cursor.ts` | `cursor-adapter.ts` | `conversation_id` extraction from hook stdin; `followup_message` auto-continue contract; IDE vs. CLI hook-type split (rejects `after-agent-response` in CLI); promise-tag matching against `run.completionProof`; fallback run resolution under `.a5c/.a5c/runs/`. |\n| **gemini** | `harness/geminiCli.ts` | `gemini-adapter.ts` | `{\"decision\":\"block\",\"reason\":…,\"systemMessage\":…}` stop-hook contract; `prompt_response` parsing; `GEMINI_EXTENSION_PATH/hooks/after-agent.sh` dispatcher; env signals `GEMINI_PROJECT_DIR`, `GEMINI_CWD`. |\n| **copilot** | `harness/githubCopilot.ts` | `copilot-adapter.ts` | `sessionEnd` cleanup handler; env-file stale-line stripping (`setBabysitterSessionIdInCopilotEnvFile`); explicit \"in-turn model\" capability flag (no stop-hook). |\n| **opencode** | `harness/opencode.ts` | `opencode-adapter.ts` | `shell.env` plugin hook for auto-injecting `BABYSITTER_SESSION_ID`; `.opencode/plugins/` + Accomplish data-dir discovery; explicit capability set `[HeadlessPrompt]`. |\n| **openclaw** | `harness/openclaw.ts` | `openclaw-adapter.ts` | Composite session key `agent:<id>:<channel>:<type>:<id>`; daemon model (no spawn); programmatic plugin registration. |\n| **pi / omp** | `harness/pi.ts`, `ohMyPi.ts` | `pi-adapter.ts`, `omp-adapter.ts` | Explicit `supportsHookType(): false`; runId-mismatch error on re-bind; `createPiContext()` prompt-context generator. |\n| **custom / null** | `harness/customAdapter.ts`, `nullAdapter.ts` | *(no equivalent)* | Fallback adapter that demands explicit `--session-id`; null adapter for unknown environments. |\n| *(cross-cutting)* | `harness/fallbackChains.ts`, `registry.ts`, `capabilityRouter.ts`, `selectionPolicies.ts`, `modelSelection.ts` | *(partial in core)* | Ordered fallback sequence with failure set and `maxRetries`; capability-based routing; selection policies. |\n\n---\n\n## 2. Top 10 Generic Feature Gaps\n\n1. **Orchestration stop-hook loop** — iteration counter, `maxIterations` (65000), breakpoint-only gating. Not present in any agent-mux adapter.\n2. **Completion-proof / promise-tag matching** — `<promise>VALUE</promise>` extraction from last assistant message cross-checked against run metadata.\n3. **Session binding with re-entrancy guard** — prevents two runs grabbing the same harness session; auto-releases on terminal run state.\n4. **PID-scoped session markers + ancestor-PID walk** — Windows fallback via wmic/PowerShell; tolerates forked shells.\n5. **Fallback chain / capability router** — `fallbackChains.ts` + `capabilityRouter.ts` aren't mirrored in agent-mux's router.\n6. **Structured journal telemetry** — `STOP_HOOK_INVOKED` events (decision, reason, pending kinds, run state) appended to the run journal.\n7. **Prompt compression / density filter + processLibraryCache** — reduces context size across iterations with TTL cache; agent-mux does no prompt compression.\n8. **Atomic env-file writes with stale-line stripping** — `CLAUDE_ENV_FILE` / Copilot env file handling; last-match semantics; tmp→rename.\n9. **Hook logger** — per-hook log at `~/.a5c/log/{hookName}.log`, best-effort, context-rich (session/run/ancestor/alive). agent-mux has no hook-side logger.\n10. **Explicit capability enums** (`HeadlessPrompt`, `SessionBinding`, `StopHook`, `MCP`, `Programmatic`) — surfaced per adapter so callers can branch; agent-mux's `AgentCapabilities` is large but lacks the orchestration-layer flags (`supportsStopHook`, `supportsSessionBinding`, `inTurnOnly`).\n\n---\n\n## 3. Actionable Follow-ups\n\n| # | Area | File (agent-mux) | Suggested change |\n|---|------|------------------|------------------|\n| F1 | Capabilities surface | `packages/core/src/types.ts` (AgentCapabilities) | Add `supportsStopHook`, `supportsSessionBinding`, `supportsInTurnOnly`, `autoResolvesSessionId`, `maxIterationsDefault` fields. |\n| F2 | Base session binding | `packages/adapters/src/base-adapter.ts` | Add `bindSession({sessionId, runId})` + `~/.a5c/state/{sessionId}.md` state file with re-entrancy guard; mirrors `bindSessionImpl` from babysitter. |\n| F3 | Stop-hook loop primitives | new `packages/adapters/src/stop-hook.ts` | Port iteration counter, `iterationTimes[]` runaway detector, breakpoint-only gate, promise-tag parser from `claudeCode.ts`. |\n| F4 | Claude PID marker | `packages/adapters/src/claude-adapter.ts` | Add PID-scoped marker file + `CLAUDE_ENV_FILE` last-match resolver in `resolveSessionId`. |\n| F5 | Codex session cascade | `packages/adapters/src/codex-adapter.ts` | Extend `resolveSessionId` to read `CODEX_THREAD_ID` then `CODEX_SESSION_ID` before legacy `BABYSITTER_SESSION_ID`. |\n| F6 | Cursor followup contract | `packages/adapters/src/cursor-adapter.ts` | Add stop-hook emitter that returns `{followup_message}` JSON; reject `after-agent-response` when in CLI mode. |\n| F7 | Gemini decision JSON | `packages/adapters/src/gemini-adapter.ts` | Add `decision:\"block\"/\"allow\"` + `systemMessage` helper for stop hooks; include `GEMINI_PROJECT_DIR`/`GEMINI_CWD` in hostEnvSignals. |\n| F8 | Copilot env-file hygiene | `packages/adapters/src/copilot-adapter.ts` | Add `setBabysitterSessionIdInCopilotEnvFile` equivalent — strip prior lines, atomic rename. |\n| F9 | Fallback chain utility | new `packages/core/src/fallback-chain.ts` | Port `resolveFallbackHarness(chain, failed, maxRetries)` returning `{next, attempt, isFallback, exhausted}`. |\n| F10 | Hook logger | new `packages/core/src/hook-logger.ts` | Structured logger → `~/.a5c/log/{hookName}.log`; best-effort, context-rich; used by all adapters' hook handlers. |\n| F11 | Journal telemetry | `packages/core/src/journal.ts` (or equivalent) | Emit `STOP_HOOK_INVOKED` with `{decision, reason, iteration, runState, pendingKinds, hadPromise}`. |\n| F12 | Prompt compression | new `packages/core/src/density-filter.ts` | Port `densityFilterText` + `processLibraryCache` with TTL; hook into iteration prompt builder. |\n| F13 | Custom / null adapters | `packages/adapters/src/` | Add `custom-adapter.ts` (requires explicit session-id) and `null-adapter.ts` (safe no-op) to match babysitter's fallback ladder. |\n| F14 | Retry policy default | `packages/adapters/src/base-adapter.ts::shouldRetry` | Extend `retryOn` defaults to include `AUTH_EXPIRED`; add exponential backoff helper (babysitter delegates but agent-mux owns retries). |\n| F15 | Windows process-tree walk | `packages/core/src/process-tree.ts` | Add wmic + PowerShell fallback for ancestor PID resolution (used by Claude adapter). |\n\n---\n\n## 4. API Shape Differences (summary)\n\n- **agent-mux**: class-based `BaseAgentAdapter` with `buildSpawnArgs`/`parseEvent`/`detectAuth`/session-on-disk.\n- **babysitter**: factory-returning `HarnessAdapter` object with `isActive`/`bindSession`/`handleStopHook`/`handleSessionStartHook`/`installHarness`/`installPlugin`/`getPromptContext`.\n- These are **complementary, not overlapping**. A future `OrchestrationAdapter` mixin or sibling interface on agent-mux adapters would let a single package expose both. See F1–F3.\n",
"documents": []
},
"outgoingEdges": [],
"incomingEdges": [
{
"from": "page:docs-agent-mux-archive-comparisons",
"to": "page:docs-agent-mux-archive-comparisons-18-babysitter-sdk-parity",
"kind": "contains_page"
}
]
}