page:docs-specs-platform-gaps-research-synthesis-adoption-proposal
Synthesis: t3code adoption-model proposal + five-spec outline (Gate A) reference
Date: 2026-09-27 · Status: Gate A decision document (D16) · Author: platform-gaps spec synthesis run
Synthesis: t3code adoption-model proposal + five-spec outline (Gate A)
Date: 2026-09-27 · Status: **Gate A decision document** (D16) · Author: platform-gaps spec synthesis run Binding intent: docs/specs/platform-gaps/00-intent.md (D1–D16, verbatim). Inputs consumed in full:
| Dossier | Path | Cited as |
|---|---|---|
| R1 — fabric current state + audit refresh | research/fabric-current-state.md | R1 §n / fabric:path:line |
| R2 — t3code architecture | research/t3code-architecture.md | R2 §n / t3:path:line |
| R3 — packaging state | research/packaging-state.md | R3 §n |
| R4 — interface delta map | research/delta-map.md | R4 Row A–D / spec input n |
Every decision below carries a **Decision proposed / Alternatives / Why** block traced to dossier evidence. Approving this document is Gate A; the five specs (§4) are then written against these decisions and reviewed at Gate B.
---
1. Per-component adoption model (D1)
D1 requires a per-component choice among **vendor-wholesale** (take the t3code unit as-is and adapt), **extract-packages** (lift self-contained packages into fabric's monorepo), and **implement-contracts** (adopt only the interfaces, keep/rewrite the implementation). D2 fixes the four components in scope.
1.1 `adapters` — harness-driving layer (D2a, D6)
**Decision proposed: implement-contracts for the adapter layer itself, plus extract-packages for the two protocol packages (effect-acp, effect-codex-app-server). ACP becomes canonical (D6) via a contract replacement over the existing 22-codec drive layer: a ProviderAdapter-equivalent contract with four lane kinds, under which the current 49-type AgentEvent union survives as an internal projection. The 12 observe-side hook adapters are retained unchanged as a fifth, fabric-only lane feeding the same projection.**
Shape (R4 §A.6, R4 spec inputs 1–4):
1. **One contract, four drive-lane kinds** — successor of BaseAgentAdapterInterface + RunHandle (fabric:packages/adapters/core/src/adapter-types.ts:24, run-handle.ts:150), modeled on t3code's ProviderAdapter contract with typed capabilities and compaction semantics (t3:apps/server/src/provider/Services/ProviderAdapter.ts:29-56): - **ACP lane**: generic runtime + per-harness extension modules, copied from t3code's AcpSessionRuntime + CursorAcpExtension/XAiAcpExtension pattern (R2 §4). - **Claude SDK lane**: @anthropic-ai/claude-agent-sdk in-process (t3:provider/Layers/ClaudeAdapter.ts:5-27), replacing fabric:packages/adapters/codecs/src/claude-agent-sdk-adapter.ts. - **Codex app-server lane**: JSON-RPC stdio typed by the effect-codex-app-server fork (t3:provider/Layers/codexLaunchArgs.ts:13, R2 §7), replacing codex-websocket-adapter.ts / codex-sdk-adapter.ts. - **OpenCode HTTP lane**: server-per-thread via @opencode-ai/sdk/v2 (t3:provider/Layers/OpenCodeAdapter.ts:32, t3:docs/internals/providers.md:14-22), replacing opencode-http-adapter.ts. - **Retained-subprocess lane** (fabric-only): the surviving codec adapters for harnesses t3code does not cover, migrated behind the new contract (R4 spec input 3). 2. **Projection direction is fixed**: ACP session/update + bespoke-lane events → normalizer → AgentEvent (fabric:packages/adapters/core/src/events.ts:411, 49 interfaces) as **derived view**; existing consumers (RunHandle iteration, gateway run.event fan-out at fabric:packages/adapters/gateway/src/runs/manager.ts:103-110, journal binding, cost/attestation) keep compiling and define the projection's acceptance tests (R4 spec input 2). This is exactly D6's "internal projection/derived view" clause. 3. **Fabric as ACP agent**: adopt effect-acp's agent side (t3:packages/effect-acp/src/agent.ts:31) so babysitter runs and genty sessions are drivable as ACP sessions by external ACP clients — zero fabric precedent, dep = effect only, cleanest early win (R4 spec input 4). 4. **Must-survive constraints (binding, R4 §A.4)**: journal/run binding (every lane still terminates in fabric:packages/babysitter-sdk/src/storage/journal.ts:72-82); the 12-adapter observe lane; trust-signed policy gates (fabric:packages/adapters/policy/src/proven-bridge.ts:92-119) gating the new drive-side permission callbacks rather than being bypassed by them; cost records + model-proxy attestation seam (fabric:packages/adapters/transport/src/server.ts:1596-1607) as projection consumers; atlas graph coupling (R4 §A.3 FABRIC-ONLY rows).
**Lane decision for ALL 16 harnesses** (t3code's 6 per R2 §4/§18.1; fabric's 10 extras per R4 spec input 3):
| # | Harness | Today in fabric | Proposed lane | Evidence / notes |
|---|---|---|---|---|
| 1 | Claude Code | codec claude-agent-sdk-adapter.ts + hook adapter; live-stack GREEN (R1 §4.3) | **Claude SDK lane** (bespoke) | t3:provider/Layers/ClaudeAdapter.ts:5-27; history in child worker (t3:claudeHistoryWorker.ts:1-11) |
| 2 | Codex | codec websocket/SDK adapters + hook adapter; GREEN | **Codex app-server lane** (bespoke, typed) | R2 §7; async-question protocol traps documented (t3:docs/internals/providers.md) |
| 3 | Cursor | codec cursor-adapter.ts + hook adapter; lane failing (#562) | **ACP lane** | cursor-agent … acp (t3:provider/acp/CursorAcpSupport.ts:56-60) |
| 4 | Grok Build | **nothing** — no adapter, no lane (R1 §3.1) | **ACP lane — new build** | grok --permission-mode <m> agent stdio (t3:provider/acp/GrokAcpSupport.ts:33-41); mandatory for D7(a) |
| 5 | OpenCode | codec opencode-http-adapter.ts + hook adapter; lane skipped/failing | **OpenCode HTTP lane** (bespoke) | server-per-thread rationale t3:docs/internals/providers.md:14-22 |
| 6 | Antigravity | hook adapter; lane failing (#945) | **ACP lane + managed installer** | downloaded release verified antigravity-acp protocolVersion 1 (t3:provider/AntigravityInstallation.ts:484-502); revert-rejection rule (R2 §3.4) |
| 7 | Gemini (CLI) | subprocess codec + hook adapter | **Retained-subprocess lane** | no ACP evidence in dossiers; re-evaluate for ACP promotion post-migration |
| 8 | Copilot (CLI) | subprocess codec + hook adapter | **Retained-subprocess lane** | same |
| 9 | Pi | subprocess codec + hook adapter; live-stack push default | **Retained-subprocess lane** | same |
| 10 | Oh-My-Pi | hook adapter adapter-oh-my-pi | **Retained-subprocess lane** | see aliasing note below |
| 11 | OMP | codec + live-stack lane id omp | **Retained-subprocess lane** | see aliasing note below |
| 12 | OpenClaw | subprocess codec + hook adapter | **Retained-subprocess lane** | no t3code counterpart (R4 §A.3) |
| 13 | Hermes | subprocess codec + hook adapter | **Retained-subprocess lane** | same |
| 14 | Droid | subprocess codec + live-stack lane (no hook adapter) | **Retained-subprocess lane** | codec-only today (R1 §4.3 vs §3.1) |
| 15 | Amp | subprocess codec + live-stack lane (no hook adapter) | **Retained-subprocess lane** | codec-only today |
| 16 | Genty (fabric's own runtime) | codec + hook adapter + runtime-cli lane | **ACP-agent lane**: genty exposed *as* an ACP agent via the effect-acp agent service, driven through the standard ACP lane | t3:packages/effect-acp/src/agent.ts:31 (R4 spec input 4) — makes fabric's own runtime the first consumer of the fabric-as-ACP-agent capability |
*Aliasing note (must be resolved by migration WP T-13):* R1 lists hook adapter oh-my-pi (R1 §3.1) while the live-stack agent map lists omp as a distinct id alongside pi (R1 §4.3), and R4 spec input 3 enumerates both oh-my-pi and omp among the ten extras. If omp is the live-stack id for the oh-my-pi adapter, rows 10–11 collapse into one harness (15 total) and the WP count in T-13 shrinks by one unit; the migration spec must confirm from the live-stack agent map before freezing the lane inventory. The observe lane is unaffected: all 12 hook adapters (claude, codex, gemini, copilot, cursor, pi, oh-my-pi, opencode, openclaw, antigravity, hermes, genty — R1 §3.1) are retained regardless of drive-lane decisions.
**Alternatives considered:**
- *Vendor-wholesale
apps/server/src/provider/**: rejected as the adapter-layer model. It would import t3code's drive-only worldview and drop fabric-unique capabilities with no t3code analogue — the observe lane, journal binding, trust-signed gates, attestation seam, atlas coupling (five FABRIC-ONLY rows, R4 §A.3) — and would drag in t3code's toolchain (pnpm catalogs, vite-plus, TS7/tsgo; R2 §18.12). The provider *implementations* (ACP runtime + support modules, installers, usage ingestion) are still lifted nearly verbatim inside the lanes, so wholesale value is captured where it is real. - *Implement-contracts only, hand-writing ACP*: rejected.
effect-acp(5.2k handwritten LOC, dep =effectonly) andeffect-codex-app-server(3.8k handwritten) are extractable as-is with regenerable schemas (R2 §18.2, §18.9); re-implementing them is pure waste and forfeits upstream protocol-churn tracking (D9). - *Extending the current 22-codec layer with an ACP codec, no contract replacement*: rejected — violates D6 ("ACP becomes CANONICAL … current event model becomes a projection"); would leave the 49-type union as the source of truth and ACP as one more codec, the inverse of the mandate.
**Why:** R4 Row A measures ~45% capability overlap — the highest of the four rows — meaning this is a true merge of two live systems, not a gap-fill. Contract replacement preserves the five fabric-only capability families while importing the five t3-only ones (ACP both directions, typed Codex lane, drive-side approvals, checkpoint coordination, injected MCP endpoint — R4 §A.3), and the four-lane shape is proven at ~200k-user scale in t3code (R2 §1). ACP being greenfield in fabric (zero hits, R1 §3.1) means there is no legacy ACP surface to reconcile — the projection boundary is the only compatibility work.
1.2 `kradle` control surfaces (D2b)
**Decision proposed: extract-packages for contracts (tracked fork, becoming fabric's single typed wire boundary) + vendor-adapt (hard fork) of apps/server as a new "environment server" that runs UNDER kradle's multi-tenant plane. Topology: kradle (multi-tenant, K8s, org-scoped) ⟷ N environment servers (one per workspace/runner), with t3code's environment descriptor + capability flags as the kradle↔environment boundary contract. The 81 untyped kradle-web routes are progressively replaced/typed against the contracts fork; the gateway's 17-frame protocol is folded into contracts rather than retained as a parallel surface.**
Shape (R4 §B.6, R4 spec inputs 5–8):
1. **Environment-server-under-plane topology**: kradle's agent-dispatch-controller/agent-workspace-controller become environment *clients* dispatching OrchestrationCommands over the contracts RPC surface (t3:packages/contracts/src/orchestration.ts:35-44); the boundary is t3:packages/contracts/src/environment.ts:1-3 (descriptor + capability flags) + environmentHttp.ts HttpApi groups. ACP terminates inside the environment; kradle never speaks it (R4 §B.6) — mirroring t3code, where web/desktop only ever see contracts RPC. 2. **Contracts adoption vs the 81 untyped routes**: kradle-web has **81 untyped .js route files** (measured, R4 §B.1) and fabric's only typed wire slice is the gateway's 151-line zod protocol (fabric:packages/adapters/gateway/src/protocol/v1.ts) vs contracts' 26,979 LOC / 144+8 typed methods (R2 §5). Proposal: adopt the contracts package as a tracked fork, extend it with fabric-only RPC groups (runs/hooks/pairing/org-admin), and map the 17 gateway frames onto contract groups per R4 spec input 6 (session.start/message→dispatchCommand, run.event→subscribeThread, hook.request/decision→pending approvals, pairing.*→pairing grants). Run/thread routes are replaced by contracts RPC; org-admin CRUD routes are typed in place (REST/SSE stays acceptable for admin surfaces, R4 spec input 10) with schemas generated from the same contracts fork. 3. **Approval mapping (binding)**: t3code's pending-approvals projection maps *onto* kradle's 7-action AgentApproval taxonomy (fabric:packages/kradle/core/src/agent-approval-controller.js:15), chained to babysitter signed breakpoints with human trust roots (proven-bridge.ts:92-119). secret-access, write-back, release, escalation have no t3code counterpart and are preserved as fabric extensions of the approval contract (R4 spec input 7). 4. **Journal sovereignty (binding)**: the environment's SQLite event store owns thread/turn projections *inside* an environment; run identity, provenance, and replay stay with the babysitter journal (storage/journal.ts:72-82; kanban reads .a5c/runs, fabric:packages/adapters/gateway/src/kanban/lib/source-discovery.ts:12-34). Any work package letting the environment store become run source-of-truth violates the dossier evidence and this proposal (R4 spec input 8). 5. **Must-survive (R4 §B.4)**: the multi-tenant org plane (org scoping org-scoping.js:5, K8s CR reconcilers, Helm/GKE — the SaaS spine t3code has no notion of), policy engine surfaces, inference/virtual-model routing, gitops/CI-runners/jitsi, journal-derived kanban, defineTask/breakpoint orchestration substrate, trust-core signing families. 6. **Gained (R4 §B.5)**: event-sourced command/decider/projector/reactor core with single-transaction commit and replay-forever discipline (t3:docs/internals/overview.md:56-72); the capability-flag/schema-transform compat doctrine (R2 §18.5) — the direct cure for the 81 untyped routes; checkpoints/turn-diff/restore; PR domain; DPoP auth; terminal; device control; receipts + drainable-worker test patterns.
**Alternatives considered:**
- *Implement-contracts only (adopt the RPC shapes, keep kradle-core as the sole runtime)*: rejected. The value is not just the types — it is the event-sourced core, checkpointing, terminal, DPoP auth and self-update that live in
apps/server(six T3-ONLY subsystem bundles, R4 §B.3); re-implementing them inside kradle-core's controller model is a multi-year rewrite of what already exists at 398.6k LOC (R2 §2). - *Vendor-wholesale: replace kradle with the t3code server*: rejected outright. t3code is single-user-single-machine by design ("one environment = one user's machine", R4 §B.3); the org control plane, policy surfaces, inference routing and GKE deployment are FABRIC-ONLY and are the product (R4 §B.4.1). D2b says replace the *control-surface interfaces*, not the tenant model.
- *Keep the gateway protocol as the canonical surface and skip contracts*: rejected — 151 lines vs 26,979; the gateway frames are the projection ancestor, not the destination, and genty-ui's copied
protocol/v1.tsproves the no-shared-contract approach already produced type-duplication rot (R4 §C.6, R4 spec input 9). R4 flags this recommendation as its one adoption-model inference (R4 CONFIRMED vs INFERRED) — Gate A explicitly ratifies it here.
**Why:** R4 Row B overlap is ~30% with the t3-only side holding whole subsystems fabric lacks and the fabric-only side holding the entire SaaS plane t3code lacks. Graft-under is therefore the only shape that keeps both: t3code's environment server slots beneath kradle exactly where fabric today has an untyped gap between controllers and harness adapters. The capability-flag doctrine also solves fabric's client/environment version-skew problem for free (clients and environments upgrade independently, t3:docs/internals/overview.md:24-44), which D10's "break freely" policy otherwise makes acute.
1.3 `genty` client shells (D2c, D13)
**Decision proposed: vendor-wholesale (hard fork) of apps/web, apps/desktop, and packages/client-runtime, adapted to fabric contracts; retirement of the 7 genty device shells + the desktop scaffold + (after parity) genty/web-app; kradle/web survives as the org-admin surface only, with run/thread UX moving to the adapted web app. Mobile is deferred per D13 — apps/mobile is not adapted now, but nothing in the adopted stack forecloses it (it consumes the same contracts + client-runtime, R2 §11).**
Shape (R4 §C.6, R4 spec inputs 9–10; R1 spec input 7):
1. **Retirement inventory**: the 7 device shells (10–25 source files each, L0, ~0 tests, no CI — R1 §3.3) plus genty/desktop-app (10-file Electron scaffold, never published — R3 §1.5) retire, destroying approximately zero tested functionality (R1 spec input 7). What must be preserved and reproduced: the genty-ui hook API semantics (useRun/useHookRequests — the only tested fabric client surface, fabric:packages/genty/ui/src/gateway.ts:1-8, 18 test files), the approval-UX (hook-request surfacing), the org/observability/journal views (R4 §C.4), and genty/web-app's Playwright e2e as the parity bar before its retirement. 2. **Client runtime**: adopt client-runtime (256 files, connection supervisor, ~30 atom state services, platform/ service interfaces as the shell plug-point — R2 §8). Each kradle-managed environment appears as one entry in the connection registry; kradle acts as catalog *source* — the hosted-web pattern (browser-held catalog, direct connection to each environment, t3:docs/internals/remote.md:28-38) is exactly fabric's multi-tenant topology (R4 §C.6). This single supervisor eliminates the divergent-reconnect bug-class that genty-ui's per-client backoff and kradle-web's hand-rolled EventSource retry (live-updates.jsx:8-30) both re-implement today (R4 §C.5). 3. **Desktop**: apps/desktop's DesktopBackendManager pattern (bundling and spawning a host environment server, R2 §11) becomes fabric's single-node desktop story and directly serves D3 Form A (R4 spec input 10). 4. **Protocol duplication ends**: genty-ui's copied protocol/v1.ts (151 lines mirroring the gateway package) is deleted; one contracts fork is imported by both sides (R4 spec input 9).
**Alternatives considered:**
- *Extract-packages only (client-runtime) and keep genty/web-app as the shell*: rejected. The web-app is a thin Vite shell (R4 §C.1); the product surface fabric lacks — composer, diff rendering, ghostty-wasm terminal, checkpoint UI, settings (~140 files) — lives in
apps/web(318k LOC, R2 §11) above client-runtime. Adopting the runtime without the app forfeits ~80% of Row C's gained value (four T3-ONLY rows, R4 §C.3) and leaves fabric rebuilding a frontend t3code already ships. - *Implement-contracts (rebuild fabric UI against contracts RPC)*: rejected for the same reason at higher cost; also violates D2c's explicit direction ("genty client shells retired in favor of adapted t3code apps").
- *Also adapt
apps/mobilenow*: rejected — D13 defers mobile; 19 of t3code's 23 pnpm patches are mobile-related (R2 §11), making it the highest-toolchain-friction unit for the lowest current value.
**Why:** Row C overlap is ~20% and three of the five SHARED rows are fabric scaffolds against t3code production systems (desktop 10 vs 258 files; web-app thin shell vs 1,258 files — R4 §C.3). This is the component where vendor-wholesale is cheapest and least destructive: fabric-unique surfaces (org-admin, observability, kanban/journal views) live in kradle-web and observer-dashboard, which survive; the retired shells carry no tests (R1 §4.4). The hard-fork posture (not tracked) is justified in §2 — the UI will diverge immediately (org semantics, approval taxonomy, journal views).
1.4 Remote access (D2d, D12)
**Decision proposed: extract-packages for ssh and tailscale (tracked forks, near-verbatim); vendor-adapt (hard fork) of the environment-side cloud/ module and of infra/relay, with two mandatory substitutions: Clerk is replaced by kradle org identity as the relay's identity provider, and relay envelope verification is built on trust-core chains instead of a second PKI. The gateway's short-code pairing is upgraded in place to DPoP-bound pairing grants. The broker-not-proxy trust model is adopted verbatim.**
Shape (R4 Row D, R4 spec input 11; R2 §10, §12, §18.6):
1. **Four routes, one auth**: direct/LAN pairing (DPoP proofs + pairing grants + scoped sessions, t3:apps/server/src/auth/), Tailscale as "an endpoint for ordinary pairing" — not a separate environment type (t3:docs/internals/remote.md:43-45, adopted as-is), SSH bootstrap + port-forward with client-owned lifecycle (t3:packages/ssh, 4,143 LOC), hosted relay (broker mints nothing, sees no session tokens; one-time bootstrap credential bound to the client's DPoP key; cloudflared managed tunnels expose only a validated loopback origin; after bootstrap the relay does not proxy traffic — t3:docs/internals/t3-connect.md:3-33). Every route terminates at the same environment auth (R4 §D.6) — remote access is about reaching the environment's contracts-RPC surface; ACP is untouched. 2. **Substitutions (binding)**: (a) T3 Connect identity is per-user Clerk (R2 §12); the fabric relay scopes environments to kradle orgs (org-scoping.js:5) and authenticates against kradle org identity (R4 §D.4.2). (b) The relay's @noble/curves signing protocol is re-anchored on trust-core key/chain machinery (fabric:packages/trust-core/src/index.ts:1-7) so fabric does not ship two parallel PKIs (R4 §D.4.1). 3. **Migration shim**: gateway pairing.register/consume frames (v1.ts:110-122) + ShortCodeStore (short-code.ts:1-20, an in-memory 8-digit/5-minute toy by comparison — R4 §D.3) occupy the same UX slot and are upgraded to DPoP-bound grants rather than deleted-and-reinvented (R4 §D.4.3). 4. **Operational cost acknowledged**: the relay implies a Cloudflare Worker + Postgres + identity stack (R2 §16); the packaging/roadmap specs must carry its ops story, and the coverage spec carries D12 regardless (the gap is CONFIRMED real: zero ssh/tailscale/relay code in fabric, R1 §3.10).
**Alternatives considered:**
- *Implement-contracts (design fabric's own relay protocol)*: rejected — Row D overlap is ~5%; there is nothing fabric-side to merge with, and the t3-connect trust model is precisely the design fabric should adopt verbatim (R4 §D.5). Greenfield protocol design here is risk without upside.
- *Vendor-wholesale including Clerk*: rejected — introduces a second identity system beside kradle orgs and a consumer-SaaS dependency into an enterprise control plane; contradicts the must-integrate constraints (R4 §D.4).
- *Tailscale/SSH only, defer the hosted relay*: rejected as a *scope* decision — D12 makes hosted remote access a guaranteed coverage-spec gap "regardless of research findings". Sequencing within the roadmap may still stage relay after ssh/tailscale (both are
effect-only-dep extractions, R2 §18.2 — the cheapest units in the whole program).
**Why:** this is pure adoption (R4 spec input 12: "Row D is pure adoption — nothing to merge"). The only genuine decisions are the two substitutions, and both follow from must-survive constraints already in evidence: fabric owns key/chain machinery with human-root semantics, and fabric's tenancy is org-scoped kradle, not per-user Clerk.
1.5 Cross-cutting: packaging-form priority (D3, proposed here for the packaging spec to inherit)
**Decision proposed: Form C (npm SDK publics) first, then Form A (single-node installer/service/self-update), then Form B (chart publication/bundling).** Why: Form C's blocker — no exports maps, unbounded publics (@a5c-ai/babysitter-sdk has zero exports entries and five bins, R3 §1.6) — is a *prerequisite* for D6's re-platforming and should land with D10's major bump (R3 spec input 8); Form A starts from zero but has a complete t3code blueprint to adapt (R3 §2, spec input 6) and is amplified by the adopted desktop app (§1.3.3); Form B already works internally (chart + GKE pipeline, R3 §1.2–1.3) and needs productization (versioning, OCI publication, bundling) rather than construction. Consistent with D11: packaging follows migration + coverage in the roadmap regardless.
---
2. Per-package Effect-TS stance (D5) and fork posture (D9)
2.1 Boundary rules (D5) — proposed as binding for all five specs
Derived from R4 spec input 13 and R2 §15/§18.3:
- **B1 — Plain-TS adapter contract.** The fabric-facing adapter contract (successor of
adapter-types.ts/run-handle.ts) exposes Promise/AsyncIterable only, exactly asRunHandledoes today. No Effect type ever crosses it. - **B2 — Effect inside lanes and forks.** Effect is unrestricted *inside* lane implementations and adopted/forked packages (
effect-acp,effect-codex-app-server, ssh, tailscale, environment server, relay). - **B3 — Effect Schema at the wire boundary only.** The contracts fork is the one place Effect surfaces in kradle-adjacent code; kradle controllers and web routes consume decoded plain objects, never Effect values. (Contracts is the contract *language*, 98% Effect — R2 §2.)
- **B4 — Fabric-core stays Effect-free.** babysitter-sdk, trust-core, kip-sdk, atlas, kradle-core, observer-dashboard do not adopt Effect in this program. The journal/replay correctness debt (§3) is fixed in plain TS; entangling it with an Effect rewrite multiplies risk on the platform's most safety-critical code.
- **B5 — One pinned Effect, centrally owned.** t3code pins
effect@4.0.0-rc.115**with a local patch** pluseffect/unstable/{rpc,sql,process,cli,http}(R2 §15) — a release candidate with unstable namespaces is a fork-tracking liability the spec must own explicitly: single version, single patch-set, one toolchain WP (T-32), no per-package Effect versions. - **B6 — UI stays dumb.** React components remain plain; Effect lives in the atom/data layer, as t3code itself proves viable at 17–21% file penetration (R2 §15).
2.2 Per-package stance table
| Unit (in fabric after adoption) | Origin | D5 Effect stance | D9 fork posture | Why (evidence) |
|---|---|---|---|---|
| contracts fork | t3:packages/contracts | **Adopt** (Effect Schema is the wire language; B3) | **Tracked fork** | Protocol-churny, dep = effect only, capability-flag doctrine must track upstream (R2 §5, §18.2; D9 names it) |
| effect-acp | t3:packages/effect-acp | **Adopt** (100% Effect) | **Tracked fork** | ACP spec churn; mostly regenerable (10.4k of 15.5k LOC generated, R2 §6); dep = effect only |
| effect-codex-app-server | t3:packages/effect-codex-app-server | **Adopt** (100%) | **Tracked fork** | Codex app-server schema churn; 58k of 61.8k LOC generated (R2 §7) |
| ssh | t3:packages/ssh | **Adopt** (100%), plain-TS facade at call sites (B1) | **Tracked fork** | 4.1k LOC, dep = effect only, extractable as-is (R2 §10, §18.2) |
| tailscale | t3:packages/tailscale | **Adopt**, plain-TS facade | **Tracked fork** | 763 LOC, wraps user CLI, secret-scrubbing error taxonomy worth tracking (R2 §10) |
| environment server | t3:apps/server (subset: orchestration, persistence, auth, checkpointing, terminal, provider, cloud) | **Adopt internally** (88% Effect; de-Effecting 398.6k LOC is infeasible); plain-TS seams to journal/trust-core (B1/B4) | **Hard fork** | Fabric grafts org boundary, journal sovereignty, approval mapping, trust gates into it — permanent divergence (R4 §B.4/§B.6); D9 names apps as hard-fork |
| client-runtime | t3:packages/client-runtime | **Quarantine** — Effect in atom/data layer; platform/ interfaces + hook API surface plain (54% today, R2 §8) | **Hard fork** | Connection catalog becomes kradle-sourced; approval UX maps to 7-action taxonomy; state services diverge immediately (R4 §C.6) — upstream pulls would conflict constantly |
| web app | t3:apps/web | **Quarantine** (17% — components plain React; B6) | **Hard fork** | Product UI diverges (org semantics, journal/kanban views); D9 names apps as hard-fork |
| desktop app | t3:apps/desktop | **Quarantine** (66% concentrated in backend manager) | **Hard fork** | Bundles the *fabric* environment server; single-node story (R4 spec input 10) |
| relay | t3:infra/relay | **Adopt** (91%) | **Hard fork** | Clerk→kradle-org identity and noble→trust-core substitutions are structural (§1.4.2) |
| shared (selected modules) | t3:packages/shared | Per-module (42% overall) | **Cherry-pick** (hard-fork of individual modules: nodeSqliteClient, DrainableWorker, relaySigning, cliRelease) | No barrel; subpath modules are independently liftable (R2 §9) |
| install/service/self-update machinery | t3:scripts/*, serviceLauncher.ts, cloud/selfUpdate.ts | n/a (scripts) / Adopt where Effect-based | **Hard fork** | Must integrate with fabric's own release resolver + 43-package train (R3 §1.1, spec inputs 3–4) |
| adapters core (contract + projection) | fabric | **Plain TS** (B1/B4) | n/a (fabric-native) | Contract surface + AgentEvent projection stay Promise/AsyncIterable (R4 spec input 13) |
| babysitter-sdk, trust-core, kip-sdk, atlas, kradle-core, observer-dashboard | fabric | **Plain TS — no Effect adoption** (B4) | n/a | Safety-critical debt fixed in place (§3); no dossier evidence favors rewriting these in Effect |
| kradle-web | fabric | Plain TS; consumes contracts-generated types only (B3) | n/a | Survives as org-admin (R4 spec input 10) |
**Alternatives considered (D5-level):** (a) *De-Effect the extracted packages* — rejected: effect-acp/codex-app-server are built on effect/unstable/rpc; de-Effecting means rewriting, which forfeits tracked-fork regeneration (R2 §6–7). (b) *Adopt Effect across fabric core* — rejected: multiplies risk on the journal/replay cluster (§3) with zero dossier evidence of benefit; t3code itself demonstrates quarantine works (17% web penetration). (c) *Tracked-fork the apps too* — rejected: divergence in server/web/desktop is structural (org plane, journal, approvals), so upstream merges would be permanent conflict; instead, the migration spec includes a periodic upstream-diff review item confined to the five tracked forks.
---
3. Refreshed-audit survivor register (D8) — definitive
R1 §2 re-verified the 2026-09-14 register (C:/work/company/products/platform/PLATFORM-REMEDIATION-AND-RENAME-ROADMAP.md, Appendix A) at fabric HEAD 5e46b998. **Outcome: zero findings fully fixed.** Every register ID survives, either intact (STILL-VALID) or as a stated residual (CHANGED). The verdict tables enumerate **40 IDs — 30 STILL-VALID + 10 CHANGED-with-residual**; R1's headline line says "24 · 10 · 0 of 34 rows", which does not sum against its own tables — the enumerated per-ID verdicts below are authoritative (each carries fresh path:line evidence in R1 §2), and the discrepancy is a dossier arithmetic slip, not a substantive disagreement: under both counts, **the survivor set = the full register**.
This register is absorbed by 20-functionality-coverage.md (and TEST1/TEST2 by 30-testing.md); the absorbing work package is listed per ID. For CHANGED IDs, the WP objective is the residual stated verbatim in R1 §2.
| ID | Verdict | One-line surviving objective | Absorbed by |
|---|---|---|---|
| C1 | STILL-VALID | Verify journal checksums on load (journal.ts:151-161 only parses) | F-01 |
| C2 | STILL-VALID | Sign journal events (trust-core exists; journal bypasses it) | F-02 |
| C3 | STILL-VALID | Attestation anchor default-on + loud journaled "disabled" marker | F-03 |
| H1 | STILL-VALID | Hash-chain events; detect tail truncation | F-01 |
| H2 | STILL-VALID | Invocation keys must digest arg values, not shapes | F-04 |
| H3 | STILL-VALID | Stable task keys under inserted steps (occurrence-index drift) | F-04 |
| H4 | STILL-VALID | Replay key mismatch must not silently re-execute | F-04 |
| H5 | STILL-VALID | Cancellation must kill live processes (journal-only today) | F-05 |
| H6 | STILL-VALID | Enforce configured effect timeouts at dispatch | F-05 |
| H7 | CHANGED | Stop-hook must use marker-precedence session resolution (env still shadows) | F-06 |
| H8 | CHANGED | Cross-process lock for session read-modify-write | F-06 |
| H9 | CHANGED | trust-core chain verifier gains requiredRootKind (human-root only enforced one layer up) | F-08 |
| H10 | CHANGED | Attestation producers default-on (wired but opt-in) | F-03 |
| M1 | STILL-VALID | Cancel-vs-complete race: typed idempotent precedence | F-07 |
| M2 | STILL-VALID | Bounded parallel: preserve undefined results/positions | F-07 |
| M3 | STILL-VALID | Parallel strategies must aggregate sibling errors | F-07 |
| M4 | STILL-VALID | Background commits need incarnation guard | F-07 |
| M5 | STILL-VALID | Hook timeout: SIGKILL escalation, no hang-on-close | F-05 |
| M6 | CHANGED | Cross-reference runState.processId liveness (24h staleness remains for non-terminal runs) | F-06 |
| M7 | STILL-VALID | Per-session discriminator in PID markers | F-06 |
| M8 | STILL-VALID | Policy gates fail closed for uncovered actions | F-03 |
| S1 | STILL-VALID | Scope unhandledRejection capture per run | F-07 |
| S2 | STILL-VALID | resolveAmbientSessionId(undefined) must not be env-first | F-06 |
| S3 | STILL-VALID (INFERRED) | Guard un-keyed same-shape conditional skipping | F-04 |
| S4 | STILL-VALID (INFERRED) | Remove ambiguous stop-hook stale-retry against raw env | F-06 |
| S5 | STILL-VALID | Thread spawning to SDK cancellation | F-05 |
| S6 | STILL-VALID | Canonical-JSON checksum canonicalization | F-01 |
| CAP1 | STILL-VALID | Unify the three-way memory split (kip-sdk / genty JSON / kradle AgentMemory) — force the ADR | F-09 |
| CAP2 | STILL-VALID | Pre-dispatch budget enforcement | F-10 |
| CAP3 | STILL-VALID | Campaigns / scheduler-preemption entities | F-11 |
| CAP4 | STILL-VALID | Improvement outer loop (history→eval→compare→promote) | F-12 |
| CAP5 | CHANGED | Inference scale-to-zero (virtual-model routing landed) | F-13 |
| CAP6 | CHANGED | Wire session pause/resume/fork/rewind into the loop | F-14 |
| KIP-TODO | STILL-VALID | KeyAuthorization chain / manifest CID / durability TODOs (kip-repo.ts:4063-4075) | F-15 |
| TEST1 | CHANGED | Wire remaining ungated suites into CI (kip/atlas/library/shared/kradle-web/…) | Q-01 |
| TEST2 | STILL-VALID | Adversarial ledger tests (recommended, not the D7 bar) | Q-08 |
| HYG1 | CHANGED | Redaction in the general logging layer (observability/logger.ts has none) | F-22 |
| HYG2 | CHANGED | Eliminate wildcard workspace deps; version-pin discipline | P-01/P-02 |
| HYG3 | STILL-VALID | Build-time duplicate-task-id scan | F-23 |
| HYG4 | STILL-VALID | Remove Windows-invalid colon-path blobs (company repo) | F-23 |
---
4. The five specs and their work-package inventories
Numbering: T = 10-t3code-migration, F = 20-functionality-coverage, Q = 30-testing, P = 40-packaging, R = 50-roadmap. Per intent acceptance criterion 3, each WP in the specs will carry ID, objective, affected paths, acceptance criteria, test requirements, dependencies, and S/M/L size; the inventory below fixes IDs and scope so the total is visible at Gate A. Sequencing honors D11 (migration first, coverage second; testing and packaging follow).
4.1 `10-t3code-migration.md` — 33 WPs
Covers, per migrated unit: adoption model, Effect stance, fork posture, license/attribution, ACP-canonical re-platforming (intent acceptance criterion 4).
| ID | Title |
|---|---|
| T-01 | Fork intake: import tracked-fork units, upstream-pin manifest, third-party attribution items (D15, MIT/T3 Tools Inc.) |
| T-02 | Contracts tracked fork: package landing, fabric RPC-group extensions, capability-flag doctrine adoption |
| T-03 | effect-acp tracked fork + schema regeneration pipeline |
| T-04 | effect-codex-app-server tracked fork + regeneration pipeline |
| T-05 | ProviderAdapter-equivalent contract replacing BaseAgentAdapterInterface/RunHandle surface (plain-TS per B1) |
| T-06 | Generic ACP lane runtime + per-harness extension-module pattern |
| T-07 | Cursor ACP lane (retire cursor-adapter.ts codec) |
| T-08 | Grok Build ACP lane — net-new harness (D7(a) requirement) |
| T-09 | Antigravity ACP lane + managed installer (version leases, identity verification) |
| T-10 | Claude SDK lane (in-process query, permission callbacks, history child worker) |
| T-11 | Codex app-server lane (retire websocket/SDK codecs) |
| T-12 | OpenCode HTTP lane (server-per-thread ownership model) |
| T-13 | Retained-subprocess lane migration for the fabric extras (gemini, copilot, pi, oh-my-pi/omp aliasing resolution, openclaw, hermes, droid, amp) — full 22-codec disposition table |
| T-14 | AgentEvent projection layer: normalizer → 49-type union as derived view; consumer acceptance suite |
| T-15 | Observe-lane rebind: 12 hook adapters feed the projection unchanged |
| T-16 | Journal sovereignty enforcement: run identity/provenance stays in the babysitter journal across all lanes |
| T-17 | Trust-signed policy gating wired into drive-lane permission callbacks (no bypass of proven-bridge) |
| T-18 | Fabric-as-ACP-agent: expose runs/genty sessions via the effect-acp agent service (genty lane #16) |
| T-19 | Environment server hard fork: orchestration/persistence/auth/checkpointing/terminal subset landing in fabric |
| T-20 | Kradle↔environment boundary: environment descriptor + capability flags; dispatch/workspace controllers become environment clients |
| T-21 | Gateway fold-in: 17-frame → contracts RPC-group mapping; gateway retired or reduced to shim |
| T-22 | kradle-web route program: type-or-replace the 81 untyped routes against the contracts fork |
| T-23 | Approval mapping: pending-approvals ↔ 7-action AgentApproval ↔ signed breakpoints (preserving fabric-only actions) |
| T-24 | client-runtime hard fork: kradle-sourced connection catalog; genty-ui hook-API parity layer |
| T-25 | Web app hard fork: run/thread UX, composer/diff/terminal, fabric theming and org semantics |
| T-26 | Desktop app hard fork: DesktopBackendManager bundling the fabric environment server |
| T-27 | genty shell retirement: 7 device shells + desktop scaffold + web-app (after Playwright parity) + protocol-copy deletion |
| T-28 | ssh package extraction (tracked fork) |
| T-29 | tailscale package extraction (tracked fork) |
| T-30 | Environment auth: DPoP + pairing grants replacing gateway token auth + short-code pairing |
| T-31 | Relay hard fork: kradle-org identity replacing Clerk; trust-core envelope verification; cloudflared managed tunnels |
| T-32 | Effect toolchain baseline: effect@4-rc pin + patch ownership, npm-workspaces integration, vite-plus divergence resolution, node:sqlite/Node-engine floors |
| T-33 | Provider maintenance adoption: installers/updaters with ownership proofs, usage/quota ingestion, model manifest |
4.2 `20-functionality-coverage.md` — 23 WPs
Absorbs the §3 survivor register (F-01…F-15, F-22, F-23), the D12 guaranteed gap, and the pre-existing gap corpora (R1 §5) by reference.
| ID | Title |
|---|---|
| F-01 | Journal integrity: checksum verification on load, hash chain, canonical JSON (C1, H1, S6) |
| F-02 | Journal event signing via trust-core (C2) |
| F-03 | Attestation default-on posture + fail-closed policy gates (C3, H10, M8) |
| F-04 | Replay key correctness: value digests, stable keys, mismatch detection (H2, H3, H4, S3) |
| F-05 | Execution control: cancellation kills processes, timeout enforcement, SIGKILL escalation (H5, H6, M5, S5) |
| F-06 | Session integrity: marker precedence, cross-process locking, liveness-based cleanup (H7, H8, M6, M7, S2, S4) |
| F-07 | Parallel/async semantics: result alignment, error aggregation, incarnation guards, scoped rejection capture (M1–M4, S1) |
| F-08 | trust-core human-root requirement in the chain verifier (H9) |
| F-09 | Memory unification ADR + implementation: kip-sdk / genty long-term-memory / kradle AgentMemory (CAP1) |
| F-10 | Pre-dispatch budget enforcement (CAP2) |
| F-11 | Campaigns and scheduler-preemption entities (CAP3) |
| F-12 | Improvement outer loop: history→eval→compare→promote (CAP4) |
| F-13 | Inference scale-to-zero (CAP5 residual) |
| F-14 | Session pause/resume/fork/rewind wired into the agent loop (CAP6) |
| F-15 | KIP security completion: KeyAuthorization chain, manifest CID, durability tiers (KIP-TODO) |
| F-16 | Hosted remote access coverage (D12 — guaranteed): four-route story, cross-ref T-28…T-31 |
| F-17 | Commander disposition: wire to live gateway/kradle per SPEC-LIVE-BACKEND or descope formally |
| F-18 | Harness matrix remediation: Cursor (#562), OpenCode, Antigravity (#945) red lanes to green; Grok coverage (with T-08) |
| F-19 | Agent-layer gap absorption: the 47 docs/agent-layer-gaps.md items by category (streaming, multi-turn history, token usage, …) |
| F-20 | Hardcoded-literals→atlas graph backlog (~201 literals) |
| F-21 | Realtime media plane: control-plane-real/media-stub closure per docs/research/realtime-agent-gaps.md |
| F-22 | Secret redaction in the general logging layer (HYG1 residual) |
| F-23 | Hygiene closure: duplicate-task-id CI scan, company-repo colon paths (HYG3, HYG4) |
4.3 `30-testing.md` — 9 WPs
Bar per D7: (a) live per-harness e2e for six harnesses, (b) whole-platform e2e, (c) unit floors + CI gating. Baseline: MATURITY-MATRIX.md refreshed by R1 §4.
| ID | Title |
|---|---|
| Q-01 | CI gating of ungated suites: kip-sdk (114 files), atlas (31), genty-runtime/cli/ui (47), kradle-web (30), adapters-tools, commander, test:library/test:shared (TEST1 residual) |
| Q-02 | Zero-test package floors: adapters-config, adapters-launch, kradle-sdk, kradle-cli; fill multi-execution.ts (0 lines) |
| Q-03 | Live per-harness e2e matrix to D7(a): six harnesses green incl. new Grok lane |
| Q-04 | Whole-platform e2e: packaged install → create run → dispatch → agent session → journal → UI assertions (D7(b) — no such lane exists) |
| Q-05 | UI e2e gating: observer-dashboard Playwright, kradle-web specs, commander suite into CI |
| Q-06 | Unit floors + coverage gates per package, agreed floors wired into ci.yml/publish.yml job map (D7(c)) |
| Q-07 | t3code test-pattern adoption: runtime receipts + DrainableWorker instead of sleeps; ACP mock agent for protocol suites |
| Q-08 | Adversarial ledger suite — recommended, explicitly outside the D7 bar (TEST2) |
| Q-09 | Migration parity suites: AgentEvent projection golden tests; gateway-frame↔contracts-RPC equivalence; genty-ui hook-API parity |
4.4 `40-packaging.md` — 13 WPs
Priorities per §1.5 proposal: C → A → B; all three forms bind (D3).
| ID | Title |
|---|---|
| P-01 | Exports-map program across the 43 publishables + babysitter bin-collision resolution (Form C prerequisite; lands with D10 major bump) |
| P-02 | Versioning discipline: wire-or-remove changesets; per-package semver signal atop the lockstep train; HYG2 wildcard-dep elimination |
| P-03 | Single-executable server build (SEA) + self-contained per-platform archives + SHA256SUMS release flow |
| P-04 | install.sh / install.ps1: channel-aware, checksum-verified, versioned runtime layout |
| P-05 | Background service: systemd-user + linger, launchd; reconciling service install; Windows explicitly out of service scope |
| P-06 | Self-update: launcher-owned two-phase commit with SQLite snapshot rollback |
| P-07 | npm platform packages + launcher so npm bytes equal release bytes (npx zero-install trial) |
| P-08 | OS package managers (winget/brew/AUR/deb) + uninstall story |
| P-09 | Helm chart productization: version-with-platform, OCI publication, fold atlas-webui overlay + CRDs + Envoy story into one installable bundle |
| P-10 | kradle-installer alignment: consume the published chart, decouple from CI flags and repo paths |
| P-11 | Release trains: stable/nightly/preview with nightly-promotion, mapped onto the existing single version resolver + tag discipline |
| P-12 | Third-party license/attribution machinery (D15): adopt third-party-licenses.config.json + sync script; cover all adopted units |
| P-13 | Artifact-home decision: public babysitter vs private fabric for GitHub-Release binaries and OCI charts (split-repo constraint) |
4.5 `50-roadmap-workpackages.md` — 3 WPs
| ID | Title |
|---|---|
| R-01 | Dependency graph + critical path over all WPs, sequenced per D11 (migration → coverage → testing → packaging) |
| R-02 | Milestone/release-train mapping incl. the D10 major-bump cutover point and tracked-fork upstream-review cadence |
| R-03 | Gate-B compliance matrix: every WP and spec section traced against D1–D16 verbatim |
4.6 Total
**33 + 23 + 9 + 13 + 3 = 81 planned work packages.** (If T-13 resolves oh-my-pi/omp as one harness, the inventory count is unchanged — T-13 is a single WP containing the disposition table.)
---
5. Risks and open points for the Gate A conversation
1. **Effect 4 release-candidate exposure** (highest technical risk): 4.0.0-rc.115 + local patch + five unstable namespaces (R2 §15). Mitigation is structural (B5: single pin, single owner, T-32) but the rc-to-stable transition cost is unknowable today. 2. **Toolchain divergence**: extracting the five tracked-fork packages avoids pnpm-catalogs/vite-plus/TS7 entirely (they build with plain tsc, R2 §18.12); the three hard-forked apps do not — T-32 must decide adopt-vs-replatform per app before T-19/T-25/T-26 start. 3. **Node floors**: node:sqlite needs ≥22.5, SEA build hosts need ≥25.7 (R2 §15, R3 spec input 5) — packaging and CI matrices must encode both. 4. **Relay ops stack**: Cloudflare Worker + Postgres + identity is a new operational surface (R2 §16); staging it after ssh/tailscale (both trivial extractions) is the low-risk order inside T-28…T-31 — D12 coverage is guaranteed by F-16 either way. 5. **R1 arithmetic slip** (§3): the survivor register is authoritative at 40 IDs; if Gate A prefers, R1's headline line can be corrected in place before Gate B. 6. **INFERRED items ratified here**: the contracts-over-gateway recommendation (R4 flagged it as inference; §1.2 alternative 3 adopts it) and the overlap percentages used only for sizing narrative, never as acceptance criteria.