From 1ad7554762180311ccc44252666c0dc57d5fc86d Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 14 Apr 2026 05:31:34 +0100 Subject: [PATCH] housekeep --- .../.backups/index.ndjson.20260414-052851.bak | 26 ++ discussion/index.ndjson | 4 +- ...anonical-scene-cache-and-resolver-split.md | 84 ++++ ...-scene-bank-and-viewport-cache-refactor.md | 408 ------------------ ...013-scene-bank-and-viewport-cache-model.md | 227 ---------- ...0011-scene-core-types-and-bank-contract.md | 152 ------- ...PLN-0012-scene-viewport-cache-structure.md | 147 ------- ...viewport-resolver-and-rematerialization.md | 161 ------- ...derer-migration-to-scene-viewport-cache.md | 142 ------ ...PLN-0015-api-bank-integration-and-tests.md | 124 ------ ...scene-binary-payload-format-and-decoder.md | 164 ------- 11 files changed, 112 insertions(+), 1527 deletions(-) create mode 100644 discussion/.backups/index.ndjson.20260414-052851.bak create mode 100644 discussion/lessons/DSC-0025-scene-bank-and-viewport-cache-refactor/LSN-0030-canonical-scene-cache-and-resolver-split.md delete mode 100644 discussion/workflow/agendas/AGD-0025-scene-bank-and-viewport-cache-refactor.md delete mode 100644 discussion/workflow/decisions/DEC-0013-scene-bank-and-viewport-cache-model.md delete mode 100644 discussion/workflow/plans/PLN-0011-scene-core-types-and-bank-contract.md delete mode 100644 discussion/workflow/plans/PLN-0012-scene-viewport-cache-structure.md delete mode 100644 discussion/workflow/plans/PLN-0013-scene-viewport-resolver-and-rematerialization.md delete mode 100644 discussion/workflow/plans/PLN-0014-renderer-migration-to-scene-viewport-cache.md delete mode 100644 discussion/workflow/plans/PLN-0015-api-bank-integration-and-tests.md delete mode 100644 discussion/workflow/plans/PLN-0016-scene-binary-payload-format-and-decoder.md diff --git a/discussion/.backups/index.ndjson.20260414-052851.bak b/discussion/.backups/index.ndjson.20260414-052851.bak new file mode 100644 index 00000000..e80e3372 --- /dev/null +++ b/discussion/.backups/index.ndjson.20260414-052851.bak @@ -0,0 +1,26 @@ +{"type":"meta","next_id":{"DSC":26,"AGD":26,"DEC":14,"PLN":17,"LSN":31,"CLSN":1}} +{"type":"discussion","id":"DSC-0023","status":"done","ticket":"perf-full-migration-to-atomic-telemetry","title":"Agenda - [PERF] Full Migration to Atomic Telemetry","created_at":"2026-04-10","updated_at":"2026-04-10","tags":["perf","runtime","telemetry"],"agendas":[{"id":"AGD-0021","file":"workflow/agendas/AGD-0021-full-migration-to-atomic-telemetry.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"decisions":[{"id":"DEC-0008","file":"workflow/decisions/DEC-0008-full-migration-to-atomic-telemetry.md","status":"accepted","created_at":"2026-04-10","updated_at":"2026-04-10"}],"plans":[{"id":"PLN-0007","file":"workflow/plans/PLN-0007-full-migration-to-atomic-telemetry.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"lessons":[{"id":"LSN-0028","file":"lessons/DSC-0023-perf-full-migration-to-atomic-telemetry/LSN-0028-converging-to-single-atomic-telemetry-source.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]} +{"type":"discussion","id":"DSC-0020","status":"done","ticket":"jenkins-gitea-integration","title":"Jenkins Gitea Integration and Relocation","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["ci","jenkins","gitea"],"agendas":[{"id":"AGD-0018","file":"workflow/agendas/AGD-0018-jenkins-gitea-integration-and-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0003","file":"workflow/decisions/DEC-0003-jenkins-gitea-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0003","file":"workflow/plans/PLN-0003-jenkins-gitea-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0021","file":"lessons/DSC-0020-jenkins-gitea-integration/LSN-0021-jenkins-gitea-integration.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]} +{"type":"discussion","id":"DSC-0021","status":"done","ticket":"asset-entry-codec-enum-with-metadata","title":"Asset Entry Codec Enum Contract","created_at":"2026-04-09","updated_at":"2026-04-09","tags":["asset","runtime","codec","metadata"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"lessons/DSC-0021-asset-entry-codec-enum-contract/LSN-0024-string-on-the-wire-enum-in-runtime.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]} +{"type":"discussion","id":"DSC-0022","status":"done","ticket":"tile-bank-vs-glyph-bank-domain-naming","title":"Glyph Bank Domain Naming Contract","created_at":"2026-04-09","updated_at":"2026-04-10","tags":["gfx","runtime","naming","domain-model"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0025","file":"lessons/DSC-0022-glyph-bank-domain-naming/LSN-0025-rename-artifact-by-meaning-not-by-token.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]} +{"type":"discussion","id":"DSC-0001","status":"done","ticket":"legacy-runtime-learn-import","title":"Import legacy runtime learn into discussion lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["migration","tech-debt"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0001","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0001-prometeu-learn-index.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0002","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0002-historical-asset-status-first-fault-and-return-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0003","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0003-historical-audio-status-first-fault-and-return-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0004","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0004-historical-cartridge-boot-protocol-and-manifest-authority.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0005","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0005-historical-game-memcard-slots-surface-and-semantics.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0006","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0006-historical-gfx-status-first-fault-and-return-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0007","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0007-historical-retired-fault-and-input-decisions.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0008","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0008-historical-vm-core-and-assets.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0009","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0009-mental-model-asset-management.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0010","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0010-mental-model-audio.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0011","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0011-mental-model-gfx.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0012","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0012-mental-model-input.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0013","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0013-mental-model-observability-and-debugging.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0014","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0014-mental-model-portability-and-cross-platform.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0015","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0015-mental-model-save-memory-and-memcard.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0016","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0016-mental-model-status-first-and-fault-thinking.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0017","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0017-mental-model-time-and-cycles.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0018","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0018-mental-model-touch.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} +{"type":"discussion","id":"DSC-0002","status":"open","ticket":"runtime-edge-test-plan","title":"Agenda - Runtime Edge Test Plan","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0001","file":"workflow/agendas/AGD-0001-runtime-edge-test-plan.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0003","status":"open","ticket":"packed-cartridge-loader-pmc","title":"Agenda - Packed Cartridge Loader PMC","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0002","file":"workflow/agendas/AGD-0002-packed-cartridge-loader-pmc.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0004","status":"open","ticket":"system-run-cart","title":"Agenda - System Run Cart","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0003","file":"workflow/agendas/AGD-0003-system-run-cart.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0005","status":"open","ticket":"system-fault-semantics-and-control-surface","title":"Agenda - System Fault Semantics and Control Surface","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0004","file":"workflow/agendas/AGD-0004-system-fault-semantics-and-control-surface.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0006","status":"open","ticket":"vm-owned-random-service","title":"Agenda - VM-Owned Random Service","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0005","file":"workflow/agendas/AGD-0005-vm-owned-random-service.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0007","status":"open","ticket":"app-home-filesystem-surface-and-semantics","title":"Agenda - App Home Filesystem Surface and Semantics","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0006","file":"workflow/agendas/AGD-0006-app-home-filesystem-surface-and-semantics.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0008","status":"done","ticket":"perf-runtime-telemetry-hot-path","title":"Agenda - [PERF] Runtime Telemetry Hot Path","created_at":"2026-03-27","updated_at":"2026-04-10","tags":[],"agendas":[{"id":"AGD-0007","file":"workflow/agendas/AGD-0007-perf-runtime-telemetry-hot-path.md","status":"done","created_at":"2026-03-27","updated_at":"2026-04-10"}],"decisions":[{"id":"DEC-0005","file":"workflow/decisions/DEC-0005-perf-push-based-telemetry-model.md","status":"accepted","created_at":"2026-04-10","updated_at":"2026-04-10"}],"plans":[{"id":"PLN-0005","file":"workflow/plans/PLN-0005-perf-push-based-telemetry-implementation.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"lessons":[{"id":"LSN-0026","file":"lessons/DSC-0008-perf-runtime-telemetry-hot-path/LSN-0026-push-based-telemetry-model.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]} +{"type":"discussion","id":"DSC-0009","status":"open","ticket":"perf-async-background-work-lanes-for-assets-and-fs","title":"Agenda - [PERF] Async Background Work Lanes for Assets and FS","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0008","file":"workflow/agendas/AGD-0008-perf-async-background-work-lanes-for-assets-and-fs.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0010","status":"open","ticket":"perf-host-desktop-frame-pacing-and-presentation","title":"Agenda - [PERF] Host Desktop Frame Pacing and Presentation","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0009","file":"workflow/agendas/AGD-0009-perf-host-desktop-frame-pacing-and-presentation.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0011","status":"open","ticket":"perf-gfx-render-pipeline-and-dirty-regions","title":"Agenda - [PERF] GFX Render Pipeline and Dirty Regions","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0010","file":"workflow/agendas/AGD-0010-perf-gfx-render-pipeline-and-dirty-regions.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0012","status":"open","ticket":"perf-runtime-introspection-syscalls","title":"Agenda - [PERF] Runtime Introspection Syscalls","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0011","file":"workflow/agendas/AGD-0011-perf-runtime-introspection-syscalls.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0013","status":"done","ticket":"perf-host-debug-overlay-isolation","title":"Agenda - [PERF] Host Debug Overlay Isolation","created_at":"2026-03-27","updated_at":"2026-04-10","tags":[],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0027","file":"lessons/DSC-0013-perf-host-debug-overlay-isolation/LSN-0027-host-debug-overlay-isolation.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]} +{"type":"discussion","id":"DSC-0024","status":"done","ticket":"generic-memory-bank-slot-contract","title":"Agenda - Generic Memory Bank Slot Contract","created_at":"2026-04-10","updated_at":"2026-04-10","tags":["runtime","asset","memory-bank","slots","host"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0029","file":"lessons/DSC-0024-generic-memory-bank-slot-contract/LSN-0029-slot-first-bank-telemetry-belongs-in-asset-manager.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]} +{"type":"discussion","id":"DSC-0025","status":"done","ticket":"scene-bank-and-viewport-cache-refactor","title":"Scene Bank and Viewport Cache Refactor","created_at":"2026-04-11","updated_at":"2026-04-14","tags":["gfx","tilemap","runtime","render"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0030","file":"lessons/DSC-0025-scene-bank-and-viewport-cache-refactor/LSN-0030-canonical-scene-cache-and-resolver-split.md","status":"done","created_at":"2026-04-14","updated_at":"2026-04-14"}]} +{"type":"discussion","id":"DSC-0014","status":"open","ticket":"perf-vm-allocation-and-copy-pressure","title":"Agenda - [PERF] VM Allocation and Copy Pressure","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0013","file":"workflow/agendas/AGD-0013-perf-vm-allocation-and-copy-pressure.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0015","status":"open","ticket":"perf-cartridge-boot-and-program-ownership","title":"Agenda - [PERF] Cartridge Boot and Program Ownership","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0014","file":"workflow/agendas/AGD-0014-perf-cartridge-boot-and-program-ownership.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0016","status":"done","ticket":"tilemap-empty-cell-vs-tile-id-zero","title":"Tilemap Empty Cell vs Tile ID Zero","created_at":"2026-03-27","updated_at":"2026-04-09","tags":[],"agendas":[{"id":"AGD-0015","file":"workflow/agendas/AGD-0015-tilemap-empty-cell-vs-tile-id-zero.md","status":"done","created_at":"2026-03-27","updated_at":"2026-04-09"}],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0022","file":"lessons/DSC-0016-tilemap-empty-cell-semantics/LSN-0022-tilemap-empty-cell-convergence.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]} +{"type":"discussion","id":"DSC-0017","status":"done","ticket":"asset-entry-metadata-normalization-contract","title":"Asset Entry Metadata Normalization Contract","created_at":"2026-03-27","updated_at":"2026-04-09","tags":[],"agendas":[{"id":"AGD-0016","file":"workflow/agendas/AGD-0016-asset-entry-metadata-normalization-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-04-09"}],"decisions":[{"id":"DEC-0004","file":"workflow/decisions/DEC-0004-asset-entry-metadata-normalization-contract.md","status":"accepted","created_at":"2026-04-09","updated_at":"2026-04-09"}],"plans":[],"lessons":[{"id":"LSN-0023","file":"lessons/DSC-0017-asset-metadata-normalization/LSN-0023-typed-asset-metadata-helpers.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]} +{"type":"discussion","id":"DSC-0018","status":"done","ticket":"asset-load-asset-id-int-contract","title":"Asset Load Asset ID Int Contract","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["asset","runtime","abi"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0019","file":"lessons/DSC-0018-asset-load-asset-id-int-contract/LSN-0019-asset-load-id-abi-convergence.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} +{"type":"discussion","id":"DSC-0019","status":"done","ticket":"jenkinsfile-correction","title":"Jenkinsfile Correction and Relocation","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["ci","jenkins"],"agendas":[{"id":"AGD-0017","file":"workflow/agendas/AGD-0017-jenkinsfile-correction.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0002","file":"workflow/decisions/DEC-0002-jenkinsfile-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0002","file":"workflow/plans/PLN-0002-jenkinsfile-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0020","file":"lessons/DSC-0019-jenkins-ci-standardization/LSN-0020-jenkins-standard-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]} diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 681487ac..e80e3372 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,4 +1,4 @@ -{"type":"meta","next_id":{"DSC":26,"AGD":26,"DEC":14,"PLN":17,"LSN":30,"CLSN":1}} +{"type":"meta","next_id":{"DSC":26,"AGD":26,"DEC":14,"PLN":17,"LSN":31,"CLSN":1}} {"type":"discussion","id":"DSC-0023","status":"done","ticket":"perf-full-migration-to-atomic-telemetry","title":"Agenda - [PERF] Full Migration to Atomic Telemetry","created_at":"2026-04-10","updated_at":"2026-04-10","tags":["perf","runtime","telemetry"],"agendas":[{"id":"AGD-0021","file":"workflow/agendas/AGD-0021-full-migration-to-atomic-telemetry.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"decisions":[{"id":"DEC-0008","file":"workflow/decisions/DEC-0008-full-migration-to-atomic-telemetry.md","status":"accepted","created_at":"2026-04-10","updated_at":"2026-04-10"}],"plans":[{"id":"PLN-0007","file":"workflow/plans/PLN-0007-full-migration-to-atomic-telemetry.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"lessons":[{"id":"LSN-0028","file":"lessons/DSC-0023-perf-full-migration-to-atomic-telemetry/LSN-0028-converging-to-single-atomic-telemetry-source.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]} {"type":"discussion","id":"DSC-0020","status":"done","ticket":"jenkins-gitea-integration","title":"Jenkins Gitea Integration and Relocation","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["ci","jenkins","gitea"],"agendas":[{"id":"AGD-0018","file":"workflow/agendas/AGD-0018-jenkins-gitea-integration-and-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0003","file":"workflow/decisions/DEC-0003-jenkins-gitea-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0003","file":"workflow/plans/PLN-0003-jenkins-gitea-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0021","file":"lessons/DSC-0020-jenkins-gitea-integration/LSN-0021-jenkins-gitea-integration.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]} {"type":"discussion","id":"DSC-0021","status":"done","ticket":"asset-entry-codec-enum-with-metadata","title":"Asset Entry Codec Enum Contract","created_at":"2026-04-09","updated_at":"2026-04-09","tags":["asset","runtime","codec","metadata"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"lessons/DSC-0021-asset-entry-codec-enum-contract/LSN-0024-string-on-the-wire-enum-in-runtime.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]} @@ -17,7 +17,7 @@ {"type":"discussion","id":"DSC-0012","status":"open","ticket":"perf-runtime-introspection-syscalls","title":"Agenda - [PERF] Runtime Introspection Syscalls","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0011","file":"workflow/agendas/AGD-0011-perf-runtime-introspection-syscalls.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} {"type":"discussion","id":"DSC-0013","status":"done","ticket":"perf-host-debug-overlay-isolation","title":"Agenda - [PERF] Host Debug Overlay Isolation","created_at":"2026-03-27","updated_at":"2026-04-10","tags":[],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0027","file":"lessons/DSC-0013-perf-host-debug-overlay-isolation/LSN-0027-host-debug-overlay-isolation.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]} {"type":"discussion","id":"DSC-0024","status":"done","ticket":"generic-memory-bank-slot-contract","title":"Agenda - Generic Memory Bank Slot Contract","created_at":"2026-04-10","updated_at":"2026-04-10","tags":["runtime","asset","memory-bank","slots","host"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0029","file":"lessons/DSC-0024-generic-memory-bank-slot-contract/LSN-0029-slot-first-bank-telemetry-belongs-in-asset-manager.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]} -{"type":"discussion","id":"DSC-0025","status":"open","ticket":"scene-bank-and-viewport-cache-refactor","title":"Agenda - Scene Bank and Viewport Cache Refactor","created_at":"2026-04-11","updated_at":"2026-04-13","tags":["gfx","tilemap","runtime","render"],"agendas":[{"id":"AGD-0025","file":"AGD-0025-scene-bank-and-viewport-cache-refactor.md","status":"accepted","created_at":"2026-04-11","updated_at":"2026-04-13"}],"decisions":[{"id":"DEC-0013","file":"DEC-0013-scene-bank-and-viewport-cache-model.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_agenda":"AGD-0025"}],"plans":[{"id":"PLN-0011","file":"PLN-0011-scene-core-types-and-bank-contract.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_decisions":["DEC-0013"]},{"id":"PLN-0012","file":"PLN-0012-scene-viewport-cache-structure.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_decisions":["DEC-0013"]},{"id":"PLN-0013","file":"PLN-0013-scene-viewport-resolver-and-rematerialization.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_decisions":["DEC-0013"]},{"id":"PLN-0014","file":"PLN-0014-renderer-migration-to-scene-viewport-cache.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_decisions":["DEC-0013"]},{"id":"PLN-0015","file":"PLN-0015-api-bank-integration-and-tests.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_decisions":["DEC-0013"]},{"id":"PLN-0016","file":"PLN-0016-scene-binary-payload-format-and-decoder.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_decisions":["DEC-0013"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0025","status":"done","ticket":"scene-bank-and-viewport-cache-refactor","title":"Scene Bank and Viewport Cache Refactor","created_at":"2026-04-11","updated_at":"2026-04-14","tags":["gfx","tilemap","runtime","render"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0030","file":"lessons/DSC-0025-scene-bank-and-viewport-cache-refactor/LSN-0030-canonical-scene-cache-and-resolver-split.md","status":"done","created_at":"2026-04-14","updated_at":"2026-04-14"}]} {"type":"discussion","id":"DSC-0014","status":"open","ticket":"perf-vm-allocation-and-copy-pressure","title":"Agenda - [PERF] VM Allocation and Copy Pressure","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0013","file":"workflow/agendas/AGD-0013-perf-vm-allocation-and-copy-pressure.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} {"type":"discussion","id":"DSC-0015","status":"open","ticket":"perf-cartridge-boot-and-program-ownership","title":"Agenda - [PERF] Cartridge Boot and Program Ownership","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0014","file":"workflow/agendas/AGD-0014-perf-cartridge-boot-and-program-ownership.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} {"type":"discussion","id":"DSC-0016","status":"done","ticket":"tilemap-empty-cell-vs-tile-id-zero","title":"Tilemap Empty Cell vs Tile ID Zero","created_at":"2026-03-27","updated_at":"2026-04-09","tags":[],"agendas":[{"id":"AGD-0015","file":"workflow/agendas/AGD-0015-tilemap-empty-cell-vs-tile-id-zero.md","status":"done","created_at":"2026-03-27","updated_at":"2026-04-09"}],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0022","file":"lessons/DSC-0016-tilemap-empty-cell-semantics/LSN-0022-tilemap-empty-cell-convergence.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]} diff --git a/discussion/lessons/DSC-0025-scene-bank-and-viewport-cache-refactor/LSN-0030-canonical-scene-cache-and-resolver-split.md b/discussion/lessons/DSC-0025-scene-bank-and-viewport-cache-refactor/LSN-0030-canonical-scene-cache-and-resolver-split.md new file mode 100644 index 00000000..7b151e06 --- /dev/null +++ b/discussion/lessons/DSC-0025-scene-bank-and-viewport-cache-refactor/LSN-0030-canonical-scene-cache-and-resolver-split.md @@ -0,0 +1,84 @@ +--- +id: LSN-0030 +ticket: scene-bank-and-viewport-cache-refactor +title: Canonical Scene Ownership Must Stay Separate from Viewport Caching +created: 2026-04-14 +tags: [gfx, runtime, tilemap, scene, render, asset] +--- + +## Context + +This discussion started as a ringbuffer exploration for tilemap rendering, but the work converged on a broader renderer and scene-model refactor. The key pressure was not world streaming in the open-world sense; it was keeping the canonical scene model simple while still allowing efficient viewport materialization, parallax, and future renderer evolution. + +The final implementation introduced `SceneBank` as the canonical loaded scene, `SceneViewportCache` as the materialized render cache, `SceneViewportResolver` as the movement and rematerialization policy owner, and a versioned binary `SCENE` asset payload. + +## Key Decisions + +### Canonical Scene Data Must Not Inherit Viewport Mechanics + +**What:** +`SceneBank` owns the canonical scene as four `SceneLayer`s, each with its own `TileMap`. Viewport concerns such as ringbuffer movement, cache origin, hysteresis, and copy offsets do not live in the canonical scene types. + +**Why:** +Once camera motion, parallax, and cache refresh strategy leak into the source-of-truth model, physics, tooling, serialization, and renderer evolution all start depending on transient viewport state. Keeping the scene canonical and static preserves simpler reasoning across the runtime. + +**Trade-offs:** +This creates more explicit layers in the architecture: canonical scene, cache, and resolver. The model is cleaner, but integration requires a little more plumbing. + +### Ringbuffer Is Safer Inside the Cache Than Inside the Scene + +**What:** +The ringbuffer is an implementation detail of `SceneViewportCache`, with one internal ringbuffer per layer. + +**Why:** +The cache is the right place to optimize for partial refresh, wraparound, and parallax movement. The scene itself should remain plain, indexable, and serialization-friendly. + +**Trade-offs:** +The renderer must consume cache materialization rather than reading the canonical scene directly. That is an extra step, but it avoids contaminating the domain model with cyclical storage concerns. + +### Resolver Owns Movement Policy, Not the Renderer + +**What:** +`SceneViewportResolver` owns the master anchor, per-layer anchors, clamp, hysteresis, drift handling, and the copy instrumentation needed by the renderer. + +**Why:** +If the renderer starts owning anchor advancement or rematerialization policy, world composition and camera policy become entangled. The resolver keeps that logic centralized and testable. + +**Trade-offs:** +The renderer becomes dependent on `ResolverUpdate`, but in return it stays focused on composition instead of movement semantics. + +### Binary Scene Assets Need a Versioned Contract Early + +**What:** +`SCENE` assets now use a versioned binary payload with fixed four-layer layout, per-layer metadata, and packed tile records. The decoder validates version, layer count, tile size, tile count, and decoded size. + +**Why:** +JSON payloads were convenient as a temporary unblocker but were fundamentally the wrong runtime contract for scene assets. A binary format is smaller, deterministic, and easier to validate. + +**Trade-offs:** +Authoring and tooling need to respect a stricter binary format, but the runtime contract becomes more stable and future-ready. + +## Patterns and Algorithms + +- Split world rendering into three responsibilities: + canonical scene ownership; + viewport cache storage; + movement and refresh policy. +- Keep camera input in pixel space, but advance anchors in tile space. +- Use hysteresis to prevent refresh thrash at tile boundaries. +- Prefer cache-backed renderer inputs over direct canonical map reads once materialization exists. +- Put binary asset validation close to decode and fail loudly on malformed payloads. + +## Pitfalls + +- Starting from a ringbuffer optimization can accidentally turn into a scene-model redesign if the boundaries are not made explicit. +- Letting the renderer read `SceneBank` directly after introducing `SceneViewportCache` leaves the codebase in a fragile dual-model state. +- Storing anchor-like state in `SceneLayer` would mix canonical scene data with transient viewport state. +- Treating binary scene format as “to be decided later” blocks load and preload integration much longer than necessary. + +## Takeaways + +- Canonical scene ownership, viewport caching, and viewport movement policy should be separate runtime concerns. +- Ringbuffer is valuable as an internal cache mechanism, not as the canonical world model. +- Hysteresis belongs in the resolver when cache refresh must avoid boundary flicker and churn. +- Scene asset formats should become binary and versioned before they become widely depended on. diff --git a/discussion/workflow/agendas/AGD-0025-scene-bank-and-viewport-cache-refactor.md b/discussion/workflow/agendas/AGD-0025-scene-bank-and-viewport-cache-refactor.md deleted file mode 100644 index 94c47791..00000000 --- a/discussion/workflow/agendas/AGD-0025-scene-bank-and-viewport-cache-refactor.md +++ /dev/null @@ -1,408 +0,0 @@ ---- -id: AGD-0025 -ticket: scene-bank-and-viewport-cache-refactor -title: Agenda - Scene Bank and Viewport Cache Refactor -status: open -created: 2026-04-11 -resolved: -decision: -tags: [gfx, tilemap, runtime, render] ---- - -# Agenda - Scene Bank and Viewport Cache Refactor - -## Contexto - -Hoje o runtime mistura diretamente: - -- o mapa canonico da layer; -- o estado de scroll; -- e o consumo direto pelo renderer. - -Na implementacao atual, os `64x64` das `ScrollableTileLayer` criadas em `Gfx::new()` sao o proprio mapa residente da layer que o renderer consulta diretamente. Nao existe hoje separacao explicita entre: - -- fonte canonica do mundo carregado; -- layer canonica da scene; -- view/cache materializada para render. - -Ao longo desta discussao, o foco deixou de ser ringbuffer como tema principal. A convergencia real passou a ser um refactor do sistema de tilemap para separar melhor: - -- modelo canonico do mundo; -- viewport materializada; -- camera; -- composicao incremental no `back`. - -Tambem ficou claro que: - -- `Tile` nao carrega RGB; ele referencia glyph/palette/flags e continua relativamente leve; -- por isso, manter o tilemap canonico inteiro em memoria e defensavel no baseline atual; -- o ganho mais promissor parece estar em reduzir recomposicao bruta, nao em residentizar parcialmente o mundo logo de inicio. - -## Problema - -Ainda nao esta definido como reorganizar o sistema de tilemap para: - -- manter um modelo canonico simples e previsivel; -- materializar apenas o necessario para render; -- permitir camera desacoplada do tilemap; -- evitar full redraw bruto sempre que a camera ou o mundo se movem; -- preparar o renderer para compor a world a partir de cache de viewport. - -## Pontos Criticos - -1. O `SceneBank` precisa ser a fonte da verdade. - Gameplay, fisica e futuras extensoes nao devem depender do cache de viewport. - -2. O `SceneViewportCache` precisa ser operacional, nao semantico. - Ele existe para render, nao para redefinir o contrato do mundo. - -3. O refactor pode quebrar o shape atual. - Nao ha necessidade de preservar `ScrollableTileLayer` nem compatibilidade com a modelagem existente. - -4. A camera deve ficar desacoplada. - O bank nao deve conhecer detalhes de camera; um componente intermediario resolve camera -> viewport -> cache. - -5. O custo principal a atacar continua sendo composicao. - A materializacao do cache precisa conversar com uma estrategia de redraw menos destrutiva no `back`. - -## Opcoes - -### Opcao A - Manter o modelo atual e otimizar o renderer em volta - -- **Abordagem:** preservar `TileLayer`/`ScrollableTileLayer` como hoje e atacar apenas dirtying, blit e composicao no `back`. -- **Pros:** menor refactor estrutural. -- **Contras:** mantem o acoplamento entre mapa, scroll e renderer; pior base para evolucao arquitetural. - -### Opcao B - Refatorar para `SceneBank` + `SceneViewportCache` - -- **Abordagem:** separar modelo canonico da scene e cache materializado de viewport, com camera desacoplada e algoritmo proprio de rematerializacao. -- **Pros:** arquitetura mais clara; melhor separacao de responsabilidades; base melhor para dirtying e composicao incremental. -- **Contras:** refactor maior; exige redefinir tipos e fluxo do renderer. - -## Sugestao / Recomendacao - -A recomendacao atual e seguir com a **Opcao B**. - -O refactor deve: - -1. manter o mundo canonico inteiro no `SceneBank`; -2. substituir o consumo direto de layer/mapa por um `SceneViewportCache`; -3. desacoplar camera do modelo canonico; -4. preparar o renderer para compor a world a partir de cache materializado; -5. preservar sprites, HUD e fades como sistemas separados da invalidacao do cache de viewport. - -## Direcao Atual Consolidada - -Fica aceito, a menos de revisao explicita posterior, que: - -- o runtime podera carregar ate **16** entradas em `BankType::TILEMAP`; -- cada entrada carregada representa um **`SceneBank`**; -- cada `SceneBank` contem as **4 layers** da scene; -- `background` e `parallax` passam a ser tratados dentro das proprias `SceneLayer`s, nao como tipo separado desta V1; -- cada `SceneLayer` porta seu proprio `TileMap`; -- cada `TileMap` e um conjunto de `Tile`; -- o renderer nao deve consumir o `SceneBank` diretamente; -- o renderer deve consumir um **`SceneViewportCache`** derivado do `SceneBank`; -- `ScrollableTileLayer` **morre** nesta arquitetura; -- nao ha obrigacao de compatibilidade com o shape atual. - -## Modelo Alvo de V1 - -### Hierarquia conceitual - -- `Scene` (`BankType::SCENE`) - - agregado canonico carregado - - contem as `SceneLayer`s da scene - -- `SceneLayer` - - layer canonica da scene - - contem metadados da layer e seu `TileMap` - - pode representar layer normal, background ou parallax pela sua configuracao - -- `TileMap` - - grade de tiles de uma layer - -- `Tile` - - unidade basica de conteudo por celula - -- `SceneViewportCache` - - cache/view materializada para render - - derivada da `Scene` - - contem ringbuffers internos, um por layer - -### Papel de cada tipo - -- `Scene` - - fonte da verdade - - usado por gameplay, fisica e materializacao - -- `SceneViewportCache` - - usado pelo renderer - - sabe scroll fino em pixels - - nao e fonte da verdade do mundo - - e a fonte imediata de copia para o blit - -- `SceneLayer` - - passa a carregar tambem metadados de movimento relativos ao totem mestre - - isso permite compor layers normais e parallax sob o mesmo contrato base - -### O que um tile do cache pode guardar - -V1 deve partir de cache leve. Alem do `Tile` cru, ele pode guardar alguns dados derivados para acelerar raster: - -- `glyph_id` pronto para consulta; -- `palette_id` pronto para uso; -- flags de flip compactadas; -- marca rapida de `active/empty`; -- referencia do glyph bank ja resolvida por layer; -- metadados de dirty local do proprio cache. - -V1 nao deve: - -- guardar pixels RGB resolvidos por tile; -- duplicar desnecessariamente fisica no cache de render; -- virar um mini-framebuffer por tile. - -### Movimento por layer - -Fica aceito que cada `SceneLayer` pode carregar um fator de movimento relativo ao totem mestre. - -Leitura: - -- existe um **totem mestre** resolvido pelo sistema de camera/viewport; -- cada layer resolve seu proprio deslocamento efetivo a partir desse totem mestre; -- layers com fator `1.0` acompanham o mundo principal; -- layers com fator diferente de `1.0` permitem efeito de parallax; -- isso mantem `background` e `parallax` dentro do mesmo modelo estrutural de `SceneLayer`. - -## Camera e Resolver - -Fica aceito que: - -- a camera existe em **pixel space**; -- a `Scene` nao conhece camera; -- um componente externo faz a ligacao entre camera e cache materializado; -- esse componente calcula viewport logica, totem mestre, drift, clamp e rematerializacao. - -Nome conceitual provisório: - -- `SceneViewportResolver` -- ou equivalente com a mesma responsabilidade. - -Direcao aceita para o `SceneViewportResolver`: - -- ele e responsavel pelos totens: - - totem mestre - - totens derivados por layer -- ele recebe posicao de camera de uma entidade externa; -- internamente, a posicao da camera e tratada como insumo para o totem mestre; -- ele clampa o totem mestre; -- ele decide se o cache precisa ou nao ser atualizado; -- se necessario, ele dispara atualizacao do `SceneViewportCache`; -- ele tambem deve saber instrumentalizar requests de copia por layer a partir da posicao da camera e do estado do cache; -- ele **nao executa a copia** no `back`, apenas informa o que deve ser copiado e de onde. - -## Viewport, Halo e Tamanho da Janela - -Dados atuais do runtime: - -- resolucao interna: **320x180** -- world layers: **16x16** -- HUD: **8x8** - -Para world `16x16` em `320x180`, a viewport raster minima atual equivale a: - -- **21x12 tiles** - -Direcao aceita para V1: - -- o `SceneViewportCache` materializa mais do que a viewport raster minima; -- o tamanho alvo de V1 passa a ser **25x16 tiles**; -- isso da folga suficiente para velocidades agressivas de camera sem inflar demais o cache; -- `64x64` deixa de ser tamanho alvo e passa a ser apenas referencia historica do modelo atual. - -Ordem de grandeza de memoria para `25x16`: - -- `400 tiles` -- usando `36 bytes/tile` como estimativa conservadora com margem, o cache fica em ~`14.1 KiB` - -## Algoritmo de Totem, Drift e Histerese - -### Modelo aceito - -- existe um totem mestre em `tile space`: `(i, j)` -- existe uma camera em `pixel space`: `(x, y)` -- com tile `16x16`, o centro do totem mestre em pixels e: - - `cx = 16 * i + 8` - - `cy = 16 * j + 8` -- o drift por eixo e: - - `dx = x - cx` - - `dy = y - cy` - -### Histerese aceita para V1 - -Fica aceito como baseline: - -- `safe = 12 px` -- `trigger = 20 px` - -Interpretacao: - -- dentro de `[-12, +12]`, nada acontece; -- entre `12` e `20`, existe tolerancia sem rematerializacao; -- ao ultrapassar `20`, o totem anda em tiles e o cache rematerializa as faixas necessarias. - -### Regra por eixo - -Horizontal: - -- se `dx > +20`, o totem anda `+1` tile em `x` -- se `dx < -20`, o totem anda `-1` tile em `x` - -Vertical: - -- se `dy > +20`, o totem anda `+1` tile em `y` -- se `dy < -20`, o totem anda `-1` tile em `y` - -Depois de cada movimento: - -- recalcula-se o centro do totem; -- recalcula-se o drift; -- se ainda houver excesso, o processo repete. - -### Motivo da histerese - -Histerese fica cravada na agenda como tecnica explicita para evitar flick/thrash de borda. - -Ela existe para: - -- evitar vai-e-volta quando camera/player oscilam perto do limite; -- manter o `SceneViewportCache` estavel; -- disparar rematerializacao por eventos discretos, nao por ruido de borda. - -### Politica de atualizacao do cache - -Fica aceito que: - -- a atualizacao normal do cache ocorre por **linha/coluna**; -- se houver trigger simultaneo em `x` e `y`, o algoritmo deve permitir atualizacao por **area/regiao** para evitar carregar tiles ja presentes; -- troca de `Scene` invalida o `SceneViewportCache` completamente; -- scroll/camera nao devem invalidar a janela inteira como regra normal. - -### `SceneViewportCache` e ringbuffer - -Leitura atual da agenda: - -- **sim, o `SceneViewportCache` deve preferencialmente usar ringbuffer internamente**; -- **nao** deve virar contrato semantico do mundo nem da `Scene`; -- a principal vantagem aparece justamente no padrao aceito de atualizacao por linha/coluna e por area nos cantos; -- com layers de parallax, esse beneficio aumenta, porque cada layer pode materializar sua propria janela efetiva a partir do totem mestre sem precisar copiar janelas inteiras sempre. - -Direcao aceita: - -- `SceneViewportCache` usa armazenamento em anel internamente como implementacao preferida; -- existe **um ringbuffer por layer**; -- isso fica encapsulado dentro do cache; -- `Scene`, `SceneLayer` e `TileMap` continuam semanticamente simples; -- o renderer deve consumir o cache como view materializada, nao como estrutura ciclica exposta. -- na primeira leva, o blit/composite no `back` ainda pode continuar destrutivo; -- o ganho esperado do ringbuffer fica principalmente em evitar copias internas repetidas do proprio cache antes do blit final. - -### Clamp de borda - -Direcao atual: - -- o totem e um valor de referencia em `x/y`; -- o clamp inicial pode ser pensado como: - - minimos em torno de `w/2` e `h/2` - - maximos em torno de `layer_size - (w/2, h/2)` -- nos cantos, camera e cache nao precisam coincidir de forma simetrica; -- o cache pode ficar clampado ao limite do `SceneBank`. - -## Composicao no Back - -Fica aceito que: - -- `HUD` continua sempre por cima; -- `sprites` podem aparecer entre layers; -- a ordem observavel de composicao continua sendo algo como: - - `layer 0` - - `sprites relevantes` - - `layer 1` - - `sprites relevantes` - - `layer 2` - - `sprites relevantes` - - `layer 3` - - `sprites relevantes` - - `HUD` - -Leitura atual: - -- ainda pode haver redraw completo da ordem de composicao observavel; -- o ganho principal esperado vem de parar de resolver o tilemap bruto toda vez e passar a compor a partir do `SceneViewportCache`; -- `sprites`, `HUD` e `fades` ficam separados da politica de invalidacao do cache de viewport. - -Invariantes aceitos: - -1. `SceneViewportCache` nao e fonte da verdade de dados, mas e a fonte imediata de copia para o blit; -2. `sprites`, `HUD` e `fades` nao entram no cache; -3. a ordem observavel continua: - - `layer 0` - - sprites intermediarios - - `layer 1` - - sprites intermediarios - - `layer 2` - - sprites intermediarios - - `layer 3` - - sprites intermediarios - - `HUD` - -## Open Questions Prioritarias - -### 1. Shape do `SceneBank` - -- **Direcao aceita:** o agregado canonico passa a se chamar **`Scene`**, com `BankType::SCENE`. -- **Direcao revisada:** `background` e `parallax` entram no mesmo contrato de `SceneLayer`, diferenciados por seus metadados e fator de movimento relativo ao totem mestre. -- **Direcao aceita:** a `Scene` deve expor leitura/escrita por tile **e** operacoes por regiao/faixa. - -### 2. Shape do `SceneViewportCache` - -- **Direcao aceita:** o cache e um unico agregado por scene, contendo as 4 layers internamente. -- **Direcao aceita:** entram na V1 campos derivados leves para acelerar raster, incluindo `glyph_id`, `palette_id`, flags de flip, marca de `active/empty` e referencia rapida de bank por layer. -- **Direcao aceita:** o cache usara ringbuffer internamente desde a V1 como implementacao preferida, com um ringbuffer por layer. - -### 3. Resolver camera -> cache - -- **Direcao aceita:** drift, trigger, clamp e posicao do totem moram no resolver. -- **Direcao aceita:** o resolver trabalha com um totem mestre e deriva deslocamentos efetivos por layer quando houver fator de movimento diferente. -- **Direcao aceita:** o cache permanece focado em armazenar a materializacao para render. - -### 4. Composicao incremental - -- **Leitura aceita desta agenda:** neste momento nao ha seguranca para assumir algo mais sofisticado do que composicao destrutiva total da ordem observavel no `back`. -- **Direcao atual:** o ganho esperado continua vindo de deixar de resolver o tilemap bruto toda vez, mesmo que a composicao no `back` continue destrutiva. - -### 5. Camera - -- **Direcao aceita:** camera completa fica fora desta decisao. -- **Direcao aceita:** esta decisao trabalha apenas com uma API que tenta mover o totem; o contrato completo de camera sera discutido separadamente. - -## Criterio para Encerrar - -Esta agenda pode ser encerrada quando houver alinhamento explicito sobre: - -- shape minimo de `Scene`, `SceneLayer`, `TileMap`, `Tile`, `SceneViewportCache` e `SceneViewportResolver`; -- contrato do resolver camera -> viewport cache; -- politica de rematerializacao por faixa/regiao; -- relacao entre `SceneViewportCache` e composicao no `back`; -- invariantes que devem aparecer na decisao posterior para renderer, camera e scene loading. - -## Estado Atual da Agenda - -Leitura consolidada desta agenda neste momento: - -- a direcao arquitetural principal ja esta aceita; -- o tema deixou de ser ringbuffer generico e virou refactor do sistema de tilemap/render para `Scene` + `SceneViewportCache`; -- `background` e `parallax` passam a ser absorvidos pelo proprio contrato de `SceneLayer`, via fator de movimento relativo ao totem mestre; -- `ScrollableTileLayer` deixa de existir na arquitetura alvo; -- a decisao seguinte deve cristalizar tipos, responsabilidades e invariantes, em vez de reabrir o debate macro. diff --git a/discussion/workflow/decisions/DEC-0013-scene-bank-and-viewport-cache-model.md b/discussion/workflow/decisions/DEC-0013-scene-bank-and-viewport-cache-model.md deleted file mode 100644 index 57e30201..00000000 --- a/discussion/workflow/decisions/DEC-0013-scene-bank-and-viewport-cache-model.md +++ /dev/null @@ -1,227 +0,0 @@ ---- -id: DEC-0013 -ticket: scene-bank-and-viewport-cache-refactor -title: Decision - Scene Bank and Viewport Cache Model -status: accepted -created: 2026-04-13 -accepted: 2026-04-13 -agenda: AGD-0025 -plans: [PLN-0011, PLN-0012, PLN-0013, PLN-0014, PLN-0015] -tags: [gfx, tilemap, runtime, render] ---- - -## Status - -Accepted. - -This decision normatively locks the V1 model for scene-backed tilemap rendering around: - -- `Scene` as canonical loaded state; -- `SceneLayer` as the canonical layer unit; -- `SceneViewportCache` as the materialized render cache; -- `SceneViewportResolver` as the owner of totems, drift, hysteresis, clamp, and cache update decisions. - -## Contexto - -The current runtime couples three concerns too tightly: - -- canonical layer data; -- scroll state; -- direct renderer consumption. - -In the current implementation, the `64x64` maps created for scrollable layers are not an independent viewport cache. They are the actual layer maps consumed directly by the renderer. That shape makes it harder to: - -- keep canonical world state simple; -- materialize only the viewport-relevant subset for render; -- evolve camera separately from the tilemap model; -- reduce repeated tilemap resolution work before the final destructive blit into `back`. - -During agenda `AGD-0025`, the discussion initially explored ringbuffer as a general topic, but converged on a different architectural target: a clean split between canonical scene state and render-oriented viewport materialization. - -## Decisao - -The runtime SHALL adopt the following V1 model: - -1. Canonical loaded tilemap state SHALL be represented by `Scene`. -2. A `Scene` SHALL contain four canonical `SceneLayer`s. -3. Each `SceneLayer` SHALL own its canonical `TileMap`. -4. Each `TileMap` SHALL remain the canonical grid of `Tile`s for that layer. -5. The renderer MUST NOT consume canonical `Scene` data directly for normal world composition. -6. The renderer SHALL consume a `SceneViewportCache` derived from `Scene`. -7. `SceneViewportCache` SHALL be operational render state only and MUST NOT become the semantic source of truth for gameplay or physics. -8. `SceneViewportCache` SHOULD use internal ringbuffer storage as the preferred V1 implementation strategy. -9. Ringbuffer details MUST remain encapsulated inside `SceneViewportCache` and MUST NOT leak into the semantic contract of `Scene`, `SceneLayer`, `TileMap`, or `Tile`. -10. `ScrollableTileLayer` SHALL be removed from the architecture and MUST NOT be preserved as a canonical runtime concept. -11. `background` and `parallax` SHALL remain expressible through `SceneLayer` itself, not through a separate V1 background type. -12. Each `SceneLayer` SHALL carry a relative movement factor against a master totem, allowing normal layers, background-like layers, and parallax-like layers under the same layer contract. - -## Rationale - -This decision prefers architectural clarity over preserving the current type graph. - -The key arguments are: - -- `Tile` remains light enough that keeping canonical tilemaps resident is acceptable in the current baseline. -- The more pressing cost appears to be repeated world resolution and composition work, not merely the existence of tilemap data in memory. -- A dedicated viewport cache gives the renderer a better contract without forcing gameplay and physics to depend on residency mechanics. -- Internal ringbuffering in the cache is useful because the first expected gain is avoiding repeated cache-side copies, even if final composition into `back` remains destructive in V1. -- Keeping parallax inside `SceneLayer` avoids prematurely splitting the scene model into separate layer families while still allowing differentiated movement behavior. - -This model also keeps room for later refinement: - -- richer camera semantics can evolve separately; -- background-specific types can still be introduced later if the layer contract becomes insufficient; -- bank-type wiring can still be finalized during planning/implementation; -- cache implementation can improve while the canonical scene contract remains stable. - -## Invariantes / Contrato - -### 1. Canonical Scene Model - -- `Scene` SHALL be the canonical loaded aggregate. -- `Scene` SHALL contain four canonical `SceneLayer`s. -- `SceneLayer` SHALL be the canonical replacement for the old `TileLayer`. -- `SceneLayer` SHALL minimally include: - - `glyph_bank_id` - - `tile_size` - - `active` - - `totem_factor (x, y)` - - `tilemap` -- `TileMap` SHALL remain a canonical grid of `Tile`. -- `Tile` SHALL remain lightweight and MUST NOT be expanded into resolved RGB pixel payload for canonical storage. - -### 2. Viewport Cache Model - -- `SceneViewportCache` SHALL be a single cache aggregate for one `Scene`. -- It SHALL contain four internal layer caches, one per canonical scene layer. -- The preferred V1 implementation is one internal ringbuffer per layer cache. -- Ringbuffer details MUST stay internal to the cache implementation. -- `SceneViewportCache` MAY store lightweight derived fields to accelerate raster, including: - - resolved `glyph_id` - - resolved `palette_id` - - packed flip flags - - `active/empty` markers - - fast layer-local glyph bank references -- `SceneViewportCache` MUST NOT duplicate full physics state unless a later decision explicitly requires it. -- `SceneViewportCache` SHALL be the immediate source of copy data for world blits, but MUST NOT become the source of truth for world semantics. - -### 3. Resolver Contract - -- `SceneViewportResolver` SHALL own: - - master totem - - per-layer derived totems - - drift calculation - - hysteresis - - clamp logic - - cache update decisions -- An external caller SHALL provide camera position to the resolver. -- The resolver SHALL treat that camera position as input for the master totem flow. -- The resolver SHALL decide whether cache updates are needed. -- The resolver SHALL trigger cache update operations when needed. -- The resolver SHALL know how to instrument per-layer copy requests from the cache to the final compositor. -- The resolver MUST NOT perform the actual framebuffer copy itself. - -### 4. Viewport Size and Cache Update Policy - -- V1 world viewport cache size SHALL be materially larger than the minimum visible world tile window and MUST include explicit halo for cache stability. -- An initial working target in the order of `25x16` tiles is accepted as planning guidance, but exact numeric sizing MAY be finalized in the implementation plan. -- Normal cache update SHALL occur by line and/or column. -- When simultaneous X and Y movement requires corner refresh, the cache MUST support area/region refresh to avoid reloading tiles already present. -- Swapping to a different `Scene` SHALL fully invalidate `SceneViewportCache`. -- Normal camera motion MUST NOT invalidate the whole viewport cache as the default path. - -### 5. Totem, Drift, and Hysteresis - -- The resolver SHALL use a master totem in tile space. -- Camera input SHALL remain in pixel space. -- For `16x16` tiles, the master totem center SHALL be computed as: - - `cx = 16 * i + 8` - - `cy = 16 * j + 8` -- Drift SHALL be computed as: - - `dx = x - cx` - - `dy = y - cy` -- V1 SHALL use hysteresis with: - - an internal safe band where no cache movement occurs; - - an external trigger band that advances the totem and requests cache refresh. -- Initial working values in the order of `safe = 12 px` and `trigger = 20 px` are accepted as planning guidance, but exact numeric tuning MAY be finalized in the implementation plan. -- Inside the safe band, no cache movement SHALL occur. -- Between safe and trigger, the system SHALL tolerate drift without rematerialization. -- Beyond trigger, the resolver SHALL move the totem discretely in tile steps and request cache refresh. -- Hysteresis is mandatory in V1 to prevent edge flick/thrash. - -### 6. Clamp Behavior - -- The resolver SHALL clamp the master totem against scene bounds. -- Initial clamp reasoning SHALL be based on minimums around `(w/2, h/2)` and maximums around `layer_size - (w/2, h/2)`. -- Near bounds, the cache MAY remain asymmetrically aligned relative to camera expectations. -- That asymmetry at scene edges SHALL be considered expected behavior, not an error. - -### 7. Composition Contract - -- `HUD` SHALL remain above world composition. -- `sprites` MAY appear between canonical world layers. -- The observable composition order SHALL remain: - - `layer 0` - - intermediate sprites - - `layer 1` - - intermediate sprites - - `layer 2` - - intermediate sprites - - `layer 3` - - intermediate sprites - - `HUD` -- `sprites`, `HUD`, and `fades` MUST remain outside the invalidation contract of `SceneViewportCache`. -- V1 MAY still use destructive full composition ordering in `back`. -- The expected win in V1 comes from avoiding repeated brute-force canonical tilemap resolution before that final destructive composition. - -## Impactos - -This decision impacts the runtime model directly: - -- `TileLayer` will be replaced by `SceneLayer`. -- `ScrollableTileLayer` will be removed. -- bank integration and naming at the asset-bank enum level SHALL be aligned during planning/implementation. -- The renderer contract will shift from direct map consumption to cache consumption. -- Scene loading, viewport cache maintenance, and composition responsibilities become explicitly separated. - -Expected propagation areas: - -- bank/domain model types; -- tilemap/layer runtime structures; -- renderer world composition flow; -- camera-to-render adapter logic; -- future plan/implementation artifacts derived from this decision. - -## Referencias - -- Agenda: [AGD-0025-scene-bank-and-viewport-cache-refactor.md](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/discussion/workflow/agendas/AGD-0025-scene-bank-and-viewport-cache-refactor.md) -- Current tile/layer model: - - [tile_layer.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/tile_layer.rs:1) - - [tile.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/tile.rs:1) - - [glyph.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/glyph.rs:1) -- Current renderer usage: - - [gfx.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/gfx.rs:291) - - [gfx.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/gfx.rs:594) - - [gfx.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/gfx.rs:673) - -## Propagacao Necessaria - -The following work MUST derive from this decision: - -1. Introduce the new canonical runtime types: - - `Scene` - - `SceneLayer` - - `SceneViewportCache` - - `SceneViewportResolver` -2. Remove or retire `ScrollableTileLayer`. -3. Migrate renderer world composition to consume `SceneViewportCache`. -4. Define the concrete cache update API for: - - line - - column - - area/region -5. Define the concrete blit instrumentation API emitted by the resolver. -6. Write an implementation plan before code changes. - -## Revision Log - -- 2026-04-13: Initial accepted decision from AGD-0025. diff --git a/discussion/workflow/plans/PLN-0011-scene-core-types-and-bank-contract.md b/discussion/workflow/plans/PLN-0011-scene-core-types-and-bank-contract.md deleted file mode 100644 index 37db1712..00000000 --- a/discussion/workflow/plans/PLN-0011-scene-core-types-and-bank-contract.md +++ /dev/null @@ -1,152 +0,0 @@ ---- -id: PLN-0011 -ticket: scene-bank-and-viewport-cache-refactor -title: Plan - Scene Core Types and Bank Contract -status: accepted -created: 2026-04-13 -completed: -tags: [gfx, tilemap, runtime, render] ---- - -## Objective - -Introduce the canonical type model required by `DEC-0013`: `SceneBank`, `SceneLayer`, `TileMap`, and `Tile`, plus the asset-bank/domain contract changes needed to carry scene-backed tilemap data as the new source of truth. - -## Background - -`DEC-0013` locks the canonical runtime model around `SceneBank` and `SceneLayer`, replacing the old `TileLayer`/`ScrollableTileLayer` coupling. This plan isolates the domain-model and bank-contract refactor before cache or renderer migration begins. - -## Scope - -### Included -- Introduce `SceneBank` and `SceneLayer` in the HAL/runtime model. -- Preserve `TileMap` and `Tile` as canonical grid/unit concepts. -- Define the minimum `SceneLayer` fields required by the decision. -- Update bank/domain enums and payload contracts so scenes can exist as first-class banked content. -- Add compile-time migration shims only when strictly needed to keep the tree buildable during the refactor. - -### Excluded -- `SceneViewportCache` -- `SceneViewportResolver` -- renderer migration to cache consumption -- rematerialization algorithm -- final composition changes -- final binary `SCENE` payload format and decoder implementation - -## Execution Steps - -### Step 1 - Introduce canonical scene types in HAL - -**What:** -Add `SceneBank` and `SceneLayer` to the HAL model and define the minimum canonical fields required by the decision. - -**How:** -- Replace or retire the old `TileLayer`-centric model in [tile_layer.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/tile_layer.rs). -- Keep `TileMap` as the canonical grid owner and `Tile` as the canonical cell unit. -- Define `SceneLayer` with: - - `glyph_bank_id` - - `tile_size` - - `active` - - `motion_factor` - - `tilemap` -- Define `SceneBank` as the aggregate of exactly four `SceneLayer`s using a fixed array. - -**File(s):** -- [crates/console/prometeu-hal/src/tile_layer.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/tile_layer.rs) -- [crates/console/prometeu-hal/src/tile.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/tile.rs) -- [crates/console/prometeu-hal/src/glyph.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/glyph.rs) -- HAL module export files as needed - -### Step 2 - Remove `ScrollableTileLayer` from the canonical model - -**What:** -Delete the canonical role of `ScrollableTileLayer` and any direct ownership path that makes scroll part of the canonical scene representation. - -**How:** -- Remove `ScrollableTileLayer` and `HudTileLayer` from the HAL tile-layer model or reduce them to non-canonical transitional wrappers only if needed to keep compilation moving during the refactor. -- Ensure canonical scene state no longer encodes direct renderer scroll ownership. - -**File(s):** -- [crates/console/prometeu-hal/src/tile_layer.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/tile_layer.rs) -- [crates/console/prometeu-hal/src/gfx_bridge.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/gfx_bridge.rs) - -### Step 3 - Introduce the bank/domain contract for scene-backed content - -**What:** -Add or revise the asset-bank/domain model so the canonical loaded scene can be represented in the bank contract. - -**How:** -- Update `BankType` and related asset/bank metadata in HAL to support `Scene`-backed content at the domain level. -- Adjust slot/reference types where necessary so scene content can be addressed consistently with existing banks. -- Keep the exact asset-bank enum wiring minimal and domain-first; do not conflate it with renderer cache details. - -**File(s):** -- [crates/console/prometeu-hal/src/asset.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/asset.rs) -- [crates/console/prometeu-hal/src/syscalls/domains/bank.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/syscalls/domains/bank.rs) -- [crates/console/prometeu-hal/src/syscalls/domains/asset.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/syscalls/domains/asset.rs) -- Any bank-facing shared types used by runtime and drivers - -### Step 4 - Thread the new scene types through driver-facing runtime structures - -**What:** -Prepare the driver layer to reference canonical `SceneBank` types instead of old layer/map ownership. - -**How:** -- Identify the driver-side structs currently owning the old layer model. -- Replace those type references with the new canonical scene types without yet switching renderer logic to the viewport cache. -- Keep this step focused on compile-safe type replacement, not behavior changes. - -**File(s):** -- [crates/console/prometeu-drivers/src/gfx.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/gfx.rs) -- [crates/console/prometeu-drivers/src/hardware.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/hardware.rs) - -### Step 5 - Add baseline tests for the canonical scene model - -**What:** -Protect the new canonical scene types with focused tests before cache and renderer work begins. - -**How:** -- Add unit tests for: - - scene-bank construction - - layer ownership of tilemaps - - tile write/read behavior - - preservation of `motion_factor` -- Keep tests domain-focused and independent of viewport caching. - -**File(s):** -- HAL tests colocated with scene/tile modules -- Driver tests only if required to preserve build integrity - -## Test Requirements - -### Unit Tests -- `SceneBank` owns exactly four canonical `SceneLayer`s. -- `SceneLayer` exposes the required minimal fields. -- `TileMap` indexing and mutation still behave canonically. -- `motion_factor` survives construction and mutation paths. - -### Integration Tests -- Asset/bank domain types accept the new scene-backed contract without breaking existing glyph/sound usage. -- `SCENE` binary decode remains intentionally open and out of scope for this plan. - -### Manual Verification -- Build the console crates and verify no canonical runtime path still treats `ScrollableTileLayer` as the source of truth. - -## Acceptance Criteria - -- [ ] `SceneBank` and `SceneLayer` exist as canonical runtime types. -- [ ] `ScrollableTileLayer` is no longer the canonical scene model. -- [ ] Bank/domain types can represent scene-backed content. -- [ ] Driver-facing runtime structures compile against the new canonical scene model. -- [ ] Baseline tests protect the new type graph. - -## Dependencies - -- Source decision: `DEC-0013` -- No dependency on later plans; this is the foundation for the rest of the family. - -## Risks - -- Breaking too many public or cross-crate type references at once can stall compilation. -- Bank enum changes can ripple into syscalls and telemetry if not scoped carefully. -- Transitional wrappers can accidentally survive longer than intended if not explicitly retired in later plans. diff --git a/discussion/workflow/plans/PLN-0012-scene-viewport-cache-structure.md b/discussion/workflow/plans/PLN-0012-scene-viewport-cache-structure.md deleted file mode 100644 index 3a02b899..00000000 --- a/discussion/workflow/plans/PLN-0012-scene-viewport-cache-structure.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -id: PLN-0012 -ticket: scene-bank-and-viewport-cache-refactor -title: Plan - Scene Viewport Cache Structure -status: accepted -created: 2026-04-13 -completed: -tags: [gfx, tilemap, runtime, render] ---- - -## Objective - -Implement the `SceneViewportCache` as the operational render cache for one `SceneBank`, including one internal ringbuffer per layer and lightweight derived cache entries for raster acceleration. - -## Background - -`DEC-0013` locks `SceneViewportCache` as the renderer-facing view of scene data and prefers internal ringbuffer storage per layer. `PLN-0011` already established the canonical source as `SceneBank` with exactly four `SceneLayer`s in a fixed array and moved per-layer movement metadata to `motion_factor`. This plan isolates the cache data structure and update API before resolver and renderer integration. - -## Scope - -### Included -- Define `SceneViewportCache`. -- Define the per-layer internal ringbuffer structure. -- Define the cached tile entry format. -- Define cache update APIs for line, column, and area/region. -- Define full invalidation on scene swap. - -### Excluded -- camera logic -- drift/hysteresis logic -- final renderer migration -- execution of blits into `back` - -## Execution Steps - -### Step 1 - Define cache entry and layer-cache structures - -**What:** -Create the internal data model for one viewport cache layer and for cached tile entries. - -**How:** -- Introduce a cache tile entry type that stores: - - resolved `glyph_id` - - resolved `palette_id` - - packed flip flags - - `active/empty` - - fast layer-local glyph bank reference/index -- Introduce one ringbuffer-backed layer-cache structure per scene layer. -- Keep ringbuffer internals encapsulated and out of public semantic APIs. - -**File(s):** -- New HAL or driver-side viewport-cache module(s), likely under: - - `crates/console/prometeu-hal/src/` - - and/or `crates/console/prometeu-drivers/src/` - -### Step 2 - Define `SceneViewportCache` as a four-layer aggregate - -**What:** -Create the top-level cache aggregate for one `SceneBank`. - -**How:** -- Represent one cache aggregate containing four internal layer caches aligned to `SceneBank.layers`. -- Thread through cache dimensions and tile-size assumptions for V1. -- Make the cache explicitly scene-derived and non-canonical. - -**File(s):** -- New cache module(s) -- Any related exports in HAL/driver public surfaces - -### Step 3 - Implement cache mutation APIs - -**What:** -Define the update surface that later plans will use for rematerialization. - -**How:** -- Add explicit APIs for: - - refresh line - - refresh column - - refresh area/region - - invalidate whole cache on scene swap -- Ensure corner refresh can use region updates without duplicate work on already-present tiles. - -**File(s):** -- New cache module(s) -- Any helper modules shared with resolver integration - -### Step 4 - Implement scene-to-cache materialization helpers - -**What:** -Add helpers that copy canonical scene data into cache entries. - -**How:** -- Build helpers that read canonical `SceneBank` / `SceneLayer` / `TileMap` data and populate cache entries. -- Keep the helpers unaware of camera policy; they should only perform requested materialization work. -- Ensure per-layer movement factors remain metadata of the scene layer, not cache-only state. - -**File(s):** -- New cache/materialization helper module(s) - -### Step 5 - Add focused tests for cache structure and update rules - -**What:** -Protect the cache shape and update operations before wiring the resolver. - -**How:** -- Add tests for: - - ringbuffer wrap behavior - - line refresh - - column refresh - - region refresh - - scene-swap invalidation - - no duplicate reload for corner-style region updates - -**File(s):** -- Tests colocated with cache modules - -## Test Requirements - -### Unit Tests -- Each cache layer maintains ringbuffer invariants under wrap. -- Cache entry fields match the expected derived values from canonical scene tiles. -- Line/column/region refresh APIs only rewrite the requested area. - -### Integration Tests -- Materialization from `SceneBank` into `SceneViewportCache` succeeds across all four layers. - -### Manual Verification -- Inspect debug output or temporary probes to confirm cache updates do not expose ringbuffer details outside the cache boundary. - -## Acceptance Criteria - -- [ ] `SceneViewportCache` exists as a four-layer aggregate. -- [ ] Each layer cache uses internal ringbuffer storage. -- [ ] Cache entries store the lightweight derived raster fields defined by the decision. -- [ ] Explicit APIs exist for line, column, area/region, and full invalidation. -- [ ] Tests cover wrap and non-duplicative corner updates. - -## Dependencies - -- Depends on `PLN-0011` for canonical `SceneBank` / `SceneLayer` / `TileMap` types and the fixed four-layer shape. -- Source decision: `DEC-0013` - -## Risks - -- Over-designing cache entry shape can accidentally turn the cache into a second heavy scene representation. -- Ringbuffer implementation bugs can stay hidden until resolver integration if tests are too weak. -- Region refresh semantics can become ambiguous if API boundaries are not explicit early. diff --git a/discussion/workflow/plans/PLN-0013-scene-viewport-resolver-and-rematerialization.md b/discussion/workflow/plans/PLN-0013-scene-viewport-resolver-and-rematerialization.md deleted file mode 100644 index 2ce22921..00000000 --- a/discussion/workflow/plans/PLN-0013-scene-viewport-resolver-and-rematerialization.md +++ /dev/null @@ -1,161 +0,0 @@ ---- -id: PLN-0013 -ticket: scene-bank-and-viewport-cache-refactor -title: Plan - Scene Viewport Resolver and Rematerialization -status: accepted -created: 2026-04-13 -completed: -tags: [gfx, tilemap, runtime, render] ---- - -## Objective - -Implement `SceneViewportResolver` as the owner of master anchor, per-layer anchors, drift, hysteresis, clamp, cache update decisions, and per-layer copy instrumentation metadata. - -## Background - -`DEC-0013` makes the resolver the owner of movement policy between camera input and viewport cache updates. `PLN-0011` already fixed the canonical source as `SceneBank` and renamed per-layer movement metadata to `motion_factor`. This plan isolates the decision logic before final renderer migration. - -## Scope - -### Included -- Define `SceneViewportResolver`. -- Implement master anchor and per-layer derived anchors. -- Implement drift and hysteresis. -- Implement clamp behavior. -- Implement cache-update triggering and copy instrumentation metadata. - -### Excluded -- actual framebuffer copy execution -- sprite/HUD/fade composition logic -- broad renderer migration - -## Execution Steps - -### Step 1 - Define resolver state and inputs - -**What:** -Create the resolver state model and its public input surface. - -**How:** -- Define resolver state to own: - - master anchor - - per-layer derived anchors - - viewport dimensions - - hysteresis thresholds - - clamp-relevant scene bounds -- Define the external entry point that accepts camera position input. - -**File(s):** -- New resolver module(s), likely under HAL or drivers depending on final ownership - -### Step 2 - Implement master-to-layer totem derivation - -**What:** -Make layer motion derive from the master anchor using each layer’s `motion_factor`. - -**How:** -- Compute per-layer effective motion from the master anchor. -- Preserve support for normal layers (`1.0`) and parallax/background-like layers (`!= 1.0`). -- Keep the derivation explicit and testable per axis. - -**File(s):** -- Resolver module(s) -- Any math/helper module(s) needed for factor handling - -### Step 3 - Implement drift, hysteresis, and clamp - -**What:** -Translate camera motion into discrete anchor advancement safely. - -**How:** -- Implement drift calculation in pixel space against anchor centers in tile space. -- Implement hysteresis with: - - internal safe band - - external trigger band -- Implement clamp against scene bounds. -- Ensure edge behavior is explicitly asymmetric when clamped. - -**File(s):** -- Resolver module(s) - -### Step 4 - Connect resolver decisions to cache update requests - -**What:** -Turn resolver state changes into concrete cache update requests. - -**How:** -- Emit requests for: - - line refresh - - column refresh - - area/region refresh for corner updates -- Ensure no duplicate work is scheduled for already-covered cache content. -- Keep the resolver in charge of “what to refresh,” not “how cache storage performs it.” - -**File(s):** -- Resolver module(s) -- Shared request/command structs between resolver and cache - -### Step 5 - Add copy instrumentation outputs for later renderer use - -**What:** -Make the resolver capable of describing which cache slice/region should be copied for each layer. - -**How:** -- Define a per-layer copy request/instrumentation type. -- Include enough information for a later compositor to copy from cache into `back` without re-deciding viewport math. -- Do not execute the copy here. - -**File(s):** -- Resolver module(s) -- Shared copy-request types - -### Step 6 - Add focused resolver tests - -**What:** -Protect resolver correctness before renderer integration. - -**How:** -- Add tests for: - - master anchor updates - - per-layer motion-factor derivation - - hysteresis stability - - repeated high-speed movement - - clamp at scene edges - - corner-trigger conversion into region refresh requests - -**File(s):** -- Tests colocated with resolver modules - -## Test Requirements - -### Unit Tests -- Hysteresis prevents edge flick/thrash. -- Anchor movement occurs discretely in tile steps. -- Per-layer anchors follow the master according to `motion_factor`. -- Clamp behavior is correct near scene edges. - -### Integration Tests -- Resolver outputs valid update requests consumable by `SceneViewportCache`. - -### Manual Verification -- Instrument logs or debug traces to confirm no unnecessary refresh churn during back-and-forth movement near edges. - -## Acceptance Criteria - -- [ ] `SceneViewportResolver` exists with the full state required by `DEC-0013`. -- [ ] Master and per-layer anchors are derived correctly. -- [ ] Hysteresis and clamp are implemented and tested. -- [ ] Cache refresh requests are emitted by line, column, and region as required. -- [ ] Copy instrumentation metadata is available for later renderer use. - -## Dependencies - -- Depends on `PLN-0011` and `PLN-0012`. -- Source decision: `DEC-0013` - -## Risks - -- Resolver logic can become hard to reason about if movement, clamp, and copy instrumentation are not clearly separated. -- Parallax factor derivation can introduce subtle off-by-one or drift mismatch issues per layer. -- Region-update scheduling can duplicate work if X/Y corner movement is not normalized carefully. diff --git a/discussion/workflow/plans/PLN-0014-renderer-migration-to-scene-viewport-cache.md b/discussion/workflow/plans/PLN-0014-renderer-migration-to-scene-viewport-cache.md deleted file mode 100644 index 4de33d2c..00000000 --- a/discussion/workflow/plans/PLN-0014-renderer-migration-to-scene-viewport-cache.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -id: PLN-0014 -ticket: scene-bank-and-viewport-cache-refactor -title: Plan - Renderer Migration to Scene Viewport Cache -status: accepted -created: 2026-04-13 -completed: -tags: [gfx, tilemap, runtime, render] ---- - -## Objective - -Migrate world rendering from direct canonical `SceneBank` consumption to `SceneViewportCache` consumption while preserving the accepted observable composition order. - -## Background - -`DEC-0013` makes `SceneViewportCache` the immediate source of copy data for world blits and preserves the visible order of world layers, interleaved sprites, and HUD. `PLN-0011` already removed the old canonical `TileLayer` / `ScrollableTileLayer` model and cleaned the bridge surface accordingly. This plan focuses on the renderer migration itself. - -## Scope - -### Included -- Remove direct world-layer map reads from the renderer hot path. -- Make world-layer composition consume cache-backed copy requests. -- Preserve sprite interleaving and HUD ordering. -- Keep V1 destructive `back` composition acceptable. - -### Excluded -- scene domain model refactor -- cache structural implementation -- resolver movement logic -- non-world rendering systems beyond required integration points - -## Execution Steps - -### Step 1 - Identify and isolate direct canonical map consumption in the renderer - -**What:** -Locate current renderer paths that read canonical scene/layer maps directly. - -**How:** -- Replace any remaining direct `SceneBank` / `SceneLayer` / `TileMap` reads in [crates/console/prometeu-drivers/src/gfx.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/gfx.rs) with abstraction points prepared to accept cache-sourced copy requests. -- Keep the migration incremental enough to preserve buildability. - -**File(s):** -- [crates/console/prometeu-drivers/src/gfx.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/gfx.rs) - -### Step 2 - Introduce world-layer copy paths driven by cache requests - -**What:** -Teach the renderer to copy world content from `SceneViewportCache`. - -**How:** -- Add renderer-facing entry points that consume per-layer copy instrumentation emitted by the resolver. -- Ensure the renderer treats the cache as the immediate world source for blit operations. -- Do not let the renderer re-own totem/drift/clamp policy. - -**File(s):** -- [crates/console/prometeu-drivers/src/gfx.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/gfx.rs) -- Supporting cache/resolver integration modules - -### Step 3 - Preserve accepted composition order - -**What:** -Keep the visible ordering of layers, sprites, and HUD intact during migration. - -**How:** -- Preserve composition order: - - world layer 0 - - sprites - - world layer 1 - - sprites - - world layer 2 - - sprites - - world layer 3 - - sprites - - HUD -- Keep `HUD`, sprites, and fades outside the viewport-cache invalidation model. - -**File(s):** -- [crates/console/prometeu-drivers/src/gfx.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/gfx.rs) - -### Step 4 - Preserve destructive `back` composition for V1 - -**What:** -Accept destructive composition while still benefiting from cache-backed world inputs. - -**How:** -- Keep the first migrated renderer implementation destructive in `back`. -- Ensure the code path clearly separates: - - canonical scene data - - viewport cache data - - final composition buffer -- Avoid mixing “cache update” with “final buffer copy” concerns in the renderer. - -**File(s):** -- [crates/console/prometeu-drivers/src/gfx.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/gfx.rs) - -### Step 5 - Add renderer regression coverage - -**What:** -Protect the migrated composition order and world rendering behavior. - -**How:** -- Add tests or golden-style checks for: - - world layers rendered from cache, not canonical maps - - visible ordering of sprites between layers - - HUD remaining on top -- Add probes or assertions preventing accidental fallback to direct canonical map reads. - -**File(s):** -- Renderer tests in [crates/console/prometeu-drivers/src/gfx.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/gfx.rs) and adjacent test modules - -## Test Requirements - -### Unit Tests -- Cache-driven world copy code produces the same visible layer ordering as the prior renderer. - -### Integration Tests -- Full `render_all()` path uses `SceneViewportCache` for world layers. -- Sprites/HUD/fades remain correctly ordered relative to world layers. - -### Manual Verification -- Render representative scenes with multiple active layers and sprites to confirm no visible ordering regressions. - -## Acceptance Criteria - -- [ ] Renderer world composition no longer reads canonical `SceneBank` data directly in the hot path. -- [ ] World layers are copied from `SceneViewportCache`. -- [ ] Sprite interleaving and HUD ordering remain correct. -- [ ] V1 destructive composition still works end-to-end. -- [ ] Regression coverage protects the migrated path. - -## Dependencies - -- Depends on `PLN-0011`, `PLN-0012`, and `PLN-0013`. -- Source decision: `DEC-0013` - -## Risks - -- Renderer migration can accidentally duplicate world-copy work if cache and compositor responsibilities blur. -- Sprite ordering regressions are easy to introduce during world-layer refactoring. -- Temporary fallback paths can linger unless tests explicitly block them. diff --git a/discussion/workflow/plans/PLN-0015-api-bank-integration-and-tests.md b/discussion/workflow/plans/PLN-0015-api-bank-integration-and-tests.md deleted file mode 100644 index 6c79d2db..00000000 --- a/discussion/workflow/plans/PLN-0015-api-bank-integration-and-tests.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -id: PLN-0015 -ticket: scene-bank-and-viewport-cache-refactor -title: Plan - API, Bank Integration, and Tests -status: accepted -created: 2026-04-13 -completed: -tags: [gfx, tilemap, runtime, render] ---- - -## Objective - -Finish the scene/viewport-cache migration by aligning exposed APIs, final integration surfaces, and test coverage across HAL, drivers, and system entry points. - -## Background - -After core types, cache, resolver, and renderer migration exist, the remaining work is to align the surrounding surfaces so the new architecture is usable as the runtime’s operational model. `PLN-0011` already removed the old canonical tile-layer APIs and introduced `BankType::SCENE` plus scene-aware bank slots. The binary `SCENE` payload contract and decoder are now isolated in `PLN-0016`. - -## Scope - -### Included -- Update bridge APIs and exposed runtime surfaces. -- Remove stale tile-layer-era interfaces. -- Add cross-layer regression coverage. - -### Excluded -- additional architectural redesign -- feature work beyond the accepted decision - -## Execution Steps - -### Step 1 - Update HAL and bridge surfaces - -**What:** -Remove or replace public APIs still shaped around the old scrollable tile-layer model. - -**How:** -- Verify `GfxBridge` and adjacent bridge traits stay free of obsolete canonical layer ownership assumptions after cache/resolver integration. -- Introduce scene/cache/resolver-oriented access only where required by runtime consumers. - -**File(s):** -- [crates/console/prometeu-hal/src/gfx_bridge.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/gfx_bridge.rs) -- Other bridge traits affected by scene model changes - -### Step 2 - Align driver/hardware construction paths - -**What:** -Ensure hardware and driver initialization paths can construct and own the new scene/cache/resolver model. - -**How:** -- Update hardware bootstrap and driver ownership paths to instantiate the canonical scene and viewport-cache stack. -- Remove any remaining ownership assumptions tied to the pre-`SceneBank` model. - -**File(s):** -- [crates/console/prometeu-drivers/src/hardware.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/hardware.rs) -- [crates/console/prometeu-drivers/src/gfx.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/gfx.rs) - -### Step 3 - Remove stale type and API remnants - -**What:** -Clean out old interfaces that would leave the codebase in a dual-model state. - -**How:** -- Remove any remaining obsolete references to: - - `TileLayer` - - `ScrollableTileLayer` - - direct old-layer scroll ownership APIs - - transitional commented fallback paths left during migration -- Keep only the canonical scene model and the viewport-cache/render pipeline required by the decision. - -**File(s):** -- HAL and driver modules touched by earlier plans - -### Step 4 - Add full-stack regression coverage - -**What:** -Add the minimum test family needed to execute the migration safely one plan at a time. - -**How:** -- Add tests for: - - canonical scene ownership - - viewport-cache update behavior - - resolver drift/hysteresis - - renderer composition order - - scene swap invalidation - - absence of stale old-layer APIs -- Add at least one integration path that exercises: - - scene load - - cache population - - resolver update - - renderer world composition - -**File(s):** -- Test modules across HAL, drivers, and system crates as needed - -## Test Requirements - -### Unit Tests -- Public/runtime-facing APIs no longer depend on `ScrollableTileLayer`. -- Cache, resolver, and renderer modules remain individually covered. - -### Integration Tests -- End-to-end scene load -> cache update -> renderer composition path succeeds. -- Scene swap invalidates cache and repopulates correctly. - -### Manual Verification -- Build the runtime and exercise representative world scenes to confirm no stale assumptions remain in construction or render flow. - -## Acceptance Criteria - -- [ ] Bridge and runtime-facing APIs align with the new scene/cache model. -- [ ] Hardware/driver construction paths instantiate the new architecture correctly. -- [ ] Stale old-layer APIs are removed. -- [ ] Full-stack regression coverage exists for the migration. - -## Dependencies - -- Depends on `PLN-0011`, `PLN-0012`, `PLN-0013`, `PLN-0014`, and `PLN-0016`. -- Source decision: `DEC-0013` - -## Risks - -- API cleanup is where hidden dependencies on the old model are most likely to surface. -- If stale APIs are not removed aggressively, the codebase can get stuck in a fragile dual-model transition. diff --git a/discussion/workflow/plans/PLN-0016-scene-binary-payload-format-and-decoder.md b/discussion/workflow/plans/PLN-0016-scene-binary-payload-format-and-decoder.md deleted file mode 100644 index f3e4c37f..00000000 --- a/discussion/workflow/plans/PLN-0016-scene-binary-payload-format-and-decoder.md +++ /dev/null @@ -1,164 +0,0 @@ ---- -id: PLN-0016 -ticket: scene-bank-and-viewport-cache-refactor -title: Plan - Scene Binary Payload Format and Decoder -status: accepted -created: 2026-04-13 -completed: -tags: [asset, runtime, scene, codec, binary-format] ---- - -## Objective - -Define the canonical binary payload contract for `SCENE` assets and implement the runtime decoder needed to load `SceneBank` content without JSON-based scene payloads. - -## Background - -`DEC-0013` established `SceneBank` as the canonical loaded scene aggregate. `PLN-0011` introduced `BankType::SCENE` and the scene-aware bank slot model, but intentionally left `SCENE` payload decoding open. A temporary `todo!()` now blocks scene payload materialization in the asset manager until the binary contract is closed. This plan isolates that format and decoder work before the final integration pass. - -## Scope - -### Included -- Define the binary on-disk/on-wire payload format for `SCENE`. -- Define the minimum metadata contract needed in `AssetEntry` for `SCENE`. -- Implement the runtime decoder from payload bytes into `SceneBank`. -- Add format and decode tests for valid and invalid scene payloads. -- Re-enable scene asset load/preload coverage once the decoder exists. - -### Excluded -- `SceneViewportCache` -- `SceneViewportResolver` -- renderer migration -- cartridge authoring tooling beyond what is strictly needed to encode test fixtures -- reopening canonical scene/runtime type design - -## Execution Steps - -### Step 1 - Define the binary `SCENE` payload contract - -**What:** -Close the binary layout for serialized `SceneBank` assets. - -**How:** -- Define a versioned binary format with: - - file/payload prelude or version marker - - fixed four-layer scene layout - - per-layer metadata block - - per-layer tilemap dimensions - - serialized tile records -- Keep the format aligned with the canonical runtime shape from `PLN-0011`: - - `SceneBank` - - `[SceneLayer; 4]` - - `motion_factor` - - `TileMap` - - `Tile` -- Document field sizes, endianness, ordering, and validation rules. - -**File(s):** -- [crates/console/prometeu-hal/src/asset.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/asset.rs) -- [crates/console/prometeu-hal/src/cartridge_loader.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/cartridge_loader.rs) -- Additional shared asset-format module(s) if needed - -### Step 2 - Define `SCENE` metadata requirements in `AssetEntry` - -**What:** -Decide what belongs in `AssetEntry.metadata` versus the binary payload itself. - -**How:** -- Keep metadata minimal and stable. -- Add only fields that materially help validation or loader routing. -- Avoid duplicating large structural scene information in both metadata and payload. -- Add typed metadata helpers in HAL if required for scene assets. - -**File(s):** -- [crates/console/prometeu-hal/src/asset.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/asset.rs) - -### Step 3 - Implement the runtime `SCENE` decoder - -**What:** -Replace the current `todo!()` loader path with a real binary decoder. - -**How:** -- Implement `perform_load_scene_bank(...)` using the accepted binary contract. -- Decode from slice/reader into canonical runtime objects: - - `SceneBank` - - `SceneLayer` - - `TileMap` - - `Tile` -- Add explicit validation for: - - invalid version - - short payload - - invalid tile-size values - - layer count mismatch - - tile count mismatch - - numeric overflow / malformed dimensions -- Keep decode logic self-contained and free of viewport/cache behavior. - -**File(s):** -- [crates/console/prometeu-drivers/src/asset.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/asset.rs) -- Supporting HAL/shared modules if decoder helpers are factored out - -### Step 4 - Re-enable scene asset loading paths and tests - -**What:** -Turn scene asset loading back on in the asset manager and restore coverage. - -**How:** -- Re-enable the `SCENE` load/preload path currently blocked by the `todo!()`. -- Add tests for: - - scene payload decode success - - scene asset load - - scene preload on initialization - - malformed scene payload rejection -- Ensure glyph/sound behavior remains unchanged. - -**File(s):** -- [crates/console/prometeu-drivers/src/asset.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/asset.rs) - -### Step 5 - Confirm cartridge-loader and asset-table compatibility - -**What:** -Ensure the broader cartridge/asset pipeline accepts the finalized `SCENE` contract cleanly. - -**How:** -- Verify `AssetEntry` and cartridge-loading paths accept the new scene metadata contract. -- Add targeted tests for asset-table parsing or preload validation if needed. -- Keep this step scoped to compatibility with the finalized binary scene payload, not new tooling features. - -**File(s):** -- [crates/console/prometeu-hal/src/cartridge_loader.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/cartridge_loader.rs) -- [crates/console/prometeu-hal/src/asset.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/asset.rs) - -## Test Requirements - -### Unit Tests -- Valid binary scene payloads decode into the expected `SceneBank`. -- Invalid payloads fail with explicit decoder errors. -- Per-layer metadata and tile contents survive round-trip fixture decode. - -### Integration Tests -- `SCENE` assets can be loaded and preloaded through `AssetManager`. -- Scene bank slot installation works without breaking glyph/sound behavior. - -### Manual Verification -- Inspect one representative binary scene fixture and confirm the decoded `SceneBank` matches the expected four-layer canonical shape. - -## Acceptance Criteria - -- [ ] The binary `SCENE` payload format is explicitly defined and versioned. -- [ ] `AssetEntry` requirements for `SCENE` are documented and implemented. -- [ ] `perform_load_scene_bank(...)` is implemented without JSON payload parsing. -- [ ] Scene load/preload tests pass against the finalized binary decoder. -- [ ] Glyph and sound asset paths remain unaffected. - -## Dependencies - -- Depends on `PLN-0011`. -- Should complete before the final integration/cleanup pass in `PLN-0015`. -- Source decision: `DEC-0013` - -## Risks - -- Overloading `AssetEntry.metadata` can duplicate scene structure and make the contract brittle. -- A weak binary format definition can create hidden compatibility problems for future scene growth. -- Decoder validation gaps can surface later as corrupted scene state instead of explicit asset-load failures.