171 lines
9.1 KiB
Markdown
171 lines
9.1 KiB
Markdown
---
|
|
id: AGD-0031
|
|
ticket: studio-frame-composer-syscall-and-sprite-alignment
|
|
title: Studio Alignment with Runtime FrameComposer Syscalls and Sprite Composition
|
|
status: in_progress
|
|
created: 2026-04-18
|
|
resolved: 2026-04-18
|
|
decision: DEC-0027
|
|
tags:
|
|
- studio
|
|
- compiler
|
|
- pbs
|
|
- stdlib
|
|
- runtime-alignment
|
|
- abi
|
|
- syscall
|
|
- frame-composer
|
|
- sprites
|
|
---
|
|
|
|
## Pain
|
|
|
|
The sibling runtime has already moved the public frame-orchestration ABI to `composer.*`.
|
|
|
|
This repository still exposes the old model through `@sdk:gfx` and `Gfx.set_sprite`, which means:
|
|
|
|
- the Studio-side compiler and stdlib still teach a legacy public contract;
|
|
- PBS examples and tests still lower sprite composition through the wrong owner;
|
|
- specs still describe a source surface that no longer matches the runtime's canonical syscall boundary;
|
|
- any new Studio work risks reinforcing a dual contract between `gfx.*` primitives and `composer.*` frame orchestration.
|
|
|
|
The user explicitly scoped this discussion to:
|
|
|
|
- ABI/syscall alignment with the current `../runtime`;
|
|
- `FrameComposer` convergence for sprite composition;
|
|
- Studio-side propagation across `compiler`, `pbs`, and `stdlib`;
|
|
- `@sdk:composer` for the sprite-composition path;
|
|
- removal of the legacy `Gfx.set_sprite` entrypoint;
|
|
- no scene-bank implementation work in this ticket.
|
|
|
|
## Context
|
|
|
|
Domain owner: `studio`
|
|
|
|
Primary affected subdomains:
|
|
|
|
- `compiler/pbs`
|
|
- `studio`
|
|
|
|
Expected propagation targets if this discussion closes:
|
|
|
|
- `docs/specs/compiler-languages/pbs`
|
|
- `docs/specs/compiler`
|
|
- PBS stdlib resources under `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/resources/stdlib`
|
|
- compiler/frontend/backend conformance tests
|
|
- Studio-adjacent examples and fixtures that still import `@sdk:gfx` for sprite composition
|
|
|
|
Observed current state on 2026-04-18:
|
|
|
|
- `../runtime` lesson `DSC-0026` locks `FrameComposer` as the canonical frame owner above the render backend.
|
|
- `../runtime` lesson `DSC-0027` locks the public VM-facing syscall ABI to `composer.bind_scene`, `composer.unbind_scene`, `composer.set_camera`, and `composer.emit_sprite`, and removes the legacy public `gfx.set_sprite` path.
|
|
- `../runtime` lesson `DSC-0028` keeps immediate/debug primitives such as `gfx.draw_text` outside canonical game composition as a deferred overlay path.
|
|
- this repository still ships `@sdk:gfx` with `LowGfx.set_sprite(...)` and `Gfx.set_sprite(...)`;
|
|
- this repository does not yet expose a reserved `@sdk:composer` module;
|
|
- docs and tests still use `@sdk:gfx` as the visible source surface for sprite composition.
|
|
|
|
This creates architectural drift:
|
|
|
|
- runtime public ownership says `composer.*` for frame composition;
|
|
- Studio-side language and stdlib surfaces still say `gfx.*` for part of that same behavior.
|
|
|
|
The drift is specifically about syscall and sprite-composer alignment.
|
|
|
|
Out of scope for this agenda:
|
|
|
|
- `composer.bind_scene`, `composer.unbind_scene`, and `composer.set_camera` rollout in Studio;
|
|
- scene-bank authoring workflows;
|
|
- scene asset import/editor design;
|
|
- scene bank build/materialization contracts beyond what is minimally needed to name ABI boundaries;
|
|
- broader scene workspace/product decisions already separated into other discussions.
|
|
|
|
## Open Questions
|
|
|
|
- [x] Studio should expose a new reserved module `@sdk:composer` as the canonical public source surface for sprite composition.
|
|
- [x] `@sdk:gfx` should remain limited to primitive/overlay/back-end-adjacent operations once sprite composition moves out.
|
|
- [x] PBS should export `@sdk:composer` using the same source-level shape already used by `@sdk:gfx`: low-level host owner plus public service facade.
|
|
- [x] Mutating composer operations should remain raw `int` status returns in v1 for now.
|
|
- [x] Tests, fixtures, examples, and callsites should all migrate in this wave if possible; no compatibility path should be preserved.
|
|
- [x] No temporary compatibility alias is acceptable; `Gfx.set_sprite` should be removed completely.
|
|
|
|
## Options
|
|
|
|
### Option A - Introduce `@sdk:composer` now for sprite emission only in this wave
|
|
- **Approach:** Add a dedicated reserved stdlib module that exposes the sprite-composition path through `composer.emit_sprite`; migrate sprite composition calls, host metadata, docs, and tests to that module; keep `@sdk:gfx` for primitives/overlay-style operations only; defer Studio-side `bind_scene`, `unbind_scene`, and `set_camera`.
|
|
- **Pro:** Matches the runtime's canonical service boundary, preserves the split between frame composition and render primitives, and avoids teaching the retired `gfx.set_sprite` contract.
|
|
- **Con:** Introduces a partial first wave of the `composer` domain, so docs must be explicit that other composer operations are intentionally deferred rather than absent by accident.
|
|
- **Maintainability:** Strong, because the public source surface mirrors the actual runtime ABI and ownership model.
|
|
|
|
### Option B - Keep `@sdk:gfx` as the user-facing module and only retarget its internals to `composer.*`
|
|
- **Approach:** Preserve the visible `Gfx.set_sprite` API in Studio while changing lowering metadata underneath to hit `composer.emit_sprite`.
|
|
- **Pro:** Smaller immediate source churn in examples and tests.
|
|
- **Con:** Encodes the wrong owner in the public teaching surface, preserves the exact dual-contract problem the runtime discussion just removed, and makes later cleanup harder.
|
|
- **Maintainability:** Weak, because it keeps historical naming instead of canonical service ownership.
|
|
|
|
### Option C - Add `@sdk:composer` but retain temporary `Gfx.set_sprite` compatibility in parallel
|
|
- **Approach:** Introduce the new canonical module while leaving `Gfx.set_sprite` as an alias or transitional wrapper for one or more waves.
|
|
- **Pro:** Softens migration pressure for existing examples and downstream users.
|
|
- **Con:** Creates two public ways to express the same operation, invites drift in specs/tests/docs, and conflicts with the runtime lesson that legacy public fallbacks should be removed when they preserve the wrong model.
|
|
- **Maintainability:** Medium at best in the short term, poor in the long term if the alias survives longer than intended.
|
|
|
|
## Discussion
|
|
|
|
The runtime side has already made two architectural facts explicit:
|
|
|
|
1. frame orchestration belongs to `FrameComposer`, not to `Gfx`;
|
|
2. the public syscall namespace must reflect that ownership.
|
|
|
|
That means this repository is no longer choosing between equivalent naming styles.
|
|
|
|
It is choosing whether Studio will:
|
|
|
|
- align its source-facing contracts with the canonical runtime boundary; or
|
|
- preserve a legacy public façade that the runtime has already declared misleading.
|
|
|
|
The user's scope also matters.
|
|
|
|
This ticket is not asking for scene-bank product work, and it also is not asking for Studio-side scene binding or camera rollout.
|
|
So the migration target should stay narrow:
|
|
|
|
- syscall/domain alignment;
|
|
- `@sdk:composer` surface alignment for sprite emission;
|
|
- compiler/PBS/stdlib propagation;
|
|
- tests and examples updated to stop asserting the retired path.
|
|
- removal of the old `Gfx.set_sprite` path.
|
|
|
|
The remaining design work is therefore smaller and more concrete:
|
|
|
|
- define the Studio-side shape of `@sdk:composer` for sprite emission;
|
|
- propagate `composer.emit_sprite` through stdlib, specs, compiler, and tests;
|
|
- keep the deferred composer calls explicitly out of this ticket so the repository does not accidentally mix sprite convergence with unfinished scene-facing rollout.
|
|
|
|
The agenda questions are now resolved with explicit user direction:
|
|
|
|
1. `@sdk:composer` should follow the same editorial pattern already used by `@sdk:gfx`, meaning a low-level host owner plus a public service facade.
|
|
2. `composer.emit_sprite` should continue returning a raw `int` status in this wave.
|
|
3. Migration should be broad and immediate across tests, fixtures, and examples where feasible.
|
|
4. `Gfx.set_sprite` should be removed entirely, with no compatibility alias or dual-path surface.
|
|
5. Specs should document only what this wave actually implements, while leaving room for `bind_scene`, `unbind_scene`, and `set_camera` to be added later using the same pattern.
|
|
|
|
## Resolution
|
|
|
|
Recommended direction:
|
|
|
|
- adopt Option A as the working direction for this discussion;
|
|
- open a Studio-side canonical `@sdk:composer` surface aligned to the runtime ABI for sprite emission in this wave;
|
|
- retire `Gfx.set_sprite` from normative Studio-facing contracts instead of preserving a compatibility façade;
|
|
- defer `composer.bind_scene`, `composer.unbind_scene`, and `composer.set_camera` to a later ticket;
|
|
- keep scene-bank authoring/editor work explicitly out of this ticket;
|
|
- keep `@sdk:gfx` focused on primitive and overlay-style operations.
|
|
|
|
Recommended next step:
|
|
|
|
- treat the sprite-only `@sdk:composer` wave as the accepted scope of this agenda;
|
|
- write a decision that locks:
|
|
- `@sdk:composer` as the canonical Studio-side sprite-composition module;
|
|
- the `LowComposer` + `Composer` shape matching the established `@sdk:gfx` pattern;
|
|
- raw `int` status returns for this wave;
|
|
- complete removal of `Gfx.set_sprite` with no compatibility path;
|
|
- broad propagation across specs, stdlib, compiler, tests, fixtures, and examples;
|
|
- deferred addition of `bind_scene`, `unbind_scene`, and `set_camera` in later work.
|