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
Implement Stage 1 of cross-worktree device ownership: a shared owner-identity and liveness model, advisory host-global local-device claims, and a daemonless agent-device device status inspection surface.
Stage 1 is deliberately observational. It must prove the claim model and lifecycle without rejecting an open or reclaiming resources. Enforcement, --stale, platform reconciliation, forced release, and remote lease projection remain later stages.
Required behavior
Shared owner primitives
Extract the reusable PID + process-start-time identity and stale-owner classification currently proven by Apple runner leases; keep runner-lease behavior unchanged.
Classify at least live, owner-process-dead/PID-reused, owner-state-dir-gone, corrupt/inconsistent, and unknown/transient-filesystem-failure.
Treat only ENOENT/ENOTDIR as proof of absence. Permission and transient filesystem failures fail closed.
Keep process-lock serialization and atomic tmp+rename persistence shared rather than cloning a second staleness implementation.
Advisory local claims
Store versioned, user-private claims under ~/.agent-device/device-claims/.
Derive claim keys from canonical provider/platform/device identity for registered local targets; do not hardcode only iOS and Android.
Record session identity, workspace, state directory, owner PID/start time, timestamps, and an opaque ownership token suitable for compare-before-clear.
Write/update claims only at lifecycle transitions. Do not add host-global claim I/O to session-bound command hot paths.
Acquire advisory state before local platform preparation and clear it after safe session teardown, including failed-open rollback.
Because enforcement is disabled, a verified live foreign claim must not block the operation and must never be overwritten. Preserve the existing owner and emit structured advisory conflict diagnostics.
Clear a claim only when its token and owner identity still match. Late cleanup from an old owner must not erase a newer claim.
Remote targets do not create host-local claim files.
Read claim files directly without starting or contacting a daemon.
Inspection is side-effect-free: never reclaim, delete, rename, or quarantine a stale/corrupt claim.
Return compact structured ownership data including device key, platform/device identity, owner session/workspace/state dir, classification, and the future recovery command shape where determinable.
Corrupt or unreadable finalized claims remain visible as inconsistent/unknown rather than being treated as free.
Update command metadata/schema, CLI help, user docs, and focused SkillGym guidance where the public surface requires it.
Explicit non-goals
No ownership enforcement or DEVICE_IN_USE rejection yet.
No automatic reclaim, device release, --stale, or --force.
No Apple runner takeover or Android resource reconciliation.
No remote provider-lease projection.
No descriptor-wide DeviceClaimPolicy rollout; that belongs to Stage 2.
Acceptance criteria
A local session produces an advisory claim that another worktree can inspect with device status while no daemon is started in the inspecting worktree.
Local open/close and failed-open rollback write and clear claims at the correct lifecycle boundaries.
A second live owner is observed but neither blocked nor allowed to overwrite the first owner during Stage 1.
Token mismatch and PID-reuse tests prove stale cleanup cannot clear a successor claim.
Process-dead, state-dir-gone, corrupt, permission-error, and transient-I/O classifications are covered and fail closed.
iOS and Android lifecycle tests exercise the same platform-neutral claim store; canonical identity is registry-derived and remains extensible to other local Apple-family targets.
Remote sessions create no local claim.
device status has a test proving it does not start a daemon and performs no mutation.
Existing Apple runner lease behavior remains covered after shared primitive extraction.
Relevant affected checks pass, and manual two-worktree evidence demonstrates create → inspect → close → free behavior.
Prefer a deep platform-neutral ownership module and keep CLI rendering separate from claim persistence/classification.
If implementation reveals that advisory single-owner records cannot safely represent observed contention without data loss, preserve the authoritative existing record and report the limitation; do not silently expand Stage 1 into enforcement.
Parent: #1320
Depends on completed Stage 0: #1323
Summary
Implement Stage 1 of cross-worktree device ownership: a shared owner-identity and liveness model, advisory host-global local-device claims, and a daemonless
agent-device device statusinspection surface.Stage 1 is deliberately observational. It must prove the claim model and lifecycle without rejecting an open or reclaiming resources. Enforcement,
--stale, platform reconciliation, forced release, and remote lease projection remain later stages.Required behavior
Shared owner primitives
ENOENT/ENOTDIRas proof of absence. Permission and transient filesystem failures fail closed.Advisory local claims
~/.agent-device/device-claims/.Daemonless status
agent-device device statusand selector-scoped status using the singulardevicecommand group from feat: add cross-worktree device ownership and safe recovery #1320.inconsistent/unknown rather than being treated as free.Explicit non-goals
DEVICE_IN_USErejection yet.device release,--stale, or--force.DeviceClaimPolicyrollout; that belongs to Stage 2.Acceptance criteria
device statuswhile no daemon is started in the inspecting worktree.device statushas a test proving it does not start a daemon and performs no mutation.Implementation notes
CONTEXT.md, the relevant ADRs, feat: add cross-worktree device ownership and safe recovery #1320, and the merged Stage 0 implementation before choosing seams.