Conform to Agent Plugins 1.0.0 and the Agent Skills specification - #4
Conform to Agent Plugins 1.0.0 and the Agent Skills specification#4jpantsjoha wants to merge 3 commits into
Conversation
Two independent fatal faults meant a conformant Agent Plugins client would
load nothing from this plugin:
1. plugin.json omitted the required $schema. It sits on a closed schema, so
§5.2 makes the omission fatal — the client rejects the plugin outright.
2. All 17 skills carried top-level frontmatter keys (version, triggers,
required_scopes, mcp_servers, persona, tier, gate, owns_eval) outside the
closed Agent Skills field set. Agent Plugins §6.1 requires clients to skip
every non-conforming skill.
Changes:
- plugin.json declares the manifest schema.
- New root mcp.json: the portable MCP manifest, with an explicit stdio
transport discriminator. It ships the gcloud server only — toolbox needs a
user-specific tools.yaml that no spec placeholder can express, so it stays a
documented opt-in. env is omitted entirely: only ${PLUGIN_ROOT} and
${PLUGIN_DATA} expand, so ${GCP_PROJECT_ID} would have been passed through
literally and mis-set the project.
- All 17 SKILL.md frontmatters reduced to {name, description, license,
metadata}. Routing keywords folded into description, which is what a
conformant client actually routes on; the plugin's own contract moves to
namespaced string values under metadata.
- validate_skills.py inverted: it now enforces the closed Agent Skills field
set instead of requiring the fields that broke conformance.
- New validate_agent_plugins.py: dependency-free conformance check wired in as
`make spec`, reporting against the spec's own FATAL/MCP/SKILL failure
boundaries.
- Smoke tests rewritten: 136 -> 195, covering both specs.
Verified against the official reference validator (agentskills/agentskills
skills-ref) — 17/17 valid — and both published JSON schemas via
check-jsonschema. All four harnesses remain installable.
Governance: - ADR-007 records the decision, the alternatives weighed, and the two fatal faults that prompted it. ADR-005 marked superseded — its contract survives, only its location changed. - SPEC.md, shared/conventions.md, plugin.yaml, .claude/CLAUDE.md and the coverage matrix updated to the new frontmatter shape. - README gains a standards-conformance section with commands a reader can run to reproduce the evidence independently. Routing, from cross-model testing: An independent Kimi agent loaded the plugin from a clean sandbox export and routed five requests against it. All 17 skills were discovered and all five routed correctly, but it flagged pairs that could misroute now that routing depends on descriptions alone: gcp-ops/logging-monitoring, iam/gcp-security, vertex-ai/agent-architect, solution-designer/gcp-architect. Its two "concrete regressions" did not survive checking — the keywords it reported missing from cloud-storage and bigquery are present in the description prose, just not in the trailing keyword list. But four other skills did have a trigger recorded only in metadata, where nothing can route on it. So each overlapping pair now states which skill owns the case and names the other, and `make validate` fails if any metadata trigger is absent from its description — keeping that index a derived view rather than a rival source of truth. Also: author URL now points at jpantsjoha.com. The schema permits one author URL, and an owned domain outlives any platform profile. make gate: 212 tests, 101 URLs, all four harnesses installable.
Adds validate_agent_plugins.py as a blocking CI step — it is deterministic and offline, since it transcribes the published schemas rather than fetching them. Adds an advisory step that validates against UPSTREAM instead: the official skills-ref reference validator and the live JSON schemas. That is what catches spec drift, but it depends on the network, so it warns rather than blocks.
Closing — fully superseded, all additive content extractedReviewed against
Verified: Why merge rather than close is not an optionThe remaining delta is −969 lines, and all of it is regression against work merged in #6–#11:
Credit where it is dueThis branch caught something the merged line missed: CI never invoked It also identified that a trigger recorded only in Two real defects, neither found by the main line of work. Closing as superseded, not as wrong. |
Summary
Brings the plugin into conformance with Agent Plugins 1.0.0 — the open, vendor-neutral packaging specification announced by Google on 2026-08-05 and co-maintained by Amazon, Cursor, Google, Microsoft, OpenAI and Vercel — and with the Agent Skills specification it references.
Before this PR, a conformant Agent Plugins client would have loaded nothing from this plugin. Two independent fatal faults, neither visible to the existing gate:
plugin.jsonomitted$schema$schemainrequiredmake gatepassed throughout, because it enforced this repo's own ADR-005 contract rather than the published specifications. That is the real lesson here, and the reason the validators were inverted rather than extended.Standards this plugin now conforms to
plugin.jsonplugin.schema.jsoncheck-jsonschemaagainst the live schemamcp.jsonmcp.schema.jsoncheck-jsonschemaagainst the live schemaskills/*/SKILL.md×17skills-ref, the official reference validatormcp.jsonmake specNormative rules now enforced in CI, quoted from the specification:
$schema,name,version,description,author,homepage,repository,license,keywords,extensions.name,description,license,compatibility,metadata,allowed-tools.metadatais a map from string keys to string values.skills/*/SKILL.md.${PLUGIN_ROOT}and${PLUGIN_DATA}; every other placeholder is passed through literally.mcp.json$schemaMUST match the versionplugin.jsontargets.type; a server omitting it is skipped.What changed
Manifests
plugin.jsondeclares the Agent Plugins manifest schema.mcp.json— the portable MCP manifest, with an explicit"type": "stdio".gcloudserver only.toolboxneeds--config <user-specific tools.yaml>, which no spec placeholder can express; shipping it would mean a server that fails on every fresh install. It stays a documented opt-in inskills/mcp-servers/.enventirely.${GCP_PROJECT_ID}does not expand — it would have been passed through literally, settingCLOUDSDK_CORE_PROJECTto the 17-character string${GCP_PROJECT_ID}. Clients may inherit the ambient environment, andgcloud-mcpalready reads project and ADC from it.Skills — all 17 reduced to
{name, description, license, metadata}. Routing keywords fold intodescription, which is what a conformant client actually routes on. The plugin's contract moves to namespaced string values undermetadata.Validators —
validate_skills.pyinverted to enforce the closed field set it previously violated. Newvalidate_agent_plugins.py(make spec) reports against the specification's own FATAL / MCP / SKILL failure boundaries. Smoke tests 136 → 212.Governance — ADR-007 records the decision and the alternatives weighed; ADR-005 marked superseded.
Cross-model validation
Per the repo's doctrine that neither model both writes and self-approves, the work was tested by an independent agent against a clean
git archiveexport — what a user actually installs.Kimi (independent harness, skills loaded via
--skills-dir)gcp-ops/logging-monitoring,iam/gcp-security,vertex-ai/agent-architect,solution-designer/gcp-architect. Acted on — each description now states which skill owns the case and names the other.cloud-storageandbigqueryare present in the description prose, just not in the trailing keyword list. Reported here rather than silently dropped, because the underlying concern was sound even though the examples were not — a sweep found four other skills with a trigger recorded only inmetadata, where nothing can route on it.make validatenow fails on that condition.Codex — could not run. The CLI returned
You've hit your usage limit … try again at Aug 8th, 2026 12:43 PM, so no independent OpenAI-side audit was produced. This PR therefore has one independent reviewer, not two. Worth rerunningcodex execagainst the sandbox once quota resets if a second opinion is wanted before merge.Evidence a reviewer can reproduce
The gate was also negative-tested: dropping
$schema, removing a transporttype, reintroducing a non-expanding${...}placeholder, and re-adding a legacy top-leveltriggersfield are each caught with an actionable message.Compatibility
No breaking change for existing users. The specification closes the
plugin.jsonfield set and fixes component locations, but says nothing about sibling directories — so.claude-plugin/,.kimi-plugin/,gemini-extension.json,.mcp.json,mcp_config.jsonand.agents/are untouched.make manifestconfirms Claude Code, Antigravity/Gemini, Codex and Kimi all remain installable.Agent Plugins 1.0.0 deliberately specifies no install mechanism, distribution protocol, permission model or sandboxing, so marketplace packaging stays harness-specific for now.
Follow-ups (not in this PR)
.claude/CLAUDE.mdis tracked in git despite the file itself stating it is gitignored and never committed. The internal construction guide currently ships to the public repo and to anyone installing the plugin. Worth a decision: untrack it, or drop the claim.metadata/version(0.1) and pluginversion(0.1.0) drift. Harmless, but they read as the same field.