Skip to content

Commit f3ef056

Browse files
nextgen-languages-evangelist: 5 trialed components + orchestrator (asks 1–5) (#533)
## What this is Your "make 1–5 into trialable tools / components for a nextgen-languages-evangelist" — done. Rather than five one-off fixes, this seeds a **nextgen-languages-evangelist**: a toolkit that automates the AffineScript-migration pipeline (triage → weak-points → boundary-proof → parity) this session ran by hand. **Every component was run and verified here** against the github-only firewall. Staged under `proposals/nextgen-evangelist/` (writes stayed affinescript-only). Builds on the merged #531 (proof) and #532 (migration + guide). ## The five components (each maps to an ask) — all trialed | Component | Ask | Trial result (this session) | |---|---|---| | **echo-boundary** | #1 #2 | encoding table → LOSSLESS/CONTROLLED-LOSS verdict + **generates & agda-typechecks** an `EchoEncodingFaithfulness` proof (`{Open:0..Strong:3}`→LOSSLESS; `+{OOB:0}`→CONTROLLED LOSS; both exit 0) | | **affine-parity** | #2 #3 | generic differential-parity runner — SecurityRank **78/78**, Kernel_IO `main()=6`, wrong-oracle negative exits 1 | | **affine-migratability** | #4 | `.res` triage — reproduces Compute=MIGRATABLE, IO=STRING-GATED, Quantum=EFFECT-GATED (3/3) | | **affine-assail** | #5 | `.affine` weak-point scanner — flags SecurityRank's clamp `PA-AFF-001` at HIGH; reference impl for the panic-attack gap | | **deno-esm-spike** | #3 | **TS-0 path WORKS** — `.affine`→Deno-ESM named exports, 5/5 driver checks, zero TypeScript | | **evangelist** | all | orchestrator — emits one readiness report (below) | ## Verified end-to-end (orchestrator output on the demo target) ``` ① migratability: Kernel_Compute → MIGRATABLE NOW Kernel_IO → STRING-GATED Kernel_Quantum → EFFECT-GATED ② weak points: SecurityRank.affine → 1 (PA-AFF-001) Kernel_IO.affine → 5 ③ boundary proof: SecurityRank → LOSSLESS (generated Agda, exit 0) ④ parity: SecurityRank → 78/78 pass ``` The toolkit even surfaces a coherent story automatically: **assail flags** SecurityRank's undeclared clamp, while **echo-boundary** certifies the in-band table as LOSSLESS *and* the same table-with-clamp as CONTROLLED LOSS — so it both flags the hazard and lets you discharge it (the `@boundary` obligation from #532's toolchain proposal). ## Honest caveats - Trial components are **Deno** (immediate runnability under the firewall; each carries the sanctioned `hypatia: allow` pragma). Production should be **Rust or AffineScript** per estate policy — flagged, your call. - `affine-parity` covers the **scalar i32 ABI**; array/string params (the `[len:i32 LE][utf8]` + `__affine_alloc` convention) are a follow-on. - `deno-esm` works for pure functions; struct→`export class` + `extern fn` lowering documented but not yet trialed (the prelude is ~440 lines). Draft for review. Eventual home: a dedicated evangelist repo or under `hyperpolymath/nextgen-languages` — your call. https://claude.ai/code/session_01WoKhFQePiRsAj7aqnxbG8s --- _Generated by [Claude Code](https://claude.ai/code/session_01WoKhFQePiRsAj7aqnxbG8s)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent e315180 commit f3ef056

24 files changed

Lines changed: 3764 additions & 0 deletions

proposals/MIGRATION-PLAN.adoc

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
// SPDX-License-Identifier: MPL-2.0
2+
// SPDX-FileCopyrightText: 2025-2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
3+
= Migration plan — organised by compaction boundary
4+
:toc: macro
5+
6+
[IMPORTANT]
7+
====
8+
*This file is the durable spine of the ReScript -> AffineScript -> wasm
9+
migration.* It is written to survive context compaction: the repo is the
10+
memory, not the model's window. Each PHASE below ends at a *committed,
11+
verified checkpoint* and updates the *Ledger* at the bottom. After any
12+
compaction, the resuming agent reads (1) this file's Ledger and (2) the
13+
latest `proposals/idaptik/migration-map.json`, and continues — it does not
14+
rely on the auto-summary.
15+
16+
Cadence: roughly one PHASE per context window ("to compact"). Each PHASE =
17+
goal + deliverables + a green checkpoint + a one-line handoff. The arc runs
18+
until "CLEAR": the migratable corpus is exhausted, the two compiler walls
19+
are down, and the cutover has retired the ReScript shadows.
20+
====
21+
22+
toc::[]
23+
24+
== Standing gates (re-check every phase)
25+
26+
* *Decision gate 1 — production language.* The evangelist tools + harnesses
27+
are Deno trials today; production should be Rust or AffineScript (owner's
28+
call). Until decided: keep the Deno trials, do NOT re-author. Blocks only
29+
the "harden the tooling" sub-tasks, not the migration.
30+
* *Decision gate 2 — evangelist home repo* (dedicated repo vs under
31+
`nextgen-languages`). Cosmetic; blocks nothing.
32+
* *Access gate — idaptik write-access.* Current rule: writes land in
33+
affinescript only; everything idaptik-bound is *staged as applyable
34+
units* under `proposals/idaptik/`. The actual *apply* + *cutover* steps
35+
(Phases C+ "apply", Phase Ω) need either idaptik opened for writes or the
36+
owner accepting the staged patches. Until then, "migrated" means
37+
"verified + staged + applyable", not "applied".
38+
39+
== The two walls (what ultimately gates "CLEAR")
40+
41+
. *Variable-string backend* — `String.length` / indexing / `startsWith` /
42+
`fromCharCode` cannot lower to wasm yet. Gates every STRING-GATED kernel
43+
(e.g. `Kernel_IO`, `DeviceType`, i18n). Lives in *this* repo's compiler,
44+
so it is attackable here.
45+
. *Effect codegen* — module-level mutable state / `Date.now` / `Console.log`
46+
cannot lower ("references an unbound binding"). Gates every EFFECT-GATED
47+
kernel (e.g. `Kernel_Quantum`). Also a compiler task.
48+
49+
Until a wall falls, its kernels stay staged with the honest
50+
"compiler-gated, not effort-gated" label.
51+
52+
== Phases
53+
54+
=== PHASE A — now -> compact 1 : consolidate + make the plan durable
55+
Goal: a clean baseline that compaction can't lose.
56+
57+
* Write this file + the Ledger (done by creating it).
58+
* Settle PR #533 (evangelist toolkit): CI green; leave as draft for owner
59+
review (merge on owner word).
60+
* Fold the three architecture artefacts (`multiplayer-determinism.adoc`,
61+
`state-vs-digest.svg`, `game-vs-deepspace.svg`) into the determinism doc
62+
as a captured "latency regimes" appendix.
63+
* Record the standing gates above.
64+
65+
*Checkpoint:* plan + ledger committed & pushed; staged work coherent.
66+
*Handoff:* "Read §Ledger; next is PHASE B (full-corpus triage)."
67+
68+
=== PHASE B — compact 1 -> 2 : broad sweep (the master worklist)
69+
Goal: know the whole backlog, prioritised.
70+
71+
* Run `affine-migratability` over all ~571 idaptik `.res`; bucket by area
72+
(`src/app`, `shared/src`, `vm`, `src/app/multiplayer`, …) x verdict
73+
(MIGRATABLE-NOW / STRING-GATED / EFFECT-GATED) x shape (pure-integer core
74+
/ binding shim / render-glue).
75+
* Emit `proposals/idaptik/migration-map.adoc` (human) +
76+
`migration-map.json` (machine, the resumable worklist) + the headline %.
77+
* Order the MIGRATABLE-NOW set into clusters: leaf pure-integer cores
78+
first, then up the dependency tree.
79+
80+
*Checkpoint:* full triage committed; backlog + order fixed.
81+
*Handoff:* "worklist = migration-map.json; cluster 1 = <top N>; PHASE C."
82+
83+
=== PHASE C — compact 2 -> 3 : deep wave 1 (first clean cluster, end-to-end)
84+
Goal: migrate + verify the first batch via the 4-gate recipe.
85+
86+
The *recipe* (every kernel, every wave):
87+
. re-decompose `.res` -> `.affine` (NOT transliterate — collapse incidental
88+
Promise/async, thread service-locator state as params, enum the options,
89+
hand-ladder int rendering, keep wire bytes identical);
90+
. `affinescript compile` -> wasm (gate 1: builds);
91+
. `affine-parity` oracle-vs-wasm sweep green (gate 2: parity);
92+
. `echo-boundary` proves each host-boundary encoding LOSSLESS or
93+
declared-clamp (gate 3: faithful);
94+
. `affine-assail` clean — no undeclared clamp / unguarded decoder (gate 4).
95+
96+
* Apply recipe to cluster 1 (~6-10 pure-integer cores). Stage each under
97+
`proposals/idaptik/migrated/<name>/` with `.affine` + harness + evidence.
98+
99+
*Checkpoint:* cluster 1 four-gate-green + staged. Ledger % updated.
100+
*Handoff:* "cluster 1 done (list); cluster 2 next; recipe in §Phase C."
101+
102+
=== PHASE D — compact 3 -> 4 : deep wave 2 + the TS-0 harness path
103+
Goal: more kernels + start retiring the 17.6k LOC of TS harness.
104+
105+
* Cluster 2 of MIGRATABLE-NOW (same recipe).
106+
* Trial `--deno-esm` struct -> `export class` + `extern fn` lowering;
107+
re-author ONE parity harness in AffineScript -> Deno-ESM; prove it
108+
reproduces the TS harness's verdict. TS-0-for-harnesses becomes real.
109+
110+
*Checkpoint:* cluster 2 green + the AffineScript-authored harness PoC.
111+
112+
=== PHASE E — compact 4 -> 5 : the multiplayer determinism spine (wasmex + SNIFS)
113+
Goal: make server-authoritative determinism concrete before the big
114+
multiplayer-client migration.
115+
116+
* `vm.affine` reversible counter; run the *identical* wasm in Deno (client)
117+
and under SNIFS/`wasmex` in a one-file Elixir (server); demonstrate
118+
identical step, reverse (rollback), and the per-tick *hash tripwire*
119+
catching an injected desync.
120+
121+
*Checkpoint:* same-binary-both-sides PoC + hash-tripwire demo verified.
122+
123+
=== PHASE F — compact 5 -> 6 : attack wall 1, slice 1 (variable-string backend)
124+
Goal: stop documenting the wall; start removing it (compiler work, in scope).
125+
126+
* Implement `String.length` + string indexing end-to-end in the compiler
127+
(lexer/typer/codegen) on the `[len:i32 LE][utf8]` read-side ABI, with
128+
tests; demonstrate a previously STRING-GATED kernel now builds +
129+
parity-greens.
130+
131+
*Checkpoint:* first string primitive lands (compiler PR) + one string-kernel
132+
unblocked.
133+
134+
=== PHASES G..N — compact -> compact : the repeating grind
135+
Each window, in order:
136+
. migrate the next cluster the latest compiler capability unblocked (recipe);
137+
. advance the next wall-slice (`startsWith` -> `fromCharCode`; then the
138+
effect-codegen slices for `Date.now`/log/module-state);
139+
. re-run the evangelist readiness map (the % climbs; gated counts fall);
140+
. update the Ledger.
141+
142+
Repeat until the MIGRATABLE set is exhausted and both walls are down — at
143+
which point `Kernel_IO` (string) and `Kernel_Quantum` (effect) finally fall.
144+
145+
=== PHASE Ω — -> CLEAR : cutover + extinction (the goodbye)
146+
Goal: flip the switches, delete the shadows. (Gated on idaptik write-access;
147+
until then each cutover is a staged applyable bundle for sign-off.)
148+
149+
* Per area, once all cores are parity-green + bindings wired: enable the
150+
`FeaturePacks` flag, delete the `.res` shadows, drop the TS harnesses,
151+
remove the lone `.py` holdout; re-run the census (ReScript -> 0 in that
152+
area).
153+
* Final census target: ReScript 0 in migrated areas, AffineScript primary,
154+
TypeScript 0, Python 0; agreed-keep set (Elixir/Zig/Idris2/Julia) intact.
155+
156+
*CLEAR* = migratable corpus migrated + applied, walls down, shadows retired.
157+
158+
== Model per phase (advise at each compact)
159+
160+
Heuristic:
161+
162+
* *Opus* — re-decomposition design, compiler-internals (the walls),
163+
novel cross-runtime integration, cutover review. Anywhere a wrong or
164+
subtle call is expensive. ("Fast" Opus when you want that reasoning with
165+
quicker output.)
166+
* *Sonnet* — known-pattern multi-file grinding: the triage sweep, the rote
167+
waves once the recipe is set, the mechanical cutover apply.
168+
* *Haiku* — pure mechanical sub-steps (bulk tool runs, boilerplate, status
169+
checks). Rarely a whole phase.
170+
171+
[cols="1,1,3",options="header"]
172+
|===
173+
| Phase | Model | Why
174+
| A consolidate/plan | Opus | synthesis + architecture
175+
| B broad triage | *Sonnet* | run one tool over ~571 files, bucket + prioritise; systematic, low-novelty
176+
| C/D deep waves | *Opus* for the re-decomposition; Sonnet once rote | re-decompose is subtle (a transliteration is rejected); the 4 gates are mechanical
177+
| E wasmex/SNIFS PoC | *Opus* | novel Elixir+wasm+Deno integration + determinism reasoning
178+
| F + walls (compiler) | *Opus* | real OCaml compiler engineering (lexer/typer/codegen/ABI), correctness-critical
179+
| G..N grind | alternate: *Sonnet* (migrate) / *Opus* (wall-slice) | per window
180+
| Ω cutover | *Sonnet* to execute, *Opus* to sign off the diff | high-stakes deletes; mechanical apply
181+
|===
182+
183+
== Ledger (each phase updates this; the resume point lives here)
184+
185+
[cols="1,1,3",options="header"]
186+
|===
187+
| Phase | State | Notes
188+
| Pre | DONE | #531 echo proof (merged); #532 migration practice + guide + proposals (merged); #533 evangelist toolkit (draft, CI green).
189+
| A | DONE | Plan + model-per-phase guidance written; determinism doc gained a latency-regimes appendix (verify-don't-transfer + game-vs-deep-space + the 2 SVGs); #533 green (draft, owner to merge). NEXT: PHASE B.
190+
| B | TODO | Full-corpus triage -> migration-map.{adoc,json}.
191+
| C+ | TODO | Deep waves via the 4-gate recipe.
192+
| F+ | TODO | Compiler walls (string backend, then effects).
193+
| Ω | TODO (access-gated) | Cutover + ReScript extinction.
194+
|===
195+
196+
*Resume rule:* read the highest non-DONE row + `migration-map.json`;
197+
continue from its "Notes".

0 commit comments

Comments
 (0)