Skip to main content

Code Sync Audit

Status: governance reference — populated incrementally by waves. Wave D fills the Valenar-docs and SECS-design-docs sections. Other artifact sections are deferred to future waves and are marked explicitly. Status vocabulary in this doc follows pr-status-and-sync-policy.md.

Active Migration: Location → Territory Rename + Force Model (Wave D Docs)

The Location → Territory rename is the active cross-cutting migration. It is governed by docs/adr/ad-0005-territory-rename-and-force-model.md. This Wave D pass covers docs only. No Location alias, compatibility shim, or transitional synonym is preserved in any live design doc — per the no-backwards-compatibility tenet, every live artifact class must reflect Territory once its corresponding wave completes.

Doc files renamed by this Wave D:

  • examples/valenar/docs/systems/gd-locations-features-sites.mdexamples/valenar/docs/systems/gd-territories-features-sites.md
  • examples/valenar/docs/ux/gd-territory-dossier.mdexamples/valenar/docs/ux/gd-territory-dossier.md
  • examples/valenar/docs/generation/gd-territory-generation-contract.mdexamples/valenar/docs/generation/gd-territory-generation-contract.md
  • examples/valenar/docs/generation/gd-start-location-contract.mdexamples/valenar/docs/generation/gd-start-territory-contract.md

Doc files created by this Wave D:

  • examples/valenar/docs/systems/gd-forces.md
  • examples/valenar/docs/systems/gd-operations.md
  • examples/valenar/docs/systems/gd-defense-zones.md
  • examples/valenar/docs/systems/gd-fronts.md
  • docs/adr/ad-0005-territory-rename-and-force-model.md

Subsequent waves (deferred):

  • Wave S.secs source rename in Content/territories/Content/territories/; new Content/forces/, Content/characters/skills/fieldcraft.secs; updates to scope Character for the four position fields and to activity definitions for the TechniqueRef typed arg.
  • Wave GGenerated/Territories/Generated/Territories/; new compiler-owned generated output for Force, Operation, DefenseZone, Front, Fieldcraft, TechniqueRef; rename TerritoryKnowledgeTypes.csTerritoryKnowledgeTypes.cs and LocationContentStateTerritoryContentState.
  • Wave MHost/ and Server/ rename: LocationDataTerritoryData, LocationDossierReadModelTerritoryDossierReadModel, GameWorld.CoreLocationIdGameWorld.CoreTerritoryId, all internal field/parameter/variable names; SignalR DTOs and ReadModel projections.
  • Wave CClient/ rename: LocationContextPanel.tsxTerritoryContextPanel.tsx, LocationPlanningBoard.tsxTerritoryPlanningBoard.tsx, useLocationDossier.tsuseTerritoryDossier.ts; capture scenarios; Zustand store keys; Force/Operation/DefenseZone/Front UI surfaces.
  • Wave T — Test file rename and new tests for Territory, Force, Operation, DefenseZone, Front, Fieldcraft, and TechniqueRef dispatch.

The behavior-vocabulary baseline at Wave D start was 158. Wave D is docs-only and does not change that baseline. The baseline is updated by the wave that fixes the underlying offending lines, not by docs touches.

Wave M Out-of-Scope Forwards (Generated/ residue, deferred to Wave G2)

Wave M (Host/ + Server/ rename) deliberately did not touch any file under examples/valenar/Generated/, because the Generated tree is owned by Wave G and its follow-ups, not by Wave M. As a result, four identifiers in examples/valenar/Generated/Territories/FeaturePlacement/FeaturePlacementTypes.cs still carry the pre-rename Location form and must be renamed in a follow-up Wave G2 micro-edit before Wave Final closes the migration. The deferred identifiers are:

  • WorldMapFacts.Locations (line 150) — should become WorldMapFacts.Territories.
  • WorldMapFacts.StartingLocationId (line 152) — should become WorldMapFacts.StartingTerritoryId.
  • TerritoryFacts.LocationId (line 113) — should become TerritoryFacts.TerritoryId.
  • FeaturePlacementResult.LocationId (line 168) — should become FeaturePlacementResult.TerritoryId.

All four will be renamed in a single Wave G2 micro-edit before Wave Final. Until that micro-edit lands, the consumer callsites continue to read the pre-rename names by design:

  • examples/valenar/Host/Bridge/HostBridge.cs:749 reads world.MapFacts.Locations.TryGetValue(...) (a comment on the preceding line already flags the deferred rename).
  • examples/valenar/Generated/Systems/World/MapGenerationSystem.cs:150 reads placement.LocationId (and again at lines 259, 301, 304 in the same file) when ordering and binding FeaturePlacementResult rows to territories.

These callsites stay temporarily — they are not Wave M regressions and must not be patched as part of Wave M cleanup. They will be updated in the same Wave G2 micro-edit that renames the four field names above.

Wave M Git-History Note — LocationFoundingReadModel D+A

The Wave M rename of examples/valenar/Host/ReadModels/LocationFoundingReadModel.cs to examples/valenar/Host/ReadModels/TerritoryFoundingReadModel.cs landed in the working tree as a git delete + add rather than as a detected rename, because the post-rename file's content similarity to the pre-rename file falls below git's default 50% rename-detection threshold. With the explicit lower threshold, git diff --find-renames=10% --name-status HEAD -- examples/valenar/Host/ReadModels/ confirms the pair as R045 (45% similarity), which is below the 50% auto-detect cutoff but above the 10% floor — so the rename is real, just not auto-detected.

The two sibling renames in the same Wave M dispatch DID auto-detect: LocationDossierReadModel.csTerritoryDossierReadModel.cs shows as R070 at the default threshold. That confirms the FoundingReadModel below-threshold case is content-driven (the file is small and most of the body changed during the rename), not the result of a Write-vs-git mv process error.

The lost line-by-line history is recoverable via:

git log --follow --find-renames=10% -- \
examples/valenar/Host/ReadModels/TerritoryFoundingReadModel.cs

No remediation is required. The file's content is correct; the git provenance is suboptimal but inspectable.

Wave D Out-of-Scope Forwards

The following items reference the old Location vocabulary and would become stale after specific later waves complete; they are recorded here as forward-pointers, not as Wave D edits:

  • examples/valenar/docs/captures.md references the pre-rename LocationContextPanel and LocationPlanningBoard identifiers. These will be updated when Wave C renames the React components and the capture scenarios are refreshed. Wave D does not edit captures.md. At Wave D close, captures.md retains 10 capital-Location mentions at lines 52, 92, 96, 101, 103, 115, 124, 130, 132, and 142. The hits reference the React components LocationContextPanel and LocationPlanningBoard, the dev-only bridge symbols window.__valenarCapture.getLocationCanvasPos and getMcLocationId, the location-* capture-scenario id family, and the lower-case location UX terms used in the rail-tab and dossier-inner-tab copy. All 10 hits will be updated in Wave C alongside the React component renames, the capture-scenario id renames, and the dev-only bridge symbol renames; a location-* -> territory-* capture scenario id migration is part of that same Wave C scope. Wave D intentionally does not touch any of these.
  • examples/valenar/docs/lore/adr/ad-0002-lore-docs-migration.md references examples/valenar/Content/territories/scopes.secs and Generated/Territories/TerritoryKnowledgeTypes.cs as historical-record citations of the docs tree at the time of that ADR. After Wave S and Wave G complete, a post-migration note may be added at the bottom of that ADR. Wave D does not edit lore ADRs.
  • examples/valenar/docs/implementation/pr-status-and-sync-policy.md references the pre-rename LocationData identifier in a status policy example. Wave M will carry the rename-related sync update for that file.
  • The Wave D-renamed doc paths are reflected in .claude/rules/valenar-generation.md paths: glob; the LocationData.csTerritoryData.cs rename target reference points at a path that does not yet exist (Wave M will land it). This forward-reference is intentional and acceptable per the rule-glob convention used elsewhere.

Wave S Outcome — Generated Provenance Tests Blocked Until Wave G

Wave S completed the Content/locations/Content/territories/ directory rename, the bare_locationbare_territory template rename, the LocationTerritory scope/contract/channel renames in .secs source, the new Content/forces/ files (Force, Operation, DefenseZone, Front scopes/contracts/channels), the new Content/characters/skills/fieldcraft.secs skill template, the four new Character position fields, the WorldData JSON-schema rename (starting_locationstarting_territory, location_cell_idterritory_cell_id, valenar:template/location/bare_locationvalenar:template/territory/bare_territory, and the top-level JSON array key "locations""territories") in both the Python generator (Content/maps/generate_dummy_worlddata.py) and the committed fixture (Content/WorldData/world-42.json).

After Wave S close, 20 of 41 GeneratedProvenanceTests fail because examples/valenar/Generated/Locations/ still emits // Source: Content/locations/... headers and the cross-checked scope, contract, and channel declarations still reference the old Location / Feature / Site Generated-side names. This is expected behavior pending Wave G and is recorded here as an explicit blocker, not as a Wave S regression. The 20 failing tests at Wave S close are:

  • EveryGeneratedFileDeclaresSourceOwnedProvenance
  • GeneratedAggregateFilesDeclareLockedSecsSources
  • GeneratedDeclarationsChannelsMirrorSecsSources
  • GeneratedDeclarationsCollectionsMirrorSecsSources
  • GeneratedDeclarationsContractMethodsMirrorSecsSources
  • GeneratedDeclarationsContractRootScopesMirrorSecsSources
  • GeneratedDeclarationsModifiersMirrorSecsSources
  • GeneratedDeclarationsRecordFieldsMirrorSecsSources
  • GeneratedDeclarationsScopeFieldsMirrorSecsSources
  • GeneratedDeclarationsScopeMethodsMirrorSecsSources
  • GeneratedDeclarationsScopesAndContractsMirrorSecsSources
  • GeneratedDeclarationsTemplateFieldsMirrorSecsSources
  • GeneratedMapGenerationCreateEntityCallsMirrorSecsSystemMethod
  • GeneratedTemplateChannelSourcesMirrorSecsTemplateBodies
  • GeneratedTemplateCommandMethodsMirrorSecsTemplateBodies
  • GeneratedTemplateCreateEntityCallsMirrorSecsTemplateMethods
  • GeneratedTemplateEntriesHaveMatchingSecsTemplateDeclarations
  • GeneratedTemplateFieldAssignmentsMirrorSecsTemplateBodies
  • GeneratedTemplateTagsMirrorSecsTemplateBodies
  • GeneratedVocabularyDeclarationsMirrorSecsSources

The historical remediation path was Wave G: rename Generated/Locations/Generated/Territories/, rewrite all // Source: Content/locations/... headers to // Source: Content/territories/..., rename Location / Feature / Site Generated scope/contract/channel declarations to their Territory counterparts, regenerate the FNV-1a-64 hash constants in compiler-owned generated output, and add emitted rows/helpers for the new Force / Operation / DefenseZone / Front / Fieldcraft constructs. Wave G must run after Wave S commits to clear all 20 provenance failures; until then dotnet test tests/Valenar.Host.Tests/ will report exactly these 20 failures and a verifier pass over the post-Wave-S state should treat them as acknowledged blockers, not Wave S regressions.

The Wave S WorldData JSON rename also breaks runtime deserialization in examples/valenar/WorldData/ValenarWorldDocument.cs, where the C# DTOs still declare Locations / LocationCellId (snake-cased to JSON locations / location_cell_id). Renaming those C# DTO members and the ValenarWorldLocation / ValenarWorldLocationFacts records to ValenarWorldTerritory / ValenarWorldTerritoryFacts / TerritoryCellId / Territories belongs to Wave M (Host/Server rename). Until Wave M runs, loading world-42.json at runtime will deserialize an empty Territories array and the world import system will fail to populate territories. dotnet build SECS.sln still passes after the Wave S round-2 fixture edits because compilation does not read the JSON.

Known Blockers At Wave Start

This section enumerates dirty-tree drift that existed in the working copy at the moment Wave D began, so future verifier passes can distinguish between Wave-D-introduced changes and inherited drift. The items here are explicitly out of Wave D scope (Wave D is docs-only per the wave matrix) and are recorded so that a subsequent verifier does not re-flag them as Wave D regressions. The Wave 0 explorer report enumerated these files in its "Repo state" section; this subsection is the audit-trail home for that enumeration.

Pre-Existing Build Break — Engine Resolver Rename Migration

A prior recovery wave began renaming the engine's primary stat-channel resolver type but did not propagate the rename to the consumer projects. As a result, dotnet build SECS.sln fails at the working-tree state Wave D inherited.

  • Wave that introduced the drift: prior recovery wave (not Wave D).
  • Build-failure sites (8 errors at conversation start):
    • benchmarks/SECS.Benchmarks/ScenarioBuilder.cs:69
    • benchmarks/SECS.Benchmarks/BenchmarkHost.cs:38 (×2)
    • benchmarks/SECS.Benchmarks/BenchmarkHost.cs:41
    • benchmarks/SECS.Benchmarks/HierarchicalScenario.cs:103
    • examples/character-trainer/Host/Bridge/HostBridge.cs:16
    • examples/character-trainer/Host/GameRuntime.cs:11
    • examples/character-trainer/Host/GameRuntime.cs:28 (×2)
  • Drift shape (per pr-status-and-sync-policy.md vocabulary): drift between current (consumer projects reference the prior engine resolver type name) and target (engine type was renamed). The fix is mechanical — update the eight call sites to the new type name — but it is a code change, not a docs change.
  • Wave D scope decision: NOT fixed in Wave D. Wave D is docs-only per the wave brief; touching benchmark or character-trainer source is outside the Wave D patch envelope.
  • Where the fix belongs: a future engine/runtime wave (Wave C in the recovery matrix, or a dedicated build-fix wave). Until that wave runs, dotnet build SECS.sln is expected to fail with these eight errors and verifier passes should treat the build break as a known blocker rather than a Wave D regression.
  • Reference for migration context: docs/copilot-stat-channel-migration.md:454 documents the rename history.
  • Assigned wave: Wave 0-Build (see pr-wave-roadmap.md § Wave 0-Build).
  • Resolved by: Wave 0-Build. All 11 StatResolver -> ChannelResolver consumer occurrences across 5 files were renamed. dotnet build SECS.sln returns 0 errors after this change. Status: CLOSED.

Pre-Existing Staged Drift In Companion Rule Files

The git status at the start of Wave D's session showed a set of files already in modified state in the working tree, before any Wave D edit ran. These modifications are content-correct (they update vocabulary in companion governance files) but predate Wave D and are not attributable to it.

  • .claude/rules/behavior-vocabulary.md — staged before Wave D began. Wave D's companion vocabulary edit went to docs/design/behavior-vocabulary.md, a different file. The pre-existing modification of the .claude/rules/ mirror is permitted under the meta-fix exception in .claude/rules/orchestrator-mode.md ("Edits that only change CLAUDE.md, .claude/rules/, settings, hooks, or auto-memory files are small and self-contained. The orchestrator may execute these inline rather than dispatching."), so no fix wave is required. The note exists to prevent future verifier passes from re-flagging the modification as a Wave D change.
  • Benchmark consumer files participating in the resolver-rename build break above:
    • benchmarks/SECS.Benchmarks/AllocationBenchmarks.cs
    • benchmarks/SECS.Benchmarks/BenchmarkHost.cs
    • benchmarks/SECS.Benchmarks/CachedHierarchicalBenchmarks.cs
    • benchmarks/SECS.Benchmarks/CommandProcessBenchmarks.cs
    • benchmarks/SECS.Benchmarks/HierarchicalBenchmarks.cs
    • benchmarks/SECS.Benchmarks/HierarchicalScenario.cs
    • benchmarks/SECS.Benchmarks/QueryBenchmarks.cs
    • benchmarks/SECS.Benchmarks/ScenarioBuilder.cs
    • benchmarks/SECS.Benchmarks/StatResolutionBenchmarks.cs
  • Character-trainer consumer files participating in the same build break:
    • examples/character-trainer/Host/Bridge/HostBridge.cs
    • examples/character-trainer/Host/GameRuntime.cs
  • Fix wave: the benchmark and character-trainer files share the same fix wave as the build break above (future engine/runtime wave). The .claude/rules/behavior-vocabulary.md modification needs no separate fix wave.

Purpose

This document tracks where committed Valenar docs, Content/, Generated/, Host/, Server/, Client/, src/SECS.*, tests/, and scripts/ diverge from each other or from the design contract. It is populated by waves; each wave fills the artifact-class sections it audits. It is the machine-readable record of drift between current implementation and target design — per-doc status blocks summarize, this doc enumerates.

When a wave audits a section, it appends a wave-labeled subsection rather than overwriting prior wave findings. Closed drift items (where the implementation is brought up to the target) are kept in the audit trail so that future readers can see what was wrong, what was fixed, and which wave fixed it.

How To Use This Document

Readers looking for the authoritative design use the doc tree (the systems/, generation/, acts/, catalogs/, and ux/ directories). Readers looking for known drift between design and implementation use this doc. Each artifact class has a top-level section; each section has one or more Wave <Letter/Number> subsections for the wave that audited it. Empty subsections say (deferred to Wave <ID>) using the wave-id convention from the wave brief. Open questions raised by an audit but not resolvable at audit time go in pr-open-questions.md, with this doc cross-linking to them.

Valenar Docs

Wave D

Wave D applied 10 patch-target edits to the Valenar docs tree to remove the deprecated behavior-noun and planning-noun vocabulary as live nouns and to fix two Territory-scale parentheticals that misled readers about Territory geometry. The deprecated terms are documented in docs/design/behavior-vocabulary.md; the audit below describes the rewrites without re-quoting them inline.

  • examples/valenar/docs/systems/objectives-clues-missions.md — H1 rewritten to "Objectives, Clues, Missions, and Activities" (the prior H1 ended with the deprecated planning-noun). Core Terms, Relationship Between The Layers, and Design Rules sections rewritten to remove the deprecated planning-noun as a live planning category and to introduce routine activity and composite activity as planning-layer sub-forms of activity (per the ADR-aligned behavior vocabulary in docs/design/behavior-vocabulary.md).

  • examples/valenar/docs/ux/current-plan.md — three substitutions removing the deprecated planning-noun and replacing it with composed-activity language at lines describing the active mission rollup, the active composed-activity context bullet, and the traceability rule.

  • examples/valenar/docs/ux/objectives-screen.md — three substitutions removing the deprecated planning-noun from the "approach" wording, the "active noun" listing wording, and the "Do not let noun replace" guidance line, all replaced with composed-activity phrasing.

  • examples/valenar/docs/systems/camp.md — one substitution rewriting "can surface as deprecated planning-noun" to "can surface as routine activity shapes".

  • examples/valenar/docs/glossary.md — Technique definition rewritten to remove the deprecated capitalized behavior-noun and planning-noun pair and to use activities, missions, and assignments instead.

  • examples/valenar/docs/systems/character-skills.md — two substitutions removing the deprecated capitalized behavior-noun and planning-noun pair from the "noun-list, Missions, or Assignments" enumeration and from the "Techniques, noun-list, Missions, and Assignments" enumeration, replaced with the activities/missions/assignments wording.

  • examples/valenar/docs/ux/combat-dungeon-screen.md — six substitutions: round-log row label rewritten so the fired noun is activity instead of the deprecated behavior-noun; behavior-branch field name updated to activity_ref (the field previously used the deprecated behavior-reference field name); resolver wording rewritten so a resolver activity takes a behavior reference (the prior wording used the deprecated resolver behavior-noun); the paired sentence about the resolver invoking the highest-weighted branch's behavior rewritten to activity; the "the resolver is itself a deprecated noun" paragraph rewritten to use activity and activity call path; and the cross-link line previously referring to the deprecated behavior-primitive wording rewritten to activity primitive. The proposal-doc nature of this file is unchanged; the substitutions are vocabulary fixes inside the proposal.

  • examples/valenar/docs/README.md — index entry for gd-realm-ranks-and-polity.md rewritten from "realm creation, rank, founding tier, and crown-scale capabilities" to "polity ladder above settlements, founding tier, and crown-scale capabilities" to remove the "realm creation" wording that contradicted the canonical line that there is no single Realm birth moment. Index entry for gd-objectives-clues-missions.md rewritten to match the new H1.

  • examples/valenar/docs/generation/territory-generation-contract.md (formerly location-generation-contract.md prior to Wave D Territory rename) — the (~50 km × 50 km) parenthetical at the Territory Scale description rewritten to (an irregular Voronoi polygon at this scale). The fix preserves the 250–500 km² area but removes the square-cell implication.

  • examples/valenar/docs/generation/world-generation-contract.md — the matching (a ~50 km × 50 km strategic cell) parenthetical rewritten to (an irregular Voronoi cell at this scale).

Wave D also created six new Valenar docs: implementation/status-and-sync-policy.md, implementation/code-sync-audit.md (this file), implementation/open-questions.md, systems/tags-and-classification.md, catalogs/tag-catalog.md, and systems/state-axes-and-thresholds.md. Inbound links from examples/valenar/docs/README.md were added in a single pass.

Wave D-Journal Readback Drift

Wave D's Journal owner-doc pass now anchors durable narrative readback in gd-journal.md and sharpens the ownership split with gd-current-plan.md, gd-territory-dossier.md, gd-objectives-screen.md, gd-objectives-clues-missions.md, gd-quest-and-lore-design.md, gd-canon.md, and gd-glossary.md. The accepted Journal code slice now ships the baseline runtime/client alignment that this owner-doc pass was pointing at: a dedicated Journal query/version/client path exists, Journal-class narrative memory no longer depends on a raw flat log surface, and Chronicle remains the separate combat-only chronology lane. The remaining drift is narrower and stays below the full contract in the following deferred areas:

  • Journal target vs raw-log surfaces — baseline implemented; single-authored Journal retained. gd-journal.md defines Journal prose as the only authored narrative lane. The dedicated Journal path now owns Journal-class narrative memory, so raw-log or event-log wording is no longer the target surface. What remains deferred is richer structure, annotation, and linking around that single surface, not a second prose lane.

  • Journal vs Chronicle separation — baseline implemented. gd-journal.md, gd-canon.md, and gd-quest-and-lore-design.md keep Journal for durable day-based narrative memory and Chronicle for combat chronology only. That boundary is now present in the accepted runtime/client slice. Remaining follow-through is richer cross-surface context, not any merger of Chronicle back into Journal.

  • Annotations and player notes. gd-journal.md defines annotation layering as part of the target contract, but player-authored notes and richer annotation affordance remain deferred.

  • Deeper Current Plan linking. gd-current-plan.md and gd-journal.md describe a tighter Journal-to-plan readback loop than the accepted baseline currently ships. Deeper Current Plan linking remains deferred.

  • Richer site / lore-artefact / faction metadata. gd-journal.md allows broader metadata and link depth than the accepted baseline currently exposes. Richer site, lore-artefact, and faction metadata remain deferred.

  • Core / camp / settlement / realm progression wording — shipped; no longer a broad deferred cleanup slice. The accepted runtime/client slice now separates these states explicitly: Core establishment creates the anchor and nearby reveal only; it does not create the first settlement or a Realm-birth moment. The first settlement is a later camp-gated step at the established Core location, and settlement, realm/governance, and construction surfaces stay locked until that first settlement exists. gd-core.md, gd-canon.md, and gd-glossary.md remain correct that the Core is distinct from settlement or realm birth. The residual in this area is no longer broad wording cleanup; only genuine Journal follow-through or any truly still-open Journal-only raw-log phrasing remains deferred.

The remaining Journal follow-through is tracked in pr-wave-roadmap.md. Wave J should now be treated as a follow-through wave for these deferred Journal items, not as first delivery of the dedicated Journal path or the Journal/Chronicle split, and not as the owner of the already-shipped Core -> camp-gated first-settlement -> settlement-gated realm/governance/construction wording slice. Rollout-sequencing decisions live in pr-open-questions.md.

Wave D-Story-Authoring Pipeline Follow-Through

This follow-through wave did not change lore truth, design truth, runtime surfaces, or story prose. It aligned docs/process surfaces around the already committed story layer from ad-0003-story-content-layer-and-agent-audit.md.

  • examples/valenar/docs/implementation/pr-llm-story-authoring-pipeline.md — new thin process doc that points local LLM agents to the committed story README, entry template, indexes, and ADR instead of re-embedding those rules; records the AGENTS.md / CLAUDE.md vs skills vs subagents split; marks story-specific skills and story-specific subagent files as future required rather than currently committed; and records the read-only auditor policy plus the current manual verification commands.

  • examples/valenar/docs/README.md — added a Story section linking the story README, entry template, all five indexes, and the new pipeline doc; also added the pipeline doc to the implementation-doc index so readers can reach the process surface from the main docs hub.

pr-open-questions.md remained unchanged because this follow-through wave did not surface a new decision that needs user input or a separate ADR. The lore prefix convention file also remained unchanged because ADR 0003 already established that the story layer sits outside the lore-tree prefix scheme.

Future required state remains deferred: dedicated story-specific skills, story-specific subagent files, and dedicated validators are not yet committed. This subsection records the governance scaffold so later waves can add those assets without collapsing the story/non-canon boundary.

Wave Q — Dynamic Quest Pressure and Cross-Act Lane Architecture

Status: SHIPPED (docs-only).

Wave Q shipped the docs-only contract for state-driven quest pressure and the seven cross-act Quest Thread lanes that feed the Saga Arc. The four user decisions Q1–Q4 are formalized in ad-0006-dynamic-quest-pressure-and-cross-act-lane-decisions.md. The runtime contract for the DynamicQuestPressureGenerator is the binding generation surface; runtime implementation is deferred to Waves QP / QL / QF / QR planned in pr-wave-roadmap.md.

Wave Q changes to the Valenar docs tree:

Wave Q did not touch any .secs, Generated/, Host/, Server/, Client/, src/SECS.*, or tests/ file. Runtime implementation is deferred to Waves QP, QL, QF, and QR.

SECS Design Docs

Wave D-Behavior Vocabulary

docs/design/behavior-vocabulary.md — the Wave 3 cleanup note was inaccurate: it claimed Wave 3 had removed the Valenar player-doc carve-out for the deprecated capitalized behavior-noun and planning-noun, when the actual doc cleanup happened in Wave D. Wave D updated that line to reference Wave D and to enumerate the player-facing Valenar docs cleaned by this wave.

The Group A allowlist section was extended with a normative bullet clarifying that Routine Activity and Composite Activity are planning-layer sub-forms of activity — not SECS keywords, not runtime nouns, and not separate behavior kinds. Routine Activity describes a reusable composed pattern; Composite Activity describes a one-time composed approach for a mission or complex operation. Both lower to sequences of atomic activity queue entries at execution time.

Content/

Wave S

  • 13 .secs system/event files: bare slot syntax replaced with assignment form (phase = Phases.X;, frequency = Cadence.Y;). The bare form (phase X;, frequency Y;) was an early prototype convention; the assignment form is canonical per the SECS design docs and matches what the future compiler will emit.
  • 6 .secs files: bare TemplateId strings (TemplateId.Create("Name")) replaced with canonical colon-slash format (TemplateId.Create("valenar:template/resource/name")). The bare form was a pre-Wave-5 convention; canonical ids are required per docs/design/01-world-shape.md § Canonical id string format and enforced by the CI guard scripts/check-secs-source-contract.sh.
  • 18+ .secs files: comment hygiene pass — removed Wave labels, v1/v2 version tags, temporary-output status adjectives, and future-compiler commentary from live source, per .claude/rules/secs-source-hygiene.md. Displaced historical context is recorded here and in pr-open-questions.md.
  • map_generation.secs: removed the bare frequency once; slot, added phase = Phases.Production; in assignment form. One-shot cadence is deferred to a future compiler keyword; the file records the Production phase commit without a frequency slot until that keyword lands.

Generated/

Wave G

  • Historical checked-in hash table: added canonical _Template hash constants for 5 resources (Iron, Coal, Copper, ManaCrystal, DragonBone) and 4 recipes (WheatFarmRecipe, LumberRecipe, IronMineRecipe, CoalMineRecipe, CopperMineRecipe). Added FNV provenance comments to Wheat and WheatFarmRecipe. Replaced stale Wave-5/5b inline comments with current canonical-format descriptions per the Wave-5b dual-use naming convention.
  • Template files: updated Id references from bare-name or unsuffixed constants to _Template hash constants (Iron, Coal, Copper, ManaCrystal, DragonBone, LumberRecipe, IronMineRecipe, CoalMineRecipe, CopperMineRecipe).
  • Building templates: updated Mine and Lumberyard ActiveRecipeId fields from bare-name template ids to _Template hash constants.
  • Historical checked-in module: added RegisterTemplateIdentifier calls for canonical ids (valenar:template/resource/iron, etc.) replacing bare-name registrations for the 5 resources and 4 recipes that now use _Template hashes.
  • GeneratedProvenanceTests: added 9 canonical-id overrides for _Template hashes (Iron_Template, Coal_Template, Copper_Template, ManaCrystal_Template, DragonBone_Template, LumberRecipe_Template, IronMineRecipe_Template, CoalMineRecipe_Template, CopperMineRecipe_Template). Fixed BuildingProductionSystemTests reference from H.Iron to H.Iron_Template.

Host/

Core Grounds — Runtime String Drift At GameRuntime.cs:356

The runtime journal string "The Core is established here and already anchors the first settlement." at examples/valenar/Host/GameRuntime.cs:356 conflates the Core layer (MC's personal anchor at the Nexus/Wardheart) with the Settlement layer (the population-bearing layer that begins at the first Outpost in Act 2). The docs commit Core and Settlement as distinct layers and commit Core Grounds as the preferred physical-area term for the Core's anchor compound; the runtime string predates that wording and is now player-visible drift.

  • Drift shape: runtime string lags the committed Core-vs-Settlement scale boundary recorded in gd-canon.md "Core Distinctions", gd-core.md, and gd-glossary.md "Core" entry. The string implies Core establishment also births the Settlement, which the docs explicitly reject.
  • Scope of fix: rewrite the journal string so Core establishment does not imply Settlement birth. Candidate wording such as "The Core is established here. The Settlement layer remains a separate Act 2 step." is illustrative; the runtime wave will finalize the exact string when it ships.
  • Wave assignment: out of scope for the Core Grounds docs wave (this task was docs + .secs comment only). Belongs to a future runtime / Host wave or to Wave L (Host and Server vocabulary audit) per pr-wave-roadmap.md. Status: OPEN.

Server/

(deferred to Wave L)

Client/

(deferred to Wave Cl)

src/SECS.*

(deferred to Wave S)

tests/

Wave T

Wave T is the additive cross-cutting audit that combines (a) the original pr-wave-roadmap.md § Wave T charter — audit tests/**/*.cs and scripts/check-behavior-vocabulary.sh for live deprecated-vocabulary tokens — with (b) the CI / test / validation consolidation slice that fell out of the Activity Detail / Nested Surface Alignment task. Both halves are docs-only edits to this audit doc and to pr-wave-roadmap.md; Wave T does not edit test code, scripts, baselines, workflows, or .secs content.

Canonical Validation Command Set

The following commands, in the order shown, are the canonical validation surface a verifier or contributor should run after any Activity Detail, nested surface, founding step, or behavior-vocabulary touching change. Wave T did not introduce or modify any of these commands; this subsection records the ordered set so future waves do not re-derive it from scratch.

  1. dotnet build SECS.sln
  2. dotnet test tests/SECS.Engine.Tests/SECS.Engine.Tests.csproj
  3. dotnet test tests/Valenar.Host.Tests/Valenar.Host.Tests.csproj
  4. dotnet test tests/Valenar.Server.Tests/Valenar.Server.Tests.csproj
  5. cd examples/valenar/Client && npx tsc --noEmit
  6. bash scripts/check-behavior-vocabulary.sh --check
  7. bash scripts/check-readonly-boundary.sh --check
  8. bash scripts/check-secs-source-contract.sh --check
  9. bash scripts/check-tag-contract.sh --check
  10. bash scripts/check-save-load-contract.sh --check
  11. bash scripts/check-activity-provenance-contract.sh
  12. bash scripts/check-valenar-story-forbidden-terms.sh
  13. bash scripts/validate-valenar-story-docs.sh
  14. python3 tests/valenar_story_audit/test_validate_story_docs.py
  15. git status --porcelain (no unintended modifications)

The Python story audit at step 14 is included per the orchestrator-committed Q4 decision: it is a canonical validator that should run alongside the C# test projects and the shell guard scripts, not as an isolated audit. It is not yet wired into a top-level dotnet test umbrella because it is a non-.NET runner; Wave T does not introduce that wiring.

Wave T — Known Pre-Existing Test State

The Wave T explorer's brief originally framed tests/Valenar.Host.Tests/GeneratedProvenanceTests.cs:1773 GeneratedTemplateFieldAssignmentsMirrorSecsTemplateBodies as a pre-existing failure caused by a mismatch between examples/valenar/Generated/Templates/Resources/Mine.cs / Lumberyard.cs field assignment rows and the corresponding examples/valenar/Content/.../mine.secs / lumberyard.secs field bodies. Wave T re-ran dotnet test tests/Valenar.Host.Tests/Valenar.Host.Tests.csproj at the working-tree state Wave T inherited and observed all 219 tests passing, including GeneratedTemplateFieldAssignmentsMirrorSecsTemplateBodies.

The drift surface the explorer flagged either:

  • has already been resolved by an intervening commit between the explorer's snapshot and the implementer's snapshot, or
  • was a false positive in the explorer's grep-based inference (the explorer did not actually run the test before writing the brief).

Wave T does not invent a .secs fix, rewrite Generated/ content, or edit the test. If a future regression re-introduces the same shape, the correct fix is to align the .secs source field declarations with the compiler-owned C# field assignment rows emitted under examples/valenar-v2/Generated/obj/**/SecsGenerated/*.g.cs. For Valenar v2, .secs source plus compiler-owned SecsGenerated output is the authoritative generated shape; checked-in examples/valenar-v2/Generated/ contains only Valenar.V2.Generated.csproj and host-owned ValenarHostIds.cs. Do not fabricate .secs content to satisfy the test.

Wave T — blockedReason Vocabulary Clarification

The strings 'Loading founding state.' at examples/valenar/Client/src/components/modes/territory/stage0TerritoryModel.ts:115 and :123 are NOT fabricated activity-availability blockedReason values. They are client-owned TerritoryFoundingStepSnapshot.blockedReason loading-state placeholders for a different snapshot type (TerritoryFoundingStepSnapshot, not ActivityAvailabilitySnapshot or QueueItemSnapshot). They exist precisely because the founding step read-model carries its own blockedReason field that the React surface must populate before the SignalR snapshot arrives. Any future grep guard targeting fabricated activity-availability blockedReason fallbacks must exclude these two lines via a type-aware allow-list or a precise regex keyed on TerritoryFoundingStepSnapshot rather than on the literal string Loading founding state.. Wave T does not add such a guard.

scripts/

Wave T

Wave T — Behavior-Vocabulary Baseline State

scripts/check-behavior-vocabulary.sh --check reports OK at 158 hits against the recorded floor of 158 in scripts/.behavior-vocabulary-baseline. The script exits 0; the target floor described by .claude/rules/behavior-vocabulary.md "Target end state is 0 hits" remains aspirational.

The pre-Wave-T history of the baseline file:

  • The historical floor was 153 (set before the engine refactor commit e26c541 "engine: replace mutable Activity/Policy contexts with structural read-only types").
  • Commit e26c541 bumped the floor to 158 in the same change that introduced ActivityQueryContext, EventQueryContext, PolicyQueryContext, CandidateBuilderContext, ReadOnlyTickContext, and IReadOnlySlotStore. The +5 absorbed by that rebaseline is pre-Wave-T drift unrelated to any Wave T edit.

Wave T does NOT rebaseline. Per the orchestrator-committed Wave T scope and .claude/rules/behavior-vocabulary.md "each cleanup wave should lower the recorded baseline rather than letting it drift upward", the correct fix is a downstream cleanup wave (Wave Z per pr-wave-roadmap.md § Wave Z) that brings the actual hit count down toward 0 and then re-runs --baseline against the lower floor. Until that wave runs, the 158 floor stays.

Wave T — Excess Hits Identified (158 - 153 = 5)

The +5 drift between the historical 153 floor and the current 158 floor breaks down by guard-script group as follows. Wave T captured these via bash scripts/check-behavior-vocabulary.sh --check (against a temporarily-zeroed baseline) and via worktree comparison against the pre-e26c541 commit e022571. To avoid Wave T's audit table itself adding hits to the guard (the table would otherwise quote each banned token literally), the table below describes each hit by file path, guard group letter, and structural shape — the verbatim hit strings are visible in the script's --check output and are intentionally NOT re-quoted here.

File:lineToken groupStructural shapeContext
.claude/rules/secs-source-hygiene.md:22A (deprecated behavior-noun family — see .claude/rules/behavior-vocabulary.md § Removed)Negative-context table row enumerating forbidden old-keyword compatibility notesThe rule cites the banned token literally in order to forbid it.
.claude/rules/secs-source-hygiene.md:22B (deprecated planning-noun family — same § Removed)Same row, separately matched by the Group B regex on the literal banned planning-nounHit attributable to the second banned token sitting on the same line.
.claude/rules/secs-source-hygiene.md:59A (deprecated behavior-noun family)Inline contrast wording naming the banned behavior token to demonstrate which forms are illegal in live sourceNegative-context normative example.
.claude/rules/secs-source-hygiene.md:60B (deprecated planning-noun family)Inline contrast wording naming the banned planning token to demonstrate which forms are illegalNegative-context normative example, paired with the line above.
examples/valenar/Generated/Activities/Character/Site/CharacterSiteActivities.cs:640D (content-row identifier in the Activity_<ContentName> shape — see .claude/rules/behavior-vocabulary.md § Generic-mechanic vs content-row)Generated registration row for a one-off activity identifier emitted during a recent rename passStructurally similar to the existing Group D content-row family that the cleanup wave must either allowlist (if it becomes a generic-mechanic family) or fold into a typed-args generic-mechanic activity.

The first four hits are structurally one cluster: a single .claude/rules/secs-source-hygiene.md edit added two table cells and one inline paragraph that quote the two banned deprecated tokens in negative context. The fifth hit is the residual from a Group D rename pass (the rename ended +5 new identifier sites and -6 removed, net -1 inside Group D but the table only enumerates one representative new site to give the cleanup wave a concrete anchor).

Wave T — Suggested Fix Shape For The Downstream Cleanup Wave

Wave T does not fix the excess; documenting the actionable shape is the deliverable. The cleanup wave (Wave Z per pr-wave-roadmap.md § Wave Z) should:

  1. Either extend GLOBAL_EXEMPT_FILES in scripts/check-behavior-vocabulary.sh to include .claude/rules/secs-source-hygiene.md (matching the existing exemption for .claude/rules/behavior-vocabulary.md and docs/design/behavior-vocabulary.md, which are likewise normative-rule docs that necessarily quote the deny list), OR rewrite the four hygiene-rule cells/lines to describe the banned vocabulary structurally without naming the tokens (e.g. "deprecated planning noun" / "deprecated behavior noun" rather than the literal forbidden words). Wave T's recommendation is the exemption: the rule's stated purpose is to forbid the tokens, so it must be allowed to name them.
  2. For the Group D hit in CharacterSiteActivities.cs:640, evaluate whether the new one-off identifier should be allowlisted (if it has become a generic-mechanic family) per the .claude/rules/behavior-vocabulary.md § "CI guard" allowlist extension procedure, or whether it stays a one-off activity that simply contributes to the baseline floor until a future content refactor folds it into a typed-args generic-mechanic activity.
  3. For this audit doc itself: extend GLOBAL_EXEMPT_FILES to include examples/valenar/docs/implementation/pr-code-sync-audit.md so that future drift audits can quote banned-token shapes verbatim without adding to the floor — mirroring the existing exemption for docs/design/behavior-vocabulary.md. Wave T avoided this by writing the audit table structurally (see the table above), but a sibling exemption would let later audits be more concrete.
  4. After steps 1, 2, and 3 land, re-run bash scripts/check-behavior-vocabulary.sh --baseline against the newly-clean tree to lock the lower floor. Per .claude/rules/behavior-vocabulary.md, the cleanup-wave baseline re-run is the only legitimate path that lowers the floor.

Wave T — Pre-Existing CI Workflow Out Of Scope

.github/workflows/wave-t-validation.yml exists in the working tree at Wave T start as pre-session drift. Per the orchestrator-committed Wave T scope guidance, Wave T does not edit, validate, dispatch, or remove that workflow. The validator and any future cleanup wave should treat the workflow file as inherited surface rather than a Wave T artifact.

Wave T — GROUP_E_FILES / scan_exact_files Question

The original pr-wave-roadmap.md § Wave T § Open Questions asked whether the GROUP_E_FILES / scan_exact_files() expansion attempted in Wave D iter-1 warrants a separate ADR-gated governance wave. Wave T's audit finding is: defer. The current Group E (stat -> channel migration) scan in check-behavior-vocabulary.sh uses gather_stat_channel_doc_files and gather_stat_channel_code_files, which are bespoke gatherers for that specific migration. They are zero-tolerance, currently report 0 hits, and serve their purpose. No generalized GROUP_E_FILES mechanism is required today; a future migration that needs the same shape can copy the pattern.

Activity Detail / Nested Surface Alignment

This top-level section records the M/B/C/T/D-Detail wave outcomes for the Activity Detail / Nested Surface Alignment task. The four task waves disambiguate from the unrelated story-layer waves of similar letter names by carrying the (Activity Detail) task suffix in their roadmap entries. Wave T's CI/validation consolidation subsections continue to live under ## tests/ and ## scripts/; this section cross-references that work without duplicating it.

Wave M (Activity Detail) — UX Owner Docs

Status: SHIPPED.

Wave M (Activity Detail) shipped the 7 UX owner docs that anchor the Activity Detail / Nested Surface design contract:

Each doc carries an ## Implementation status section using the pr-status-and-sync-policy.md vocabulary. Wave M (Activity Detail) deliberately did not lock backend DTO field names in these docs; the abstract phrasing ("the parent-run / child-run reference Wave B (Activity Detail) exposes — Wave B-owned, pending sync") was intentional because Wave B (Activity Detail) had not yet committed names at the time of authoring.

Remaining drift (deferred): all 7 owner docs still use the abstract phrasing for parent-run / child-run / blocked-reason references. Now that Wave B (Activity Detail) has committed concrete names (ActivityRunSnapshot.ParentRunId, ActivityRunSnapshot.ChildRunId, QueueItemSnapshot.BlockedReason, TypeScript parentRunId, childRunId, blockedReason), a field-name sync pass is needed. Wave D-Detail deferred this pass to a dedicated Wave B-sync (Activity Detail) entry in pr-wave-roadmap.md rather than touching Wave M's territory in a Wave D-Detail docs-only scope. The open question is recorded in pr-open-questions.md § Wave B Field-Name Sync in gd-* Docs.

Wave B (Activity Detail) — Backend Fields, Scout Retirement, Demo Mods, Tests

Status: SHIPPED (engine wave committed, field names committed, tests at 219/219 PASS).

Wave B (Activity Detail) shipped engine parent/child run linkage, server-truthful blocked-reason projection, Scout lead retirement, demo mod retargeting, and two new test files:

  • ActivityRunSnapshot record at Server/Services/GameSnapshot.cs:121–122 added ParentRunId : long? and ChildRunId : long?. SHIPPED.
  • QueueItemSnapshot record at GameSnapshot.cs:224 added BlockedReason : string?. SHIPPED.
  • PlayerActivityQueueItemReadModel at Host/ReadModels/PlayerActivityQueueReadModel.cs:57 added BlockedReason : string?. SHIPPED.
  • TypeScript types at Client/src/api/types.ts:663–664 added parentRunId?: number | null and childRunId?: number | null on ActivityRunSnapshot. SHIPPED.
  • ScoutApproach activity WireId "scout-approach" at Generated/Activities/Character/Site/CharacterSiteActivities.cs:640 is committed and live; the legacy Scout lead identifier is retired. SHIPPED.
  • Demo mods retargeted: Generated/Mods/CompatScoutActivityMod.cs and ExtendedScoutActivityMod.cs both target the ScoutApproach activity hash constant in the H.Activity_<ContentName> shape (see Generated/Activities/Character/Site/CharacterSiteActivities.cs:640 for the canonical declaration; the literal hash identifier is the same Group D content-row token Wave T described structurally to avoid adding to the behavior-vocabulary baseline). SHIPPED.
  • Engine commit e26c541 introduced ActivityRun.Origin, ActivityRun.ParentRunId, ActivityRun.ChildRunId, and ActivityExecutor.StartAt(ActivityRequest, TickContext, int). The "PASS-conditional on engine-wave commit" gate that Wave B (Activity Detail) carried at brief time is now resolved; the engine APIs are in HEAD.
  • Two new test files cover the projected fields: tests/Valenar.Host.Tests/ActivityRunNestingProjectionTests.cs (2 tests covering host-side parent/child null projection and the host reverse-lookup round trip) and tests/Valenar.Host.Tests/QueueProjectionBlockedReasonTests.cs (2 tests covering null and non-null BlockedReason on queue rows). Both pass as part of the 219/219 PASS recorded by Wave T.

The locked Wave B (Activity Detail) field-name set is exactly parentRunId, childRunId, and blockedReason; no other fields were exposed by this wave.

Wave C (Activity Detail) — Shared Activity Detail Host, Openers, Client Cleanup

Status: SHIPPED with 2 openers deferred.

Wave C (Activity Detail) shipped the shared Activity Detail host component, the new mode, the depth/cycle guards, and the wired openers:

  • New activity-detail/ directory at Client/src/components/activity-detail/ carrying ActivityDetailHost.tsx, ActivityDetailHost.module.css, activityDetailRequest.ts, and useActivityDetailViewModel.ts. SHIPPED.

  • Mode mc/activity-detail with hiddenFromRail: true at Client/src/components/shell/modes.tsx:268,272. SHIPPED.

  • hiddenFromRail?: boolean field on ModeDef at Client/src/components/shell/modeDef.ts:118. SHIPPED.

  • Depth guard ACTIVITY_DETAIL_MAX_DEPTH = 16 at Client/src/components/activity-detail/activityDetailRequest.ts:84. SHIPPED.

  • 7 logical openers across 9 caller sites:

    1. Activities (catalog) — ActivitiesSummary.tsx, source 'catalog'.
    2. Activities (here/dossier) — ActivitiesSummary.tsx, source 'dossier'.
    3. Queue / QueueSummary — QueueSummary.tsx, source 'queue'.
    4. Queue / QueueNavigator — QueueNavigator.tsx, source 'queue'.
    5. Queue / QueueExpansion — QueueExpansion.tsx, source 'queue'.
    6. Territory Dossier rows — Stage0ActivityRows.tsx, source 'dossier'.
    7. BottomQueueSlots — BottomQueueSlots.tsx, source 'bottom-queue-slots'.
    8. Journal entries — MissionsExpansion.tsx, source 'journal'.
    9. Objectives entries — MissionsExpansion.tsx, source 'objectives'.

    The brief framed this as "7 openers SHIPPED" by collapsing ActivitiesSummary's two source variants into a single "Activities" opener and Queue's three caller sites into a single "Queue" opener, yielding 7 logical openers. The audit records both counts to avoid ambiguity in future waves.

  • Stage0ActivityPresentation.ts fallback cleanup at lines 33, 72, 98. The ?? undefined patterns are legitimate display deferrals (undefined hides the row) and not fabricated engine-data fallbacks. Cross-reference: Wave T — blockedReason Vocabulary Clarification under ## tests/ for the related distinction between activity availability and TerritoryFoundingStepSnapshot.blockedReason loading- state strings. SHIPPED.

  • FocusedQueueItem replaced — zero references remain in the client source tree. SHIPPED.

  • ActivitiesExpansion.{tsx,module.css} deleted — only a comment reference remains in ActivityDetailHost.module.css:4. SHIPPED.

  • queueStore.mapQueueItem at Client/src/stores/queueStore.ts:197 propagates blockedReason. SHIPPED.

Deferred openers (2):

  1. TerritoryContextPanel name tap (source: 'context-panel'). The ActivityDetailOpenerSource union at Client/src/components/activity-detail/activityDetailRequest.ts:29 already declares the 'context-panel' source value, but no TerritoryContextPanel caller invokes open('left', ACTIVITY_DETAIL_MODE_ID, ...). Wave D-Detail does not ship the wiring; the deferral is tracked in pr-open-questions.md § Activity Detail — Deferred Opener Decisions and as Wave TerritoryContextPanel (Activity Detail) in pr-wave-roadmap.md.
  2. Current Plan / Situations opener (source: 'plan'). The same union at line 27 already declares the 'plan' source value, but no plan/situations surface caller invokes the opener. Wave D-Detail does not ship the wiring; the deferral is tracked in the same pr-open-questions.md section and as Wave Plan (Activity Detail) in pr-wave-roadmap.md.

Wave T (Activity Detail) — CI / Validation Consolidation (cross-reference)

Wave T's Activity Detail-additive scope (canonical 15-step validation command list, pre-existing 153 -> 158 baseline drift documentation, blockedReason vocabulary clarification, and the 219/219 host-test state) already lives under ## tests/ § Wave T and ## scripts/ § Wave T. The Wave T entry is recorded once there and not duplicated here. Status: SHIPPED (docs-only).

Pre-Existing Drift Resolution Summary

Two pre-existing drift items called out by the Wave T audit had already resolved themselves at the current tree state Wave D-Detail inherited:

Wave D (Activity Detail) — Implementation / Process Docs / Backlog Alignment

Status: SHIPPED (docs-only).

Wave D-Detail aligned the implementation / process docs and the backlog to record the M/B/C/T (Activity Detail) outcomes:

  • This section in pr-code-sync-audit.md added.
  • 5 new wave entries added to pr-wave-roadmap.md: Wave M (Activity Detail), Wave B (Activity Detail), Wave C (Activity Detail), Wave TerritoryContextPanel (Activity Detail), Wave Plan (Activity Detail), plus the Wave B-sync (Activity Detail) field-name sync entry and Wave Vitest test-runner setup entry.
  • 3 new sections added to pr-open-questions.md: the deferred opener decisions, the Wave B field-name sync question, and the Vitest / JS test setup framework choice question.
  • pr-roadmap.md updated with the shared Activity Detail host runtime surface and the field-name sync near-term consumer.

Wave D-Detail did not touch the 7 gd-* owner docs; the field-name sync work is deferred per the open question and the scheduled Wave B-sync (Activity Detail) entry.

Open Drift Items

The following drift items are surfaced by Wave D for tracking but are not closed by Wave D. They live here as anchors and are cross-linked from the relevant design docs.

  • Territory knowledge axis: prototype vs target ladder. CLOSED by Wave R-1 (2026-05-10). The int Explored binary on TerritoryData was replaced by the eight-step TerritoryKnowledgeState enum (Unknown -> Sighted -> Scouted -> Surveyed -> Secured -> Claimed -> Cleansed -> Developed) plus a forward-compat int KnowledgeIntensity nuance field. The enum lives in examples/valenar/Generated/Territories/TerritoryKnowledgeTypes.cs; the scope-field row pair is registered through H.KnowledgeState / H.KnowledgeIntensity in the compiler-emitted hash table plus the compiler-emitted declaration rows. Numeric intensity thresholds remain TBD per systems/state-axes-and-thresholds.md "Territory Knowledge Axis".

  • Site numeric intensity field. CLOSED by Wave R-2 (2026-05-10). int StateIntensity was added to SiteData with a verified FNV-1a-64 hash constant (H.StateIntensity = 0x2BD07323BBB9FC07UL), a ScopeFieldDeclaration row in Generated/Declarations.cs, and read/write paths through the Site branch of HostBridge. Content/territories/sites/scopes.secs is in sync. The field tracks intensity on the State (progress ladder) axis, not on DiscoveryState. Default 0; numeric thresholds within each ladder label remain TBD per a future balance wave. Wire projection (SiteSnapshot) is deferred to a future Server wave. Resolved by: Wave R-2. Status: CLOSED.

  • Feature numeric intensity field. CLOSED for the field foundation by Wave R-3 (2026-05-10). int DiscoveryIntensity was added to FeatureData with a verified FNV-1a-64 hash constant (H.DiscoveryIntensity = 0x6B8E15B1072C893AUL), a ScopeFieldDeclaration row in Generated/Declarations.cs, and read/write paths through the Feature branch of HostBridge. Content/territories/features/scopes.secs is in sync. The field tracks intensity on the DiscoveryState ladder. Default 0; bare integer per the unified convention established by R-1's KnowledgeIntensity and R-2's StateIntensity. Wire projection (FeatureSnapshot.discoveryIntensity) is deferred to a future Server wave, mirroring R-2's SiteSnapshot deferral. Resolved by: Wave R-3. Status: CLOSED for the field foundation.

  • Feature numeric intensity thresholds. The 0–100 intensity ranges per FeatureDiscoveryState label are design intent but not committed values per the authority doc's explicit balance-pass deferral. Wave R-3 shipped the field foundation only (int DiscoveryIntensity); threshold commitments remain open. Closing this drift requires a future balance-pass wave to commit per-label intensity ranges. Status: OPEN for thresholds.

  • Feature placement formula and ownership. CLOSED by Wave R-4 (2026-05-10) for the algorithm rewrite and the host-system retirement. The additive ScoreCandidate (suitability * 2 - avoidance + noise / 2) was replaced by the multiplicative score formula authored in gd-feature-generation-contract.md "Placement Formula": score = hardGate * suitability * rarityModifier * seededNoise * spacingPenalty * storyBias. Static factors (hardGate, suitability, seededNoise, storyBias = 1.0 stub) are computed by Generated/Territories/FeaturePlacement/FeaturePlacementQuery.Evaluate; dynamic factors (rarityModifier = clamp(1 - used/budget, 0, 1), spacingPenalty = clamp(distance / minSpacing, 0, 1)) are applied by the new FeaturePlacementSelector static helper at selection time. FeatureFamily was expanded to 14 values matching the contract's family list; stub families (Water, Food, Forest, Travel, Shelter, Corruption, Nexus) carry no committed templates yet and read-model switches default-case to the Landmark / generic visual until templates land. AvoidanceWeights was folded into SuitabilityWeights as negated entries on every profile so each profile carries one self-consistent weight set; H.AvoidanceWeights was retired from the hash table and the field row was dropped from Generated/Declarations.cs. FeaturePlacementSystem was deleted and its logic moved to the static Generated/Territories/FeaturePlacement/FeaturePlacementSelector.cs, which MapGenerationSystem.Execute calls after CreateForcedFeatures so ordinary Features are placed in the Generated entry-point system, not in a Host-side ITickSystem. TerritoryFacts gained an IsWater field (1 = water, 0 = land) so the hardGate factor blocks Land-family Features from spawning on water Territories. Resolved by: Wave R-4. Status: CLOSED for the algorithm and ownership refactor.

  • Feature placement balance pass. The MinScore thresholds on each profile (130–165) were tuned for the additive formula's score distribution. Wave R-4 changed the formula scale to a fixed-point integer in [0, 1000], so the existing thresholds are now permissive rather than restrictive at the static-score gate. Profile budget values (MinPerWorld, MaxPerWorld, DensityDivisor, MinSpacingRank, etc.) are also untuned for the new formula's distribution. Closing this drift requires a future balance-pass wave to recommit threshold values against the multiplicative formula. Status: OPEN for thresholds.

  • Feature stub-family templates. Seven of the 14 Feature families expanded by Wave R-4 (Water, Food, Forest, Travel, Shelter, Corruption, Nexus) carry no committed templates today. The Nexus family is occupied semantically by DormantNexus but that template remains in the Story family pending the contract's Nexus-promotion decision; the other six families have no templates at all. Closing this drift requires future content waves to author templates per the example list in gd-feature-generation-contract.md "Feature Families". Status: OPEN.

  • FeatureSnapshot wire shape. The FeatureSnapshot projection surfaced to the React client does not yet expose the placement intensity, score, or family fields beyond what was committed before Wave R-3. Wave R-4 deliberately did not extend the wire surface (parity with R-2 / R-3 deferral). Closing this drift requires a future Server wave. Status: OPEN.

  • Planned terrain tags. 19 terrain-derived tags listed in gd-territory-generation-contract.md "Derived Classes And Tags" are not yet committed to Content/common/tags.secs. See catalogs/tag-catalog.md "Planned Tags (Not Yet Committed)" section.

  • gd-dynamic-quest-pressure-model.md doc-runtime gap. Wave Q shipped the docs-only generation contract at ../systems/gd-dynamic-quest-pressure-model.md with five binding Generator Contract Rules (causal source fact, player-actionable contract, consequence-if-ignored, consequence-if-resolved, Journal readback hook), the Feature-Transition Trigger Table, the Urgency Signal Contract, and the First Proof Slice walkthroughs. No DynamicQuestPressureGenerator C# class, no read-model field for source-fact / urgency-rank / lane-name, and no test exists in examples/valenar/Host/, examples/valenar/Server/, examples/valenar/Client/, examples/valenar/Generated/, or tests/Valenar.Host.Tests/. The contract is binding but no runtime consumes it. Resolved by: Wave QP (generator runtime) + Wave QR (read-model extensions). Status: OPEN.

  • Cross-act lane owner docs doc-runtime gap. The 7 lane owner docs under examples/valenar/docs/quest-threads/ (Core/Truth, Survival/Settlement, Pressure/Corruption, People/Retinue, Faction/Polity, Rune/Crafting/True Harm, Reclamation/Crown) exist and carry lane-scope metadata. No Quest Thread runtime object, no lane-key enum, and no lane-association field exist in any C# type under examples/valenar/Host/, examples/valenar/Server/, examples/valenar/Client/, or examples/valenar/Generated/. The authored lanes are binding for content authoring (Wave QL) but no runtime artifact references them today. Resolved by: Wave QP (generator emits lane-declared artifacts) + Wave QL (mission ladders authored per lane). Status: OPEN.

  • Interacting removal — CLOSED. The Interacting state was removed from both ../generation/gd-feature-generation-contract.md (10→9 state ladder) and ../generation/gd-territory-generation-contract.md by Wave Q. The runtime 9-state enum in examples/valenar/Generated/Territories/FeaturePlacement/FeaturePlacementTypes.cs was not changed; the doc ladder now matches the committed runtime enum. The drift note at ../systems/gd-state-axes-and-thresholds.md line 96 records the resolution. No Interacting alias, default, or transitional synonym is preserved in any live doc per the no-fallback redesign propagation rule. Resolved by: Wave Q. Status: CLOSED.

Pending Runtime Backing — Foundation Hardening

The following contract surfaces were authored as design / ADR commitments by the Foundation Hardening (Waves 2a / 2b / 3a / 3b) but have no live runtime backing today. Each row is a contract-only runtime- backing status per .claude/rules/valenar-contract-backing.md. The named owner files do NOT yet exist on disk; the next closure wave column names the Foundation Hardening wave that lands them.

Contract surfaceAuthorityPending runtime owner(s)Closure waveStatus
QuestThread scope + Mission scope + lifecycle channelsgd-quest-thread-and-mission-state-machine.md, ad-0007legacy/v1/examples/valenar/Host/Systems/QuestThreadSystem.cs (does not exist), legacy/v1/examples/valenar/Host/Systems/MissionSystem.cs (does not exist), matching Host/Data typesWave 5a (source / Generated) + Wave 6 (runtime backing)contract-only
ThreatSource scope + FrontCandidate scope + emergence state machinegd-front-emergence.md, ad-0008Host data + Host system for ThreatSource and FrontCandidate (do not exist)Wave 5a + Wave 6contract-only
Realm scope + PolityRank channel + laddergd-realm-ranks-and-polity.md, ad-0009legacy/v1/examples/valenar/Host/Data/RealmData.cs (does not exist), legacy/v1/examples/valenar/Host/Systems/RealmRankSystem.cs (does not exist)Wave 5a + Wave 6contract-only
ActState scope + ActProgressionSystemgd-act-progression.md, ad-0010legacy/v1/examples/valenar/Host/Data/ActStateData.cs (does not exist), legacy/v1/examples/valenar/Host/Systems/ActProgressionSystem.cs (does not exist)Wave 5a + Wave 6contract-only
ProvinceDefensePlan.PlanState channelgd-defense-zones.md (PlanState section), Foundation Hardening resolver R4 (2026-05-17)New PlanState channel added to existing legacy/v1/examples/valenar/Host/Data/ProvinceDefensePlanData.cs (file exists; PlanState channel does not)Wave 5a + Wave 6partial (host data file exists, channel does not)
MC Conditions / Injuries Modifier templates + apply/tend/clear Activitiesgd-character-conditions-and-injuries.md, ad-0012Modifier templates plus the apply / tend / clear Condition Activity templates (do not exist); ActivityExecutor extensionsWave 5a (Modifier + Activity templates) + Wave 6 (execution paths)contract-only
Labor and Capacity Settlement-scope and Province-scope channelsgd-labor-and-capacity.mdSettlement-scope and Province-scope Labor / Capacity channels (do not exist); channel resolution paths through HostBridgeWave 5a + Wave 6contract-only
ContactEngagement scopegd-combat-rules.md (ContactEngagement section)ContactEngagement host data + scope read/write paths through HostBridge (do not exist)Wave 5a + Wave 6contract-only
ValidationReport host typegd-generation-validation.mdValidationReport host type populated by the generation pipeline (does not exist)Wave 5a + Wave 6contract-only
storyBias placeholdergd-feature-generation-contract.md, Foundation Hardening resolver R17 (2026-05-17)FeaturePlacementQuery.cs:190 currently returns => 1.0 as a silent stub. Per R17 this becomes throw new NotImplementedException in Wave 5a, and the authored formula lands in Wave 5a / Wave 6 when source-fact dependencies resolve.Wave 5a (replace stub with NotImplementedException) + Wave 6 (author formula)stubbed (illegal silent-default fallback; closing requires the R17 sequence)