Agentic AI Atlasby a5c.ai
OverviewWikiGraphFor AgentsEdgesSearchWorkspace
/
GitHubDocsDiscord
iiRecord
Agentic AI Atlas · Spec 10 — t3code migration (WP-T3-*)
page:docs-specs-platform-gaps-10-t3code-migrationa5c.ai
Search record views/
Record · tabs

Available views

II.Record viewspp. 1 - 1
overviewarticlejsongraph
III.Related pagespp. 1 - 1
II.
Page reference

page:docs-specs-platform-gaps-10-t3code-migration

Reading · 54 min

Spec 10 — t3code migration (WP-T3-*) reference

Date: 2026-09-27 · Status: Gate-B draft · Binding decisions: D1, D2, D5, D6, D9, D10, D13, D15 and amendment D17–D21 (docs/specs/platform-gaps/00-intent.md:19-46).

Pagewiki/docs/specs/platform-gaps/10-t3code-migration.mdOutgoing · 0Incoming · 1

Spec 10 — t3code migration (WP-T3-*)

Date: 2026-09-27 · Status: Gate-B draft · Binding decisions: **D1, D2, D5, D6, D9, D10, D13, D15** and amendment **D17–D21** (docs/specs/platform-gaps/00-intent.md:19-46).

Inputs consumed in full: the Gate-A-approved adoption proposal research/synthesis-adoption-proposal.md (per-component decisions §1, boundary rules B1–B6 §2.1, per-package stance table §2.2, the planned 33-WP inventory §4.1); dossiers R1 research/fabric-current-state.md, R2 research/t3code-architecture.md, R3 research/packaging-state.md, R4 research/delta-map.md; and spec 15 15-private-isolation-rename.md, whose **§3.3 name matrix is this spec's naming source of truth** (D21, WP-RN-08). Citations: fabric: paths relative to C:/work/fabric at HEAD 5e46b998e; t3: paths relative to the MIT t3code snapshot at C:/Users/tmusk/AppData/Local/Temp/claude/C--work-company/368e0399-fd11-4960-8b4d-b4dcf1d79c43/scratchpad/t3code.

**ID convention.** Work packages here are WP-T3-01 … WP-T3-33. The short form T-<n> used by the Gate-A proposal and by specs 15/20/30/40/50 refers to the same packages one-to-one (T-02 ≡ WP-T3-02, etc.). The count matches the proposal's planned 33 (synthesis-adoption-proposal.md §4.1); no WPs were added or removed — the two adjustments made against the proposal are internal to existing WPs and justified in §3.2 (oh-my-pi/omp aliasing resolved: one harness, not two) and §3.4 (the codec disposition table covers 22 codec files as measured at HEAD, including four files the dossiers did not characterize: babysitter, adapters-remote, claude-remote-control, pi-sdk, plus the qwen codec).

---

1. Scope, invariants, non-goals

In scope (D2, all four surfaces): (a) the adapters harness-driving layer re-platformed onto ACP-canonical lanes (D6); (b) kradle control-surface interfaces aligned to the t3code contracts/environment model; (c) genty client shells retired in favor of adapted t3code server/web/desktop apps + client-runtime; (d) the remote-access stack (ssh/tailscale/hosted relay).

Binding invariants:

1. **Public repo untouched (D17).** No WP in this spec reads from, writes to, renames, or republishes anything in public a5c-ai/babysitter. All work lands fabric-only. Upstream intake of t3code snapshots is governed by WP-T3-01; upstream intake of public-babysitter fixes is spec 15 §1.4 and out of scope here. 2. **No double rename (D21, spec 15 interaction rule 1).** Every migrated unit lands directly under its 15-private-isolation-rename.md §3.3 name, scope @fabricstack, directory, and bin — never under a @t3code/*, t3-*, or @a5c-ai/* name, even transiently. The WP-RN-08 CI gate enforces this mechanically and blocks WP-T3-01. 3. **Registry (D19).** Every new package's publishConfig.registry is the GCP Artifact Registry npm URL (spec 15 §4.1); guards G1–G6 (spec 15 §4.3) apply from the first landed commit. 4. **Later rename phases do not block migration (spec 15 interaction rule 3).** WPs below reference existing fabric code by its **current** paths/names (packages/adapters/..., .a5c/, KRADLE_*); RN-2/RN-3 sweeps rename migrated units together with the rest of the tree. New units use §3.3 names from birth. 5. **Mobile deferred (D13).** t3:apps/mobile is not adapted. Nothing below forecloses it: the adopted stack (contracts + client-runtime) is exactly what mobile consumes upstream (R2 §11), and 19 of t3code's 23 pnpm patches are mobile-only friction this program never imports (R2 §11). 6. **Break freely (D10).** No compatibility shims anywhere. Every in-repo consumer of a broken API is migrated inside the same WP or an explicitly-dependent WP (§7 inventory). The major version bump lands with RN-1/P-01 in one train (spec 15 §5 interaction rule 6). 7. **No implementation in this run (D4).** This document specifies; implementation is later babysitter runs executing the WPs.

Non-goals: public-facing branding (D14); functionality-coverage debt (spec 20 — e.g. journal checksum verification C1/F-01 is *referenced* by the journal-sovereignty rule but *fixed* by F-01); testing floors (spec 30); packaging forms (spec 40, though §2 rows note where a unit's landing is owned there).

---

2. Per-unit adoption matrix (D1/D5/D9/D15/D21)

This table is the intent's acceptance-criterion-4 artifact: per migrated unit — adoption model, Effect stance, fork posture, license/attribution, target location under the new private name.

#Unit (t3code origin)Adoption model (D1)Effect stance (D5, §2.1 rule)Fork posture (D9)License/attribution (D15)Lands as (spec 15 §3.3)WP
1t3:packages/contracts (74 modules, 26,979 LOC, 98% Effect — R2 §5)Extract-packages; extended with fabric RPC groups**Adopt** — Effect Schema is the wire language, surfaces only at the wire boundary (B3)**Tracked fork** (protocol-churny; capability-flag doctrine tracks upstream — R2 §18.5)MIT notice + upstream pin; row in third-party-licenses.config.json@fabricstack/contracts · packages/contractsWP-T3-02
2t3:packages/effect-acp (15,546 LOC, 10,375 generated — R2 §6)Extract-packages**Adopt** (100% Effect, B2)**Tracked fork** + schema regeneration pipelinesame@fabricstack/acp · packages/acpWP-T3-03
3t3:packages/effect-codex-app-server (61,816 LOC, 58,004 generated — R2 §7)Extract-packages**Adopt** (100%, B2)**Tracked fork** + regeneration pipelinesame@fabricstack/codex-protocol · packages/codex-protocolWP-T3-04
4t3:packages/ssh (4,143 LOC — R2 §10)Extract-packages, near-verbatim**Adopt** (100%, B2); plain-TS facade at call sites (B1)**Tracked fork**same@fabricstack/ssh · packages/sshWP-T3-28
5t3:packages/tailscale (763 LOC — R2 §10)Extract-packages, near-verbatim**Adopt** (B2); plain-TS facade (B1)**Tracked fork**same@fabricstack/tailscale · packages/tailscaleWP-T3-29
6t3:apps/server subset: orchestration/ persistence/ auth/ checkpointing/ terminal/ provider/ cloud/ vcs/ git/ sourceControl/ project/ usage/ textGeneration/ mcp/ resourceTelemetry/ (R2 §3)Vendor-adapt as the **environment server** under kradle's plane**Adopt internally** (88% Effect; de-Effecting 398.6k LOC infeasible — R2 §2); plain-TS seams to journal/trust-core (B1/B4)**Hard fork** (org boundary, journal sovereignty, approval mapping, trust gates are permanent divergence — R4 §B.4/§B.6)same; per-file provenance headers kept@fabricstack/environment · apps/environment · bin environment-serverWP-T3-19 (auth: WP-T3-30; provider lanes: WP-T3-06…13; cloud: WP-T3-31)
7t3:packages/client-runtime (256 files, 65,846 LOC, 54% Effect — R2 §8)Vendor-adapt**Quarantine** — Effect in atom/data layer; platform/ interfaces + hook API surface plain (B1/B6)**Hard fork** (kradle-sourced catalog, 7-action approval UX diverge immediately — R4 §C.6)same@fabricstack/client-runtime · packages/client-runtimeWP-T3-24
8t3:apps/web (1,258 files, 318,401 LOC, 17% Effect — R2 §11)Vendor-wholesale, adapted**Quarantine** (components plain React, B6)**Hard fork** (D9 names apps)same@fabricstack/console-web (private) · apps/console-webWP-T3-25
9t3:apps/desktop (258 files, 81,239 LOC, 66% Effect — R2 §11)Vendor-wholesale, adapted**Quarantine** (Effect concentrated in backend manager, B2/B6)**Hard fork**same@fabricstack/console-desktop (private) · apps/console-desktopWP-T3-26
10t3:infra/relay (78 files, 27,381 LOC, 91% Effect — R2 §12)Vendor-adapt with two mandatory substitutions (Clerk→kradle org identity; noble-PKI→trust-core envelopes)**Adopt** (B2)**Hard fork** (substitutions are structural)same@fabricstack/relay (private) · infra/relayWP-T3-31
11t3:packages/shared selected modules: nodeSqliteClient, DrainableWorker, relaySigning/relayClient, cliRelease (R2 §9)**Cherry-pick** individual subpath modulesPer module (B2 where Effect)Hard fork of individual modulessame (module-level provenance headers)**No new package minted** — modules land inside their adopters: apps/environment/src/shared/, infra/relay/src/shared/, packages/client-runtime/src/shared/ (keeps spec 15 §3 closed under its own matrix)WP-T3-19/24/31
12Install/service/self-update machinery (t3:scripts/install.sh, serviceLauncher.ts, cloud/selfUpdate.ts — R2 §14)Vendor-adaptAdopt where Effect-basedHard forksameLanding owned by **spec 40** (P-03…P-08); this spec only lands cloud/selfUpdate.ts as part of unit 6 and hands the rest over(spec 40)
13Provider maintenance: installers/updaters with ownership proofs, usage/quota ingestion, model-manifest.json (t3:apps/server/src/provider/providerMaintenance.ts, usage/ — R2 §4)Vendor-adapt inside the harness layerAdopt inside lanes (B2)Hard fork (rides unit 6's tree)sameinside packages/harness/* lane implementations and apps/environmentWP-T3-33
14Fabric-native successor surfaces (adapter contract + projection)Implement-contracts (fabric-authored)**Plain TS** (B1/B4)n/a — fabric-nativen/acurrent packages/adapters/core (renamed to packages/harness/core by RN-3, spec 15 §3.1 row 10)WP-T3-05, WP-T3-14

Excluded from adoption, permanently or for this program: t3:apps/mobile (D13); t3:apps/marketing; t3:apps/server/src/{pullRequest,device,preview,desktopUpdate} and t3:native/{browser-secret,hyprland-snap-shot,kde-snap-shot} (pruned at WP-T3-19 landing; recoverable later from the WP-T3-01 import snapshot without re-import); t3:.repos/* vendored references (never imported upstream either — R2 §2); Clerk and every Clerk-dependent path (substituted per row 10); oxlint-plugin-t3code, vite-plus, TS7/tsgo toolchain (re-platformed instead — WP-T3-32). native/libghostty-vt + native/resource-monitor ride WP-T3-25/WP-T3-19 respectively as vendored assets (see those WPs).

2.1 Effect boundary rules (D5) — binding, restated from the approved proposal

The Gate-A rules synthesis-adoption-proposal.md §2.1 apply verbatim to every WP below:

  • **B1** — the fabric-facing adapter contract exposes Promise/AsyncIterable only, as RunHandle does today (fabric:packages/adapters/core/src/run-handle.ts:150). No Effect type crosses it.
  • **B2** — Effect is unrestricted inside lane implementations and adopted/forked packages.
  • **B3** — Effect Schema surfaces only at the wire boundary (the contracts fork); kradle controllers and web routes consume decoded plain objects.
  • **B4** — fabric core (babysitter-sdk, trust-core, kip-sdk, atlas, kradle-core, observer-dashboard) adopts no Effect in this program.
  • **B5** — one pinned Effect (effect@4.0.0-rc.115 + the single local patch, t3:patches/effect@4.0.0-rc.115.patch — R2 §2), centrally owned by WP-T3-32; no per-package Effect versions.
  • **B6** — UI components stay plain React; Effect lives in the atom/data layer (proven viable at 17–21% penetration — R2 §15).

Every WP whose acceptance criteria mention a "boundary check" means: a CI lint/architecture rule (extending the existing architecture boundary gate, fabric:.github/workflows/ci.yml:114-117) asserting no import ... from "effect" (or effect/*) in the files the rule names as plain-TS.

2.2 Fork-posture mechanics

  • **Tracked fork** (units 1–5): WP-T3-01 lands each with an UPSTREAM.json at the package root recording {upstream repo URL, snapshot commit SHA, snapshot date, local-divergence log}. Divergence is allowed but every divergent hunk is listed. A quarterly upstream-diff review item (recorded per package in UPSTREAM.json) re-pulls the upstream package, regenerates schemas (units 2–3), and cherry-picks protocol updates. Tracked forks build with plain tsc and have effect as their only runtime dep (R2 §18.2, §18.12) — no toolchain import.
  • **Hard fork** (units 6–13): one-time import, attribution preserved, **no** upstream tracking obligation; upstream divergence is expected and undocumented beyond the initial UPSTREAM.json pin.
  • **Cherry-pick** (unit 11): module files copied with a provenance header (// Adapted from t3code <path> @ <sha>, MIT © 2026 T3 Tools Inc.); no package-level tracking.

2.3 License and attribution (D15)

t3code is MIT, © 2026 T3 Tools Inc. (t3:LICENSE; intent D15). Binding attribution work, distributed across WPs and centralized in WP-T3-01:

1. Every landed unit carries the upstream MIT license text in a LICENSE-THIRD-PARTY (tracked forks) or an entry in the repo-level third-party notice file (hard forks/cherry-picks). 2. Fabric adopts t3code's own attribution machinery: t3:third-party-licenses.config.json + t3:scripts/sync-third-party-license-notices.ts (R2 §14), landed by WP-T3-01 and extended by spec 40's P-12 to cover all adopted units; the config gains one entry per §2 row. 3. Generated files (units 2–3) keep their generator provenance banners so regeneration does not orphan attribution. 4. No copyright headers are stripped; adapted files get the §2.2 provenance header **added**, never substituted.

---

3. The ACP-canonical adapters re-platforming (D6)

3.1 Contract: one `ProviderAdapter`-equivalent, plain TS, five lanes

D6 makes ACP fabric's canonical harness protocol and demotes the current adapters event model to an internal projection. The concrete shape, fixed by evidence (R4 §A.6, R2 §18.1):

1. **ACP lane** (WP-T3-06): generic runtime + per-harness extension modules, adapted from t3:apps/server/src/provider/acp/{AcpSessionRuntime,AcpAdapterSupport,AcpCoreRuntimeEvents,AcpRuntimeModel,AcpStderr}.ts with extensions in the CursorAcpExtension/XAiAcpExtension pattern (R2 §4), speaking ACP through @fabricstack/acp's client side. 2. **Claude SDK lane** (WP-T3-10): @anthropic-ai/claude-agent-sdk in-process (t3:apps/server/src/provider/Layers/ClaudeAdapter.ts:5-27), history/fork in a child worker (t3:apps/server/src/claudeHistoryWorker.ts:1-11). 3. **Codex app-server lane** (WP-T3-11): codex app-server JSON-RPC stdio (t3:apps/server/src/provider/Layers/codexLaunchArgs.ts:13), typed by @fabricstack/codex-protocol. 4. **OpenCode HTTP lane** (WP-T3-12): server-per-thread via @opencode-ai/sdk/v2 (t3:apps/server/src/provider/Layers/OpenCodeAdapter.ts:32; rationale t3:docs/internals/providers.md:14-22). 5. **Retained-subprocess lane** (WP-T3-13, fabric-only): the surviving codec adapters for harnesses t3code does not cover, migrated behind the new contract.

  • **The contract** (WP-T3-05) succeeds BaseAgentAdapterInterface (fabric:packages/adapters/core/src/adapter-types.ts:24, kinds at :79,:93,:168) and RunHandle (fabric:packages/adapters/core/src/run-handle.ts:150), modeled on t3:apps/server/src/provider/Services/ProviderAdapter.ts:29-56: typed capability declarations (sessionModelSwitch, promptlessTurnContinuation, supportsConversationRollback — ProviderAdapter.ts:46-56), compaction semantics (native vs slash-command, :36-44), turn dispatch, drive-side permission callbacks, auth detection, session-file parsing (fabric is broader here and keeps its surface — R4 §A.3). It is **plain TS** (B1): Promise/AsyncIterable, no Effect exports. Deferred-prompt steering (run-handle.ts:44-51) is preserved as a contract capability.
  • **Five lanes** behind that one contract:
  • Plus the **observe lane** (WP-T3-15): the 12 hook adapters (fabric:packages/adapters/hooks/adapter-{antigravity,claude,codex,copilot,cursor,gemini,genty,hermes,oh-my-pi,openclaw,opencode,pi} — R1 §3.1) survive unchanged in role, re-bound to feed the same projection. t3code has no observe mode (R4 §A.3); this is a fabric-only plane and is **not** retired by anything below.

3.2 Lane decision for all 16 harness rows (15 distinct harnesses + 1 codec-only addition)

The Gate-A table is adopted with the aliasing question **resolved from code**: the oh-my-pi hook adapter and the omp codec/live-stack id are the **same harness** — the hook adapter's own tests key sessions on OMP_SESSION_ID and omp- prefixes (fabric:packages/adapters/hooks/adapter-oh-my-pi/src/__tests__/session-resolver.test.ts:8,28,40,134), the codec registers factory id omp (fabric:packages/adapters/codecs/src/omp-adapter.ts:248-249), and the live-stack agent map carries a single omp entry (fabric:.github/workflows/live-stack.yml:169). Rows 10–11 therefore collapse to one harness (15 distinct); the WP-T3-13 disposition table records the resolution.

#HarnessToday in fabricLane (binding)Evidence
1Claude Codecodec claude-agent-sdk-adapter.ts + claude-adapter.ts + hook adapter; live-stack GREEN (R1 §4.3)**Claude SDK lane**t3:apps/server/src/provider/Layers/ClaudeAdapter.ts:5-27
2Codexcodecs codex-adapter.ts/codex-sdk-adapter.ts/codex-websocket-adapter.ts + hook adapter; GREEN**Codex app-server lane**t3:apps/server/src/provider/Layers/codexLaunchArgs.ts:13; R2 §7
3Cursorcodec cursor-adapter.ts + hook adapter; lane failing (#562, R1 §4.3)**ACP lane**cursor-agent … acp (t3:apps/server/src/provider/acp/CursorAcpSupport.ts:56-60)
4Grok Build**nothing** (no adapter, no lane — R1 §3.1)**ACP lane — net-new build** (mandatory for D7(a))grok --permission-mode <m> agent stdio (t3:apps/server/src/provider/acp/GrokAcpSupport.ts:33-41)
5OpenCodecodecs opencode-adapter.ts/opencode-http-adapter.ts + hook adapter; lane skipped/failing**OpenCode HTTP lane**t3:docs/internals/providers.md:14-22
6Antigravityhook adapter; lane failing (#945)**ACP lane + managed installer**identity check agentInfo.name === "antigravity-acp", protocolVersion 1 (t3:apps/server/src/provider/AntigravityInstallation.ts:484-502); revert-rejection rule (R2 §3.4)
7Gemini CLIcodec + hook adapter**Retained-subprocess** (re-evaluate for ACP promotion post-migration; no ACP evidence in dossiers)R1 §3.1
8Copilot CLIcodec + hook adapter**Retained-subprocess**R1 §3.1
9Picodecs pi-adapter.ts + pi-sdk-adapter.ts (programmatic) + hook adapter; live-stack push default**Retained-subprocess** (both codecs)R1 §4.3
10–11Oh-My-Pi ≡ OMP (one harness, resolved above)hook adapter adapter-oh-my-pi + codec omp-adapter.ts + live-stack id omp**Retained-subprocess**session-resolver.test.ts:8,40; omp-adapter.ts:248-249; live-stack.yml:169
12OpenClawcodec + hook adapter**Retained-subprocess**R4 §A.3 (no t3code counterpart)
13Hermescodec + hook adapter**Retained-subprocess**R1 §3.1
14Droidcodec + live-stack lane, no hook adapter**Retained-subprocess**R1 §4.3 vs §3.1
15Ampcodec + live-stack lane, no hook adapter**Retained-subprocess**R1 §4.3
16Genty (fabric's own runtime)codec + hook adapter + runtime-cli lane**ACP-agent lane**: genty exposed *as* an ACP agent via @fabricstack/acp's agent service, then driven through the standard ACP lanet3:packages/effect-acp/src/agent.ts:31; R4 spec input 4
+1Qwen (codec-only, found at HEAD; absent from all dossier inventories)codec qwen-adapter.ts, no hook adapter, no live-stack lane**Retained-subprocess** (no live-stack obligation added)fabric:packages/adapters/codecs/src/qwen-adapter.ts (dir listing at HEAD)

3.3 Projection direction (D6, binding)

ACP session/update notifications and bespoke-lane events → normalizer (pattern: t3:apps/server/src/orchestration/Normalizer.ts, R2 §3.1) → the **67-member** AgentEvent union (all members extend BaseEvent — 49 defined in events.ts plus 18 in events-control.ts; the research dossier's 49 counted only events.ts) (fabric:packages/adapters/core/src/events.ts:411) as **derived view**. Existing consumers keep compiling and become the projection's acceptance suite (WP-T3-14):

  • RunHandle iteration/emitter/thenable semantics (run-handle.ts:1-8,150);
  • gateway run.event fan-out (fabric:packages/adapters/gateway/src/runs/manager.ts:103-110);
  • journal binding (fabric:packages/babysitter-sdk/src/storage/journal.ts:72-82; hook→session→run resolution fabric:packages/babysitter-sdk/src/harness/hooks/stopHookHandler.ts:209-225);
  • cost records (run-handle.ts:9,21-27) and the model-proxy attestation seam (fabric:packages/adapters/transport/src/server.ts:1596-1607).

The inverse direction is forbidden: no WP may make the 67-member union the source of truth with ACP as "one more codec" (the rejected alternative, synthesis-adoption-proposal.md §1.1).

3.4 Fabric-unique planes preserved (binding, R4 §A.4)

1. **Journal/run binding** — every lane terminates in the babysitter journal (§4.4 rule). 2. **Observe lane** — all 12 hook adapters survive (§3.1). 3. **Trust-signed gates** — fabric:packages/adapters/policy/src/proven-bridge.ts:92-119 (human-root chain) gates the new drive-side permission callbacks; never bypassed by them (WP-T3-17). 4. **Cost + attestation seam** — projection consumers (§3.3). 5. **Atlas graph coupling** — every hooks adapter depends on atlas (R1 §3.6); lane implementations keep deriving harness metadata from the graph, and the ~201-literal backlog (fabric:docs/hard-coded-and-should-be-in-graph-gaps-backlog.md) is not worsened: new lanes introduce no new hardcoded harness literals (checked in each lane WP). 6. **7-action approval taxonomy superset** — preserved via the approval mapping (§4.3, WP-T3-23).

The full 22-file codec disposition table is the WP-T3-13 deliverable; its terminal states are fixed here: retire (cursor, claude-agent-sdk, claude-adapter, claude-remote-control, codex, codex-sdk, codex-websocket, opencode, opencode-http — each inside its replacing lane WP after live-stack parity), retain-behind-contract (gemini, copilot, pi, pi-sdk, omp, openclaw, hermes, droid, amp, qwen, babysitter, adapters-remote), infrastructure superseded (base-adapter.ts retired when the last codec migrates to the WP-T3-05 contract).

---

4. kradle control-surface alignment (D2b)

4.1 Topology: environment server under the multi-tenant plane

Adopted per Gate A (synthesis-adoption-proposal.md §1.2): kradle (multi-tenant, K8s, org-scoped — fabric:packages/kradle/core/src/org-scoping.js:5) ⟷ N environment servers (one per workspace/runner). Kradle's agent-dispatch-controller/agent-workspace-controller become environment **clients** dispatching OrchestrationCommands over contracts RPC (t3:packages/contracts/src/orchestration.ts:35-44). The kradle↔environment boundary contract is the environment descriptor + capability flags (t3:packages/contracts/src/environment.ts:1-3) + the 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.

4.2 Contracts adoption over the 81 untyped routes

kradle-web has 81 untyped .js route files (measured — R4 §B.1) against contracts' 144 Rpc.make definitions + 8 orchestration methods (the 139-entry WS_METHODS map — t3:packages/contracts/src/rpc.ts:277,1394; orchestration.ts:35-44). Program (WP-T3-21/22):

  • **Run/thread/session surfaces**: replaced by contracts RPC against environments (the gateway fold-in, §4.5).
  • **Org-admin CRUD** (orgs/[org]/{policies,policy-exception-requests,policy-reports,secrets,webhooks,inference,pipelines,profile,repositories,resources,views,workspaces,artifacts,assistant,external,hooks,jitsi,search,snapshot,agents} + auth/*, atlas/search, git-proxy, and the SSE watch route fabric:packages/kradle/web/app/api/watch/[[...resource]]/route.js:1-20): typed **in place** — REST/SSE stays acceptable for admin surfaces (R4 spec input 10) — with request/response schemas defined in fabric-only RPC/HTTP groups added to the contracts fork, so there is exactly one schema source (B3: routes consume decoded plain objects).
  • The capability-flag/schema-transform compat doctrine (t3:docs/internals/overview.md:24-44; legacy-field transform example orchestration.ts:60-74) is adopted as the versioning discipline for the new boundary — the structural cure for the untyped-route class and for D10's client/environment version skew.

4.3 Approval mapping (binding table, WP-T3-23)

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):

kradle gate actiont3code counterpartMapping rule
tool-usedrive-side permission requests: Claude CanUseTool, ACP permission modes, ProviderApprovalDecision (R2 §4, §5)bidirectional: lane permission callback → pending approval → AgentApproval(tool-use) → decision → callback resolution; decision evidence signed via proven-bridge
reviewproposed-plans projection + approval policies (t3:packages/contracts/src/orchestration.ts, R2 §5)t3code plan approvals surface as review gates
ai-reviewnone**fabric extension, preserved**
secret-accessnone**fabric extension, preserved**
write-backnone**fabric extension, preserved**
releasenone**fabric extension, preserved**
escalationnone**fabric extension, preserved**

The approval contract extension (fabric RPC group in the contracts fork) types all seven; the four/five t3code-blind actions flow through the same pending-approvals plumbing as first-class variants, not stringly-typed extras.

4.4 Journal sovereignty rule (binding on every WP)

The environment's SQLite event store (t3:packages/shared/src/nodeSqliteClient.ts:1-7; t3:apps/server/src/persistence/Layers/Sqlite.ts:6,37) owns **thread/turn projections inside an environment**. Run identity, provenance, and replay stay with the babysitter journal (fabric:packages/babysitter-sdk/src/storage/journal.ts:72-82); the kanban read model keeps deriving from .a5c/runs journal directories (fabric:packages/adapters/gateway/src/kanban/lib/source-discovery.ts:12-34). **Any WP that lets the environment store become run source-of-truth violates this spec** (R4 spec input 8). WP-T3-16 makes the rule mechanical.

4.5 Gateway fold-in (17 frames → contracts)

The gateway's zod protocol v1 (fabric:packages/adapters/gateway/src/protocol/v1.ts, 151 lines, union at :151) is the projection ancestor, not the destination (Gate-A ratified — synthesis-adoption-proposal.md §1.2 alternative 3). Mapping (WP-T3-21):

Gateway frame (v1.ts)Contracts destination
auth (:6)environment auth handshake: DPoP-bound session (WP-T3-30), not a frame
hello (:11)environment descriptor + capability flags (t3:packages/contracts/src/environment.ts:1-3)
subscribe (:26)subscribeThread/subscribeShell (orchestration.ts:35-44)
session.start (:47)dispatchCommand (thread-start command)
session.message (:61)dispatchCommand (user-message command)
run.event (:79)subscribeThread stream carrying the AgentEvent projection payloads (§3.3)
hook.request (:87)pending-approvals projection subscription (§4.3)
hook.decision (:96)approval-decision command via dispatchCommand
hook.resolved (:103)pending-approvals projection update
pairing.register/consume/consumed (:110-122)DPoP pairing grants (WP-T3-30)
remaining ack/error/keepalive frames (balance of the 17-frame union, :151)native RPC response/error/heartbeat envelopes of the effect/unstable/rpc runtime (t3:packages/contracts/src/rpc.ts:1-3) — no bespoke equivalents retained

Run/hook/pairing/org-admin become **fabric-only RPC groups in the contracts fork** (WP-T3-02); the gateway package is then reduced to what has no contracts equivalent: the kanban read model and webhook fan-out (manager.ts:103-224), re-hosted per WP-T3-21.

---

5. genty shell retirement (D2c, D13)

Retired: the 7 device shells (mobile-android 23 files, mobile-ios 22, tv-androidtv 18, tv-appletv 16, watch-watchos 25, watch-wearos 22, desktop-app 10 — all L0, ~0 tests, no CI, R1 §3.3) and, **after Playwright parity**, genty/web-app (the only e2e-gated shell). Replacements: adapted apps/console-web (WP-T3-25), apps/console-desktop bundling the fabric environment server (WP-T3-26), on @fabricstack/client-runtime (WP-T3-24). kradle/web survives as the org-admin surface only (spec 15 §3.2: @fabricstack/admin-console); run/thread UX moves to console-web. Mobile deferred (D13). Preserved through parity layers: the genty-ui hook API semantics (useRun/useHookRequests, fabric:packages/genty/ui/src/gateway.ts:1-8, 18 test files — the only tested fabric client surface, R4 §C.4), approval UX, org/observability/journal views. The duplicated protocol copy (fabric:packages/genty/ui/src/protocol/v1.ts:1-15, 151 lines mirroring the gateway package — R4 §C.1) is deleted, replaced by the single contracts import (R4 spec input 9). The T-27 retirement list is the single exemption list for all rename completeness checks (spec 15 interaction rule 4).

6. Remote-access stack (D2d, D12)

Four routes, one auth (R4 §D.6): 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), SSH bootstrap + port-forward with client-owned lifecycle (t3:packages/ssh), hosted relay with the broker-not-proxy trust model adopted verbatim (relay 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 — t3:docs/internals/t3-connect.md:3-33). Two mandatory substitutions (Gate A §1.4): Clerk → kradle org identity (org-scoping.js:5); @noble/curves relay PKI → trust-core key/chain machinery (fabric:packages/trust-core/src/index.ts:1-7) so fabric ships one PKI. The gateway's short-code pairing (fabric:packages/adapters/gateway/src/pairing/short-code.ts:1-20, 8-digit/5-minute in-memory) is the upgrade seed, not deleted-and-reinvented: same UX slot, upgraded to DPoP-bound grants (WP-T3-30). Fabric has zero ssh/tailscale/relay code today (R1 §3.10) — rows here are pure adoption.

7. Break-freely policy (D10) and the in-repo consumer inventory

No compatibility shims; major bump lands with RN-1/P-01. Every consumer broken by this program, with its migrating WP:

Broken surfaceIn-repo consumersMigrated by
BaseAgentAdapterInterface/RunHandle replaced by the WP-T3-05 contract22 codec files (fabric:packages/adapters/codecs/src/*-adapter.ts, listing at HEAD); @a5c-ai/comm-adapter type importers across codecs (e.g. babysitter-adapter.ts:12-24); genty-platform createRun orchestration (fabric:packages/genty/platform/src/harness/internal/createRun/orchestration/policy-enforcement-wiring.ts:123-150); gateway run manager (manager.ts:103-224)WP-T3-05/06/10/11/12/13 (codecs), WP-T3-17 (policy wiring), WP-T3-21 (gateway)
AgentEvent production path (union stays; producers re-platformed)journal binding, cost/attestation, observer-dashboard event viewsWP-T3-14 (consumers are its acceptance suite)
Gateway protocol v1 framesgenty-ui GatewayClient + hooks (gateway.ts:1-8), its protocol copy (genty/ui/src/protocol/v1.ts); kanban UI routes (fabric:packages/adapters/gateway/src/kanban/routes.ts region, registered server.ts:24)WP-T3-21 (server side), WP-T3-24 (client side), WP-T3-27 (copy deletion)
kradle dispatch/workspace controllers driving adapters directlyfabric:packages/kradle/core/src/agent-dispatch-controller.js, agent-workspace-controller.jsWP-T3-20
kradle-web untyped route handlersthe 81 route files (R4 §B.1)WP-T3-22
Gateway token auth + short-code pairingfabric:packages/adapters/gateway/src/auth/{tokens,middleware,bootstrap,hashing}.ts, pairing/short-code.ts:1-20WP-T3-30
genty shells and genty-ui as shipped surfacesweb-app/desktop-app/device shells; tui/ui keep operating against contracts via the parity layer until console-web parity, then per retirement listWP-T3-24/25/27

apps/commander (mock-only backend by design, zero CI references — R1 §3.9) consumes **frozen mirrors** of these contracts, not live imports; its disposition is F-17 (spec 20), not a migration item here. observer-dashboard reads journal artifacts, not the adapter contract, and is untouched except as a WP-T3-14 acceptance consumer.

8. Sequencing

  • **Naming/registry preconditions**: WP-RN-01…04 + WP-RN-08 precede WP-T3-01 (spec 15 interaction rule 2). All WP-T3-* depend on WP-T3-01 transitively unless noted.
  • **Critical path**: WP-T3-32(pin) → WP-T3-01 → WP-T3-02/03/04 → WP-T3-05/14 → lanes (06…13) → 15/16/17/18; in parallel WP-T3-19 → 20/21/22/23 → 30 → 31; client chain 24 → 25 → 26 → 27; remote extractions 28/29 anytime after 01/32.
  • **D11**: this migration is roadmap priority 1; spec 50's R-01 owns the merged cross-spec graph.

---

9. Work packages

WP-T3-01: Fork intake — import machinery, upstream pins, attribution (D15/D17/D21)

  • **Objective**: Land the intake mechanics for all §2 units: pristine-snapshot import branch, per-unit UPSTREAM.json pins, MIT attribution files, and the adopted third-party-license machinery — so every subsequent WP lands code with provenance, under @fabricstack/* names only.
  • **Affected paths**: new orphan branch vendor/t3code-snapshot holding the unmodified snapshot (tree from C:/Users/tmusk/AppData/Local/Temp/claude/.../t3code, pinned by commit SHA recorded in-branch); new docs/THIRD-PARTY-NOTICES.md; third-party-licenses.config.json + scripts/sync-third-party-license-notices.cjs adapted from t3:third-party-licenses.config.json + t3:scripts/sync-third-party-license-notices.ts (R2 §14); UPSTREAM.json template; intake PR template gaining the §3.3-names checklist.
  • **Acceptance criteria**: (1) the snapshot branch exists with the upstream SHA + t3:LICENSE verbatim; (2) the license-sync script runs in CI and fails when a §2 unit lacks its config entry (negative fixture proves it); (3) zero manifests anywhere introduce @t3code/*/t3-*/@a5c-ai/* names — the WP-RN-08 gate passes un-waived on this WP's output; (4) docs/THIRD-PARTY-NOTICES.md carries the MIT © 2026 T3 Tools Inc. notice; (5) no file in the public babysitter repo is touched (PR audit note).
  • **Test requirements**: license-sync negative-fixture test; WP-RN-08 gate fixture run; docs-quality gate green.
  • **Dependencies**: WP-RN-03, WP-RN-04, WP-RN-08 (spec 15); WP-T3-32 stage 1 (Effect pin exists so imported manifests resolve).
  • **Size**: M

WP-T3-02: Contracts tracked fork — `@fabricstack/contracts` + fabric RPC groups + capability-flag doctrine

  • **Objective**: Land t3:packages/contracts (74 modules, 26,979 LOC — R2 §5) as @fabricstack/contracts at packages/contracts; add fabric-only RPC/HTTP groups (runs, hooks/approvals incl. the 7-action taxonomy §4.3, pairing, org-admin schemas for WP-T3-22); adopt the capability-flag + schema-transform versioning doctrine (t3:docs/internals/overview.md:24-44; orchestration.ts:60-74) as the boundary discipline.
  • **Affected paths**: new packages/contracts/ (fork of all 48 non-test modules incl. rpc.ts, orchestration.ts, providerRuntime.ts, environment.ts, environmentHttp.ts, auth.ts, settings.ts, terminal.ts — R2 §5 inventory); new fabric-group modules packages/contracts/src/fabric/{runs,approvals,pairing,orgAdmin}.ts; UPSTREAM.json; pruned modules recorded as divergence (ipc.ts stays for WP-T3-26; pullRequest.ts/device.ts/preview*.ts retained-dark per §2 exclusions with a divergence note, since deleting them would poison future tracked-fork pulls).
  • **Acceptance criteria**: (1) package builds with plain tsc under fabric's npm workspace, effect as the sole runtime dep (R2 §18.2); (2) the 139-entry WS_METHODS map and the file's 144 Rpc.make definitions (t3:packages/contracts/src/rpc.ts:277; both counts measured in the pinned snapshot — the AC includes re-verifying both numbers against the forked source at fork time and recording them in UPSTREAM.json) and the 8 orchestration methods (orchestration.ts:35-44) compile unmodified; (3) fabric groups type all 7 approval actions of agent-approval-controller.js:15 as first-class variants; (4) a capability-flag negotiation unit test proves an old client degrades against a new environment descriptor without error; (5) publishConfig.registry = AR URL (guard G1); WP-RN-08 gate green.
  • **Test requirements**: upstream test files retained and green under fabric's vitest; new schema round-trip tests for every fabric group; legacy-wire-transform regression test replicating the orchestration.ts:60-74 pattern on one fabric field.
  • **Dependencies**: WP-T3-01, WP-T3-32 (pin).
  • **Size**: L

WP-T3-03: `@fabricstack/acp` tracked fork + schema regeneration pipeline

  • **Objective**: Land t3:packages/effect-acp (15,546 LOC, 10,375 generated — R2 §6) as @fabricstack/acp at packages/acp, with the generator wired so upstream ACP-spec churn is a regeneration, not a hand-merge.
  • **Affected paths**: new packages/acp/ — _generated/schema.gen.ts, meta.gen.ts, rpc.ts (22 Rpc.make — t3:packages/effect-acp/src/rpc.ts:8-40), protocol.ts (:23-80 JSON-RPC stdio, client+server from one child stdio), client.ts (AcpClient — client.ts:49), agent.ts (AcpAgent — agent.ts:31), errors.ts, terminal.ts (:6-25); the five subpath exports (client/agent/schema/protocol/errors) preserved; regeneration script adapted from t3:packages/effect-acp package.json "generate" (@effect/openapi-generator); UPSTREAM.json.
  • **Acceptance criteria**: (1) builds with plain tsc, dep = effect only; (2) regeneration run against the pinned ACP schema reproduces _generated/* byte-identically (proves the pipeline, not just the copy); (3) the ACP mock agent (adapted from t3:apps/server/scripts/acp-mock-agent.ts) completes an initialize → session/new → prompt-turn → session/update cycle against client.ts in CI; (4) both directions exported: client (drive) and agent (be-driven).
  • **Test requirements**: upstream tests green; mock-agent protocol suite (the Q-07 pattern, spec 30) wired as this package's CI job.
  • **Dependencies**: WP-T3-01, WP-T3-32.
  • **Size**: M

WP-T3-04: `@fabricstack/codex-protocol` tracked fork + regeneration pipeline

  • **Objective**: Land t3:packages/effect-codex-app-server (61,816 LOC, 58,004 generated — R2 §7) as @fabricstack/codex-protocol at packages/codex-protocol, regenerable from the Codex app-server schema.
  • **Affected paths**: new packages/codex-protocol/ — _generated/{schema.gen.ts,namespaces.gen.ts}, meta.gen.ts, client.ts (262 LOC, spawns codex app-server), protocol.ts (485 LOC), re-export rpc.ts (t3:packages/effect-codex-app-server/src/rpc.ts:1); regeneration script; probe example adapted from t3:packages/effect-codex-app-server/test/examples/codex-app-server-probe.ts; UPSTREAM.json additionally recording the upstream schema source once confirmed (R2 §17 flags the generator source as INFERRED — confirming it is an acceptance item here, closing that dossier gap).
  • **Acceptance criteria**: (1) builds with plain tsc, dep = effect only; (2) regeneration reproduces _generated/*; (3) the probe example completes a handshake against a locally installed codex binary in the live-stack lane (skippable-by-absence, asserted in the WP-T3-11 lane run); (4) UPSTREAM.json names the confirmed schema provenance.
  • **Test requirements**: upstream tests green; regeneration determinism test in CI.
  • **Dependencies**: WP-T3-01, WP-T3-32.
  • **Size**: M

WP-T3-05: The `ProviderAdapter`-equivalent plain-TS contract (successor of `BaseAgentAdapterInterface`/`RunHandle`)

  • **Objective**: Define fabric's one adapter contract per §3.1: typed capabilities + compaction semantics modeled on t3:apps/server/src/provider/Services/ProviderAdapter.ts:29-56, retaining fabric's broader surfaces (auth detection adapter-types.ts:42, session-file parsing :46-49, deferred prompts run-handle.ts:44-51, cost types run-handle.ts:9,21-27) and adding drive-side permission callbacks routed to §4.3 approvals. Plain TS only (B1).
  • **Affected paths**: fabric:packages/adapters/core/src/adapter-types.ts (superseded), run-handle.ts (retained shape, re-exported by the new contract), new packages/adapters/core/src/contract/{provider-adapter.ts,lanes.ts,permissions.ts}; fabric:packages/adapters/codecs/src/base-adapter.ts:61,75 (registry migrates to lane-aware factory).
  • **Acceptance criteria**: (1) contract module has zero effect imports (boundary check per §2.1); (2) RunHandle's triple nature (AsyncIterable + emitter + thenable, run-handle.ts:1-8) is preserved verbatim in the new contract's run surface; (3) capability set includes at minimum sessionModelSwitch, promptlessTurnContinuation, supportsConversationRollback, compaction mode, deferred-prompt targets; (4) permission-callback type routes through the approval contract of WP-T3-02 (compile-time proof: shared type import); (5) all five lane kinds declared (acp, claude-sdk, codex-app-server, opencode-http, subprocess) plus the observe lane binding point.
  • **Test requirements**: contract unit tests incl. a fake lane exercising run/steer/cancel/permission flows; architecture-gate rule added (no Effect in packages/adapters/core/src/contract/**).
  • **Dependencies**: WP-T3-02 (approval/event vocabulary types).
  • **Size**: M

WP-T3-06: Generic ACP lane runtime + per-harness extension modules

  • **Objective**: Implement the ACP lane: one generic session runtime over @fabricstack/acp's client, with per-harness extension modules, adapted from t3:apps/server/src/provider/acp/{AcpSessionRuntime,AcpAdapterSupport,AcpCoreRuntimeEvents,AcpRuntimeModel,AcpStderr}.ts (R2 §4), exposed through the WP-T3-05 contract (Effect quarantined inside, B2/B1).
  • **Affected paths**: new packages/adapters/codecs/src/lanes/acp/{runtime.ts,support.ts,events.ts,stderr.ts} + extensions/ directory (Cursor/Grok/Antigravity modules land in WP-T3-07/08/09); wiring into the lane-aware registry (WP-T3-05).
  • **Acceptance criteria**: (1) the runtime drives the WP-T3-03 mock agent end-to-end through the plain-TS contract: start session → prompt → streamed session/update → permission request surfaced via the contract callback → terminal completion; (2) no Effect type escapes the lane boundary (boundary check); (3) ACP permission requests reach the WP-T3-02 approval types; (4) stderr and crash taxonomy normalized into projection-ready events.
  • **Test requirements**: mock-agent lane suite in PR CI; permission round-trip test; kill/cancel propagation test (child process actually terminates — the H5-class behavior must hold in the new lane even though H5 itself is F-05/spec 20).
  • **Dependencies**: WP-T3-03, WP-T3-05.
  • **Size**: L

WP-T3-07: Cursor ACP lane

  • **Objective**: Cursor drives via cursor-agent [permission args] acp (t3:apps/server/src/provider/acp/CursorAcpSupport.ts:56-60) with the CursorAcpExtension pattern; the cursor-adapter.ts codec retires after parity; the red live-stack lane (#562 — R1 §4.3) goes green on the new lane (shared objective with F-18, spec 20).
  • **Affected paths**: new packages/adapters/codecs/src/lanes/acp/extensions/cursor.ts (from t3:.../CursorAcpExtension.ts + CursorAcpSupport.ts); delete fabric:packages/adapters/codecs/src/cursor-adapter.ts; live-stack agent map entry cursor re-pointed at the lane (live-stack.yml Compute Matrix agents map).
  • **Acceptance criteria**: (1) live-stack cursor lane green with lane artifacts (adapters-events, trace ids — R1 §4.3 artifact set); (2) hook adapter adapter-cursor continues to feed the projection for user-driven sessions (observe lane untouched); (3) codec file deleted, registry has no cursor subprocess factory; (4) Cursor's self-updater constraint honored: fabric never attempts to update the Cursor binary (t3:docs/internals/providers.md, updates section).
  • **Test requirements**: lane unit tests against recorded ACP transcripts; live-stack dispatch run linked in the WP closing note.
  • **Dependencies**: WP-T3-06, WP-T3-14.
  • **Size**: M

WP-T3-08: Grok Build ACP lane — net-new harness (D7(a))

  • **Objective**: Build fabric's first Grok support: ACP lane via grok --permission-mode <mode> agent stdio (t3:apps/server/src/provider/acp/GrokAcpSupport.ts:33-41,55-56) with the XAi extension pattern (XAiAcpExtension.ts, XAiBackgroundTasks.ts); add the live-stack lane the D7(a) matrix requires (fabric has zero grok code today — R1 §3.1).
  • **Affected paths**: new packages/adapters/codecs/src/lanes/acp/extensions/grok.ts; live-stack agents map gains grok; setup probe logic honoring the no-side-effects rule (t3:docs/internals/providers.md, setup section).
  • **Acceptance criteria**: (1) live-stack grok lane runs and produces the standard artifact set; (2) permission modes map onto the approval contract; (3) background-task events normalize into the projection; (4) probe performs no auth/session mutation.
  • **Test requirements**: recorded-transcript unit suite; live-stack lane added to the dispatch matrix (push-default inclusion decided by spec 30's Q-03).
  • **Dependencies**: WP-T3-06, WP-T3-14.
  • **Size**: M

WP-T3-09: Antigravity ACP lane + managed installer

  • **Objective**: Replace the failing Antigravity integration (#945 — R1 §4.3) with the t3code model: fabric-downloaded release with immutable versions + version leases, identity verified as agentInfo.name === "antigravity-acp" / protocolVersion === 1 (t3:apps/server/src/provider/AntigravityInstallation.ts:484-502), OAuth loopback-callback forwarding (AntigravityAuth.ts), per-instance profile isolation, and the revert-rejection rule (cannot roll back conversation ⇒ reject revert before touching files — R2 §3.4).
  • **Affected paths**: new packages/adapters/codecs/src/lanes/acp/extensions/antigravity.ts + installers/antigravity.ts (from AntigravityInstallation.ts, spawn builder antigravityAuthSupport.ts:434); hook adapter adapter-antigravity unchanged; live-stack antigravity entry re-pointed.
  • **Acceptance criteria**: (1) installer downloads, verifies identity, and leases a version in an integration test with a stubbed release feed; (2) live-stack antigravity lane green; (3) revert requests against an antigravity session are rejected with a typed error before any file mutation (unit test); (4) installer work reuses WP-T3-33's ownership-proof machinery, not a parallel implementation.
  • **Test requirements**: installer integration test; lane transcript suite; live-stack run.
  • **Dependencies**: WP-T3-06, WP-T3-14, WP-T3-33.
  • **Size**: L

WP-T3-10: Claude SDK lane

  • **Objective**: Claude drives via @anthropic-ai/claude-agent-sdk in-process query() (t3:apps/server/src/provider/Layers/ClaudeAdapter.ts:5,14-27): permission callbacks via SDK CanUseTool, usage limits from SDKRateLimitInfo (Layers/claudeUsageLimits.ts), session history/fork in a **child worker** so the SDK sees the provider environment without mutating the server's (t3:apps/server/src/claudeHistoryWorker.ts:1-11). Replaces codecs claude-agent-sdk-adapter.ts, claude-adapter.ts, and claude-remote-control-adapter.ts after parity.
  • **Affected paths**: new packages/adapters/codecs/src/lanes/claude-sdk/{lane.ts,history-worker.ts,usage-limits.ts}; delete the three claude codec files after the acceptance run; hook adapter adapter-claude unchanged.
  • **Acceptance criteria**: (1) live-stack claude-code lane green on the new lane (it is GREEN today — R1 §4.3 — so this is a no-regression bar with the same artifact set); (2) CanUseTool callbacks route through WP-T3-17's trust-gated approvals; (3) history worker runs out-of-process (asserted by PID inequality in test); (4) the three retired codecs deleted and unregistered; (5) parity checklist against claude-remote-control-adapter.ts capabilities recorded in the WP closing note before its deletion (it imports programmatic-run types — fabric:packages/adapters/codecs/src/claude-remote-control-adapter.ts:7-24 — so remote-control-mode coverage must be explicitly confirmed or consciously dropped with a note, not silently lost).
  • **Test requirements**: lane unit suite with SDK mocked; live-stack claude lane (push default — R1 §4.3); permission round-trip e2e.
  • **Dependencies**: WP-T3-05, WP-T3-14, WP-T3-17.
  • **Size**: L

WP-T3-11: Codex app-server lane

  • **Objective**: Codex drives via codex app-server JSON-RPC stdio typed by @fabricstack/codex-protocol (t3:apps/server/src/provider/Layers/CodexAdapter.ts:45-46, CodexSessionRuntime.ts; launch args codexLaunchArgs.ts:13), honoring the async-question protocol traps (notifications answered by a new user message; blocking questions via request/response — t3:docs/internals/providers.md, protocol-traps). Retires codecs codex-adapter.ts, codex-sdk-adapter.ts, codex-websocket-adapter.ts.
  • **Affected paths**: new packages/adapters/codecs/src/lanes/codex-app-server/lane.ts; delete the three codex codecs; hook adapter adapter-codex unchanged.
  • **Acceptance criteria**: (1) live-stack codex lane green (no-regression, GREEN today — R1 §4.3); (2) async questions surface as approval/steering events, blocking questions as contract permission callbacks; (3) the three codecs deleted and unregistered; (4) protocol typed end-to-end — no untyped JSON handling outside @fabricstack/codex-protocol.
  • **Test requirements**: probe handshake (WP-T3-04) in lane CI; recorded app-server transcript suite; live-stack codex lane (push default).
  • **Dependencies**: WP-T3-04, WP-T3-05, WP-T3-14.
  • **Size**: L

WP-T3-12: OpenCode HTTP lane

  • **Objective**: OpenCode drives via @opencode-ai/sdk/v2 with one fabric-managed opencode server **per thread** (or an external server) — the per-directory MCP registration constraint forces server-per-thread (t3:apps/server/src/provider/Layers/OpenCodeAdapter.ts:32; t3:docs/internals/providers.md:14-22); shared instance-owned helper for catalog/text-gen per OpenCodeServerOwner.ts. Retires codecs opencode-adapter.ts, opencode-http-adapter.ts; turns the skipped/failing lane green (with F-18).
  • **Affected paths**: new packages/adapters/codecs/src/lanes/opencode-http/{lane.ts,server-owner.ts}; delete the two opencode codecs; hook adapter adapter-opencode unchanged.
  • **Acceptance criteria**: (1) live-stack opencode lane green; (2) server lifecycle owned per thread with leak-free teardown (test asserts zero orphan opencode processes after suite); (3) external-server mode configurable; (4) codecs deleted and unregistered.
  • **Test requirements**: lane suite against a local opencode server in CI; process-leak assertion; live-stack run.
  • **Dependencies**: WP-T3-05, WP-T3-14.
  • **Size**: M

WP-T3-13: Retained-subprocess lane migration — the full 22-codec disposition table

  • **Objective**: Migrate the retained codecs behind the WP-T3-05 contract as the fifth lane and execute the terminal disposition of **all 22** codec files (listing at HEAD, fabric:packages/adapters/codecs/src/*-adapter.ts), including the four undossiered files and qwen, with the oh-my-pi/omp aliasing resolved per §3.2. Dispositions (binding): **retain-behind-contract** — gemini, copilot, pi, pi-sdk (programmatic — fabric:packages/adapters/codecs/src/pi-sdk-adapter.ts:1-7,25), omp (≡ oh-my-pi), openclaw, hermes, droid, amp, qwen, babysitter (self-driving orchestrator harness — babysitter-adapter.ts:1-6; long-term successor is the WP-T3-18 ACP-agent lane, retained until that lands and proves parity), adapters-remote (nesting pass-through emitting adapters run spawn args for docker/ssh/k8s wrapping — adapters-remote-adapter.ts:1-18; retained now, re-evaluated against WP-T3-19/30 remote connectivity in the WP closing note); **retired by other WPs** — cursor (T3-07), claude×3 (T3-10), codex×3 (T3-11), opencode×2 (T3-12); **infrastructure** — base-adapter.ts (:61,75) retired here once the last retained codec runs on the new contract.
  • **Affected paths**: the 12 retained codec files (mechanical port to the lane API); base-adapter.ts deletion; registry finalization; live-stack agents map (14 ids — R1 §4.3) re-verified against the final lane inventory.
  • **Acceptance criteria**: (1) the disposition table lands in-code as a checked test fixture (every codec file at HEAD accounted for; adding an unlisted codec fails the test); (2) all retained harness lanes produce identical projection output before/after migration on recorded fixtures (golden diff); (3) base-adapter.ts deleted; zero imports of the old BaseAgentAdapterInterface remain repo-wide; (4) live-stack push-default lanes (claude-code, codex, pi, antigravity, genty — R1 §4.3) green post-migration; (5) the aliasing resolution recorded: exactly one lane id omp, hook adapter adapter-oh-my-pi mapped to it.
  • **Test requirements**: golden projection fixtures per retained codec; full live-stack dispatch matrix run; registry completeness test.
  • **Dependencies**: WP-T3-05, WP-T3-14; retirement entries depend on WP-T3-07/10/11/12.
  • **Size**: L

WP-T3-14: AgentEvent projection layer — 67-member union as derived view + consumer acceptance suite

  • **Objective**: Build the normalizer that projects ACP session/update + bespoke-lane events into the existing 67-member AgentEvent union (all members extend BaseEvent — 49 defined in events.ts plus 18 in events-control.ts; the research dossier's 49 counted only events.ts) (fabric:packages/adapters/core/src/events.ts:411; families at :21-46,:57-75,:85-115,:124-153,:164-186,:196-212,:222-238,:250-265) as a **derived view** (D6), with the four consumer families of §3.3 compiled and tested unchanged.
  • **Affected paths**: new packages/adapters/core/src/projection/{normalizer.ts,acp.ts,claude.ts,codex.ts,opencode.ts,subprocess.ts}; events.ts untouched (the union is the target, not the casualty); consumer test harness under packages/adapters/core/src/projection/__tests__/.
  • **Acceptance criteria**: (1) golden tests: for each lane, recorded native transcripts project to expected AgentEvent sequences — golden coverage scoped to the **full 67-member union membership derived from the AgentEvent type itself**: a completeness test enumerates the union's discriminants from the type (not from an extends BaseEvent grep — the 67 members are split across events.ts and events-control.ts, so a file-scoped grep can silently undercount) and fails when any member lacks either a golden fixture or an explicit, reviewed not-producible-by-any-lane annotation; (2) the four consumer families pass unmodified: RunHandle iteration semantics (run-handle.ts:1-8), gateway fan-out (manager.ts:103-110), journal binding (journal.ts:72-82 write path receives identical event payload shapes), cost/attestation (transport/src/server.ts:1596-1607 seam receives cost records); (3) a reverse-dependency check proves no producer writes AgentEvent except through the normalizer (architecture-gate rule); (4) token-usage projection covers t3code's turn-usage shape (t3:packages/contracts/src/providerRuntime.ts turn token usage — R2 §5) mapped to TokenUsageSummary (run-handle.ts:21-27).
  • **Test requirements**: golden fixture suite (this is spec 30's Q-09 anchor); consumer compile+test gate in PR CI.
  • **Dependencies**: WP-T3-02 (ProviderRuntimeEvent vocabulary), WP-T3-05.
  • **Size**: L

WP-T3-15: Observe-lane rebind — 12 hook adapters feed the projection unchanged

  • **Objective**: Re-bind the 12 hook adapters (R1 §3.1 listing) so their observe-side events enter the WP-T3-14 normalizer instead of the legacy event plumbing — with zero behavior change to the adapters themselves (t3code has no observe mode; this plane is fabric-only and survives whole — R4 §A.3).
  • **Affected paths**: packages/adapters/hooks/core event-emission seam; hook→session→run resolution untouched (stopHookHandler.ts:209-225 is F-06 territory, spec 20); the 12 adapter-* packages: dependency bumps only.
  • **Acceptance criteria**: (1) all 12 adapters' existing test suites green without source changes inside the adapters; (2) an observe-lane event for a user-driven session reaches the same AgentEvent consumers as a drive-lane event (integration test per adapter family); (3) live-stack babysitter-plugin install-mode lanes (R1 §4.3) green.
  • **Test requirements**: hooks-adapter suites (already PR-gated — ci.yml test job, R1 §4.1); one new observe→projection integration test.
  • **Dependencies**: WP-T3-14.
  • **Size**: M

WP-T3-16: Journal sovereignty enforcement across all lanes

  • **Objective**: Make §4.4 mechanical: run identity, provenance, and replay live in the babysitter journal for every lane; the environment SQLite store is projection-only for threads/turns.
  • **Affected paths**: lane→journal binding in packages/adapters/codecs/src/lanes/* (each lane's run termination writes through journal.ts:72-82 exactly as today's codecs do); apps/environment persistence layer annotated: run-scoped tables carry a journalRunRef, never the inverse; a CI architecture rule forbidding imports from apps/environment/src/persistence into packages/babysitter-sdk.
  • **Acceptance criteria**: (1) for each of the five lanes, an e2e run produces a journal under .a5c/runs/ whose event sequence replays (existing replay engine, R1 §3.4) and whose run id appears in the kanban source discovery (source-discovery.ts:12-34); (2) deleting the environment SQLite DB mid-suite loses no run identity/provenance (journal replay reconstructs run state; thread projections rebuild); (3) the architecture rule trips on a negative fixture.
  • **Test requirements**: per-lane journal e2e; DB-deletion recovery test; replay determinism assertion (checksum-level verification itself remains F-01, spec 20 — this WP asserts presence and replayability, not tamper-proofing).
  • **Dependencies**: WP-T3-14, WP-T3-19.
  • **Size**: M

WP-T3-17: Trust-signed policy gating wired into drive-lane permission callbacks

  • **Objective**: Every drive-side permission callback (Claude CanUseTool, ACP permission requests, Codex blocking questions) is gated by the proven-bridge human-root chain (fabric:packages/adapters/policy/src/proven-bridge.ts:92-119) — the new lanes must not create an approval path that bypasses trust-signed breakpoints (§3.4.3).
  • **Affected paths**: packages/adapters/policy/src/proven-bridge.ts (new entry point for lane callbacks); lane permission plumbing (lanes/*/); genty-platform policy wiring (policy-enforcement-wiring.ts:123-150) consuming the contract callback instead of legacy seams.
  • **Acceptance criteria**: (1) a lane permission grant without a valid human-root-chained signature is rejected when POLICY_CONFIG_ROOT_FP is pinned (mirrors the fail-closed behavior at policy-enforcement-wiring.ts:139-150); (2) with no anchor pinned, behavior matches today's back-compat posture (:132-137) — flipping the default is F-03, spec 20, not this WP; (3) no lane contains a code path resolving a permission callback without consulting the policy bridge (architecture-gate rule + negative test); (4) approval decisions carry signature evidence into the WP-T3-23 approval records.
  • **Test requirements**: tamper test (forged decision rejected); policy-adapter suite (PR-gated today, ci.yml:171-183) extended and green.
  • **Dependencies**: WP-T3-05, WP-T3-14; consumed by WP-T3-06/10/11.
  • **Size**: M

WP-T3-18: Fabric-as-ACP-agent — runs and genty sessions drivable by external ACP clients

  • **Objective**: Adopt @fabricstack/acp's agent side (t3:packages/effect-acp/src/agent.ts:31) to expose babysitter runs and genty sessions as ACP sessions — zero fabric precedent, the reciprocal seam of D6 (R4 spec input 4); genty (harness row 16) becomes the first consumer, driven through the standard ACP lane.
  • **Affected paths**: new packages/adapters/gateway/src/acp-agent/ (ACP agent service bridging session/new → run dispatch, session/update ← projection events, permission requests ← approval gates); genty lane registration switching from the genty subprocess codec to the ACP-agent lane; packages/adapters/codecs/src/lanes/acp/extensions/genty.ts.
  • **Acceptance criteria**: (1) an external ACP client (the WP-T3-03 mock client harness inverted) initializes, starts a session, and receives streamed updates for a real babysitter run; (2) permission requests surface as ACP requests and resolve through WP-T3-17 gates; (3) live-stack genty lane green via the ACP path; (4) the babysitter self-driving codec's parity is evaluated against this lane and the result recorded (WP-T3-13 cross-item).
  • **Test requirements**: ACP conformance suite over the agent side (mock client); live-stack genty lane.
  • **Dependencies**: WP-T3-03, WP-T3-05, WP-T3-14.
  • **Size**: L

WP-T3-19: Environment server hard fork — `@fabricstack/environment`

  • **Objective**: Land the t3:apps/server subset (§2 row 6: orchestration 38 files/20.4k LOC, persistence 84/7.6k, checkpointing, terminal 4/3.5k, vcs/git/sourceControl/project/usage/textGeneration/mcp/resourceTelemetry — R2 §3 table) as @fabricstack/environment at apps/environment, bin environment-server: the single-node environment that runs under kradle's plane, hosting the WP-T3-05 lane layer. Pruned at landing: pullRequest/, device/, preview/, desktopUpdate/, marketing/mobile-adjacent code (§2 exclusions). Cherry-picked shared modules (nodeSqliteClient, DrainableWorker — t3:packages/shared/src/{nodeSqliteClient.ts:1-7,DrainableWorker.ts}) land under apps/environment/src/shared/.
  • **Affected paths**: new apps/environment/ (event-sourced engine: commands → pure decider → events → projector → reactors, single SQLite transaction — t3:docs/internals/overview.md:56-72; state under the fabric data dir, .a5c/ today, .fabric/ after RN-3); UPSTREAM.json; the resource-monitor Rust helper (t3:native/resource-monitor, stdin/stdout protocol v3 — main.rs:11) vendored under apps/environment/native/resource-monitor as an optional sidecar.
  • **Acceptance criteria**: (1) environment-server starts under fabric's npm workspace on Node ≥22.16 (engines per t3:apps/server/package.json; node:sqlite floor ≥22.5 — R2 §15), serves contracts RPC, and completes dispatchCommand → decider → projector → subscribeThread round-trip; (2) replay-forever discipline holds: a persisted event log from the acceptance run replays cleanly on restart (overview.md:68-70); (3) checkpoints work as hidden git refs with capture/restore/diff (t3:apps/server/src/checkpointing/CheckpointStore.ts:1-15) and never add commits to the user's branch; (4) terminal subsystem serves a PTY over subscribeShell (node-pty as the only new native build dep); (5) pruned subsystems absent from the shipped tree (grep gate); (6) journal sovereignty holds (WP-T3-16 tests pass against this server); (7) runtime-receipt test bus operational (overview.md:89-92) — production layer no-op.
  • **Test requirements**: upstream test suites of adopted subsystems green under the fabric toolchain; receipts/DrainableWorker-based integration suite (no sleeps — Q-07 pattern); replay determinism test.
  • **Dependencies**: WP-T3-01, WP-T3-02, WP-T3-32 (stage 2).
  • **Size**: L

WP-T3-20: Kradle↔environment boundary — controllers become environment clients

  • **Objective**: Kradle's agent-dispatch-controller/agent-workspace-controller dispatch OrchestrationCommands to environment servers over contracts RPC instead of driving adapters directly; the boundary is the environment descriptor + capability flags (t3:packages/contracts/src/environment.ts:1-3) + environmentHttp.ts groups; kradle never speaks ACP (§4.1).
  • **Affected paths**: fabric:packages/kradle/core/src/agent-dispatch-controller.js, agent-workspace-controller.js (become clients); new environment-registry controller (which environments exist per org, descriptor cache, capability negotiation); org scoping preserved (org-scoping.js:5).
  • **Acceptance criteria**: (1) a kradle-dispatched run executes inside an apps/environment instance and streams back through subscribeThread, with the run journaled per WP-T3-16; (2) capability negotiation proven: a controller degrades gracefully against an environment lacking a flag (unit test per the overview.md:24-44 doctrine); (3) zero ACP imports under packages/kradle (grep gate); (4) org boundary enforced: an environment registered to org A is not dispatchable from org B (test); (5) K8s CR reconcilers, Helm/GKE deployment, and the 7-action approval controller continue functioning (kradle-core suite green — publish.yml:565-568).
  • **Test requirements**: kradle-core node:test suite green; new dispatch-through-environment e2e in the deployed-stack lane (publish.yml:423-424).
  • **Dependencies**: WP-T3-02, WP-T3-19.
  • **Size**: L

WP-T3-21: Gateway fold-in — 17 frames → contracts RPC; gateway reduced

  • **Objective**: Execute the §4.5 mapping table: every gateway frame's function is served by contracts RPC groups on the environment; the gateway package is reduced to its fabric-only residue (journal-derived kanban read model + webhook fan-out), re-hosted behind typed routes.
  • **Affected paths**: fabric:packages/adapters/gateway/src/protocol/v1.ts (deleted at completion), server.ts:4,177,181,572 (WS server retired), runs/manager.ts:103-224 (run-event fan-out re-platformed onto subscribeThread; webhook fan-out kept); kanban/ retained, reading .a5c/runs as today (source-discovery.ts:12-34), served via a typed fabric HTTP group from WP-T3-02.
  • **Acceptance criteria**: (1) each row of the §4.5 table demonstrated by an equivalence test (same stimulus, equivalent observable result on old frame vs new RPC — spec 30 Q-09's gateway-frame↔contracts suite); (2) protocol/v1.ts deleted; repo-wide grep shows no gateway-frame type imports outside historical docs; (3) kanban UI functions against the typed route; (4) webhook fan-out fires on projection events with unchanged payloads (golden test); (5) the gateway-node-engine CI job (ci.yml:319) is retargeted or retired with its floor assertions moved to apps/environment.
  • **Test requirements**: frame↔RPC equivalence suite; kanban source-discovery tests green; webhook golden tests.
  • **Dependencies**: WP-T3-02, WP-T3-19, WP-T3-20; client side in WP-T3-24.
  • **Size**: L

WP-T3-22: kradle-web route program — type-or-replace the 81 untyped routes

  • **Objective**: Execute §4.2 over the measured 81 route files (R4 §B.1): run/thread/session routes replaced by contracts RPC; org-admin CRUD routes typed in place against the WP-T3-02 fabric org-admin schemas; the SSE watch route (watch/[[...resource]]/route.js:1-20) typed; zero untyped route handlers remain.
  • **Affected paths**: fabric:packages/kradle/web/app/api/** (all 81 files); shared schema-decode helper consuming @fabricstack/contracts (B3: routes receive decoded plain objects); route-by-route disposition ledger committed as packages/kradle/web/ROUTE-DISPOSITIONS.md listing each file → {typed-in-place | replaced-by-RPC | deleted} .
  • **Acceptance criteria**: (1) the disposition ledger covers exactly the 81 files (CI test derives the list from the tree and diffs); (2) every surviving route validates request+response against contracts schemas (middleware test hits each route with a malformed payload and asserts a typed 4xx); (3) kradle-web's 30 spec files pass (their CI gating is Q-01/Q-05, spec 30 — here they must merely be green locally); (4) no effect imports in route files (B3 boundary check); (5) org scoping semantics unchanged (org-scoped route test matrix).
  • **Test requirements**: route validation matrix; SSE watch typed-event test; disposition-ledger completeness test.
  • **Dependencies**: WP-T3-02, WP-T3-20.
  • **Size**: L

WP-T3-23: Approval mapping — pending approvals ↔ 7-action AgentApproval ↔ signed breakpoints

  • **Objective**: Implement the §4.3 table: t3code's pending-approvals projection surfaces as kradle AgentApproval resources; the four fabric-only actions (secret-access, write-back, release, escalation) plus ai-review flow as first-class variants; every decision is chained to signed breakpoints (proven-bridge.ts:92-119).
  • **Affected paths**: fabric:packages/kradle/core/src/agent-approval-controller.js (consumes the approval RPC group); environment pending-approvals projection (from WP-T3-19); the WP-T3-02 approval contract; babysitter breakpoint enforcement (fabric:packages/babysitter-sdk/src/breakpoints/enforce-signed-breakpoint.ts) as the signature spine.
  • **Acceptance criteria**: (1) a drive-lane tool-permission request round-trips: lane callback → environment pending approval → kradle AgentApproval(tool-use) → human decision → signed evidence → callback resolution — asserted end-to-end in the deployed-stack e2e; (2) each of the 7 actions has a typed round-trip test; the 5 t3code-blind actions verified to carry their fabric semantics (e.g. secret-access gates a secret-config grant — agent-secret-config-grant-controller.js path); (3) an unsigned or non-human-root decision is rejected (tamper test, mirroring enforce-signed-breakpoint.test.ts patterns — R1 TEST2 note); (4) t3code plan proposals surface as review gates.
  • **Test requirements**: 7-action round-trip matrix; tamper suite; deployed-stack approval e2e.
  • **Dependencies**: WP-T3-02, WP-T3-17, WP-T3-19, WP-T3-20.
  • **Size**: L

WP-T3-24: client-runtime hard fork — `@fabricstack/client-runtime`

  • **Objective**: Land t3:packages/client-runtime (256 files — R2 §8) as @fabricstack/client-runtime at packages/client-runtime: single connection supervisor (connection/supervisor.ts), per-environment registry (connection/registry.ts) with **kradle as catalog source** (each kradle-managed environment = one entry — the hosted-web pattern, t3:docs/internals/remote.md:28-38), ~30 atom state services, credential refresh decoupled from socket lifetime (authorization/service.ts), platform/ service interfaces as the shell plug-point; plus a **genty-ui hook-API parity layer** reproducing useRun/useHookRequests/useGateway/useAgents/useConnection semantics (fabric:packages/genty/ui/src/gateway.ts:1-8).
  • **Affected paths**: new packages/client-runtime/ (fork, minus relay/device modules deferred to WP-T3-31/never); new packages/client-runtime/src/compat/genty-ui-hooks.ts (parity layer); cherry-picked shared modules under src/shared/; approval UX mapped to the 7-action taxonomy.
  • **Acceptance criteria**: (1) genty-ui's 18 test files pass against the parity layer (the R4 §C.4 bar) with only import-path changes; (2) one supervisor owns all reconnect behavior — the divergent-backoff bug class (genty/ui/src/client/backoff.ts vs kradle/web/app/components/agent/live-updates.jsx:8-30) is demonstrably unified (chaos test: drop/restore transport, all surfaces reconnect through the supervisor); (3) connection catalog populated from kradle's environment registry (WP-T3-20); (4) Effect quarantined to the atom/data layer; platform/ interfaces and the hook API are plain TS (boundary check, B1/B6); (5) no protocol/v1 types anywhere in the package.
  • **Test requirements**: genty-ui parity suite; supervisor chaos test; catalog integration test against a stub kradle.
  • **Dependencies**: WP-T3-02, WP-T3-21, WP-T3-32.
  • **Size**: L

WP-T3-25: Web app hard fork — `@fabricstack/console-web`

  • **Objective**: Land t3:apps/web (1,258 files — R2 §11) as @fabricstack/console-web at apps/console-web: run/thread UX, tiptap composer, @pierre/diffs rendering, ghostty-wasm terminal (t3:apps/web/src/terminal/ghostty/core.ts:13-15; headers pinned by t3:native/libghostty-vt/VERSION — the wasm artifact build provenance, flagged INFERRED in R2 §17, is resolved as an acceptance item), checkpoint UI, settings — re-pointed at @fabricstack/client-runtime + @fabricstack/contracts, with fabric org semantics and approval views for all 7 actions. Clerk paths removed (hosted identity is kradle's — §6). Deployment forms: server-served local client (from apps/environment) and the kradle-hosted multi-tenant client.
  • **Affected paths**: new apps/console-web/ (fork, Clerk-dependent modules deleted as divergence); vendored native/libghostty-vt headers + a documented wasm build step; theming/branding neutralized (D14: no public branding work, neutral defaults only).
  • **Acceptance criteria**: (1) Playwright parity bar met: every scenario in genty/web-app's existing Playwright e2e (the ci.yml "adapters webui browser e2e" step — R1 §4.1) has an equivalent green console-web scenario — this is the precondition WP-T3-27 consumes; (2) run/thread views work against a live environment (create → stream → approve → diff → checkpoint restore); (3) approval UI renders all 7 actions incl. the fabric-only four; (4) terminal renders via the wasm build whose provenance is scripted in-repo (INFERRED gap closed); (5) zero Clerk imports (grep gate); (6) org-scoped views respect kradle org boundaries; (7) builds on the fabric toolchain (WP-T3-32 stage 2 — stock Vite), not vite-plus.
  • **Test requirements**: Playwright parity suite in PR CI; component tests for approval views; wasm terminal smoke test.
  • **Dependencies**: WP-T3-24, WP-T3-32.
  • **Size**: L

WP-T3-26: Desktop app hard fork — `@fabricstack/console-desktop`

  • **Objective**: Land t3:apps/desktop (258 files — R2 §11) as @fabricstack/console-desktop at apps/console-desktop: Electron shell wrapping the console-web renderer, with the DesktopBackendManager/Pool pattern (t3:apps/desktop/src/backend/{DesktopBackendManager,DesktopBackendPool,DesktopServerExposure}.ts) bundling and spawning the **fabric** environment server — fabric's single-node desktop story (serves D3 Form A; packaging productization is spec 40 P-03…P-08). IPC stays typed by the contracts fork's ipc.ts (1,388 LOC — R2 §5). Native-module discipline preserved: Electron main loads no native modules; native capability in deadline-bounded children (t3:docs/internals/overview.md:105-110). Snapshot/browser-import native helpers (browser-secret, hyprland/kde snap-shot) are pruned per §2 exclusions.
  • **Affected paths**: new apps/console-desktop/ (fork: src/backend/, src/electron/, src/ssh/, src/wsl/; src/snapShot/, src/preview/ pruned); bundles apps/environment build output.
  • **Acceptance criteria**: (1) desktop app launches, spawns its bundled environment server, and drives a full run locally with no external services; (2) IPC surface compiles against @fabricstack/contracts ipc.ts; (3) Electron main native-module import graph is empty (build-time assertion); (4) ssh remote-connect flow works against WP-T3-28's package (desktop-owned lifecycle — t3:docs/internals/remote.md:47-50); (5) pruned trees absent (grep gate).
  • **Test requirements**: Electron smoke e2e (launch → local run → quit, no orphan processes); backend-manager lifecycle unit tests; IPC type-compile gate.
  • **Dependencies**: WP-T3-19, WP-T3-25; ssh flow needs WP-T3-28.
  • **Size**: L

WP-T3-27: genty shell retirement + protocol-copy deletion

  • **Objective**: Execute §5: delete the 7 device shells + genty/desktop-app scaffold (fabric:packages/genty/desktop-app/package.json:9-13) immediately; delete genty/web-app after WP-T3-25's Playwright parity bar is met; delete genty-ui's protocol copy (fabric:packages/genty/ui/src/protocol/v1.ts:1-15); publish the retirement list as the single rename-exemption list (spec 15 §3.2/interaction rule 4).
  • **Affected paths**: delete packages/genty/{desktop-app,web-app} and the mobile/tv/watch shell workspaces (R1 §3.3 inventory); packages/genty/ui retained but its protocol/transport layer replaced by @fabricstack/client-runtime imports (tui keeps working through the same parity layer); root package.json workspaces pruned; RETIREMENT-LIST.md at repo root consumed by the WP-RN completeness checks.
  • **Acceptance criteria**: (1) shells deleted; workspace install/build green; (2) web-app deletion gated on the recorded parity run (link in closing note) — if parity is not yet green, web-app survives and this WP closes partially with the survivor named on the retirement list (spec 15 §3.2 contingency); (3) repo-wide grep for genty/ui/src/protocol imports returns zero; genty-ui + tui suites green on client-runtime imports; (4) wildcard deps that pointed at retired shells are gone (genty/desktop-app/package.json:16, genty/web-app/package.json:15 — R1 HYG2 partial relief, remainder is P-02); (5) RETIREMENT-LIST.md matches exactly what was deleted/kept.
  • **Test requirements**: full PR CI on the deletion commit; genty-tui/ui suites; Playwright parity evidence attached.
  • **Dependencies**: WP-T3-24, WP-T3-25.
  • **Size**: M

WP-T3-28: `@fabricstack/ssh` extraction (tracked fork)

  • **Objective**: Land t3:packages/ssh (10 files, 4,143 LOC, 100% Effect — R2 §10) as @fabricstack/ssh at packages/ssh: auth, command execution, config, tunnels; remote bootstrap downloads the **fabric** environment server via fabric's release URLs (replacing the cliRelease base URL seam — t3:packages/ssh/src/tunnel.ts:9; fabric's release-asset story is spec 40 P-03/P-04, so bootstrap-download activation is gated on those artifacts existing); client-owned lifecycle: cleanup stops a remote server only if it started it (t3:docs/internals/remote.md:47-50).
  • **Affected paths**: new packages/ssh/ + UPSTREAM.json; plain-TS facade module for non-Effect call sites (B1); the cliRelease URL builder cherry-picked and re-pointed at fabric release endpoints (inert until P-03 ships assets — the facade exposes port-forward/exec/tunnel immediately, bootstrap behind a capability check).
  • **Acceptance criteria**: (1) builds with plain tsc, dep = effect only; (2) port-forward + remote-exec integration test against a local sshd container green; (3) lifecycle rule tested: a pre-existing remote server is not stopped by cleanup; (4) facade exports Promise-based API with zero Effect types (boundary check); (5) bootstrap path unit-tested against a stub release endpoint and marked capability-gated pending P-03.
  • **Test requirements**: sshd-container integration suite in CI; facade type test.
  • **Dependencies**: WP-T3-01, WP-T3-32.
  • **Size**: M

WP-T3-29: `@fabricstack/tailscale` extraction (tracked fork)

  • **Objective**: Land t3:packages/tailscale (763 LOC — R2 §10) as @fabricstack/tailscale at packages/tailscale: wraps the user's tailscale executable (status, serve) with the schema-validated, secret-scrubbing error taxonomy (t3:packages/tailscale/src/tailscale.ts:10-31); doctrine adopted as-is — tailscale is "an endpoint for ordinary pairing", not a separate environment type (t3:docs/internals/remote.md:43-45).
  • **Affected paths**: new packages/tailscale/ + UPSTREAM.json; plain-TS facade (B1); environment-server integration point (advertise the environment on the tailnet, pairing terminates in WP-T3-30 auth).
  • **Acceptance criteria**: (1) builds with plain tsc, dep = effect only; (2) error taxonomy scrubbing verified: a fixture tailscale status output containing auth keys yields errors with secrets redacted (unit test); (3) serve wrapper integration-tested against a stubbed CLI; (4) no separate environment type introduced — pairing over tailscale uses the identical WP-T3-30 grant flow (integration test).
  • **Test requirements**: stub-CLI unit suite; secret-scrub fixtures; pairing-equivalence test with WP-T3-30.
  • **Dependencies**: WP-T3-01, WP-T3-32; equivalence test needs WP-T3-30.
  • **Size**: S

WP-T3-30: Environment auth — DPoP + pairing grants replacing gateway token auth + short-code pairing

  • **Objective**: Adopt t3:apps/server/src/auth/ (DPoP proofs dpop.ts, pairing grants PairingGrantStore.ts, persisted auth sessions with scopes/thumbprint/expiry — t3:apps/server/src/persistence/AuthSessions.ts:1-30, AuthPairingLinks.ts:19-31, per-method RPC authorization RpcAuthorization.ts; "authentication of a socket does not authorize every method on it" — t3:docs/internals/overview.md:18-19) as the environment's auth, **upgrading in place** the gateway's short-code pairing UX slot (fabric:packages/adapters/gateway/src/pairing/short-code.ts:1-20; frames v1.ts:110-122) to DPoP-bound grants, and retiring gateway bearer tokens (fabric:packages/adapters/gateway/src/auth/{tokens,middleware,bootstrap,hashing}.ts).
  • **Affected paths**: apps/environment/src/auth/ (landed in WP-T3-19's tree, activated and integrated here); deletion of the gateway auth/pairing modules with WP-T3-21; client pairing flow in packages/client-runtime (pairing UX slot preserved: short human-friendly code initiates a grant, but the grant is DPoP-bound, one-time, TTL'd, scoped).
  • **Acceptance criteria**: (1) pairing e2e: client generates DPoP keypair → enters short code → receives grant → establishes scoped session; replayed grant fails (one-time); expired grant fails (TTL); (2) per-method authorization enforced: a standard-scope session calling an admin-scoped RPC is rejected (matrix test over scope×method samples); (3) stolen-token uselessness: a captured session token without the DPoP private key fails proof verification (test); (4) zero bearer-token auth code remains in the serving path (grep gate after WP-T3-21 completes); (5) secrets stored via the OS credential store seam (t3:apps/server/src/auth/ServerSecretStore.ts + @napi-rs/keyring — R2 §3.3).
  • **Test requirements**: auth conformance suite (grant lifecycle, DPoP proofs, scope matrix); client-runtime pairing e2e.
  • **Dependencies**: WP-T3-19, WP-T3-21, WP-T3-24.
  • **Size**: L

WP-T3-31: Relay hard fork — `@fabricstack/relay` with kradle org identity + trust-core envelopes

  • **Objective**: Land t3:infra/relay (78 files, 27,381 LOC — R2 §12) as @fabricstack/relay at infra/relay with the two Gate-A substitutions: (a) Clerk replaced by kradle org identity — the relay scopes environments to orgs (org-scoping.js:5) and authenticates against the kradle control plane; (b) the @noble/curves signing protocol re-anchored on trust-core key/chain machinery (fabric:packages/trust-core/src/index.ts:1-7) so fabric ships one PKI. The broker-not-proxy trust model is adopted verbatim: relay mints nothing, never sees session tokens, one-time bootstrap credential bound to the client's DPoP key, cloudflared managed tunnels expose only a validated loopback origin, no application-traffic proxying after bootstrap (t3:docs/internals/t3-connect.md:3-33); tunnel lifetime rules per t3-connect.md:41-56. Environment-side cloud/ module (managed tunnel runtime t3:apps/server/src/cloud/ManagedEndpointRuntime.ts:77, startup reconciliation, CLI tokens, self-update handoff) activates in apps/environment.
  • **Affected paths**: new infra/relay/ (Cloudflare Worker + @effect/sql-pg/drizzle persistence; Clerk modules deleted as divergence; relaySigning cherry-picked under infra/relay/src/shared/ and rebuilt on trust-core primitives); apps/environment/src/cloud/ activation; kradle org-identity federation endpoint (environment↔org linking anchored in the control plane — R4 §D.4.2); ops story (Worker + Postgres + cloudflared) documented for spec 40/50 consumption.
  • **Acceptance criteria**: (1) full broker flow e2e on a staging deployment: environment publishes → client (authenticated via kradle org identity) requests access → relay brokers one-time DPoP-bound bootstrap credential → client redeems **directly** with the environment → session established; relay logs prove it never held a session token; (2) envelope signatures verify against trust-core chains both directions; a foreign-signed envelope is rejected (tamper test); (3) org scoping: client of org A cannot discover/bootstrap org B's environments; (4) managed tunnel exposes only the validated loopback origin (probe test against other ports); (5) zero Clerk and zero standalone-noble-PKI code (grep gates; @noble/* may remain as a crypto primitive only where trust-core itself uses it); (6) after bootstrap, application traffic bypasses the relay (network assertion in e2e).
  • **Test requirements**: relay unit suite (forked upstream tests adapted); staging broker e2e; tamper suite; org-isolation matrix.
  • **Dependencies**: WP-T3-19, WP-T3-30; identity federation needs WP-T3-20.
  • **Size**: L

WP-T3-32: Effect toolchain baseline — pin ownership, npm-workspaces integration, app-build re-platform, engine floors

  • **Objective**: Own B5 and the toolchain divergence (R2 §18.12) in two stages. **Stage 1 (blocks WP-T3-01)**: single workspace-wide pin effect@4.0.0-rc.115 + the one local patch (t3:patches/effect@4.0.0-rc.115.patch) and patched @effect/vitest, ported from pnpm patchedDependencies to an npm-workspaces-compatible patch mechanism; inventory of the 23 upstream patches with the 19 mobile-only ones dropped; unstable-namespace usage register (effect/unstable/{rpc,sql,process,cli,http} — R2 §15) with a named owner and an rc→stable transition watch item. **Stage 2 (blocks WP-T3-19/25/26)**: apps re-platform decision executed — stock Vite + vitest + fabric's tsc replace vite-plus (vite: npm:@voidzero-dev/vite-plus-core is Voidzero-private — R2 §15) and TS7/tsgo; Node floors encoded: workspace engines ≥22.16 (environment server ^22.16 || ^23.11 || >=24.10 — R2 §15), node:sqlite ≥22.5, SEA-build-host ≥25.7 recorded for spec 40's P-03 (R3 spec input 5).
  • **Affected paths**: root package.json (overrides + patch wiring + engines), patches/ directory, CI setup steps (Node version matrix in ci.yml/live-stack.yml); per-app vite.config.ts replacements in apps/console-web, apps/console-desktop, apps/environment build scripts; docs/EFFECT-BASELINE.md (pin, patch provenance, unstable-namespace register, upgrade playbook).
  • **Acceptance criteria**: (1) exactly one resolved effect version across the workspace (npm ls effect singleton test in CI); (2) the local patch applies and a patched-behavior regression test passes (the test encodes what the patch changes, so an upgrade that silently drops it fails); (3) all five tracked forks + apps/environment compile and test under stage-1 tooling; (4) console-web production build succeeds on stock Vite with no @voidzero-dev/* in the dependency graph (grep gate); (5) CI Node matrix enforces the floors (a sub-floor Node run fails the engines check); (6) the baseline doc names the pin owner and the rc→stable criteria.
  • **Test requirements**: singleton-version test; patch-regression test; toolchain build matrix over the three apps.
  • **Dependencies**: stage 1: WP-RN-03/04 (registry + guards); stage 2: WP-T3-01.
  • **Size**: L

WP-T3-33: Provider maintenance adoption — installers/updaters, usage/quota ingestion, model manifest

  • **Objective**: Adopt the cross-cutting provider services (R2 §4): installer/updater machinery with updater-ownership proofs (t3:apps/server/src/provider/providerMaintenance.ts), the usage/quota ingestion subsystem (t3:apps/server/src/usage/, 11 files/3.9k LOC — R2 §3), ModelManifest.ts + model-manifest.json classification, RuntimeInstructions.ts per-provider prompt injection, and the injected MCP control endpoint (t3:apps/server/src/mcp/McpProviderSession.ts:1-12) — integrated with fabric's existing surfaces: install flows merge with fabric:packages/adapters/codecs/src/adapter-install.ts (import at base-adapter.ts:43 today), usage records flow into fabric cost records (run-handle.ts:9,21-27), and model metadata **feeds from the atlas graph where fabric already derives it** rather than forking a second static source (§3.4.5; the static model-manifest.json becomes an atlas-fed projection, not a rival registry — guards the ~201-literal backlog from growing).
  • **Affected paths**: apps/environment/src/provider/ maintenance/usage/mcp modules (activated from the WP-T3-19 tree); packages/adapters/codecs/src/lanes/*/install.ts seams; atlas-fed manifest bridge in packages/adapters/core; per-provider auth flows (ProviderAuthService pattern) wired to lane auth detection (adapter-types.ts:42 successor).
  • **Acceptance criteria**: (1) one-click provider update honors ownership proofs: fabric updates only binaries it installed; user-managed installs (e.g. Cursor's self-updater — WP-T3-07) are surfaced-but-not-touched (test per policy); (2) usage/quota ingestion produces rolling-window records surfaced through contracts (providerUsageLimits.ts shapes — R2 §5) **and** projected into fabric cost summaries (one source, two views — golden test); (3) the injected MCP endpoint appears in each drive-lane session with a scoped bearer, and tool calls through it are policy-gated via WP-T3-17 (test); (4) model classification resolves through the atlas bridge with model-manifest.json as fallback fixture only (grep: no lane reads the JSON directly); (5) new lanes introduce zero new hardcoded harness literals (backlog diff against docs/hard-coded-and-should-be-in-graph-gaps-backlog.md categories).
  • **Test requirements**: installer ownership-proof suite; usage-ingestion golden tests; MCP-injection policy-gate e2e.
  • **Dependencies**: WP-T3-05, WP-T3-06, WP-T3-17, WP-T3-19.
  • **Size**: L

---

10. Cross-spec obligations honored (D21 checklist)

  • Every landed unit uses a spec 15 §3.3 name; WP-T3-01 is gated by WP-RN-08; WP-T3-02…33 depend transitively (spec 15 §5 rules 1–2 satisfied).
  • No WP waits on RN-2…RN-5 (rule 3); migrated units join those sweeps.
  • The WP-T3-27 retirement list is the single rename-exemption list (rule 4).
  • No WP touches the public repo (intent acceptance criterion 7); publishing targets only Artifact Registry (D19).
  • Spec 20 cross-refs: F-16 (remote-access coverage) ↔ WP-T3-28…31; F-18 (red lanes) ↔ WP-T3-07/08/09/12; F-17 (commander) explicitly not a migration item (§7). Spec 30 cross-refs: Q-07 (receipts/DrainableWorker/mock-agent patterns) seeded by WP-T3-03/19; Q-09 (projection goldens, frame↔RPC equivalence, hook-API parity) anchored by WP-T3-14/21/24. Spec 40: P-03…P-08 consume WP-T3-26/28 and §2 row 12; P-12 extends WP-T3-01's license machinery.

Work-package count in this spec: **33** (WP-T3-01 … WP-T3-33).

Article source

The article body is owned directly by this record.

Related pages

No related wiki pages for this record.

Shortcuts

Open overview
Open JSON
Open graph