Skip to content

Slice 1: first-class session homes, client state contract, session-list drift gate #294

Description

@aarontrowbridge

Spec: spec-20260905-045114-session-device-lifecycle (D1, D2, D6). Label: afk.

Important

Problem — Session history can be invisible or stale without anything being
wrong server-side: non-git session homes resolve to a project the panel never
renders as a group; a client can serve a persisted empty session snapshot
forever, issuing zero list requests (#293); and a build can
silently change what a session-list query means (the v1 route: directory-
filtered → project-scoped), turning correct queries into empty answers.
Approach — Make every session home first-class (resolve + backfill + re-key

  • prune, keyed by worktree path); make the client state contract observable
    (fetch before first render, a derived projection-sensitive currency token,
    honest empty states, in-product reset); and declare session-list query
    semantics frozen surface behind the drift gate.
    Approaches considered — Convention only (git-init every home): rejected,
    leaves every non-git workspace a trap. Panel-side "loose sessions" group only:
    rejected as the sole mechanism, keeps server-side identity incoherent — kept
    as the render for the root fallback.
    Scope — in: project resolution + backfill + git-init re-key + junk-home
    lint; client boot/fetch/currency/reset contract; the drift-gate fixture. ·
    out: retention policy (slice 3), fleet overlay (slice 4).

Acceptance Criteria

  • Sessions in a non-git home render as a first-class panel group — for homes created before this change (backfill over existing session directories) and after
  • A non-git home that later becomes a git repo re-keys cleanly: sessions merge to the git-derived project, the auto row retires, and a merge killed mid-flight converges on the next boot
  • The junk-home lint never prunes a home holding archived sessions; restoring an archived session re-resolves its project row
  • A fresh headless client boots, and the hub's request log shows the session-list fetch initiated before the list first renders (the Sessions dropdown and home sessions list render empty despite successful session-list responses #288 boot harness)
  • The derived currency token (count, max, sum over the rendered projection + hub build id) advances on: same-tick writes, archive churn, delete-then-touch, direct out-of-band writes (property tests)
  • A client seeded with the BUG: Sessions dropdown stays empty after window reloads — stale client-side session cache is never invalidated #293 stale-storage shape self-heals on boot — no manual cache surgery
  • The UI renders "not yet fetched" and "genuinely empty" as different states
  • The in-product panel-state reset clears session caches only; workspace preferences survive
  • The boot fetch is paginated (recent tail first)
  • Drift-gate fixture: a PR changing session-list query semantics without a companion update fails; an additive optional field with base defaults passes

Testing Decisions

Harnesses H1 (fresh-client boot), H2 (DB-snapshot smoke — re-key resumability),
H4 (currency property tests), H5 (drift fixture) per the spec's verification
matrix; extend the existing #288 boot harness rather than new scaffolding.

Key Decisions

  • Project identity keys on the worktree path; git-derived identity supersedes
    auto-created rows for the same path (ADR-0002 boundary test applied to homes).
  • The currency token is derived from table state, never hand-bumped — no
    out-of-band write path can leave clients stale.
  • Client self-restraint against an unreachable hub (spawn backoff, attach-retry
    cap) is base and ships here: a solo client storming its own dead hub is the
    same failure as a fleet client's.

Constraints & Invariants

  • No directory a user can open as a workspace may strand its sessions in an
    unrenderable group.
  • Archive never orphans a home; restore re-resolves by worktree.
  • The global project remains the fallback for never-opened paths, rendered as
    an explicit "loose sessions" group.

Prior Art

The fork's session list + project resolver; #288's boot harness and fix;
#293 (the stale-client founding bug); the #356 M1 companion-gate pattern.

Source

spec-20260905-045114-session-device-lifecycle (D1, D2, D6) · slice 1 of 4

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    afkImplement + merge unattended

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions