Xantham Execution Plan — Steps
The steps document. LANDSCAPE.md holds context/analysis, GOALS.md the acceptance criteria (layer definitions L0–L3, phase exits), *STATUS.md the dated state — generated, machine-sourced from the gate baselines; read progress THERE, not here.** This file holds the remaining steps and their closure criteria, plus a compressed dated record of closed steps. A step closes only when its criterion is met with evidence (a gate passing, an artifact existing, a number reported); the full engineering narratives live where the evidence lives — the dated comment blocks in scripts/partition-gate.baseline / golden-gate.baseline and git history — not here.*
Doer tags: [owner] = decision/markup only the owner can make. [gen] = generator-side work (this repo). [both] = gen produces, owner reviews/acks.
Model-tier tags (added 2026-07-03): Phase 1 built a machine-checked enclosure — four ratcheting gates, 1,020 test pins, the advisory ledger, and baseline files whose dated narratives double as execution briefs — which converts much of the remaining work from "trust the model's judgment" into "trust the gate." Accordingly each open step carries a tier: [frontier] = diagnosis, design, or first-contact debugging IS the work (new defect classes, API shape decisions, unknown-unknowns) — run on a frontier-class model. [delegable] = the mechanism is already written down (in the step itself, a baseline narrative, or a memory brief) and the gates/closure criterion fully enclose the change — suitable for a Sonnet/Opus-class session under the Delegation protocol (standing rules, below). A frontier session that resolves an unknown should end by writing or refreshing the briefs its findings unlock, converting downstream [frontier] steps to [delegable].
Phase 0 — Declare the surface — CLOSED 2026-07-02
All nine steps closed 2026-07-02 (constellation survey; cloudflare.pilot.toml v0; multi-entry crawl seeding + per-entry provenance; recipe loader/entry resolution; first v0 crawl, 31 roots / 30,719 types; status-report.sh → generated STATUS.md with the L0 gate; re-baseline of all four gates; exit: unassigned = 0, every reached package policied). Owner recipe markup deferred by owner ("defaults stand, ratified by use"). Findings ledger (module-twin DECISION reversed by measurement; MISSREF crawl-gating deferred to Phase 4) — details in git history of this file and the baselines.
Phase 1 — Partitioned emission + per-area L1 gates — CLOSED 2026-07-03
Exit criterion MET 2026-07-03: every unit's own-file error count = 0 (compiles + produces its assembly) — the STATUS matrix is all-zero.
Closed steps (dated; narratives in scripts/partition-gate.baseline unless noted):
- 2026-07-02: recipe consumed by generation; area-assignment pass (monotone-lattice fixpoint; shared synthetics 40%); first partitioned emission (7 units, publish order, per-unit fsprojs); per-area L1 gate (
partition-gate.sh+ baseline). - 2026-07-03: zod opaque-handle policy end-to-end (332 machinery nodes unemitted, 564 refs collapsed onto the handle); the "Fantomas floor" resolved (doc-cascade was ours; wide-format emission) — Zod unit typechecks; monolith retired (units are the ONLY artifact; golden/arity gates re-aimed); type-granular shared placement (
SyntheticPlacementOrder); chunk-provenance root fix (encoder FQNs); erased-dep enforcement machinery + enablement (advisory ledger,Erased.*aliases, forward-ref scrub — the DAG holds by construction); second-order burn 63→42. - 2026-07-04: coordinated phantom-typar arc 42→10 (case-twin dedup, opaque/erased prefix collapse, nested-child arm fix, def/ref-symmetry walk; three ref-side variants measured and REVERTED — pinned negative results); ZOD AT 0 (home-child scrub + support library as project reference + function-param parens + duplicate-property dedup); Workers burn-down 86→8 (heritage scrubs, def/ref-closure scrub, abbreviation-legality verdict, Fable arity table, memoized per-export stores) → final-8→8-neutral composition fixes (five singletons killed).
- 2026-07-05: WORKERS AT 0 (rpcStub anchor/localise split → path-occupancy Case{n} re-homing, encoder verified clean → return-only overload unification + same-name method grouping + unit-setter drop); PARTYSOCKET AT 0 (real, unblocked); PARTYSERVER AT 0 (Function-arm anchor/localise split — the flagged latent twin; scrub-host correction catalogued to land WITH the cross-owner def/ref closure); Mcp first real count 26 → burn-down (holder-channel scrubs, Generator/AsyncGenerator arity, alias-arity recording gate removal).
Closed 2026-07-05 (continued): MCP AT 0 (obj-alias→empty-interface verdict shape ×215 ledgered + 0-typar export-key arity recording + function-return parenthesization; fifth cell); CODEMODE AT 0 (stdlib-ALIAS substitution at the remap mint — PropertyKey class; sixth cell); Agents first real count 4 → 2 (decorator-context types joined the obj map).
Closed 2026-07-03 (agents-close): AGENTS AT 0 — PHASE-1 EXIT, 7/7 UNITS ASSEMBLE. The cross-owner cache-hit class closed on the REF side (scrubDanglingSelfRefs — fired exactly 4×, zero false positives; def-side adoption measured 3 ways, pinned 3-for-3 negative), which unmasked 14 later-phase latents (the Workers-88 pattern) burned to 0 by four seam fixes (collection mergeTypeLike, render-entry groupFunctionsByName, partition property-vs-method drop, and two unification-KEY corrections: bare-Erased.X-as-obj + two-channel optionality). +22 coverage pins (suite 620, new OverloadUnification.fs plane); arity gate ratcheted 11→0 disagreeing names; golden callbacks 75→69, synth-public 1067→1058. Full narrative: the baseline's agents-close entry.
2026-07-03 dated note (divergence-edit per standing rules): the DEFERRED-TOGETHER pair closed differently than designed — the ref side (scrub) sufficed for assembly; the def side (cross-owner def materialization) and the params scrub-host correction are NOT landed and NO LONGER BLOCK any unit. Their remaining value is fidelity (real types instead of ledgered obj degradations), so they move to the Phase-3 fidelity catalogue below, alongside the SharedLiterals manifest-placement item (same reclassification: its dangle class is scrubbed-to-obj + ledgered, not erroring).
Phase 2 — Ship the first slice (the near-term goal)
Deployment model (owner directive 2026-07-05): NO WRANGLER/MINIFLARE. Fidelity.CloudEdge's deployment side already exists and is largely solved: the SpeakEZ clef-lang-site repo's cli (Hawaii-generated Cloudflare management-API bindings, consumed as the published Fidelity.CloudEdge.Management nupkg). Its reusable primitives — generic buildWorker (dotnet fable → esbuild ESM bundle) + deployWorker/UploadWorkerWithBindings (multipart script upload with metadata/bindings, workers.dev subdomain enable), env-var auth (CLOUDFLARE_API_TOKEN/CLOUDFLARE_ACCOUNT_ID) — are the proof-run harness. The worker-side bindings that CLI's workers consume today are Glutinum-built (Fidelity.CloudEdge/src/Runtime/*); Xantham's units are their replacement. Worker entry shape in production there: [<ExportDefault>] createObj [ "fetch" ==> fun req env ctx -> promise { ... } ].
Recommended order: 2.1 and 2.2 are independent and can run in either order; 2.3 needs both; 2.4 inherits 2.3's findings; 2.5 can run any time after 2.1; 2.6 is the exit.
- 2.1 [gen][delegable] Pack the v0 libs as nupkgs. Mechanism: the generator already emits per-unit fsprojs in publish order (Emission.fs); packing = per-unit
PackageId/Versionmetadata, intra-constellationProjectReferences re-expressed as versionedPackageReferences matching the publish-order DAG (Zod → Workers → PartySocket → PartyServer → Mcp → CodeMode → Agents), and the support library packed first (the Zod unit consumes it as a project reference today). Versioning tracks each unit's OWN upstream package version (constellation-survey rule: root==oldest trap — never version the set from the oldest root). Publish to a local folder feed. Closure:dotnet add packageof every unit from the local feed restores and compiles in a fresh consumer project. Brief: this bullet + the emitted fsprojs under the output dir. Note: the partition/golden gates do not cover packing — the closure criterion IS the gate here. - 2.2 [gen][frontier] Fx Emit-rebind core (HelloWorker precondition; ~150 lines by estimate). Why:
@cloudflare/workers-typesis a types-only npm package, so the emitted[<Import>]VALUE members are dead (910 counted) — constructors and statics (Response,Request,Headers,URL, ...) are unreachable at runtime. The core re-binds the needed value-position surface via[<Emit>]against the V8-isolate globals. Frontier because it is API design plus the first live check of which value members HelloWorker actually needs. Closure: HelloWorker compiles against it and the bundled JS contains no imports from workers-types. - 2.3 [gen][frontier] HelloWorker: fetch handler + KV/R2/D1 round-trip. Pipeline: consumer project referencing the packed units (or project refs if 2.1 lags) →
dotnet fable→ esbuild ESM bundle → deploy via theFidelity.CloudEdge.Managementprimitives (buildWorker/deployWorker/UploadWorkerWithBindings, env-var auth) → assert response bytes from the live workers.dev endpoint; KV/R2/D1 resources provisioned through the management plane (Hawaii bindings), never wrangler. FIRST-SIGNAL RISKS (why frontier): fable 5.0.0-rc.3 × Fable.Core 5.0.0-beta.4 has never compiled a generated unit — erased unions (U2/U3),namespace rec,Erased.*advisory aliases, and[<Import>]lowering are all first-exercised here; the per-CELL doctrine bounds any resulting burn-down to the cells HelloWorker touches. Closure: deploy succeeds + correct response bytes from the deployed worker. A closing frontier session writes the "Fable-lowering findings" brief that 2.4 and future consumers execute against. - 2.4 [gen][frontier] Minimal Agent slice consumer:
Agentsubclass +routeAgentRequest+getAgentByName+ state +this.sql, compiled through the bindings, deployed the same way. Second contact — inherits 2.3's pipeline and findings; the DO-hosted actor surface (the MailboxProcessor-on-DurableObject thesis) gets its first compile signal here. Closure: Fable compile exit 0; deployed slice responds. (Ungated 2026-07-03 — Agents at 0.) Downgrades to [delegable] if 2.3's findings brief covers the class-inheritance + DO shapes. - 2.5 [owner][delegable] zod/MCP policy proof-or-adjust: a
registerToolauthoring sample against the opaque-handle builders (the Zod overlay handle module, already emitted), or the policy is revised. Closure: a tool-authoring sample compiles. Brief: the zod opaque-handle entries inscripts/partition-gate.baseline+ this bullet; owner judges ergonomics, a delegable session drafts the sample. - 2.6 [both] Phase 2 exit = the "ecstatic" milestone: 1:1 import→export, a consumer builds something real without reading Xantham internals.
Phase 3 — L2 conventions per area (after the milestone)
- 3.1 [gen][frontier] 7-stage hook model implemented; the inline policies accumulated during Phase 1 (opaque-handle overlay, lib-es substitution maps, the scrub family, obj-alias verdicts) migrated behind declared stages. Architecture work on mature machinery — the design decides where every future policy lands, so it stays frontier. Closure: every inline policy reachable through a declared hook stage; suites + gates hold.
- 3.2 [both] Per-area L2 conventions: derive the limited L2 per area FROM the advisory ledger + raw-surface impedance markers, declared per-area in
cloudflare.pilot.toml(the derivation meta-task — derive from measurement, not imagined usage). [frontier] for the derivation design and the FIRST templated area; [delegable] for each subsequent area once the template exists (brief = the templated area + that area's ledger slice). Closure: zero unacknowledged advisories on shipping areas. -
3.3 [gen] FIDELITY CATALOGUE (moved from Phase 1, 2026-07-03 — scrubbed-to-obj + ledgered, no longer assembly-blocking; each item retires its advisory-ledger class and lands with its pin per the parity rule). Individually tiered:
- 3.3a [delegable] never-arm strip for XOR expansions: drop
never-typed arms from expanded XOR unions at the render seam. Pin-sized, gate-enclosed. Brief: this bullet + the ledger class + the existing OverloadUnification/Collection pin idioms. - 3.3b [delegable] literal-discriminant widening (KV
get/getWithMetadataoverloads become real again): preserve literal param types where they discriminate overloads instead of widening to the base primitive. Render-tier, enclosed by the FS0438 pins and the partition gate; the executing session MUST hold every OverloadUnification pin green. Brief: the overload-unification narratives inscripts/partition-gate.baseline(Workers 2026-07-05 + agents-close entries). - 3.3c [frontier]
TypeReferenceintermediate-alias arg preservation (the BaseToolCallback middle-arg drop): IR-side fidelity in the alias-collapse machinery — the region with a documented regression history (the phantom-typar arc's reverted attempts). Diagnosis is the work. - 3.3d [frontier] params scrub-host correction (holder params render true
Request/URLinstead ofobj): documented coupling — correcting the host lets real refs through, which re-surfaces cross-owner dangles unless 3.3e lands with or before it (the measured hazard in the PartyServer/agents-close baseline entries). - 3.3e [frontier] cross-owner def materialization + SharedLiterals homes placed by manifest classification (the
foreign-transient-scruband literal-home classes get real defs instead of obj): the def-placement problem with a 3-for-3 pinned-negative history on adoption approaches — new design required, binding constraint: the ref-side scrub stays until a def-side design is measured clean.
- 3.3a [delegable] never-arm strip for XOR expansions: drop
Phase 4 — L3 + steady-state operation
- 4.1 [gen][delegable] Update run end-to-end: bump pin → crawl → four gates → drift report → regenerate → changed-only republish. The pipeline is composition of existing parts (crawl seeding, gates, STATUS regen) and the gates ARE the judge — this is the designed steady-state loop where the F# compiler + gate matrix reveal whether upstream churn is material. ESCALATION RULE: a gate failure in a class with an existing baseline narrative is executable from that brief; a failure with NO narrative (a new defect class) stops the session and escalates to [frontier]. Closure: one real upstream bump processed (agents 0.17.1→0.17.3 is queued as the first).
- 4.2 [gen][delegable] Extensions packages scaffolded; ported upstream test slice green. Mechanical scaffolding against the packed units; the ported tests are the correctness judge. Brief: this bullet + the upstream test files chosen by the owner.
- 4.3 [both] Next-wave entries promoted by owner decision (oauth-provider, containers, sandbox) — [owner] for the promotion decision and recipe markup; [delegable] for the execution per entry (re-run the proven Phase 0→1 pipeline: add crawl root, policy the reached packages, emit, burn the unit to 0 against the gates — escalate on any new defect class per the 4.1 rule).
Standing rules:
- Work lands against this plan; progress is read in STATUS.md (generated from the gate baselines — regenerate with scripts/status-report.sh whenever a baseline moves). When a step closes, it moves to its phase's dated Closed list as ONE line; the narrative stays with the evidence (baseline comments, git history). When reality diverges from a step, the step is edited (with a dated note), never silently skipped.
- Test-coverage parity (owner directive 2026-07-02): every new code structure lands with its parallel unit + integration coverage in the same change, and coverage remains in relative parity to new code as it is ratified within the design's scaffolding. Coverage reporting is part of status-report.sh (per-module test counts). A structure without its coverage plane is not closed.
- Delegation protocol (added 2026-07-03; governs every [delegable] step): one step per session, with the step's brief (its bullet + the pointed-to baseline narratives/memory) as the session's whole scope. Hard rules for the executing session: (1) all four gates + both test suites pass before handoff — a failing gate or any surprise outside the brief means STOP AND REPORT, never improvise a workaround; (2) PINNED NEGATIVES ARE BINDING — approaches documented as measured-negative (def-side adoption, the thin-reference store fix, the broad decl-oracle proxy, ...) are not re-attempted; (3) baselines ratchet DOWN only, with a dated justification comment — never up, never silently; (4) coverage parity applies — a fix without its pin is not closed; (5) judge by generation correctness, not error-count movement (the count is a smoke detector, not the target). A [frontier] step stays on a frontier-class model end-to-end; its closing act is writing/refreshing the downstream briefs.