Problem Statement
The auth path has accumulated 5 uncoordinated cookie-jar writers, 10+ implicit state machine transitions, and scattered conversation-threading logic across 4 files. Every fix in the phantom-auth saga (v2.6.0–v2.7.0) added a new branch to the implicit state machine, and 4 of 10 fixes touched jar-writer logic — each with a different merge strategy.
The RotateCookies 401 session-kill fix is the first fix that UNDOES a previous fix — confirming the rotation apparatus was over-engineered. Comparison with v2.4.0 (which still works in production with 12-day-old sessions) shows that the RotateCookies + phantom detection + targeted L2 layers were built on the false premise that the jar was complete.
An alternate plan to remove these layers entirely is documented at docs/alternate-plan-simplify.md. This issue covers the active plan: keep the layers but make the architecture explicit.
See architecture review v5 at Temp folder.
Solution
- Candidate A — CookieJar unification: Replace 5 uncoordinated jar writers with one CookieJar module (replace/upsert policies).
- Candidate C — Explicit state machine: Split ensureAuthenticated into classifySession (5 states) and recover.
- Candidate B — Conversation threading: Deep module for cid/rid/rcid indexing.
- Candidate E — Post-call seam: Consolidate persistRefreshedCookies 8 call sites to one hook.
Commits
Phase 1: Merge prerequisite
- Merge fix/rotate-cookies-401-session-kill → main (4 commits, 954/1/0)
Phase 2: Candidate A — CookieJar (8 commits)
- Create cookie-jar.ts — replace/upsert, keyed by (name, domain, path)
- Wire CookieMonitor capture → CookieJar.replace()
- Wire persistRefreshedCookies → CookieJar.upsert()
- Wire L1 rotateCookies → CookieJar.upsert()
- Wire targeted silentRefresh → CookieJar.upsert()
- Wire full silentRefresh → CookieJar.upsert()
- Remove mergeCookies standalone function
- Integration tests for CookieJar pipeline
Phase 3: Candidate C — State machine (4 commits)
- Extract classifySession() with 5 states (Fresh/Phantom/Dead/Stale/Declined)
- Extract getRecoveryAction() policy function
- Wire into ensureAuthenticated
- Integration tests for state machine wiring
Phase 4: Candidate B — Conversation threading (4 commits)
- Create ConversationThreading module (threadOnto + captureFrom)
- Wire threadOnto into sendMessage
- Wire captureFrom into fetchChat/seedMetadataFromChat
- Remove raw metadata extraction from seedMetadataFromChat
Phase 5: Candidate E — Post-call seam (1-2 commits)
- Consolidate persistRefreshedCookies to one post-call hook
- Final verification (954+/1/0, typecheck, openspec validate)
Decision Document
- CookieJar has two policies (replace/upsert), not five. Callers filter.
- State machine is two pure functions (classification + recovery), independently testable.
- ConversationThreading is pure transformations. Magic indices in one file.
- CookieJar delegates to CookieStorageService (doesn't bypass to CookieStorage directly).
- RotateCookies 401 → Declined state, not Dead state.
- upsert key is (name, domain, path).
Testing Decisions
- Test external behavior, not implementation
- New unit tests for CookieJar, classifySession, getRecoveryAction, ConversationThreading
- Integration tests using gimme helper pattern from phantom-auth.test.ts
- Existing 954 tests must stay GREEN on every commit
- Phase 0 v2 regression net (10 tests) is the safety net
Out of Scope
- Candidate D (probe consolidation) — deferred
- Removing RotateCookies/phantom detection — alternate plan in docs/alternate-plan-simplify.md
- Background daemon / gemiterm watch
- Profile-aware factory wiring full refactor
- CI gating
- Live verification (user-driven)
Further Notes
- Baseline: 954/1/0 (2031 expects). Must not regress.
- Branch: overhaul/auth-architecture off main after merging 401 fix.
- Fallback: docs/alternate-plan-simplify.md if state machine proves too complex.
- Related: docs/phantom-bug-synthesis.md, docs/phase-0/phase-0-v2-design.md
Problem Statement
The auth path has accumulated 5 uncoordinated cookie-jar writers, 10+ implicit state machine transitions, and scattered conversation-threading logic across 4 files. Every fix in the phantom-auth saga (v2.6.0–v2.7.0) added a new branch to the implicit state machine, and 4 of 10 fixes touched jar-writer logic — each with a different merge strategy.
The RotateCookies 401 session-kill fix is the first fix that UNDOES a previous fix — confirming the rotation apparatus was over-engineered. Comparison with v2.4.0 (which still works in production with 12-day-old sessions) shows that the RotateCookies + phantom detection + targeted L2 layers were built on the false premise that the jar was complete.
An alternate plan to remove these layers entirely is documented at docs/alternate-plan-simplify.md. This issue covers the active plan: keep the layers but make the architecture explicit.
See architecture review v5 at Temp folder.
Solution
Commits
Phase 1: Merge prerequisite
Phase 2: Candidate A — CookieJar (8 commits)
Phase 3: Candidate C — State machine (4 commits)
Phase 4: Candidate B — Conversation threading (4 commits)
Phase 5: Candidate E — Post-call seam (1-2 commits)
Decision Document
Testing Decisions
Out of Scope
Further Notes