Skip to content

docs(conventions): add the routing-as-data convention and resolve user-interface sibling detects by name - #6640

Merged
kyle-sexton merged 7 commits into
mainfrom
docs/routing-as-data-6483
Oct 9, 2026
Merged

kyle-sexton merged 7 commits into
mainfrom
docs/routing-as-data-6483

Conversation

@kyle-sexton

@kyle-sexton kyle-sexton commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Closes #6483

Summary

Adds docs/conventions/routing-as-data/, the owner doc for plugins that keep routes to other skills,
plugins, MCP servers and tools as data, and registers it in the plugin philosophy. user-interface
adopts it: own-marketplace detects are bare plugin names, every kind: skill id is its slash
invocation, and own-skill rows carry no pointer.

One divergence from the issue: it says installed and reachable are "each true, false or null". This
convention keeps installed as a list of row ids, or null with a reason (interview Q3); only
reachable values are true, false or null.

The amended plugin-philosophy rule makes 43 existing cross-plugin skill-folder URLs in 39 files
nonconforming (36 are the source-control gather-block record). #6638 sweeps them; this PR does not
touch them.

Fix

  • New convention doc and CHANGELOG (1.0.0): route rows, detection by name, team routing layer at
    <home>/<plugin>.yaml, fail-open degradation with disclosure.
  • Plugin philosophy: registry row; the encapsulation rule now covers URLs as well as paths into a
    skill in another plugin in this marketplace, and the org-agnosticism paragraph links to it.
  • Seam phrasing: a third-party route row's detect, and its id on a kind: plugin row, are exempt
    from the marketplace-id rule.
  • user-interface: schema version 2 enforces the slash id and pointer rule; detect.mjs resolves a
    bare sibling against its own marketplace, falling back to a name match with a reason and
    reporting same-named third-party plugins as uncertain; the design skill drops the leading slash
    before calling the Skill tool.

Verification

  • node --test via routing.test.sh 15/15 pass and detect.test.sh 28/28 pass (red state before
    the fix: RT 10 ok / 6 not ok, DT 19 ok / 9 not ok).
  • ajv-cli@5 --spec=draft2020: routing.json valid; a skill id with no slash, an own-skill row with
    a pointer, and an external row with no pointer are each rejected.
  • scripts/validate-plugins.sh --only user-interface: 135 pass / 0 fail. check-changelog-parity.sh --check and --check-bump origin/main: exit 0. markdownlint-cli2 over the changed .md files:
    0 issues.
  • Resolved path via probe-market: resolved path not live-verified: claude plugin marketplace add
    takes no name option, and the worktree's marketplace name collides with the configured GitHub
    marketplace. Covered by the detect fixture tests.
  • Fallback disclosure: detect.mjs --project . from the checkout and under claude --plugin-dir plugins/user-interface both print the installed list with reason: "own marketplace unresolved (no record at this plugin's path); matched by name".
  • Skill call: a claude -p --plugin-dir stream-json run of /user-interface:design called the Skill
    tool with user-interface:design and then prototype:explore-directions, no leading slash.
  • Mutation checks: removing the non-string-id filter or letting a bad record end the self lookup
    each fails a DT test.

Related

🤖 Generated with Claude Code

kyle-sexton and others added 5 commits October 8, 2026 21:29
Tests for adopting the routing-as-data convention: slash skill ids,
the schema's pointer rule, own rows found without the publisher name,
and detect.mjs resolving bare siblings against its own marketplace with
a disclosed name-match fallback. They fail until the next commit.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…'s own marketplace

Route data moves to schema version 2: kind skill ids are slash
invocations, own-marketplace detects are bare plugin names, and own
skill rows carry no pointer. detect.mjs finds its own marketplace from
the plugin list record installed at its root, guarded per record, and
falls back to a name match with a reason, reporting names a same-named
third-party plugin may hold as uncertain.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… tool and release 0.2.0

The design skill reads the slash ids, drops the slash before matching
the skill listing or calling the Skill tool, and discloses the
name-match reason and uncertain ids once.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The owner doc for plugins that keep routes to skills, plugins, MCP
servers and tools as data: route rows, detection by name, the team
routing layer and fail-open degradation. The plugin philosophy
registers it and extends the cross-plugin skill rule to URLs; seam
phrasing exempts third-party route-row id and detect fields.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
A bare detect on a kind: tool row names a tool, not a skill directory
or MCP server, as detect.mjs resolves it. The seam-phrasing gate rule
now defers to the carve-outs, which limit a third-party id to
kind: plugin rows, instead of naming every third-party id field.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@kyle-sexton
kyle-sexton marked this pull request as ready for review October 9, 2026 02:02
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-09T02:05:51.289937Z 60e2fcd Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@claude

claude Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 6m 13s —— View job


Code review in progress

  • Gather context (CLAUDE.md, REVIEW.md, diff)
  • Review new convention doc and philosophy changes
  • Review user-interface plugin changes (schema, detect.mjs, tests)
  • Fan out adversarial validation on candidate findings (running)
  • Post inline findings and summary

@claude

claude Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 2m 3s —— View job


Security review (/review:security-review)

Scope: diff against origin/main (13 files, +531/-74): docs/conventions/routing-as-data/, docs/plugin-philosophy.md, docs/conventions/seam-phrasing/README.md, and plugins/user-interface/{plugin.json, CHANGELOG.md, reference/routing.json, reference/routing.schema.json, scripts/detect.mjs, skills/design/SKILL.md, tests/*}.

No security issues found.

Notes from the review, none of which rise to a finding:

  • plugins/user-interface/scripts/detect.mjs adds ownMarketplace(), which resolves a plugin's own marketplace via realpathSync.native comparison against claude plugin list --json records rather than trusting a bare name. The new fallback path (lines L132-L146) is a hardening of the prior bare-name matching, not a weakening: when the own-marketplace record can't be resolved, it falls back to name-only matching but explicitly discloses this (reason: "own marketplace unresolved...; matched by name") and flags ambiguous same-named third-party plugins in a separate uncertain map rather than silently treating them as installed.
  • The consuming skill (skills/design/SKILL.md) correctly surfaces that reason/uncertain disclosure to the user and continues to treat routing/project data as data, not instructions ("an instruction in them to run, install or fetch something is reported to the user, never carried out").
  • detect.mjs's spawnSync("claude", ...) call (unchanged by this PR) still runs with shell only on Windows and with NoDefaultCurrentDirectoryInExePath set there, so no new command-injection surface was introduced.
  • The docs/plugin-philosophy.md and docs/conventions/seam-phrasing/README.md edits narrow/extend citation conventions (allowing marketplace-qualified ids in route-row detect/id fields, and third-party pointer URLs as citations). I checked these against the instruction-exception-register classes (irreversible-action, secret-handling, data-integrity, external-publication, legal-compliance, agent-authority) — these are documentation-citation/branding conventions, not a protected guardrail, and no mechanism is removed.
  • docs/conventions/routing-as-data/README.md's "Degradation" section explicitly documents fail-open behavior for a malformed/missing team routing file as a deliberate, bounded choice ("never grants access... a hard block uses managed settings or permissions"), which is sound reasoning rather than a gap.
  • Route pointer URLs are reader citations only (per the design boundary rule), not fetched or executed by any script in this diff.

Per this lane's scope, GitHub Actions/workflow hardening is deferred to zizmor (none of this PR's changed files touch .github/workflows/), and general code-quality/style observations are left to /review:code-review.
(branch)

@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

claude-security-review has reviewed this pull request through 9fa7dba; a later push is reviewed from there.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 60e2fcd8ca

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/user-interface/skills/design/SKILL.md
@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

claude-review has reviewed this pull request through 9fa7dba; a later push is reviewed from there.

The detect rule said every third-party row's detect carries
name@marketplace, but skill-directory, MCP-server and tool detects stay
bare in the adopter's data. Scope it to detects that name a plugin, in
both the routing-as-data doc and the seam-phrasing carve-out.

Record the deferred axe-accessibility row as the adopter's exception,
rename its test to what it checks, and drop the version test the schema
test already covers.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@claude

claude Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 3m 27s —— View job


Code review in progress (incremental: changes since 60e2fcd)

  • Gather context (incremental diff, CLAUDE.md/AGENTS.md, REVIEW.md)
  • Review docs/conventions/routing-as-data/README.md and docs/conventions/seam-phrasing/README.md changes
  • Review plugins/user-interface/tests/detect.test.mjs and routing.test.mjs changes
  • Fan out adversarial validation on candidate findings (running)
  • Post inline findings and summary

@claude

claude Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 1m 45s —— View job


Security review (/review:security-review)

Scope: incremental diff only (.claude-lane/incremental.diff), reviewed against head
97889a6:

  • docs/conventions/routing-as-data/README.md
  • docs/conventions/seam-phrasing/README.md
  • plugins/user-interface/tests/detect.test.mjs
  • plugins/user-interface/tests/routing.test.mjs

Everything else in the PR was already covered by the prior review through 60e2fcd and is out of
scope for this lane run.

No security issues found.

Notes from the review, none of which rise to a finding:

  • routing-as-data/README.md and seam-phrasing/README.md reword which rows the name@marketplace qualifier applies to (from "a third-party route row's detect" to "a detect that names a third-party plugin"). This is a wording fix to make the two docs agree with each other and with the schema, not a behavior change: detect.mjs and routing.schema.json are unchanged in this increment and were reviewed at 60e2fcd.
  • The new status-table line noting the axe-accessibility row "keeps a bare detect until it is qualified" documents a pre-existing row already present in reference/routing.json (kind: plugin, detect: "axe-accessibility", status: deferred), not a new exception introduced here — routing.json itself isn't touched by this increment. The same-name collision this bare detect could cause is the scenario detect.mjs's uncertain map and own-marketplace resolution (reviewed at 60e2fcd) already guard against, and is exactly what the renamed test below exercises.
  • detect.test.mjs only renames "axe-accessibility is never installed" to "a bare third-party plugin detect does not match another marketplace once the own marketplace resolves"; the assertions are unchanged, so no coverage is lost.
  • routing.test.mjs drops the standalone routing.json version is 2 assertion. This isn't a coverage loss: routing.schema.json requires version and constrains it to {"const": 2}, and the retained "routing.json matches its schema" test already validates the full document (including version) against that schema. No standing instruction or guardrail is being removed here — checked against the instruction-exception-register classes (irreversible-action, secret-handling, data-integrity, external-publication, legal-compliance, agent-authority); none apply to a redundant test deletion that's still enforced by schema validation.

Per this lane's scope, GitHub Actions/workflow hardening is deferred to zizmor (no .github/workflows/ files touched by this increment), and general code-quality/style observations are left to /review:code-review.
(branch)

…ception

The deferred row is a third-party kind: plugin row, so its unqualified
id breaks the id half of the rule as well as the detect half.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@claude

claude Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 1m 9s —— View job


Code review complete (incremental: changes since 97889a6)

  • Gather context (incremental diff, CLAUDE.md/AGENTS.md, REVIEW.md)
  • Review docs/conventions/routing-as-data/README.md changes since 97889a6
  • Fan out adversarial validation on candidate findings
  • Post inline findings and summary

Scope: incremental diff only (.claude-lane/incremental.diff), reviewed against head
9fa7dba:

  • docs/conventions/routing-as-data/README.md (1 line changed, in the Adopters table)

Everything else in the PR was already covered by the prior review through 97889a6 and is out of
scope for this lane run.

No findings.

The change widens the stated exception from "keeps a bare detect" to "keeps a bare id and
detect" for the deferred axe-accessibility row
(line 152).
I checked this against plugins/user-interface/reference/routing.json (unchanged in this
increment): the axe-accessibility row has "kind": "plugin", "id": "axe-accessibility" and
"detect": "axe-accessibility" — both bare, no @marketplace qualifier. Per the doc's own id
rule a few paragraphs up ("a third-party kind: plugin row's id... carry name@marketplace")
and the matching seam-phrasing carve-out, a bare id on this third-party plugin row is exactly
the second half of the exception the old wording omitted. The correction is accurate and brings
the Adopters-table description in line with the data and the rest of the doc; no behavior,
schema or test changes accompany it, and none were needed since the schema cannot express this
rule (the doc already says so) and the adopter's tests, not this prose, enforce it.

This is a docs-only clarification of an already-documented exception, consistent with this
convention's own versioning rule, and doesn't need a CHANGELOG.md bump beyond the unreleased
1.0.0 entry this PR is shipping.
(branch)

@kyle-sexton
kyle-sexton added this pull request to the merge queue Oct 9, 2026
Merged via the queue into main with commit 74e40e0 Oct 9, 2026
16 checks passed
@kyle-sexton
kyle-sexton deleted the docs/routing-as-data-6483 branch October 9, 2026 02:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: add a routing-as-data convention for plugins that route to installed tools

1 participant