fix(session_start): report which pin a re-pin moved (#517) - #533
Merged
Merged
Conversation
golimpio
pushed a commit
that referenced
this pull request
Sep 30, 2026
- attachOrRepinTo returns the connection's previous root read inside its mutation lane. It was read before the lane, so two callers racing to one target both reported moving the pin, and followConnectionShards could be handed a stale root, missing shards seeded at an intermediate one. - The caller's next-call root is derived from the move rather than re-read through workspaceFor afterwards, where a peer's concurrent move could mislabel it. An empty one is rendered as "nothing" instead of the connection's root. - The unattached path (a caller whose declaration is refused resolves to nothing while the connection is pinned) renders the report too. - repinConnection clears the caller's own refused-declaration marker; the identity-stripped move used to clear only the anonymous one. - The #516 CHANGELOG bullet is folded into this change's entry, since its interim wording never shipped. Tests: a concurrent same-target regression, an agent re-pinning its own pin (pins "from" on the agent path), and a connection-scoped move from a refused declaration. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
golimpio
pushed a commit
that referenced
this pull request
Sep 30, 2026
…#533 review 2) connScopeCallerRoot read the caller's shard root after a connection-scoped move and the report labelled any difference "(your own pin, not the connection's)". A shard that never chose a root follows the connection, so a peer's concurrent connection move dragged it on and the caller was told it was on its own pin (107 of 320 reports in the reviewer's run). Decide by whether the shard follows instead: a shard that is neither self-pinned nor restored resolves against the root this move left the connection at; only a self-pinned or restored shard reports its own root. selfPinned never goes back to false, and a self-pinned shard's root moves only through its own agent, so the one window left is that agent's own concurrent session_start. Tests: a bounded stress test of concurrent connection-scoped moves by two following agents asserting zero mislabels, a restored-pin case, and a guard that a refused connection-scoped move keeps the caller's refused-declaration marker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
golimpio
pushed a commit
that referenced
this pull request
Sep 30, 2026
- attachOrRepinTo returns the connection's previous root read inside its mutation lane. It was read before the lane, so two callers racing to one target both reported moving the pin, and followConnectionShards could be handed a stale root, missing shards seeded at an intermediate one. - The caller's next-call root is derived from the move rather than re-read through workspaceFor afterwards, where a peer's concurrent move could mislabel it. An empty one is rendered as "nothing" instead of the connection's root. - The unattached path (a caller whose declaration is refused resolves to nothing while the connection is pinned) renders the report too. - repinConnection clears the caller's own refused-declaration marker; the identity-stripped move used to clear only the anonymous one. - The #516 CHANGELOG bullet is folded into this change's entry, since its interim wording never shipped. Tests: a concurrent same-target regression, an agent re-pinning its own pin (pins "from" on the agent path), and a connection-scoped move from a refused declaration. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
golimpio
pushed a commit
that referenced
this pull request
Sep 30, 2026
…#533 review 2) connScopeCallerRoot read the caller's shard root after a connection-scoped move and the report labelled any difference "(your own pin, not the connection's)". A shard that never chose a root follows the connection, so a peer's concurrent connection move dragged it on and the caller was told it was on its own pin (107 of 320 reports in the reviewer's run). Decide by whether the shard follows instead: a shard that is neither self-pinned nor restored resolves against the root this move left the connection at; only a self-pinned or restored shard reports its own root. selfPinned never goes back to false, and a self-pinned shard's root moves only through its own agent, so the one window left is that agent's own concurrent session_start. Tests: a bounded stress test of concurrent connection-scoped moves by two following agents asserting zero mislabels, a restored-pin case, and a guard that a refused connection-scoped move keeps the caller's refused-declaration marker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
golimpio
force-pushed
the
atlas/fix-517-repin-report
branch
from
September 30, 2026 21:25
604745a to
7a86ec8
Compare
The re-pin callback (repinWorkspace, wired through WithRepin) now returns a tools.RepinReport: the pin the daemon moved (the caller's own shard or the connection's), that pin's previous root, how many OTHER agents' shards followed a connection move, and the root the caller's next relative path resolves against. repinWorkspaceFrom, repinConnection and repinAgent carry the outcome up; followConnectionShards returns the ids it moved. session_start renders "Re-pinned your pin: A → B" or "Re-pinned this connection's pin: A → B (N other agents follow it)" plus a "Next relative-path call resolves against:" line in both the full and brief packets, and the "# Workspace:" header now names the caller's own effective root. Previously an anonymous default-scope re-pin on a shared connection dragged its peers silently, and scope "connection" from an agent holding its own pin showed its own root as "from" and the connection's new root as its workspace. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- attachOrRepinTo returns the connection's previous root read inside its mutation lane. It was read before the lane, so two callers racing to one target both reported moving the pin, and followConnectionShards could be handed a stale root, missing shards seeded at an intermediate one. - The caller's next-call root is derived from the move rather than re-read through workspaceFor afterwards, where a peer's concurrent move could mislabel it. An empty one is rendered as "nothing" instead of the connection's root. - The unattached path (a caller whose declaration is refused resolves to nothing while the connection is pinned) renders the report too. - repinConnection clears the caller's own refused-declaration marker; the identity-stripped move used to clear only the anonymous one. - The #516 CHANGELOG bullet is folded into this change's entry, since its interim wording never shipped. Tests: a concurrent same-target regression, an agent re-pinning its own pin (pins "from" on the agent path), and a connection-scoped move from a refused declaration. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#533 review 2) connScopeCallerRoot read the caller's shard root after a connection-scoped move and the report labelled any difference "(your own pin, not the connection's)". A shard that never chose a root follows the connection, so a peer's concurrent connection move dragged it on and the caller was told it was on its own pin (107 of 320 reports in the reviewer's run). Decide by whether the shard follows instead: a shard that is neither self-pinned nor restored resolves against the root this move left the connection at; only a self-pinned or restored shard reports its own root. selfPinned never goes back to false, and a self-pinned shard's root moves only through its own agent, so the one window left is that agent's own concurrent session_start. Tests: a bounded stress test of concurrent connection-scoped moves by two following agents asserting zero mislabels, a restored-pin case, and a guard that a refused connection-scoped move keeps the caller's refused-declaration marker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
golimpio
force-pushed
the
atlas/fix-517-repin-report
branch
from
September 30, 2026 21:45
7a86ec8 to
4159b4f
Compare
golimpio
approved these changes
Oct 1, 2026
golimpio
left a comment
Contributor
There was a problem hiding this comment.
Taken over to merge at the owner's request. Its own two review rounds are recorded on the PR, with both blockers fixed and confirmed; updated with main by a clean merge.
atlas-from-plumb
enabled auto-merge
October 1, 2026 00:12
golimpio
pushed a commit
that referenced
this pull request
Oct 1, 2026
…ask-config #533 changed session_start's struct (repin now returns a RepinReport) and repinAgent's return values. Conflict resolved by keeping main's struct with this branch's ctx-taking tasksFn, and updating the new #522 test helper to repinAgent's three return values. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Plumb-Session: vivid-mink
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.
Why
After a re-pin,
session_startprinted a neutralRe-pinned: <from> → <to>. It could not say which pin had moved: the caller's own per-agent pin, or the connection's pin, which every agent without a pin of its own follows. The daemon makes that choice, but the tool only got the previous root back, and it computed "from" from the caller's own root. That gave two wrong outputs:scope: "connection"from an agent that has its own pin. The agent's own root was shown as "from", and the# Workspace:header showed the connection's new root. The agent itself still resolves against its own pin, so the header named a root its relative paths do not use.Change
WithRepincallback now returns atools.RepinReportinstead of a bare root. The report holds:Root: the resolved root;Scope:agentorconnection;From: that pin's previous root;Followers: how many other agents' shards followed a connection move;Effective: the root the caller's next relative-path call resolves against, read throughworkspaceForunder the caller's own ctx after the move.internal/cli):repinWorkspaceis the callback and returns the report.repinWorkspaceFromandrepinConnectionreturn arepinOutcome.repinAgentalso returns the shard's previous root, read under the samesh.mulock that moves it.followConnectionShardsreturns the ids it moved.repinReport(newconn_repin_report.go) leaves the caller out of the follower count.Re-pinned your pin: A → BRe-pinned this connection's pin: A → B (N other agents follow it)Next relative-path call resolves against: <root>. When that root is the agent's own pin rather than the connection's new root, the line adds(your own pin, not the connection's).# Workspace:(and the rest of the packet) now uses the caller's own root.Re-pinned, so the existing absence checks on that bare prefix still apply.TestSessionStartBrief_ByteBudget) and the brief re-pin case (1536 bytes) still pass.Tests
New tests in
internal/cli/session_start_repin_report_test.go. They run through the realtools.SessionStartwiring (newSessionStartTool), and each one runs with bothdetail: fullanddetail: brief:2 other agents follow it, and both peers really moved;scope: "connection"from an agent with its own pin: reports the connection's previous root, the header and next-call line name the agent's own root, and the peer followed;scope: "connection"from a seeded agent: the caller follows too but is not counted;no other agent follows it, with a same-root control that prints noRe-pinnedat all.TestRepinAnnouncementis now table-driven and covers every variant. The existing stubs and assertions are updated to the new signature and wording.Evidence:
origin/main(b5a4392) with the new test file copied in. They fail on the wording, on the wrong "from" and on the wrong header. They pass here.Effectivefalling back toRoot;followConnectionShardsreporting nothing;go test ./... -count=1exits 0.go test -tags=integration ./internal/cli/ -count=1exits 0.golangci-lintis clean.check-changelog-placement --require-baseis OK.Closes #517.
🤖 Generated with Claude Code