Measured on a real boot while root-causing the #7526 parity failure on PR #12348 (booted showcase stack, bootStack(showcaseStack), authenticated as the dev admin):
POST /api/v1/actions/_activation/showcase_task/showcase_mark_done {"enabled": false}
-> 503 SERVICE_UNAVAILABLE
"Cannot disable packaged action 'showcase_mark_done' — no activation ledger is attached to this
engine (sys_metadata_activation, ADR-0126 §4), so the flip could not be made durable and would
silently revert on the next restart."
The refusal itself is the DESIGNED behaviour and is working: ADR-0126 §6 wall 3 says a flip that cannot be made durable must not be reported as one, so the door refuses loudly and names the remedy instead of keeping an in-process bit that reverts on restart.
The gap
sys_metadata_activation is declared in packages/platform-objects, but the only thing that REGISTERS it today is the automation service plugin's manifest (registerRunObject, alongside sys_automation_run and sys_flow_dispatch) — because flows were the ledger's first and, until #12348, only consumer. Actions are now a second consumer with a different owner: the consult and the write path live on the ObjectQL engine, which is present in every composition that can execute an action, automation service or not.
So in a deployment that has actions and no automation service, packaged-action disable is unavailable — visibly (503 on the flip, a warn at boot naming the same cause), never silently, but unavailable.
Why it was not fixed inside #12348
Where the shared object gets registered is a decision that reaches beyond the action leg:
- registering it from
ObjectQLPlugin adds an @objectstack/objectql -> @objectstack/platform-objects dependency, which inverts the tiering (platform-objects is a catalog the engine serves); - registering it from
PlatformObjectsPlugin — where the object is declared, beside SysMigration / SysMigrationJournal / SysSecret — is the natural home, but it would then be registered by two manifests in any deployment that also runs automation, and object ownership is governed (ADR-0029 D7 contributor kinds). Whether that double registration is benign was not measured; - doing nothing is defensible for now: most real deployments run automation, and the failure mode is loud.
That is a judgement about the ledger's ownership shared by the flow leg and every future Regime C consumer (ADR-0126 §8 pre-charts tool, skill, position), so it is filed rather than decided inside an implementation card.
Reproducing
packages/qa/dogfood boots exactly this composition. bootStack(showcaseStack) + a POST to the activation door reproduces the 503 in about 25 seconds.
Refs: PR #12348 · #12160 · #12296 (the flow leg that registers the object today) · ADR-0126 §4/§6 · ADR-0029 D7
Generated by Claude Code
Measured on a real boot while root-causing the #7526 parity failure on PR #12348 (booted showcase stack,
bootStack(showcaseStack), authenticated as the dev admin):The refusal itself is the DESIGNED behaviour and is working: ADR-0126 §6 wall 3 says a flip that cannot be made durable must not be reported as one, so the door refuses loudly and names the remedy instead of keeping an in-process bit that reverts on restart.
The gap
sys_metadata_activationis declared inpackages/platform-objects, but the only thing that REGISTERS it today is the automation service plugin's manifest (registerRunObject, alongsidesys_automation_runandsys_flow_dispatch) — because flows were the ledger's first and, until #12348, only consumer. Actions are now a second consumer with a different owner: the consult and the write path live on the ObjectQL engine, which is present in every composition that can execute an action, automation service or not.So in a deployment that has actions and no automation service, packaged-action disable is unavailable — visibly (503 on the flip, a
warnat boot naming the same cause), never silently, but unavailable.Why it was not fixed inside #12348
Where the shared object gets registered is a decision that reaches beyond the action leg:
ObjectQLPluginadds an@objectstack/objectql->@objectstack/platform-objectsdependency, which inverts the tiering (platform-objects is a catalog the engine serves);PlatformObjectsPlugin— where the object is declared, besideSysMigration/SysMigrationJournal/SysSecret— is the natural home, but it would then be registered by two manifests in any deployment that also runs automation, and object ownership is governed (ADR-0029 D7 contributor kinds). Whether that double registration is benign was not measured;That is a judgement about the ledger's ownership shared by the flow leg and every future Regime C consumer (ADR-0126 §8 pre-charts
tool,skill,position), so it is filed rather than decided inside an implementation card.Reproducing
packages/qa/dogfoodboots exactly this composition.bootStack(showcaseStack)+ a POST to the activation door reproduces the 503 in about 25 seconds.Refs: PR #12348 · #12160 · #12296 (the flow leg that registers the object today) · ADR-0126 §4/§6 · ADR-0029 D7
Generated by Claude Code