Run the Planner as a full Atomic session with questions routed to Decisions - #215
lavaman131 wants to merge 11 commits into
Conversation
| if (!run.stopped) { | ||
| run.emit({ type: "stream-start", modelId: agent.model?.id }); | ||
| await agent.prompt(text, { expandPromptTemplates: false }); | ||
| await agent.prompt(text, { expandPromptTemplates: !!full }); |
There was a problem hiding this comment.
The session closes after the “workflow started” reply, so later workflow questions never reach Decisions. Could we track owned workflows through workflow_lifecycle in atomicTurnExtension, then wait for them here before ending the stream or clearing current? Cancellation should stop those workflows and release the wait.
This needs changes in a few places, so there isn't a safe single-line replacement. Please cover the case where a workflow asks a question after the initial reply finishes.
There was a problem hiding this comment.
Agreed, that was a real gap. It's fixed in the PR stacked on this one, #230, using a slightly different approach. Instead of holding the stream open until the workflow finishes, Chopin keeps the atomic Planner session and its owner binding after the turn whenever the session still owns live or paused workflow runs. It tracks them through Atomic's workflow activity stream and workflow_lifecycle events. So the chat turn ends normally, but later questions from the workflow still reach Decisions through the same session, and the next turn reuses it.
Cancellation is handled too: Stop Planner pauses the session's runs through session.workflows, and Resume Planner resumes them. The session is let go when its runs end, the owner binding ends, or the document closes. Covered by a Planner that still owns workflow runs outlives its turn, pauses, resumes, and is let go when they finish, plus a live run where the workflow asked its intent review well after the launch reply and was answered in Decisions.
Assistant-workflow: inline
Assistant-verification: bun test passed: retention, pause/resume, and release tests in #230
Co-authored-by: Alex Lavaee lavaman131@github.com
| })), | ||
| }], | ||
| })); | ||
| // Verbatim host input has no per-field limits, so the document bounds it. |
There was a problem hiding this comment.
A long answer can make the saved document too large for the Planner to edit afterwards. Check it on a temporary copy first; if it doesn't fit, the real document stays unchanged and the question stays open. I checked this against the oversized-answer reproduction.
In submit(), replace the call to room.projectAnswer(plan.document, msg.id, answers, settled) with:
let preview = await room.create(room.project(plan.document));
try {
room.projectAnswer(preview, msg.id, answers, settled);
room.validate(room.project(preview));
} finally {
preview.doc.destroy();
}
mutation = room.projectAnswer(plan.document, msg.id, answers, settled);There was a problem hiding this comment.
Confirmed and fixed in 6e7685e with your preview check. To reproduce it: with about 100 KB of prose in the document, four 50 KB edits (each under the 64 KiB edit limit) built an answer that saved a 302 KB document, past the 256 KiB limit, after which a Planner edit was refused. Now the submit is refused, the document is unchanged, and the question stays open. The new test fails without the check and passes with it.
Assistant-workflow: inline
Assistant-verification: fail-before/pass-after passed: oversized answer refused with the document unchanged and the question open
Co-authored-by: Alex Lavaee lavaman131@github.com
| question: workflow ? `${question.question}\n\n${workflow}` : question.question, | ||
| options: question.options.map(option => ({ | ||
| label: option.label, | ||
| description: option.description, |
There was a problem hiding this comment.
People need to see the supplied mockup or code before choosing. Including the preview in the description gives Decisions the missing content without changing the option labels or answers.
| description: option.description, | |
| description: [option.description, option.preview] | |
| .filter(value => value !== undefined) | |
| .join("\n\n"), |
There was a problem hiding this comment.
Applied in 6e7685e. The preview now follows the description, and the label and the returned answer are unchanged. The test checks an option with a preview and one without.
Assistant-workflow: inline
Co-authored-by: Alex Lavaee lavaman131@github.com
e2654f8 to
6e7685e
Compare
Opt in with ATOMIC_PLANNER=full only under local authentication and the Atomic harness. Verify each Planner checkout's origin before enabling Atomic coding tools, builtins, and operator resources. Unregistered worker sessions and Planner sessions without a verified checkout retain the isolated boundary. Bind Chopin's Decisions to Atomic HostInput rather than intercepting tools. Map questionnaires and dialogs, preserve raw answers, label workflow requests, and withdraw pending cards on abort or timeout after durable persistence. Document the operator-level shell and filesystem trust change. Assistant-model: Claude Opus 5.5 Assistant-workflow: goal (run 98acf681-3730-4957-b885-0d70e0e6b32a) Assistant-verification: bun test passed: 1706 pass, 2 PostgreSQL skips, 0 fail across 193 files Assistant-verification: bun test apps/server/src/harness passed: 141 tests, including full Atomic SDK tools, resources, cwd, HostInput and isolated fallback Assistant-verification: bun run types passed: all workspaces and E2E TypeScript checks Assistant-verification: bun run fix passed: formatting inspected; no errors and one existing lint warning Assistant-verification: bun run ci passed: formatting, lint, tokens, typography and design checks; no new design findings Assistant-verification: isolation mutation checks passed: builtins on caused 16 failures, skill discovery caused 2, and plain-turn result tool caused 9; all mutations reverted byte-for-byte Assistant-verification: relative documentation link check passed: 38 links and anchors resolved with exact casing Assistant-verification: qlty smells passed: no duplication findings; complexity diagnostics match existing adapter closure patterns and are recorded in implementation notes User-preference: "Atomic's SDK is the runtime and the host supplies human input; Chopin implements HostInput rather than intercepting tools" User-preference: "In local mode the Planner may run as a full Atomic session so workflows run inside Chopin with questions in Decisions" Co-authored-by: Alex Lavaee <lavaman131@github.com>
Wrap the rename, archive and restore result unions in object schemas without changing their branches. Check every exported tool and the fully enabled MCP tools/list response. Assistant-model: Claude Opus 5.5 Assistant-workflow: goal (run 98acf681-3730-4957-b885-0d70e0e6b32a) Assistant-verification: focused MCP tests passed: 81 tests, 450 assertions; the new invariant failed before the fix on rename_document Assistant-verification: bun run types passed: all workspaces and E2E Assistant-verification: bun run fix and bun run ci passed: formatting inspected, no errors and one existing lint warning User-preference: "Atomic's SDK is the runtime and the host supplies human input; Chopin implements HostInput rather than intercepting tools" User-preference: "In local mode the Planner may run as a full Atomic session so workflows run inside Chopin with questions in Decisions" Co-authored-by: Alex Lavaee <lavaman131@github.com>
Expose invoke_planner only for the full local Atomic mode. Resolve the existing document and require a live browser login for the MCP caller's GitHub identity; the bearer never supplies Planner ownership. Verify an explicit checkout before posting, and retain it only for its own turn. Persist the verbatim instruction as a member message before returning the canonical document URL. Keep a server-opened room alive through the turn and queue, without changing ordinary socket-only eviction. Document the local shell and filesystem trust boundary and refusal codes. Assistant-model: Claude Opus 5.5 Assistant-workflow: goal (run 98acf681-3730-4957-b885-0d70e0e6b32a) Assistant-verification: bun test passed: 1718 pass, 2 PostgreSQL skips, 0 fail, 7344 assertions across 196 files Assistant-verification: focused MCP tests passed: 87 tests, including capability gating, input bounds, output schemas, session ownership and checkout verification Assistant-verification: harness tests passed: 141 tests; full Atomic and default isolated behavior remain covered Assistant-verification: bun run types passed: all workspaces and E2E Assistant-verification: bun run fix and bun run ci passed: formatting inspected; no errors, one existing lint warning and no new design findings Assistant-verification: relative documentation links passed: 26 targets and anchors resolved with exact casing Assistant-verification: qlty smells completed: guard-return complexity and existing archive/restore duplication recorded in implementation notes User-preference: "Atomic's SDK is the runtime and the host supplies human input; Chopin implements HostInput rather than intercepting tools" User-preference: "In local mode the Planner may run as a full Atomic session so workflows run inside Chopin with questions in Decisions" Co-authored-by: Alex Lavaee <lavaman131@github.com>
Return a written answer as Atomic's custom kind only where its own dialog accepts typed text, and as typed chat on multi-select or preview questions, so Atomic's validator accepts every answer a member can give. Hold verbatim host input only to aggregate bounds. Normalization and the shared draft skip per-field counts and lengths for verbatim questions, the dialect bounds questionnaire text by the source size, and an ask that would take the document past 256 KiB fails before any card or record exists. The Planner's ask tool keeps its per-field limits. Read the Atomic checkout and timeout settings only in full mode, treating empty values as unset. Assistant-model: Claude Opus 5.5 Assistant-workflow: goal (run 98acf681-3730-4957-b885-0d70e0e6b32a) Assistant-verification: fail-before/pass-after passed: the 9 new tests failed with source changes stashed (InvalidHostInput, per-field QuestionErrors, config throw) and 93 of 93 passed after Assistant-verification: bun test passed: 1727 pass, 2 PostgreSQL skips, 0 fail, 7393 assertions across 196 files Assistant-verification: focused bun test passed: 294 tests in harness, question, dialect and config, including a full Atomic session answered through Decisions Assistant-verification: aggregate-bound mutation check passed: disabling the document fit check made the oversize dialog test time out; source restored byte-for-byte Assistant-verification: bun run types passed: all workspaces and E2E Assistant-verification: bun run fix and bun run ci passed: formatting inspected; no errors, one existing lint warning and no new design findings Assistant-verification: relative documentation links passed: 27 links and anchors resolved with exact casing User-preference: "Atomic's SDK is the runtime and the host supplies human input; Chopin implements HostInput rather than intercepting tools" User-preference: "In local mode the Planner may run as a full Atomic session so workflows run inside Chopin with questions in Decisions" Co-authored-by: Alex Lavaee <lavaman131@github.com>
Replacing a custom answer always deleted the current text first. On an empty answer json-joy 17 binary-encodes that zero-length delete so the server decodes garbage that swallows the following insert, yet still acknowledges the edit. A paste, fill or one-character answer into the empty box was lost, and a verbatim host question then saved "". Delete only existing text, and skip the insert for an empty value, which json-joy refuses: clearing a typed answer threw after its delete. Assistant-model: Claude Opus 5.5 Assistant-workflow: goal (run 98acf681-3730-4957-b885-0d70e0e6b32a) Assistant-verification: fail-before/pass-after passed: with the unfixed change() the 5 new controller tests failed (the server-applied draft kept custom "" after one input for verbatim and ordinary questions and a host-only paste, and clearing threw EMPTY_STRING); 12 of 12 passed after Assistant-verification: bun test passed: 1732 pass, 2 PostgreSQL skips, 0 fail, 7402 assertions across 196 files Assistant-verification: bun test packages/question passed: 35 pass, 0 fail Assistant-verification: bun run types passed: all workspaces and E2E Assistant-verification: bun run fix passed: no change to tracked files; one existing lint warning Assistant-verification: bun run ci failed: dprint flagged only three untracked .atomic/todos files; dprint check excluding .atomic, oxlint, token, type-scale and design checks then passed User-preference: "Atomic's SDK is the runtime and the host supplies human input; Chopin implements HostInput rather than intercepting tools" User-preference: "In local mode the Planner may run as a full Atomic session so workflows run inside Chopin with questions in Decisions" Co-authored-by: Alex Lavaee <lavaman131@github.com>
HARNESS=atomic is now the only switch. Every Planner session on that harness, local or hosted, runs as a full Atomic session: builtins, default coding tools, the operator's Atomic resources, and Chopin bound as HostInput. The summary and research workers keep their isolated sessions, and copilot-sdk and pi are unchanged. This supersedes the local-only opt-in from c84fa4e. Its environment variables and Config.atomicPlanner are gone, and nothing replaces them. A checkout now comes only from invoke_planner. On the atomic harness it is verified against the document's origin before anything is posted, then remembered in memory for that channel. Every later Planner session re-verifies it before use, whether it starts from the browser or MCP. Without a remembered checkout, the session runs with the same tools in an empty 0700 directory created for that channel alone and removed at shutdown. The Planner's instructions say which case applies. Host input expires after a fixed 30 minutes. The questionnaire record and question:resolved now carry an "expired" status. The card stays in the document with status="expired" and is listed among the resolved Decisions, with a note that nobody answered and the Planner will use its best judgement. Atomic receives no answer, and late submissions are refused. An abort or member cancel still withdraws cards as before. invoke_planner is offered for every harness and auth mode. The posted message is attributed to the caller. The turn runs under the channel's existing owner, or the caller's live browser login claims ownership, or the call is refused before anything is posted. Other harnesses ignore the checkout. Assistant-model: Claude Opus 5.5 Assistant-workflow: goal (run 98acf681-3730-4957-b885-0d70e0e6b32a) Assistant-verification: bun test passed: 1746 pass, 2 PostgreSQL skips, 0 fail, 7619 assertions across 196 files Assistant-verification: focused bun test (harness, mcp, chat, config, question, protocol) passed: 390 pass, 0 fail, 1821 assertions across 38 files Assistant-verification: worker isolation mutations passed: BUILTINS_OFF set true failed 17 of 34, isolated skill discovery failed 2, the result tool offered on plain turns failed 11; the adapter was restored byte-for-byte Assistant-verification: behaviour mutations passed: never registering atomic sessions, withdrawing on expiry, rejecting expired records on restore, and refusing an owner other than the caller each failed their new tests; every file was restored byte-for-byte Assistant-verification: bun run types passed: all workspaces and E2E Assistant-verification: bun run fix passed: formatted changed files and one untracked .atomic todo, which was restored byte-for-byte; one existing lint warning Assistant-verification: bun run ci failed: dprint flagged only one untracked .atomic/todos file; dprint check on the tracked and new files, oxlint, token, type-scale and design checks then passed Assistant-verification: relative-link check passed: every relative link and anchor in README.md, AGENTS.md and docs resolves with exact casing User-preference: "Atomic's SDK is the runtime and the host supplies human input; Chopin implements HostInput rather than intercepting tools" User-preference: "In local mode the Planner may run as a full Atomic session so workflows run inside Chopin with questions in Decisions" User-preference: No extra per-harness flags; HARNESS=atomic always runs the Planner as a full Atomic session, hosted included User-preference: No extra per-harness env settings; the checkout comes from invoke_planner and the input timeout is a code constant Co-authored-by: Alex Lavaee <lavaman131@github.com>
The full Planner kept the operator's settings in an in-memory manager with no project scope, so packages a repository installs for itself (`atomic install -l`, recorded in `.atomic/settings.json`) never loaded, and their workflows and tools were missing from Planner turns run in that checkout. Seed the in-memory project scope from the working directory's `.atomic/settings.json` as trusted project settings, keep both files unwritten, and reapply Chopin's compaction, summary, and cache overrides. Assistant-model: Claude Opus 5.5 Assistant-workflow: inline Assistant-verification: bun test passed: 1749 tests, 2 PostgreSQL skips, 0 fail, including a new full-Planner test that a checkout's project package contributes its tool and skill without writing either settings file Assistant-verification: bun run types passed: all workspaces Assistant-verification: bun run ci passed: dprint, oxlint, tokens, type scale, Impeccable baseline Assistant-verification: local E2E failed before this fix: invoke_planner reached a full Planner whose tools lacked a package installed through the checkout's .atomic/settings.json User-preference: HARNESS=atomic runs the Planner as a full Atomic session, so a checkout should behave like a local Atomic session in that repository Co-authored-by: Alex Lavaee <lavaman131@github.com>
Drop the full Atomic session framing and the tool inventory from the Planner's workspace instructions; the system prompt already lists its tools. Keep only what the model cannot infer: questions from ask_user_question and workflows appear as Decisions, and an expired question means proceeding on best judgement. Assistant-model: Claude Opus 5.5 Assistant-workflow: inline Assistant-duration: 12m converged, estimated 10m Assistant-verification: bun test passed: apps/server/src/harness, chat and agent, 302 pass, 0 fail Assistant-verification: bun run types passed: all workspaces and E2E Assistant-verification: bun run ci passed: dprint, oxlint, tokens, type scale and design checks User-preference: Planner prompts stay neutral; no "full Atomic session" meta framing, name tools only where it adds information the system prompt lacks Co-authored-by: Alex Lavaee <lavaman131@github.com>
Apply dprint's formatting to the Planner workspace instructions, which the format check flagged. Assistant-model: Claude Opus 5.5 Assistant-workflow: inline Assistant-verification: bun run ci passed: dprint check clean after formatting Co-authored-by: Alex Lavaee <lavaman131@github.com>
…sions Decisions on main no longer offers a free-text custom answer: a member writes one by adding an option. The host input bridge now returns an added option as a written answer, as custom where Atomic's own dialog accepts typed text and as chat otherwise, so Atomic never receives a label it did not offer. An input or editor dialog, which has no options, is answered by the option a member adds. The test fixture adds options the way the client does, and the view tests check that a no-option host card offers "Add an option" rather than a text box. The rebase added the expired-card view to question-view.tsx and the editor questionnaire widget. Their reviewed dynamic class and pointing expressions are unchanged and take no data from the new code, so both review hashes are renewed. Assistant-model: Claude Opus 5.5 Assistant-workflow: inline Assistant-verification: bun test passed: 1882 pass, 2 PostgreSQL skips, 0 fail, including added options returned as custom, chat, and input/editor answers Assistant-verification: bun run types passed: all workspaces Assistant-verification: bun run ci passed: dprint, oxlint, tokens, design contract, design record, Impeccable (no new findings) User-preference: Rebase PRs onto the latest main and adapt to its code rather than keeping the old design User-preference: Fit agent questions to Decisions' options format rather than adding a free-text field Co-authored-by: Alex Lavaee <lavaman131@github.com>
…views Edits under the per-edit limit could build an answer large enough to push the saved document past its size limit, after which the Planner could no longer edit it. Project the answer onto a copy and validate it first; when it does not fit, the document stays unchanged and the question stays open. Decisions has no preview pane, so an Atomic option's preview (a mockup or code) now travels in its description, and people see it before choosing without the label or the returned answer changing. Both reported by Maggie Appleton in review. Assistant-model: Claude Opus 5.5 Assistant-workflow: inline Assistant-verification: fail-before/pass-after passed: with about 100 KB of prose, four 50 KB edits built an answer that saved a 302 KB document past the 256 KiB limit; with the check the submit is refused, the document is unchanged and the question stays open Assistant-verification: bun test passed: 1883 pass, 2 PostgreSQL skips, 0 fail Assistant-verification: bun run types passed: all workspaces Assistant-verification: bun run ci passed: dprint, oxlint, tokens, design contract, design record, Impeccable (no new findings) Co-authored-by: Alex Lavaee <lavaman131@github.com>
6e7685e to
fb57aa9
Compare
Summary
Closes #213.
Builds on and stacked on #210 (
atomic-harness).Makes
HARNESS=atomicrun the hosted Planner as a full Atomic session in both local and hosted configurations, with Chopin acting as the human-input host (HostInput) so every question routes to Decisions.Full Atomic Planner session:
HARNESS=atomicalways runs Planner sessions as full Atomic sessions with Atomic builtins (workflows, subagents, MCP, web access, intercom), default coding tools, and operator Atomic resources (extensions, skills, prompt templates, context files).copilot-sdkandpiharnesses are unchanged.invoke_planneris verified against the document repository's git origin, then remembered for that channel and reused on later browser- and agent-initiated turns. Without a verified checkout, the session runs in an isolated empty working directory with the same tools.docs/self-hosting.mdanddocs/hosted-agent.md.Chopin as Atomic HostInput backed by Decisions:
HostInputbound viaextensionBindings.humanInput.questionnaireto Chopin'sask(Decisions) one-to-one; single-choice and multi-choice map cleanly;confirmandselectbecome single-question questionnaires;inputandeditorbecome free-text cards.AbortSignal(withdraws the card) and handles timeouts: after a 30-minute timeout, the card resolves as expired with an inline notice in Decisions that nobody answered and the Planner will proceed on best judgement, while the callback returns "no answer".workflowRunIdandworkflowStageId. Unanchored batches append to the document end.invoke_plannerMCP tool:invoke_planner({ id, instruction, checkout? })across all harnesses.checkoutverification applies to the atomic harness.MCP
outputSchemaspecification compliance:"type": "object"output schemas forrename_document,archive_document, andrestore_document(wrapping oneOf unions), unblocking strict MCP clients such as Atomic's zod-validated MCP client."type": "object"output schema.Verification
Assistant-verification: bun test passed: 1746 pass, 2 PostgreSQL skips, 0 fail, 7619 assertions across 196 files
Assistant-verification: bun run types passed: all workspaces and E2E TypeScript checks
Assistant-verification: bun run ci passed: dprint, oxlint (0 errors, 1 existing warning), check-tokens, check-type-scale, and Impeccable design checks
Assistant-verification: bun run e2e passed: 236 passed, 0 failed in Chromium integration suite
Assistant-verification: worker isolation mutations passed: BUILTINS_OFF set true failed 17 of 34, isolated skill discovery failed 2, result tool on plain turns failed 11; all restored byte-for-byte
Assistant-verification: behaviour mutations passed: session registration, expiry withdrawal, expired record rejection on restore, and owner verification each failed their new tests; all restored byte-for-byte
Assistant-verification: documentation links passed: relative links and anchors in README.md, AGENTS.md, and docs resolve with exact casing
Assistant-model: Claude Opus 5.5
Assistant-workflow: goal (run 98acf681-3730-4957-b885-0d70e0e6b32a)
User-preference: "Atomic's SDK is the runtime and the host supplies human input; Chopin implements HostInput rather than intercepting tools"
User-preference: "In local mode the Planner may run as a full Atomic session so workflows run inside Chopin with questions in Decisions"
User-preference: No extra per-harness flags; HARNESS=atomic always runs the Planner as a full Atomic session, hosted included
User-preference: No extra per-harness env settings; the checkout comes from invoke_planner and the input timeout is a code constant
Co-authored-by: Alex Lavaee lavaman131@github.com