Repository navigation
Make an attached remote Planner own its document - #469
Merged
Merged
Conversation
…hed requests Under HARNESS=remote, attaching a client now makes its account the document's Planner owner through the same generation-guarded claim every owner takes. The owner record names the account's live browser login, since Chopin's repository tools run with that login's GitHub App token and never with the link's bearer; an account without one is refused with sign-in-required (4401). Attaching needs the eligibility every Planner owner already needs, instance admission plus push or administration access, rather than the design's pull access, and the periodic recheck now holds a link to that too. A document has one Planner. Another attach while one is attached is refused with planner-attached (4409), naming the holder's login. A detach or dropped socket keeps the ownership for PLANNER_ATTACH_GRACE_MS (two minutes by default) so the same account can reattach under the same generation; then it is cleared under that generation. Attachments live in the process, and startup already clears every owner reference. Members, MCP callers and research requests no longer claim ownership under this harness. An @chopin message or invoke_planner call for a document with no attached client is refused with planner-not-attached before anything is posted or queued; the message names the document URL and says to run pdd-plan with it as plan_document from a checkout of the repository. The browser shows that text in full on the request, and MCP returns it beside the code. With a client attached, both arrive as turns on its link, and Stop and Resume Planner reach it. Other harnesses are unchanged. Assistant-model: Claude Opus 5.5 (fast) Assistant-workflow: hosted-planner-slices Assistant-duration: 13m converged, estimated unmeasured Assistant-verification: bun run types passed: every workspace package and e2e Assistant-verification: GIT_CONFIG_GLOBAL=/dev/null bun test passed: 4657 pass, 0 fail Assistant-verification: bun run ci passed: dprint, oxlint (0 errors), tokens, design contract, Impeccable Assistant-verification: PostgreSQL contract passed: bun test apps/server/src/storage/postgres against a disposable postgres:17-alpine on port 55432, 83 pass, 0 fail Assistant-verification: mutation check passed: disabling the planner-not-attached refusal in processSend fails the new chat service test Co-authored-by: Alex Lavaee <alexlavaee@microsoft.com>
An attachment trusted its in-memory link after the stored ownership under it was gone. Signing the owner's browser login out, its expiry, or a repository writer's Planner reset left the link attached, so @chopin and invoke_planner failed later with planner-owner-unavailable instead of planner-not-attached, and no one could attach until the old socket closed. Ending a login now closes every link it owns with sign-in-required (4401) and clears that ownership under its generation; a reset closes the link with access-revoked (4403). Neither starts a grace period, so any eligible account can attach at once. The checks before every start and turn, and the periodic one, also close a link whose stored owner no longer names its login and generation, or whose login expired without being revoked. The documentation now limits planner-not-attached to @chopin and invoke_planner, says how other Planner requests behave unattached, and says model-backed research is unavailable under the remote Planner. Assistant-model: Claude Opus 5.5 (fast) Assistant-workflow: hosted-planner-slices Assistant-duration: 6m converged, estimated 10m Assistant-verification: bun run types passed: every workspace package and e2e Assistant-verification: GIT_CONFIG_GLOBAL=/dev/null bun test passed: 4663 pass, 0 fail Assistant-verification: bun run ci passed: dprint, oxlint, tokens, design contract, Impeccable Assistant-verification: mutation check passed: disabling sessionRevoked, ownerReset and verify fails all six new link and chat service tests Co-authored-by: Alex Lavaee <alexlavaee@microsoft.com>
A grace reattach read the stored owner and then bound the hold it had captured, without checking whether a Planner reset or the owner's sign-out had released that hold during the read. A snapshot taken before the reset could still match, so the client reported attached while the server had no owner, refused attached turns, and kept an orphaned registry link. Each attach now records the sign-ins it rests on while it runs. A reset of its document or the end of one of those sign-ins marks it, and it binds only if nothing marked it and its owner sign-in is still live after its last await; otherwise it releases any ownership it claimed, under its generation, and is refused with the code an attached link would be closed with. The recheck of an attached link now asks whether the owner's sign-in is live before comparing the stored owner. PostgreSQL and memory storage report an expired sign-in's ownership as released, so an expiry that cleanup had not yet seen closed the link with access-revoked (4403) instead of sign-in-required (4401). Assistant-model: Claude Opus 5.5 (fast) Assistant-workflow: hosted-planner-slices Assistant-duration: 9m converged, estimated 15m Assistant-verification: bun run types passed: every workspace package and e2e Assistant-verification: GIT_CONFIG_GLOBAL=/dev/null bun test passed: 4668 pass, 4 skip, 0 fail Assistant-verification: bun run ci passed: dprint, oxlint, tokens, design contract, Impeccable Assistant-verification: PostgreSQL contract passed: bun test apps/server/src/storage/postgres against disposable postgres:17-alpine on 55432, 85 pass, container stopped Assistant-verification: mutation check passed: the previous attachments.ts fails all five new link and storage contract tests Co-authored-by: Alex Lavaee <alexlavaee@microsoft.com>
The Chat and invoke_planner preflight under HARNESS=remote accepted any in-memory attachment with a link, without asking whether its owner's browser sign-in was still live or storage still assigned that owner. If the sign-in expired before the link's periodic recheck, Chat saved and announced the member's message before owner resolution failed, and invoke_planner returned planner-owner-unavailable instead of planner-not-attached. Both now confirm the attachment as the periodic recheck does. A stale one is closed with the code an attached link would get (sign-in-required or access-revoked), its ownership is released, and the request is refused with planner-not-attached and the attach guidance, with nothing saved or queued. A fresh attach registered its sign-in with the attempt only after the repository and admission checks, so a sign-out during them went unnoticed and the ownership claim then threw once storage had deleted the session, refusing the client with unavailable (1011). The sign-in is now registered before those checks, and a claim that storage refuses because the sign-in ended is refused with sign-in-required (4401). Assistant-model: Claude Opus 5.5 (fast) Assistant-workflow: hosted-planner-slices (run b51d4e3c) repair (worker subagent) Assistant-verification: bun run types passed: every workspace package and e2e, 14 exited with code 0 Assistant-verification: GIT_CONFIG_GLOBAL=/dev/null bun test passed: 4672 pass, 4 skip, 0 fail Assistant-verification: bun run ci passed: dprint, oxlint 0 errors, tokens, design contract, Impeccable Assistant-verification: PostgreSQL contract passed: bun test apps/server/src/storage/postgres against disposable postgres:17-alpine on 55432, 85 pass, container stopped Assistant-verification: mutation check passed: the previous attachments.ts and main.ts preflight fail all four new tests; removing only the claim fallback fails the storage-expiry attach test Co-authored-by: Alex Lavaee <alexlavaee@microsoft.com>
lavaman131
force-pushed
the
planner-attach-ownership
branch
from
October 11, 2026 03:48
9d01994 to
114ba56
Compare
lavaman131
marked this pull request as ready for review
October 11, 2026 04:39
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on the remote Planner link PR. Under
HARNESS=remote, attaching makes the client the document's Planner owner, and a document with no attached Planner refuses Planner requests clearly.docs/hosted-agent.md).planner-attached, naming the holder.planner-not-attached:@chopinand MCPinvoke_planneron an unattached document fail with that code, nothing posted or queued; the message names the document URL and says to connect a Planner client to it from a checkout of the repository. A stale attachment (owner sign-in expired) counts as unattached. Other harnesses are unchanged.invoke_plannerand@chopinbecome turns, and Stop/Resume Planner reach the client.Verification
bun run types: passed.GIT_CONFIG_GLOBAL=/dev/null bun test: 4672 pass, 4 skip, 0 fail (on main with Atomic 0.9.33).bun run ci: passed (0 errors).postgres:17-alpine: 85 pass, 0 fail.planner-attached, grace reattach/release, sign-out during attach (sign-in-required/4401), and Chat/MCP refusals with nothing saved.docs/planner-link.md: passed (summary in a comment on this PR).Assistant-model: Claude Opus 5.5 (fast)
Assistant-workflow: hosted-planner-slices (run b51d4e3c, repairs by worker subagents)
Assistant-verification: bun test passed: 4672 pass, 0 fail
Assistant-verification: postgres contract passed: 85 pass on a disposable database
Co-authored-by: Alex Lavaee alexlavaee@microsoft.com