githubnext/chopinPublic

Let's compose rich plans together

Add an Atomic SDK harness for the hosted Planner #210

Mergedlavaman131merged 6 commits intomainfromrefs/pull/210/head
  1. LA

    ## Summary

    Adds `HARNESS=atomic`, a `HarnessV1` adapter (`apps/server/src/harness/atomic/adapter.ts`) that embeds `@bastani/atomic` 0.9.23 in the Chopin server process through its headless SDK: `createAgentSession`, `ModelRuntime`, `DefaultResourceLoader`, and in-memory session and settings managers. It does not spawn the `atomic` CLI, use RPC mode, or alias Pi. The `copilot-sdk` and `pi` harnesses are unchanged.

    - `07c5852` adds the adapter, its unit tests (`atomic/adapter.test.ts`), the shared contract suite (`harness/atomic.contract.test.ts`), `harnesses.ts`/`config.ts` wiring and tests, and docs (`docs/hosted-agent.md`, `docs/self-hosting.md`, `docs/architecture.md`, `README.md`). - `878147a` keeps the research notes that map the SDK to `HarnessV1` and list the caveats. - `4c685ef` documents that `auto` also honors the legacy `PI_CODING_AGENT_DIR`. Atomic checks `ATOMIC_CODING_AGENT_DIR` first, then `PI_CODING_AGENT_DIR`, and a set variable disables the `~/.pi` fallback.

    This branch was rebased onto `main` (99204aa). The only conflict was `bun.lock`. I regenerated it from main's lockfile, and it matches the branch's original lockfile except for main's `impeccable` entries.

    ## Security boundary

    - Only Chopin's host tools are exposed. Every shipped Atomic package is disabled (workflows, subagents, MCP, web access, Intercom), and Atomic's coding tools are not registered. - The resource loader discovers no context files, skills, prompt templates, themes, or extensions. The working and configuration directory is an empty private temporary directory. - A per-turn hook replaces the whole system prompt, so Atomic's coding-agent preamble never reaches the model. - The active tool set is re-checked before every model request, and any unexpected tool fails the turn. The session is also checked before the first request for extensions, context files, skills, templates, or prompt drift. - An unknown `MODEL` fails the turn before any model request. Atomic would otherwise silently pick another model. - Structured output uses a terminating result tool, enabled only when the turn requests a JSON response format and blocked otherwise. It does not use Atomic's `createStructuredOutputTool`, which makes a second model call.

    ## Auth modes

    `HARNESS=atomic` requires an explicit `HARNESS_AUTH`:

    - `auto` copies the host's Atomic login into memory (`$ATOMIC_CODING_AGENT_DIR`, then `$PI_CODING_AGENT_DIR`, otherwise `~/.atomic/agent` over `~/.pi/agent`), plus env keys and ambient cloud credentials. Startup refuses it unless `SERVER_HOST` is loopback-only. - `ai-gateway` reads `AI_GATEWAY_API_KEY` and accepts only `vercel-ai-gateway` models. It is the only mode allowed on a public bind.

    No credentials, `models.json`, or `models-store.json` are written to disk.

    ## Documented caveats

    - Atomic's SDK defaults suit a local coding agent. The adapter overrides them and fails closed on the ones it can observe, but a future release could add a default the suite does not check. Run the contract suite before bumping `@bastani/atomic`. - Sessions live only in memory and cannot resume across restarts. Compaction, turn suspension, and skills are unsupported. Atomic's automatic retries stay on. - Under `auto`, an in-memory OAuth refresh can rotate the host CLI's refresh token. `!command` API-key entries in `auth.json` are executed. - There is no per-session credit limit, so a worker's `maxAiCredits` does not apply. - `@bastani/atomic` adds more than 250 MB of dependencies. The rebuilt `chopin-atomic` image is 2.1 GB. - Atomic uses `typebox` 1.3.27 while Chopin pins 1.3.7. Host tool schemas cross as plain JSON Schema, so the two versions never meet.

    ## Verification on this machine

    These checks ran on a new checkout after the rebase. Earlier results from the original machine are in the `07c5852` commit trailers.

    The Playwright suite does not exercise `HARNESS=atomic`; its agent servers use `AGENT=off` or the fake harness. I tested the Atomic harness separately in a real browser against a real model.

    ### Browser test of the Atomic harness with a live model

    I started a server on loopback with `AGENT=on HARNESS=atomic HARNESS_AUTH=auto MODEL=github-copilot/gpt-6-luna`, using the E2E preloads (`e2e/github.ts` and `e2e/harness/preload.ts`). Those preloads fake only GitHub's REST and OAuth endpoints and the GitHub MCP URL. Model traffic went to GitHub Copilot through the host's Atomic login. With agent-browser I signed in through the server's real OAuth callback, added `octo-org/score` in the UI, created a document, typed a sentence, and sent two `@chopin` turns.

    1. **Read turn.** The Planner called `read_plan` and `list_pull_requests`, then answered with the document's sentence and the fixture PR title "Restring the harp section". The fake MCP log shows `list_pull_requests` was called for `octo-org/score` with a bearer token, `readonly=true`, and `toolsets=pull_requests`.

    ![A read turn with read_plan and list_pull_requests](https://github.com/user-attachments/assets/fc1360eb-8be7-49db-bbe6-fd3451ee5a3e)

    2. **Edit turn.** The Planner called `read_plan` and then `edit_plan` twice to append a three-item list and keep the existing sentence. The document and the transcript were unchanged after a page reload.

    ![An edit turn that survived a reload](https://github.com/user-attachments/assets/378b6076-35a2-476f-b075-1a4ede43ff51)

    The server's `[agent]` diagnostic listed exactly Chopin's 16 host tools plus `chopin_submit_atomic_result`. It showed no `bash`, filesystem, fetch, or Intercom tool. Nothing in `~/.atomic/agent` was modified during the run.

    Assistant-verification: docker build passed: `docker build --no-cache -t chopin-atomic .` completed; both `bun install --frozen-lockfile` stages fetched from registry.npmjs.org (build 995 packages, production 908 packages) Assistant-verification: docker runtime import passed: `docker run --rm chopin-atomic bun -e "await import('./apps/server/src/harness/harnesses.ts')"` and a direct import of `atomic/adapter.ts` both loaded `@bastani/atomic` in the production image Assistant-verification: bun run fix passed: no changes beyond the doc edit; one existing oxlint warning in the untouched `github-tools.test.ts` Assistant-verification: bun test passed: 1688 pass, 2 PostgreSQL skips, 0 fail across 190 files; `apps/server/src/harness` alone 127 pass, covering atomic, copilot-sdk and pi Assistant-verification: bun run types passed: all workspaces and E2E Assistant-verification: bun run ci passed: dprint, oxlint (0 errors), tokens, type scale, Impeccable design check Assistant-verification: bun run e2e passed: 236 Chromium tests after confirming ports 8788, 8789, 8791, 8792 and 8797 were free Assistant-verification: agent-browser E2E passed: live github-copilot/gpt-6-luna turns through HARNESS=atomic HARNESS_AUTH=auto ran read_plan, list_pull_requests over the fake GitHub MCP (bearer, readonly, pull_requests toolset) and edit_plan; the edit and transcript persisted across reload; ~/.atomic/agent was not modified Assistant-verification: atomic source check passed: `@bastani/atomic` 0.9.23 `dist/config.js` reads `ATOMIC_CODING_AGENT_DIR`, then `PI_CODING_AGENT_DIR`

    Assistant-model: Claude Opus 5.5 Assistant-workflow: inline Assistant-duration: 12m converged, estimated none given User-preference: Build the Atomic harness on Atomic's headless SDK, which separates runtime from hosts Co-authored-by: Alex Lavaee <lavaman131@github.com>

    ## Merge preparation

    Rebased onto main after #236 and #212. The database lifecycle test now allows 20 seconds for its three server starts, rather than Bun’s default five seconds. Its server-readiness checks and all assertions are unchanged. The previously passing Atomic run took 4.986 seconds; the rebased run hit the five-second limit. Fresh CI passed on the updated head: validation, browser integration, and container build.

  2. lavaman131referenced this in Empty paragraphs make room projection non-canonical, failing document descriptions #211last month on GitHub

  3. lavaman131head-ref-force-pushed 115df2598d14last month on GitHub

  4. lavaman131referenced this in Run the Planner as a full Atomic session with questions routed to Decisions #215last month on GitHub

  5. lavaman131added-to-stacklast month on GitHub

  6. MA

    No review summary.

  7. MA
    Hidden as resolved.
  8. MA

    No review summary.

  9. lavaman131head-ref-force-pushed 7544ed030aa0last month on GitHub

  10. LA
    Author
    Hidden as resolved.
  11. LA
    Author

    No review summary.

  12. MA

    all good

  13. MaggieAppletonhead-ref-force-pushed 6df7db0b4b75last month on GitHub

  14. MaggieAppletonhead-ref-force-pushed a390374b3c64last month on GitHub

  15. MaggieAppletonmerged 5ac2f30cc60alast month on GitHub

  16. MaggieAppletonclosedlast month on GitHub

  17. MaggieAppletonhead-ref-deletedlast month on GitHub