Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,26 @@ Agent Cards v1.1.0 is intentionally flat:
- current cards bind **directly** to `commandlayer.org` mirror URLs
- current v1.1.0 uses **no `_shared`**

## Validation and release trust

The default reviewer path is the current canonical line.

```bash
npm install
npm run validate
```

Validation commands are intentionally split by authority surface:

- `npm run validate` — release-facing validation for the current canonical line; runs current discovery validation, current v1.1.0 card validation, checksum verification, and typecheck
- `npm run validate:current` — current discovery + current v1.1.0 cards only
- `npm run validate:legacy` — archival/compatibility validation for `agents/v1.0.0/`
- `npm run validate:checksums` — verifies `checksums.txt` against tracked release artifacts
- `npm run validate:release` — explicit alias for the full current release flow used by CI
- `npm run validate:cards` — runs both current and legacy card schema/path validation when a maintainer wants a full repository sweep

`npm run validate` is the command reviewers should trust most because it centers the current release line instead of the compatibility archive.

## How card bindings work

For `v1.1.0`:
Expand Down
3 changes: 3 additions & 0 deletions agents/v1.0.0/commercial/verifyagent.eth.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
"payments",
"settlement",
"protocol-reference"
],
"notes": [
"Legacy commercial v1.0.0 cards are preserved without mirror URLs because no canonical IPFS mirror binding was recorded for this line."
]
},
"networks": [
Expand Down
16 changes: 14 additions & 2 deletions scripts/validate-cards.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ const expectedV11 = {
commercial: commercialVerbs.map((verb) => `${verb}agent.eth.json`)
};

const VALIDATION_MODES = new Set(["current", "legacy", "all"]);
const CURRENT_DESCRIPTOR_PATHS = [
".well-known/agent.json",
".well-known/agent-cards-v1.1.0.json"
];

const ajv = new Ajv2020({ strict: true, allErrors: true });
addFormats(ajv);

Expand Down Expand Up @@ -110,15 +116,21 @@ function validateCard(fullPath) {
const primaryVerb = card.implements[0];
const expectedId = `https://commandlayer.org/agent-cards/${relativePath}`;
const expectedEntry = `x402://${card.ens}/${primaryVerb}/v${card.version}`;
const semverFolder = folderVersion.replace(/^v/, "");
const expectedSchema = "https://commandlayer.org/agent-cards/schemas/v1.1.0/agent.card.schema.json";
const rawCommons = /^https:\/\/raw\.githubusercontent\.com\/commandlayer\/protocol-commons\/refs\/tags\/v1\.1\.0\/schemas\/v1\.1\.0\/commons\/([^/]+)\/\1\.(request|receipt)\.schema\.json$/;
const rawCommercial = /^https:\/\/raw\.githubusercontent\.com\/commandlayer\/protocol-commercial\/refs\/tags\/v1\.1\.0\/schemas\/v1\.1\.0\/commercial\/([^/]+)\/\1\.(request|receipt)\.schema\.json$/;
const mirrorCommons = /^https:\/\/commandlayer\.org\/schemas\/v1\.1\.0\/commons\/([^/]+)\/\1\.(request|receipt)\.schema\.json$/;
const mirrorCommercial = /^https:\/\/commandlayer\.org\/schemas\/v1\.1\.0\/commercial\/([^/]+)\/\1\.(request|receipt)\.schema\.json$/;

if (card.version !== semverFolder) fail(`${relativePath}: version mismatch.`);
if (card.version !== folderVersion.replace(/^v/, "")) fail(`${relativePath}: version mismatch.`);
if (card.$id !== expectedId) fail(`${relativePath}: $id mismatch.`);
if (card.$schema !== expectedSchema) fail(`${relativePath}: stale or invalid $schema.`);
if (card.entry !== expectedEntry) fail(`${relativePath}: entry mismatch.`);
if (card.id !== card.ens) fail(`${relativePath}: id must equal ens.`);
if (card.class !== tier) fail(`${relativePath}: class mismatch.`);
if (fileName !== `${card.ens}.json`) fail(`${relativePath}: filename mismatch.`);
if (new Date(card.updated_at).getTime() < new Date(card.created_at).getTime()) fail(`${relativePath}: updated_at must be >= created_at.`);
if (JSON.stringify(card).includes("_shared")) fail(`${relativePath}: current v1.1.0 card must not reference _shared.`);

if (folderVersion === CURRENT_LINE) {
const expectedSchema = `https://commandlayer.org/agent-cards/schemas/${CURRENT_LINE}/agent.card.schema.json`;
Expand Down
Loading