You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Summary. The ARD audit in this repository follows ARD as it stood in June 2026:
its bundled conformance validator is a faithful port of the upstream conformance
test at that date, and its gatherer looks for the well-known path ARD specified at
that date.
ARD v0.91, published in August, changed three things: the well-known path a
consumer must fetch, the schema a manifest is validated against, and the severity
of a root collections array.
The pinned upstream commit was then advanced past v0.91 twice, both times inside a
routine "deps: upgrade deps" PR (#17206, #17245), and the ported code was never
adapted to the changes the pin had just crossed.
Two consequences, both reproduced below: a site that follows the current specification
is invisible to this audit, and a manifest that ARD considers valid scores 0.
Both confirmed at current HEAD (08c05cdee7e191719480477056bd145abcb09c17,
2026-09-18, 13.5.0) by reading source and reproducing locally.
Defect 1: the audit looks for the wrong discovery path.
Seeing this needs no fixture. The audit's title is "ai-catalog.json schema is
valid". Its description reads
"Valid ai-catalog.json manifests are required for autonomous AI agents and
registries to discover and verify your resources."
Follow the link to §5.1 "Discovery Mechanisms," the paragraph headed "Consumer resolution (normative)", quoted verbatim and in full from
the published page (confirmed identical to spec/ard.md at the currently
pinned upstream commit):
"A consumer resolving a domain's entries MUST fetch /.well-known/ard.json,
and MUST honour a rel="ard" link. ARD's predecessor specified the path /.well-known/ai-catalog.json and the link relation ai-catalog; a consumer
MAY additionally consult these, and a consumer that does treats them as
equivalent entry sources. Consulting the predecessor names is a courtesy to
resources published before this revision, not a conformance requirement: a
consumer that resolves only ard.json and rel="ard" is fully conformant."
The audit's own description says the opposite of the document it cites: it calls
the predecessor name required, where the linked specification says a consumer
needs it only as a courtesy.
Confirmed in source at HEAD, core/gather/gatherers/agentic/ard.js:
parsed.get('rel', 'ai-catalog') (HTTP Link header)
new URL('/.well-known/ai-catalog.json', finalDisplayedUrl) (fallback)
Never rel="ard", never /.well-known/ard.json. A publisher who follows the
spec's own MUST and serves only /.well-known/ard.json is invisible to this
audit: it reports notApplicable, not a failure, so nothing in the report says
why.
Defect 2: a manifest ARD considers valid scores 0.
A manifest carrying a collections array at its root fails this audit outright.
Upstream, at the commit this port currently pins, says that manifest is valid:
"Top-level collections were removed in ADR-0003; ARD ignores unrecognized
top-level members, so this does not invalidate the manifest, but hierarchies
should be modeled inside 'entries'."
There are two independent causes, and fixing either one alone still scores 0. All
four states were run on the same fixture: as shipped, severity fixed alone, schema
fixed alone, both fixed. Scores 0, 0, 0, 0.9.
Severity.third-party/ard/ard.js calls add_error for the collections
check where upstream calls add_warning. core/audits/agentic/ard-schema.js
sets score = 0 on any Error before it tests for Low severity, so the check
never reaches the audit's existing Low severity path, which scores 0.9 instead
of failing (the behaviour specified for this audit's non-fatal issues in core(ard): add support for partial scores audit results #17181).
Schema. The bundled validator is compiled from the predecessor schema file,
which is additionalProperties: false, so any unrecognized root member is a
hard Error, while the reference conformance test validates against a definition
that is deliberately open. Reasoning and file names in the collapsed section.
Each cause is sufficient on its own to hold the score at 0, which is why the two
fixes have to ship together.
Target Agents
Not applicable: this is a conformance and scoring defect in an existing audit, not
a new-signal proposal.
Proposed Implementation / Suggested Improvement
core/gather/gatherers/agentic/ard.js: check /.well-known/ard.json (and rel="ard", Link: rel="ard") first, falling back to the existing ai-catalog paths, matching the spec's own MUST/MAY order in §5.1. The audit's title, failureTitle and description strings need the same correction.
third-party/ard/ard.js: change the collections-at-root check from add_error to add_warning, so it lands on the existing Low severity path.
build/build-ard-schema.js: compile the validator from spec/schemas/ard-entry.schema.json's $defs.ArdManifest, as the reference
conformance test does, instead of ai-catalog.schema.json. core/scripts/update-ard-spec.js fetches the predecessor schema by hardcoded
path and needs the same change to stay correct.
Items 2 and 3 are one fix. Both were also measured separately, and each on its own
still scores 0: either alone leaves the audit failing a manifest the specification
says is valid.
Example URL
None: Defect 1 is visible in any report that ran this audit, and both defects are
reproduced with a local fixture in the collapsed section below.
Reproduction, schema detail, pin history, and why the weekly sync check did not catch either
Defect 2, cause 2: the schema, in full
build/build-ard-schema.js compiles third-party/ard/spec/schemas/ai-catalog.schema.json, which is additionalProperties: false, so any unrecognized root member is a schema
Error. That is precisely what the second half of the upstream sentence quoted
above, "ARD ignores unrecognized top-level members", says must not happen.
Upstream's conformance test does not open that file. It validates the manifest
against spec/schemas/ard-entry.schema.json's $defs.ArdManifest, whose own
description reads "any other top-level members are transport-defined and ignored
by ARD, so additionalProperties is open", and which is additionalProperties: true. ai-catalog.schema.json is still present upstream; it is the predecessor
artefact, and the conformance test stopped using it in v0.91. The port reads it
because that is what upstream read in June 2026.
So the effect is broader than collections: any unrecognized root member fails
this audit, and the specification says ARD ignores all of them.
Why the weekly ARD sync check (#17171) did not catch either
core/scripts/update-ard-spec.js has RELEVANT_PREFIXES = ['spec/schemas/', 'conformance/']. Defect 1 lives in spec/ard.md, outside that list by
construction, so no upstream change to the discovery rules can raise a flag at
all.
Defect 2 lives in conformance/bin/conformance-test, which the check does watch,
so upstream's change of 2026-08-26 was visible. But the check's output is a diff
printed for a human to read. Step 2 of this port's own documented update procedure
is:
"Review the printed diff of conformance/bin/conformance-test and adapt third-party/ard/ard.js to match any updated validation rules"
Nothing enforces that step, and the one file the script updates automatically is
hardcoded: it fetches spec/schemas/ai-catalog.schema.json, the predecessor the
conformance test no longer uses. The mechanism advances the pin and refreshes the
wrong schema, and nothing prompts revisiting ard.js.
Reproduction: source at HEAD, Chrome 153 headless, local, not PageSpeed Insights
Environment: Lighthouse 13.5.0 at commit 08c05cdee7e191719480477056bd145abcb09c17
(2026-09-18), run against Chrome 153.0.8010.53 headless (--headless=new). That
is the environment this reproduction was run in, with nothing implied about any
other runner's version.
git clone https://github.com/GoogleChrome/lighthouse.git
cd lighthouse
git checkout 08c05cdee7e191719480477056bd145abcb09c17 # or main
yarn install --frozen-lockfile
yarn build-report
Result: {"id": "ard-schema", "score": null, "scoreDisplayMode": "notApplicable"}.
A fully valid manifest, at the path the linked specification says a conformant
consumer MUST fetch, is invisible to the audit.
Scenario B, identical manifest, /.well-known/ai-catalog.json only (the
predecessor path):
Same command against a server serving the byte-identical file at the old path.
Result: {"id": "ard-schema", "score": 1, "scoreDisplayMode": "binary"}. Same
bytes, correctly detected and scored, once served at the path the spec demoted.
Scenario C, collections: [] added at root, served at /.well-known/ai-catalog.json (so the audit runs). Run in four states:
(a) as shipped, score 0
{"id": "ard-schema", "score": 0, "scoreDisplayMode": "binary",
"details": {"items": [
{"element": "Root", "issue": "JSON Schema Validation Failed: must NOT have additional properties at path 'root'", "severity": "Error"},
{"element": "Root", "issue": "Deprecated field check: Found 'collections' array at root. Top-level collections were REMOVED in ADR-0003. Catalog hierarchies MUST be modeled inside 'entries' using 'type: application/ai-catalog+json'.", "severity": "Error"}
]}}
(b) add_error changed to add_warning on the collections check, nothing
else, still score 0
{"id": "ard-schema", "score": 0, "scoreDisplayMode": "binary",
"details": {"items": [
{"element": "Root", "issue": "JSON Schema Validation Failed: must NOT have additional properties at path 'root'", "severity": "Error"},
{"element": "Root", "issue": "Deprecated field check: Found 'collections' array at root. ...", "severity": "Low"}
]}}
core/audits/agentic/ard-schema.js sets score = 0 on any Error before testing
for Low severity, so the schema Error alone holds the score at 0.
(c) validator compiled from ard-entry.schema.json's $defs.ArdManifest, the collections check left as add_error, score 0
{"id": "ard-schema", "score": 0, "scoreDisplayMode": "binary",
"details": {"items": [
{"element": "Root", "issue": "Deprecated field check: Found 'collections' array at root. Top-level collections were REMOVED in ADR-0003. Catalog hierarchies MUST be modeled inside 'entries' using 'type: application/ai-catalog+json'.", "severity": "Error"}
]}}
The schema Error is gone and the remaining Error is the collections check itself,
which is enough to keep the score at 0. Together with (b) this is why items 2 and 3
of the proposal are one fix: neither is sufficient alone.
(d) both, (b) plus (c), score 0.9
{"id": "ard-schema", "score": 0.9, "scoreDisplayMode": "binary",
"details": {"items": [
{"element": "Root", "issue": "Deprecated field check: Found 'collections' array at root. ...", "severity": "Low"}
]}}
For the schema change in (c) and (d), build/build-ard-schema.js was pointed at ard-entry.schema.json with schema['$ref'] = '#/$defs/ArdManifest', the same variant construction upstream's as_def("ArdManifest") performs, then node build/build-ard-schema.js. One
incidental adjustment was needed: the build script strips require("ajv-formats/dist/formats") out of the standalone output by matching the
literal variable names formats0 and formats10, and Ajv numbers those per
schema, so the rewrite has to be generalised to formats\d+ or the generated
module throws require is not defined on import.
Regression check. Scenario B (clean manifest, no collections) re-run in state
(d): {"score": 1, "scoreDisplayMode": "binary"}, zero detail items. The schema
change does not affect the clean case.
node core/test/scripts/run-mocha-tests.js third-party/ard/ard-test.js in state
(d): 12 passing, 1 failing, "fails with Error when root contains deprecated
collections field (ADR-0003)". That test asserts the current behaviour and would
move from tester.errors to tester.warnings as part of the fix.
All local edits were then reverted; git status clean at 08c05cdee7e191719480477056bd145abcb09c17.
Upstream pin history
third-party/ard/README.md, against the upstream content at each pinned commit:
The port matches the first populated row in every column.
Existing issues checked
Searched open and closed issues for ard, ai-catalog, agentic, agent-discoverability, well-known, "ard.json", "rel=ard", "well-known/ard". No open or closed issue reports either defect. Two closed
issues are adjacent and were read in full before concluding this: #17082 (notes
the Chromium-146-vs-Chrome-150 mismatch, but the confirmed root cause was a
2-second fetch timeout, unrelated to either defect here) and #17194 (a false
negative on llms.txt caused by server-side cloaking, also unrelated to ard-schema). Neither addresses the ARD discovery path or the collections
severity.
The audit's own history, for context
The ard-schema audit was first proposed in #17158 (opened 2026-08-06), which was
closed without merging. The port that is live today merged in #17168 (2026-08-31),
carrying no upstream pin at all; the pin was introduced minutes later by #17171 and
has moved twice since.
Submission Type
Audit Name / Affected Audit
ard-schema(Agent Resource Discovery / ARD)Description & Rationale
Summary. The ARD audit in this repository follows ARD as it stood in June 2026:
its bundled conformance validator is a faithful port of the upstream conformance
test at that date, and its gatherer looks for the well-known path ARD specified at
that date.
ARD v0.91, published in August, changed three things: the well-known path a
consumer must fetch, the schema a manifest is validated against, and the severity
of a root
collectionsarray.The pinned upstream commit was then advanced past v0.91 twice, both times inside a
routine "deps: upgrade deps" PR (#17206, #17245), and the ported code was never
adapted to the changes the pin had just crossed.
Two consequences, both reproduced below: a site that follows the current specification
is invisible to this audit, and a manifest that ARD considers valid scores 0.
Both confirmed at current HEAD (
08c05cdee7e191719480477056bd145abcb09c17,2026-09-18,
13.5.0) by reading source and reproducing locally.Defect 1: the audit looks for the wrong discovery path.
Seeing this needs no fixture. The audit's title is "
ai-catalog.jsonschema isvalid". Its description reads
and that description links to the ARD specification.
Follow the link to §5.1 "Discovery Mechanisms," the paragraph headed
"Consumer resolution (normative)", quoted verbatim and in full from
the published page (confirmed identical to
spec/ard.mdat the currentlypinned upstream commit):
The audit's own description says the opposite of the document it cites: it calls
the predecessor name required, where the linked specification says a consumer
needs it only as a courtesy.
Confirmed in source at HEAD,
core/gather/gatherers/agentic/ard.js:document.querySelector('link[rel~="ai-catalog" i]')parsed.get('rel', 'ai-catalog')(HTTPLinkheader)new URL('/.well-known/ai-catalog.json', finalDisplayedUrl)(fallback)Never
rel="ard", never/.well-known/ard.json. A publisher who follows thespec's own MUST and serves only
/.well-known/ard.jsonis invisible to thisaudit: it reports
notApplicable, not a failure, so nothing in the report sayswhy.
Defect 2: a manifest ARD considers valid scores 0.
A manifest carrying a
collectionsarray at its root fails this audit outright.Upstream, at the commit this port currently pins, says that manifest is valid:
There are two independent causes, and fixing either one alone still scores 0. All
four states were run on the same fixture: as shipped, severity fixed alone, schema
fixed alone, both fixed. Scores 0, 0, 0, 0.9.
third-party/ard/ard.jscallsadd_errorfor thecollectionscheck where upstream calls
add_warning.core/audits/agentic/ard-schema.jssets
score = 0on any Error before it tests for Low severity, so the checknever reaches the audit's existing Low severity path, which scores 0.9 instead
of failing (the behaviour specified for this audit's non-fatal issues in
core(ard): add support for partial scores audit results #17181).
which is
additionalProperties: false, so any unrecognized root member is ahard Error, while the reference conformance test validates against a definition
that is deliberately open. Reasoning and file names in the collapsed section.
Each cause is sufficient on its own to hold the score at 0, which is why the two
fixes have to ship together.
Target Agents
Not applicable: this is a conformance and scoring defect in an existing audit, not
a new-signal proposal.
Proposed Implementation / Suggested Improvement
core/gather/gatherers/agentic/ard.js: check/.well-known/ard.json(andrel="ard",Link: rel="ard") first, falling back to the existingai-catalogpaths, matching the spec's own MUST/MAY order in §5.1. The audit'stitle,failureTitleanddescriptionstrings need the same correction.third-party/ard/ard.js: change thecollections-at-root check fromadd_errortoadd_warning, so it lands on the existing Low severity path.build/build-ard-schema.js: compile the validator fromspec/schemas/ard-entry.schema.json's$defs.ArdManifest, as the referenceconformance test does, instead of
ai-catalog.schema.json.core/scripts/update-ard-spec.jsfetches the predecessor schema by hardcodedpath and needs the same change to stay correct.
Items 2 and 3 are one fix. Both were also measured separately, and each on its own
still scores 0: either alone leaves the audit failing a manifest the specification
says is valid.
Example URL
None: Defect 1 is visible in any report that ran this audit, and both defects are
reproduced with a local fixture in the collapsed section below.
Reproduction, schema detail, pin history, and why the weekly sync check did not catch either
Defect 2, cause 2: the schema, in full
build/build-ard-schema.jscompilesthird-party/ard/spec/schemas/ai-catalog.schema.json, which isadditionalProperties: false, so any unrecognized root member is a schemaError. That is precisely what the second half of the upstream sentence quoted
above, "ARD ignores unrecognized top-level members", says must not happen.
Upstream's conformance test does not open that file. It validates the manifest
against
spec/schemas/ard-entry.schema.json's$defs.ArdManifest, whose owndescription reads "any other top-level members are transport-defined and ignored
by ARD, so additionalProperties is open", and which is
additionalProperties: true.ai-catalog.schema.jsonis still present upstream; it is the predecessorartefact, and the conformance test stopped using it in v0.91. The port reads it
because that is what upstream read in June 2026.
So the effect is broader than
collections: any unrecognized root member failsthis audit, and the specification says ARD ignores all of them.
Why the weekly ARD sync check (#17171) did not catch either
core/scripts/update-ard-spec.jshasRELEVANT_PREFIXES = ['spec/schemas/', 'conformance/']. Defect 1 lives inspec/ard.md, outside that list byconstruction, so no upstream change to the discovery rules can raise a flag at
all.
Defect 2 lives in
conformance/bin/conformance-test, which the check does watch,so upstream's change of 2026-08-26 was visible. But the check's output is a diff
printed for a human to read. Step 2 of this port's own documented update procedure
is:
Nothing enforces that step, and the one file the script updates automatically is
hardcoded: it fetches
spec/schemas/ai-catalog.schema.json, the predecessor theconformance test no longer uses. The mechanism advances the pin and refreshes the
wrong schema, and nothing prompts revisiting
ard.js.Reproduction: source at HEAD, Chrome 153 headless, local, not PageSpeed Insights
Environment: Lighthouse
13.5.0at commit08c05cdee7e191719480477056bd145abcb09c17(2026-09-18), run against Chrome
153.0.8010.53headless (--headless=new). Thatis the environment this reproduction was run in, with nothing implied about any
other runner's version.
Config used for every run (
ard-only-config.js):Fixture manifest, spec-compliant, no
collections(manifest-clean.json):{ "specVersion": "1.0", "entries": [{ "identifier": "urn:air:example.com:catalog:main-agent", "displayName": "Example Agent Catalog", "type": "application/ai-catalog+json", "url": "https://example.com/agents/main", "representativeQueries": ["find agents on example.com", "list the example.com catalog"] }] }Any minimal static server works, serving that file at exactly one well-known
path per run, plus a bare
/page.Scenario A, spec-compliant,
/.well-known/ard.jsononly (the MUST path):Result:
{"id": "ard-schema", "score": null, "scoreDisplayMode": "notApplicable"}.A fully valid manifest, at the path the linked specification says a conformant
consumer MUST fetch, is invisible to the audit.
Scenario B, identical manifest,
/.well-known/ai-catalog.jsononly (thepredecessor path):
Same command against a server serving the byte-identical file at the old path.
Result:
{"id": "ard-schema", "score": 1, "scoreDisplayMode": "binary"}. Samebytes, correctly detected and scored, once served at the path the spec demoted.
Scenario C,
collections: []added at root, served at/.well-known/ai-catalog.json(so the audit runs). Run in four states:(a) as shipped, score 0
{"id": "ard-schema", "score": 0, "scoreDisplayMode": "binary", "details": {"items": [ {"element": "Root", "issue": "JSON Schema Validation Failed: must NOT have additional properties at path 'root'", "severity": "Error"}, {"element": "Root", "issue": "Deprecated field check: Found 'collections' array at root. Top-level collections were REMOVED in ADR-0003. Catalog hierarchies MUST be modeled inside 'entries' using 'type: application/ai-catalog+json'.", "severity": "Error"} ]}}(b)
add_errorchanged toadd_warningon thecollectionscheck, nothingelse, still score 0
{"id": "ard-schema", "score": 0, "scoreDisplayMode": "binary", "details": {"items": [ {"element": "Root", "issue": "JSON Schema Validation Failed: must NOT have additional properties at path 'root'", "severity": "Error"}, {"element": "Root", "issue": "Deprecated field check: Found 'collections' array at root. ...", "severity": "Low"} ]}}core/audits/agentic/ard-schema.jssetsscore = 0on any Error before testingfor Low severity, so the schema Error alone holds the score at 0.
(c) validator compiled from
ard-entry.schema.json's$defs.ArdManifest, thecollectionscheck left asadd_error, score 0{"id": "ard-schema", "score": 0, "scoreDisplayMode": "binary", "details": {"items": [ {"element": "Root", "issue": "Deprecated field check: Found 'collections' array at root. Top-level collections were REMOVED in ADR-0003. Catalog hierarchies MUST be modeled inside 'entries' using 'type: application/ai-catalog+json'.", "severity": "Error"} ]}}The schema Error is gone and the remaining Error is the
collectionscheck itself,which is enough to keep the score at 0. Together with (b) this is why items 2 and 3
of the proposal are one fix: neither is sufficient alone.
(d) both, (b) plus (c), score 0.9
{"id": "ard-schema", "score": 0.9, "scoreDisplayMode": "binary", "details": {"items": [ {"element": "Root", "issue": "Deprecated field check: Found 'collections' array at root. ...", "severity": "Low"} ]}}For the schema change in (c) and (d),
build/build-ard-schema.jswas pointed atard-entry.schema.jsonwithschema['$ref'] = '#/$defs/ArdManifest', the same variant construction upstream'sas_def("ArdManifest")performs, thennode build/build-ard-schema.js. Oneincidental adjustment was needed: the build script strips
require("ajv-formats/dist/formats")out of the standalone output by matching theliteral variable names
formats0andformats10, and Ajv numbers those perschema, so the rewrite has to be generalised to
formats\d+or the generatedmodule throws
require is not definedon import.Regression check. Scenario B (clean manifest, no
collections) re-run in state(d):
{"score": 1, "scoreDisplayMode": "binary"}, zero detail items. The schemachange does not affect the clean case.
node core/test/scripts/run-mocha-tests.js third-party/ard/ard-test.jsin state(d): 12 passing, 1 failing, "fails with Error when root contains deprecated
collections field (ADR-0003)". That test asserts the current behaviour and would
move from
tester.errorstotester.warningsas part of the fix.All local edits were then reverted;
git statusclean at08c05cdee7e191719480477056bd145abcb09c17.Upstream pin history
third-party/ard/README.md, against the upstream content at each pinned commit:collectionsard.jsonin spec47042e5c(#17171)add_errorai-catalog.schema.jsonaa3e598(#17206)add_warningard-entry.schema.jsonb76f235a(#17245)add_warningard-entry.schema.jsonThe port matches the first populated row in every column.
Existing issues checked
Searched open and closed issues for
ard,ai-catalog,agentic,agent-discoverability,well-known,"ard.json","rel=ard","well-known/ard". No open or closed issue reports either defect. Two closedissues are adjacent and were read in full before concluding this: #17082 (notes
the Chromium-146-vs-Chrome-150 mismatch, but the confirmed root cause was a
2-second fetch timeout, unrelated to either defect here) and #17194 (a false
negative on
llms.txtcaused by server-side cloaking, also unrelated toard-schema). Neither addresses the ARD discovery path or thecollectionsseverity.
The audit's own history, for context
The
ard-schemaaudit was first proposed in #17158 (opened 2026-08-06), which wasclosed without merging. The port that is live today merged in #17168 (2026-08-31),
carrying no upstream pin at all; the pin was introduced minutes later by #17171 and
has moved twice since.