Re-home the session & device lifecycle base contract onto the app overlay (canonical v1.18.29) - #819
Draft
aarontrowbridge wants to merge 11 commits into
Draft
Re-home the session & device lifecycle base contract onto the app overlay (canonical v1.18.29)#819aarontrowbridge wants to merge 11 commits into
aarontrowbridge wants to merge 11 commits into
Conversation
… classifier (D2 core) Issue #817 — port of the held fork reference (harmoniqs/opencode#296) onto the app overlay at canonical v1.18.29. The pure core of D2 (spec spec-20260905-045114): sessionListState distinguishes 'not yet fetched' (incident #293's invisible failure) from 'genuinely empty', and the reset scope classifier + touch-list pin that 'Reset panel state' clears session caches ONLY — workspace preferences and drafts survive recovery. Wiring into the sync stores, dropdown, home, and the command lands next.
…he fetched projection (D2/H4) Issue #817 — the revised placement: the fork's token was a server field (core/src/session/currency.ts + the v2 response); the overlay port drops that dependency entirely. deriveCurrencyToken recomputes (count, max time_updated, sum time_updated) over the rows the list returns, stamped with the server-reported version. The H4 properties are enforced client-side: same-tick writes, archive churn, delete-then-touch pairs, and out-of-band writes all advance the token by construction — derived, never hand-bumped.
…d flag, dropdown, in-product panel reset (D2) Issue #817 — port of the fork's d4e3d64f82 adapted to the overlay's sync shape: child stores carry a sessions_fetched flag set when a list fetch resolves (both the cached-store early-return and the fetch path), the sessions dropdown routes through sessionListState and renders loading — never the empty state — while no fetch has resolved (#293's invisible failure shape). 'Reset panel state' (command.panel.reset, all 18 overlay locales) calls project.resetSessionCaches: in-memory session fields, sessionTotal/status, and the loadSessions/activeSessions query keys only — persisted workspace preferences are never touched, pinned by the wiring test's no-persisted-write assertion.
…via the client-derived token (D2) Issue #817 — port of the fork's 95a065f7ec adapted to the revised placement: child stores persist a per-workspace 'session:snapshot' (render accelerator, never an authority), hydrated only until the first real list fetch resolves (sessions_fetched gate). Every list response verifies the snapshot via bootCurrencyDecision over the CLIENT-derived token — count/max/sum of the fetched rows stamped with the hub's self-reported version (resolved once per server context through the health endpoint, exposed as serverSDK.version()). A stale or tokenless snapshot — the #293 shape — is invalidated by the overwrite, so recovery needs zero filesystem surgery. The panel reset invalidates all snapshots too (session:snapshot is on the pinned touch-list).
…ss (D2/D4) Issue #817 — port of the fork's 10b7e96e onto the overlay: home-session-index is carried into the overlay (upstream-maintained true overlay, per the M2 pattern) with the exhaustion signal corrected — a page shorter than the requested limit does NOT mean the store ended; only a missing continuation cursor does. A hub capping page size below the request would otherwise silently drop everything past its first short page. The carried module's pure deps (session-trim, utils, path-key) ride along so the module stays importable by the extension's vitest suite; utils' session-ui import becomes type-only (used only in a return type). Pagination property tests ported: desc-first recent tail, cursor-driven multi-page assembly, short-page continuation, abort between pages.
…onest states on the home page (D1 + D2) Issue #817 — the revised placement of D1: project grouping resolves CLIENT-side over directory/projectID (data the global home index already returns) — no server project rows, no boot-time backfill, no junk lint. The old controller dropped every session whose directory resolved to no opened project (the founding incident: 687 sessions in a non-git home, API-visible but panel-invisible); resolution now keys on the WORKTREE PATH (the D1 identity — a stale projectID never steals a session), synthesizes a first-class home for unmatched directories, and re-keys for free when a non-git home later becomes a git repo (opened projects resolve first). The per-project home scope keeps its deliberate filtering; the all-projects scope drops nothing. home-sessions-controller/home-sessions are carried into the overlay (upstream-maintained true overlays) wired to the new pure module (home-session-groups, unit-tested headless), and the home page routes through sessionListState: while the index query has never succeeded the view renders the skeleton, never the empty state.
…s release channel, fail-open (D3) Issue #817 — the revised placement of D3: parity is checked CLIENT-side at boot using the server-reported version (from the health check the app already runs) against the canonical opencode release channel. Three outcomes — parity-ok | parity-drift | channel-unreachable — and the check fails OPEN on an unreachable channel while recording a DISTINCT outcome, so an assertion that never ran is never mistaken for one that passed (the lagging-hub incident). The record is logged, never a gate: enforcement of upgrading stays advisory for solo users; the check is not.
…+ hub request log) Issue #817 — port of the fork's 80a57acc8a adapted to the client-derived currency: boots the client's session-list layer against a seeded hub and asserts on the hub's request log — the same evidence that diagnosed #293. Owns the D2 criteria's fixtures: fetch-before-first-render (the boot order snapshot-hydrate → fetch-initiate → first-render, with the fetch initiated unconditionally — a persisted snapshot is never an authority), stale-client self-heal (seeded with the #293 webview-storage shape), tokenless-snapshot invalidation, out-of-band projection change, and the honest states after a resolved fetch.
…te becomes per-harness contract testing (D6) Issue #817 — the revised placement: the fork's protocol-level drift gate (packages/protocol session-list-semantics) becomes a CONFORMANCE suite the client carries. The client's expectations of session-list query semantics are declared (CANONICAL_SESSION_LIST_SEMANTICS: directory + parentID scoping, desc order, archived excluded, roots-only on parentID null, cursor-only pagination exhaustion) and probed against any harness's session.list — canonical opencode today, Telaio tomorrow. A semantic change without a companion update goes red (scoping/filtering/pagination drift probes fail); an additive optional field with a base default goes green (the D6 change policy, with the F5 additive-field registry declared). The pagination probe takes the fixture's expected row count — no black-box probe can distinguish a store that truly ended from a hub that stopped early on a short page.
…iles; add the missed snapshot behavior test The #817 overlay additions (session-currency, session-snapshot, session-list-state, boot-parity, session-list-conformance, home-session-groups, h1-client-boot, the carried true overlays) registered via refresh_manifest.mjs against upstream v1.18.29; the boot-currency decision's behavior suite (session_snapshot_817.test.ts) lands with it — it was authored in the TDD loop but left unstaged at its commit boundary.
…ase.version, readonly projects, parity parts typing Issue #817 — the app-tree typecheck (materialize + tsgo -b) caught three gaps in the port: ServerSDKBase declares the version accessor the sync consumes; home-session-groups takes a readonly project list; boot-parity's log parts are typed as strings. Manifest + drift-report re-recorded for the touched overlay files, and .materialized/ is gitignored — it is a local build artifact and was never meant to ride a commit. The app package now typechecks clean against upstream v1.18.29 except two PRE-EXISTING error classes on origin/main (server-session.ts diff_version vs the overlay's SessionCache; i18n/parity.test.ts's 'am' locale not in the overlay dict set) — noted for a follow-up, not fixed here (no drive-bys). The vite production build succeeds.
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This was referenced Sep 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #817 (issue: #817). Spec of record:
spec-20260905-045114-session-device-lifecycle— the Placement under harness-agnostic (amendment, revised same day) section and D2/D6 govern this port.What this is
The session & device lifecycle base contract, ported from the held fork reference (harmoniqs/opencode#296, branch
slice1-session-lifecycle) onto the app overlay at canonical opencode v1.18.29, with the three ADAPTATIONS the revised placement requires:serverSDK.version()). No server field; the fork'score/session/currency.ts+ server-handler dependency is dropped entirely.parity-ok | parity-drift | channel-unreachable), fail-open; the fork-era server-side drift gate becomes a per-harness conformance suite fixture (D6's revised placement).Commits (small, each green at its boundary)
sessionListStatemachine + the panel-reset scope classifier/touch-list (pure, unit-tested)deriveCurrencyToken+ H4 properties: same-tick writes, archive churn, delete-then-touch, out-of-band writes all advance it by constructionsession:snapshot(accelerator, never authority),bootCurrencyDecision, hydration gated onsessions_fetched, verify+overwrite on every list responsesessions_fetchedflag in both load paths, dropdown renders loading-never-empty,command.panel.reset(18 locales)home-session-indexcarried as a true overlay with the exhaustion-signal fixhome-session-groups(path-keyed resolution, synthesized non-git homes, free re-key); home page threadslistStaterecordBootParitywired into the ConnectionGate health checkGreen criteria (verified)
*_817.test.tsgreen (state machine, currency properties, snapshot decision, wiring pins, pagination, grouping, parity, H1, conformance).app-bundledrift gate: PASS (overlay + manifest in sync, 589 files).Not-green / honest caveats (pre-existing on origin/main, not touched here)
packages/apptypecheck:server-session.ts(497)— upstream'screateServerSessiondoesn't satisfy the overlay'sSessionCache(diff_versionrequired); andi18n/parity.test.ts— upstream's 46-locale set includes"am", not in the overlay's dict set. Both reproduce on a pristine origin/main materialization; noted for a follow-up (no drive-by fixes per discipline).packages/extensionvitest:test/terminal.test.ts(OPENCODE_DB/OPENCODE_CONFIG_DIR injection) fails identically on pristine origin/main — environment-dependent, pre-existing.fleet_overlay_unstaged_without_entitlementis out of scope (amicissimo#380, parallel session) per the issue.Runner discipline
Tests run under vitest (extension suite) via relative imports of the overlay's pure modules + the repo's established source-pin idiom for Solid wiring; no
bun testwas used, no live chat DB or running server touched.