Skip to content

Logistics performance validation

This workflow validates the external Screeps milestone 0.3.6.4 — Performance and Traffic Feedback through the normal Screeps Lab subject boundary. It does not import subject source, alter ../screeps, change the snapshot schema, place MMO construction sites, deploy to the public MMO, update a baseline, or merge a branch.

Inputs and preparation

Use Node 22 from .nvmrc. The external subject must be a clean checkout at ../screeps, on feature/logistics-performance-traffic-feedback, with package version 0.3.6.4; the adapter enforces and records those values. Use the existing snapshot:

artifacts/incoming/screeps/snapshots/latest/snapshot.json

The current snapshot provides an owned room, sources, source containers, roads, storage, and source/receiver links. Scenario preparation removes only the primary room's derived logisticsNetwork, logisticsNetworkEvaluation, and matching aggregate performance stats so the subject rebuilds route telemetry against private-world object IDs. Infrastructure plans, approvals, remote policy, unrelated Memory, and the snapshot schema are preserved.

Objects are selected semantically by structure role and position. The importer mapping resolves selected snapshot objects to private-server IDs; no MMO object ID or creep name is hardcoded. Because MMO snapshots omit live creeps, Lab seeds role Memory and normally spawns one working harvester per semantic source plus four haulers (and B-only contamination controls). Contract H instead seeds and spawns one MOVE-only role=harvester sentinel with a valid sourceId per source. This satisfies subject population checks without producing energy while Lab controls source energy explicitly for the quiescent decay phase.

Shared execution and evidence

Scenarios sample at each 25-tick subject rollup boundary, including tick zero and the final tick. Contracts A, I, D, and H additionally sample every five ticks so their scheduled mutations run at distinct boundaries. A reapplies its one-target drain so active demand cannot disappear between rollups; I refills one storage destination so zero destination demand remains deterministic. Assertions require at least 75 confidence ticks before mature health conclusions. The engine supports bounded scheduled mutations at these boundaries, records each mutation in timeline.jsonl, and rewrites the final world-mutations.json with applied ticks, commands, successful results, and failed creative-command evidence.

Each run retains the standard scenario-report.json, assertions.json, subject-runtime-errors.json, timeline.jsonl, final tick and cleanup evidence, plus:

  • final-player-memory.json
  • logistics-performance-samples.json
  • route-performance.json and route-health.json
  • traffic-evidence.json
  • topology-cache.json
  • logistics-performance-stats.json
  • debug-equivalent.json
  • mutation-timeline.json
  • memory-bounds.json
  • healthy-route-contract.json (Contract A route selection, correlated mature checkpoints, and stability)
  • idle-destination-contract.json (Contract I route selection, stability, and mature idle evidence)

The scenario engine cannot invoke subject debug globals without adding a console execution tick. Instead, debug-equivalent.json captures the equivalent network, route list, exact route performance, health reason, traffic, fingerprint, cache, and aggregate Memory.stats.rooms.<room>.logistics.network.performance fields. This limitation is explicit and does not claim direct debug.logisticsNetwork, debug.logisticsRoutes, or debug.logisticsRoute invocation.

All route summaries assert at most 24 traffic tiles, at most eight anomalies, no detected per-tick performance ledger, and pathCache.enabled === false. Traffic-related road evidence may change route intent priority but an unreferenced construction-site record fails validation.

Scenario contracts

Contract Scenario ID Ticks Fixture and phase assertion
A logistics-performance-healthy-road 150 Drain one semantic spawn (or deterministic fallback endpoint) every five ticks. Lock the highest-completion, then lexical, local route with at least 80% completed road support. One mature checkpoint on that exact stable route must jointly show active obligation, expected and actual throughput, efficiency at least 0.8, non-growing backlog, healthy cycle/job bounds, low unavailable/congestion/fatigue/fallback evidence, at most two recalculations, and final healthy.
I logistics-performance-idle-destination 100 Fill one semantic storage destination every five ticks and lock one local storage route. After maturity it must have positive source backlog, zero destination demand, no service obligation, zero expected and actual throughput, no blockage or delay evidence, non-critical health, and the reason idle: no current service obligation without a throughput-failure claim.
C logistics-performance-destination-blocked 175 Initially drain one semantic storage target and lock one matching local route by its destination component position. Require active demand before tick 25, then fill through tick 100 and prove that the same route pauses as non-critical idle with zero current demand-summary and actual throughput, without invented blockage; its rolling expected-throughput EWMA may remain positive while it decays. Drain at tick 100 and require that route to regain obligation and actual throughput. This transient three-phase contract is distinct from the mature steady idle state in Contract I.
D logistics-performance-link-blocked 175 Fill semantic source and receiver links, require exactly one locked route whose destination component position matches the receiver, and keep that receiver full through tick 75. Five-tick evidence cadence applies each recovery drain/refill pair at its own boundary. Blockage, attributed fallback, and recovery must all belong to that exact route; missing, multiple, or semantically mismatched locks fail closed even if unrelated link routes qualify.
F logistics-performance-fatigue 150 Remove up to eight road tiles from the semantic source-to-storage corridor; fatigue rises distinctly while delivery continues.
B logistics-performance-unroaded 150 Remove up to twelve corridor roads; correlate a positive on-route unroaded tile by position with an active road intent or inspectable pending candidate, without depending on presentation wording or directly placing an unapproved site.
E logistics-performance-congestion 200 Starting at tick 25, retry within a bounded window until up to two immobile Lab-owned interference creeps can be placed on/adjacent to an on-route traffic tile or stable interior road segment. Preserve every attempted creative command and its success or error, record every actual successful position, and correlate only successful positions that are captured traffic or road geometry. Require fixture success, four congestion samples, chokepoint status, fatigue distinction, and congestion health on those exact positions.
G logistics-performance-topology-invalidation 250 Before tick 200, lock every route whose source component position matches the semantic endpoint. Remove that endpoint and retain those route IDs from the unfiltered captured route list even when they become incomplete. At least one single locked route must itself show the post-mutation fingerprint change, disabled invalid/ineligible cache, and eventual zero stale traffic; evidence split across different routes fails all three assertions.
H logistics-performance-evidence-decay 300 Spawn one MOVE-only harvester sentinel per source, fill one semantic source container every five ticks during warmup, and lock all routes whose source component position matches it. From tick 100, drain every five ticks; both the retained 0.85 rollup and a later lower-weight checkpoint must contain every locked route at zero backlog with no obligation. Capture tick 226 before retiring the endpoint, then at tick 251 or later require prior active target intent to be inactive/absent while at least one same-ID non-target control intent remains active.

A/I/C/D/F have deterministic fixtures and automated assertions. Contract A mutates only its one selected destination; it records one road-backed route ID once route telemetry appears and never substitutes another route. Its correlated assertions cannot combine evidence from different routes or checkpoints. C and D likewise lock their semantic destination route before changing capacity. B is kept operator-run because proposal cadence may consume the full duration. E remains operator-run because engine collision timing can vary by two ticks even with the Lab interference hook. G needs 200 ticks to reach telemetry-only eligibility before mutation. G and H correlate imported targets by component role, structure type, and position rather than comparing importer-private IDs with logical node IDs. H uses the 100-tick controlled warmup, full-window quiescent decay comparisons before retirement, the tick-226 pre-retirement intent snapshot, and tick-251-or-later target/control comparison through tick 300.

Operator commands

Run scenarios from the Lab repository. Expected success is exit code 0, terminal classification pass, exact requested tick completion, no subject runtime errors, all required assertions passing, and successful cleanup.

npm run scenario:run -- logistics-performance-healthy-road --subject-path ../screeps --snapshot artifacts/incoming/screeps/snapshots/latest/snapshot.json --reset --server-tick-duration-ms 100
npm run scenario:run -- logistics-performance-idle-destination --subject-path ../screeps --snapshot artifacts/incoming/screeps/snapshots/latest/snapshot.json --reset --server-tick-duration-ms 100
npm run scenario:run -- logistics-performance-destination-blocked --subject-path ../screeps --snapshot artifacts/incoming/screeps/snapshots/latest/snapshot.json --reset --server-tick-duration-ms 100
npm run scenario:run -- logistics-performance-link-blocked --subject-path ../screeps --snapshot artifacts/incoming/screeps/snapshots/latest/snapshot.json --reset --server-tick-duration-ms 100
npm run scenario:run -- logistics-performance-fatigue --subject-path ../screeps --snapshot artifacts/incoming/screeps/snapshots/latest/snapshot.json --reset --server-tick-duration-ms 100
npm run scenario:run -- logistics-performance-unroaded --subject-path ../screeps --snapshot artifacts/incoming/screeps/snapshots/latest/snapshot.json --reset --server-tick-duration-ms 100
npm run scenario:run -- logistics-performance-congestion --subject-path ../screeps --snapshot artifacts/incoming/screeps/snapshots/latest/snapshot.json --reset --server-tick-duration-ms 100
npm run scenario:run -- logistics-performance-topology-invalidation --subject-path ../screeps --snapshot artifacts/incoming/screeps/snapshots/latest/snapshot.json --reset --server-tick-duration-ms 100
npm run scenario:run -- logistics-performance-evidence-decay --subject-path ../screeps --snapshot artifacts/incoming/screeps/snapshots/latest/snapshot.json --reset --server-tick-duration-ms 100

Or run the 1,650-tick sequential operator suite:

npm run suite:run -- logistics-performance-validation \
  --subject-path ../screeps \
  --snapshot artifacts/incoming/screeps/snapshots/latest/snapshot.json \
  --reset \
  --server-tick-duration-ms 100

The complete suite is intentionally operator-run under the Lab's 15-minute agent policy. Child artifacts live under artifacts/suites/runs/<run-id>/; the latest scenario convenience link is artifacts/scenarios/latest/. Generated run artifacts remain ignored and must not be committed.

Tolerances and interpretation

Tick boundaries allow plus or minus one observed tick. Contract I requires a mature exact idle reason with all blockage and delay counters at zero. Contract A requires throughput efficiency of at least 0.8, actual cycle time within 25% of the estimate, average job time within 50% of the estimate, road completion of at least 80%, delay and fallback ratios below their subject healthy thresholds, and no more than two cumulative path recalculations. Other rolling throughput and cycle comparisons allow plus or minus 20%. The fatigue comparison allows 25% cycle tolerance. Health is not asserted before 75 confidence ticks. Congestion requires four qualifying same-position samples and may vary by two engine ticks. Traffic weight decays by 0.85 per 25-tick rollup, subject to three-decimal rounding and minimum-weight removal. Contract H accepts retention only at least one full 25-tick window after drain, and both retained and later-reduced samples must contain every locked target route in the quiescent state. Contract C checks current demand-summary throughput separately from its decaying rolling expected throughput. These tolerances come from the subject validation contract and are not weakened for Lab execution.

A failed assertion, subject error, timeout, preparation/deployment/orchestration error, or cleanup error is not a pass. Inspect summary.txt, scenario-report.json, assertions.json, mutation-timeline.json, and subject-runtime-errors.json before diagnosing subject behavior or rerunning.