fix: separate session containment from opened-by provenance - #569
Conversation
Model: gpt-5
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Model: gpt-5
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3620c06691
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| - Root archive, restore, and permanent delete include only direct child Tabs whose | ||
| `parentSessionId` equals the root id. Independently opened Sessions keep their own | ||
| state and resources. Permanent deletion requires a complete metadata cache before | ||
| selecting targets; nested child Sessions are unsupported. Keep dangling `openedBy*` |
There was a problem hiding this comment.
Add a draft Spec for the lifecycle guarantee
This introduces binding archive, restore, permanent-delete, and dangling-navigation semantics, but records them only in an AGENTS rule, implementation documentation, and an Agent Note. Add or update the owning public session-lifecycle Spec with Status: draft; otherwise these destructive ownership semantics ship without the repository's required human-reviewable intent contract.
AGENTS.md reference: AGENTS.md:L15-L17
Useful? React with 👍 / 👎.
Model: gpt-5
Related issue
Closes #531
Problem / pressure
Desktop and mobile treated
openedBySessionIdandopenedByRootSessionIdas lifecycle ownership edges. Archive/restore could stop an independently owned Session, and the natural archive-then-delete flow could permanently delete that still-active Session and its worktree without warning.A later safety gate also made
deleteSessions(ids)wait for complete metadata, even though its production callers use it for exact compensation and cleanup during hydration.Summary
parentSessionIdchild Tabs.deleteSessions(ids)exact: delete only the supplied ids, with no relation discovery or metadata-readiness requirement.openedBy*metadata as provenance after an opener is deleted. Once metadata hydration proves that the exact opener or route root is missing, show deleted-session provenance without a working navigation action.deleteArchivedSession(rootId), where the operation must discover the destructive set.specs/session-relations.mdas the durable relation and operation-target contract.collectSessionLifecycleIdsgraph and its opened-descendant contract. Keep archived opened-by tree construction as presentation behavior.No tombstone store, relationship policy layer, recursive nested-child behavior, or supervised-worker product from #529 is introduced.
Visual explanation
The solid edge is containment and selects root-operation targets. The dotted edges are provenance only. Exact cleanup does not traverse either edge:
deleteSessions([X])deletes only X.Before / after
deleteSessions(ids)removes exactly the known ids during hydration and never discovers extra targets.Test plan
use-session-actions.test.ts: 33/33 passed, including incomplete-cache exact Tab deletion, partial-create compensation, archive/restore isolation, archive-then-delete, and incomplete-cache archived-root rejection.SessionManager.requestSessionTerminate: 4/4 passed. A retry after the runtime is gone returnsnot-found; the RPC handler maps that result to success, so side-session termination retry is idempotent at the RPC boundary.pnpm checkwrapper could not start in this shell because its hardcodedcorepackexecutable is unavailable. The directly invokable affected checks above passed; GitHub CI is authoritative for the full matrix.Follow-up
#574 continues to track the pre-existing archive cold-start race where Session Detail may expose Archive before all direct child Tabs hydrate. The draft Spec records the intended complete-target contract and the current implementation gap.
Context handoff
Instructions for reviewing agents
parentSessionIdTabs. VerifydeleteSessions(ids)deletes only supplied ids and remains usable before metadata hydration. Review the draft Spec as the owner of these guarantees.openedBy*remains historical provenance while navigation requires both the exact opener and route root after hydration.sessionMetaCacheAtom; [Bug] Archive can miss child Tabs before metadata cache hydration #574 tracks their pre-hydration completeness race.Authoring context
parentSessionIdselects root-operation targets;openedBy*remains provenance; discovery-based archived-root deletion waits for complete metadata; exact cleanup does not.deleteSessions(ids)removes exactly the supplied Sessions. Independently opened Sessions and resources are excluded unless explicitly supplied.