You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
_fix_seats_of (scripts/lib/self-fix.sh) recovers a lock's team/agent by
splitting its filename on __. That only holds for a legacy-keyed lock
(actas.<team>__<agent>.session). An id-keyed lock (#1023: actas.<team_id>__<member_id>.session, minted once a team has a team_id
and the roster journal has minted a member_id for that agent — which join.sh does by default for any team that already has a team_id) splits
into two opaque ids that are not a team and an agent at all.
Concrete repro
join.sh testteam bob claude-code <project> against a team whose config.json already carries a team_id (the common case once a team
has gone through remote.sh connect, or was created after id-keying
landed).
Claim the actas lock for (testteam, bob) — e.g. via actas-claim.sh.
The lock lands at an ID-KEYED path, e.g.:
Returned:team=01a0a22a-72b0-7585-81fa-4768f17a6720 agent=01a0a22a-7a80-7a83-8a00-739985dc594b owner=bob-sid.12345 — the two
UUID halves of the id-key, not a real team/agent.
self-fix.sh's fix (no-argument self-repair) calls _fix_seats_of to
find which seats the calling session owns, then tries to prove and rewrite
each returned (team, agent) pair. For an id-keyed lock, it would attempt to
prove/write a placement for a UUID-named "team" and "agent" that do not
exist — at minimum silently doing nothing useful for that seat, possibly
worse depending on what the proof/write path does with a nonexistent
team/agent. Not confirmed against a live fix run; only the direct _fix_seats_of return value was reproduced.
Suggested fix direction
Do not recover team/agent by reverse-parsing the lock filename. A
(team, agent) pair is only ever discoverable in a BOUNDED way (this
project's own team rosters), so scanning a project's registered
(team, agent) candidates and resolving each FORWARD through actas_lock_read (already correct for both id-keyed and legacy locks)
avoids the reverse-parse entirely. #1229's PR explored exactly this shape
(as agmsg_actas_owner_in_team) before reverting it in favor of reusing identities.sh's existing (project, type) → (team, agent) resolution for
that PR's own narrower need; a general fix for _fix_seats_of itself would
need a "scan every locally known team's roster" version of the same idea.
_fix_seats_of(scripts/lib/self-fix.sh) recovers a lock'steam/agentbysplitting its filename on
__. That only holds for a legacy-keyed lock(
actas.<team>__<agent>.session). An id-keyed lock (#1023:actas.<team_id>__<member_id>.session, minted once a team has ateam_idand the roster journal has minted a
member_idfor that agent — whichjoin.shdoes by default for any team that already has ateam_id) splitsinto two opaque ids that are not a team and an agent at all.
Concrete repro
join.sh testteam bob claude-code <project>against a team whoseconfig.jsonalready carries ateam_id(the common case once a teamhas gone through
remote.sh connect, or was created after id-keyinglanded).
(testteam, bob)— e.g. viaactas-claim.sh.The lock lands at an ID-KEYED path, e.g.:
bob-sid.12345)._fix_seats_of "bob-sid"(or the promotedagmsg_actas_owned_seats,same logic, proposed then reverted in plain driver: let an agent-native channel stand in for peek/poke when there is no pane #1229's PR — see that PR's commits
for the exact reproduction script used to find this).
Returned:
team=01a0a22a-72b0-7585-81fa-4768f17a6720 agent=01a0a22a-7a80-7a83-8a00-739985dc594b owner=bob-sid.12345— the twoUUID halves of the id-key, not a real team/agent.
Expected:
team=testteam agent=bob owner=bob-sid.12345.Impact
self-fix.sh'sfix(no-argument self-repair) calls_fix_seats_oftofind which seats the calling session owns, then tries to prove and rewrite
each returned (team, agent) pair. For an id-keyed lock, it would attempt to
prove/write a placement for a UUID-named "team" and "agent" that do not
exist — at minimum silently doing nothing useful for that seat, possibly
worse depending on what the proof/write path does with a nonexistent
team/agent. Not confirmed against a live
fixrun; only the direct_fix_seats_ofreturn value was reproduced.Suggested fix direction
Do not recover team/agent by reverse-parsing the lock filename. A
(team, agent) pair is only ever discoverable in a BOUNDED way (this
project's own team rosters), so scanning a project's registered
(team, agent) candidates and resolving each FORWARD through
actas_lock_read(already correct for both id-keyed and legacy locks)avoids the reverse-parse entirely. #1229's PR explored exactly this shape
(as
agmsg_actas_owner_in_team) before reverting it in favor of reusingidentities.sh's existing (project, type) → (team, agent) resolution forthat PR's own narrower need; a general fix for
_fix_seats_ofitself wouldneed a "scan every locally known team's roster" version of the same idea.