Repository navigation
Implement RunOptions/ScenarioDefinition shape validation (REQ-CONFIG-005) #74
Description
Activity
- addedpriority:highImportant and time-sensitive; schedule ahead of normal workImportant and time-sensitive; schedule ahead of normal worktype:featureNew simulation capability or observable behaviorNew simulation capability or observable behaviorarea:simulation-coreTick loop, ordering, determinism, configurationTick loop, ordering, determinism, configurationstatus:readySpecified and unblocked; safe for an agent to claimSpecified and unblocked; safe for an agent to claimstatus:in-progressClaimed work with an active branch or pull requestClaimed work with an active branch or pull requestand removedstatus:readySpecified and unblocked; safe for an agent to claimSpecified and unblocked; safe for an agent to claim
on Sep 5, 2026 AUTHOR claim
- Role: AUTHOR
- Scope:
REQ-CONFIG-005— fail-fast, non-coercing validation ofRunOptionsandScenarioDefinition's required top-level field shapes, exactly as scoped in this Issue. Additive alongsideassertNoBehavioralOverrides; noNumericConfig/CadenceConfig/etc. bound checks, no seed-content/cross-reference checks (per Non-goals — those types remain empty placeholders pendingREQ-CONFIG-003). - Branch:
claude/issue-74-config-005-shape-validation - Known blocker: none yet.
Note: this run also reconciled
docs/spec/IMPLEMENTATION_STATUS.md's staleREQ-CORE-003row (PR #73 merged as3b6f2ebc87c204de75e0f2064df3c33f9e9efb48, closing Issue #72, since that row was last written) perAUTHOR_RUNBOOK.mdsection 1; that correction is carried in the same pull request as this Issue's work.- addedstatus:needs-reviewImplementation complete, awaiting acceptanceImplementation complete, awaiting acceptanceand removedstatus:in-progressClaimed work with an active branch or pull requestClaimed work with an active branch or pull request
on Sep 5, 2026 AUTHOR handoff
- Branch:
claude/issue-74-config-005-shape-validation - Tested revision:
524d95806bb25171f05b215d14103d6cf676ad1a - Pull request: Implement RunOptions/ScenarioDefinition shape validation (REQ-CONFIG-005) #76
Decisions: added a new sibling module
src/config/shapeValidation.ts(rather
than extendingsrc/config/validation.ts) since that file's own doc comment
already scopes itself to key-membership only and namesREQ-CONFIG-005as
out of its own scope. Both new functions are additive alongside
assertNoBehavioralOverrides.Checks:
npm ci/typecheck/test/buildall passed at the tested
revision (137 tests, 26 new);scripts/testsandpolicy_guard.pypassed;
dotnet build/testreportednot_run— noTradeCraftSimulation/**file
changed, so legacy risk is none. Full evidence is in PR #76's Checks table.This run also reconciled
IMPLEMENTATION_STATUS.md's staleREQ-CORE-003
row (PR #73 merged as3b6f2eb, closing Issue #72) in the same PR, per
AUTHOR_RUNBOOK.mdsection 1.What remains: none for this PR's own scope.
IMPLEMENTATION_STATUS.md
gains aREQ-CONFIG-005row only in a follow-up once this merges and its
merge commit is known — the row cannot honestly claimIMPLEMENTEDwhile
naming its own not-yet-existent merge commit. Settingstatus:needs-review.- Branch:
ACCEPTED and merged as squash commit
561e45290915d3107310e1de828af06c4f061b60(PR #76, tested revision524d95806bb25171f05b215d14103d6cf676ad1a).Verified independently before merge:
npm ci && npm run typecheck && npm test && npm run buildall passed at head (17 files / 137 tests); required CI checks (build-and-test,policy-guard,typescript) green at head; diff confined tosrc/config/shapeValidation.ts,src/config/shapeValidation.test.ts,src/config/index.ts,docs/spec/IMPLEMENTATION_STATUS.md; no invariant or test weakened; no secrets present. All acceptance criteria met except the self-referential IMPLEMENTATION_STATUS.md row, which per this repo's established precedent (Issue #72/PR #73 for REQ-CORE-003) is added in a later reconciliation PR rather than this one, since the merge commit can't be known before merging. Full verdict posted on PR #76.Removing
status:needs-reviewsince the Issue is now closed.- removedstatus:needs-reviewImplementation complete, awaiting acceptanceImplementation complete, awaiting acceptance
on Sep 5, 2026
Goal
Implement the slice of
REQ-CONFIG-005that is actually realizable today:fail-fast, non-coercing validation of
RunOptionsand ofScenarioDefinition'srequired top-level field shapes, so an invalid run configuration or a
structurally malformed scenario candidate is rejected before it can reach
world construction.
Evidence
docs/spec/mirror/REQUIREMENTS_REGISTRY.csvrowREQ-CONFIG-005: areaCONFIG, typeinvariant, priorityP0, statusREADY,DEPENDS_ON=REQ-CONFIG-001(alreadyIMPLEMENTED, PR #67, merge commit493da16e53e58e78a830ad44f1da627f9196742c). Acceptance: "Negative/invalidcross-reference and numeric cases fail before canonical world execution."
docs/spec/mirror/06 - Handoff/03 — CANONICAL_CONFIG_AND_WORLD_GENERATION.mdsection 21 ("Validation rules") lists ~20 fail-fast conditions: non-finite
values,
min > maxpairs, EMA alpha outside(0,1], probability/shareoutside
[0,1], cadence< 1, soft maxima below target, unknownGood/Recipe/Event/Metric IDs, missing Region/State/Clan/Currency/Authority
references, duplicate keys, per-entity numeric bounds (e.g. ProductionUnit
installedCapital < 0), bond-holdings-sum checks, and genesis reconciliationfailures.
Fact, not inference — checked directly against the current source, not
assumed from the document: every one of those bound/reference checks
targets a field that does not exist in the codebase yet:
src/config/simulationConfig.tsdeclaresNumericConfig,CadenceConfig,MarketConfig,TradeConfig,ProductionConfig,LaborConfig,PopulationConfig,ClanConfig,FiscalConfig,MonetaryConfig,ExpansionConfig,EventConfigandPerformanceConfigas empty{}placeholder interfaces. The file's own header comment states their
concrete fields "land with the requirement that owns the corresponding
subsystem (M3-M10)" — i.e. not this requirement.
src/config/scenarioDefinition.tsdeclares every seed type(
RegionSeed,TransportLinkSeed,StateSeed,CurrencySeed,MonetaryAuthoritySeed,ClanSeed,CohortSeed,ProductionUnitSeed,MarketSeed,BondSeed,InitialEventSeed,ScenarioVariationConfig) asempty
{}placeholders, explicitly pendingREQ-CONFIG-003/REQ-CORE-003.src/config/definitionPack.tsdeclaresGoodDefinition,RecipeDefinition,EventDefinitionandMetricDefinitionthe same way, pendingREQ-CONFIG-003.Only two layers currently carry concrete fields:
RunOptions(
scenarioId,seed,maxTicks?,diagnosticsLevel) andScenarioDefinition's own top-level shape (id,version,name,description,definitionPackId, plus its required/optional array/objectfields) — the latter already has a key-membership check
(
src/config/validation.ts'sassertNoBehavioralOverrides, fromREQ-CONFIG-001) but no check that a present key's value actually has therequired shape.
Scope
Add fail-fast, non-coercing validation, alongside (not replacing)
assertNoBehavioralOverrides, for exactly the fields that exist today:RunOptions:seedis a finite number (rejectNaN/±Infinity/non-number);maxTicks, when present, is a finite positive integer;diagnosticsLevelis exactly one of'OFF' | 'SUMMARY' | 'DEBUG';scenarioIdis a non-empty string.ScenarioDefinitiontop-level required-field shape (beyond keymembership):
id,version,name,description,definitionPackIdarenon-empty strings;
geography,transportLinks,states,currencies,monetaryAuthorities,clans,cohorts,productionUnitsare arrays;markets,bonds,initialEvents, when present, are arrays;variation, when present, is a plain object.what was found, matching section 21's "do not silently coerce" rule.
Non-goals
NumericConfig/CadenceConfig/MarketConfig/TradeConfig/ProductionConfig/LaborConfig/PopulationConfig/ClanConfig/FiscalConfig/MonetaryConfig/ExpansionConfig/EventConfig/PerformanceConfig— these are empty placeholders owned by later M3-M10requirements per Evidence above; there is nothing to bound-check yet.
ScenarioDefinitionseed type (RegionSeed,TransportLinkSeed,StateSeed,CurrencySeed,MonetaryAuthoritySeed,ClanSeed,CohortSeed,ProductionUnitSeed,MarketSeed,BondSeed,InitialEventSeed) — these are empty placeholders pendingREQ-CONFIG-003; duplicate-key and missing-reference checks cannot bewritten against a type with no fields.
DefinitionPackcontent validation (GoodDefinition,RecipeDefinition,EventDefinition,MetricDefinition) — same reason, pendingREQ-CONFIG-003.genesis reconciliation") —
REQ-CONFIG-004.assertNoBehavioralOverrides's existing key-membership behavior;new checks must be additive.
REQ-CONFIG-003and the relevant M3-M10 subsystem requirements landconcrete fields — that follow-up is separate work, not part of this Issue.
Acceptance criteria
RunOptionscandidate whoseseedisNaN,+Infinity,-Infinity, or not a number.RunOptionscandidate whosemaxTicksis present and is non-finite, non-integer, or
<= 0.RunOptionscandidate whosediagnosticsLevelis not exactly'OFF','SUMMARY', or'DEBUG'.RunOptionscandidate whosescenarioIdis empty or not a string.RunOptionsunchanged (no mutation/coercion of any field).
ScenarioDefinitioncandidate missingany required top-level field, or where a required field has the wrong
primitive/array shape (e.g.
geographygiven as a plain object insteadof an array,
idgiven as a number).ScenarioDefinition(the same shape
src/config/validation.test.ts'sminimalScenario()already uses) unchanged.
npm run typecheck,npm test, andnpm run buildpass.docs/spec/IMPLEMENTATION_STATUS.mdgains aREQ-CONFIG-005row oncethis merges, explicitly recording that only the
RunOptions+ScenarioDefinitiontop-level-shape slice is covered, and naming thesub-config/seed-content validation left open per this Issue's
Non-goals.
Verification
npm ci npm run typecheck npm test npm run buildDependencies, authority, and risks
REQ-CONFIG-001is alreadyIMPLEMENTED(PR Implement the canonical configuration hierarchy (REQ-CONFIG-001) #67); no other opendependency blocks this Issue.
NumericConfig/seed types might expect this Issue to cover all of section21. The Evidence section above documents, from the current source, why
that is not yet possible — the highest-risk area for review is confirming
that scoping boundary is correct rather than an implementer shortcut.
src/configchange plus its tests.