Post-1.0 maintenance directive (archived)
Archived 2026-07-06. Snapshot of the completed post-1.0 phases from
.agent-state/directive.md, migrated out of the live directive so the queue tracks only in-flight work. Every item below is[x]/DONE. The WHY-per-commit record is preserved here; the live directive now carries only the RFC-0001 milestone. See also 1.0 stabilization.
Active queue — post-merge release + maintenance
Section titled “Active queue — post-merge release + maintenance”Phase LF — library-fit decomposition (Epic LF, in PR)
Section titled “Phase LF — library-fit decomposition (Epic LF, in PR)”- LF-PR53 — ✅ PR #53 (Epic LF, branch
feat/library-fit-decomposition) merged 2026-05-28 as main commit4f442ba. All 21 commits across LF1–LF8 squashed in; Gemini review threads addressed in commit2e58f64and resolved viaaddPullRequestReviewThreadReply+resolveReviewThreadgraphql mutations; CodeRabbit hit its rate limit so no human-style review threads to reply to; CodeQLjs/incomplete-sanitizationregex meta-escape fix shipped in7cab6b9.
Phase G — release (in-flight)
Section titled “Phase G — release (in-flight)”- G8 — ✅ Release flow exercised end-to-end 2026-05-28, but the deliverable identity changed mid-flight: the original
medieval-hexagon-gameboard@1.0.0release-please PR (#6) merged + cut a GH release but release.yml failed at workflow setup on a badactions/attest-build-provenanceSHA pin (the pinned SHAe7af5b09…didn’t exist in the action’s repo —977bb373…is the real v3.0.0 SHA). That stale release + tag were deleted; the package was renamed todeclarative-hex-worlds(PR #55 / commitb0964bc), release-please then cut a freshdeclarative-hex-worlds@1.0.0release via PR #56 (commit0564ff2). The npm publish happens locally viaNPMJS_TOKEN(in.env, gitignored); release.yml is then converted to OIDC trusted publishing so subsequent releases need no token. See [[rename-to-declarative-hex-worlds]].
Phase RB — bootstrap CI integration (continuation)
Section titled “Phase RB — bootstrap CI integration (continuation)”- RB-CI — ✅ commit (2026-05-27) established the browser-free visual gate. 2026-06-25 closeout keeps
pnpm test:browser:freeas the full local visual/screenshot gate and wires required CI Coverage throughpnpm coverage:all:enforce(unit + browser-free coverage merged before threshold enforcement).
Phase E0 — coverage closure (continuation toward 100/100/100/100)
Section titled “Phase E0 — coverage closure (continuation toward 100/100/100/100)”The A8 coverage ratchet floors at 64.5 / 62.3 / 76.4 / 64 (unit harness) as of 33d271b. The final PR #210 ratchets merged coverage to 100 / 100 / 100 / 100.
- [DONE] E0a — Simulation + patrol files toward 100%. PR#10-#51 merged; no open PR remains for the old PR#52 note as of 2026-06-25. Current CI-measured merged coverage gate after browser-free integration is 76.74 / 70.87 / 84.69 / 76.48 (PR #106 Coverage); local reference-enabled runs read 78.19 / 72.18 / 86.11 / 77.94. CLI command batch PR #108 Coverage measured 78.32 / 72.80 / 85.69 / 78.06 and staged thresholds at 77.8 / 72.3 / 85.1 / 77.5. CLI shared-helper batch PR #109 Coverage measured 79.02 / 73.84 / 86.49 / 78.76 and staged thresholds at 78.3 / 73.0 / 85.6 / 78.0. CLI validation-command batch PR #110 Coverage measured 79.56 / 74.44 / 86.65 / 79.32 and staged thresholds at 78.8 / 73.5 / 85.9 / 78.5. CLI simulation-command batch PR #111 Coverage measured 80.29 / 75.00 / 86.91 / 80.04 and staged thresholds at 79.6 / 74.2 / 86.2 / 79.2. CLI layout/piece-command batch PR #112 Coverage measured 81.04 / 75.76 / 87.14 / 80.81 and staged thresholds at 80.3 / 75.1 / 86.6 / 80.2. CLI piece-registry batch PR #113 Coverage measured 82.30 / 77.02 / 88.60 / 82.08 and staged thresholds at 81.3 / 76.0 / 87.6 / 81.1. CLI summary-variant batch PR #114 Coverage measured 82.54 / 77.44 / 88.60 / 82.33 and staged thresholds at 81.8 / 76.5 / 87.9 / 81.6. CLI guide-output batch PR #115 Coverage measured 82.96 / 77.80 / 88.64 / 82.77 and staged thresholds at 82.2 / 77.0 / 88.0 / 82.0. CLI guide-render batch PR #116 Coverage measured 83.26 / 78.06 / 88.72 / 83.08 and staged thresholds at 82.5 / 77.4 / 88.1 / 82.4. CLI scenario/patrol batch PR #117 Coverage measured 83.98 / 78.47 / 89.18 / 83.82 and staged thresholds at 83.4 / 77.9 / 88.6 / 83.3. CLI declaration/piece batch PR #118 Coverage measured 84.40 / 78.82 / 89.29 / 84.24 and staged thresholds at 83.8 / 78.2 / 88.7 / 83.6. CLI readable command batch PR #119 Coverage measured 85.65 / 79.52 / 89.83 / 85.52 and staged thresholds at 84.8 / 79.1 / 89.4 / 84.8. CLI snapshot/piece batch PR #120 Coverage measured 86.17 / 80.32 / 90.02 / 86.07 and staged thresholds at 85.3 / 79.8 / 89.7 / 85.3. CLI reference generator script batch PR #121 Coverage measured 86.23 / 80.27 / 90.04 / 86.13 and staged thresholds at 85.7 / 79.8 / 89.7 / 85.7. Package-assets generator script batch PR #122 Coverage measured 86.48 / 80.44 / 90.09 / 86.38 and staged thresholds at 86.0 / 79.9 / 89.7 / 85.9. Packed consumer smoke orchestrator batch PR #123 Coverage measured 86.77 / 80.43 / 90.33 / 86.66 and staged thresholds at 86.2 / 80.0 / 90.0 / 86.2. Packed consumer types attestation batch PR #124 Coverage measured 86.81 / 80.41 / 90.38 / 86.70 and staged thresholds at 86.3 / 80.1 / 90.1 / 86.3. Packed consumer install smoke batch PR #125 Coverage measured 87.28 / 80.83 / 90.47 / 87.19 and staged thresholds at 86.7 / 80.5 / 90.2 / 86.7. Simulation engine defensive branch batch PR #126 Coverage measured 87.32 / 80.88 / 90.47 / 87.23 and stages thresholds at 86.8 / 80.6 / 90.3 / 86.8. Selectors edge-mask branch cleanup PR #127 Coverage measured 87.32 / 80.89 / 90.47 / 87.23 and stages thresholds at 86.8 / 80.7 / 90.3 / 86.8. Command handler branch batch PR #128 Coverage measured 87.37 / 80.98 / 90.47 / 87.28 and stages thresholds at 86.9 / 80.8 / 90.3 / 86.9. Ratchet against CI-measured merged coverage after each ≤200 LOC test batch; E8’s 100/100/100/100 flip is complete. NOTE: scenario.ts:1189 (spawn-group warning map) + 1204 (patrol warning map) effectively unreachable — spawn groups never emit warnings; patrol warning in patrol-route planning needs >1 waypoint + 0 segments (contradictory). Skip these arms.
- World-rules system branch batch PR #129 Coverage measured 87.37 / 81.01 / 90.47 / 87.28, reached 100 / 100 / 100 / 100 for
src/systems/world-rules-system.ts, and stages thresholds at 86.9 / 80.9 / 90.3 / 86.9. - Command-dispatch branch cleanup PR #130 Coverage measured 87.37 / 81.02 / 90.47 / 87.28, reached 100 / 100 / 100 / 100 for
src/systems/command-dispatch.ts, and stages thresholds at 86.9 / 81.0 / 90.3 / 86.9. - Systems/runtime branch cleanup PR #131 Coverage measured 87.44 / 81.27 / 90.47 / 87.36, reached 100 / 100 / 100 / 100 for
src/systems/systems.ts,src/systems/events.ts,src/systems/tick.ts,src/runtime/asset-root.ts, andsrc/runtime/runtime.ts, and staged thresholds at 87.0 / 81.1 / 90.3 / 87.0. - Simulation engine branch closure PR #132 Coverage measured 87.44 / 81.60 / 90.47 / 87.36, reached 100 / 100 / 100 / 100 for
src/simulation/engine.ts, and staged thresholds at 87.0 / 81.2 / 90.3 / 87.0. - Script-validator branch cleanup PR #133 Coverage measured 87.44 / 81.73 / 90.47 / 87.36, reached 100 / 100 / 100 / 100 for
src/simulation/script-validators.ts, and staged thresholds at 87.0 / 81.3 / 90.3 / 87.0. - Pieces branch cleanup PR #134 Coverage measured 87.44 / 81.80 / 90.47 / 87.36, reached 100 / 100 / 100 / 100 for
src/pieces/pieces.ts, and staged thresholds at 87.0 / 81.4 / 90.3 / 87.0. - Occupancy branch cleanup PR #135 Coverage measured 87.44 / 81.81 / 90.47 / 87.36, reached 100 / 100 / 100 / 100 for
src/gameboard/occupancy.ts, and staged thresholds at 87.0 / 81.5 / 90.3 / 87.0. - Manifest schema branch cleanup PR #136 Coverage measured 87.44 / 81.86 / 90.47 / 87.36, reached 100 / 100 / 100 / 100 for
src/manifest/schema.ts, and staged thresholds at 87.0 / 81.6 / 90.3 / 87.0. - Catalog treatments branch cleanup PR #137 Coverage measured 87.44 / 81.89 / 90.47 / 87.36, reached 100 / 100 / 100 / 100 for
src/scenario/catalog-treatments.ts, and staged thresholds at 87.0 / 81.7 / 90.3 / 87.0. - Catalog guide-data branch cleanup PR #138 Coverage measured 87.44 / 81.90 / 90.47 / 87.36, reached 100 / 100 / 100 / 100 for
src/scenario/catalog-guide-data.ts, and staged thresholds at 87.0 / 81.8 / 90.3 / 87.0. - CLI/source-root branch cleanup PR #139 Coverage measured 88.25 / 82.55 / 91.27 / 88.19, reached 100 / 100 / 100 / 100 for
scripts/smoke/types.ts,src/cli/commands/bootstrap/target.ts,src/cli/commands/manifest.ts,src/cli/commands/validate.ts, andsrc/guides/simple-rpg/exercises.ts; also closed branch gaps insrc/cli/commands/extract.ts. Staged thresholds at 87.0 / 81.9 / 90.3 / 87.0. - Interop compatibility branch cleanup PR #140 Coverage measured 88.26 / 82.60 / 91.27 / 88.20, reached 100 / 100 / 100 / 100 for
src/interop/compatibility.tsafter KayKit tile placement, facing defaults, spawn fallback metadata, rigged default roles, idle/first animation fallback, and removal of an unreachable rigged-non-unit warning. Staged thresholds at 87.1 / 82.0 / 90.3 / 87.1. - CLI usage branch cleanup PR #141 Coverage measured 88.29 / 82.60 / 91.31 / 88.23, reached 100 / 100 / 100 / 100 for
src/cli/usage.tsthrough direct import coverage ofHELP_TEXTandusage(). Staged thresholds at 87.2 / 82.1 / 90.4 / 87.2. - Bootstrap upstream-layout cleanup PR #142 Coverage measured 88.31 / 82.62 / 91.31 / 88.25, reached 100 / 100 / 100 / 100 for
src/cli/commands/bootstrap/upstream-layout.tsby covering the FREE-with-units rejection and removing redundant EXTRA units/nullish texture branches. Staged thresholds at 88.1 / 82.4 / 90.9 / 88.1. - CLI validate-plan exit cleanup PR #143 Coverage measured 88.37 / 82.64 / 91.42 / 88.29, reached focused 100 / 100 / 100 / 100 for
src/cli/commands/validate-plan.tsby exercising the validation-errorprocess.exit(1)path; merged report still carries a browser-map statement-id artifact for the same line. Staged thresholds at 88.2 / 82.5 / 91.0 / 88.2. - Gameboard terrain branch cleanup PR #144 Coverage measured 88.38 / 82.70 / 91.42 / 88.30, reached 100 / 100 / 100 / 100 for
src/gameboard/terrain.tsby covering plan default fallbacks, same-order placement sort, custom tile tags, river crossing overlays, single-edge river masks, and sloped road overlays while removing unreachable internal terrain branches. Staged thresholds at 88.3 / 82.6 / 91.1 / 88.2. - CLI compatibility exit cleanup PR #145 Coverage measured 88.43 / 82.78 / 91.42 / 88.35, reached 100 / 100 / 100 / 100 for
src/cli/commands/compatibility.tsby covering--failOnWarningwarning exits and fatal bounds-error exits. Staged thresholds at 88.3 / 82.7 / 91.1 / 88.3. - CLI guide API/role cleanup PR #146 Coverage measured 88.46 / 82.84 / 91.42 / 88.39, reached 100 / 100 / 100 / 100 for
src/cli/commands/guide-apis.tsandsrc/cli/commands/guide-roles.tsby covering empty selections, unfiltered API summary overflow, and removing unreachable selected-value/nullish and role truncation branches. Staged thresholds at 88.4 / 82.8 / 91.1 / 88.3. - CLI validate-recipe exit cleanup PR #147 Coverage measured 88.48 / 82.87 / 91.46 / 88.41, reached 100 / 100 / 100 / 100 for
src/cli/commands/validate-recipe.tsby covering readable recipe validation errors and the fatalprocess.exit(1)branch. Staged thresholds at 88.4 / 82.8 / 91.2 / 88.4. - Coordinates projection cleanup PR #148 Coverage measured 88.50 / 82.93 / 91.46 / 88.43, reached 100 / 100 / 100 / 100 for
src/coordinates/projection.tsby covering sloped road projection, river crossing projection, custom placement tie sorting, and removing unreachable projection defaults/helpers. Staged thresholds at 88.4 / 82.9 / 91.2 / 88.4. - Packed install smoke branch cleanup PR #149 Coverage measured 88.51 / 82.99 / 91.46 / 88.44, reached 100 / 100 / 100 / 100 for
scripts/smoke/pack-install.tsby covering invalid pack metadata, missing plan/scenario count fallbacks, non-array SimpleRPG exercise evidence, and retained temp-app logging. Staged thresholds at 88.45 / 82.93 / 91.3 / 88.41. - CLI reference generator branch cleanup PR #150 Coverage measured 88.51 / 83.07 / 91.46 / 88.44, reached 100 / 100 / 100 / 100 for
scripts/generate-cli-reference.tsby covering default generator option resolution, injected IO execution, direct-run predicate branches, and excluding only the thin executable entrypoint guard. Staged thresholds at 88.5 / 83.0 / 91.35 / 88.43. - SimpleRPG executable smoke branch cleanup PR #151 Coverage measured 88.55 / 83.11 / 91.54 / 88.47, reached 100 / 100 / 100 / 100 for
src/guides/simple-rpg/smoke.tsby covering plan tile fallback/empty-plan failure, recipe error-count helpers, layout fill rule id fallback, and the FREE manifest asset lookup without the literal-key lint warning. Staged thresholds at 88.52 / 83.05 / 91.44 / 88.44. - Package-assets generator branch cleanup PR #152 Coverage measured 88.57 / 83.19 / 91.54 / 88.50, reached 100 / 100 / 100 / 100 for
scripts/generate-package-assets.tsby covering default/injected dependency resolution, FREE/EXTRA write behavior, source-count failure, argument parsing, and the direct-run predicate while ignoring only the thin executable entrypoint guard. Staged thresholds at 88.55 / 83.14 / 91.5 / 88.46. - CLI snapshot branch cleanup PR #153 Coverage measured 88.61 / 83.21 / 91.58 / 88.53, reached 100 / 100 / 100 / 100 for
src/cli/commands/snapshot.tsby covering invalid-plan validation exits, recipe compile failure afterallowInvalid, stdout snapshot output, and plan/recipe/scenario option variants. Staged thresholds at 88.57 / 83.19 / 91.53 / 88.49. - CLI doctor/validate-manifest + scenario registry branch cleanup PR #154 Coverage measured 88.72 / 83.40 / 91.62 / 88.63, reached focused zero-miss coverage for
src/cli/commands/doctor.ts,src/cli/commands/validate-manifest.ts, andsrc/scenario/registry.tsby covering coverage delegation, existing-source/missing-montage reporting, readable empty-manifest summaries, JSON output, fatal manifest validation issue exits, z-origin geometry warnings, terrainless manifest tile inference, default declaration asset/source normalization, object declaration application, custom placement kind defaults, and support-tile registry analysis while removing private unreachable layer/median guards. Staged thresholds at 88.64 / 83.28 / 91.56 / 88.54. - CLI guide-permutations/patrol-script branch cleanup PR #155 Coverage measured 88.83 / 83.50 / 91.70 / 88.74, reached focused zero-miss coverage for
src/cli/commands/guide-permutations.tsandsrc/cli/commands/patrol-script.tsby covering manifest-backed missing permutation assets, readable missing-asset reporting, assignment-file array variants, missing-assignment validation, readable warning/error reporting, and fatal error/warning exits. Staged thresholds at 88.72 / 83.42 / 91.64 / 88.65. - Coordinates/quests branch cleanup PR #156 Coverage measured 88.89 / 83.67 / 91.70 / 88.78, reached 100 / 98.91 / 100 / 100 for
src/quests/quests.tsand closed the remaining merged misses forsrc/coordinates/coordinates.tsby covering quest metadata/lookups, reach-tile pending progress, fallback progress preservation, source-less collision evaluation, non-quest entity rejection, canonical-key path reconstruction, spawn passability, and exported heap boundary cases while removing private unreachable coordinate/quest guards. Staged thresholds at 88.78 / 83.55 / 91.64 / 88.70. - CLI command-gap cleanup PR #157 Coverage measured 88.95 / 83.74 / 91.73 / 88.83, advanced
src/cli/commandsto 85.41 / 71.20 / 86.04 / 85.85 andguide-usages.tsto 100 / 92.30 / 100 / 100 by covering readable guide summaries, edition-scope and small-result filters, missing manifest asset exits, synthetic source-root extract/declarations success, doctor source reporting, and validation/compatibility fatal exits. Staged thresholds at 88.84 / 83.62 / 91.66 / 88.76. - CLI summarize-scenario cleanup PR #158 Coverage measured 88.98 / 83.88 / 91.73 / 88.86, reached 100 / 93.10 / 100 / 100 for
src/cli/commands/summarize-scenario.tsby covering validation-error exits, allow-invalid readable summaries without a compiled board, warning-onlyfailOnWarningexits, and readable title/top-asset/patrol summary fallbacks. Staged thresholds at 88.87 / 83.76 / 91.67 / 88.79. - Spawn-group/quest branch cleanup PR #159 Coverage measured 89.02 / 83.97 / 91.80 / 88.89, reached focused zero-miss coverage for
src/gameboard/spawn-groups.tsby covering terrain/elevation/tag candidate filters, found/lower-cost/shorter/empty route selection, and removing unreachable route tie-key and warning-aggregate branches; removed the redundant quest metadata fallback after normalization and kept no-metadata quest spawn coverage. Staged thresholds at 88.90 / 83.86 / 91.74 / 88.82. - Command-handler branch cleanup PR #160 Coverage measured 89.02 / 84.11 / 91.80 / 88.89, reached focused zero-miss coverage for
src/commands/commands.tsby covering source-less/unreachable/manual move previews, completed same-tile move execution, no-effect handler normalization, empty actor-target selection, single-handler presets, stale actor/placement removals, and successful placement removal while removing post-preview unreachable movement/handler defensive branches. Staged thresholds at 88.91 / 84.00 / 91.75 / 88.84. - Coverage merge location-key cleanup PR #161 Coverage measured 89.50 / 84.06 / 93.03 / 89.42, fixes cross-harness Istanbul statement/function/branch id and column drift by merging counters by source location with unique line fallback and ignoring zero-only unmatched browser entries. Staged thresholds at 89.10 / 84.00 / 92.00 / 89.00.
- Dead built-CLI smoke cleanup PR #162 Coverage measured 91.81 / 85.47 / 94.01 / 91.81, removes stale unreferenced
scripts/smoke-built-cli.tsaftertest:cliwas deleted and rewrites current docs/commentary to the actual Vitest/coverage workflow. Staged thresholds at 91.50 / 85.30 / 93.80 / 91.50. - CLI entrypoint dispatcher PR #163 Coverage measured 92.55 / 85.85 / 95.60 / 92.57, reached 100 / 100 / 100 / 100 for
src/cli/cli.tsthrough controlled side-effect imports with mockedcitty, usage, and subcommand modules. Staged thresholds at 92.30 / 85.80 / 95.20 / 92.30. - Showcase promotion script PR #164 Coverage measured 93.07 / 85.96 / 95.88 / 93.07, reached 100 / 74 / 100 / 100 for
scripts/promote-showcases.tsby extracting injectedpromoteShowcases()/runPromoteShowcases()helpers and covering check/promote/failure/quality paths. Staged thresholds at 92.80 / 85.85 / 95.65 / 92.80. - KayKit guide extractor PR #165 Coverage measured 93.57 / 86.22 / 96.32 / 93.60, reached 100 / 78.66 / 100 / 100 for
scripts/extract-kaykit-guide.tsby extracting injected parser/runner/renderer helpers and covering Swift, portable, Windows lookup, missing-PDF, no-renderer, no-page, and command-failure paths. Staged thresholds at 93.30 / 86.10 / 96.00 / 93.30. - Spawn-groups command PR #166 Coverage measured 93.65 / 86.35 / 96.36 / 93.68 in CI (local reference-enabled proof read 94.01 / 86.68 / 96.55 / 94.03), reached 100 / 100 / 100 / 100 for
src/cli/commands/spawn-groups.tsby covering missing--groups, validation-error exits, JSON output, spawn-plan error exits, and documenting the currently unreachable aggregate-warning exit. Staged thresholds at 93.50 / 86.30 / 96.30 / 93.50. - Blueprint command PR #167 local reference-enabled proof measured 94.33 / 87.35 / 96.74 / 94.34, advanced
src/cli/commands/blueprint.tsto 98.33 / 93.47 / 90.90 / 99.14 by covering wrapped config parsing, CLI overrides, scenario/interop predicates, payload summaries, readable warnings, JSON output, warning exits, and scenario error exits; defensive output guards stay annotated becauseshouldInspectBlueprintScenarioandshouldEmitBlueprintInteropmake them unreachable through the public command flow. Staged thresholds at 93.90 / 86.90 / 96.40 / 93.90. - Guide-scenarios command PR #168 local reference-enabled proof measured 94.58 / 87.67 / 96.98 / 94.58, reached 100 / 93.10 / 100 / 100 for
src/cli/commands/guide-scenarios.tsby covering guide filters, include-treatment payloads, missing-manifest asset reporting and exits, markdown stdout, JSON file output, invalid asset-scope errors, and the missing-treatment guard with restored fixture state. Staged thresholds at 94.20 / 87.20 / 96.60 / 94.20. - CLI shared-helper PR #169 local reference-enabled proof measured 95.06 / 88.12 / 97.17 / 95.08, advanced
src/cli/_shared.tsto 87.86 / 83.16 / 94.12 by covering registry and piece-registry validation, output emission, GLTF metadata extraction, piece flag/source URL parsing, and readable helper reports. Staged thresholds at 94.60 / 87.70 / 96.80 / 94.60. - Patrol-routes command PR #170 local reference-enabled proof measured 95.15 / 88.27 / 97.21 / 95.17, advanced
src/cli/commands/patrol-routes.tsto 95.83 / 90.90 / 100 / 95.74 by covering missing routes, malformed scenarios, validation exits, spawn-group exits, JSON and file output, scenario seed fallbacks, and route-error readable output. The remaining route warning/fail-on-warning arm depends on the documented contradictory route-planning warning path. Staged thresholds at 94.70 / 87.80 / 96.85 / 94.70. - Guide-assets command PR #171 local reference-enabled proof measured 95.25 / 88.45 / 97.36 / 95.25, reached 100 / 97.67 / 100 / 100 for
src/cli/commands/guide-assets.tsby covering single-asset selected payloads, file output, readable small/overflow summaries, each empty-selection filter branch, and the no-match command error. Staged thresholds at 94.80 / 88.00 / 97.00 / 94.80. - Place-piece command PR #172 local reference-enabled proof measured 95.37 / 88.66 / 97.40 / 95.38, reached 100 / 97.29 / 100 / 100 for
src/cli/commands/place-piece.tsby covering input validation, piece-registry selection failures, JSON/file/readable output, out-plan writes, invalid-plan exits, no-placement min-count exits, and seed/id-prefix placement output. The remaining coordinate-string readable branch is defensive because generated piece placements use coordinate objects. Staged thresholds at 94.90 / 88.10 / 97.10 / 94.90. - Analyze-layout command PR #173 local reference-enabled proof measured 95.48 / 88.88 / 97.44 / 95.49, reached 100 / 100 / 100 / 100 for
src/cli/commands/analyze-layout.tsby covering input/rules validation, rule array and object parsing, file and CLI seed resolution, JSON/file/readable output, out-plan writes, invalid-plan exits, error exits, and fail-on-warning exits. Staged thresholds at 95.00 / 88.30 / 97.20 / 95.00. - Summarize-plan command PR #174 local reference-enabled proof measured 95.66 / 89.09 / 97.52 / 95.67, reached 100 / 100 / 100 / 100 for
src/cli/commands/summarize-plan.tsby covering exact-input and JSON-shape validation, recipe/scenario compile exits, plan validation exits, validation warning exits, readable none/EXTRA top-asset branches, out/outPlan writes, and blueprint/config input aliases. Staged thresholds at 95.20 / 88.60 / 97.30 / 95.20. - Simulate-scenario command PR #175 local reference-enabled proof measured 95.82 / 89.41 / 97.59 / 95.83, reached 100 / 92.42 / 100 / 100 for
src/cli/commands/simulate-scenario.tsby covering missing-input and malformed-scenario guards, scenario/script validation exits, JSON success and expectation-failure outputs, readable expectation-failure summaries, blocked-quest exits, and actor-target/mutation readable fallbacks. Staged thresholds at 95.30 / 88.90 / 97.40 / 95.30. - Piece command PR #176 local reference-enabled proof measured 95.85 / 89.54 / 97.59 / 95.86, reached 100 / 100 / 100 / 100 for
src/cli/commands/piece.tsby covering missing-asset validation, derived asset and piece ids, default source and omitted role/report branches, explicit attribution/file output, warning exits, and fatal report error exits. Staged thresholds at 95.40 / 89.00 / 97.40 / 95.40. - Pieces command PR #177 local reference-enabled proof measured 95.91 / 89.68 / 97.59 / 95.92, reached 100 / 100 / 100 / 100 for
src/cli/commands/pieces.tsby covering missing-input and conflicting placement-input validation, rule/source-url/placement payload variants, file output, registry analysis errors, registry warning exits, and placement-warning exits while marking the defensive placement-error guard unreachable because registry analysis blocks invalid selections before inspection. Staged thresholds at 95.45 / 89.10 / 97.40 / 95.45. - Bootstrap core PR #178 local reference-enabled proof measured 96.32 / 90.15 / 97.59 / 96.36, reached 100 / 100 / 100 / 100 for
src/cli/commands/bootstrap/core.tsby covering default output resolution, same-size hash drift, non-empty targets without sidecars, malformed/oversized/escaping sidecars, source-format inclusion under the GLTF root, missing texture directories, deep/corrupt zip failures, successful mocked GitHub downloads, stream cleanup, and HTTP failure fallbacks; fixed extension parsing to use the file basename and marked only defensive library/filesystem race guards unreachable through the public zip path. Staged thresholds at 95.80 / 89.70 / 97.40 / 95.80. - Validate-simulation command PR #179 local reference-enabled proof measured 96.36 / 90.25 / 97.63 / 96.39, reached 100 / 100 / 100 / 100 for
src/cli/commands/validate-simulation.tsby covering missing scenario/script guards, non-object scenario validation, JSON/readable output fallbacks with empty actor/quest lists, actor/quest JSON mapping, out-plan writes, and fatal script validation exits while simplifying redundant script-step array guards afterreadSimulationScriptvalidation. Staged thresholds at 95.90 / 89.80 / 97.40 / 95.90. - Validate-scenario command PR #180 local reference-enabled proof measured 96.39 / 90.41 / 97.71 / 96.41, reached 100 / 100 / 100 / 100 for
src/cli/commands/validate-scenario.tsby covering the missing-scenario guard, compiled-plan output, JSON/runtime actor and quest payloads, authored/empty fallback payloads when validation errors skip runtime creation, readable spawn/patrol summaries, and fatal validation exits while simplifying the unreachable runtime-plan fallback after inspection already compiles the plan. Staged thresholds at 96.00 / 89.90 / 97.40 / 96.00. - Pieces-from-assets command PR #181 local reference-enabled proof measured 96.57 / 90.74 / 97.75 / 96.60, reached 100 / 100 / 100 / 100 for
src/cli/commands/pieces-from-assets.tsby covering missing inputs, no-model scans, override payload validation, single-file and multi-root asset inputs, absolute-path/includeReport payloads, prefix/tag file output, override-warning fail-on-warning exits, registry warning/error printing, and fatal registry-error exits while pairing scanned paths with source records and relying on the scanned-root invariant for relative asset paths. Staged thresholds at 96.10 / 90.20 / 97.40 / 96.10. - Guide-render-requests command PR #182 local reference-enabled proof measured 96.64 / 90.84 / 97.79 / 96.66, reached 100 / 100 / 100 / 100 for
src/cli/commands/guide-render-requests.tsby covering empty selections, readable URL output, JSON grouped payloads, edition-scoped file output, missing manifest asset reporting, fatal missing-asset exits, and request overflow summaries. Staged thresholds at 96.20 / 90.30 / 97.40 / 96.20. - Guide-assets command PR #183 local reference-enabled proof measured 96.64 / 90.85 / 97.79 / 96.66, reached 100 / 100 / 100 / 100 for
src/cli/commands/guide-assets.tsby removing the unreachable selected-asset nullish fallback after theassetIdFilter.length === 1guard. Staged thresholds at 96.20 / 90.40 / 97.40 / 96.20. - Summarize-scenario command PR #184 local reference-enabled proof measured 96.64 / 90.88 / 97.79 / 96.66, reached 100 / 100 / 100 / 100 for
src/cli/commands/summarize-scenario.tsby covering readable EXTRA actor asset output, including the top-asset*suffix and non-empty actor extra asset list. Staged thresholds at 96.20 / 90.50 / 97.40 / 96.20. - CLI command-output PR #185 local reference-enabled proof measured 96.68 / 90.98 / 97.87 / 96.69, reached 100 / 100 / 100 / 100 for
src/cli/commands/place-piece.tsand advancedblueprint,patrol-routes, andsimulate-scenariocommand-output gaps through blueprint default-shape/error/warning/scenario-validation exits, readable actor-target and mutation output, and documented defensive display branches with no current public producer. Staged thresholds at 96.30 / 90.60 / 97.50 / 96.30. - CLI branch-artifact PR #186 local reference-enabled proof measured 96.69 / 91.08 / 97.87 / 96.70, reached 100 / 100 / 100 / 100 for
src/cli/commands/blueprint.ts,src/cli/commands/patrol-routes.ts, andsrc/cli/commands/simulate-scenario.tsby covering the empty patrol-route display, JSON simulation report file output, and reducing redundant CLI blueprint numeric flag branches. Staged thresholds at 96.30 / 90.70 / 97.50 / 96.30. - Gameboard patrol-route PR #187 local reference-enabled proof measured 96.81 / 91.19 / 97.91 / 96.81, reached 100 / 100 / 100 / 100 for
src/gameboard/patrol-routes.tsby covering explicit-start/default route diagnostics, open non-loop route warnings, route-set warning aggregation, and documenting public-path-unreachable waypoint-pair invariants. Staged thresholds at 96.40 / 90.80 / 97.50 / 96.40. - Gameboard navigation PR #188 local reference-enabled proof measured 96.92 / 91.37 / 97.95 / 96.91, reached 100 / 100 / 100 / 100 for
src/gameboard/navigation.tsby covering blocked-start/blocked-goal path branches, reachability sorting and wrapper output, movement-cost fallbacks, malformed key diagnostics, and documented heap/map invariants maintained by the exported planners. Staged thresholds at 96.50 / 91.00 / 97.60 / 96.50. - Patrol runtime PR #189 local reference-enabled proof measured 96.97 / 91.57 / 97.99 / 96.96, reached 100 / 100 / 100 / 100 for
src/patrol/patrol.tsby covering route snapshot sorting, current-waypoint fallbacks, blocked movement fallback context, resetless blocked movement requests, completed-route wrap/end states, missing-trait diagnostics, and sparse waypoint invariant errors while removing redundant post-normalization segment-cost fallback branching. Staged thresholds at 96.60 / 91.20 / 97.70 / 96.60. - Scenario branch cleanup PR #190 CI-measured merged proof measured 96.65 / 91.55 / 97.91 / 96.65, reached 100 / 95.95 / 100 / 100 for
src/scenario/scenario.tsby covering collision objective tile targets, deep clone coverage for scenario metadata/navigation/agent options, actor asset aggregation, and documenting only public-path-unreachable spawn-resolution and warning diagnostics. Staged thresholds at 96.50 / 91.40 / 97.80 / 96.50. - Movement edge cleanup local merged proof measured 97.14 / 92.00 / 98.10 / 97.14, reached 100 / 98.18 / 100 / 100 for
src/movement/movement.tsby covering stale completed paths, malformed sparse path diagnostics, newly blocked stale paths, missing board/placement state diagnostics, no-agent movement-budget fallback, and fixing movement-agent writes to add the trait when absent. Staged thresholds at 96.70 / 91.60 / 97.90 / 96.70. - Movement final branch cleanup local merged proof measured 97.14 / 92.02 / 98.10 / 97.14, reached 100 / 100 / 100 / 100 for
src/movement/movement.tsby covering the idle path-state fallback and removing the unreachable entity-side missing-placement error branch. Staged thresholds at 96.70 / 91.65 / 97.90 / 96.70. - Showcase promotion branch cleanup local merged proof measured 97.14 / 92.18 / 98.10 / 97.14, reached 100 / 100 / 100 / 100 for
scripts/promote-showcases.tsby covering default workspace/target/dependency fallbacks, promotion-mode runner success output, andErrorquality analyzer reporting. Staged thresholds at 96.70 / 91.75 / 97.90 / 96.70. - KayKit guide extractor branch cleanup local merged proof measured 97.14 / 92.36 / 98.10 / 97.14, reached 100 / 100 / 100 / 100 for
scripts/extract-kaykit-guide.tsby covering default dependency/repo-root fallbacks, process-platform command detection, non-Errorrunner failures, null Swift exit status fallback, and simplifying page-number sorting to the already-filtered filename invariant. Staged thresholds at 96.70 / 91.90 / 97.90 / 96.70. - Packed consumer smoke branch cleanup local merged proof measured 97.17 / 92.52 / 98.10 / 97.17, reached 100 / 100 / 100 / 100 for
scripts/smoke-packed-consumer.tsby covering non-Errorphase failures, default context/process/filesystem fallbacks, default runner dependency wiring on safe failure paths, and the injectable direct-run predicate while ignoring only the thin executable guard. Staged thresholds at 96.75 / 92.00 / 97.90 / 96.75. - Scenario final branch cleanup local merged proof measured 97.17 / 92.72 / 98.10 / 97.17, reached 100 / 100 / 100 / 100 for
src/scenario/scenario.tsby covering unknown-id diagnostics, omitted scenario arrays/objectives, sparse navigation clone options, unresolved-summary actor copy variants, and removing redundant claimant/spawn-index invariant fallbacks. Staged thresholds at 96.75 / 92.20 / 97.90 / 96.75. - Scenario catalog branch cleanup local merged proof measured 97.25 / 92.83 / 98.22 / 97.25, reached 100 / 100 / 100 / 100 for
src/scenario/catalog.tsby covering texture/faction/unit guards, empty edition-scope usage filters, Markdown option branches, missing-treatment usage/role-count behavior, and preserving default asset-id sort order. Staged thresholds at 96.80 / 92.30 / 98.00 / 96.80. - Ingest duplicate branch cleanup local merged proof measured 97.35 / 93.08 / 98.22 / 97.36, reached 100 / 100 / 100 / 100 for
src/ingest/ingest.tsby covering missing manifest roots, manifest JSON output, duplicate asset-id suffix allocation, sparse GLTF metadata, optional texture discovery, unsupported categories, symlink skipping, and simplifying private fallback branches to the generated-manifest invariants. Staged thresholds at 96.90 / 92.60 / 98.00 / 96.90. - script-validators.ts 100 / 100 / 100 / 100; remaining simulation-surface gaps are in assertions/patrol/report-adjacent helpers, not authored-script validators.
- engine.ts 100 / 100 / 100 / 100 — direct mutation defaults, patrol simulation route-set branch, actor-target default spreads, and unreachable koota placement-state fallbacks closed.
- assertions.ts 100 / 100 / 100 / 100 — expectation branches and actor-target matching are zero-miss in merged coverage.
- report.ts 100 / 100 / 100 / 100 — copyQuestObjective tile/targetTile branches done.
- patrol.ts 100 / 100 / 100 / 100 — route sorting, blocked fallback context, completed wrap/end transitions, and malformed entity diagnostics closed.
- layout.ts 87.13 → ratcheting; normalizeArchetypes, resolveArchetype, selectLayout count=0.
- quests.ts merged zero-miss after metadata normalization cleanup; historical objective rollover coverage remains in place.
- manifest/schema.ts 100 / 100 / 100 / 100 — unit-style exclusion plus malformed-id diagnostic fallback branches closed.
- scenario/catalog-treatments.ts 100 / 100 / 100 / 100 — source-path sort tie plus fallback neutral-structure and prop treatment branches closed.
- scenario/catalog-guide-data.ts 100 / 100 / 100 / 100 — private guide scenario input now requires authored public APIs instead of carrying an unreachable fallback.
- scenario/catalog.ts 100 / 100 / 100 / 100 — public taxonomy guards, usage filter edges, Markdown option branches, missing-treatment guards, and asset-id sort behavior closed.
- actors.ts 88.93 → register + navigationProfile action wrappers.
- pieces.ts 100 / 100 / 100 / 100 — declaration asset defaults, pooled object-archetype checks, placement count fallbacks, and compatibility override tags closed.
- scenario/scenario.ts 100 / 100 / 100 / 100 — clone/summary option branches, collision target tile validation, unknown scenario ids, optional quest objectives, allocator claimant labels, unset spawn indexes, omitted cloned navigation fields, and unresolved-summary actor copies closed.
- gameboard.ts 92.21 → addUnitPreset role variants.
- bootstrap.ts 75 → verifyBootstrap unsafe-sidecar + missing-file.
- movement.ts 100 / 100 / 100 / 100 — stale completed paths, idle fallback, sparse path diagnostics, blocked stale paths, missing board/placement state diagnostics, no-agent budget fallback, and add-if-absent agent writes covered.
- interop/compatibility.ts 100 / 100 / 100 / 100 — tile-compatible placement, facing defaults, spawn fallback metadata, rigged default roles, animation fallback chain, and unreachable rigged-non-unit warning removed.
- cli/usage.ts 100 / 100 / 100 / 100 — direct import covers
HELP_TEXT, console output, and requested exit code. - cli/commands/bootstrap/upstream-layout.ts 100 / 100 / 100 / 100 — FREE-with-units rejection covered; redundant EXTRA units and nullish texture fallback branches removed.
- cli/commands/validate-plan.ts 100 / 100 / 100 / 100 — validation-error output plus
process.exit(1)branch covered. - cli/commands/compatibility.ts 100 / 100 / 100 / 100 — warning and fatal error
process.exit(1)branches covered. - cli/commands/guide-apis.ts 100 / 100 / 100 / 100 — empty selection, selected payload, and readable overflow summary covered.
- cli/commands/guide-roles.ts 100 / 100 / 100 / 100 — empty selection and selected payload covered; fixed readable output to list all current roles instead of carrying unreachable overflow.
- cli/commands/validate-recipe.ts 100 / 100 / 100 / 100 — readable validation errors plus fatal
process.exit(1)branch covered. - coordinates/projection.ts 100 / 100 / 100 / 100 — sloped road/crossing projection, custom placement tie sort, and unreachable defaults/helpers closed.
- gameboard/terrain.ts 100 / 100 / 100 / 100 — default plan fallbacks, placement tie sort, authored tags, river crossing/single-edge river overlays, and sloped road overlays covered; unreachable internal branches removed.
- gameboard/spawn-groups.ts, gameboard/patrol-routes.ts, and gameboard/navigation.ts 100 / 100 / 100 / 100.
- ingest.ts 100 / 100 / 100 / 100 — duplicate suffix allocation, sparse GLTF metadata, texture discovery, symlink skip, missing-root errors, and manifest JSON output covered; private fallback invariants simplified.
- Browser branch-map cleanup batch local merged proof measured 97.35 / 93.16 / 98.22 / 97.36, reached merged zero-miss coverage for
src/coordinates/projection.ts,src/gameboard/terrain.ts, andsrc/simulation/engine.tsby exercising river-crossing projection/terrain and direct simulation mutation system branches in Chromium while simplifying actor-update mutation reads to use the updated entity. Staged thresholds at 96.90 / 92.70 / 98.00 / 96.90. - Gameboard/validation branch cleanup local merged proof measured 97.61 / 93.74 / 98.21 / 97.62, reached merged zero-miss coverage for
src/gameboard/gameboard.tsandsrc/rules/validation.tsby covering builder default/variant/boundary branches, invalid authored placement/connectivity validation diagnostics, EXTRA asset references, and declaration adjacency boundaries while documenting only current public-path-impossible fallback guards. Staged thresholds at 97.10 / 93.20 / 98.00 / 97.10. - Seeded rules branch cleanup local merged proof measured 97.78 / 94.10 / 98.29 / 97.80, reached merged zero-miss coverage for
src/rules/rules.tsby covering seeded board defaults/degenerate shapes, density override exclusivity, piece-fill registry errors/empty selections/object archetypes, and option-level layout archetype fills while documenting deterministic built-in shape/path invariants. Staged thresholds at 97.30 / 93.60 / 98.10 / 97.30. - Recipe branch cleanup local merged proof measured 97.84 / 94.60 / 98.40 / 97.86, reached merged zero-miss coverage for
src/scenario/recipe.tsby covering remaining serializable step dispatch and clone paths, raw malformed action diagnostics, empty/no-seed/piece-only generation, local/global archetype merges, and deep criteria footprint/distance/preference cloning while fixingsetTileAssetrecipe tag cloning. Staged thresholds at 97.40 / 94.10 / 98.20 / 97.40. - Koota branch cleanup local merged proof measured 98.00 / 94.96 / 98.52 / 98.03, reached merged zero-miss coverage for
src/koota/koota.tsby covering stale placement-index collision recovery, trait-corruption error paths, sparse occupancy relations, equal-order placement/occupancy sorting, default layer dispatch, computed placement offsets, and invalid tile-key inspection while simplifying query-required placement state reads. Staged thresholds at 97.50 / 94.50 / 98.30 / 97.50. - Blueprint branch cleanup local merged proof measured 98.19 / 95.62 / 98.52 / 98.23, reached merged zero-miss coverage for
src/scenario/blueprint.tsby covering tiny-board diagnostics, authored town/harbor/road/river fallback IDs, generated defaults, semantic prop-cluster dressing, bridge de-duplication, empty-shape ridge failures, and defensive blueprint compiler invariants. Staged thresholds at 97.70 / 95.10 / 98.30 / 97.70. - Three branch cleanup local merged proof measured 98.39 / 95.99 / 98.75 / 98.44, reached merged zero-miss coverage for
src/three/three.tsby covering asset URL defaults, animation URL overrides and clip fallbacks, transform/framing helpers, recursive user-data tagging, interaction lookup misses, stale-removal branches, no-parent sync, and sync load error collection/rethrow paths. Staged thresholds at 97.90 / 95.50 / 98.50 / 97.90. - Interop branch cleanup local merged proof measured 98.53 / 96.84 / 98.79 / 98.58, reached merged zero-miss coverage for
src/interop/interop.tsby covering base snapshot inclusion flags, spawn candidates, legacy adjacency relation fallback, missing relation target reporting, out-of-board footprint filtering, scenario inclusion flags, unresolved actor/quest relation skips, spawn/patrol planning errors, runtime snapshot inclusion flags, and simulation report fallback variants while documenting only public-path-impossible interop serialization invariants. Staged thresholds at 98.00 / 96.30 / 98.50 / 98.00. - Layout branch cleanup local merged proof measured 98.79 / 97.74 / 98.87 / 98.85, reached merged zero-miss coverage for
src/coordinates/layout.tsby covering layout archetype fallback registries, custom/radius/adjacent footprints, harbor facing inference, fill diagnostics, default layers, sparse serialized plans, and fill/spawn default seeds while documenting only public-path-impossible analyzer and slot-angle invariants. Staged thresholds at 98.30 / 97.20 / 98.60 / 98.30. - Actors branch cleanup local merged proof measured 99.15 / 98.79 / 98.99 / 99.23, reached merged zero-miss coverage for
src/actors/actors.tsby covering actor kind inference, selector/string fallbacks, collision profiles, neighborhood aggregation, interaction command edges, actor-target sorting, disconnected target paths, and documenting only public-path-impossible ECS corruption/route sentinel invariants. Staged thresholds at 98.60 / 98.30 / 98.80 / 98.70. - CLI shared-helper cleanup local merged proof measured 99.65 / 99.57 / 99.18 / 99.75, reached 100 / 100 / 100 / 100 for
src/cli/_shared.tsby covering manifest/registry validation, synthetic source manifest generation, plan reader exits, patrol route-set fallbacks, GLB metadata chunks, piece selection/source branches, and readable report edge cases while simplifying only guarded route and asset-id fallbacks. Staged thresholds at 99.30 / 99.20 / 99.00 / 99.40. - React cleanup local merged proof measured 100 / 100 / 100 / 100, reached merged zero-miss coverage for
src/react/react.tsby covering provider factories, action-hook factories, empty-world fallbacks, coordinate-object tile hooks, queued revision disposal, and browser interop spawn-location merge counters while simplifying only unreachable/internal option guards. Remaining gaps: none in merged coverage. The explicitscript.ts,script-validators.ts, bootstrap core,gameboard/gameboard.ts,rules/validation.ts,rules/rules.ts,scenario/recipe.ts,scenario/blueprint.ts,koota/koota.ts,three/three.ts,interop/interop.ts,coordinates/layout.ts,actors/actors.ts,cli/_shared.ts, andreact/react.tsgaps are closed.
- World-rules system branch batch PR #129 Coverage measured 87.37 / 81.01 / 90.47 / 87.28, reached 100 / 100 / 100 / 100 for
- [DONE] E0h — Sweep remaining src/ files to 100% (paired with E0a per-PR). PR#10 closures advanced many of these in tandem with E0a. Status post-merge:
pieces/pieces.ts100 / 100 / 100 / 100 in focused and merged unit coverage after declaration defaults, pooled-rule compatibility, placement fallback, and override-tag branch closuregameboard/occupancy.ts100 / 100 / 100 / 100 in merged coverage after explicit layout-footprint opt-out branch closurequests/quests.tsmerged zero-miss after metadata normalization cleanup; quest objective rollover + reward dispatch coverage remains in the existing slicesactors/actors.ts100 / 100 / 100 / 100 in focused and merged coverage after actor kind inference, selector/string fallbacks, collision profiles, neighborhood aggregation, interaction command edges, actor-target sorting, disconnected target paths, and defensive ECS/route invariant cleanup.scenario/scenario.ts100 / 100 / 100 / 100 in merged coverage after unknown-id diagnostics, omitted scenario arrays/objectives, sparse navigation clone options, unresolved-summary actor copy variants, and invariant fallback cleanupscenario/blueprint.ts100 / 100 / 100 / 100 in merged coverage after tiny-board diagnostics, authored fallback ids/defaults, semantic prop-cluster dressing, bridge de-duplication, and defensive compiler invariantsscenario/catalog.ts100 / 100 / 100 / 100 in merged coverage after public taxonomy guards, usage filter edges, Markdown option branches, missing-treatment guards, and asset-id sort behavioringest/ingest.ts100 / 100 / 100 / 100 in merged coverage after duplicate suffix allocation, sparse GLTF metadata, texture discovery, symlink skip, missing-root errors, and manifest JSON outputmanifest/schema.ts100 / 100 / 100 / 100 in merged coverage after manifest normalization/filter combinationsgameboard/navigation.ts100 / 100 / 100 / 100 in merged coverage after pathfinding and reachability edge branchescoordinates/layout.ts100 / 100 / 100 / 100 in merged coverage after layout archetype fallback registries, custom/radius/adjacent footprints, harbor facing inference, fill diagnostics, default layers, sparse serialized plans, and fill/spawn default seed branch coverage.three/three.ts100 / 100 / 100 / 100 in merged coverage after URL fallback, animation fallback, transform/framing helper, user-data lookup, and sync error/stale branch coverage.interop/interop.ts100 / 100 / 100 / 100 in merged coverage after snapshot option, relation fallback, scenario/runtime/simulation projection, and defensive serialization invariant coverage.cli/_shared.ts100 / 100 / 100 / 100 in merged coverage after manifest/registry validation, synthetic source manifest generation, plan reader exits, patrol route-set fallbacks, GLB metadata chunks, piece selection/source branches, and readable report edge cases.react/react.ts100 / 100 / 100 / 100 in merged coverage after provider/action hook factories, empty-world fallbacks, coordinate-object tile helpers, queued revision disposal, and browser interop spawn-location counter closure.scenario/recipe.tsmerged zero-miss after serializable step dispatch and clone branch coverage, empty/no-seed/piece-only generation coverage, local/global archetype merge coverage, malformed action diagnostics, andsetTileAssettag clone hardening.patrol/patrol.ts100 / 100 / 100 / 100 in merged coverage after route snapshot sorting, blocked context fallbacks, completed-route wrap/end states, and malformed trait diagnostics.src/cli/commands/{blueprint,summarize-plan,snapshot,spawn-groups,patrol-routes}.tsadvanced by a direct-import blueprint-derived command batch;src/cli/_shared.tsadvanced by guide-filter, authored-option, piece-source-root, and scalar-helper coverage;validate-plan,validate-recipe,validate-scenario,validate-simulation, andsummarize-scenarioadvanced by docs-fixture happy paths;simulate-scenarioandpatrol-scriptadvanced by report/output happy paths;validate-manifest,analyze-layout, andplace-pieceadvanced by docs/blueprint fixture success paths;doctorandvalidate-manifestreached focused 100 / 100 / 100 / 100 through coverage delegation, existing-source/missing-montage reporting, readable empty-manifest summaries, JSON output, and fatal manifest validation issue exits;scenario/registry.tsreached focused zero-miss coverage through z-origin geometry warnings, terrainless manifest tile inference, default declaration asset/source normalization, object declaration application, custom placement kind defaults, and support-tile registry analysis;pieces-from-assetsandpiecesadvanced by local GLTF fixture registry/rules/source URL paths;summarize-plan,patrol-routes,validate-scenario,validate-simulation, andsummarize-scenarioadvanced through recipe/scenario/blueprint input variants and JSON/output paths;guide-assets,guide-roles,guide-scenarios, andguide-usagesadvanced through filtered file output, markdown output, and readable summaries;guide-apis,guide-permutations, andguide-render-requestsadvanced through filtered file output, grouped render requests, asset-base URLs, and readable summaries;summarize-scenario,patrol-routes, andpatrol-scriptadvanced through readable summaries, assignment-file variants, and malformed payload guards;declarations,analyze,compatibility, andpieceadvanced through packaged-manifest output, readable analysis, synthetic GLTF compatibility, and piece declaration output; readable command-output variants advancedsummarize-plan,validate-plan,validate-recipe,validate-scenario,validate-simulation,spawn-groups,analyze-layout, andplace-piecethrough readable report paths;blueprint,snapshot,pieces-from-assets, andpiecesadvanced through readable blueprint/scenario inspection, plan/recipe snapshot variants, GLTF asset scans, registry analysis, rules, source URLs, and piece-fill placement output.scripts/smoke/pack-install.tsadvanced through dependency-injected packed install, CLI assertion, temp-write, and generated source coverage. The larger CLI command surface still has low-coverage command modules. Each file’s continuation work lands as one commit that adds ≤200 LOC of test code and ratchets the floor.
- [DONE] E8 — Flip coverage thresholds to 100 / 100 / 100 / 100 in
vitest.coverage.shared.ts. Final React cleanup local merged Coverage proof is 100 / 100 / 100 / 100 and the remainingreact/react.tsgap is closed.
Phase E-MergedGate — wire browser coverage into the enforced gate
Section titled “Phase E-MergedGate — wire browser coverage into the enforced gate”User decision (2026-05-28): the enforced CI gate (test:coverage:enforce) is unit-only, but it measures src/react/react.ts + src/three/three.ts which Node can never cover (292 uncov lines / 134 uncov fns dragging the gate ~1.5–4pt). Chosen fix: wire browser-free coverage into the gate (merge unit + browser-free, enforce on merged) so react/three are measured where they CAN be covered — NOT exclude them.
Closeout (2026-06-25):
- [DONE] Stale browser alias/import safety work from LF8 remains green;
tests/unit/umbrella-browser-safe.test.tsasserts zeronode:*leaks from the umbrella. - [DONE] Vitest Browser hang fixed:
publicDir: packageRootwas shadowing Vitest Browser’s client; browser-free now usespublicDir: false, serves bootstrapped GLTFs through/@fs/<repo>/models, and has an explicit@vitest/runnerdev dependency plus browser harness smoke coverage. - [DONE] Local visual gate is green:
pnpm exec tsx src/cli/cli.ts bootstrap --source github --out models;pnpm test:browser:free. - [DONE] Merged coverage gate is enforced:
scripts/merge-coverage.tsrunsnyc check-coveragewhenHEX_WORLDS_COVERAGE_ENFORCE=1;pnpm coverage:all:enforcepassed locally at 78.19 / 72.18 / 86.11 / 77.94 and.github/workflows/ci.ymlCoverage now bootstraps FREE models, installs Playwright Chromium, and enforces the merged unit+browser-free tree.
Layering decisions (2026-05-28, user-directed during link-3 investigation):
- The 1100-line root
src/index.tshand-relisted 956 named symbols that the 18 domain barrels alreadyexport *— pure duplication, not curation (tiering is enforced at package.json#exports + @internal, not the root hand-list). Root rewritten to barrel-forwarding (export * from './<domain>'). Adding a public export to a domain now needs no root edit. - There is NO server/browser split and NO
server.ts(rejected as a wrapper shim). The umbrella is browser-safe by correct layering: it exports library/runtime API only.bootstrapis a CLI-domain capability (reachable ONLY fromsrc/cli/; never from runtime/react/three) — it was wrong to re-export it from the umbrella at all. Bootstrap stays reachable via the./bootstrapsubpath for programmatic CLI-equivalent callers. manifest/upstream-layout.tswas mis-filed: its data + fs-probers are consumed ONLY by bootstrap (CLI-domain), nothing in manifest/runtime uses it. Movesrc/manifest/upstream-layout.ts→src/bootstrap/upstream-layout.ts; published subpath renamed./manifest/upstream-layout→./bootstrap/upstream-layout(pre-1.0; update docs-site 3 refs + smoke/types.ts + architecture table + biome restricted-imports + tsup entry + package.json exports). bootstrap barrel re-exports it.
Ordered sequence: The LF batch below remains the historical decomposition that unblocked browser-safe imports. Step C and Step D are complete as of 2026-06-25; the remaining coverage work is E0a/E0h/E8’s progressive 100% ratchet, not the browser/merge gate itself.
Batch — library-fit-decomposition (batch-20260528-103351)
Section titled “Batch — library-fit-decomposition (batch-20260528-103351)”Source: docs/plans/library-fit-decomposition.prq.md (sha256: 42bbb50d5a7041055a2a67438c99192629f0f2264f89871989985fdb892d6f96) Started: 2026-05-28T10:33:51Z
task-LF1 Barrel-forwarding umbrella + internal extraction (merged LF1+LF1b)
Section titled “task-LF1 Barrel-forwarding umbrella + internal extraction (merged LF1+LF1b)”- task-LF1 ✅ (commit, 2026-05-28) Rewrite src/index.ts to
export * from './<domain>'only (18 library barrels); drop bootstrap re-exports. Extract the 28 internal helpers the barrels over-export so they’re shareable-but-private:- DISCOVERY (2026-05-28): the old hand-list root was NOT pure duplication — it curated OUT 28 internal helpers the domain barrels over-export via
export *. Barrel-forwarding surfaces them; they must leave the public boundary. - Generic cross-cutting → new
src/internal/(NOT in package.json#exports): errorMessage, isNonEmptyString, isRecord (dedupe the cli/_shared.ts copy too), includesString, isHexCoordinatesInput, tryParseHexKey, plus the type-guards/const-arrays that are pure utilities. - Domain-specific internals stay in their domain file but leave the public boundary (the barrel/shim re-exports only public names; siblings import directly): report.ts internals (actorRecord/…/simulationResult), script.ts SIMULATION_* arrays + isSimulation* guards + tileKeyFromTargetInput, gameboardPlanIndex@gameboard, isTextureSet/isUnitStyle@catalog, readValidationGameboardPlanFromWorld@projection, GAMEBOARD_RELEASE_GATE_SUMMARIES + GAMEBOARD_REQUIRED_BROWSER_SCREENSHOT_ARTIFACTS@coverage, KAYKIT_ATTRIBUTION@schema.
- Mechanism: where a shim/barrel does
export *and must drop internals, either move internals tosrc/internal/(generic) or convert that shim to public-named re-exports (domain-specific). Update all importers + biome noRestrictedImports for../internal. typecheck + unit green. - CONTRACT DECISION (2026-05-28, user: “pick the BEST for the library”): umbrella = union of legitimately-public subpath symbols; genuinely-internal symbols leave ALL public surfaces. The old hand-list was a curated-subset (umbrella ⊊ subpaths) — that was WRONG for symbols with real external consumers. Classification of the post-barrel-forwarding leaks:
- Move to internal (no external consumer; only cross-file impl detail; auto-typedoc is noise):
actorRecord/placementRecord/simulationResult/actorTargetsRecordFromReport/emptyActorTargetsRecord(report↔engine) →src/simulation/internal.ts;tryParseHexKey(coordinates-internal) →src/internalor private;gameboardPlanIndex(cross-domain layout/interop/gameboard impl) →src/internal;GAMEBOARD_RELEASE_GATE_SUMMARIES(coverage-internal) +GAMEBOARD_REQUIRED_BROWSER_SCREENSHOT_ARTIFACTS(coverage→cli impl) →src/internalor interop-internal. - Keep public — real external consumers, umbrella SHOULD expose (old list wrongly omitted):
KAYKIT_ATTRIBUTION(scripts/audit-package.ts) ;readValidationGameboardPlanFromWorld(scripts/smoke/*). These were already public on their subpath; accept into umbrella, add to snapshot. - Final snapshot diff = bootstrap (13) + all genuine internals removed; + KAYKIT_ATTRIBUTION + readValidationGameboardPlanFromWorld + any other real-consumer symbols added. Delete stale auto-typedoc pages for the now-internal symbols (docs-site reference regen).
- Move to internal (no external consumer; only cross-file impl detail; auto-typedoc is noise):
- PROGRESS (2026-05-28): umbrella → barrel-forwarding DONE. src/internal/predicates.ts (5 generic) DONE. src/simulation/internal.ts (SIMULATION_* arrays + isSimulation* guards + tileKeyFromTargetInput) DONE — cycle broken by owning STEP_ACTIONS in internal.ts. simulation.ts shim curated (report records omitted) DONE. tsc green, 714/715 unit pass, ONLY public-api snapshot red.
- REMAINING 6 leaks + decisions: KEEP-PUBLIC (real consumers, accept into snapshot):
KAYKIT_ATTRIBUTION(scripts/audit-package),readValidationGameboardPlanFromWorld(scripts/smoke). MOVE-INTERNAL via per-domain shim/barrel curation (same pattern as simulation.ts):tryParseHexKey(coordinates.ts-internal, used by parseHexKey),gameboardPlanIndex(gameboard.ts, cross-domain → coordinates/interop import it; curate gameboard barrel + give cross-domain callers a path — likelysrc/internalre-home accepting type-only domain imports, OR a gameboard/internal.ts with a biome exception),GAMEBOARD_RELEASE_GATE_SUMMARIES(coverage.ts-internal),GAMEBOARD_REQUIRED_BROWSER_SCREENSHOT_ARTIFACTS(coverage.ts → cli consumes; cross-domain). Then update snapshot, delete stale typedoc pages, biome rule for any new internal import paths. typecheck + unit + coverage green → commit LF1. REORDER (2026-05-28, forward self-assessment after LF1): LF2 (config extraction) was originally first, but the work surfaced that its content — the KAYKIT_FREE_GITHUB_* constants + repo-clone patterns — is downstream of LF7’s git-clone decision (github→git changes those constants’ semantics entirely) AND lives in bootstrap files that LF4 relocates. Extracting config now would build a schema LF7 then reshapes. BEST order: LF3 → LF4 → LF7 → LF2 → LF5 → LF6 → LF8 so config captures the SETTLED constants (incl. git-clone patterns) from their final home. (Per “pick the BEST, let work surface the next step”.)
- DISCOVERY (2026-05-28): the old hand-list root was NOT pure duplication — it curated OUT 28 internal helpers the domain barrels over-export via
task-LF2 src/config JSON config domain (reordered: after LF7)
Section titled “task-LF2 src/config JSON config domain (reordered: after LF7)”- task-LF2 ✅ (commit, 2026-05-28) Created src/config/ with 3 JSON files (kaykit-source, bootstrap-paths, upstream-layouts) + typed loader (
KAYKIT_SOURCE,BOOTSTRAP_PATHS,UPSTREAM_LAYOUTS,kaykitGithubArchiveUrl). Migrated all KAYKIT_BOOTSTRAP_, KAYKIT_FREE_GITHUB_, KAYKIT_FREE_USER_AGENT, KAYKIT_*_EXTENSIONS, KAYKIT_SIDECAR_SCHEMA_VERSION, KAYKIT_MEDIEVAL_FREE/EXTRA_LAYOUT to derive from config. Public names unchanged, browser-safe (pure JSON, no node), internal (not in exports). All green.
task-LF3 Relocate upstream-layout
Section titled “task-LF3 Relocate upstream-layout”- task-LF3 ✅ (commit, 2026-05-28) Moved src/manifest/upstream-layout.ts → src/bootstrap/upstream-layout.ts (whole file; config extraction of its data deferred to reordered LF2). manifest barrel drops it; bootstrap barrel re-exports. Subpath renamed manifest/upstream-layout → bootstrap/upstream-layout (tsup+package.json+smoke+astro typedoc). 6 layout symbols left umbrella (→ ./bootstrap). Also: react/three added to umbrella (LF1 follow-up, invariant #5, commit
3461858). All green: typecheck/715 unit/build/lint.
task-LF4 Relocate bootstrap to CLI command area
Section titled “task-LF4 Relocate bootstrap to CLI command area”- task-LF4 ✅ (commit, 2026-05-28) Moved src/bootstrap/* → src/cli/commands/bootstrap/ (core/target/upstream-layout/index.ts; index now hosts the
runcommand merging the old thin wrapper). _shared imports./commands/bootstrap/core(cycle-safe). tsup + astro typedoc inputs repointed; subpath KEYS + dist paths unchanged. e2e/integration tests repointed. No top-level src/bootstrap/. All green: typecheck/715 unit/build/lint.
task-LF5 Repoint subpaths + build + lint + docs
Section titled “task-LF5 Repoint subpaths + build + lint + docs”- task-LF5 ✅ (commit, 2026-05-28) Hand-written docs repointed (architecture, errors guide, kaykit-upstream-layout guide). Auto-typedoc regenerated. Empty stale
reference/bootstrap/deleted. biome rule needed no change (bootstrap moved INTO src/cli/commands; the rule’s../bootstrapmatchers no longer apply since there’s no top-level bootstrap domain). package.json exports + tsup + scripts/smoke + astro typedoc inputs already updated in LF3+LF4. All green.
task-LF6 Proper CLI library
Section titled “task-LF6 Proper CLI library”- task-LF6 ✅ (commit, 2026-05-28) Adopted citty for command routing + lazy subcommand loading; hand-curated
./usagepreserved for--help(intercept BEFORE runMain since citty auto-help only lists subcommand names). All 35 subcommands unchanged (kept run(parsed, sourceRoot, edition) contract; citty wraps each with ctx.rawArgs → parseFlags). Lazy import per command preserves the cold-start budget. 31 cli tests pass; all green.
task-LF7 Unify bootstrap source on the zip flow (no git, no peer dep)
Section titled “task-LF7 Unify bootstrap source on the zip flow (no git, no peer dep)”- task-LF7 ✅ (commit
644862c, 2026-05-28) Unified: github source downloads the stable/archive/refs/heads/main.zipthen reusesstageFromZip(same detector handles itch.io<pack>/Assets/gltf+ github<repo>-main/addons/kaykit_.../Assets/gltf). Removed tar/gunzip/stream-pipeline +tarruntime dep +.gzext. Verified structures via download. All green. ORIGINAL: REVISED (user, 2026-05-28): isomorphic-git rejected as overkill. The GitHub archive URLhttps://github.com/KayKit-Game-Assets/KayKit-Medieval-Hexagon-Pack-1.0/archive/refs/heads/main.zipis stable and never changes. Collapse the two source modes into ONE flow: the CLI accepts a local zip path and auto-detects free/extra by expected structural alignment (via the layout detector); if no zip is given, it fetches that stable archive .zip and feeds the SAME zip-extract flow (FREE only). Remove the tarball/gunzip/tar machinery (node:zlib,node:stream/promises,tardep,kayKitFreeGithubTarballUrl’s codeload tar.gz URL → archive .zip URL). Keep the existingopenHttpsStreamredirect handling (github archive → codeload redirect) but pipe to a temp.zipfile then reusestageFromZip. Verify viatreethat a fresh download of that zip extracts to the same structure as the FREEreferences/tree; support both structures if they differ. Droptarruntime dep. Coverage for the unified path. typecheck+unit+build+lint green.
task-LF8 Browser-import-safety verification
Section titled “task-LF8 Browser-import-safety verification”- task-LF8 ✅ (commit, 2026-05-28) Static-graph guard
tests/unit/umbrella-browser-safe.test.tswalks src/index.ts transitive imports + asserts ZEROnode:*leaks (72 files visited, 0 leaks). 2026-06-25 empirical verification: browser-free React/Three visual suites load under Chromium,pnpm test:browser:freepasses with screenshot QA, andpnpm coverage:all:enforcemeasures the merged unit+browser-free tree.
Phase E9 — visual integration gate (continuation)
Section titled “Phase E9 — visual integration gate (continuation)”- E9 — ✅ Browser visual integration gate closed (2026-06-25).
tests/browser/free-visual.test.ts,simple-rpg-visual.test.ts, andfeature-gallery.spec.tsrender the Three-backed catalog/gameboard/example surfaces into Chromium and assert committed PNG artifacts undertests/browser/__screenshots__/;tests/browser/react-bindings.test.tsexercises React hooks/providers/actions in Chromium;tests/browser/browser-harness-smoke.test.tscatches Vitest Browser client regressions. Local proof:pnpm exec tsx src/cli/cli.ts bootstrap --source github --out models;pnpm test:browser:free;pnpm coverage:all:enforce.
Phase F-Site — docs-site continuation
Section titled “Phase F-Site — docs-site continuation”- F-Audit-7b-equiv — ✅ Migrated all six
docs/guides/*.mdlegacy files intodocs-site/src/content/docs/guides/with canonical-URL redirect notes pointing back. The legacydocs/guides/*.mdfiles stay (load-bearing insrc/scenario/catalog.tsat lines 1366/1515/1557/1571/1614/1653/1673) with a top-of-file canonical pointer; the docs-site versions are the human-facing canonical with Starlight frontmatter. Six files: guide-scenario-coverage, public-api, recipes-scenarios-and-simulation, release-readiness, rendering-assets-and-external-packs, runtime-integration.
Phase CR — Comprehensive Review Action Queue (2026-05-28)
Section titled “Phase CR — Comprehensive Review Action Queue (2026-05-28)”Findings from full 5-phase review (.full-review/05-final-report.md). Ordered by priority: P0 must ship before next release; P1 before next release but can batch; P2 sprint-level; P3 backlog.
P0 — Critical (must fix before next release)
Section titled “P0 — Critical (must fix before next release)”- CR-P0-1 — ✅ PR #62 (2026-05-28): main branch protection enabled via
gh apiwith required checks: lint/typecheck/build/test/Coverage/Docs Site Build/Semgrep SAST/Dependency Review. - CR-P0-2 — ✅ PR #62 (2026-05-28): Removed
release-as: "1.0.0"fromrelease-please-config.json. - CR-P0-3 — ✅ PR #62 (2026-05-28): react/three/koota/react-dom → peerDependencies (optional); @types/react → devDependencies; citty/honeycomb-grid/seedrandom/yauzl stay as runtime deps.
- CR-P0-4 — ✅ (2026-05-28) Added
src/cli/commands/bootstrap/__tests__/security.test.tswith 6 tests: (a) redirect allowlist — non-allowlisted host rejected, allowlisted host accepted (objects.githubusercontent.com → 503 proves 2nd hop ran), redirect depth >5 rejected; (b) zip-slip — raw-binary zip with../../../entry name rejected by extractZipTo; (c) zip-bomb — declared uncompressedSize > 64 MB rejected by pre-check, at-limit (=64 MB) passes pre-check but fails yauzl size-mismatch. Usesvi.mock('node:https')+ raw zip buffer construction (yazl rejects../names). All 6 pass; lint/typecheck/test green. - CR-P0-5 — ✅ PR #62 (2026-05-28):
readJson<T>→readJson(): unknown; ~25 call sites updated with explicitas Xcasts; two unvalidated plan-return paths (layoutAnalysisPlanFromArgs, summaryPlanFromArgs) now run validateGameboardPlan; null/primitive guards added to readRegistry, readPieceRegistry, pieceOverridesFromArgs. Remaining:readValidatedJsonwrapper + file-size ceiling + error-contract tests — tracked as CR-P1-partial below.
P1 — High (fix before next release, can batch)
Section titled “P1 — High (fix before next release, can batch)”- CR-P1-1 — ✅ (2026-05-29) Added 9 golden-path oracle tests (
pathfinding-oracle.test.ts) pinning correctness + visit-count ceilings. Replaced O(N)lowestScoreKey+ Set open-list infindHexPathwith binary min-heap A* (lazy deletion via g-cost mismatch). Replaced O(N)lowestCostKeyinreachableGameboardTileswith binary min-heap Dijkstra. Zero new deps. BiomenoNonNullAssertionsatisfied via explicit undefined checks. PR #65. - CR-P1-2 — ✅ (2026-05-29) Created
src/guides/simple-rpg/(types/exercises/smoke/index.ts). Moved types + catalog + smoke to production; CLI imports../guides/simple-rpg+ passesscenarioJson as GameboardScenario; test file re-exports production module + zero-arg wrapper._shared.tsno longer imports fromtests/. PR #66. - CR-P1-3 — ✅ (2026-05-28) Fixed SAFE_REF regex in config/index.ts: original
/^[a-zA-Z0-9._\-/]{1,200}$/allowed../../etc/passwd(dots+slashes in charset); replaced with/^(?!.*\.\.)(?!\.)(?!.*\/$)[a-zA-Z0-9._\-/]{1,200}$/rejecting..sequences, leading dots, trailing/. Added CWE-74 guard test in smoke.test.ts; fixed security.test.ts typecheck (3×as unknown as ReturnType<typeof request>+ headers cast). All 67 test files pass; tsc exit 0; lint clean. - CR-P1-4 — ✅ (2026-05-29) Added
WeakMap<World, Map<string, Entity>>for tile-key and placement-id inkoota.ts.findTileEntity+findPlacementEntityare now O(1).spawnGameboardPlanfills both indexes;spawnGameboardPlacementregisters;removeGameboardPlacementderegisters;clearGameboardWorldclears. 68/68 tests pass. - CR-P1-5 — ✅ (2026-05-29) Added
KNOWN_EXTRA_ASSET_IDSIIFE-computedSet<string>incatalog.ts.isKnownExtraAssetIdis now a singleSet.has()call. 68/68 tests pass. - CR-P1-6 — ✅ PR #62 (2026-05-28): dedicated
coveragejob added to ci.yml runningpnpm test:coverage:enforce; added as required status check in branch protection. - CR-P1-7 — ✅ (2026-05-28) bootstrap-nightly.yml: SHA-pinned all 4 actions, added pull_request paths trigger, hoisted HEX_WORLDS_OUT_ROOT to job env.
- CR-P1-8 — ✅ (2026-05-28) engine.ts:663-665: null-check .at(-1) result, throw GameboardRuntimeError with actor.actorId + actor.spawnGroupId.
- CR-P1-9 — ✅ (2026-05-28) release.yml: guarded npm publish with
if: github.event_name == 'release'. - CR-P1-10 — ✅ (2026-05-28) core.ts: replaced
dirname(new URL(import.meta.url).pathname)withimport.meta.dirname.
P2 — Medium (plan for next sprint)
Section titled “P2 — Medium (plan for next sprint)”- CR-P2-1 —
_shared.tsdecomposition: per-command files; extractemitOutput()helper; fixcommandHandlerMutationsto throwGameboardRuntimeErroronnever. [CQ-1, CQ-2] - CR-P2-2 — ✅ PR #69 (2026-05-29):
findGameboardPath/reachableGameboardTilesdefault-arg Map allocations routed throughgameboardPlanIndexWeakMap. - CR-P2-3 — ✅ PR #69 (2026-05-29): world.query() spreads removed (patrol.ts:227, movement.ts:421); flatMap+spread in runGameboardSystems replaced with nested for-loop push. Koota world.query() verified snapshot via .slice() — gemini live-iterator concern was a false positive.
- CR-P2-4 — ✅
gameboard.tsno longer statically importsfreeManifest;requiresExtraAssetuses catalog treatment metadata,getPlacementAssetis explicit-manifest sync, and newloadPlacementAssetlazy-loads the packaged FREE manifest via dynamic import. Added focused gameboard tests, public API snapshot update, and adist/gameboard.jsstatic import-graph guard proving the FREE manifest record chunk is not statically reachable. Also refreshed packed-consumer smoke peer fixture (koota,three@^0.184.0) and flatbaseUrlURL assertion. Verified withpnpm verify,pnpm docs-site:build, packed-consumer smoke, andnpm pack --dry-run. - CR-P2-5 — ✅
useGameboardDerivedRevision: split React selector invalidation into state/tile/placement/actor/movement/quest/patrol domains, coalesced trait events through one microtask revision bump, and added jsdom tests proving placement selectors ignore tile-only updates and coalesce repeated placement changes.pnpm verifygreen. [P-10] - CR-P2-6 — ✅
stageUpstreamSource: inlined github download path withtry/finallyfordownloadRootcleanup;stageFromZiprestructured tolet succeeded = false; try { ... succeeded = true; } finally { if (!succeeded) rmSync(...) }. - CR-P2-7 — ✅
readSidecar: addedSIDECAR_MAX_BYTES = 4 MiB+SIDECAR_MAX_FILES = 100_000constants; guards throwGameboardIoErroron oversize or overcount. - CR-P2-8 — ✅
walkFilesInternal: addedsymlinkCountref parameter; warns once on stderr when symlink encountered; passes through recursive calls. - CR-P2-9 — ✅
koota.tsno longer importsisKnownExtraAssetIdfromscenario; runtime placement spawn/update now require callers to set or preserverequiresExtraexplicitly. Added Koota regression coverage for explicit EXTRA tagging.pnpm verifygreen. [AR-1] - CR-P2-10 — ✅
ci.yml: unified pnpm/action-setup and actions/setup-node SHAs across all 4 jobs tov6.0.8/v6.4.0(docs job was on v4.2.0/v6.3.0). - CR-P2-11 — ✅
release.yml: added post-publishnpm audit signaturesverify step; wroteROLLBACK.mdrunbook covering deprecate, unpublish, patch-release, and signature failure scenarios. - CR-P2-12 — ✅
automerge.yml: branch protection now has strict required checks (lint,typecheck,build,test,Docs Site Build,Semgrep SAST,Dependency Review,Coverage), so Dependabot keepsgh pr merge --auto --squashbehind the gate while release-please auto-approval/auto-merge is removed. Release PRs are now a maintainer checkpoint for the computed version + changelog; workflow contract + deployment docs updated. Local proof:pnpm exec vitest run tests/contract/workflows-contract.test.ts --config vitest.config.ts;pnpm typecheck;pnpm lint. [CI-6] - CR-P2-13 — ✅ H-DOC-1: fixed CLI reference redundant binary mention; H-DOC-2: added package rename narrative to CHANGELOG.md 1.0.0 + created
docs-site/guides/migration.md; H-DOC-3: added JSON flag schema/error-contract subsection; M-DOC-1: addedHEX_WORLDS_OUT_ROOTdanger aside. - CR-P2-14 — ✅ Removed
it.skipat cli.test.ts:1922 (fixture key updated tofixture-castle-kitto satisfy[A-Za-z0-9_:-]+guard); tightened__proto__guard message assertion in cli-security.test.ts; fixed--piecesarg to use temp file (CLI requires path, not inline JSON). Skips at lines 219 (Phase RB) and 1426 (Phase RS) remain legitimately blocked. - CR-P2-15 — ✅
requirePlacementStatenow returnsReadonly<PlacementStateValue>(live ECS value, no copy) for internal reads;snapshotPlacementStatedoes the deep-spread and is used only at the two external-result callsites (requestGameboardMovement and movementAdvanceResult). - CR-P2-16 — ✅
tsconfig.json: removedignoreDeprecations: "6.0"; migrated allpathsvalues from bare relative (src/...) to./-prefixed relative (./src/...) and removedbaseUrl: "."— TS 6 requires explicit relative paths inpathswhenbaseUrlis absent. tsc clean, all 68 test files pass. - CR-P2-17 — ✅
tsup.config.ts: addedtreeshake: trueexplicit; documented bundle model (honeycomb-grid/seedrandom/citty/yauzl bundled as deps; koota/react/three external as peerDeps); addedtests/unit/bundle-size.test.tswith 60KB ceiling on index.js + 100KB ceiling on cli.js (skips when dist/ absent). - CR-P2-18 — ✅
release.yml: pinnednpm@11.11.0(was@latest); added@cyclonedx/cyclonedx-npm@4.2.1as pinned devDependency; switched fromnpx --yes @cyclonedx/cyclonedx-npm@latesttopnpm exec cyclonedx-npm; updated contract test assertion to match.
P3 — Backlog
Section titled “P3 — Backlog”- CR-P3-1 — ✅ Architecture decomposition:
simulation/script.ts(3,163 lines → script-types/validators/index);gameboard/gameboard.ts(2,228 lines → plan/spawn-groups/terrain);systems/systems.ts(900 lines → command/tick/events);scenario/catalog.ts(2,401 lines). Progress:simulation/script.tsis now an 11-line stable public shim overscript-types.ts(DTOs/schema/result records) andscript-validators.ts(authored-script validators/scenario index); gameboard plan contracts, builder option contracts, memoized plan index, and plan summary helpers are split intosrc/gameboard/plan.ts; gameboard asset lookup/EXTRA/prop-cluster helpers are split intosrc/gameboard/assets.ts; derived terrain/connectivity placement construction is split intosrc/gameboard/terrain.ts, leavinggameboard.tsfocused on builder/runtime construction behavior and built-in sample boards; board-aware spawn selection and spawn-group routing are split intosrc/gameboard/spawn-groups.ts; patrol waypoint and route-segment planning is split intosrc/gameboard/patrol-routes.ts, leavingnavigation.tsfocused on occupancy-backed pathfinding/reachability and public navigation re-exports; systems event contracts, event record contracts, and snapshot serializers are split intosrc/systems/events.ts; systems command dispatch contracts/helpers are split intosrc/systems/command-dispatch.ts; systems patrol/movement/quest tick orchestration is split intosrc/systems/tick.ts, leavingsystems.tsfocused on action bundles and command-plus-tick composition; scenario guide-page image/table normalization is split intosrc/scenario/catalog-guide-data.ts, and KayKit public treatment construction is split intosrc/scenario/catalog-treatments.ts, leavingcatalog.tsfocused on public constants, queries, inverse indexes, coverage summaries, and Markdown rendering without moving the public/catalogAPI surface. Local proof:pnpm typecheck; focused catalog/public API/docs contract Vitest slice. [AR-4, AR-5, AR-6] - CR-P3-2 — ✅
noRestrictedImportsenforcement gaps: added../interop/internal,../internal/predicates, trait deep paths, config JSON deep paths, and.jsmirrors for every extensionless restricted path; routed existing trait imports through../traits; added a contract test for required gaps and.jsmirror coverage. Local proof:pnpm exec vitest run tests/contract/biome-restricted-imports-contract.test.ts --config vitest.config.ts; focused actor/Koota/movement/patrol/quest/public-api Vitest slice;pnpm typecheck;pnpm lint;pnpm verify. [AR-10, BP-8] - CR-P3-3 — ✅
interop/coverage.tscohesion: documented the release-tooling vs runtime interop split in the architecture page, mirrored the distinction in thecoverage.tsmodule comment, and clarified both public API guide copies so./coverageis build/review tooling rather than runtime ECS adapter glue. Kept the existingsrc/interop/coverage.tslocation because/coverageis already a stable public surface joining interop, compatibility, manifest, scenario, and visual evidence. Local proof:pnpm exec vitest run src/interop/__tests__/coverage.test.ts tests/contract/docs-frontmatter-contract.test.ts --config vitest.config.ts;pnpm lint;pnpm typecheck;pnpm docs-site:build. [AR-7] - CR-P3-4 — ✅ Branded types: added public-api migration status tables to both docs-site canonical and legacy metadata guides, explicitly stating branded IDs are NOT yet enforced; added a docs contract pinning the caveat, tracked domains, tracked brands, and current implementation boundary. [AR-8, M-DOC-4]
- CR-P3-5 — ✅
useStableOptionsJSON.stringify: added a plain-empty-options fast-path before serialization; the React memoization test is now included in the main Vitest config and pins that fresh{}selector options do not callJSON.stringify. Local proof:pnpm exec vitest run src/react/__tests__/memoization.test.tsx --config vitest.config.ts. [P-11] - CR-P3-6 — ✅ Added
.github/workflows/benchmarks.ymlto runpnpm build+pnpm benchon main pushes, nightly schedule, manual dispatch, and benchmark-wiring PRs; uploads text benchmark output plus metadata artifacts; workflow contract now pins the benchmark workflow shape and SHA-pinned actions. [T-bench] - CR-P3-7 — ✅ Inline docs: added A* heap/heuristic commentary in
findHexPath; patrol state-machine transition diagram aboveadvancePatrolEntity; section maps for the split simulation script implementation (script-types.tsandscript-validators.tsbehind the stablescript.tsshim); anddocs/vsdocs-site/canonical ownership guidance in CONTRIBUTING.md. [L-DOC-1, L-DOC-2, M-DOC-5, L-DOC-3] - CR-P3-8 — ✅
CI_GITHUB_TOKENPAT removed from release-please auth.cd.ymlnow mints a repo-scoped GitHub App installation token via pinnedactions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1(v3.2.0), requests only the current repository, narrows App-token permissions to contents/pull-requests write, keeps the jobGITHUB_TOKENread-only, and passessteps.release-please-token.outputs.tokento release-please. Deployment docs namevars.RELEASE_PLEASE_APP_CLIENT_ID+secrets.RELEASE_PLEASE_APP_PRIVATE_KEY; workflow contract rejectssecrets.CI_GITHUB_TOKEN. [CI-9] - CR-P3-9 — ✅
GAMEBOARD_REQUIRED_BROWSER_SCREENSHOT_ARTIFACTSnow re-exports throughsrc/interop/coverage.tsand thesrc/interop/index.tsbarrel. The CLI coverage command imports it from../../interopinstead of../../interop/internal, coverage tests pin the barrel path, and the public API snapshot records the intentional release-tooling export. [L-1/Sec, AR-2] - CR-P3-10 — ✅
advancePatrolEntitysplit into explicit transition helpers for inactive, invalid-route, existing-movement, idle/wait/completed, and request-next-segment branches. Trait writes stay in the same behavior points, but the monolithic early-return ladder and mutablenextAgentflow are replaced withPatrolAdvanceTransitionobjects. Patrol edge tests, simulation patrol tests, lint, typecheck, and full verify pass locally. [CQ-7] - CR-P3-11 — ✅
hashFilenow hashes throughstream/promises.pipelineinto a hashingWritable, so verification waits for stream cleanup instead of resolving on the read streamendevent. Bootstrap core tests, lint, typecheck, and full verify pass locally. [CQ-9] - CR-P3-12 — ✅ Removed the dead
src/simulation/simulation.tsdouble-shim and moved the public simulation barrel directly intosrc/simulation/index.ts. Source docs now point atsrc/simulation/index.ts; focused simulation/public API tests, lint, typecheck, and full verify pass locally. [AR-3]