feat(coder): start a coding agent on a developer's task instead of the plan
Merged
DA
8d ago+369+369+012345678901234567890123456789-63-63-01234567890123456789
Summary
Dean, on the "+" menu's New coding agent: it "must NOT send the plan". A new agent from the "+" starts on the developer's first message, used as its task. Until now, every Start handed the agent the plan document as its first message, and nothing could carry anything else. This is the service half of that split, agreed with the orchestrator. The desktop's "+" row and draft tab come in a PR stacked on this one.
- The start request gains an optional
task(codingAgentStartRequestSchema, so also the view params, the gateway, and the act payload). It is trimmed and bounded like a message (MAX_MESSAGE_CHARS, 16,000).host-operator.tsforwards it explicitly, as it does model and effort. startEndpoint: with a task, the eve session opens with the task as its first message, and the plan is never sent. The agent still works in the plan's repository, under the same checks as before (owned plan, repository set, GitHub reaches it, model choice, idempotency key). A Start without a task is byte-for-byte what it was.- Body cap kept, sized for the task:
MAXIMUM_START_BODY_BYTESgrows from 4,096 to6 Ć MAX_MESSAGE_CHARS + 4,096, so a task at its bound still fits at JSON's widest escape. This is the same rule the message route's cap uses. - Store (migration
0067_coding_agent_task):coding_agent.task text NULLis added, andplan_snapshotbecomes nullable. Exactly one of the two holds what the agent was handed, so a task agent keeps no copy of the plan.NewCodingAgenttakes the pair as a union type (CodingAgentBriefText), so the compiler won't build a row with both or neither.drizzle-schema.test.tschecks the module against the migrated database. - Coder instructions:
coderInstructions(repository, brief). The plan wording is unchanged character for character. The task wording says the job is "the task the developer gave as the first message", reads the code the task touches, and says nothing of a plan. Everything else (checkout, branch rule, commit identity, checks, delegation, never printing secrets) is shared. CodingAgentSummary.brief(plan|task, optional): every list, start, and change answer says what the agent was handed. The desktop uses it to draw a task as the developer's own message, not the "Plan" card. It is optional so a desktop reading an older service treats a missing value as the plan. An older desktop ignores the new key, since answers ignore unknown keys.- Docs:
apps/web/server/README.md(coding-agent service and routes),docs/PLANNING.md, andPRIVACY.md. Deleting a plan now removes "the copy of the plan, or the task you wrote in its place" an agent was handed. This is a product-facing wording change, called out here.
The never-secrets rules are unchanged: a task is the developer's own words, stored and shown exactly like a message to an agent.
Evidence
- Platform-independent checks:
./scripts/check.shexits 0. - macOS Electron verification (
./scripts/verify.sh):not run. CI could not verify the Mac. This PR changes no UI. Its one desktop change is the main process forwardingtaskinhost-operator.ts. Done on a Linux VM; LUKE-159 is the manual Mac pass.
Visual evidence
- None: no UI changes in this PR.
Physical-device evidence
- Screenshot or screen recording:
not attached
Tests
Each fails without this change:
coding-agents-app.test.ts:- A Start naming a task (padded with whitespace) opens eve with the trimmed task as the only first message, never the plan. The stored row has the task and a null
plan_snapshot, and is in the plan's repository. The answer and the list saybrief: task. - A task one past the bound, or whitespace only, is refused as
invalid-requestand opens nothing. A task at the bound made entirely of a character JSON escapes to six bytes is accepted (the old 4,096-byte cap refused it). - The existing Start test now also asserts
brief: planandtask: null.
- A Start naming a task (padded with whitespace) opens eve with the trimmed task as the only first message, never the plan. The stored row has the task and a null
coding-agent-store.test.ts: a task Start stores the task and no plan copy, and reads back the same.coder-agent.test.ts:- The task wording names the task as the job, keeps the repository, and contains no "plan".
- The commit-identity, checkout, and delegation rules hold for both wordings.
coding-agent-client.test.ts: a task travels to the service as sent. Before, the client's own request schema refused it and sent nothing.host-operator.test.ts: a Start's task reaches the gateway, and a Start without one carries notaskfield.
Goldens (LUKE_UPDATE_FIXTURES=1, packages/hosted/fixtures/json-schema/). Seven files, each adding one optional property:
coding-agent-wire-codingAgentStartRequestSchema.jsonandcoding-agent-view-codingAgentStartParamsSchema.json:task(string, 1ā16,000), not required.coding-agent-wire-codingAgentSummarySchema.json, plus the four answers that embed the summary (coding-agent-wire-codingAgentAnswerSchema,-ListAnswerSchema,coding-agent-view-codingAgentAgentAnswerSchema,-ListAnswerViewSchema):brief(enumplan|task), not required.
Test count: +6.
Invariants
-
./scripts/check.shgreen;verify.shnot run (no UI; Linux VM). - JSON Schema goldens changed only as listed above, each an added optional property.
- Every behavior change has, in this PR, the test that fails without it; no change-detector test added.
- Gateway envelope goldens unchanged (none exist for coding agents).
- No new
astype assertion outside the allowlisted files. - No
Effect.runPromise/runSync/runForkoutside the runtime edges. - No new
setTimeout/setInterval/new Promise/AbortController/fs.watch. - No Effect, Stream, or Layer written as a statement and dropped.
- Test count delta listed above.
- No hand-rolled file replaced.
- Docs naming the changed parts edited (
apps/web/server/README.md,docs/PLANNING.md);AGENTS.md/CLAUDE.mdname none of them. -
PRIVACY.mdchanged: what deleting a plan removes now names the task an agent may have been handed in the plan's place. - No dependency changes.
- No barrel/door change.
Notes
- The desktop half (the "+" New coding agent row, which opens a draft agent tab whose first message starts the agent on that task) is stacked on this PR.
š¤ Generated with Claude Code