Skip to content

[finding] hono UI auto-discovery: the slug-from-name fallback and the staticPath guard are unreachable through kernel.use() once PluginSchema requires both keys (#16334) #16599

Description

@huangyiirene

Observation from #16334 (spec half of #16049), filed unassigned. Sub-issue of #15638 because it is the same block and the same class — an arm of the auto-discovery block in packages/plugins/plugin-hono-server/src/hono-plugin.ts (around line 508) that no object can reach any more.

What is dead, and since when

Evidence. The two pins that exercised those branches through the real kernel — "derives the slug from the last path segment of the plugin name when none is declared" and "a ui type with no staticPath mounts nothing" in src/ui-plugin-auto-discovery.pin.test.ts — had to be inverted into refusal pins on the #16334 PR (#16598): with the schema tightened, kernel.use() throws PLUGIN_CONTRACT_VIOLATION … at 'slug' / at 'staticPath' before start() ever runs. The it.todo for case C in that file still narrates a boot path that "never calls PluginSchema", which stopped being true at #16363.

Left out of #16334 by scope. Retiring the two arms is a plugin-hono-server change with its own verification surface, and #15638 already owns the third arm of the same guard. Suggested shape, for whoever lands it: read plugin.slug and plugin.staticPath as the contract now guarantees them, drop the fallback and the guard, and rewrite the case-C todo against the post-#16363 boot path. The same block also reads an isDefault alias beside default (plugin.default || plugin.isDefault); isDefault is not a PluginSchema key and is worth a look in the same pass.

Activity

  1. added theissue type on Sep 7, 2026
  2. os-zhuang commented on Sep 7, 2026

    @os-zhuang
    Contributor

    Triage: lands in domain:services (packages/plugins/plugin-hono-server/src/hono-plugin.ts + its pin file); Bug, priority:p3, pm:queue. Routed as a child of the open parent #15638 — per SKILL.md, a parent with sub-structure gets the queue label and triage expands the children individually; ⛔ the parent is a coordination node and is never dispatched.

    Admission basis, stated because the obvious reading would close it: unreachable arms are 死代码, which the rule lists under 其余 ⛔ 不立卡. ⇒ Two things admit it anyway:

    1. ⭐ A false statement in the tree, which is class (a). The it.todo for case C "still narrates a boot path that never calls PluginSchema, which stopped being true at feat(core): enforce PluginSchema at kernel.use() (#16049) #16363." ⇒ Same grounds as objectstack#16602, [finding] a pinned NON-rule in packages/spec justifies itself with a record-validator.ts line number that is 319 lines off, and nothing checks prose line anchors #16441 and objectui#8029 today — prose that is measurably wrong, in a file whose comments are load-bearing.
    2. ⭐ The unreachability is proven, not asserted, and it is proven by a change that already landed. The two pins that exercised these branches through the real kernel — "derives the slug from the last path segment of the plugin name when none is declared" and "a ui type with no staticPath mounts nothing" — had to be inverted into refusal pins on PR fix(spec,core): PluginSchema requires staticPath/slug for type "ui", and Plugin derives its metadata keys from PluginDefinition (#16334) #16598, because kernel.use() now throws PLUGIN_CONTRACT_VIOLATION … at 'slug' / at 'staticPath' before start() ever runs. ⇒ The tests that used to reach the arms now assert they cannot be reached.

    priority:p3: ⛔ no behaviour, no consumer-visible change — the arms cannot execute, so removing them changes nothing observable. This is ledger hygiene under ADR-0049 plus one false comment.

    Scope, and ⭐ the third arm is the one worth not missing: the same block reads plugin.default || plugin.isDefault, and isDefault is not a PluginSchema key — ⇒ likely a fourth dead alias, and the card is right that it "is worth a look in the same pass." ⛔ Do not retire two arms and leave a third of the same shape two lines away unexamined; that is how this card's parent came to have children.

    ⇒ Deliverable, as the card shapes it: read plugin.slug and plugin.staticPath as the contract now guarantees them, drop the || fallback and the && plugin.staticPath conjunct, rewrite the case-C todo against the post-#16363 boot path, and measure isDefault.

    ⚠️ Coordinate with the parent: #15638 owns the ui-plugin disjunct of the same guard, which was already unreachable after #16363. ⇒ Whoever lands either should check whether both can go in one PR — three arms of one guard, one verification surface — or state why not. ⛔ Two PRs racing on the same if is the avoidable outcome.

    ⛔ Correctly left out of #16334: retiring these is a plugin-hono-server change with its own verification surface, and that PR is the spec half.

    ⛔ This seat grades and routes only: not claimed, not dispatched, no code.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions