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
40 changes: 40 additions & 0 deletions consumers.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "Registry of repositories that consume @wasmagent/protocol as an npm dependency, and the supported version band.",
"consumers": [
{
"repo": "WasmAgent/wasmagent-js",
"packageJsonPath": "package.json",
"version": "^0.1.5",
"notes": "Primary consumer; placeholder version until the repo actually adds the dependency."
},
{
"repo": "WasmAgent/wasmagent-proxy",
"packageJsonPath": "package.json",
"version": "^0.1.0",
"notes": "Placeholder version until the repo actually adds the dependency."
},
{
"repo": "WasmAgent/trace-pipeline",
"packageJsonPath": "package.json",
"version": "^0.1.0",
"notes": "Placeholder version until the repo actually adds the dependency."
},
{
"repo": "WasmAgent/wasmagent-train-replay",
"packageJsonPath": "package.json",
"version": "^0.1.0",
"notes": "Placeholder version until the repo actually adds the dependency."
},
{
"repo": "WasmAgent/open-agent-audit",
"packageJsonPath": "package.json",
"version": "^0.1.0",
"notes": "Placeholder version until the repo actually adds the dependency."
}
],
"supportedBand": {
"min": "0.1.0",
"max": "0.1.99"
}
}
22 changes: 22 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,25 @@ export const schemas: Record<string, unknown>;
* (e.g. "aep-record", "constraint-ir"). Throws on unknown id.
*/
export function getSchema(id: string): unknown;

export interface ConsumerEntry {
repo: string;
packageJsonPath: string;
version?: string;
notes?: string;
}

export interface SupportedBand {
min: string;
max: string;
}

export interface ConsumerRegistry {
$schema: string;
description: string;
consumers: ConsumerEntry[];
supportedBand: SupportedBand;
}

/** Machine-readable registry of repositories that consume @wasmagent/protocol. */
export const consumerRegistry: ConsumerRegistry;
3 changes: 3 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ export function getSchema(id) {

/** All schemas as a plain object keyed by id. */
export const schemas = Object.fromEntries(index.schemas.map((s) => [s.id, getSchema(s.id)]));

/** Machine-readable registry of repositories that consume @wasmagent/protocol. */
export const consumerRegistry = JSON.parse(readFileSync(join(here, 'consumers.json'), 'utf8'));
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/*",
"./consumers.json": "./consumers.json"
},
"files": [
"index.js",
"index.d.ts",
"schemas/"
"schemas/",
"consumers.json"
],
"scripts": {
"test": "node --test"
Expand Down
16 changes: 15 additions & 1 deletion tests/loader.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import assert from 'node:assert/strict';
import { test } from 'node:test';
import { getSchema, index, schemas } from '../index.js';
import { consumerRegistry, getSchema, index, schemas } from '../index.js';

test('registry lists at least one schema', () => {
assert.ok(index.schemas.length >= 1);
Expand All @@ -23,3 +23,17 @@ test('schemas map is keyed by id', () => {
test('getSchema throws on unknown id', () => {
assert.throws(() => getSchema('does-not-exist'), /unknown schema id/);
});

test('consumerRegistry has required structure', () => {
assert.ok(Array.isArray(consumerRegistry.consumers));
assert.ok(consumerRegistry.consumers.length >= 1, 'at least one consumer required');
assert.equal(typeof consumerRegistry.supportedBand.min, 'string');
assert.equal(typeof consumerRegistry.supportedBand.max, 'string');
});

test('consumerRegistry entries have repo and packageJsonPath', () => {
for (const entry of consumerRegistry.consumers) {
assert.ok(entry.repo, `consumer missing repo: ${JSON.stringify(entry)}`);
assert.ok(entry.packageJsonPath, `consumer missing packageJsonPath: ${JSON.stringify(entry)}`);
}
});
54 changes: 54 additions & 0 deletions tests/test_conformance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Pytest wrapper around the conformance harness.
# The conformance script is a standalone CLI; this module lets
# `pytest tests/` discover and run it as a test.

from __future__ import annotations

import json
import subprocess
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent
CONFORMANCE = ROOT / "tests" / "conformance.py"
CONSUMERS_JSON = ROOT / "consumers.json"


def test_conformance_script_passes():
"""Run the conformance harness; it must exit 0."""
result = subprocess.run(
[sys.executable, str(CONFORMANCE)],
capture_output=True,
text=True,
)
assert result.returncode == 0, (
f"conformance.py failed (exit {result.returncode}):\n"
f"stdout: {result.stdout}\n"
f"stderr: {result.stderr}"
)


def test_consumers_json_exists_and_is_valid():
"""consumers.json must exist and be valid JSON with required fields."""
assert CONSUMERS_JSON.is_file(), "consumers.json does not exist"
doc = json.loads(CONSUMERS_JSON.read_text(encoding="utf-8"))

# Top-level shape
assert "consumers" in doc, "missing 'consumers' key"
assert "supportedBand" in doc, "missing 'supportedBand' key"

# supportedBand must have min and max
band = doc["supportedBand"]
assert "min" in band, "supportedBand missing 'min'"
assert "max" in band, "supportedBand missing 'max'"

# At least one consumer entry
assert isinstance(doc["consumers"], list), "'consumers' must be a list"
assert len(doc["consumers"]) >= 1, "consumers list must have >= 1 entry"

# Each consumer must have 'repo' and 'packageJsonPath'
for entry in doc["consumers"]:
assert "repo" in entry, f"consumer entry missing 'repo': {entry}"
assert "packageJsonPath" in entry, (
f"consumer entry missing 'packageJsonPath': {entry}"
)
Loading