LoopX 2.0 · Engineering
LoopX 2.0: Two Months of TypeScript Control-Plane Engineering
From an incremental migration proposal to complete transactions, shared authority, semantic checks, and retirement of old paths. How real callers and counterexamples changed the design.
LoopX 2.0 is out. This is an account of the history and technical details behind its TypeScript refactor.
The formal migration RFC merged on August 15. By the concentrated retirement of ordinary legacy writers in mid-October, the program had spanned roughly two months. Several tracks overlapped: transaction ownership, caller integration, shared authority, storage and history costs, Semantics, compatibility, and retirement.
The final relay by three developers and their agents in #6396 depended on that earlier work. Earlier choices determined what could be deleted and what still had to recover afterward.
@@ -324,7 +324,14 @@Counterexamples for the checker itself
False alarms and missed values have different consequences. A conservative candidate set may report an extra problem. Missing a real produced value can let an unregistered output through. Unsupported dynamic forms must preserve an unknown.
The checks also need scan-coverage floors, so scanning fewer files cannot make the result green. Retiring an expanding committed inventory in favor of on-demand full-tree computation did not remove that obligation. Gaps outside supported forms remain explicit, and the tracking issue remains part of the work.
Generation and checking reduce synchronization mistakes. Their assumptions, coverage, and error direction still require review.
-8. Callers and defaults determine whether migration reaches users
+8. Using stronger models to repair control-plane semantics
+After the migration, we continued using stronger models to examine what the control plane means: does a state retain the same meaning across its producer, rules, callers and recovery paths? Models contribute to design, implementation and review, particularly by tracing assumptions across files and runtimes. The two later repairs below merged after October 16 and are outside the two-month statistics above.
+Static types check the shape of a value. They do not automatically catch a recovery command whose arguments are correct but whose executable has changed. #7145 addressed exactly that failure: after entering LoopX through a specified runtime, a failed task selection could return a command that invoked a different global loopx on PATH. Goal, Agent and Turn were preserved; entrypoint identity was not.
The regression put a deliberately failing global CLI on PATH and then executed the returned recovery command unchanged. The repair reused the existing CLI entrypoint builder. Validation checked that the original runtime route and work identity survived, rejection preceded business side effects, and the original result settled once. Checking which argument strings appear in the command would miss the defect.
+#7269 exposed another distinction. must_attempt expresses an obligation to advance work this Turn; delivery_allowed still depends on the action’s permissions, lease and stop conditions. Planning successor work also does not permit settling the current result under that successor’s identity.
The earlier #3464 illustrates the same lesson. Reducing cross-language calls still required preflight before irreversible side effects. A correct check performed too late cannot protect the user.
+We constrain model-assisted repairs through this chain: identify a wrong assumption, trace it to the shared semantic owner, construct a counterexample that fails on the old version, then exercise real calls, rejection and recovery. The value lies in the meaning repaired, rather than TypeScript generated. We have no per-PR model comparison establishing a particular model’s independent benefit.
+9. Callers and defaults determine whether migration reaches users
Complete transactions need real producers. In September, #4178 converged nonterminal planning updates around one authority snapshot and a TS transaction. It removed a Python route that synthesized Markdown, parsed it again, and performed target reads before the transaction.
Omission, null, an empty value, and false each carry intent here. Dry-run must model that intent accurately. An unavailable selected provider must not trigger fallback elsewhere. #4279 later converged read classification and projection-delivery semantics. Some Python read ownership was deliberately retained. Clear ownership matters more than creating a second interpretation to pursue language purity.
Defaults expose similar distinctions. Current priority regressions protect these cases:
@@ -363,7 +370,7 @@8. Callers and defaults determine whether migration reaches u
The File and SQLite regressions protect these cases. Applying new defaults after original-receipt recovery prevents an upgrade from making new decisions for history.
The closing review found another caller gap. The TS core passed direct tests for metadata-only completion repair. The normal Python producer automatically attached defaults such as completion policy and auto-acquire. The core interpreted them as fresh work mixed into a historical repair. The actual File and SQLite entrypoints failed in both dry-run and execution. The public counterexample records this.
That recovery gap also existed in the baseline, so it cannot all be attributed to the final contributor. The repair had to reach the normal producer while continuing to reject real changes to text, continuation, ownership, or validation. A correctly constructed typed request proves only that the inner boundary can handle it.
-9. Recover the original result while protecting current authority
+10. Recover the original result while protecting current authority
Recovery can confuse two points in time: whether the original operation was valid, and whether today's executor may continue changing state.
Suppose a team-plan committed but its response was lost. After an upgrade, the caller retries the same operation ID under stricter admission rules. Rejecting it as fresh work first can hide the original success. A closing recovery review caught that problem.
9. Recover the original result while protecting current autho
Returning the original result does not renew a lease, overwrite later commits, or revive a retired writer. Lease transfers, epoch changes, and subsequent state have their own protections.
Types express the distinction too. Historical decoding still recognizes legacy; current fresh-execution handoff configuration accepts soft_claim and hard_lease. Reading an old record, recovering an original operation, and authorizing current execution each have independent conditions.
An internal receipt also has a limited scope. If a remote external effect lacks a verifiable idempotent identity and readback, settling once in the control plane cannot establish that the remote effect executed exactly once. Uncertainty belongs at the boundary where it actually occurs.
-10. CLI output budgets: protect decision semantics before compression
+11. CLI output budgets: protect decision semantics before compression
CLI language participates in an agent's decisions. This engineering constraint predates the final writer retirement and remained a validation boundary during migration.
The interface budget contract examines:
-
@@ -384,7 +391,7 @@
10. CLI output budgets: protect decision semantics before co
Natural language requires clause-level review: obligations, ordering, evidence provenance, authority qualifiers, scope, continuation, and stop conditions. Removing a phrase such as “only when the original proof is valid” can change behavior even when every field remains.
One bounded example removed JSON indentation and separator whitespace. On the same historical fixture of 36 Todos and 12 runs, output fell from 48,418 to 39,726 characters, about 18%, with the complete decoded payload unchanged. This establishes a presentation-size change. Tokens, cost, and agent outcomes need separate measurements.
The budget protects an interface the consumer can use. Valuable guidance may justify increasing it with matched evidence. Dropping decision conditions to make a size test green damages the interface.
-11. Final retirement: preserve credit and account for the deletions
+12. Final retirement: preserve credit and account for the deletions
Late-September work had already removed an unused authority prototype and the experimental Todo event overlay, dual-writer, and backfill. Old sources containing data received explicit preservation or refusal handling. This did not remove all event logging or the new authority's atomic events and receipts.
October work further isolated ordinary Markdown writers and validated real subsequent writes without the old modules. Concentrated deletion became possible after consumer routes and replacement paths were connected.
Duang777 led #6396. Song and maintainer-side agents continued recovery, producer, and integration work along the original branch, preserving contribution history. This three-developer-and-agent relay was the closing phase of the two-month program.
@@ -424,7 +431,7 @@