Skip to content

Devframe migration 2: sessions procedures as hub functions - #693

Draft
omridevk wants to merge 17 commits into
devframe-loginfrom
devframe-sessions
Draft

omridevk wants to merge 17 commits into
devframe-loginfrom
devframe-sessions

Conversation

@omridevk

@omridevk omridevk commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Devframe migration PR 2 (sessions group), stacked on the 1b login PR (#692). Draft until review.

What this does

  • Contract: the sessions schemas and error maps are named exports, shared by oRPC and Devframe.
  • Core: each sessions procedure body is one plain function; the oRPC procedure and a conciv:sessions:* Devframe function both call it, with the same error codes. Every sessions change publishes the list to shared state conciv:sessions; publishes run one at a time on a @tanstack/pacer queue so the last write is the latest list, and chat turns publish when they start and end so the running flag and title stay current.
  • Client: hubRoutedRpc(rpc, hub, groups) sends the listed groups' procedures to conciv:<group>:<proc> and leaves everything else on oRPC. Query utils are built over it, so query keys and invalidation are unchanged and direct rpc.sessions.* callers move without edits. A coded hub error counts as an answer for reachability; only DISCONNECTED reads as unreachable.
  • Widget: DEVFRAME_GROUPS = {'sessions'}. The router reads conciv:sessions for its whole lifetime (started at creation, stopped with its disposers) and writes it into the sessions.list query, so the selector follows renames and deletes made elsewhere without a refetch. The read waits for trust without a timeout, so a widget that logs in late still follows the list.
  • Extension: browserClient fetches the connection meta of the base it was given instead of reusing the first engine the page met; the reconnecting client reports status per attempt (see below).
  • Tests: kit.rpc.sessions.* sites use kit.hub; widget and embed sessions faults and waits use devframe-faults (new awaitCompletedCall); the oRPC-only rpc-wire helper is gone.

Behaviour notes

  • A hub call fails with the connection attempt in flight. While the engine refuses connections, a routed hub call waits only for the current attempt (or the next one if the client is between attempts) and rejects with DISCONNECTED when it fails, so a dead engine at boot shows "couldn't reach the engine" and one Retry recovers. A call on a closed hub connection rejects at once.
  • Per-attempt connection status. The reconnecting client now reports connecting at the start of every attempt and disconnected after each failed one, instead of staying disconnected through all retries. Status listeners see the pair repeat while an engine is down; reachability ignores connecting, so the online flag is unchanged.
  • Path-only hub base. browserClient resolves a base such as /__conciv/ against the page before fetching the connection meta, so page-origin hubs (Next, webpack, rspack) connect.

Not moved here

  • harness-testkit kit.session / cleanup still call oRPC: the testkit cannot see the conciv:sessions:* function types (the declare module 'devframe' augmentation lives in @conciv/core, which the testkit does not depend on). Moves in PR 20 with the rest of the oRPC removal.
  • Native CLI sessions appearing on disk do not publish (no server event exists); the widget's own refetch covers them as before.

🤖 Generated with Claude Code

The sessions group's schemas and error maps are named exports of the
contract, each procedure body is one plain function that both the oRPC
procedure and a conciv:sessions:* hub function call, and every sessions
change publishes the session list to the hub's conciv:sessions shared
state. Tests that called kit.rpc.sessions now call kit.hub.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.

@omridevk
omridevk changed the base branch from devframe-foundation to devframe-login November 2, 2026 00:16
@omridevk
omridevk added this pull request to stack #694 November 2, 2026 00:16
Hub publishes of conciv:sessions now go through a concurrency-1 pacer
queue, so each write reads the list after the previous one finished and
the last write is the latest list. A chat turn publishes when it starts
and when it ends, so the running flag, title and usage in shared state
follow the turn the way the widget's sessions.list refetch does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
omridevk and others added 15 commits November 2, 2026 03:05
The probe plugin registered conciv:sessions:list and conciv:sessions:create, which the engine now serves itself, so boot failed on the duplicate name and afterAll then called cleanup on an undefined kit. The test now boots a plain kit, proves the hub path by pointing the oRPC client at an unreachable address, proves the oRPC path with a hub call that rejects, and cleans up per test only when a kit exists.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The widget routes rpc.sessions through the hub once it holds a trusted base, keeps the oRPC query keys, and writes the published conciv:sessions list into the sessions query. Answered hub errors no longer read as an unreachable engine, and a browser hub client fetches the connection meta of the base it was given instead of reusing the first engine the page met.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… an effect

The router starts the conciv:sessions read when it is created and stops it with its other disposers, and the read waits for trust without a timeout, so a widget that logs in late still follows the list. A read the reader already abandoned no longer logs a failure, and the shell test harness unmounts the widget before it closes the hub, which is what left a read in flight against a closed connection.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ssions

# Conflicts:
#	packages/client/src/query-utils.ts
#	packages/client/test/client.test.ts
#	packages/core/src/devframe-plane.ts
The embed widget lists sessions over the hub, so the boot waits and the loading-shell gate in the embed tests now wrap conciv:sessions:list on the kit's hub through devframe-faults, which gains a wait for the first completed call. The page-level rpc-wire helper only watched the sessions procedures and is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… refuses

A routed sessions call waited on the hub connection forever while the engine
refused, so a dead engine at boot left the panel on its loading screen. The
reconnecting client now reports connecting and disconnected for every attempt,
and the widget's hub call waits only for the attempt in flight, rejecting with
DISCONNECTED when it fails. The panel shows the unreachable-engine screen again
and one Retry recovers once the engine answers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nection meta

browserClient fetched __connection.json with new URL(file, baseURL), which
throws for a path-only base such as '/__conciv/', so a page on the hub origin
retried forever and never connected. Every page-origin hub (Next, webpack,
rspack) uses that form. The base now resolves against the page location first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A closed connection emits no further status, so a call made after the widget
disposed its hub waited forever. It now rejects with DISCONNECTED immediately.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The embed built its hub client once, from the first engine base. When the
handle rebound to an engine on another port and the old port closed, the hub
went disconnected, engine reachability voted offline, and the composer stayed
disabled. The embed now derives the hub from the bound base: a rebind to a
different hub base closes the old hub and opens one for the new base, and the
router, the hub-routed sessions calls, the session list subscription and the
reachability subscription all read the current hub. The rebind test now
asserts the hub reaches the new port, so it fails on every platform when the
hub stays behind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ssions

# Conflicts:
#	packages/core/src/devframe-plane.ts
Engine reachability is now a subscribable source (engineReachability) that the
router reads through Solid's from(), keyed on the api base and the hub
connection, and the router context hands the result to the reachability
context instead of a second onlineManager signal. The embed's followed hub
connection is a keyed mapArray entry: a hub base change makes a new entry and
the old connection closes when its owner is disposed, while the first entry
reuses the connection the login card already holds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The memo that re-runs once per hub connection now opens the
conciv:sessions subscription for that connection and closes it on
cleanup, replacing the last raw createEffect in wireEngineConnection.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant