The Runtime Refactoring: How Three Design Improvements Were Discovered Mid-Implementation
During Phase 0 implementation of the Runtime subsystem, three architectural improvements were discovered in practice: the Context was simplified to passive storage, the State Machine became the sole lifecycle authority, and the Runtime Loop became lifecycle-independent — all mid-implementation corrections.
- Reference
- V012
- Project
- VANI
- Status
- Completed — Phase 0
- Evidence
- high
- Source
- 012-runtime-refactoring-discoveries.md
Context
VANI's FOUNDATION.md establishes that "Architecture always precedes implementation" and "No undocumented shortcuts or temporary solutions remain." Yet the Phase 0 changelog and implementation report both record architectural improvements that occurred during or after implementation — not before it.
This gap between the principle and the reality is worth examining.
The Question
What was discovered during Runtime implementation that wasn't known from the architecture documents alone?
What Happened
From docs/phases/phase0/CHANGELOG.md, Version 0.6.0 (Runtime) explicitly records under "Refactored":
"Runtime Context converted into passive storage." "State Machine became lifecycle authority." "Runtime Loop became execution-only." "Engine assumed coordination ownership." "Runtime diagnostics separated from Guardian."
From docs/phases/phase0/IMPLEMENTATION_REPORT.md — "Major Refactors" section:
"Runtime Context simplified into passive storage." "Runtime State Machine became the sole lifecycle authority." "Runtime Loop became lifecycle-independent." "Runtime Engine assumed complete coordination ownership."
These are not minor tweaks — they describe ownership transfers between components.
What Each Discovery Means
1. Runtime Context converted to passive storage
Before the change: The Context object contained some form of logic or mutable behavior.
After the change: Context became a pure data container — no methods that change state, no decision-making.
Why this matters: When Context contains logic, it becomes a hidden second authority for lifecycle decisions. Two authorities for the same decision create race conditions and tracing difficulties. Making Context passive makes State Machine ownership unambiguous.
2. State Machine became the sole lifecycle authority
Before the change: Lifecycle decision-making was distributed — some in the State Machine, some elsewhere.
After the change: All lifecycle transitions are authorized only by the State Machine.
Why this matters: Distributed lifecycle control creates the classic "who changed this state?" debugging problem. A single State Machine with explicit transition rules makes every state change traceable.
3. Runtime Loop became lifecycle-independent
Before the change: The execution loop had some awareness of or responsibility for lifecycle state.
After the change: The loop only executes — it has no authority over its own lifecycle.
Why this matters: Mixing "am I allowed to run?" with "do the work" in the same component makes both harder to reason about. Separating them means the loop is always executing (if it's running at all), and lifecycle is always the State Machine's concern.
Evidence
docs/phases/phase0/CHANGELOG.md— Version 0.6.0 "Refactored" sectiondocs/phases/phase0/IMPLEMENTATION_REPORT.md— "Major Refactors" section (lines ~312–320)docs/phases/phase0/LESSONS_LEARNED.md— Lessons on passive storage, state machine ownership, engine coordinationsrc/runtime/— Runtime source directory (implementation exists)
Diagnosis
Established: The three Runtime refactors are explicitly documented in the changelog and implementation report. These are not speculative — they are recorded changes.
Established: The lessons learned document directly reflects these discoveries: "Context objects should never contain business logic. By restricting Contexts to passive storage, lifecycle decisions remain entirely inside State Machines while execution remains inside Engines."
Established: The refactoring occurred during Phase 0 implementation, not before it. The "Architecture Before Implementation" principle was applied at the subsystem level (architecture was documented before the Runtime was started), but the specific internal design discoveries about Context passivity were made during implementation.
Likely: These discoveries prompted generalization of the pattern — the six-layer rule (Foundation → Context → State Machine → Engine → Executor → Orchestrator) was refined as a result of these specific Runtime observations.
What Changed
The Runtime subsystem was internally restructured. The broader effect was that the lessons were applied to subsequent subsystems and the Bootstrap, which also went through architectural refinement.
From the Implementation Report "Architectural Refinements" section:
"Passive Context pattern, Immutable Snapshot pattern, Protocol-first subsystem boundaries, Constructor dependency injection, State Machine ownership of lifecycle, Separation of Engine, Executor, and Orchestrator responsibilities"
What I Learned
Architecture documents can define layer responsibilities, but the precise answer to "where does this logic belong?" is often only clear once you've started implementing and discovered that two components are competing for the same responsibility. The Runtime refactoring is documented evidence that architectural understanding deepens through implementation, not just design.
The lesson the project explicitly drew: "Continuous Review Prevents Technical Debt — Reviewing every subsystem before implementation prevented architectural drift and reduced the need for large refactors. Incremental review proved substantially more effective than attempting to correct issues after implementation was complete."
This is partially true — the refactoring happened during implementation, not after large accumulation of technical debt. The review-during cycle (not just review-before) is what allowed correction before it became expensive.
Broader Principle
For components that interact with lifecycle management, passive context storage is almost always the correct design. When a Context object contains logic, it competes with the State Machine for lifecycle authority. This competition is invisible in simple tests but becomes a debugging nightmare in production. The pattern: Context stores data, State Machine changes data, Engine reads data to coordinate work.
Technical References
docs/phases/phase0/CHANGELOG.md— Version 0.6.0docs/phases/phase0/IMPLEMENTATION_REPORT.md— "Major Refactors" and "Architectural Refinements" sectionsdocs/phases/phase0/LESSONS_LEARNED.md— Passive storage and state machine ownership sectionssrc/runtime/— Runtime source
Failure sequence
On the record- Attempt
- What was discovered during Runtime implementation that wasn't known from the architecture documents alone?
- Failure
- From `docs/phases/phase0/CHANGELOG.md`, Version 0.6.0 (Runtime) explicitly records under "Refactored": > "Runtime Context converted into passive storage." > "State Machine became lifecycle authority." > "Runtime Loop became execution-only." > "Engine assumed coordination ownership." > "Runtime diagnostics separated from Guardian." From `docs/phases/phase0/IMPLEMENTATION_REPORT.md` — "Major Refactors" section: > "Runtime Context simplified into passive storage." > "Runtime State Machine became the sole lifecycle authority." > "Runtime Loop became lifecycle-independent." > "Runtime Engine assumed complete coordination ownership." These are not minor tweaks — they describe ownership transfers between components.
- Diagnosis
- **Established:** The three Runtime refactors are explicitly documented in the changelog and implementation report. These are not speculative — they are recorded changes. **Established:** The lessons learned document directly reflects these discoveries: "Context objects should never contain business logic. By restricting Contexts to passive storage, lifecycle decisions remain entirely inside State Machines while execution remains inside Engines." **Established:** The refactoring occurred during Phase 0 implementation, not before it. The "Architecture Before Implementation" principle was applied at the subsystem level (architecture was documented before the Runtime was started), but the specific internal design discoveries about Context passivity were made during implementation. **Likely:** These discoveries prompted generalization of the pattern — the six-layer rule (Foundation → Context → State Machine → Engine → Executor → Orchestrator) was refined as a result of these specific Runtime observations.
- Lesson
- Architecture documents can define layer responsibilities, but the precise answer to "where does this logic belong?" is often only clear once you've started implementing and discovered that two components are competing for the same responsibility. The Runtime refactoring is documented evidence that architectural understanding deepens through implementation, not just design. The lesson the project explicitly drew: "Continuous Review Prevents Technical Debt — Reviewing every subsystem before implementation prevented architectural drift and reduced the need for large refactors. Incremental review proved substantially more effective than attempting to correct issues after implementation was complete." This is partially true — the refactoring happened *during* implementation, not after large accumulation of technical debt. The review-during cycle (not just review-before) is what allowed correction before it became expensive.
- Next iteration
- The Runtime subsystem was internally restructured. The broader effect was that the lessons were applied to subsequent subsystems and the Bootstrap, which also went through architectural refinement. From the Implementation Report "Architectural Refinements" section: > "Passive Context pattern, Immutable Snapshot pattern, Protocol-first subsystem boundaries, Constructor dependency injection, State Machine ownership of lifecycle, Separation of Engine, Executor, and Orchestrator responsibilities"