Build1 distinct publisher3 min readPublished
The plugin.json schema sets additionalProperties:false while section 5.2 tells clients to report unknown fields and carry on loading, so the four-line validate-and-reject loader fails the spec in exactly two places and looks correct everywhere else.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
The defect is in the return type. `validate(manifest)` hands back one bit, and the four-line loader branches on it [6]. The specification wants a decision per rule. A manifest missing a required field and a manifest carrying one extra top-level key both come back false, and only the first is fatal [1][2][4]. An `extensions` field that is not an object is the second tolerated case [3]. The author of the dev.to write-up puts it as one boolean where the spec wants three outcomes, with the natural implementation non-conformant in exactly two cases and correct everywhere else [5]. A conformant loader needs the failure list, not the verdict.
`$schema` is where this stops being theoretical, and it points in opposite directions in two different clients. oh-my-pi routed any package declaring the agent-plugins.org `$schema` to a strict provider that dropped every `SKILL.md` with an extra frontmatter key, taking one plugin from 33 skills to 3 [8]. That is 30 of 33 gone, about 91% of the plugin's surface [2]. The remedy was to delete `$schema` from the manifest, so declaring the standard was the thing that cost them the standard [8]. Kiro went the other way: dotnet/skills manifests shipped with no `$schema` and with `skills`, `agents` and `mcpServers` as top-level fields, Kiro refused them outright, and adding `$schema` got past the rejection and then loaded the package with every functional component excluded [9]. Neither client reported anything a user could act on.
That is why the post argues plugin validators and client conformance are different jobs needing different fixtures [11]. The unit it settles on is a pair: a real plugin directory on disk plus the load report a conformant client must produce for it [12]. The AP-5.2-UNKNOWN-FIELD case is a manifest with the canonical `$schema`, name `demo`, and `skills: []`, and an expected report of `rejected: null`, empty `loaded` lists, and one `reported` entry naming the field [13]. Validate-and-reject answers `rejected: "additional-properties"` and fails it [14]. The adapter is a shell script that prints that JSON, mapping the client's warnings into `reported` and dropped paths into `skipped`, which is what makes a Go or Rust client testable without any plugin API [15]. It also means a client with no warning channel answers `rejected: null` correctly and still fails, because `reported` comes back empty [3]. VS Code, described in the post as the largest shipping client, has no validation surface at all; its documented procedure is to open `SKILL.md` and check the `name` field by hand [10].
Treat 131 of 133 as a claim about one loader against one reader's parse of the document, not a grade [16]. The 1.5% failure rate [1] transfers only if the fixtures cover every MUST you care about and your loader already surfaces per-field warnings in a shape the adapter can print [15].
The containment finding is the one I would fix first. The same loader enforces the plugin.json boundary and not the two for `skills/` [17], and the post reads the presence of the manifest check as evidence the design was there and two boundaries were missed rather than declined [19].
Ranked by verification strength, evidence, and original report placement.
Agent Plugins 1.0.0 ships a JSON Schema for plugin.json that sets additionalProperties: false, making any extra top-level field a schema violation.
Section 5.2 of the specification states: "Clients MUST report and ignore each unknown field and MUST continue loading the plugin if the manifest otherwise satisfies this section."
Section 8.1 requires the same report-and-continue treatment for an extensions field that is not an object.
Every schema violation other than an unknown top-level field and a non-object extensions field is fatal under the specification.
The author writes that a validator gives one boolean where the spec wants three different outcomes, so the natural implementation is non-conformant in exactly two cases and correct everywhere else.
The obvious loader is four lines: JSON.parse the plugin.json from disk, then if validate(manifest) is false, return reject('invalid manifest').
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 31, 2026
Follow any of these and your For You feed starts watching them — no settings page required.
build
Cloudflare pins shadow MCP traffic on three protocol headers1 distinct publisher
build
AWS wants data governance to ship as a pull request, not a sign-off1 distinct publisher
build
AWS's one-minute test for agent access is really a test of where the answer lives1 distinct publisher
build
Spline V2 turns the 3D editor into an endpoint, with the desktop app as the only door1 distinct publisher
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Spec quotes checkable, field record unverifiable
Two grades of proof share one post. The schema clause, the §5.2 sentence and VS Code's own advice to eyeball the name field are quoted and can be checked against published documents in a minute. Everything else — Codex's dead hooks, the 33-skills-to-3 collapse, Kiro's empty load, the loader that lets a symlink out of skills/ — names no repository, issue or version, and the implementation that fails twice is never identified. The argument is legible; the incident list is a memory.
Spec widely implemented, its test suite barely
Split the question and it answers itself. Agent Plugins 1.0.0 is already parsing manifests inside Codex, oh-my-pi, Kiro and VS Code — that is why a report-and-continue clause matters at all. The corpus written to police those clients has exactly two adapters, both built by its author, one of which rewrote three of his own fixtures, and there is no sign of anyone else running the 133 cases.
Mostly sized to what it shows
The headline promises a specification that forbids what it orders clients to keep, and the quoted text actually delivers that — rarer than the genre suggests. The stretch is scope rather than substance: "the largest shipping client", "nothing that checks whether a client behaves", 131 of 133 against a loader nobody can name. Standards-body assertions carried by one weekend's evidence, with the author's self-corrections pulling in the honest direction.
The toolmaker arguing for the tool
The four opening horror stories exist to justify the thing the author built, and he is the only person vouching for its results. What partly offsets that: he publishes the second client's verdict against himself, downgrades a fixture he had filed as fatal to disputed, and asks the spec maintainers who is right. There is no product, price or employer in view — the payoff on offer is credibility.
Trust the reading, not the counts
One author, one publication, no corroboration would normally cap this low. Two things lift it: the specification quotations stand independently of him, and the defect he describes — a validator returning one boolean where three outcomes are required — is either true of the 1.0.0 schema or it isn't, and it is checkable. The tallies, the loader identities and the upstream reports are where the story asks to be taken on faith.