Skip to content

feat(components): enforce per-host component feature sets for commands and rules (#100) - #427

Merged
ScriptedAlchemy merged 4 commits into
mainfrom
feat/100-component-features
Sep 3, 2026
Merged

feat(components): enforce per-host component feature sets for commands and rules (#100)#427
ScriptedAlchemy merged 4 commits into
mainfrom
feat/100-component-features

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Summary

Closes the "component feature sets" item from the #100 remaining-scope comment (2026-09-03), following the closed per-host Skill IR schema pattern from #108 rather than a second mechanism.

  • Feature rows. Each host publishes one <kind capability>.<feature> four-state row per feature a component kind may use (shared helpers featureCapabilitiesFrom / frontmatterFeatureCapabilitiesFrom / featureCapabilityName):
    • commands.{description,argumentHint,allowedTools,model,disableModelInvocation} — Claude supported (plugin.commandFrontmatter, the five documented kebab-case fields the lowering regenerates); Cursor unavailable with dated evidence that its commands surface is frontmatter-free Markdown (the 2026-09-03 commands docs URL now resolves to Skills and documents no command frontmatter). Codex/portable publish none (no commands kind).
    • rules.{description,globs,alwaysApply} — Cursor supported (plugin.ruleFrontmatter, retrieved 2026-09-03 from https://cursor.com/docs/context/rules).
    • hooks.{timeout,toolMatchers} — Claude/Codex from new hooks.features blocks citing the pinned hooks schemas; Cursor reuses the Refresh Cursor plugin contract coverage against current public docs #189 hooks.options.{timeout,matcher} rows.
    • skills.{hostFrontmatter,markdownTokens} — mirrors the Skill IR: typed host frontmatter on Claude/Cursor/Codex (sidecar), portable unavailable; Markdown tokens Claude only, others unavailable citing AB3008.
    • Composite plugin: intersection in capabilities, union in componentCapabilities (it emits Claude-format commands and Cursor rules).
  • Build-time enforcement (config/validate.ts, commands and rules): every frontmatter field is judged against the target's row using the component-emission judgment (componentCapabilityState), only where the kind itself is supported. Author-required target → error AB4927 (commands) / AB4907 (rules); implicitly selected target → the component still ships minus the feature and validate reports a warning AB4928 / AB4908 with the host's reason. Documented in docs/diagnostics.md.
  • Inspection. Selected components carry omittedFeatures: [{ feature, capability }]; human inspect prints <kind> <name> omits <feature>: <row> <state> — <reason>. Hooks report timeout/toolMatchers features; skills report hostFrontmatter/markdownTokens.
  • Docs: docs/framework-mode.md "Component feature sets" subsection + matrix; docs/entry-conventions.md. Changeset agent-bundle patch. adapterRevision: claude 1.24.0, codex 1.11.0, cursor 1.11.0, portable 1.8.0, plugin 1.27.0.

Deliberate behavior change: a command that explicitly targets: [cursor] may no longer carry description (or any other frontmatter field) — Cursor cannot express it, so per the fail-closed rule it is AB4927. Two test fixtures were updated accordingly; no example ships commands. If the Cursor lane (#189) later pins evidence that Cursor commands tolerate frontmatter, flipping plugin.commandFrontmatter.state in the table is the only change needed.

Evidence

  • tests/command-config.test.ts "enforces command feature sets…": explicit Cursor target → two AB4927 errors (argumentHint, description) with the frontmatter-free reason; implicit claude+cursor+codex → two AB4928 warnings on cursor only; Claude-only and plugin-only → silent.
  • tests/rule-config.test.ts "judges rule frontmatter features…": all three .mdc fields supported on Cursor (no diagnostics across all five targets); a synthetic host with rules but no field rows → three AB4908 warnings (missing-row reason) / three AB4907 errors when explicit.
  • tests/adapter-capability-states.test.ts "publishes dated component feature rows per kind and host": every row above, composite intersection vs union, dated evidence prefixes.
  • tests/api.test.ts "reports omitted component features per target…": Cursor command carries two omittedFeatures; Claude/plugin commands, Cursor/plugin rules, and hooks on every host carry none; validate yields exactly the two AB4928.
  • tests/cli.test.ts: human command deploy omits argumentHint: commands.argumentHint unavailable — …frontmatter-free… line.
  • Local gates on this head: pnpm typecheck 0 errors, pnpm lint 0/0, targeted unit files 132/132, integration files (api, cli, plugin-bundle, host-adapters, cursor-adapter) 342/342; earlier full runs of pnpm test:unit (only the pre-existing native-claude-contract 5 s timeout wobble, reproduced on clean main), pnpm test:route-unit 38/38, pnpm test:projection 66/66.

Test plan

  • targeted rstest files above
  • typecheck / lint
  • CI green, @codex review on head

Review status

Automated reviewer (chatgpt-codex-connector) covered cc4b90e (one thread, fixed) and 7efddad (one thread, fixed); both threads are answered. It returned "usage limits reached" for the current head 3add52b73 (the fix(plugin): the composite's shared skills tree cannot carry host frontmatter or Markdown tokens commit: composite skills.* rows, api/capability tests, one docs paragraph), so that commit is unreviewed; merged on CI green per the amended lane rule. Request @codex review on a follow-up when credits return.

…s and rules

Publishes <kind>.<feature> capability rows (commands.* on Claude/Cursor,
rules.* on Cursor, hooks.timeout/toolMatchers on hook hosts, skills.*
mirroring the Skill IR) with dated evidence, judges every command and rule
frontmatter field per target at validation time (AB4907/AB4927 fail closed
for explicit targets, AB4908/AB4928 omit-with-reason warnings for implicit
ones), and reports omitted features on selected components in inspect.

Refs #100
@changeset-bot

changeset-bot Bot commented Sep 3, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 3add52b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
agent-bundle Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 3, 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-09-03T14:38:54.499186Z 7efddad Manual request
ℹ️ 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.

@pkg-pr-new

pkg-pr-new Bot commented Sep 3, 2026

Copy link
Copy Markdown
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle@427
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/create-agent-bundle@427
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@427

commit: 3add52b

@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: cc4b90eeec

ℹ️ 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 .changeset/component-feature-sets.md Outdated
@@ -0,0 +1,5 @@
---
'agent-bundle': patch

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Mark the breaking validation change as minor

Change this changeset from patch to minor: existing projects with frontmatter-bearing commands that explicitly target Cursor previously built successfully but now fail with AB4927, so this is an intentional breaking behavior change. Publishing it as a patch would expose 0.x consumers to a breaking upgrade contrary to the repository's pre-1.0 semver policy.

AGENTS.md reference: AGENTS.md:L25-L26

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Agreed — changed to minor in 7efddad. A Cursor-required command carrying frontmatter previously built and now fails AB4927, which is a breaking behavior change under the pre-1.0 policy; the summary already spells the new failure out.

@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

@codex review

@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: 7efddad8d7

ℹ️ 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".

*/
const componentCapabilities: Readonly<Record<string, CapabilityState>> = Object.freeze({
...pluginCapabilities,
...compositeFeatureCapabilities(unionCapabilityStates),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Mark plugin skill frontmatter omitted on portable fallback

When a plugin-targeted skill declares a Claude or Codex host extension, pluginSharedDocument in config/normalize.ts selects the portable lowering because the host documents differ, and that lowering strips the host extension. Unioning all feature rows here nevertheless marks skills.hostFrontmatter as supported, so inspect reports the skill as selected without omittedFeatures even though the built composite artifact discarded the applicable host metadata. Derive this feature judgment from the shared document actually selected for the composite rather than whether any constituent host supports the feature.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in 3add52b: the composite now publishes skills.hostFrontmatter and skills.markdownTokens as explicit unavailable rows (in both capabilities and componentCapabilities) with the reason that its shared skills/ tree lowers any skill with a host extension or token to the portable document (pluginSharedDocument), instead of unioning the host halves. Pinned by the extended 'reports omitted component features…' api test: a skill with targets.claude.model reports no omission on Claude, omittedFeatures: [hostFrontmatter] on plugin, and the plugin host document has no model field; adapter-capability-states asserts both composite rows. Documented in the feature-set section of docs/framework-mode.md.

@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@ScriptedAlchemy
ScriptedAlchemy merged commit 1daaf69 into main Sep 3, 2026
13 checks passed
ScriptedAlchemy added a commit that referenced this pull request Sep 3, 2026
#428)

Document the user-facing behaviour that landed on main after the docsite
PR (#384) merged, in both locales:

- install: `agent-bundle install cursor --mode local|marketplace` and the
  Doctor findings for Cursor hook registration and marketplace staging
  (AB7322-AB7324) (#414)
- project structure: per-host feature sets for src/commands and src/rules,
  with AB4907/AB4908 and AB4927/AB4928 (#427)
- testing: the script-dispatch and workbench-surface proof levels, eleven in
  all, and the routed cli-tool template (#398)
- notices reference: inbox and resources/updated wiring gated on the host's
  noticeDelivery advertisement (#412, #376)
@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

Review-status tracking (final sweep, 2026-09-03 16:37 UTC): @codex review re-requested for the merged head; the connector answered usage limits reached. Last Codex-reviewed commit: 7efddad8d7 (14:38 UTC). Unreviewed: 3add52b73c (head, fix(plugin): composite shared skills tree cannot carry host frontmatter) and the squash merge 1daaf696dd. Re-request once credits return; no thread on this PR awaits a reply.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

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.

1 participant