prometeu-runtime/discussion/lessons/DSC-0027-frame-composer-public-syscall-surface/LSN-0032-public-abi-must-follow-the-canonical-service-boundary.md
bQUARKz 73cf96ed6c
All checks were successful
Intrepid/Prometeu/Runtime/pipeline/pr-master This commit looks good
housekeep
2026-04-18 16:31:23 +01:00

2.9 KiB

id ticket title created tags
LSN-0032 frame-composer-public-syscall-surface Public ABI Must Follow the Canonical Service Boundary 2026-04-18
gfx
runtime
syscall
abi
frame-composer
scene
camera
sprites

Context

DSC-0026 finished the internal migration to FrameComposer as the canonical frame-orchestration owner, but the public VM-facing ABI still exposed part of that behavior through legacy gfx-domain calls. That left the codebase with a mismatch between the real runtime ownership model and the surface visible to cartridges, tooling, and syscall declarations.

DSC-0027 closed that gap by introducing the composer.* public domain and removing the old public sprite path.

Key Decisions

Public Syscalls Must Expose the Real Owner

What: Scene binding, camera control, and sprite emission now live under composer.*, and the legacy public gfx.set_sprite path is gone.

Why: Once FrameComposer became the canonical orchestration service, keeping public orchestration under gfx.* would preserve the wrong mental model and encourage callers to treat the render backend as the owner of frame policy.

Trade-offs: This forces migration across ABI declarations, runtime dispatch, tests, and tooling, but it removes the long-term cost of a misleading public boundary.

Domain-Specific Status Types Preserve Architectural Meaning

What: Mutating public composer operations return ComposerOpStatus instead of reusing backend-oriented status naming.

Why: Operational outcomes for scene binding or sprite emission are not backend-domain results. Reusing GfxOpStatus would blur the boundary that the migration was trying to make explicit.

Trade-offs: This adds one more status family to maintain, but it keeps the public ABI semantically aligned with the actual service contract.

Patterns and Algorithms

  • Promote internal ownership changes into the public ABI as part of the same migration thread.
  • Use syscall domains to encode service boundaries, not just namespace aesthetics.
  • Remove obsolete public fallbacks completely when they preserve the wrong operational model.
  • Keep runtime dispatch, bytecode declarations, and tooling aligned so the public path is exercised end to end.

Pitfalls

  • Leaving a legacy public syscall alive after the internal model changes creates a dual-contract system that is harder to remove later.
  • Migrating runtime dispatch without migrating declarations and tooling can leave hidden ABI drift in tests and generators.
  • Reusing backend-specific status names in the wrong domain quietly leaks old ownership assumptions into new APIs.

Takeaways

  • The public ABI should mirror the canonical service boundary, not historical implementation leftovers.
  • Namespace changes are architectural when they change who is responsible for a behavior.
  • Removing a legacy public entrypoint is often safer than preserving a compatibility shim that encodes the wrong model.