Skip to content

[70_TD] Portable client driver for stock Interchange bootstrap - #739

Merged
TheGreatAxios merged 8 commits into
mainfrom
cl-intx-client-driver
Sep 16, 2026
Merged

TheGreatAxios merged 8 commits into
mainfrom
cl-intx-client-driver

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Contributor

Intent

There is no parent bench: the web client drives stock Interchange directly. This branch introduces the portable, thread-native client driver (bootstrap on first open and signup, convergence of remaining importers) and deletes the bench-mediated tenancy-kind abstraction without replacement — a hard cutover to the client-owned model.

Key commits

  • 1ba09afb test(web): define portable client convergence
  • 97718206 feat(web): portable client-driven Interchange bootstrap
  • 91525144 feat(web): run portable client bootstrap on first open and signup
  • d2824a01 fix(web): resolve critic findings on portable client driver
  • 369eb755 feat(web): thread-native portable client convergence
  • b75cd51e fix(web): participant-scope thread fallback and fork replay key
  • 226864ca feat(web): cut remaining importers to thread-native client model
  • ac003b8b docs(web): scope cutover note to client-only tenancy-kind removal

Verification

  • Suites (added/updated on this branch): apps/web/src/threads.test.ts (new convergence coverage), needs-converge / needs-list tests, updated overlay/palette/page test expectations, bench-ui tenancy-kind removal.
  • Critics: findings resolved in d2824a01.
  • Full bun run check gate runs in CI on this PR.

Notes

  • Linear issue IDs are pending; this branch will be renamed to cl-<id>-<slug> once filed.
  • Merge order is 1 → 2 → 3 with (3) hub last. This is PR (1) of 3 — merge first.

The client holds a needs-list manifest and converges it against stock
Interchange routes only: manifest with arktype boundary, StockHub port,
DM derivation (one chat child per owned top-level workflow refId),
typed upstream-gap errors, and a hub/account-scoped client-side store
for created child tenant ids.
Converges the client needs-list beside server provisioning at both
entry points. Non-gating: a stock capability gap is logged, never
shown, and a thrown failure is caught so it can never surface as an
unhandled rejection.
Pagination follows nextCursor on both stock listings, bootstrap
log branches share one helper, the child-tenant store filters
per row, the dead tenant-kind capability and unreachable
primary-tenant guard are removed, and the workbench write path
gains create+invite and idempotent reclaim coverage.
DMs derive from participant-filtered threads; workbenches converge as
child tenant plus primary thread plus In-Reply-To sub-thread forks.
Creation idempotency rides native Message-IDs; stock routes only.
Summary:
- deriveThreads subject fallback merges only within one participant set, so distinct 1:1 pairs sharing a subject keep separate threads and both DMs survive.
- forkSubThread replay key covers parent plus subject plus recipients plus body; edited bodies and retargeted forks send anew while pre-upgrade rows keep parent-plus-subject replay.
- convergeNeedsList documents the mail[0] oldest-first ordering assumption beside the fallback; isDuplicateMessageId keeps its shared-helper role by comment.
- DM-tenancy deletion completed: client-bootstrap exposes primaryThreads with no DesiredDirectMessage/directMessages, and the stale DM-children comment in main.tsx now reads child rooms.

Verification:
- bun test ./src in apps/web: 375 pass, 0 fail across 48 files.
- tsc --noEmit in apps/web: exit 0.
- prettier --check and eslint on touched files: clean, exit 0.
- bun run check:structural including no-product-tenancy: all ok, exit 0.
- New keeper tests failed before the fix (subject merge collapsed both DMs to [], fork replay dropped edited bodies) and pass after.
Summary: bench selection, routines roster, and command palette filter benches by human-assigned name (isBenchMembership over isRawIdentifier) with no kinds lookup; meKeys.workbenchTenancyKinds removed; bench-ui drops tenancy-kind/api surface and keeps raw-id guard plus tenancy contracts; test fetch stubs for POST /kinds removed; docs carry a cutover note.

Verification: bun run scripts/typecheck.ts exit 0; tsc --noEmit in apps/web and packages/bench-ui exit 0; prettier check on touched files exit 0; eslint on touched sources/tests exit 0; 79 pass across 9 affected web test files; 22 pass in packages/bench-ui; bun run check:structural exit 0.
The thread-native client-driver branch cut web/bench-ui client usage
only (classifyBenchMembership/filterBenchMemberships/TenancyKind, kinds
client); the server WorkbenchTenancyStore/workbench_tenancy table/POST
/api/workbench-tenancies/kinds surface is untouched here and its removal
lands separately. TENANCY.md tenancy-kind passages go past tense with a
pointer to isBenchMembership; bench-context selector comment drops the
deleted TenancyKind wording; the named-child-tenant open question is
recorded as docs-only.
@TheGreatAxios
TheGreatAxios merged commit e81334c into main Sep 16, 2026
24 checks passed
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