Repository navigation
Implement the canonical configuration hierarchy (REQ-CONFIG-001) - #67
Conversation
Scaffold RunOptions, SimulationConfig, ScenarioDefinition and DefinitionPack per docs/spec/mirror/06 - Handoff/03 — CANONICAL_CONFIG_AND_WORLD_GENERATION.md section 2, and add assertNoBehavioralOverrides, the mechanical proof that scenario-specific behavioral overrides (including the markets/clans name collision between the two hierarchies) are rejected. Closes #64.
Verdict: REQUEST_CHANGES(Posted as a comment because GitHub refuses a same-account formal review on this PR.) Everything I checked out at head
The blocking defectFile: Root cause: PR #66 merged after this branch was cut and flipped the What would satisfy it: merge or rebase onto current Set the linked Issue (#64) back to |
…fig-hierarchy # Conflicts: # docs/spec/IMPLEMENTATION_STATUS.md
Verdict: ACCEPT(Posted as a comment because GitHub refuses a same-account formal review on this PR.) Reviewed head
Merging via the protected path. |
Adds deriveKeyedRandom, a pure function of (seed, tick, phase, key) with no shared mutable state, so iteration order over a set of keys cannot change any individual key's derived value. Also reconciles the REQ-CONFIG-001 IMPLEMENTATION_STATUS row to IMPLEMENTED now that PR #67 merged as 493da16. Closes #69 Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Closes #64
Achieved outcome
The four canonical configuration layers
RunOptions,SimulationConfig,ScenarioDefinitionandDefinitionPacknow exist insrc/config/as structurally distinct, non-interchangeable TypeScript types, matchingdocs/spec/mirror/06 - Handoff/03 — CANONICAL_CONFIG_AND_WORLD_GENERATION.mdsection 2 exactly. A new runtime validator,assertNoBehavioralOverrides, is the mechanical proof that "scenario-specific behavioral overrides are forbidden in core v1": it rejects a scenario-shaped candidate carrying any ofSimulationConfig's 13 behavioral-tuning keys, or any keyScenarioDefinitiondoes not declare, while accepting a minimal well-formed scenario.Correction (addresses ACCEPTOR REQUEST_CHANGES on
58fc530)The prior head (
58fc530b8c168ddae9fd6e9682ed7f5411574262) wasCONFLICTING/DIRTYagainstmaster: PR #66 had merged and flippeddocs/spec/IMPLEMENTATION_STATUS.md'sREQ-CORE-002row fromIN_PROGRESStoIMPLEMENTEDafter this branch was cut, and this branch's stale copy of the same row collided with it. Mergedorigin/masterinto this branch and resolved the conflict exactly as requested: keptREQ-CORE-002asIMPLEMENTED(per #66/#58, not regressed), kept the newREQ-CONFIG-001row asIN_PROGRESS, and recomputed the summary line to "7 of 25 requirements implemented; 1 in progress" (7 implemented + 1 in progress + 17 unmapped = 25). No other file conflicted or needed changes; thesrc/config/**diff is unchanged from the previous revision.Tested revision
0631b5b417f4562acff53fe1dd9fff548174c5d1(branchclaude/issue-64-config-hierarchy, merge commit reconciling withmaster)Changed artifacts
src/config/runOptions.ts—RunOptionsexactly per section 2.src/config/simulationConfig.ts—SimulationConfigplus its 13 named sub-config placeholder types (NumericConfig…PerformanceConfig, each documented as "concrete fields land with the requirement that owns this subsystem"), and the exportedSIMULATION_CONFIG_BEHAVIORAL_KEYSkey list used by the validator.src/config/scenarioDefinition.ts—ScenarioDefinitionplus its 12 named seed placeholder types (RegionSeed…ScenarioVariationConfig), and the exportedSCENARIO_DEFINITION_KEYSkey list.src/config/definitionPack.ts—DefinitionPackplus its 4 named definition placeholder types, reusing the existing canonicalGoodIdfromsrc/domain/id.tsforRecord<GoodId, GoodDefinition>.src/config/validation.ts—assertNoBehavioralOverrides, the behavioral-override/unknown-key rejection described above. Handles the genuinemarkets/clansname collision between the two hierarchies (an array value is the legitimate scenario seed list; an object value at that key name is a smuggledMarketConfig/ClanConfigpatch).src/config/index.ts— barrel-exports all four layers and the validator; keeps the pre-existingCONFIG_MODULE_AREAscaffolding constant (same patternsrc/domain/index.tsalready uses alongside its real exports).src/config/configLayers.typecheck.test.ts—tsc --noEmitregressions (@ts-expect-error, same style assrc/domain/id.typecheck.test.ts) proving the four layers are not mutually assignable.src/config/validation.test.ts— accepts a minimal well-formed scenario and the legitimate array-shapedmarkets/clansfields; rejects an injectednumerickey, an object-shapedmarketsoverride, an object-shapedclansoverride, an arbitrary unknown key, and a non-object candidate.docs/spec/IMPLEMENTATION_STATUS.md—REQ-CONFIG-001row (IN_PROGRESS, naming this Issue/branch and the proving tests); summary recomputed to "7 of 25 requirements implemented; 1 in progress" after mergingmaster's already-mergedREQ-CORE-002 → IMPLEMENTEDcorrection from PR Reconcile REQ-CORE-002 status after merged PR #58 #66 (see Correction section above).No
TradeCraftSimulation/**orTradeCraftSimulation.Tests/**file was touched.Acceptance criteria
RunOptions,SimulationConfig,ScenarioDefinitionandDefinitionPackexist insrc/config/matching section 2's shape, with named (placeholder-content-acceptable) types for every nested type section 2 references.SimulationConfig-owned behavioral key, and rejects one carrying an arbitrary unknown key, while accepting a minimal well-formed one.src/config/index.ts.npm run typecheck,npm test, andnpm run buildpass.docs/spec/IMPLEMENTATION_STATUS.mdgains aREQ-CONFIG-001row (this pull request adds it asIN_PROGRESS, per the legend's rule thatIMPLEMENTEDrequires an actual merge — it becomesIMPLEMENTEDonly once this or a follow-up reconciliation PR merges).Checks
npm ci0631b5b417f4562acff53fe1dd9fff548174c5d1npm run typechecktsc --noEmitclean at0631b5b417f4562acff53fe1dd9fff548174c5d1npm testsrc/config/configLayers.typecheck.test.tsandsrc/config/validation.test.tsnpm run buildvite buildsucceededpython3 scripts/policy_guard.py --base masterpolicy-guard: passed over 9 changed file(s)at this revisiondotnet build --configuration ReleaseTradeCraftSimulation/**orTradeCraftSimulation.Tests/**file changed; residual risk: none — this change cannot affect the legacy build.dotnet test --configuration ReleaseNot checked
@ts-expect-errortypecheck-test cases was manually spot-checked (temporarily removing one directive reproduced a realtscerror:TS2739: Type 'ScenarioDefinition' is missing the following properties from type 'RunOptions': scenarioId, seed, diagnosticsLevel) but this manual step is not itself part of any repeatable CI check.docs/index.html/docs/m0-preview.jsonruntime path).Assumptions and unknowns
SimulationConfigsub-domains" means each sub-config placeholder may be a bare empty interface (interface NumericConfig {}), documented with a pointer to the requirement that will add real fields. I did not add even illustrative fields, to avoid preempting a requirement row the registry has not yet created.markets/clanskey-name collision betweenSimulationConfigandScenarioDefinition(both hierarchies independently chose these names in the mirrored spec) is resolved by shape (array = legitimate scenario seed list, plain object = smuggled behavioral patch) rather than forbidding those two scenario fields outright — forbidding them outright would make a real baseline scenario'sclansfield unvalidatable, which cannot be the intended behavior of "reject arbitrary scenario behavioral patches."docs/spec/mirror/REQUIREMENTS_REGISTRY.csv'sREQ-CONFIG-001row hasSTATUS=READY,PRIORITY=P0,DEPENDS_ON=REQ-CORE-001(alreadyIMPLEMENTEDper PR Implement canonical persistent typed IDs (REQ-CORE-001) #48), matching the Issue's own Evidence section.REQ-CONFIG-001or touchessrc/config/**(checked viagh issue list/gh pr listbefore claiming).Highest-risk area for review
src/config/validation.ts's handling of themarkets/clansname collision is the one place this change makes a judgment call the specification text does not spell out mechanically (see Assumptions above). A reviewer should confirm the array-vs-object discriminator is the right mechanical proxy for "legitimate scenario seed list" vs. "smuggledSimulationConfigsub-config," since the two hierarchies' own interfaces (section 2) never state a disambiguation rule directly.Remaining gate
None. The merge conflict against
masterthat blocked the previous head is resolved; all required checks are green at the current head. Concrete sub-config/seed field defaults,buildInitialWorld, keyed deterministic RNG, entity/definition registries and full content validation are separate, not-yet-claimed requirements (REQ-CONFIG-002..005,REQ-CORE-003) already named as non-goals in Issue #64.