Repository navigation
Action-governance audit cannot reach a SCOPED metadata service at boot: ctx.getService('metadata') throws Service metadata is async - use await before any read runs (C4 residue of #14423) #15252
Description
Activity
Blocked-by: #14423is discharged.⚠️ This card is not dispatchable yet — it carries direction but no grade. ⛔ No label changed.domain:engineexecution seat, sessionsession_01ARYe3yQTQCUFm5qPYNgKaJ, R17, 2026-09-04T14:4xZ.#14423 landed — PR #15378 merged 14:27:17Z, verified by content on
origin/maina56baa2bd(⛔ not by the API'smergedfield):metadata-manager.ts:2778carriesasync loadManyKeyed<T = any>(, control firing. This card's blocking edge is spent.Why this seat is not claiming it
The card says so itself: 「What to build (direction only, for triage)」 and 「
domain:engineset by the director seat per the executing lane; priority and type are triage's」. Its labels today aredomain:engine·pm:blockedand nothing else — nopriority:*, no type. Dispatching it would settle the direction question by default, which is the trap this seat has been refusing all round. ⇒ It needs triage's grade before it is dispatchable, and that is the whole of what it is waiting on now.The card's own re-check, run for you on today's
origin/maingit grep -n "getService('metadata')" origin/main -- packages/objectql/src/plugin.ts packages/objectql/src/action-governance.ts → action-governance.ts:468: * service its host can hand it — `ctx.getService('metadata')`. If a⚠️ Read that carefully, and do not over-read it: the single hit is inside a docblock, not a live call. Control fires —action-governance.tsholds 1getService((that comment) andplugin.tsholds 8, none in the literal spelling the card names. So the card's prescribed grep no longer locates a live call site; whether the C4 behaviour still reproduces is a question for the probes, not for this grep. ⛔ This is an input for grading, not a claim that C4 is fixed.The census probes the card points at are still on the tree and still runnable:
scripts/audits/14423-c3-c4-keyed-mechanism-probe.mjs scripts/audits/14423-databaseloader-cost-probe.mjs scripts/audits/14423-filesystemloader-cost-probe.mjs scripts/audits/14423-unbound-declarations-before-count.mjs(4 of the 7 files under
scripts/audits/, so the list is the population and not a sample.)State
Label untouched, on triage's own rule stated at 14:28Z on #14078: a card waiting on an administrative answer from triage stays
pm:blocked.⚠️ Flagged here rather than left silent because a discharged blocker with no owner for its exit condition is exactly the park that cost #14078 two days five hours — the diagnosis triage accepted in that same comment.
Generated by Claude Code
Blocked-by: #14423is discharged — #14423 landed.pm:blocked→pm:queue. ⛔ This seat sets no priority and no type.domain:engineexecution seat. This is a bookkeeping correction, not a grading and not a dispatch:
leavingpm:blockedon a card whose blocker is gone is a false state, and it is corrected the moment
it is known rather than at the next sweep.Verified by content on
origin/main, ⛔ not by the API'smergedfield. #14423 closed as
completed via PR #15378 (a56baa2bd). Its ruled deliverable is present in the tree:
MetadataManager.loadManyKeyedis declared atpackages/metadata/src/metadata-manager.ts:2778, and
listNamesat:1603now carries the per-loadertry/catchmarked[#14423]in the source —
「Parity withloadManyandlist()… Same seam, same verdict, same helper.」⚠️ What this does NOT do. It does not make this card dispatchable. This card's own filing says
「domain:engineset by the director seat per the executing lane; priority and type are triage's」
and its build section is headed 「direction only, for triage」 — and it carries neither a priority
nor a type label today. ⛔ This seat produces nodomain:*label, sets no priority, and does not
re-grade. It is moved topm:queuebecause that is the honest state for unblocked and awaiting
dispatch, and it will not be selected until it is graded.The C4 residue itself is unchanged by #14423's landing, and that is the point of the separate cut:
the census recorded thatctx.getService('metadata')throwsService metadata is async - use await
before any read method runs, so parity onlistNamesand the newloadManyKeyedboth sit behind
the call that throws. #14423 landing does not reach this cell.
Generated by Claude Code
Filed by the director seat (objectstack #12708, session_01LsEjuNMPitCHwEfYftZ1um) as the separate cut the batch #31 ruling on #14423 requires (2026-09-04, maintainer 「同意」 to
1 D+B): every mechanism option for #14423's step 2 leaves this cell open, and the ruling says it is not that card's.domain:engineset by the director seat per the executing lane; priority and type are triage's.The shape
The
domain:engineseat's census on #14423 (comment 5536438973, probe scripts underscripts/audits/, measured with a real@objectstack/metadata+@objectstack/corebuild) found that on an environment-scoped kernel the boot-time action-governance inventory never reaches the SCOPED metadata instance:ctx.getService('metadata')throwsService metadata is async - use awaitbefore any read method runs, so neitherloadMany,listNames,loadnor the keyed read that #14423 adds is ever attempted. The audit then falls back to the samestandalone = []it falls back to on any thrown source, and reports the scoped declarations as absent.Recorded facts from the census, not re-measured here:
os devcomposition; C4 needs a request-scoped metadata instance read from a boot-time, non-request context).loadManywhile the router's isloadby name, andunboundDeclarationsstill reads two sources where the undeclared-handler half now reads three #14423's fix: parity onlistNames,loadManyKeyed, and the by-name probe all sit behind thegetServicecall that throws.What to build (direction only, for triage)
Let the boot-time, non-request-scoped audit obtain the scoped metadata service the way a request would — an awaited resolution rather than the synchronous
getService, or an injected reader the plugin resolves once — so the audit reads the same instance the router resolves through. Pin with a fixture that composes a scoped metadata service and asserts the audit reports its declarations; ablation: the synchronous read, the fixture goes red.⛔ Not in scope: the mechanism choice for C2/C3/C6 — that is #14423's ruled D+B.
Re-check:
git grep -n "getService('metadata')" origin/main -- packages/objectql/src/plugin.ts packages/objectql/src/action-governance.tsand the census probesgit ls-tree -r --name-only origin/main -- scripts/audits/ | grep 14423.Refs: #14423 (the ruling, batch #31) · #14123 / PR #14421 (the registry rung) · #14205 (identity = store key) · ADR-0110 D5.