diff --git a/discussion/index.ndjson b/discussion/index.ndjson index b8501bd6..c8617971 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,4 +1,4 @@ -{"type":"meta","next_id":{"DSC":27,"AGD":27,"DEC":15,"PLN":22,"LSN":31,"CLSN":1}} +{"type":"meta","next_id":{"DSC":28,"AGD":28,"DEC":16,"PLN":26,"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"}]} @@ -19,6 +19,7 @@ {"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-0026","status":"open","ticket":"render-all-scene-cache-and-camera-integration","title":"Integrate render_all with Scene Cache and Camera","created_at":"2026-04-14","updated_at":"2026-04-15","tags":["gfx","runtime","render","camera","scene"],"agendas":[{"id":"AGD-0026","file":"workflow/agendas/AGD-0026-render-all-scene-cache-and-camera-integration.md","status":"accepted","created_at":"2026-04-14","updated_at":"2026-04-15"}],"decisions":[{"id":"DEC-0014","file":"workflow/decisions/DEC-0014-frame-composer-render-integration.md","status":"accepted","created_at":"2026-04-14","updated_at":"2026-04-15","ref_agenda":"AGD-0026"}],"plans":[{"id":"PLN-0017","file":"workflow/plans/PLN-0017-frame-composer-core-and-hardware-ownership.md","status":"accepted","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0014"]},{"id":"PLN-0018","file":"workflow/plans/PLN-0018-sprite-controller-and-frame-emission-model.md","status":"accepted","created_at":"2026-04-14","updated_at":"2026-04-14","ref_decisions":["DEC-0014"]},{"id":"PLN-0019","file":"workflow/plans/PLN-0019-scene-binding-camera-and-scene-status.md","status":"accepted","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0014"]},{"id":"PLN-0020","file":"workflow/plans/PLN-0020-cache-refresh-and-render-frame-path.md","status":"accepted","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0014"]},{"id":"PLN-0021","file":"workflow/plans/PLN-0021-service-retirement-callsite-migration-and-regression.md","status":"accepted","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0014"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0027","status":"open","ticket":"frame-composer-public-syscall-surface","title":"Agenda - FrameComposer Public Syscall Surface","created_at":"2026-04-17","updated_at":"2026-04-17","tags":["gfx","runtime","syscall","abi","frame-composer","scene","camera","sprites"],"agendas":[{"id":"AGD-0027","file":"workflow/agendas/AGD-0027-frame-composer-public-syscall-surface.md","status":"accepted","created_at":"2026-04-17","updated_at":"2026-04-17"}],"decisions":[{"id":"DEC-0015","file":"workflow/decisions/DEC-0015-frame-composer-public-syscall-surface.md","status":"accepted","created_at":"2026-04-17","updated_at":"2026-04-17","ref_agenda":"AGD-0027"}],"plans":[{"id":"PLN-0022","file":"workflow/plans/PLN-0022-composer-syscall-domain-and-spec-propagation.md","status":"accepted","created_at":"2026-04-17","updated_at":"2026-04-17","ref_decisions":["DEC-0015"]},{"id":"PLN-0023","file":"workflow/plans/PLN-0023-composer-runtime-dispatch-and-legacy-removal.md","status":"accepted","created_at":"2026-04-17","updated_at":"2026-04-17","ref_decisions":["DEC-0015"]},{"id":"PLN-0024","file":"workflow/plans/PLN-0024-composer-cartridge-tooling-and-regression-migration.md","status":"accepted","created_at":"2026-04-17","updated_at":"2026-04-17","ref_decisions":["DEC-0015"]},{"id":"PLN-0025","file":"workflow/plans/PLN-0025-final-ci-validation-and-polish.md","status":"accepted","created_at":"2026-04-17","updated_at":"2026-04-17","ref_decisions":["DEC-0015"]}],"lessons":[]} {"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/workflow/agendas/AGD-0027-frame-composer-public-syscall-surface.md b/discussion/workflow/agendas/AGD-0027-frame-composer-public-syscall-surface.md new file mode 100644 index 00000000..560720cd --- /dev/null +++ b/discussion/workflow/agendas/AGD-0027-frame-composer-public-syscall-surface.md @@ -0,0 +1,214 @@ +--- +id: AGD-0027 +ticket: frame-composer-public-syscall-surface +title: Agenda - FrameComposer Public Syscall Surface +status: accepted +created: 2026-04-17 +updated: 2026-04-17 +tags: [gfx, runtime, syscall, abi, frame-composer, scene, camera, sprites] +--- + +## Contexto + +`DEC-0014` e os planos `PLN-0017` a `PLN-0021` fecharam a migração interna do pipeline de frame para `FrameComposer`: + +- `FrameComposer` virou o orquestrador canônico do frame; +- `Hardware` passou a agregá-lo ao lado de `Gfx`; +- scene, camera, cache, resolver e sprite emission migraram para ownership interno dele; +- o frame loop do runtime passou a renderizar via `FrameComposer.render_frame()`. + +Isso resolveu a base operacional interna, mas não fechou a superfície pública equivalente para a VM. A ABI pública ainda expõe apenas o contrato legado de `gfx.set_sprite(...)`, enquanto `bind_scene(...)` e `set_camera(...)` existem apenas como APIs internas do driver. + +Na prática, hoje temos uma assimetria: + +- a base canônica do frame está em `FrameComposer`; +- mas a ABI pública ainda não trata `FrameComposer` como serviço canônico para scene, camera e sprites. + +Essa lacuna impede a migração do restante da stack e também impede um stress cartridge que atravesse de verdade o pipeline novo por syscall pública. + +## Problema + +Precisamos definir a nova superfície pública de syscall para o pipeline canônico de `FrameComposer` sem reabrir a decisão já aceita sobre ownership interno do frame. + +O problema concreto não é “adicionar 2 ou 3 syscalls”. Precisamos decidir: + +- quais operações de `FrameComposer` viram ABI pública agora; +- se `gfx.set_sprite(...)` continua como shim legado ou perde status canônico; +- qual é o contrato mínimo de scene/camera que a VM pode observar/controlar; +- como nomear e versionar essa superfície pública sem criar um segundo modelo canônico concorrente; +- qual é a estratégia de transição para cartridge, runtime tests e stress tests; +- como propagar essa mudança para a spec canônica e, se necessário, para contratos de ABI e `ISA_CORE`. + +## Pontos Criticos + +- `DEC-0014` já fechou `FrameComposer` como base canônica interna; esta agenda não deve reabrir isso. +- A ABI pública atual ainda expõe `gfx.set_sprite(...)` com semântica herdada de índice/slot, mesmo que a implementação interna já use frame emission. +- `bind_scene(scene_bank_id)` e `set_camera(x, y)` já existem no driver, mas ainda não existem como syscalls públicas. +- Se a nova ABI expuser demais logo de início, vamos congelar cedo demais detalhes que ainda não provaram valor operacional. +- Se a nova ABI expuser de menos, manteremos um modelo híbrido por tempo demais: + - canônico internamente via `FrameComposer`; + - legado externamente via `Gfx`/`set_sprite`. +- Precisamos decidir se o namespace público continua em `gfx.*` por estabilidade do domínio, ou se devemos introduzir algo como `frame.*`. +- A transição precisa preservar compatibilidade suficiente para não quebrar cartridges e testes existentes antes da migração do restante. +- O contrato de sprite precisa deixar claro se o chamador ainda informa índice, se informa `layer`, e se `active` continua existindo na superfície pública. +- A mudança não pode ficar só em código/runtime; a spec canônica precisa ser atualizada para refletir o novo serviço público. +- Se o contrato público afetar superfícies documentadas de ABI ou o material de `ISA_CORE`, essa propagação precisa ser tratada como parte da mesma thread, não como follow-up solto. + +## Opcoes + +### Opcao 1 - Expor um núcleo mínimo canônico em `gfx.*` + +**Como seria:** +Adicionar apenas a superfície mínima para a VM controlar o pipeline novo: + +- `gfx.bind_scene(bank_id)` +- `gfx.unbind_scene()` +- `gfx.set_camera(x, y)` +- `gfx.emit_sprite(...)` + +`gfx.set_sprite(...)` permaneceria por um período como shim legado de compatibilidade. + +**Vantagens:** +- fecha rapidamente a lacuna operacional; +- habilita stress real do pipeline novo; +- reduz o tempo de convivência entre modelo canônico e legado; +- mantém o domínio público em `gfx`, evitando churn de namespace. + +**Desvantagens:** +- introduz ABI nova que precisará de migração coordenada; +- exige definir `emit_sprite(...)` com cuidado para não herdar sem querer o modelo de slot. + +### Opcao 2 - Expor scene/camera agora e adiar o contrato novo de sprite + +**Como seria:** +Publicar apenas: + +- `gfx.bind_scene(bank_id)` +- `gfx.unbind_scene()` +- `gfx.set_camera(x, y)` + +Sprites continuariam publicamente via `gfx.set_sprite(...)` até uma segunda fase. + +**Vantagens:** +- menor mudança imediata de ABI; +- desbloqueia o stress do world path e da câmera; +- reduz o volume inicial da migração pública. + +**Desvantagens:** +- mantém dois modelos públicos de sprite por mais tempo; +- prolonga a semântica de compatibilidade do syscall legado; +- adia exatamente uma das partes centrais da migração para `FrameComposer`. + +### Opcao 3 - Criar um novo namespace público separado, como `composer.*` + +**Como seria:** +O pipeline novo ganha syscalls em um domínio separado, por exemplo: + +- `composer.bind_scene` +- `composer.unbind_scene` +- `composer.set_camera` +- `composer.emit_sprite` + +`gfx.*` ficaria como superfície legacy/low-level. + +**Vantagens:** +- deixa explícita a mudança de serviço canônico; +- evita sobrecarregar semanticamente `gfx`. + +**Desvantagens:** +- adiciona churn conceitual e de nomenclatura; +- fragmenta demais a superfície pública neste momento; +- cria um custo de transição maior sem benefício operacional evidente. + +## Sugestao / Recomendacao + +Seguir com a **Opcao 3**. + +Direção recomendada: + +- a superfície pública canônica deve migrar para o domínio `composer.*`; +- `FrameComposer` vira a base canônica também na ABI pública, com namespace próprio em vez de continuar semanticamente preso a `gfx.*`; +- o núcleo mínimo público deve ser: + - `composer.bind_scene(bank_id) -> status` + - `composer.unbind_scene()` + - `composer.set_camera(x, y)` + - `composer.emit_sprite(...) -> status` +- `gfx.set_sprite(...)` deve morrer e ser removido completamente do contrato público. + +Para sprites, a recomendação provisória é: + +- a nova ABI pública não deve exigir índice explícito; +- `composer.emit_sprite(...)` deve receber o payload completo necessário para o frame: + - `glyph_id` + - `palette_id` + - `x` + - `y` + - `layer` + - `bank_id` + - `flip_x` + - `flip_y` + - `priority` +- a ABI pode futuramente agrupar esse payload se isso melhorar ergonomia, mas o contrato mínimo deve nascer completo; +- `active` não deve continuar no contrato canônico novo; +- overflow continua sendo ignorado com status/telemetria adequada, sem trapar o runtime. + +Para scene/camera, a recomendação provisória é: + +- manter o contrato mínimo já aceito internamente; +- `bind_scene` por bank id; +- `unbind_scene` explícito; +- `set_camera(x, y)` em pixel space com top-left viewport. +- `bind_scene(...)`, `unbind_scene(...)` e `emit_sprite(...)` devem usar `ComposerOpStatus` como retorno operacional canônico. + +## Perguntas em Aberto + +- Resolvido: + - o nome público canônico de sprite será `composer.emit_sprite(...)`; + - o syscall novo de sprite nasce completo com `glyph_id`, `palette_id`, `x`, `y`, `layer`, `bank_id`, `flip_x`, `flip_y`, `priority`; + - `gfx.set_sprite(...)` deve morrer e ser removido completamente; + - não haverá leitura de estado nesta primeira fase; + - `bind_scene(...)`, `unbind_scene(...)` e `emit_sprite(...)` usarão `ComposerOpStatus`; +- A ABI nova precisa expor refresh explícito, ou isso deve continuar totalmente interno ao `FrameComposer`? +- Resolvido: + - a ABI nova não deve expor refresh explícito; + - o domínio público canônico será `composer.*`, não `gfx.*`. + +## Criterio para Encerrar + +Esta agenda pode ser encerrada quando houver acordo explícito sobre: + +- a lista mínima de syscalls públicas canônicas do `FrameComposer`; +- o nome canônico da operação pública de sprite; +- a remoção completa de `gfx.set_sprite(...)` do contrato público; +- o formato de retorno/status das novas operações; +- a estratégia de transição necessária para decisão, plano e migração do restante da stack. + +## Resolucao em Andamento + +Direção atualmente acordada nesta agenda: + +- o namespace público canônico será `composer.*`; +- o núcleo mínimo inicial será: + - `composer.bind_scene(bank_id) -> ComposerOpStatus` + - `composer.unbind_scene() -> ComposerOpStatus` + - `composer.set_camera(x, y)` + - `composer.emit_sprite(glyph_id, palette_id, x, y, layer, bank_id, flip_x, flip_y, priority) -> ComposerOpStatus` +- não haverá introspecção pública nesta primeira fase; +- refresh/cache policy continua interno ao `FrameComposer`; +- `gfx.set_sprite(...)` não terá caminho de compatibilidade e deve ser removido. + +## Resolucao + +Esta agenda fica aceita com os seguintes pontos fechados: + +- o namespace público canônico do serviço será `composer.*`; +- a superfície mínima inicial será: + - `composer.bind_scene(bank_id) -> ComposerOpStatus` + - `composer.unbind_scene() -> ComposerOpStatus` + - `composer.set_camera(x, y)` + - `composer.emit_sprite(glyph_id, palette_id, x, y, layer, bank_id, flip_x, flip_y, priority) -> ComposerOpStatus` +- não haverá introspecção pública nesta primeira fase; +- não haverá refresh/cache policy público; +- `gfx.set_sprite(...)` deve ser removido completamente, sem shim de compatibilidade; +- a transição deve introduzir `composer.*` e remover `gfx.set_sprite(...)` na mesma thread de migração, com atualização coordenada de bytecode, cartridges, tests e runtime; +- a mesma thread deve atualizar a spec canônica do assunto e propagar a mudança para contratos de ABI e `ISA_CORE` quando essas superfícies forem impactadas pelo novo serviço público. diff --git a/discussion/workflow/decisions/DEC-0015-frame-composer-public-syscall-surface.md b/discussion/workflow/decisions/DEC-0015-frame-composer-public-syscall-surface.md new file mode 100644 index 00000000..f0fb8fba --- /dev/null +++ b/discussion/workflow/decisions/DEC-0015-frame-composer-public-syscall-surface.md @@ -0,0 +1,166 @@ +--- +id: DEC-0015 +ticket: frame-composer-public-syscall-surface +title: FrameComposer Public Syscall Surface +status: accepted +created: 2026-04-17 +accepted: 2026-04-17 +agenda: AGD-0027 +plans: [PLN-0022, PLN-0023, PLN-0024, PLN-0025] +tags: [gfx, runtime, syscall, abi, frame-composer, scene, camera, sprites] +--- + +## Status + +Accepted. + +## Contexto + +`DEC-0014` locked `FrameComposer` as the canonical internal frame orchestration service and `PLN-0017` through `PLN-0021` completed that internal migration path. `Hardware` now owns `FrameComposer`, the runtime renders through `FrameComposer.render_frame()`, and scene/camera/cache/resolver/sprite ownership no longer belongs canonically to `Gfx`. + +That migration did not define the equivalent public syscall contract for VM code. The public ABI still exposed legacy `gfx`-domain sprite control while the canonical scene/camera operations existed only as internal driver APIs. + +This decision closes that public ABI gap without reopening the already accepted internal ownership model. + +## Decisao + +The canonical public syscall surface for frame orchestration SHALL move to the `composer.*` namespace. + +Normatively: + +- The canonical public service domain for `FrameComposer` operations SHALL be `composer`. +- The initial canonical syscall set SHALL be: + - `composer.bind_scene(bank_id) -> ComposerOpStatus` + - `composer.unbind_scene() -> ComposerOpStatus` + - `composer.set_camera(x, y)` + - `composer.emit_sprite(glyph_id, palette_id, x, y, layer, bank_id, flip_x, flip_y, priority) -> ComposerOpStatus` +- `composer.emit_sprite(...)` SHALL be the canonical public sprite submission path. +- `composer.emit_sprite(...)` MUST NOT require a caller-provided sprite index. +- `composer.emit_sprite(...)` MUST carry `layer` and `priority`. +- `composer.emit_sprite(...)` MUST NOT expose `active` as part of the canonical contract. +- `composer.bind_scene(...)`, `composer.unbind_scene()`, and `composer.emit_sprite(...)` SHALL return `ComposerOpStatus`. +- `composer.set_camera(x, y)` SHALL keep the minimal V1 camera contract already accepted by `DEC-0014`: + - `x` and `y` are `i32` pixel coordinates; + - they represent the top-left viewport origin in world space. +- The public ABI MUST NOT expose cache refresh policy or explicit refresh controls. +- The public ABI MUST NOT expose scene/camera introspection in this first phase. +- `gfx.set_sprite(...)` MUST be removed completely from the public contract. +- No compatibility shim for `gfx.set_sprite(...)` SHALL remain as part of the canonical migration target. +- Introduction of `composer.*` and removal of `gfx.set_sprite(...)` SHALL be executed in the same migration thread. + +## Rationale + +The public ABI must reflect the accepted ownership model rather than preserve a misleading legacy shape. + +Keeping the canonical public surface under `gfx.*` would continue to tie orchestration semantics to the wrong service boundary. The new namespace makes the ownership change explicit: + +- `Gfx` is the visual backend; +- `FrameComposer` is the frame orchestration service. + +Removing `gfx.set_sprite(...)` completely avoids prolonging a dual public sprite model. A compatibility shim would preserve legacy slot/index semantics in the public contract after those semantics had already ceased to be canonical internally. + +Returning `ComposerOpStatus` for operational mutating calls preserves status-first behavior while keeping the public contract aligned with the new service boundary. Reusing `GfxOpStatus` would leak backend-domain semantics into orchestration-domain syscalls after that separation had already been made explicit. + +Deferring introspection and explicit refresh controls keeps the first public ABI focused on control, not diagnostics or internal policy leakage. + +## Invariantes / Contrato + +### 1. Namespace + +- Public frame-orchestration syscalls MUST live under `composer.*`. +- `composer.*` SHALL be treated as the canonical public orchestration surface. +- `gfx.*` SHALL NOT remain the canonical public orchestration namespace for scene/camera/sprite submission. + +### 2. Scene Control + +- `composer.bind_scene(bank_id)` MUST bind by scene bank id. +- Binding semantics MUST remain aligned with `DEC-0014`: + - scene resolution through the scene bank pool; + - explicit bind/unbind lifecycle; + - no implicit per-frame rebinding. +- `composer.unbind_scene()` MUST leave no-scene rendering valid. +- `ComposerOpStatus` SHALL be the canonical operational status family for composer-domain mutating syscalls. + +### 3. Camera + +- `composer.set_camera(x, y)` MUST remain the minimal V1 camera API. +- Camera follow, smoothing, shake, transitions, and readback are OUT OF SCOPE for this decision. + +### 4. Sprite Submission + +- `composer.emit_sprite(...)` MUST be frame-emission based. +- The caller MUST NOT provide sprite slot/index information. +- The public payload MUST include: + - `glyph_id` + - `palette_id` + - `x` + - `y` + - `layer` + - `bank_id` + - `flip_x` + - `flip_y` + - `priority` +- The canonical public sprite contract MUST NOT include `active`. +- Overflow behavior SHALL remain aligned with `DEC-0014`: + - excess sprites are ignored; + - overflow is not a hard VM fault in V1. + +### 5. Non-Goals for V1 Public ABI + +- No public refresh/invalidate syscalls. +- No public cache inspection syscalls. +- No public `scene_status()` syscall. +- No public `get_camera()` syscall. + +### 6. Migration Contract + +- Migration MUST update: + - syscall registry and ABI resolution; + - runtime dispatch; + - bytecode/cartridge declarations; + - tests; + - stress cartridges and related tooling where applicable. +- Migration MUST NOT leave `gfx.set_sprite(...)` as a supported public fallback after the new contract lands. + +## Impactos + +### HAL + +- The syscall enum, registry, metadata, and resolver will need a new `composer` domain surface. +- `gfx.set_sprite(...)` must be removed from the public ABI contract. +- A new `ComposerOpStatus` contract will need to be introduced for composer-domain operational returns. + +### Runtime / VM + +- Runtime dispatch must route public scene/camera/sprite orchestration through `FrameComposer`. +- Existing bytecode declarations and cartridges that rely on `gfx.set_sprite(...)` will need coordinated migration. + +### Spec / ABI / ISA_CORE + +- The canonical spec for the public VM-facing graphics/composition surface must be updated to reflect `composer.*`. +- ABI-facing documentation and contracts must be updated wherever syscall domain, names, arguments, or return semantics are specified. +- `ISA_CORE` must be updated if and where it normatively references the public syscall surface affected by this decision. + +### Drivers / Hardware + +- `FrameComposer` already has the required internal base; execution work will focus on public ABI exposure rather than internal ownership redesign. + +### Tooling / Stress + +- Stress cartridges and bytecode generators can only exercise the canonical frame path publicly after `composer.*` exists. + +## Referencias + +- [AGD-0027-frame-composer-public-syscall-surface.md](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/discussion/workflow/agendas/AGD-0027-frame-composer-public-syscall-surface.md) +- [DEC-0014-frame-composer-render-integration.md](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/discussion/workflow/decisions/DEC-0014-frame-composer-render-integration.md) + +## Propagacao Necessaria + +- A new implementation plan MUST be created from this decision before code changes. +- The plan MUST cover ABI introduction, legacy syscall removal, cartridge/test migration, regression coverage, and canonical spec propagation. +- The plan MUST explicitly assess and update ABI and `ISA_CORE` artifacts where this decision changes documented public behavior. +- Stress tooling SHOULD be updated as part of the migration thread so the public ABI can exercise the canonical frame path end-to-end. + +## Revision Log + +- 2026-04-17: Initial accepted decision from `AGD-0027`. diff --git a/discussion/workflow/plans/PLN-0022-composer-syscall-domain-and-spec-propagation.md b/discussion/workflow/plans/PLN-0022-composer-syscall-domain-and-spec-propagation.md new file mode 100644 index 00000000..34916ad3 --- /dev/null +++ b/discussion/workflow/plans/PLN-0022-composer-syscall-domain-and-spec-propagation.md @@ -0,0 +1,122 @@ +--- +id: PLN-0022 +ticket: frame-composer-public-syscall-surface +title: Plan - Composer Syscall Domain and Spec Propagation +status: accepted +created: 2026-04-17 +completed: +tags: [gfx, runtime, syscall, abi, spec, isa-core, frame-composer] +--- + +## Objective + +Introduce the canonical `composer.*` syscall domain, define `ComposerOpStatus`, and propagate the new public contract through the canonical spec, ABI documentation, and `ISA_CORE` artifacts where affected. + +## Background + +`DEC-0015` locks the public orchestration surface on `composer.*`, requires `ComposerOpStatus` for mutating composer-domain calls, and requires propagation beyond code into canonical spec, ABI-facing documentation, and `ISA_CORE` where the public syscall surface is described normatively. + +## Scope + +### Included +- add the `composer` syscall domain and ids +- define `ComposerOpStatus` +- remove `gfx.set_sprite(...)` from the public ABI contract +- update canonical spec documentation for the new public surface +- update ABI-facing documentation and `ISA_CORE` wherever the public syscall contract is described + +### Excluded +- runtime dispatch implementation +- cartridge and stress program migration +- final repository-wide CI execution + +## Execution Steps + +### Step 1 - Define the public `composer` syscall contract + +**What:** +Add the new canonical public syscall surface to the HAL syscall contract. + +**How:** +- Extend the syscall enum, registry, metadata, and resolver with a new `composer` domain. +- Allocate explicit syscall ids for: + - `composer.bind_scene` + - `composer.unbind_scene` + - `composer.set_camera` + - `composer.emit_sprite` +- Remove `gfx.set_sprite` from the public syscall contract and registry. +- Keep syscall metadata explicit for arg/ret slots and capability requirements. + +**File(s):** +- `crates/console/prometeu-hal/src/syscalls.rs` +- `crates/console/prometeu-hal/src/syscalls/domains/*` +- `crates/console/prometeu-hal/src/syscalls/registry.rs` +- `crates/console/prometeu-hal/src/syscalls/resolver.rs` + +### Step 2 - Introduce `ComposerOpStatus` + +**What:** +Create the status family for composer-domain mutating operations. + +**How:** +- Define a `ComposerOpStatus` type in HAL with explicit operational states needed by: + - scene binding + - scene unbinding + - sprite emission +- Ensure the enum is semantically composer-domain specific rather than a rename wrapper around `GfxOpStatus`. +- Update public API references so composer syscalls return `ComposerOpStatus` where required by `DEC-0015`. + +**File(s):** +- `crates/console/prometeu-hal/src/*` +- any shared status exports used by runtime/VM code + +### Step 3 - Propagate the contract into spec, ABI docs, and `ISA_CORE` + +**What:** +Update normative documentation so the public contract no longer describes legacy `gfx.set_sprite`. + +**How:** +- Identify canonical spec files that describe VM graphics/composition syscalls. +- Replace public references to legacy sprite orchestration with `composer.*`. +- Update ABI-facing docs to pin: + - namespace + - names + - arg order + - return semantics +- Update `ISA_CORE` if and where it references the affected syscall surface. +- Keep published spec content in English per repository policy. + +**File(s):** +- canonical spec location(s) +- ABI contract documentation +- `ISA_CORE` artifact(s) if affected + +## Test Requirements + +### Unit Tests +- syscall registry tests pin the new `composer.*` entries and reject removed legacy identities +- `ComposerOpStatus` values are pinned where public return semantics are asserted + +### Integration Tests +- declared syscall resolution accepts `composer.*` declarations and rejects removed `gfx.set_sprite` + +### Manual Verification +- inspect canonical spec, ABI docs, and `ISA_CORE` references to confirm the public contract matches `DEC-0015` + +## Acceptance Criteria + +- [ ] The public syscall registry exposes `composer.bind_scene`, `composer.unbind_scene`, `composer.set_camera`, and `composer.emit_sprite`. +- [ ] `ComposerOpStatus` exists as the canonical status family for composer-domain mutating syscalls. +- [ ] `gfx.set_sprite` is removed from the public ABI contract. +- [ ] Canonical spec documentation is updated to describe `composer.*`. +- [ ] ABI-facing docs and `ISA_CORE` are updated wherever the affected public surface is documented. + +## Dependencies + +- Source decision: `DEC-0015` + +## Risks + +- Missing a normative doc location would leave the code and published contract divergent. +- Reusing `GfxOpStatus` semantics by accident would weaken the service-boundary separation required by `DEC-0015`. +- Removing the legacy syscall contract incompletely could leave resolver or ABI ambiguity behind. diff --git a/discussion/workflow/plans/PLN-0023-composer-runtime-dispatch-and-legacy-removal.md b/discussion/workflow/plans/PLN-0023-composer-runtime-dispatch-and-legacy-removal.md new file mode 100644 index 00000000..70999ee8 --- /dev/null +++ b/discussion/workflow/plans/PLN-0023-composer-runtime-dispatch-and-legacy-removal.md @@ -0,0 +1,112 @@ +--- +id: PLN-0023 +ticket: frame-composer-public-syscall-surface +title: Plan - Composer Runtime Dispatch and Legacy Removal +status: accepted +created: 2026-04-17 +completed: +tags: [runtime, syscall, frame-composer, dispatch, migration] +--- + +## Objective + +Route the new public `composer.*` syscalls through `FrameComposer`, remove legacy `gfx.set_sprite` handling, and align runtime-side operational behavior with `DEC-0015`. + +## Background + +`DEC-0015` closes the public contract around `composer.*` and requires that `gfx.set_sprite` be removed completely rather than kept as a compatibility shim. The internal `FrameComposer` ownership model already exists from `DEC-0014` and plans `PLN-0017` through `PLN-0021`. + +## Scope + +### Included +- runtime syscall dispatch for `composer.*` +- operational mapping from syscall args to `FrameComposer` +- removal of legacy `gfx.set_sprite` runtime handling +- runtime-facing tests for composer-domain behavior + +### Excluded +- spec and ABI doc propagation +- cartridge/tooling migration +- final `make ci` closure + +## Execution Steps + +### Step 1 - Add runtime dispatch for `composer.*` + +**What:** +Teach VM runtime dispatch to call `FrameComposer` through the new public contract. + +**How:** +- Add dispatch arms for: + - `composer.bind_scene` + - `composer.unbind_scene` + - `composer.set_camera` + - `composer.emit_sprite` +- Parse arguments exactly as pinned by the HAL metadata. +- Return `ComposerOpStatus` for mutating composer-domain syscalls. + +**File(s):** +- `crates/console/prometeu-system/src/virtual_machine_runtime/dispatch.rs` +- any adjacent runtime helpers + +### Step 2 - Map operational outcomes cleanly onto `ComposerOpStatus` + +**What:** +Make runtime failures and normal outcomes reflect the new composer-domain status model. + +**How:** +- Bind runtime-side operational checks to status outcomes such as: + - scene bank unavailable + - bank invalid + - argument range invalid + - layer invalid + - sprite overflow if surfaced operationally +- Keep non-fatal overflow behavior aligned with `DEC-0015`. + +**File(s):** +- `crates/console/prometeu-system/src/virtual_machine_runtime/dispatch.rs` +- `crates/console/prometeu-hal/src/*` as needed for shared status meaning + +### Step 3 - Remove legacy `gfx.set_sprite` runtime support + +**What:** +Delete the old public runtime path for slot-style sprite submission. + +**How:** +- Remove dispatch support for `gfx.set_sprite`. +- Remove runtime assumptions about `active`, caller-provided indices, and legacy sprite ABI shape. +- Keep no private compatibility hook behind the public API. + +**File(s):** +- `crates/console/prometeu-system/src/virtual_machine_runtime/dispatch.rs` +- adjacent tests and public syscall references + +## Test Requirements + +### Unit Tests +- runtime dispatch returns `ComposerOpStatus` for bind, unbind, and emit operations +- `composer.set_camera` stores the minimal V1 camera coordinates correctly + +### Integration Tests +- a VM/runtime test can bind a scene, set camera, emit a sprite, reach `FRAME_SYNC`, and render through the canonical frame path +- public runtime behavior rejects removed `gfx.set_sprite` declarations/calls + +### Manual Verification +- inspect dispatch code to confirm all public orchestration now routes through `FrameComposer` rather than a legacy `gfx` sprite syscall path + +## Acceptance Criteria + +- [ ] Runtime dispatch supports all canonical `composer.*` syscalls. +- [ ] Mutating composer-domain calls return `ComposerOpStatus`. +- [ ] `gfx.set_sprite` is removed from runtime public handling. +- [ ] Runtime tests cover scene bind, camera set, sprite emit, and frame rendering through the public path. + +## Dependencies + +- Depends on `PLN-0022` +- Source decision: `DEC-0015` + +## Risks + +- Removing legacy handling before all runtime references are migrated can strand tests or bytecode fixtures. +- Poor `ComposerOpStatus` mapping could collapse useful operational distinctions into generic failures. diff --git a/discussion/workflow/plans/PLN-0024-composer-cartridge-tooling-and-regression-migration.md b/discussion/workflow/plans/PLN-0024-composer-cartridge-tooling-and-regression-migration.md new file mode 100644 index 00000000..1e5fb3a1 --- /dev/null +++ b/discussion/workflow/plans/PLN-0024-composer-cartridge-tooling-and-regression-migration.md @@ -0,0 +1,107 @@ +--- +id: PLN-0024 +ticket: frame-composer-public-syscall-surface +title: Plan - Composer Cartridge, Tooling, and Regression Migration +status: accepted +created: 2026-04-17 +completed: +tags: [runtime, bytecode, tooling, stress, regression, frame-composer] +--- + +## Objective + +Migrate bytecode declarations, cartridges, stress tooling, and regression coverage from legacy public sprite orchestration to the canonical `composer.*` surface. + +## Background + +`DEC-0015` requires the new public composer-domain ABI to land without leaving `gfx.set_sprite` as a fallback. That means the migration must cover the generated bytecode, test cartridges, and stress tooling that still assume the old public contract. + +## Scope + +### Included +- bytecode declaration updates for `composer.*` +- cartridge and stress generator migration +- regression coverage for the public composer-domain path +- removal of legacy syscall usage from test and tooling surfaces + +### Excluded +- canonical spec propagation +- runtime dispatch implementation +- final repository-wide CI closure + +## Execution Steps + +### Step 1 - Migrate declared syscall users and fixtures + +**What:** +Update code and fixtures that declare public syscalls so they target `composer.*`. + +**How:** +- Replace legacy public sprite syscall declarations with composer-domain declarations. +- Update ABI expectations in bytecode-related tests and fixtures. +- Ensure removal of `gfx.set_sprite` is reflected in any declaration validation snapshots. + +**File(s):** +- bytecode tests and fixtures +- syscall declaration users across runtime and tools + +### Step 2 - Migrate stress and cartridge tooling + +**What:** +Make the stress cartridge and related generators exercise the canonical public frame path. + +**How:** +- Update `pbxgen-stress` and any cartridge generators to declare and call `composer.*`. +- Replace legacy sprite-path usage with `composer.emit_sprite`. +- Add scene bind and camera usage where needed so the stress path reaches the real canonical pipeline. + +**File(s):** +- `crates/tools/pbxgen-stress/src/*` +- `test-cartridges/stress-console/*` +- related scripts such as `scripts/run-stress.sh` + +### Step 3 - Expand regression coverage around the public path + +**What:** +Lock the new public orchestration contract with regression tests. + +**How:** +- Add tests that cover: + - composer-domain declaration resolution + - public bind/unbind/camera/emit behavior + - scene rendering through the public path + - stress/tooling integration using `composer.*` +- Ensure no regression fixture still relies on removed `gfx.set_sprite`. + +**File(s):** +- runtime tests +- HAL syscall tests +- tooling tests where available + +## Test Requirements + +### Unit Tests +- bytecode and syscall declaration tests pin `composer.*` names and slot counts + +### Integration Tests +- stress or cartridge-facing tests exercise scene bind, camera set, and sprite emit through `composer.*` +- regression fixtures fail if `gfx.set_sprite` is reintroduced + +### Manual Verification +- inspect generated stress cartridge declarations and program behavior to confirm the public path is truly composer-domain based + +## Acceptance Criteria + +- [ ] Bytecode declarations and fixtures use `composer.*` instead of legacy public sprite orchestration. +- [ ] Stress tooling and test cartridges exercise the canonical public `FrameComposer` path. +- [ ] Regression coverage protects against fallback to `gfx.set_sprite`. + +## Dependencies + +- Depends on `PLN-0022` and `PLN-0023` +- Source decision: `DEC-0015` + +## Risks + +- Partial cartridge/tooling migration could leave the repository with hidden legacy public ABI usage. +- Stress tooling may appear to pass while still missing scene/camera coverage if it only migrates sprite calls. diff --git a/discussion/workflow/plans/PLN-0025-final-ci-validation-and-polish.md b/discussion/workflow/plans/PLN-0025-final-ci-validation-and-polish.md new file mode 100644 index 00000000..fd510d0d --- /dev/null +++ b/discussion/workflow/plans/PLN-0025-final-ci-validation-and-polish.md @@ -0,0 +1,96 @@ +--- +id: PLN-0025 +ticket: frame-composer-public-syscall-surface +title: Plan - Final CI Validation and Polish +status: accepted +created: 2026-04-17 +completed: +tags: [ci, validation, regression, polish] +--- + +## Objective + +Run the final repository validation path, including `make ci`, and perform the last compatibility, formatting, lint, and regression fixes required to close the composer-domain migration cleanly. + +## Background + +`DEC-0015` requires a coordinated migration across ABI, runtime, tooling, cartridges, spec, and documentation. After the implementation plans land, the repository still needs a final closure pass so no residual breakage survives in formatting, linting, tests, generated artifacts, or CI expectations. + +## Scope + +### Included +- final repository validation with `make ci` +- fixups required by formatting, lint, tests, snapshots, or generated artifacts +- final consistency pass across migrated files + +### Excluded +- introducing new contract changes beyond `DEC-0015` +- reopening ABI or service-boundary decisions + +## Execution Steps + +### Step 1 - Run the final validation entrypoint + +**What:** +Execute the repository’s final CI validation path. + +**How:** +- Run `make ci` after `PLN-0022`, `PLN-0023`, and `PLN-0024` are complete. +- Capture failures from formatting, lint, tests, coverage setup, generation steps, or artifact drift. + +**File(s):** +- repository-wide validation entrypoints + +### Step 2 - Apply closure fixes without reopening scope + +**What:** +Resolve residual breakage surfaced by final validation. + +**How:** +- Fix formatting and lint issues. +- Update snapshots or generated artifacts only where the migrated public contract requires it. +- Repair any remaining tests or documentation references that fail under `make ci`. +- Do not widen scope beyond the accepted composer-domain migration. + +**File(s):** +- any files directly implicated by final validation failures + +### Step 3 - Confirm final repository consistency + +**What:** +Leave the migration in a stable publishable state. + +**How:** +- Re-run `make ci` until it passes cleanly. +- Verify no legacy public `gfx.set_sprite` usage remains in code, tests, tooling, or docs. +- Confirm the worktree reflects only intended migration changes. + +**File(s):** +- repository-wide + +## Test Requirements + +### Unit Tests +- whatever unit coverage is exercised by `make ci` must remain green + +### Integration Tests +- repository integration coverage under `make ci` must pass after the migration + +### Manual Verification +- inspect the tree for residual `gfx.set_sprite` references and incomplete composer-domain propagation + +## Acceptance Criteria + +- [ ] `make ci` passes after the composer-domain migration family lands. +- [ ] Final fixups do not reopen contract scope beyond `DEC-0015`. +- [ ] No residual public `gfx.set_sprite` usage remains in the repository. + +## Dependencies + +- Depends on `PLN-0022`, `PLN-0023`, and `PLN-0024` +- Source decision: `DEC-0015` + +## Risks + +- If this final closure pass is skipped, small residual regressions can survive across formatting, lint, or generated artifacts even when the core implementation is correct. +- Late fixes can accidentally widen scope unless kept strictly bounded to validation fallout.