You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[finding] PluginSchema has zero runtime callers — kernel.use() admits any object with name + init + a semver, so the kernel's declared plugin contract is enforced nowhere #16133
Filed by the triage seat from a measurement the #15638 implementer handed back rather than filing blind (report 5555111376, dispatch instruction 5 — "the seat decides whether it becomes a card"). Every reading below was re-taken independently by triage on origin/main @ 932acc3d, 2026-09-06T02:48Z, and reproduces.
⛔ No remedy is prescribed and no shape is chosen — this card records the gap. ⛔ Triage does not claim, dispatch, write code or merge.
The finding
packages/spec/src/kernel/plugin.zod.ts declares PluginSchema with a closedtype set (CORE_PLUGIN_TYPES spread into an enum) and an authorable surface (kernel/Plugin:staticPath is in packages/spec/authorable-surface/kernel.json).
Nothing in production ever parses it.
reading
result
PluginSchema.parse / .safeParse call sites, all of packages/
2 files, both tests — packages/core/src/plugin-type-closed-set.test.ts, packages/spec/src/kernel/plugin.test.ts
CONTROL — ObjectSchema.parse / .safeParse call sites
14 files ⇒ runtime schema parsing exists in this repo; the zero is real
⚠️ The grep that makes this look live — read this before re-measuring
A bare git grep PluginSchema -- packages returns 20 hits and reads as a live symbol. It is not:
18 of them are a different, substring-colliding family in plugin-auth — buildOrganizationPluginSchema, buildJwtPluginSchema, buildTwoFactorPluginSchema, buildPhoneNumberPluginSchema, buildAdminPluginSchema, buildOauthProviderPluginSchema, buildDeviceAuthorizationPluginSchema. Every one of them contains the string PluginSchema and none of them is it.
2 are prose comments in packages/core/src/types.ts (:97, :127) — and :127 says "PluginSchema.type refuses it at parse", which is the claim this card measures as false in production, because that parse never runs.
⇒ Anyone re-checking this must grep the call (PluginSchema.parse / .safeParse), not the identifier.
The actual boot path, measured end to end
Every step read on main; no step inferred from a description.
plugins: z.array(z.unknown()).optional().describe('Plugins to load'),
z.unknown() — no refusal, no shape.
kernel.use() → PluginLoader.toPluginMetadata is a CAST, not a copy.packages/core/src/plugin-loader.ts, its own comment:
// Fix: Do not use object spread {...plugin} as it destroys the prototype chain for Class-based plugins. // Instead, cast the original object and inject default values if missing.
⇒ whatever the caller passed survives verbatim, plus a default version.
validatePluginStructure never reads type. The whole function:
if(!plugin.name)thrownewError('Plugin name is required');if(!plugin.init)thrownewError('Plugin init function is required');if(!this.isValidSemanticVersion(plugin.version))thrownewError(`Invalid semantic version: ${plugin.version}`);
Three checks. type is not among them, and neither is any other declared key.
⇒ The kernel's admission test is name + init + a parseable semver. Everything else PluginSchema declares — the closed type set included — is declared and enforced nowhere at runtime.
#15638 asked whether a legacy 'ui-plugin' arm in plugin-hono-server was dead code. Its premise was "PluginSchema refuses ui-plugin, so the arm is unreachable." The implementer measured the arm live — it mounts routes — and the reason is this card: there is no refusal because there is no parse.
⭐ The sharpest single reading, from the #15638 probe (same value, same run): defineStackaccepts a plugin declaring type: 'ui-plugin' while PluginSchema.safeParse on that same value returns success: false, code: 'invalid_value'. Two contracts, one value, opposite verdicts.
⇒ This is the ADR-0049 / Prime Directive #10 shape ("declared ≠ enforced") one level above#15638, and it is the root cause of that card's falsified premise. #15638's three candidate shapes (normalize-in-place, delete, or enforce at kernel.use()) all have to be read underneath the answer to this one.
⛔ What is NOT claimed
⛔ No severity beyond the grade below, and no remedy. Whether the repair is enforcing PluginSchema at kernel.use(), enforcing only the closed type set, tightening stack.zod.ts's z.unknown(), or accepting the looseness and retiring the schema's enforcement claims — is not decided here. Enforcing would begin refusing plugin objects the runtime accepts today, which is a contract decision with its own review.
⛔ kernel.use(plugin as any) is a shipped in-repo pattern (packages/cli/src/utils/schema-migrate.ts:346, :349), so even the TypeScript-level check is not universal on the boot path — recorded, not graded.
Dedupe
⚠️Stated honestly, not dressed up. Triage's search_issuesin:body channel is not trustworthy for absence in this repo (it has returned 0 for terms verifiably present), so ⛔ this card does not claim an exhaustive enumeration. What was done: the #15638 thread's own dedupe (4 adjacent cards — #14609, #10869, #15219, #14473 — none naming this), plus a label-filtered read of the open domain:engine / domain:cli backlog for a plugin-admission card, which found none. If a duplicate surfaces, close this one.
Refs
#15638 (the card whose premise this falsifies; its report 5555111376 carries the probe) · #14609 · ADR-0049 · Prime Directive #10
Triage's search_issuesin:body channel is not trustworthy for absence in this repo … ⛔ this card does not claim an exhaustive enumeration. What was done: the #15638 thread's own dedupe (4 adjacent cards) plus a label-filtered read of the open domain:engine / domain:cli backlog。
Filed by the triage seat from a measurement the #15638 implementer handed back rather than filing blind (report
5555111376, dispatch instruction 5 — "the seat decides whether it becomes a card"). Every reading below was re-taken independently by triage onorigin/main@932acc3d, 2026-09-06T02:48Z, and reproduces.⛔ No remedy is prescribed and no shape is chosen — this card records the gap. ⛔ Triage does not claim, dispatch, write code or merge.
The finding
packages/spec/src/kernel/plugin.zod.tsdeclaresPluginSchemawith a closedtypeset (CORE_PLUGIN_TYPESspread into an enum) and an authorable surface (kernel/Plugin:staticPathis inpackages/spec/authorable-surface/kernel.json).Nothing in production ever parses it.
PluginSchema.parse/.safeParsecall sites, all ofpackages/packages/core/src/plugin-type-closed-set.test.ts,packages/spec/src/kernel/plugin.test.tsObjectSchema.parse/.safeParsecall sitesA bare
git grep PluginSchema -- packagesreturns 20 hits and reads as a live symbol. It is not:plugin-auth—buildOrganizationPluginSchema,buildJwtPluginSchema,buildTwoFactorPluginSchema,buildPhoneNumberPluginSchema,buildAdminPluginSchema,buildOauthProviderPluginSchema,buildDeviceAuthorizationPluginSchema. Every one of them contains the stringPluginSchemaand none of them is it.packages/core/src/types.ts(:97,:127) — and:127says "PluginSchema.typerefuses it at parse", which is the claim this card measures as false in production, because that parse never runs.⇒ Anyone re-checking this must grep the call (
PluginSchema.parse/.safeParse), not the identifier.The actual boot path, measured end to end
Every step read on
main; no step inferred from a description.Authoring boundary declares nothing.
packages/spec/src/stack.zod.ts:724z.unknown()— no refusal, no shape.kernel.use()→PluginLoader.toPluginMetadatais a CAST, not a copy.packages/core/src/plugin-loader.ts, its own comment:⇒ whatever the caller passed survives verbatim, plus a default version.
validatePluginStructurenever readstype. The whole function:Three checks.
typeis not among them, and neither is any other declared key.⇒ The kernel's admission test is
name+init+ a parseable semver. Everything elsePluginSchemadeclares — the closedtypeset included — is declared and enforced nowhere at runtime.Why this is a card and not a note on #15638
#15638 asked whether a legacy
'ui-plugin'arm inplugin-hono-serverwas dead code. Its premise was "PluginSchemarefusesui-plugin, so the arm is unreachable." The implementer measured the arm live — it mounts routes — and the reason is this card: there is no refusal because there is no parse.⭐ The sharpest single reading, from the #15638 probe (same value, same run):
defineStackaccepts a plugin declaringtype: 'ui-plugin'whilePluginSchema.safeParseon that same value returnssuccess: false, code: 'invalid_value'. Two contracts, one value, opposite verdicts.⇒ This is the ADR-0049 / Prime Directive #10 shape ("declared ≠ enforced") one level above #15638, and it is the root cause of that card's falsified premise. #15638's three candidate shapes (normalize-in-place, delete, or enforce at
kernel.use()) all have to be read underneath the answer to this one.⛔ What is NOT claimed
PluginSchemaatkernel.use(), enforcing only the closedtypeset, tighteningstack.zod.ts'sz.unknown(), or accepting the looseness and retiring the schema's enforcement claims — is not decided here. Enforcing would begin refusing plugin objects the runtime accepts today, which is a contract decision with its own review.plugin-hono-serverstill accepts the legacyui-plugintype thatPluginSchemarefuses — an unreachable arm under ADR-0049 #15638 round measured thatstaticPathandtype: 'ui'have zero in-repo producers (6staticPathhits, all of them the hono arm itself, two generated JSON baselines, and the declaration) — so the population this seam serves is authored outside this repo and was not surveyed.PluginSchema, which is where the [finding]plugin-hono-serverstill accepts the legacyui-plugintype thatPluginSchemarefuses — an unreachable arm under ADR-0049 #15638 measurement crossed it.kernel.use(plugin as any)is a shipped in-repo pattern (packages/cli/src/utils/schema-migrate.ts:346,:349), so even the TypeScript-level check is not universal on the boot path — recorded, not graded.Dedupe
search_issuesin:bodychannel is not trustworthy for absence in this repo (it has returned 0 for terms verifiably present), so ⛔ this card does not claim an exhaustive enumeration. What was done: the #15638 thread's own dedupe (4 adjacent cards — #14609, #10869, #15219, #14473 — none naming this), plus a label-filtered read of the opendomain:engine/domain:clibacklog for a plugin-admission card, which found none. If a duplicate surfaces, close this one.Refs
#15638 (the card whose premise this falsifies; its report
5555111376carries the probe) · #14609 · ADR-0049 · Prime Directive #10