II.
Page JSON
Structured · livepage:docs-specs-platform-gaps-research-synthesis-adoption-proposal
Synthesis: t3code adoption-model proposal + five-spec outline (Gate A) json
Inspect the normalized record payload exactly as the atlas UI reads it.
{
"id": "page:docs-specs-platform-gaps-research-synthesis-adoption-proposal",
"_kind": "Page",
"_file": "wiki/docs/specs/platform-gaps/research/synthesis-adoption-proposal.md",
"_cluster": "wiki",
"attributes": {
"nodeKind": "Page",
"sourcePath": "docs/specs/platform-gaps/research/synthesis-adoption-proposal.md",
"sourceKind": "repo-docs",
"title": "Synthesis: t3code adoption-model proposal + five-spec outline (Gate A)",
"displayName": "Synthesis: t3code adoption-model proposal + five-spec outline (Gate A)",
"slug": "docs/specs/platform-gaps/research/synthesis-adoption-proposal",
"articlePath": "wiki/docs/specs/platform-gaps/research/synthesis-adoption-proposal.md",
"article": "\n# Synthesis: t3code adoption-model proposal + five-spec outline (Gate A)\n\nDate: 2026-09-27 · Status: **Gate A decision document** (D16) · Author: platform-gaps spec synthesis run\nBinding intent: `docs/specs/platform-gaps/00-intent.md` (D1–D16, verbatim). Inputs consumed in full:\n\n| Dossier | Path | Cited as |\n|---|---|---|\n| R1 — fabric current state + audit refresh | `research/fabric-current-state.md` | R1 §n / `fabric:path:line` |\n| R2 — t3code architecture | `research/t3code-architecture.md` | R2 §n / `t3:path:line` |\n| R3 — packaging state | `research/packaging-state.md` | R3 §n |\n| R4 — interface delta map | `research/delta-map.md` | R4 Row A–D / spec input n |\n\nEvery 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.\n\n---\n\n## 1. Per-component adoption model (D1)\n\nD1 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.\n\n### 1.1 `adapters` — harness-driving layer (D2a, D6)\n\n**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.**\n\nShape (R4 §A.6, R4 spec inputs 1–4):\n\n1. **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`):\n - **ACP lane**: generic runtime + per-harness extension modules, copied from t3code's `AcpSessionRuntime` + `CursorAcpExtension`/`XAiAcpExtension` pattern (R2 §4).\n - **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`.\n - **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`.\n - **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`.\n - **Retained-subprocess lane** (fabric-only): the surviving codec adapters for harnesses t3code does not cover, migrated behind the new contract (R4 spec input 3).\n2. **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.\n3. **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).\n4. **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).\n\n**Lane decision for ALL 16 harnesses** (t3code's 6 per R2 §4/§18.1; fabric's 10 extras per R4 spec input 3):\n\n| # | Harness | Today in fabric | Proposed lane | Evidence / notes |\n|---|---|---|---|---|\n| 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`) |\n| 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`) |\n| 3 | Cursor | codec `cursor-adapter.ts` + hook adapter; lane failing (#562) | **ACP lane** | `cursor-agent … acp` (`t3:provider/acp/CursorAcpSupport.ts:56-60`) |\n| 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) |\n| 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` |\n| 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) |\n| 7 | Gemini (CLI) | subprocess codec + hook adapter | **Retained-subprocess lane** | no ACP evidence in dossiers; re-evaluate for ACP promotion post-migration |\n| 8 | Copilot (CLI) | subprocess codec + hook adapter | **Retained-subprocess lane** | same |\n| 9 | Pi | subprocess codec + hook adapter; live-stack push default | **Retained-subprocess lane** | same |\n| 10 | Oh-My-Pi | hook adapter `adapter-oh-my-pi` | **Retained-subprocess lane** | see aliasing note below |\n| 11 | OMP | codec + live-stack lane id `omp` | **Retained-subprocess lane** | see aliasing note below |\n| 12 | OpenClaw | subprocess codec + hook adapter | **Retained-subprocess lane** | no t3code counterpart (R4 §A.3) |\n| 13 | Hermes | subprocess codec + hook adapter | **Retained-subprocess lane** | same |\n| 14 | Droid | subprocess codec + live-stack lane (no hook adapter) | **Retained-subprocess lane** | codec-only today (R1 §4.3 vs §3.1) |\n| 15 | Amp | subprocess codec + live-stack lane (no hook adapter) | **Retained-subprocess lane** | codec-only today |\n| 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 |\n\n*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.\n\n**Alternatives considered:**\n- *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.\n- *Implement-contracts only, hand-writing ACP*: rejected. `effect-acp` (5.2k handwritten LOC, dep = `effect` only) and `effect-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).\n- *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.\n\n**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.\n\n### 1.2 `kradle` control surfaces (D2b)\n\n**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.**\n\nShape (R4 §B.6, R4 spec inputs 5–8):\n\n1. **Environment-server-under-plane topology**: kradle's `agent-dispatch-controller`/`agent-workspace-controller` become environment *clients* dispatching `OrchestrationCommand`s 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.\n2. **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.\n3. **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).\n4. **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).\n5. **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.\n6. **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.\n\n**Alternatives considered:**\n- *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).\n- *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.\n- *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.ts` proves 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.\n\n**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.\n\n### 1.3 `genty` client shells (D2c, D13)\n\n**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).**\n\nShape (R4 §C.6, R4 spec inputs 9–10; R1 spec input 7):\n\n1. **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.\n2. **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).\n3. **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).\n4. **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).\n\n**Alternatives considered:**\n- *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.\n- *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\").\n- *Also adapt `apps/mobile` now*: 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.\n\n**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).\n\n### 1.4 Remote access (D2d, D12)\n\n**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.**\n\nShape (R4 Row D, R4 spec input 11; R2 §10, §12, §18.6):\n\n1. **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.\n2. **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).\n3. **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).\n4. **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).\n\n**Alternatives considered:**\n- *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.\n- *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).\n- *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).\n\n**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.\n\n### 1.5 Cross-cutting: packaging-form priority (D3, proposed here for the packaging spec to inherit)\n\n**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.\n\n---\n\n## 2. Per-package Effect-TS stance (D5) and fork posture (D9)\n\n### 2.1 Boundary rules (D5) — proposed as binding for all five specs\n\nDerived from R4 spec input 13 and R2 §15/§18.3:\n\n- **B1 — Plain-TS adapter contract.** The fabric-facing adapter contract (successor of `adapter-types.ts` / `run-handle.ts`) exposes Promise/AsyncIterable only, exactly as `RunHandle` does today. No Effect type ever crosses it.\n- **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).\n- **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.)\n- **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.\n- **B5 — One pinned Effect, centrally owned.** t3code pins `effect@4.0.0-rc.115` **with a local patch** plus `effect/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.\n- **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).\n\n### 2.2 Per-package stance table\n\n| Unit (in fabric after adoption) | Origin | D5 Effect stance | D9 fork posture | Why (evidence) |\n|---|---|---|---|---|\n| 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) |\n| 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 |\n| 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) |\n| 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) |\n| tailscale | `t3:packages/tailscale` | **Adopt**, plain-TS facade | **Tracked fork** | 763 LOC, wraps user CLI, secret-scrubbing error taxonomy worth tracking (R2 §10) |\n| 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 |\n| 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 |\n| 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 |\n| 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) |\n| relay | `t3:infra/relay` | **Adopt** (91%) | **Hard fork** | Clerk→kradle-org identity and noble→trust-core substitutions are structural (§1.4.2) |\n| 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) |\n| 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) |\n| adapters core (contract + projection) | fabric | **Plain TS** (B1/B4) | n/a (fabric-native) | Contract surface + `AgentEvent` projection stay Promise/AsyncIterable (R4 spec input 13) |\n| 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 |\n| kradle-web | fabric | Plain TS; consumes contracts-generated types only (B3) | n/a | Survives as org-admin (R4 spec input 10) |\n\n**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.\n\n---\n\n## 3. Refreshed-audit survivor register (D8) — definitive\n\nR1 §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**.\n\nThis 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.\n\n| ID | Verdict | One-line surviving objective | Absorbed by |\n|---|---|---|---|\n| C1 | STILL-VALID | Verify journal checksums on load (`journal.ts:151-161` only parses) | F-01 |\n| C2 | STILL-VALID | Sign journal events (trust-core exists; journal bypasses it) | F-02 |\n| C3 | STILL-VALID | Attestation anchor default-on + loud journaled \"disabled\" marker | F-03 |\n| H1 | STILL-VALID | Hash-chain events; detect tail truncation | F-01 |\n| H2 | STILL-VALID | Invocation keys must digest arg values, not shapes | F-04 |\n| H3 | STILL-VALID | Stable task keys under inserted steps (occurrence-index drift) | F-04 |\n| H4 | STILL-VALID | Replay key mismatch must not silently re-execute | F-04 |\n| H5 | STILL-VALID | Cancellation must kill live processes (journal-only today) | F-05 |\n| H6 | STILL-VALID | Enforce configured effect timeouts at dispatch | F-05 |\n| H7 | CHANGED | Stop-hook must use marker-precedence session resolution (env still shadows) | F-06 |\n| H8 | CHANGED | Cross-process lock for session read-modify-write | F-06 |\n| H9 | CHANGED | trust-core chain verifier gains `requiredRootKind` (human-root only enforced one layer up) | F-08 |\n| H10 | CHANGED | Attestation producers default-on (wired but opt-in) | F-03 |\n| M1 | STILL-VALID | Cancel-vs-complete race: typed idempotent precedence | F-07 |\n| M2 | STILL-VALID | Bounded parallel: preserve `undefined` results/positions | F-07 |\n| M3 | STILL-VALID | Parallel strategies must aggregate sibling errors | F-07 |\n| M4 | STILL-VALID | Background commits need incarnation guard | F-07 |\n| M5 | STILL-VALID | Hook timeout: SIGKILL escalation, no hang-on-close | F-05 |\n| M6 | CHANGED | Cross-reference `runState.processId` liveness (24h staleness remains for non-terminal runs) | F-06 |\n| M7 | STILL-VALID | Per-session discriminator in PID markers | F-06 |\n| M8 | STILL-VALID | Policy gates fail closed for uncovered actions | F-03 |\n| S1 | STILL-VALID | Scope unhandledRejection capture per run | F-07 |\n| S2 | STILL-VALID | `resolveAmbientSessionId(undefined)` must not be env-first | F-06 |\n| S3 | STILL-VALID (INFERRED) | Guard un-keyed same-shape conditional skipping | F-04 |\n| S4 | STILL-VALID (INFERRED) | Remove ambiguous stop-hook stale-retry against raw env | F-06 |\n| S5 | STILL-VALID | Thread spawning to SDK cancellation | F-05 |\n| S6 | STILL-VALID | Canonical-JSON checksum canonicalization | F-01 |\n| CAP1 | STILL-VALID | Unify the three-way memory split (kip-sdk / genty JSON / kradle AgentMemory) — force the ADR | F-09 |\n| CAP2 | STILL-VALID | Pre-dispatch budget enforcement | F-10 |\n| CAP3 | STILL-VALID | Campaigns / scheduler-preemption entities | F-11 |\n| CAP4 | STILL-VALID | Improvement outer loop (history→eval→compare→promote) | F-12 |\n| CAP5 | CHANGED | Inference scale-to-zero (virtual-model routing landed) | F-13 |\n| CAP6 | CHANGED | Wire session pause/resume/fork/rewind into the loop | F-14 |\n| KIP-TODO | STILL-VALID | KeyAuthorization chain / manifest CID / durability TODOs (`kip-repo.ts:4063-4075`) | F-15 |\n| TEST1 | CHANGED | Wire remaining ungated suites into CI (kip/atlas/library/shared/kradle-web/…) | Q-01 |\n| TEST2 | STILL-VALID | Adversarial ledger tests (recommended, not the D7 bar) | Q-08 |\n| HYG1 | CHANGED | Redaction in the general logging layer (`observability/logger.ts` has none) | F-22 |\n| HYG2 | CHANGED | Eliminate wildcard workspace deps; version-pin discipline | P-01/P-02 |\n| HYG3 | STILL-VALID | Build-time duplicate-task-id scan | F-23 |\n| HYG4 | STILL-VALID | Remove Windows-invalid colon-path blobs (company repo) | F-23 |\n\n---\n\n## 4. The five specs and their work-package inventories\n\nNumbering: `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).\n\n### 4.1 `10-t3code-migration.md` — 33 WPs\n\nCovers, per migrated unit: adoption model, Effect stance, fork posture, license/attribution, ACP-canonical re-platforming (intent acceptance criterion 4).\n\n| ID | Title |\n|---|---|\n| T-01 | Fork intake: import tracked-fork units, upstream-pin manifest, third-party attribution items (D15, MIT/T3 Tools Inc.) |\n| T-02 | Contracts tracked fork: package landing, fabric RPC-group extensions, capability-flag doctrine adoption |\n| T-03 | effect-acp tracked fork + schema regeneration pipeline |\n| T-04 | effect-codex-app-server tracked fork + regeneration pipeline |\n| T-05 | ProviderAdapter-equivalent contract replacing `BaseAgentAdapterInterface`/`RunHandle` surface (plain-TS per B1) |\n| T-06 | Generic ACP lane runtime + per-harness extension-module pattern |\n| T-07 | Cursor ACP lane (retire `cursor-adapter.ts` codec) |\n| T-08 | Grok Build ACP lane — net-new harness (D7(a) requirement) |\n| T-09 | Antigravity ACP lane + managed installer (version leases, identity verification) |\n| T-10 | Claude SDK lane (in-process query, permission callbacks, history child worker) |\n| T-11 | Codex app-server lane (retire websocket/SDK codecs) |\n| T-12 | OpenCode HTTP lane (server-per-thread ownership model) |\n| 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 |\n| T-14 | AgentEvent projection layer: normalizer → 49-type union as derived view; consumer acceptance suite |\n| T-15 | Observe-lane rebind: 12 hook adapters feed the projection unchanged |\n| T-16 | Journal sovereignty enforcement: run identity/provenance stays in the babysitter journal across all lanes |\n| T-17 | Trust-signed policy gating wired into drive-lane permission callbacks (no bypass of proven-bridge) |\n| T-18 | Fabric-as-ACP-agent: expose runs/genty sessions via the effect-acp agent service (genty lane #16) |\n| T-19 | Environment server hard fork: orchestration/persistence/auth/checkpointing/terminal subset landing in fabric |\n| T-20 | Kradle↔environment boundary: environment descriptor + capability flags; dispatch/workspace controllers become environment clients |\n| T-21 | Gateway fold-in: 17-frame → contracts RPC-group mapping; gateway retired or reduced to shim |\n| T-22 | kradle-web route program: type-or-replace the 81 untyped routes against the contracts fork |\n| T-23 | Approval mapping: pending-approvals ↔ 7-action AgentApproval ↔ signed breakpoints (preserving fabric-only actions) |\n| T-24 | client-runtime hard fork: kradle-sourced connection catalog; genty-ui hook-API parity layer |\n| T-25 | Web app hard fork: run/thread UX, composer/diff/terminal, fabric theming and org semantics |\n| T-26 | Desktop app hard fork: DesktopBackendManager bundling the fabric environment server |\n| T-27 | genty shell retirement: 7 device shells + desktop scaffold + web-app (after Playwright parity) + protocol-copy deletion |\n| T-28 | ssh package extraction (tracked fork) |\n| T-29 | tailscale package extraction (tracked fork) |\n| T-30 | Environment auth: DPoP + pairing grants replacing gateway token auth + short-code pairing |\n| T-31 | Relay hard fork: kradle-org identity replacing Clerk; trust-core envelope verification; cloudflared managed tunnels |\n| T-32 | Effect toolchain baseline: effect@4-rc pin + patch ownership, npm-workspaces integration, vite-plus divergence resolution, node:sqlite/Node-engine floors |\n| T-33 | Provider maintenance adoption: installers/updaters with ownership proofs, usage/quota ingestion, model manifest |\n\n### 4.2 `20-functionality-coverage.md` — 23 WPs\n\nAbsorbs 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.\n\n| ID | Title |\n|---|---|\n| F-01 | Journal integrity: checksum verification on load, hash chain, canonical JSON (C1, H1, S6) |\n| F-02 | Journal event signing via trust-core (C2) |\n| F-03 | Attestation default-on posture + fail-closed policy gates (C3, H10, M8) |\n| F-04 | Replay key correctness: value digests, stable keys, mismatch detection (H2, H3, H4, S3) |\n| F-05 | Execution control: cancellation kills processes, timeout enforcement, SIGKILL escalation (H5, H6, M5, S5) |\n| F-06 | Session integrity: marker precedence, cross-process locking, liveness-based cleanup (H7, H8, M6, M7, S2, S4) |\n| F-07 | Parallel/async semantics: result alignment, error aggregation, incarnation guards, scoped rejection capture (M1–M4, S1) |\n| F-08 | trust-core human-root requirement in the chain verifier (H9) |\n| F-09 | Memory unification ADR + implementation: kip-sdk / genty long-term-memory / kradle AgentMemory (CAP1) |\n| F-10 | Pre-dispatch budget enforcement (CAP2) |\n| F-11 | Campaigns and scheduler-preemption entities (CAP3) |\n| F-12 | Improvement outer loop: history→eval→compare→promote (CAP4) |\n| F-13 | Inference scale-to-zero (CAP5 residual) |\n| F-14 | Session pause/resume/fork/rewind wired into the agent loop (CAP6) |\n| F-15 | KIP security completion: KeyAuthorization chain, manifest CID, durability tiers (KIP-TODO) |\n| F-16 | Hosted remote access coverage (D12 — guaranteed): four-route story, cross-ref T-28…T-31 |\n| F-17 | Commander disposition: wire to live gateway/kradle per SPEC-LIVE-BACKEND or descope formally |\n| F-18 | Harness matrix remediation: Cursor (#562), OpenCode, Antigravity (#945) red lanes to green; Grok coverage (with T-08) |\n| F-19 | Agent-layer gap absorption: the 47 `docs/agent-layer-gaps.md` items by category (streaming, multi-turn history, token usage, …) |\n| F-20 | Hardcoded-literals→atlas graph backlog (~201 literals) |\n| F-21 | Realtime media plane: control-plane-real/media-stub closure per `docs/research/realtime-agent-gaps.md` |\n| F-22 | Secret redaction in the general logging layer (HYG1 residual) |\n| F-23 | Hygiene closure: duplicate-task-id CI scan, company-repo colon paths (HYG3, HYG4) |\n\n### 4.3 `30-testing.md` — 9 WPs\n\nBar 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.\n\n| ID | Title |\n|---|---|\n| 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) |\n| Q-02 | Zero-test package floors: adapters-config, adapters-launch, kradle-sdk, kradle-cli; fill `multi-execution.ts` (0 lines) |\n| Q-03 | Live per-harness e2e matrix to D7(a): six harnesses green incl. new Grok lane |\n| Q-04 | Whole-platform e2e: packaged install → create run → dispatch → agent session → journal → UI assertions (D7(b) — no such lane exists) |\n| Q-05 | UI e2e gating: observer-dashboard Playwright, kradle-web specs, commander suite into CI |\n| Q-06 | Unit floors + coverage gates per package, agreed floors wired into ci.yml/publish.yml job map (D7(c)) |\n| Q-07 | t3code test-pattern adoption: runtime receipts + DrainableWorker instead of sleeps; ACP mock agent for protocol suites |\n| Q-08 | Adversarial ledger suite — recommended, explicitly outside the D7 bar (TEST2) |\n| Q-09 | Migration parity suites: AgentEvent projection golden tests; gateway-frame↔contracts-RPC equivalence; genty-ui hook-API parity |\n\n### 4.4 `40-packaging.md` — 13 WPs\n\nPriorities per §1.5 proposal: C → A → B; all three forms bind (D3).\n\n| ID | Title |\n|---|---|\n| P-01 | Exports-map program across the 43 publishables + `babysitter` bin-collision resolution (Form C prerequisite; lands with D10 major bump) |\n| P-02 | Versioning discipline: wire-or-remove changesets; per-package semver signal atop the lockstep train; HYG2 wildcard-dep elimination |\n| P-03 | Single-executable server build (SEA) + self-contained per-platform archives + SHA256SUMS release flow |\n| P-04 | `install.sh` / `install.ps1`: channel-aware, checksum-verified, versioned runtime layout |\n| P-05 | Background service: systemd-user + linger, launchd; reconciling `service install`; Windows explicitly out of service scope |\n| P-06 | Self-update: launcher-owned two-phase commit with SQLite snapshot rollback |\n| P-07 | npm platform packages + launcher so npm bytes equal release bytes (`npx` zero-install trial) |\n| P-08 | OS package managers (winget/brew/AUR/deb) + uninstall story |\n| P-09 | Helm chart productization: version-with-platform, OCI publication, fold atlas-webui overlay + CRDs + Envoy story into one installable bundle |\n| P-10 | kradle-installer alignment: consume the published chart, decouple from CI flags and repo paths |\n| P-11 | Release trains: stable/nightly/preview with nightly-promotion, mapped onto the existing single version resolver + tag discipline |\n| P-12 | Third-party license/attribution machinery (D15): adopt `third-party-licenses.config.json` + sync script; cover all adopted units |\n| P-13 | Artifact-home decision: public babysitter vs private fabric for GitHub-Release binaries and OCI charts (split-repo constraint) |\n\n### 4.5 `50-roadmap-workpackages.md` — 3 WPs\n\n| ID | Title |\n|---|---|\n| R-01 | Dependency graph + critical path over all WPs, sequenced per D11 (migration → coverage → testing → packaging) |\n| R-02 | Milestone/release-train mapping incl. the D10 major-bump cutover point and tracked-fork upstream-review cadence |\n| R-03 | Gate-B compliance matrix: every WP and spec section traced against D1–D16 verbatim |\n\n### 4.6 Total\n\n**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.)\n\n---\n\n## 5. Risks and open points for the Gate A conversation\n\n1. **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.\n2. **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.\n3. **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.\n4. **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.\n5. **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.\n6. **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.\n",
"documents": []
},
"outgoingEdges": [],
"incomingEdges": [
{
"from": "page:docs",
"to": "page:docs-specs-platform-gaps-research-synthesis-adoption-proposal",
"kind": "contains_page"
}
]
}