# sx-vm-extensions loop agent Role: drives `plans/sx-vm-opcode-extension.md` to completion. One phase per fire (A → B → C → D → E). Bounded loop — after Phase E acceptance, the loop is done. ``` description: sx-vm-extensions queue loop subagent_type: general-purpose run_in_background: true isolation: worktree (already on loops/sx-vm-extensions) ``` ## What this loop is for Mechanism in `hosts/ocaml/lib/` that lets language ports register specialized bytecode opcodes without modifying the SX VM core. Direct prerequisite for **erlang-on-sx Phase 9** (the BEAM analog) and a structural enabler for any future language port that wants performance-critical opcodes. ## The queue Per `plans/sx-vm-opcode-extension.md`, in order: - **Phase A** — Opcode ID partition + dispatch fallthrough in `sx_vm.ml`. Add `Invalid_opcode of int` exception, `extension_dispatch_ref`, the `| op when op >= 200 -> !extension_dispatch_ref op vm frame` arm, and a partition comment near the opcode list. - **Phase B** — Extension registry module (`sx_vm_extensions.ml`). `register`, `dispatch`, `id_of_name`, `state_of_extension`. Wire dispatch into Phase A's ref at module init. - **Phase C** — Compiler-side opcode lookup primitive (`extension-opcode-id`). - **Phase D** — Test extension at `hosts/ocaml/lib/extensions/test_ext.ml`, end-to-end SX → bytecode → VM dispatch flow. - **Phase E** — JIT awareness: extension opcodes mark a lambda as interpret-only. ## Per-fire workflow (hard) 1. Read `plans/sx-vm-opcode-extension.md` — find the first un-ticked phase. 2. Implement the phase (only files in `hosts/ocaml/**` and the plan file). 3. Build via `sx_build target=ocaml`. 4. Run regression: every existing language-port conformance suite plus the OCaml unit tests. The list lives at `lib//conformance.sh` — 13 suites at last count (apl, common-lisp, datalog, erlang, forth, guest, haskell, js, lua, ocaml, prolog, smalltalk, tcl). 5. If green, commit (short factual message — `vm-ext: phase A — dispatch fallthrough` style). 6. Tick the `[ ]` for the completed phase in the plan, append one dated line to the Progress log (newest first). 7. Stop. Wait for the next fire. ## Ground rules (hard) - **Scope:** only `hosts/ocaml/**` and `plans/sx-vm-opcode-extension.md`. Do **not** edit `lib//**`, `spec/**`, `shared/**`, or any other language port's tests. - **One phase per fire.** Don't combine phases even if a phase looks small. The point of the loop is incremental commits. - **Commit locally only.** Do **not** push. Do **not** touch `main`. - **Worktree:** you are on `loops/sx-vm-extensions` in `/root/rose-ash-loops/sx-vm-extensions`. - **OCaml SX VM gotchas:** - `vm` and `frame` types are defined in `sx_vm.ml`, not `sx_types.ml`. Forward refs (like the existing `jit_compile_ref` pattern) are how sibling modules avoid circular dependency. - Current core opcode ceiling is 175 (OP_DEC). The extension threshold is 200, leaving 24 spare slots for future core opcodes. - JIT compilation is lazy per-lambda. See `project_jit_compilation.md` in memory for the cache + sentinel pattern. - **SX edits:** `sx-tree` MCP tools only (none expected for this loop, but if needed). - **OCaml edits:** Edit/Write tools are fine — these aren't `.sx` files. ## Done condition Phase E acceptance: all 13 (or however many exist at the time) language-port conformance suites pass, OCaml unit tests pass, the test extension from Phase D demonstrates end-to-end flow including JIT routing. Loop is complete; mark and stop. ## After acceptance Hand off to the Erlang loop: `hosts/ocaml/lib/extensions/erlang.ml` becomes the first real consumer, written against this mechanism instead of the Phase 9b stub dispatcher in `lib/erlang/vm/dispatcher.sx`.