From 008f66257610a5a7408f62705446514afb5851d4 Mon Sep 17 00:00:00 2001 From: claude-bot-go Date: Sun, 26 Jul 2026 17:48:00 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20#104:=20[milestone=20Milestone=204=20]=20?= =?UTF-8?q?Add=20`schemas/aep/memory-evidence.schema.json`=20=E2=80=94=20t?= =?UTF-8?q?amper-evident=20memory=20read/wri...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 13 +++++++++ schemas/aep/memory-evidence.schema.json | 28 +++++++++++++++++++ schemas/index.json | 15 ++++++++++ .../invalid/memory-evidence/example.json | 8 ++++++ .../valid/memory-evidence/example.json | 14 ++++++++++ tests/test_conformance.py | 24 ++++++++++++++++ 6 files changed, 102 insertions(+) create mode 100644 package-lock.json create mode 100644 schemas/aep/memory-evidence.schema.json create mode 100644 tests/fixtures/invalid/memory-evidence/example.json create mode 100644 tests/fixtures/valid/memory-evidence/example.json create mode 100644 tests/test_conformance.py diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..edb03f9 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "@wasmagent/protocol", + "version": "0.1.5", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@wasmagent/protocol", + "version": "0.1.5", + "license": "Apache-2.0" + } + } +} diff --git a/schemas/aep/memory-evidence.schema.json b/schemas/aep/memory-evidence.schema.json new file mode 100644 index 0000000..0bac86e --- /dev/null +++ b/schemas/aep/memory-evidence.schema.json @@ -0,0 +1,28 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://wasmagent.dev/schemas/aep/memory-evidence.schema.json", + "title": "MemoryEvidence", + "description": "Tamper-evident memory read/write record — binds an agent memory access to a content digest and the digest of the memory state observed immediately before, so a chain of memory operations is verifiable and non-repudiable. Shares the AEP signature envelope.", + "type": "object", + "required": ["schema_version", "mem_ref", "op", "digest", "prior_digest", "timestamp_ms"], + "properties": { + "schema_version": { "type": "string", "enum": ["aep/v0.1"], "description": "Semver-like schema identifier for the memory-evidence evidence type" }, + "trace_id": { "type": "string", "description": "Optional correlation ID linking related evidence records" }, + "mem_ref": { "type": "string", "description": "Stable reference (URI or opaque id) of the memory cell or region accessed" }, + "op": { "type": "string", "enum": ["read", "write"], "description": "Memory operation performed against mem_ref" }, + "digest": { "type": "string", "description": "Content digest of the memory value read or written (e.g. sha256:...)" }, + "prior_digest": { "type": ["string", "null"], "description": "Content digest of the memory cell immediately before this op; null on a cold read / first write so the chain start is explicit" }, + "timestamp_ms": { "type": "number", "description": "UTC epoch milliseconds when the memory op was recorded" }, + "signature": { + "type": "object", + "description": "Optional tamper-evident signature over the record content", + "required": ["alg", "key_id", "sig"], + "properties": { + "alg": { "type": "string", "description": "Signature algorithm, e.g. ed25519" }, + "key_id": { "type": "string", "description": "Identifier of the signing key" }, + "sig": { "type": "string", "description": "Base64-encoded signature bytes" } + }, + "additionalProperties": false + } + } +} diff --git a/schemas/index.json b/schemas/index.json index 8afcecb..4d1f7e1 100644 --- a/schemas/index.json +++ b/schemas/index.json @@ -41,6 +41,21 @@ ], "summary": "Shared envelope base for all AEP evidence records \u2014 schema_version, trace_id, created_at_ms, and optional signature." }, + { + "id": "memory-evidence", + "title": "MemoryEvidence", + "path": "schemas/aep/memory-evidence.schema.json", + "canonical_id": "https://wasmagent.dev/schemas/aep/memory-evidence.schema.json", + "version": "aep/v0.1", + "stability": "evolving", + "owners": [ + "wasmagent-protocol" + ], + "consumers": [ + "wasmagent-js" + ], + "summary": "Tamper-evident memory read/write record \u2014 binds a memory access to a content digest and the prior state digest so a chain of memory operations is verifiable." + }, { "id": "constraint-ir", "title": "ConstraintIR", diff --git a/tests/fixtures/invalid/memory-evidence/example.json b/tests/fixtures/invalid/memory-evidence/example.json new file mode 100644 index 0000000..4328f99 --- /dev/null +++ b/tests/fixtures/invalid/memory-evidence/example.json @@ -0,0 +1,8 @@ +{ + "schema_version": "aep/v0.1", + "mem_ref": "mem://agent-1/context-window", + "op": "delete", + "digest": "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", + "prior_digest": null, + "timestamp_ms": 1737600000200 +} diff --git a/tests/fixtures/valid/memory-evidence/example.json b/tests/fixtures/valid/memory-evidence/example.json new file mode 100644 index 0000000..36c007f --- /dev/null +++ b/tests/fixtures/valid/memory-evidence/example.json @@ -0,0 +1,14 @@ +{ + "schema_version": "aep/v0.1", + "trace_id": "trace-mem-001", + "mem_ref": "mem://agent-1/context-window", + "op": "write", + "digest": "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", + "prior_digest": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "timestamp_ms": 1737600000200, + "signature": { + "alg": "ed25519", + "key_id": "mem-key-001", + "sig": "base64sig==" + } +} diff --git a/tests/test_conformance.py b/tests/test_conformance.py new file mode 100644 index 0000000..99eae3f --- /dev/null +++ b/tests/test_conformance.py @@ -0,0 +1,24 @@ +"""Pytest entry point for the conformance harness. + +`tests/conformance.py` is a standalone script (run via `python3 tests/conformance.py` +in CLAUDE.md / CI). This thin wrapper re-exposes it under pytest so `pytest tests/` +collects and runs the same invariants — every schema well-formed, refs resolve, +index entries match on-disk `$id`s, and each registered schema has VALID fixtures +that pass plus INVALID fixtures that fail. It owns no logic of its own. +""" +from __future__ import annotations + +import sys +from pathlib import Path + +# tests/ is not a package; put it on sys.path so `import conformance` works +# regardless of pytest's invocation cwd. +TESTS_DIR = Path(__file__).resolve().parent +if str(TESTS_DIR) not in sys.path: + sys.path.insert(0, str(TESTS_DIR)) + +import conformance # noqa: E402 + + +def test_conformance_harness_passes() -> None: + assert conformance.main() == 0