Skip to content
Closed
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
69 changes: 69 additions & 0 deletions aep-conformance/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# `aep-conformance/` — AEP record conformance fixture set

A versioned corpus of **valid** and **invalid** `aep-record` instances, published
inside the [`@wasmagent/protocol`](https://www.npmjs.com/package/@wasmagent/protocol)
package so that any Agent Evidence Protocol emitter can self-check:

> _Does my output validate against the canonical record contract?_

This is the consumer-facing counterpart to the repository's internal
[`tests/fixtures/`](../tests/fixtures/) harness. Where `tests/fixtures/` holds one
example per schema to guard the repo itself, `aep-conformance/` is a richer,
deliberately enumerated set covering the distinct constraint regions of
`aep-record`, intended to be pointed at a real emitter's output.

## Layout

| Path | Purpose |
| --- | --- |
| [`manifest.json`](manifest.json) | Machine-readable index of every fixture: path, `valid` flag, description, and (for invalid cases) the `expect_keyword` the violation should trip. |
| `valid/*.json` | Records that **MUST pass** validation against [`schemas/aep/aep-record.schema.json`](../schemas/aep/aep-record.schema.json). |
| `invalid/*.json` | Records that **MUST fail**, each violating exactly one constraint, annotated in the manifest. |

## Coverage

- **Valid** — minimal record, the `aep/v0.1` legacy version, capability decisions +
actions + verifier results, a full budget ledger + run context, and input/output
refs with taint labels and redaction profiles.
- **Invalid** — `enum` (schema version, capability decision), `required` (missing
top-level / action / signature fields), and `type` (numeric field as string)
violations.

## Using it

Iterate `manifest.json`, load the schema from the package, and validate each
fixture — asserting the opposite result for `valid` vs `invalid`.

### JavaScript / TypeScript

```ts
import { readFileSync } from "node:fs";
import { createRequire } from "node:module";

// Fixture corpus + manifest ship inside the package under aep-conformance/.
const manifest = JSON.parse(
readFileSync(require.resolve("@wasmagent/protocol/aep-conformance/manifest.json"), "utf8"),
);

// Resolve the canonical schema and a validator from your toolchain (e.g. ajv).
const require = createRequire(import.meta.url);
const schema = require("@wasmagent/protocol/schemas/aep/aep-record.schema.json");
```

### Python

```python
import json
from importlib import resources
from wasmagent_protocol import get_schema

schema = get_schema("aep-record") # parsed canonical schema
manifest = json.loads(
(resources.files("wasmagent_protocol") / "aep_conformance" / "manifest.json")
.read_text("utf-8")
)
```

> The npm package exposes the corpus via `@wasmagent/protocol/aep-conformance/*`.
> Consumers iterate the manifest rather than hard-coding paths so the set can grow
> additively across versions.
13 changes: 13 additions & 0 deletions aep-conformance/invalid/bad-capability-decision.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"schema_version": "aep/v0.2",
"run_id": "run-bad-decision",
"created_at_ms": 1737600000000,
"capability_decisions": [
{
"capability": "fs.write",
"subject": "agent-1",
"resource": "/tmp/x",
"decision": "blocked"
}
]
}
5 changes: 5 additions & 0 deletions aep-conformance/invalid/bad-schema-version.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"schema_version": "aep/v9.9",
"run_id": "run-bad-version",
"created_at_ms": 1737600000000
}
13 changes: 13 additions & 0 deletions aep-conformance/invalid/bad-timestamp-type.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"schema_version": "aep/v0.2",
"run_id": "run-bad-ts-type",
"created_at_ms": 1737600000000,
"actions": [
{
"action_id": "a1",
"tool_name": "write_file",
"state_changing": true,
"timestamp_ms": "1737600000100"
}
]
}
12 changes: 12 additions & 0 deletions aep-conformance/invalid/missing-action-required.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"schema_version": "aep/v0.2",
"run_id": "run-action-missing-tool",
"created_at_ms": 1737600000000,
"actions": [
{
"action_id": "a1",
"state_changing": true,
"timestamp_ms": 1737600000100
}
]
}
4 changes: 4 additions & 0 deletions aep-conformance/invalid/missing-created-at-ms.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"schema_version": "aep/v0.2",
"run_id": "run-no-created"
}
4 changes: 4 additions & 0 deletions aep-conformance/invalid/missing-run-id.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"schema_version": "aep/v0.2",
"created_at_ms": 1737600000000
}
9 changes: 9 additions & 0 deletions aep-conformance/invalid/missing-signature-required.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"schema_version": "aep/v0.2",
"run_id": "run-sig-incomplete",
"created_at_ms": 1737600000000,
"signature": {
"alg": "ed25519",
"key_id": "k1"
}
}
79 changes: 79 additions & 0 deletions aep-conformance/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{
"name": "aep-conformance",
"description": "Machine-readable index of the aep-record conformance fixture set. Each entry names a fixture, whether it MUST pass (valid) or MUST fail (invalid) against the canonical aep-record schema, and for invalid cases the JSON Schema keyword the violation is expected to trip. Consumers iterate these fixtures to self-check their emitter output.",
"schema": {
"id": "aep-record",
"version": "aep/v0.2",
"canonical_id": "https://wasmagent.dev/schemas/aep/aep-record.schema.json",
"path": "schemas/aep/aep-record.schema.json"
},
"fixtures": [
{
"path": "valid/minimal.json",
"valid": true,
"description": "Minimal record carrying only the three required top-level fields (schema_version, run_id, created_at_ms)."
},
{
"path": "valid/v0.1.json",
"valid": true,
"description": "Record using the legacy aep/v0.1 schema_version plus optional scalar provenance fields."
},
{
"path": "valid/with-capabilities.json",
"valid": true,
"description": "Record exercising capability_decisions, actions, verifier_results, and the signature envelope."
},
{
"path": "valid/with-budget-ledger.json",
"valid": true,
"description": "Record exercising a fully-populated budget_ledger (all six budget kinds) and run_context."
},
{
"path": "valid/with-refs.json",
"valid": true,
"description": "Record exercising input_refs (with taint_labels) and output_refs (with redaction_profile)."
},
{
"path": "invalid/bad-schema-version.json",
"valid": false,
"description": "schema_version is outside the allowed aep/v0.1, aep/v0.2 enum.",
"expect_keyword": "enum"
},
{
"path": "invalid/missing-run-id.json",
"valid": false,
"description": "Missing the required run_id top-level field.",
"expect_keyword": "required"
},
{
"path": "invalid/missing-created-at-ms.json",
"valid": false,
"description": "Missing the required created_at_ms top-level field.",
"expect_keyword": "required"
},
{
"path": "invalid/bad-capability-decision.json",
"valid": false,
"description": "A capability decision uses a value outside the allow/deny/ask_user/dry_run enum.",
"expect_keyword": "enum"
},
{
"path": "invalid/missing-action-required.json",
"valid": false,
"description": "An action is missing the required tool_name field.",
"expect_keyword": "required"
},
{
"path": "invalid/bad-timestamp-type.json",
"valid": false,
"description": "An action timestamp_ms is a string rather than a number.",
"expect_keyword": "type"
},
{
"path": "invalid/missing-signature-required.json",
"valid": false,
"description": "The signature block is present but missing its required sig field.",
"expect_keyword": "required"
}
]
}
5 changes: 5 additions & 0 deletions aep-conformance/valid/minimal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"schema_version": "aep/v0.2",
"run_id": "run-minimal",
"created_at_ms": 1737600000000
}
9 changes: 9 additions & 0 deletions aep-conformance/valid/v0.1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"schema_version": "aep/v0.1",
"run_id": "run-v0-1",
"trace_id": "trace-v0-1",
"runtime_version": "wasmagent-js@1.19.0",
"model_provider": "anthropic",
"model_id": "claude-sonnet-5",
"created_at_ms": 1737600000000
}
22 changes: 22 additions & 0 deletions aep-conformance/valid/with-budget-ledger.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"schema_version": "aep/v0.2",
"run_id": "run-budget",
"trace_id": "trace-budget-001",
"created_at_ms": 1737600000000,
"budget_ledger": {
"token_budget": { "limit": 100000, "spent": 42300 },
"latency_budget": { "limit_ms": 30000, "actual_ms": 8421 },
"tool_budget": { "limit": 50, "spent": 3 },
"risk_budget": { "limit": 100, "spent": 12 },
"retry_budget": { "limit": 5, "spent": 0 },
"human_approval_budget": { "limit": 3, "spent": 1 }
},
"run_context": {
"agent_id": "agent-1",
"agent_version": "0.4.2",
"subagent_id": "sub-1",
"delegation_chain": ["agent-1", "sub-1"],
"environment_digest": "sha256:env",
"dependency_lock_digest": "sha256:lock"
}
}
50 changes: 50 additions & 0 deletions aep-conformance/valid/with-capabilities.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"schema_version": "aep/v0.2",
"run_id": "run-capabilities",
"trace_id": "trace-capabilities-001",
"parent_trace_id": null,
"repo_commit": "deadbeef",
"runtime_version": "wasmagent-js@1.20.0",
"created_at_ms": 1737600000000,
"capability_decisions": [
{
"capability": "fs.write",
"subject": "agent-1",
"resource": "/tmp/out.txt",
"decision": "allow"
},
{
"capability": "net.request",
"subject": "agent-1",
"resource": "https://example.com",
"decision": "deny",
"reason_code": "no_network_scope"
}
],
"actions": [
{
"action_id": "a1",
"tool_name": "write_file",
"state_changing": true,
"precondition_digest": "sha256:pre",
"result_digest": "sha256:post",
"evidence_refs": ["ev-1"],
"parent_action_id": "a0",
"causal_chain_id": "chain-1",
"timestamp_ms": 1737600000100
}
],
"verifier_results": [
{
"verifier_id": "symkernel-cel",
"passed": true,
"score": 1.0,
"claim_ids": ["claim-1"]
}
],
"signature": {
"alg": "ed25519",
"key_id": "k1",
"sig": "base64sig=="
}
}
24 changes: 24 additions & 0 deletions aep-conformance/valid/with-refs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"schema_version": "aep/v0.2",
"run_id": "run-refs",
"trace_id": "trace-refs-001",
"runtime_version": "wasmagent-js@1.20.0",
"policy_bundle_digest": "sha256:policy",
"tool_manifest_digest": "sha256:manifest",
"mcp_server_card_digest": null,
"created_at_ms": 1737600000000,
"input_refs": [
{
"uri": "file:///workspace/src/app.ts",
"digest": "sha256:in1",
"taint_labels": ["user-input"]
}
],
"output_refs": [
{
"uri": "file:///workspace/dist/app.js",
"digest": "sha256:out1",
"redaction_profile": "default"
}
]
}
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@
"types": "./index.d.ts",
"import": "./index.js"
},
"./schemas/*": "./schemas/*"
"./schemas/*": "./schemas/*",
"./aep-conformance/*": "./aep-conformance/*"
},
"files": [
"index.js",
"index.d.ts",
"schemas/"
"schemas/",
"aep-conformance/"
],
"scripts": {
"test": "node --test"
Expand Down
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,6 @@ packages = ["src/wasmagent_protocol"]
# from an installed wheel.
[tool.hatch.build.targets.wheel.force-include]
"schemas" = "wasmagent_protocol/schemas"
# Ship the aep-conformance fixture corpus so consumers can self-check their
# emitter output from an installed wheel (mirrors how schemas ship).
"aep-conformance" = "wasmagent_protocol/aep_conformance"
Loading
Loading