Freeze the v0.1 contract and the local ingest connector.

The snapshot and manifest schemas, both example dataspaces, and the shared text renderer now pass the fixture validator and the negative contract tests. JSON, NDJSON, and Markdown frontmatter publish a snapshot only when rights, identity, and references allow it. CONTENT-WP-0001 and CONTENT-WP-0003 are marked finished against those artifacts. CONTENT-WP-0000-T04 stays open. SCOPE.md and the 19:05 scope-against-intent note record the stop.

Assistant: grok
Assistant-Session: 01a130f1-abfb-7d71-9cd6-a8b75ec7f95a
This commit is contained in:
tegwick 2026-10-12 19:07:32 +02:00
parent 2b1706559b
commit 072a7fa550
30 changed files with 1896 additions and 264 deletions

View file

@ -1,27 +1,33 @@
#!/usr/bin/env python3
"""Portable smoke validator: structural and cross-reference checks; not full JSON Schema compliance."""
"""Validate every example dataspace against the v0.1 contract."""
from __future__ import annotations
import sys
from pathlib import Path
import json, sys
ROOT = Path(__file__).resolve().parent.parent
errors=[]
for path in sorted((ROOT/'examples/dataspaces').glob('*/snapshot.json')):
d=json.loads(path.read_text())
kinds={r['id'] for r in d['kinds']}; ids=[r['id'] for r in d['entities']]
sources={r['id'] for r in d['sources']}
if d['schemaVersion']!='0.1': errors.append(f'{path}: schemaVersion')
if len(ids)!=len(set(ids)): errors.append(f'{path}: duplicate entities')
for e in d['entities']:
if e['kindId'] not in kinds: errors.append(f'{path}: undeclared kind {e["kindId"]}')
for sid in e.get('sourceRefs',[]):
if sid not in sources: errors.append(f'{path}: missing source {sid}')
for r in d['relations']:
for field in ('from','to'):
if r[field] not in ids: errors.append(f'{path}: dangling {field} {r[field]}')
for sid in r.get('sourceRefs',[]):
if sid not in sources: errors.append(f'{path}: missing edge source {sid}')
manifest=json.loads((path.parent/'manifest.json').read_text())
if manifest['id']!=d['dataspace']['id']: errors.append(f'{path}: manifest ID mismatch')
print(f'{d["dataspace"]["id"]}: {len(ids)} entities, {len(d["relations"])} relations, {len(kinds)} kinds')
if errors:
print('\n'.join(errors),file=sys.stderr);sys.exit(1)
print('Smoke validation OK (full JSON Schema and claims pending).')
sys.path.insert(0, str(ROOT))
from content_explorer.contract import validate_dataspace # noqa: E402
def main() -> int:
errors: list[str] = []
directories = sorted((ROOT / "examples" / "dataspaces").glob("*/snapshot.json"))
if not directories:
print("no dataspace fixtures found", file=sys.stderr)
return 1
for snapshot_path in directories:
directory = snapshot_path.parent
found = validate_dataspace(directory, require_size=True)
errors.extend(found)
if not found:
print(f"{directory.name}: contract ok")
if errors:
print("\n".join(errors), file=sys.stderr)
return 1
print("Fixture validation OK")
return 0
if __name__ == "__main__":
raise SystemExit(main())