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
Umbrella / discussion issue. Frames a collaborative-builder workflow where a team member can hand an in-flight builder to a teammate (for review, partial work, or shift change) and the teammate picks it up on their own machine. Same primitives serve both synchronous ("Alice pings Bob, Bob looks at it in 20 min, bounces back") and asynchronous ("end of day, Bob picks up tomorrow") modes. Several design calls are deliberately left open for team input rather than pre-decided.
Why this is tractable
Codev's builder model makes this less invasive than it would be in most multi-machine handoff designs:
The builder branch is the source of truth for builder state. Porch commits codev/projects/<id>-<name>/status.yaml to the branch on every phase transition. The thread file, plan, spec, and review artifacts all live on the branch. Once the branch is pushed to origin, a second machine has everything it needs to resume the work.
afx spawn --resume already exists. The missing piece is letting --resume (or a new sibling command) pull state from origin when the worktree doesn't exist locally yet, rather than demanding the worktree already exists.
GitHub Issues already encode ownership via the assignee field. That's the natural anchor for "who owns this builder right now", with no parallel registry to invent.
Inter-architect messaging exists (afx send <workspace>:architect:<name>) for the sync notification case, and gh issue comment works for the async case.
The work is mostly generalizing primitives we have, not building new infrastructure.
Proposed shape
Two coordinated commands:
Donor side (Alice has the builder):
afx handoff spir-42 --to @bob "review the spec; my concern is X"
Verifies the branch is at a stable boundary (between porch phases, working tree clean).
Pushes the branch to origin with all uncommitted porch chore commits.
Posts a GitHub issue comment: @bob taking over from @alice. State: at spec-approval gate. Note: ... (always — durable, async-native).
Fires a Tower-side message via afx send <workspace>:architect:<name> if reachable (sync ping when both are online; silent fall-through otherwise).
Sets currentArchitect: bob in status.yaml and commits/pushes it.
Marks Alice's local worktree as read-only (see decision point Scaling Crisis - AI Autonomy Decreases as Projects Grow #3 below): worktree preserved, but afx send / spawn --resume against it errors with "currently owned by @bob; use afx pickup to take back."
Verifies Bob is the current GitHub assignee and status.yaml.currentArchitect == bob (the handoff actually happened).
git fetch && git worktree add .builders/spir-42 builder/spir-42 (or equivalent if a local worktree already exists).
Spawns a fresh local builder via the standard afx spawn --resume path, pointing at the existing state.
The new builder reads status.yaml, thread.md, and the artifacts to come up to speed (the LLM session is fresh, the project state is continuous).
Returning to the original donor uses the same commands in reverse: Bob runs afx handoff spir-42 --to @alice "feedback done; ready for spec-approval gate."
Exclusivity guard
Two architects can't both write to the same builder branch concurrently without racing on porch state and thread. The guard:
GitHub assignee is the public-facing source of truth.
status.yaml.currentArchitect: <name> is the per-branch source of truth (travels with the branch, survives clone).
Both are checked on every afx write against that builder (spawn --resume, send, eventually cleanup).
Mismatch produces a loud error pointing at the recovery command: builder spir-42 is currently owned by @bob; use 'afx pickup' to take ownership before continuing.
Open decisions for team discussion
These are the calls where preferences will affect the UX. Initial leans below; not yet committed.
1. Stable-boundary requirement on handoff
Option A (lean): Require the builder to be at a porch gate (between phases) and the worktree clean. State is coherent by construction, recipient lands somewhere semantically meaningful.
Option B: Allow handoff any time, with git status clean. More flexible, but recipient might land mid-phase with partial work the donor hasn't framed.
An --override flag on the strict default covers the occasional "I really need to hand off this mid-phase work" case.
2. Sync notification: try Tower message in addition to GH comment?
Option A (lean): Always post GH comment (durable). Additionally fire Tower-side ping if reachable (instant when both online, silent fall-through otherwise). --no-ping flag for users who find the dual-notification noisy.
Option B: GH comment only. Recipient sees it on next GitHub poll / notification check. Simpler, fewer moving parts.
Option C: Tower-only, fail the handoff if recipient is offline. Forces sync mode. Almost certainly wrong for a multi-mode design.
3. Donor's local worktree after handoff
Option A: Tear down completely (clean slate, fresh afx pickup later if needed). Cleanest, matches the existing afx cleanup model.
Option B (lean): Preserve as read-only with a currentArchitect != self marker. Re-pickup is instant (no fetch, no new worktree). Better for sync ping-pong. Risk: stale local worktree if Bob makes lots of changes before handing back. Mitigated by afx pickup doing a fast-forward fetch and refusing if there are local commits ahead of origin.
Option C: Just warn and keep, no read-only mark. Simplest, but lets a confused user write to a builder they no longer own and silently lose work when the recipient pushes.
4. Naming for "look without taking ownership"
A secondary primitive worth thinking about: sometimes Alice wants Bob to eyeball the spec without a full ownership transfer (Bob comments, Alice keeps going). Could be:
Option A (defer): Skip this for v1. Bob can just git fetch && git worktree add manually and look. Handoff is the only first-class operation.
Option B: afx peek <id> — fetches the branch into a read-only local checkout, no ownership transfer. Bob comments via PR review or GH issue comment.
Option C: Lean on existing GitHub PR review for this case entirely (the spec phase doesn't produce a PR yet, but maybe it should for review purposes).
What this isn't (for v1)
Not a real-time collaboration model. One owner at a time. Two architects can't both edit the worktree concurrently. The handoff dance is coordination, not concurrent editing.
Not multi-machine builder mirroring. The branch state is what travels; the live AI session does not. Recipient's LLM starts fresh, reading the existing artifacts to catch up.
Not a replacement for sibling architects within one workspace.afx workspace add-architect (existing) is for multiple architects sharing one machine / Tower. This issue is for handoffs across machines and people.
Suggested protocol when ready to build
PIR. The plumbing is small (two afx commands, a currentArchitect field, the exclusivity-check helper, the GH/Tower notification dispatch), but the decision surface is wide and benefits from a plan-gate that locks the four open decisions above before code is written. CMAP at PR catches concurrency edge cases that a single reviewer is likely to miss.
Related
afx send <workspace>:architect:<name> for the sync notification channel (existing).
afx spawn --resume for the local-resume primitive that the recipient command generalizes (existing).
Porch chore commits on the builder branch as the carrier for state-machine snapshots (existing).
Why this is tractable
Codev's builder model makes this less invasive than it would be in most multi-machine handoff designs:
codev/projects/<id>-<name>/status.yamlto the branch on every phase transition. The thread file, plan, spec, and review artifacts all live on the branch. Once the branch is pushed to origin, a second machine has everything it needs to resume the work.afx spawn --resumealready exists. The missing piece is letting--resume(or a new sibling command) pull state from origin when the worktree doesn't exist locally yet, rather than demanding the worktree already exists.afx send <workspace>:architect:<name>) for the sync notification case, andgh issue commentworks for the async case.The work is mostly generalizing primitives we have, not building new infrastructure.
Proposed shape
Two coordinated commands:
Donor side (Alice has the builder):
afx handoff spir-42 --to @bob "review the spec; my concern is X"@bob taking over from @alice. State: at spec-approval gate. Note: ...(always — durable, async-native).afx send <workspace>:architect:<name>if reachable (sync ping when both are online; silent fall-through otherwise).currentArchitect: bobinstatus.yamland commits/pushes it.afx send / spawn --resumeagainst it errors with "currently owned by @bob; useafx pickupto take back."Recipient side (Bob takes over):
builder/spir-42.status.yaml.currentArchitect == bob(the handoff actually happened).git fetch && git worktree add .builders/spir-42 builder/spir-42(or equivalent if a local worktree already exists).afx spawn --resumepath, pointing at the existing state.status.yaml,thread.md, and the artifacts to come up to speed (the LLM session is fresh, the project state is continuous).Returning to the original donor uses the same commands in reverse: Bob runs
afx handoff spir-42 --to @alice "feedback done; ready for spec-approval gate."Exclusivity guard
Two architects can't both write to the same builder branch concurrently without racing on porch state and thread. The guard:
status.yaml.currentArchitect: <name>is the per-branch source of truth (travels with the branch, survives clone).afxwrite against that builder (spawn --resume,send, eventuallycleanup).builder spir-42 is currently owned by @bob; use 'afx pickup' to take ownership before continuing.Open decisions for team discussion
These are the calls where preferences will affect the UX. Initial leans below; not yet committed.
1. Stable-boundary requirement on handoff
git statusclean. More flexible, but recipient might land mid-phase with partial work the donor hasn't framed.--overrideflag on the strict default covers the occasional "I really need to hand off this mid-phase work" case.2. Sync notification: try Tower message in addition to GH comment?
--no-pingflag for users who find the dual-notification noisy.3. Donor's local worktree after handoff
afx pickuplater if needed). Cleanest, matches the existingafx cleanupmodel.currentArchitect != selfmarker. Re-pickup is instant (no fetch, no new worktree). Better for sync ping-pong. Risk: stale local worktree if Bob makes lots of changes before handing back. Mitigated byafx pickupdoing a fast-forward fetch and refusing if there are local commits ahead of origin.4. Naming for "look without taking ownership"
A secondary primitive worth thinking about: sometimes Alice wants Bob to eyeball the spec without a full ownership transfer (Bob comments, Alice keeps going). Could be:
git fetch && git worktree addmanually and look. Handoff is the only first-class operation.afx peek <id>— fetches the branch into a read-only local checkout, no ownership transfer. Bob comments via PR review or GH issue comment.What this isn't (for v1)
afx workspace add-architect(existing) is for multiple architects sharing one machine / Tower. This issue is for handoffs across machines and people.Suggested protocol when ready to build
PIR. The plumbing is small (two
afxcommands, acurrentArchitectfield, the exclusivity-check helper, the GH/Tower notification dispatch), but the decision surface is wide and benefits from a plan-gate that locks the four open decisions above before code is written. CMAP at PR catches concurrency edge cases that a single reviewer is likely to miss.Related
afx send <workspace>:architect:<name>for the sync notification channel (existing).afx spawn --resumefor the local-resume primitive that the recipient command generalizes (existing).area:*for ownership-routing assistance, handoff candidates could surface naturally in views.