Agentic AI Atlasby a5c.ai
OverviewWikiGraphFor AgentsEdgesSearchWorkspace
/
GitHubDocsDiscord
iiRecord
Agentic AI Atlas · WP-T3-32 stage 1 record: Effect toolchain baseline (pin, patch port, register)
page:docs-specs-platform-gaps-phase0-effect-baselinea5c.ai
Search record views/
Record · tabs

Available views

II.Record viewspp. 1 - 1
overviewarticlejsongraph
II.
Page JSON

page:docs-specs-platform-gaps-phase0-effect-baseline

Structured · live

WP-T3-32 stage 1 record: Effect toolchain baseline (pin, patch port, register) json

Inspect the normalized record payload exactly as the atlas UI reads it.

File · wiki/docs/specs/platform-gaps/phase0/effect-baseline.mdCluster · wiki
Record JSON
{
  "id": "page:docs-specs-platform-gaps-phase0-effect-baseline",
  "_kind": "Page",
  "_file": "wiki/docs/specs/platform-gaps/phase0/effect-baseline.md",
  "_cluster": "wiki",
  "attributes": {
    "nodeKind": "Page",
    "sourcePath": "docs/specs/platform-gaps/phase0/effect-baseline.md",
    "sourceKind": "repo-docs",
    "title": "WP-T3-32 stage 1 record: Effect toolchain baseline (pin, patch port, register)",
    "displayName": "WP-T3-32 stage 1 record: Effect toolchain baseline (pin, patch port, register)",
    "slug": "docs/specs/platform-gaps/phase0/effect-baseline",
    "articlePath": "wiki/docs/specs/platform-gaps/phase0/effect-baseline.md",
    "article": "\n# WP-T3-32 stage 1 record: Effect toolchain baseline (pin, patch port, register)\n\nExecuted 2026-09-28 on branch `phase0/hard-split-registry-guards` of `a5c-ai/fabric`. Spec: `docs/specs/platform-gaps/10-t3code-migration.md` \"WP-T3-32\" (stage 1: AC1, AC2, AC6; stage 2 out of scope), §2 B5 and the toolchain exclusion list; research `research/t3code-architecture.md` §15 and §18.12 (items 3, 12); intent `00-intent.md` D5, D15, D17–D21; roadmap `50-roadmap-workpackages.md` (WP-T3-32 row \"0→2 (staged)\", M0 exit criterion 5: \"`npm ls effect` resolves a single `effect@4.0.0-rc.115` workspace-wide and the patch-regression test passes\"). Builds on WP-RN-03/04 (registry + guards; the `test` job and the npm/Windows spawning conventions) and WP-RN-08. The public repository `a5c-ai/babysitter` was never written to (`gh api repos/a5c-ai/babysitter --jq .pushed_at` → `2026-09-16T19:59:50Z` at start and end; only GET calls were issued; `git remote -v` → `upstream no_push (push)`), nothing was published anywhere (no `npm publish`, no `npm pack`), no infrastructure changed.\n\nOwner document: `docs/EFFECT-BASELINE.md`. Inventory: `t3code-patches-inventory.md` beside this file.\n\n## What landed\n\n| Item | Where |\n|---|---|\n| Workspace-wide pin `effect@4.0.0-rc.115`, `@effect/vitest@4.0.0-rc.115` | root `package.json` `overrides` + root `devDependencies` (both exact); `package-lock.json` resolves both |\n| Patch mechanism | `patch-package 8.0.1` (root devDependency), `postinstall: patch-package --error-on-fail` |\n| Ported patch | `patches/effect+4.0.0-rc.115.patch` (from t3code `patches/effect@4.0.0-rc.115.patch` at `de251fc2971a884cb5b1305ba4daf309dc8cccb0`); `patches/README.md` states the rules |\n| Attribution (D15) | `third_party/t3code-patches/LICENSE` (verbatim upstream MIT, T3 Tools Inc.) + `PATCHES.md` (provenance), following the `third_party/webpackbar/` convention (`LICENSE` + `PATCHES.md`); the repository has no root THIRD-PARTY/NOTICE file |\n| Tests | `scripts/ci/effect-baseline.test.mjs`, 13 cases, `npm run test:effect-baseline` |\n| CI | `.github/workflows/ci.yml` `test` job, step \"Effect baseline (single pin, patch regression, inventory)\" right after `npm ci` (which runs the postinstall) — the dependency-free `publish-isolation` job cannot host it |\n| Docs | `docs/EFFECT-BASELINE.md` (pin owner, provenance, `@effect/vitest` decision, unstable-namespace register with rc→stable criteria, Node floors as stage-2 input, upgrade playbook, stage-2 deferrals); `t3code-patches-inventory.md` |\n\nNot landed (stage 2, depends on WP-T3-01): apps re-platform on stock Vite/vitest/tsc, `@voidzero-dev/*` grep gate, workspace `engines` ≥22.16 with the sub-floor CI run, the tracked-fork build matrix (AC3, AC4, AC5).\n\n## Pin resolution\n\n`npm install --legacy-peer-deps` (CI's flag; `@effect/vitest@4.0.0-rc.115` declares `peerDependencies.vitest \">=5.0.0 <6.0.0\"` against fabric's `vitest 4.1.6`, so the flag is required, exactly as it is in every CI job) → `added 11 packages, removed 65 packages, changed 13 packages, and audited 3330 packages in 30s`, with the postinstall log:\n\n```text\n> babysitter@6.0.3 postinstall\n> patch-package --error-on-fail\n\npatch-package 8.0.1\nApplying patches...\neffect@4.0.0-rc.115 ✔\n```\n\n`npm ls effect --all`:\n\n```text\nbabysitter@6.0.3 C:\\work\\fabric\n├─┬ @effect/vitest@4.0.0-rc.115 overridden\n│ └── effect@4.0.0-rc.115 deduped\n└── effect@4.0.0-rc.115 overridden\n```\n\n`npm ls @effect/vitest --all` → `└── @effect/vitest@4.0.0-rc.115 overridden`. Before this WP, `npm ls effect --all` printed `(empty)` and `package-lock.json` had no `node_modules/effect` or `node_modules/@effect/*` entry, so the pin is the first Effect dependency in the tree (roadmap risk 1: \"before any Effect code is imported\").\n\n**Lockfile note.** The `package-lock.json` diff removes 45 stale entries unrelated to this WP (`jsdom`, `postject`, `electron-winstaller`, `@anthropic-ai/sdk`, `temp`, …). Proven pre-existing: with this WP's `package.json` and lockfile stashed, `npm install --package-lock-only --legacy-peer-deps --ignore-scripts` on the pristine tree removes the same 45 entries (1,680 deletions). The committed lockfile was simply behind the manifests; `npm run guard:packages` (lockfile sync) passes after the change.\n\n## Patch port\n\nConversion (scratch script, no hand edits): `diff --git a/<f> b/<f>` → `a/node_modules/effect/<f> b/node_modules/effect/<f>`, `--- a/<f>` → `--- a/node_modules/effect/<f>`, `+++ b/<f>` → `+++ b/node_modules/effect/<f>`; every other line untouched. Verified: `diff` of the two files with those three header kinds removed → identical (352 lines each). patch-package's parser (`patch-package/dist/patch/parse.js`) reads 5 file parts, 23 hunks: `dist/unstable/ai/McpServer.js` 2, `dist/unstable/http/HttpClientResponse.js` 1, `dist/unstable/rpc/RpcClient.d.ts` 2, `dist/unstable/rpc/RpcClient.js` 17, `src/unstable/http/HttpClientResponse.ts` 1. Applied on the first `npm install` with no rejected hunk (log above). Post-apply spot checks in `node_modules/effect`: `RequestHooks` ×3 in `RpcClient.js`, `getSetCookie?.() ?? []` in `HttpClientResponse.js:183` and `HttpClientResponse.ts:324`, `router.add(\"DELETE\"` in `McpServer.js`, `missedPongs` in `RpcClient.js:744-753`. The `src/` hunk applies because the published `effect` tarball ships `src/` (checked, not assumed).\n\n**`@effect/vitest` patch not ported — DROPPED-toolchain.** Its 7 hunks are all `\"vitest\"` → `\"vite-plus/test\"` in `dist/` and `src/`; under fabric's stock vitest that is the wrong direction and `vite-plus` is not installed. The unpatched package imports `vitest` (`node_modules/@effect/vitest/dist/index.js:1,6` → `from \"vitest\"`), which test 10 pins. The `vitest >=5 <6` peer range is recorded in `docs/EFFECT-BASELINE.md` §3 as a stage-2 input: the package is locked but not yet runnable as a harness here.\n\n## Inventory counts\n\nAll 23 files of the snapshot's `patches/` directory read hunk by hunk; consumers derived from `grep -l \"<pkg>\" apps/*/package.json packages/*/package.json infra/*/package.json scripts/package.json package.json` in the snapshot. Result: **PORTED 1** (`effect`), **DROPPED-toolchain 1** (`@effect/vitest`), **DROPPED-mobile-only 17**, **DEFERRED-stage-2 4** (`@ff-labs/fff-node` → server / WP-T3-19; `dbus-next` → desktop / WP-T3-26; `@legendapp/list` and `@pierre/diffs` → declared by `t3:apps/web` as well as mobile / WP-T3-25). The brief's \"19 mobile-only\" is therefore **17**: `@legendapp/list` and `@pierre/diffs` are web consumers too (`t3:apps/web/package.json`), and their hunks touch web entrypoints (`react.js`, `react-native.web.*`; `dist/react/utils/useFileInstance.js`). Row 14 notes that fabric's own root carries `expo-notifications ^55` for the retired mobile shells; the upstream patch targets 57.0.15 and does not apply to that line.\n\n## Tests (red, then green)\n\n`npm run test:effect-baseline` → `# tests 13 / # pass 13 / # fail 0 / # duration_ms 5756`. Cases:\n\n| # | Case | Kind |\n|---|---|---|\n| 1 | root manifest: one exact version in `overrides`, mirrored in `devDependencies`, `patch-package --error-on-fail` on postinstall, installed `effect` version equals the pin | manifest |\n| 2 | no workspace manifest declares its own `effect`/`@effect/*` version (B5) | manifest (walks the root `workspaces` list) |\n| 3 | `npm ls effect --all --json` → exactly one version == pin | singleton (AC1) |\n| 4 | `npm ls @effect/vitest --all --json` → exactly one version == pin | singleton |\n| 5 | `import('effect/unstable/rpc/RpcClient')` exports `RequestHooks` with key `effect/rpc/RpcClient/RequestHooks`; `.d.ts` declares it and its four hooks; control: `ConnectionHooks.key` | patch regression, observable (AC2) |\n| 6 | `HttpClientResponse.fromWeb(req, { status, headers: {…} }).cookies` is empty instead of throwing; control: a real `Response` still parses `a=b`; `src/…/HttpClientResponse.ts` carries the fallback | patch regression, observable (AC2) |\n| 7 | pinger: `missedPongs >= 3`, `onPingTimeout`, `makePinger(writePing, hooks)`; `.d.ts` `onPing/onPong/onPingTimeout` | patch regression, source-text fallback (internal to a live socket) |\n| 8 | `McpServer.js`: `router.add(\"DELETE\", options.path, …)`, session delete, and no DELETE in the method-not-allowed routes | patch regression, source-text fallback (needs an HttpRouter + RpcServer stack) |\n| 9 | patch file parses to the 5 files / 23 hunks, only patch-package-named files in `patches/`, `patch-package --error-on-fail` exits 0 naming `effect@4.0.0-rc.115` | patch file |\n| 10 | `@effect/vitest` installed at the pin, imports `vitest`, never `vite-plus`, no `@effect+vitest*.patch` | decision pin |\n| 11 | inventory names all 23 upstream patch files with a decision each, the snapshot SHA, `Total 23`, `PORTED 1` | inventory |\n| 12 | `docs/EFFECT-BASELINE.md` names `effect@4.0.0-rc.115`, \"Pin owner\", \"fabric maintainers (Tal)\", the five namespaces, \"rc→stable\", the upgrade playbook, the snapshot SHA | AC6 |\n| 13 | `ci.yml` runs `npm run test:effect-baseline` after `npm ci --prefer-offline --legacy-peer-deps` | CI wiring |\n\nRed proof (an upgrade that silently drops the patch): `node node_modules/patch-package/index.js --reverse` (→ `RequestHooks` count in `RpcClient.js` = 0), then the suite → `not ok 5`, `not ok 6`, `not ok 7`, `not ok 8`; `# pass 9 / # fail 4`. Case 9 stays green on that tree because it runs `patch-package --error-on-fail` itself and thereby re-applies the patch (count back to 3); cases 5–8, which run first, are the drop detectors, and case 9 turns red when the patch *file* is missing, misnamed for the resolved version, or no longer applies. Re-running the suite after the re-apply → `13 / 13 / 0`.\n\nAlso proven: `patch-package --error-on-fail` on an already-patched tree prints `effect@4.0.0-rc.115 ✔` and exits 0 (so the CI `npm install --no-save …linux optional deps` re-run of postinstall is harmless).\n\n## Docs and guards\n\n- `npx markdownlint-cli2 docs/EFFECT-BASELINE.md docs/specs/platform-gaps/phase0/t3code-patches-inventory.md patches/README.md third_party/t3code-patches/PATCHES.md` → `Summary: 0 error(s)`; `node scripts/docs-style-check.cjs` on the two docs → `issueCount: 0` each; `js-yaml` loads `ci.yml` (jobs `public-push-guard,publish-isolation,docs-quality,test,gateway-node-engine,workspace-coverage,observer-dashboard`; `test` steps `… / Install dependencies / Prepare artifact directories / Effect baseline (single pin, patch regression, inventory) / Lint`).\n- `node scripts/ci/no-double-rename.cjs --self-test` → `repository scan — 59 manifest(s), 0 findings, 0 notice(s), 0 new unit(s)`, `10/10 assertions passed` (no new workspace was added: the pin lives in root `devDependencies`, so no `@fabricstack/*` name question arises).\n- `node scripts/ci/publish-isolation-guard.cjs --self-test` → `self-test passed; repository scan clean (122 files, 0 findings, 8 legacy-train notice(s))`.\n- `node scripts/ci/public-push-guard.cjs` → `scanned 215 files, 0 finding(s), 0 suppressed`.\n- `npm run guard:packages` → `package-integrity guard passed (lockfile sync, native bindings, metadata, arch boundaries)`.\n- `npm run test:publish-guards` → `17 / 17 / 0`; `node --test scripts/__tests__/publishable-packages.test.mjs` → `7 / 7 / 0`; `node scripts/ci/check-spec10-names.cjs --self-test` → passed.\n\n## Judgement calls\n\n1. Root `devDependencies` over a dedicated workspace: matches how the repository holds shared dev tooling, avoids inventing a non-spec unit name (WP-RN-08 gate), and still resolves the pin in the lockfile.\n2. `--error-on-fail` on postinstall: a silently skipped patch is exactly the failure mode AC2 exists to prevent, so the install fails loudly; `npm install --ignore-scripts` bypasses it, which is why the regression test (not only the install) asserts the behaviour.\n3. `@effect/vitest` pinned but unpatched (above). The alternative — carrying the vite-plus patch — would have been a faithful port of something that cannot load here.\n4. The 17-vs-19 mobile-only count is reported as read, not as briefed.\n5. Node floors are quoted and recorded, not enforced: enforcing ≥22.16 is stage 2 (AC5) and would otherwise change `engines` of packages the public train still publishes.\n",
    "documents": []
  },
  "outgoingEdges": [],
  "incomingEdges": [
    {
      "from": "page:docs",
      "to": "page:docs-specs-platform-gaps-phase0-effect-baseline",
      "kind": "contains_page"
    }
  ]
}

Shortcuts

Back to overview
Open graph tab