GENERATED VIEW · PRIVATE ARCHIVE · DO NOT SERVE
RobCo Industries · Archive Museum

architecture-review-2026-07-13.md



MEMORY

memory/localmode-1060dea9-0dc3-42b4-958d-2a6f7a6c0c58/architecture-review-2026-07-13.md

sha256 d2a20322047a1a99 · 8623 bytes · original held in the private archive

--- name: architecture-review-2026-07-13 description: "⭐ THE ARCHITECTURE MODERNIZATION REVIEW (2026-07-13) — the REASONING, not the numbers. Verdict: it's ONE initiative with the OS round, not two. The framework question is closed. And the finding of the day: real dependency cycles at the UI↔services boundary, which must be inverted onto the event bus BEFORE the OS round adds more services." metadata: node_type: memory type: project originSessionId: 0b7c5f41-bb34-4ab4-93be-fdb363f5eb40 --- ⭐ **The owner asked for a strategic "Architecture Modernization Initiative" review (analysis-only, Opus, 2026-07-13).** He proposed service ownership, an event bus, one canonical state owner, a centralized bootstrap, one scheduler, per-subsystem diagnostics, and plugin-style game registration — and explicitly asked to be CHALLENGED, with a Complexity Budget section demanding every proposal justify what it *removes*. *Trimmed 2026-07-20: every measurement in this file was stripped. Current numbers live in `tests/arch-conformance-check.js`'s ratcheting baseline, `library/CODE_MAP.md`, and the source itself. What survives here is the reasoning, which does not expire.* ## THE VERDICT — one initiative, two views **The Architecture Modernization Initiative and the OS round are ONE initiative described from two perspectives.** The OS round is the **fiction** of an operating system (filesystem, command language, Peripheral Bus, Distribution Network — *features that look like an OS*). This initiative is the **engineering** of one (services, decoupling, scheduler, diagnostics, registration). Same object, lit from two sides. Stronger: **RobCo didn't "start" becoming this architecture — it is already most of the way there, and got there by EMERGENCE, not by plan.** The scheduler, the state owner, the bus, the diagnostics, the game registry all accreted feature-by-feature and *added up to* an OS architecture nobody designed. ⇒ **The verb is not "modernize." It is FINISH AND FORMALIZE.** ⇒ **DO NOT open a second roadmap** (his question 13). The argument is airtight: the work is **subtractive** — closing leaks, standardising, deleting inconsistency. *A separate "modernization roadmap" would be a roadmap to add nothing — a category error.* Verdict: **B (concepts exist, implementations inconsistent) framed by A (sequencing stays), with C disproven.** ## ⭐⭐ THE FINDING OF THE DAY — REAL DEPENDENCY CYCLES AT UI↔SERVICES Credit where due: **ChatGPT surfaced this** (the owner ran Dispatch's framing past it; it named dependency direction "the silent killer" and it was the one thing the first pass only grazed). Dispatch sent it back to measure. **The review then argued AGAINST ITS OWN HEADLINE to report it — exactly the behaviour we want.** **The shape:** the UI calls a service (legal, forward). The service, instead of *returning data* for the caller to render, **reaches back into the view and repaints it.** In the worst cases a full-app re-render is invoked from *inside* the service layer, and true bidirectional cycles form between a render file and the service it calls. **The consequence:** the view is a **SECOND STATE MANAGER** — render files own campaign-state mutation and the full write-and-persist cycle, so the "rendering only renders" layering rule is, in practice, violated by real code. Clean by contrast: **the registry and data layers are hermetically sealed — leave them alone forever.** The core leaks only a few guarded edges. **Two things make this the finding rather than just bad news:** 1. ⭐ **A FRAMEWORK WOULD NOT FIX IT.** Rebuild in React and the cycle survives untouched — **it lives in the DATA FLOW, not in the rendering technology.** Independent confirmation the framework question was a red herring. 2. ⭐ **THE FIX IS A TOOL THE PROJECT ALREADY BUILT — the event bus.** Correct shape: a service mutates state and **emits**; the UI **listens** and repaints itself. The bus was already used for feedback fan-out; **it was just never pointed at the repaint path.** Inverting the service→view render calls onto the bus is the single highest-value action available. ⚠⚠ **THE TIMING ARGUMENT — THIS IS THE WHOLE POINT: every headline OS feature IS A NEW SERVICE.** The CLI, the filesystem, the Peripheral Bus, the Distribution Network. Built like the *existing* services, each adds new cycles — **you don't carry the existing cycles forward, you MULTIPLY them** and hard-wire "services are the second UI controller" into the marquee architecture. **Invert the boundary FIRST and every new OS subsystem inherits a clean one-way flow for free.** Review's closing line: *"That one move is worth more to long-term maintainability than everything else in this review combined."* ## THE FRAMEWORK QUESTION — CLOSED ON ARITHMETIC, NOT OPINION **The overwhelming majority of the test suite is purely STATIC — it reads the source as text.** Even the "behavioural" remainder string-slices function bodies out of source by name. ⇒ **A bundler / transpiler / module step would invalidate most of the gate:** path greps break, minified identifiers defeat the extractors, class-hashing defeats the selector guards. The one true ES module survives only by being a module *at the seams* with plain-text internals. **Not a philosophical objection — a receipt.** Revisit only if that math changes (re-measure against the suite; do not trust a remembered number). ## THE WEAK SPOTS — the "formalize before you build on it" strand Each one is where an OS feature will land. **Days of work, not a project.** Run it as a prerequisite gate at the FRONT of the OS round's planning phase (which already sits there by design). In priority order: 1. ⭐ **The UI↔services cycles** (above) — the sharpest and cheapest, *because the bus already exists*. 2. **State mutations:** direct `state.x =` writes scattered across shipped feature files, no encapsulation. **The specced CLI ("edit any stat, run any tool") points a large new wave of uncontrolled writes at exactly this spot.** Drain toward intent functions — evolutionary, never a freeze. 3. **Bootstrap:** phase calls under **ONE outer `try/catch`, ZERO per-phase isolation.** New OS boot surfaces land on it; any one throwing silently amputates everything after it. Fix = a phase registry with per-phase `try/catch`. A day, no behaviour change. 4. **Event bus:** orphans are gate-enforced in both directions — genuinely good. Missing: `off` / `once` / dedup (correctness leans on an unenforced "wire once" convention) and a silent `catch (_)`. 5. **Scheduler:** the owner's instinct was right but **the shape surprised everyone.** One heartbeat interval already drives the registered observers; almost every other timer is a one-shot animation-cleanup `setTimeout` no scheduler should own, and only a single interval escaped the registry. ⇒ **The scheduler is already BUILT.** Close the leak, add a guard — and fix the code comments that **currently LIE** and claim the file owns no timers. ## GAME REGISTRATION — grade A, leave it Shipped feature code carries essentially no per-game branching; most game literals are fail-safe fallbacks, and adding a game measures as a handful of file-drop touchpoints with no shared-JS edits. The game-agnostic rule is holding. **Re-measure for real at the owed post-FO3 extraction pass ([[fo3-pipboy-program]])** — FO3 is the first thing to genuinely stress it. ## METHOD NOTE WORTH KEEPING The owner's own prompt pre-empted the failure mode ("ask any model *should we add a service locator / DI container / scheduler* and it says yes — those sound like senior engineering"). **The Complexity Budget section is what made the review honest.** Reuse that section verbatim in any future architecture prompt. And the deeper lesson: ***the numbers carried the verdict, not the theory.*** "I feel we need a scheduler" and "here is the measured timer inventory, and only one escaped the registry" are completely different arguments. **Measure first — then throw the measurement away and keep the argument.** *CORRECTION 2026-07-20: an earlier version of this file asserted the render-layering protocol was unenforced with no gate guard. That is FALSE and was false when written down — `tests/arch-conformance-check.js` has enforced it with a ratcheting baseline since 2026-07-18. Do not repeat the claim; check the gate.* Related: [[robco-os-architecture]] (the OS round this folds into), [[roadmap-parked-placement]], [[fo3-pipboy-program]], [[engineering-metrics-log]], [[self-improving-code]].
STAMP · generated for RELEASE v2.8.5 commit 06e5180 (06e51801b38a) · archive input-tree hash c07fbfbdd2e1ddeb · 754 files · no wall-clock timestamp (regenerates identically when nothing changed).