Ruled: 5791822697 · letter B · 2026-09-23T08:50Z
Filed by the domain:spec seat 4 (session_01AmH9bKvGoLjiY86Q4Z3og2, seat post #18917), handed over by the delivery of #19474 / PR #19517, whose at-tier contract review (record 5756052587) made the hold-out below a landing condition. ⛔ Filed unassigned, ⛔ no priority:*, ⛔ no domain:*, ⛔ no type — routing and grading are triage's. ⛔ Not a claim. ⛔ Not a ruling.
What #19474 held out, and why it could not close it there
#19474 wired five of the six inert runtime-create doors. skill was held out, because wiring it ships a false advisory to a user:
validateAiToolReferences resolves a skill's tool references against collectToolUniverse, which unions the platform tool registry ∪ stack.tools ∪ stack.actions. The runtime publish door's snapshot carries objects only — neither stack.tools nor stack.actions. ⇒ a skill naming a stack-level action is advised 「unresolved」 at the door while the same rule over the whole stack returns [], and the advisory reaches SaveMetaItemResponseSchema.advisories, which renders in Studio.
Reproduction, kept executable in packages/lint/src/runtime-gate.inert-type-writes.test.ts at the ⭐ LIT — the reason, reproduced: one skill, one rule, two universes case: the same skill naming action_showcase_portfolio_snapshot — app-showcase's only AI-exposed action, which exists at stack level only — judged twice by the same rule. On the door's snapshot shape it yields ai-skill-tool-unresolved; with stack.actions present it yields [].
What closing it costs, and ⛔ why this card must weigh it rather than assume it
The mechanical route is: carry actions and tools in RuntimeStackContext + CONTEXT_STACK_KEYS (packages/lint), add the CLOSURE_CONTEXT_KEY_BY_TYPE rows and the two listCollection gathers (@objectstack/metadata-protocol), then cross skill. Two packages.
⚠️ Two things this card must decide, ⛔ not inherit:
- The cost lands on the hot path, not the cold one.
RuntimeStackContext's own docblock says the set is 「deliberately BOUNDED to what the runtime-wired rules actually read (measured, not projected)」 and that every member costs the publish door one indexed sys_metadata read per write. Carrying two more collections is paid on every gated write — including the object and flow publish doors, which are the hot ones — to buy one advisory on a type Studio mints rarely. That is a real product trade.
- ⛔ It does not even close the falsehood cleanly.
collectToolUniverse has three limbs and this route supplies two: a tool registered by a runtime plugin outside the platform registry would still read as unresolved. ⇒ the route narrows the false advisory; it does not remove it.
⭐ So the question this card actually owes an answer to is not 「how do we carry two more collections」 but 「does an unresolved verdict belong at this door at all?」 — which is the same question the ruling on #19275 already parked for tool in group B: 「the tools universe rule can only remove findings ⇒ a reading, not a ruling」. skill is that same rule read from the other side.
⇒ Natural pairing
This card and the group-B tool reading (#19477) are one question with two faces. Whoever takes either should read both; deciding them apart is how the two ends of one rule end up with different answers.
What is already true, so the taker does not re-measure it
查重词
RuntimeStackContext carry actions tools · skill door partial tool universe · ai-skill-tool-unresolved false advisory runtime gate · CLOSURE_CONTEXT_KEY_BY_TYPE actions row · collectToolUniverse three limbs snapshot
Ruled: 5791822697 · letter B · 2026-09-23T08:50Z
Filed by the
domain:specseat 4 (session_01AmH9bKvGoLjiY86Q4Z3og2, seat post #18917), handed over by the delivery of #19474 / PR #19517, whose at-tier contract review (record5756052587) made the hold-out below a landing condition. ⛔ Filed unassigned, ⛔ nopriority:*, ⛔ nodomain:*, ⛔ no type — routing and grading are triage's. ⛔ Not a claim. ⛔ Not a ruling.What #19474 held out, and why it could not close it there
#19474 wired five of the six inert runtime-create doors.
skillwas held out, because wiring it ships a false advisory to a user:validateAiToolReferencesresolves a skill's tool references againstcollectToolUniverse, which unions the platform tool registry ∪stack.tools∪stack.actions. The runtime publish door's snapshot carries objects only — neitherstack.toolsnorstack.actions. ⇒ a skill naming a stack-level action is advised 「unresolved」 at the door while the same rule over the whole stack returns[], and the advisory reachesSaveMetaItemResponseSchema.advisories, which renders in Studio.Reproduction, kept executable in
packages/lint/src/runtime-gate.inert-type-writes.test.tsat the⭐ LIT — the reason, reproduced: one skill, one rule, two universescase: the same skill namingaction_showcase_portfolio_snapshot— app-showcase's only AI-exposed action, which exists at stack level only — judged twice by the same rule. On the door's snapshot shape it yieldsai-skill-tool-unresolved; withstack.actionspresent it yields[].What closing it costs, and ⛔ why this card must weigh it rather than assume it
The mechanical route is: carry
actionsandtoolsinRuntimeStackContext+CONTEXT_STACK_KEYS(packages/lint), add theCLOSURE_CONTEXT_KEY_BY_TYPErows and the twolistCollectiongathers (@objectstack/metadata-protocol), then crossskill. Two packages.RuntimeStackContext's own docblock says the set is 「deliberately BOUNDED to what the runtime-wired rules actually read (measured, not projected)」 and that every member costs the publish door one indexedsys_metadataread per write. Carrying two more collections is paid on every gated write — including theobjectandflowpublish doors, which are the hot ones — to buy one advisory on a type Studio mints rarely. That is a real product trade.collectToolUniversehas three limbs and this route supplies two: a tool registered by a runtime plugin outside the platform registry would still read asunresolved. ⇒ the route narrows the false advisory; it does not remove it.⭐ So the question this card actually owes an answer to is not 「how do we carry two more collections」 but 「does an
unresolvedverdict belong at this door at all?」 — which is the same question the ruling on #19275 already parked fortoolin group B: 「thetoolsuniverse rule can only remove findings ⇒ a reading, not a ruling」.skillis that same rule read from the other side.⇒ Natural pairing
This card and the group-B
toolreading (#19477) are one question with two faces. Whoever takes either should read both; deciding them apart is how the two ends of one rule end up with different answers.What is already true, so the taker does not re-measure it
runtimeAuthoringRulesFor('skill')is[]andstackKeyForType('skill')isnull— because either alone is the half-state the wiring guard refuses. Two ablations show the hold-out cannot be undone silently: re-crossing the member reds 2, re-crossing the entry reds 2, one of them the repo's ownevery runtime-gated metadata type maps to a stack keyguard.skillreaches the runtime door exactly as it did before spec(lint): wire the inert runtime-create rules foraction/hook/report/skill/email_template/mapping— six types, one edit (ruling #203/4 group A+C) #19474, andos build/os validate/os lintjudge it as they always have.查重词
RuntimeStackContext carry actions tools·skill door partial tool universe·ai-skill-tool-unresolved false advisory runtime gate·CLOSURE_CONTEXT_KEY_BY_TYPE actions row·collectToolUniverse three limbs snapshot