Skip to content

M4 Phase-5 production execution still reads immutable seed lifecycle status after #636 #638

Description

@andy-zen-dev

Goal

Finish the lifecycle-authority repair introduced by #636: every canonical Phase-5 production-execution decision must use the sole mutable live ProductionUnitState.status, never immutable ProductionUnitSeed.status. Reactivated or closing units must behave according to their current lifecycle state regardless of how they started the scenario.

Evidence

Current live baseline: master is 3a774cfbe2f2f6d5d46ccea75770a475b78eaf1d. Its only commit after the #636 squash merge (8f44c3ead86ca8b9ca3623a9911132492c22851e) is MACHINE ledger-provenance PR #637, which changed only docs/spec/implementation_status.csv and its generated Markdown. Therefore the Phase-5 source below is still the accepted #636 product code.

Concrete location: src/simulation/productionExecution.ts already plans physical production from the live authority (if (unit.status !== "ACTIVE") ...), but later runtime validation/coverage/output-sale paths still read unit.seed.status in six places:

  1. validateExecutionPhysicalContract() rejects positive realizedBatches when the seed was non-ACTIVE.
  2. The same validator requires the exact recipe input-good set only when the seed is ACTIVE.
  3. Its extraction-resource provenance check is likewise conditional on seed ACTIVE.
  4. validateProductionExecutionCoverage() derives expectedActiveUnitIds from unit.seed.status.
  5. The same coverage validator records submitted ACTIVE units from unit.seed.status.
  6. buildProductionOutputSellIntentsPhase5() skips a unit when unit.seed.status !== "ACTIVE".

This is a split runtime authority inside one module. For a unit that starts MOTHBALLED and is later reactivated by #636, Phase 2/early Phase 5 correctly see unit.status === "ACTIVE", but the transition validator can reject its positive production before output selling is reached because seed.status remains MOTHBALLED. The reverse divergence (seed=ACTIVE, live non-ACTIVE) can give validation/coverage privileges to a unit whose current state forbids normal production.

Governing contract: Issue #635 / REQ-PRODUCTION-007 acceptance criterion 1 requires one mutable runtime lifecycle authority, with runtime production/labor/lifecycle consumers using it while seed.status remains immutable starting data. Canonical Handoff/05 further states that PLANNED, MOTHBALLED and CLOSING units have zero normal production capacity (PCL-I18); reactivated MOTHBALLED units become ordinary ACTIVE units after the N+1 transition; MOTHBALLED units may liquidate excess inventory only through the configured/ordinary market path; and CLOSING units must perform no hiring/production/new investment while selling transferable inventories through ordinary SELL intents before safe retirement (PCL-I21, PCL-T24).

The original post-merge finding named only the output-SELL gate. Independent current-master validation found the five additional seed-status runtime decisions above, so this Issue is deliberately widened to one coherent Phase-5 lifecycle-authority repair rather than leaving another latent half-fix.

Scope

  • Replace every runtime lifecycle decision in src/simulation/productionExecution.ts that currently reads unit.seed.status with the canonical live unit.status, unless a read is proven to be genuinely about immutable scenario provenance rather than current behavior.
  • Make execution physical-contract validation use live status for positive-production eligibility, input-good provenance and extraction-resource provenance.
  • Make production-execution coverage derive expected/submitted ACTIVE units from live status.
  • Make output-sale eligibility derive explicitly from live lifecycle semantics, not seed status:
    • live ACTIVE keeps ordinary post-production OUTPUT selling;
    • live CLOSING can liquidate transferable OUTPUT stock through the existing ordinary SELL-intent path while still producing zero normal output;
    • live MOTHBALLED follows only the existing explicitly supported liquidation behavior (if any), never ACTIVE behavior merely because its seed was ACTIVE;
    • live PLANNED never gains ordinary ACTIVE production/sale privileges from its seed.
  • Add paired seed/live-divergence regressions around execution transition validation, coverage and OUTPUT SELL intents.

Non-goals

  • No change to lifecycle thresholds/cadence, Phase-14 decisions, N+1 activation, market clearing, reserve-price formulas, wage settlement, capital formation or safe-retirement stock accounting.
  • No new general liquidation subsystem and no new MOTHBALLED liquidation configuration. Input/INVESTMENT liquidation beyond the existing path is separate work unless already present and required to keep this bounded repair correct.
  • No M5 trade/FX, M6 mutable institutions, M8 demography/migration, credit path or specification change.
  • Do not mutate seed.status; it remains immutable starting data.

Acceptance criteria

  1. A seed=MOTHBALLED, live status=ACTIVE unit with otherwise valid current-tick plan/labor evidence can realize production, pass applyProductionExecutionTransition(), satisfy execution coverage and emit the same normalized OUTPUT SELL intent as an otherwise identical seed=ACTIVE, live ACTIVE unit.
  2. Changing only immutable seed.status while holding the complete live ProductionUnit state and Phase-5 evidence fixed cannot change any runtime Phase-5 production validation, coverage or output-sale decision.
  3. A seed=ACTIVE unit whose live status is PLANNED, MOTHBALLED or CLOSING cannot realize positive normal production and is not counted as an expected/submitted live-ACTIVE execution merely because of its seed.
  4. Input-good and extraction-resource provenance validation follows live ACTIVE status and remains fail-closed for forged positive ACTIVE execution evidence.
  5. A live CLOSING unit with residual transferable OUTPUT stock can use the ordinary OUTPUT SELL-intent path while realizing zero normal production; its eligibility is independent of immutable seed status. MOTHBALLED/PLANNED behavior remains bounded by the canonical lifecycle rules and does not acquire ACTIVE production privileges.
  6. No runtime unit.seed.status lifecycle gate remains in productionExecution.ts unless the PR handoff documents a concrete seed-only semantic reason and a regression proves it cannot override live status.
  7. Existing Implement deterministic ProductionUnit lifecycle and startup safety #636 lifecycle/startup, Phase-5 production/execution, Phase-12 capital and safe-retirement regressions remain green.
  8. Exact-head build-and-test, typescript, policy-guard, and mergeability are green on the repair revision.

Verification

Add focused tests in/around productionExecution.test.ts that construct semantically identical live ProductionUnit states with different immutable seed statuses and compare normalized Phase-5 results. At minimum cover:

  • seed=MOTHBALLED -> live=ACTIVE positive execution through transition + coverage + OUTPUT SELL;
  • seed=ACTIVE -> live=MOTHBALLED (and/or PLANNED) zero-production/coverage refusal control;
  • live CLOSING with residual OUTPUT stock and two different seed statuses, proving identical liquidation SELL intents and zero realized production;
  • an ACTIVE forged input/extraction provenance negative control proving the authority change does not weaken physical validation.

Run the full required TypeScript and retained .NET gates and report the exact tested head in the PR handoff.

Type: bug
Area: simulation-core
Priority: high

Activity

  1. added
    area:simulation-coreTick loop, ordering, determinism, configuration
    priority:highImportant and time-sensitive; schedule ahead of normal work
    qaFinding from the external QA voice, not yet turned into a work contract
    status:needs-triageAwaiting classification, evidence, or label axes
    type:bugVerified behavior differs from the intended contract
    on Sep 22, 2026
  2. andy-zen-dev commented on Sep 22, 2026

    @andy-zen-dev
    Author

    Independent validation on current master 3a774cfbe2f2f6d5d46ccea75770a475b78eaf1d: the stale-status finding is real, but the current Issue scope is narrower than the remaining code defect.

    src/simulation/productionExecution.ts still reads unit.seed.status in five runtime decisions, not only buildProductionOutputSellIntentsPhase5():

    • validateExecutionPhysicalContract() rejects positive realizedBatches when the seed was non-ACTIVE;
    • the same validator conditions input-good and extraction-resource provenance checks on the seed status;
    • validateProductionExecutionCoverage() builds expectedActiveUnitIds from seed status and records submitted ACTIVE units from seed status;
    • buildProductionOutputSellIntentsPhase5() skips seed-non-ACTIVE units as already described here.

    This makes the reactivation case stronger than the Issue currently states: a seed=MOTHBALLED, live status=ACTIVE unit can be planned with positive production by the live-status path, then fail during applyProductionExecutionTransition() before the SELL-intent builder is reached because validateExecutionPhysicalContract() still sees the old seed status. The reverse divergence (seed=ACTIVE, live non-ACTIVE) also leaves validation/coverage semantics tied to the wrong authority.

    #635 AC1 required all runtime production/labor/lifecycle consumers to use the sole mutable live status. I recommend expanding this repair (or splitting an explicitly linked sibling if scope must stay narrow) so every remaining seed.status runtime read in productionExecution.ts is either replaced with live unit.status or justified as genuinely seed-semantic. Add paired seed/live-divergence regressions around transition validation/coverage as well as the OUTPUT SELL boundary; changing only seed.status must not alter any runtime Phase-5 decision once live state is fixed.

  3. changed the title [-]Lifecycle output selling still reads immutable seed status after #636[/-] [+]M4 Phase-5 production execution still reads immutable seed lifecycle status after #636[/+] on Sep 22, 2026
  4. added
    status:readySpecified and unblocked; safe for an agent to claim
    status:in-progressClaimed work with an active branch or pull request
    and removed
    status:needs-triageAwaiting classification, evidence, or label axes
    status:readySpecified and unblocked; safe for an agent to claim
    on Sep 22, 2026
  5. drevendev commented on Sep 22, 2026

    @drevendev
    Owner

    Claimed for the bounded Phase-5 lifecycle-authority repair.

    Role: EndlessZen primary delivery worker
    Branch: zen/issue-638-phase5-live-status
    Scope: replace the remaining runtime unit.seed.status gates in productionExecution.ts with live-status authority; preserve zero normal production for non-ACTIVE units; permit CLOSING OUTPUT liquidation through the existing SELL path; add focused seed/live-divergence regressions; run the full required TypeScript and retained .NET gates; hand the exact PR head to SLOPSTER. No M5+ behavior or lifecycle-threshold redesign.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:simulation-coreTick loop, ordering, determinism, configurationpriority:highImportant and time-sensitive; schedule ahead of normal workqaFinding from the external QA voice, not yet turned into a work contracttype:bugVerified behavior differs from the intended contract

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions