Complete G7 reciprocal canon interfaces and source-review evidence
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a070b5-4994-7271-bd8b-7c3dbcedec4b
This commit is contained in:
parent
942d345cb5
commit
49b03943c8
8 changed files with 373 additions and 5 deletions
|
|
@ -16,8 +16,8 @@
|
||||||
| task | CFED-WP-0001-T05 | done | — | workplans/CFED-WP-0001-foundation.md |
|
| task | CFED-WP-0001-T05 | done | — | workplans/CFED-WP-0001-foundation.md |
|
||||||
| task | CFED-WP-0001-T06 | done | — | workplans/CFED-WP-0001-foundation.md |
|
| task | CFED-WP-0001-T06 | done | — | workplans/CFED-WP-0001-foundation.md |
|
||||||
| task | CFED-WP-0001-T07 | done | — | workplans/CFED-WP-0001-foundation.md |
|
| task | CFED-WP-0001-T07 | done | — | workplans/CFED-WP-0001-foundation.md |
|
||||||
| task | CFED-WP-0001-T08 | todo | — | workplans/CFED-WP-0001-foundation.md |
|
| task | CFED-WP-0001-T08 | done | — | workplans/CFED-WP-0001-foundation.md |
|
||||||
| task | CFED-WP-0001-T09 | wait | — | workplans/CFED-WP-0001-foundation.md |
|
| task | CFED-WP-0001-T09 | todo | — | workplans/CFED-WP-0001-foundation.md |
|
||||||
| task | CFED-WP-0001-T10 | wait | — | workplans/CFED-WP-0001-foundation.md |
|
| task | CFED-WP-0001-T10 | wait | — | workplans/CFED-WP-0001-foundation.md |
|
||||||
| task | CFED-WP-0001-T11 | done | — | workplans/CFED-WP-0001-foundation.md |
|
| task | CFED-WP-0001-T11 | done | — | workplans/CFED-WP-0001-foundation.md |
|
||||||
| task | CFED-WP-0001-T12 | done | — | workplans/CFED-WP-0001-foundation.md |
|
| task | CFED-WP-0001-T12 | done | — | workplans/CFED-WP-0001-foundation.md |
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,10 @@ for row in manifest['imports']:
|
||||||
text = historical.decode()
|
text = historical.decode()
|
||||||
if text.startswith('---\n'):
|
if text.startswith('---\n'):
|
||||||
upstream_fm = yaml.safe_load(text.split('---')[1])
|
upstream_fm = yaml.safe_load(text.split('---')[1])
|
||||||
upstream_owned = set(upstream_fm['owned_concepts'])
|
upstream_owned = set(upstream_fm.get('owned_concepts', []))
|
||||||
|
# Organization frontmatter records only its incremental social extension.
|
||||||
|
# Include explicit legacy definitions, never bare imported anchors.
|
||||||
|
upstream_owned.update(re.findall(r'^(?:An? )?\*\*(.+?)\*\* is\b', text, re.M))
|
||||||
else:
|
else:
|
||||||
upstream_owned = set(re.findall(r'^## \d+\.\d+[a-z]? (.+)$', text, re.M))
|
upstream_owned = set(re.findall(r'^## \d+\.\d+[a-z]? (.+)$', text, re.M))
|
||||||
assert set(row['concepts']) <= upstream_owned, set(row['concepts']) - upstream_owned
|
assert set(row['concepts']) <= upstream_owned, set(row['concepts']) - upstream_owned
|
||||||
|
|
|
||||||
15
docs/evidence/2026-09-06-interface-cards.json
Normal file
15
docs/evidence/2026-09-06-interface-cards.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"gate": "G7",
|
||||||
|
"result": "pass",
|
||||||
|
"cards": 3,
|
||||||
|
"reciprocal_peer_links": 6,
|
||||||
|
"import_edges": 6,
|
||||||
|
"ledger_concepts_and_seed_covered": 59,
|
||||||
|
"imported_concepts": 25,
|
||||||
|
"historical_and_current_import_blobs_checked": 8,
|
||||||
|
"source_commit": "372f671eef861e3f180eb5f9fc2fbd8c479ef8b7",
|
||||||
|
"upstream_changes_since_review": [],
|
||||||
|
"navigation_links_checked": 27,
|
||||||
|
"custodian_domain_concepts": 0,
|
||||||
|
"family": "seeded-not-authored"
|
||||||
|
}
|
||||||
100
docs/evidence/2026-09-06-interface-cards.md
Normal file
100
docs/evidence/2026-09-06-interface-cards.md
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
# G7 — Reciprocal canon interfaces, 2026-09-06
|
||||||
|
|
||||||
|
CFED-WP-0001-T08 publishes three repository-owned cards:
|
||||||
|
|
||||||
|
- [InfoTechCanon](../../../info-tech-canon/infospace/interfaces/federation.yaml), implemented by [INFO-WP-0025](../../../info-tech-canon/workplans/INFO-WP-0025-federation-interface.md).
|
||||||
|
- [CommerceCanon](../../../commerce-canon/infospace/interfaces/federation.yaml), implemented by [COMMERCE-WP-0004](../../../commerce-canon/workplans/COMMERCE-WP-0004-federation-interface.md).
|
||||||
|
- [Custodian canon](../../../the-custodian/canon/interfaces/federation.yaml), implemented by [THE-WP-0001](../../../the-custodian/workplans/THE-WP-0001-federation-interface.md).
|
||||||
|
|
||||||
|
The cards follow InfoTechCanonCore §24 and its existing JSON Schema. They name
|
||||||
|
source authority, imports, available exports, source-of-truth boundaries,
|
||||||
|
limitations, and both peer cards. Card shape uses the schema's string consumer
|
||||||
|
and array canon_surfaces; richer Core fields are additive. This does not claim
|
||||||
|
a new standardized runtime exchange protocol or repair every older card template.
|
||||||
|
|
||||||
|
Six reciprocal peer links and six actual import edges are checked: each domain
|
||||||
|
canon imports accepted CUST-ADR-006 governance; Commerce also imports four
|
||||||
|
InfoTech models. A reciprocal navigation link does not invent a reverse semantic
|
||||||
|
import. Custodian exports accepted federation governance, owns no domain
|
||||||
|
semantics, and leaves the accepted ADR unchanged.
|
||||||
|
|
||||||
|
Exports cover all 58 ledger domain concepts and the separately classified Family
|
||||||
|
seed. Non-canonical convenience terms remain in model resolution guidance, not
|
||||||
|
new canonical roots. Community/Household remain the draft social extension;
|
||||||
|
Family remains seeded-not-authored. No stable model promotion or consumer
|
||||||
|
adoption is asserted.
|
||||||
|
|
||||||
|
## Explicit upstream review
|
||||||
|
|
||||||
|
Commerce retains its [original import manifest](../../../commerce-canon/infospace/models/counterparty/import-history/2026-09-05-imports.json)
|
||||||
|
byte-for-byte against published Commerce revision
|
||||||
|
`bc67e1f25b140ecb60d1439de984f8361acabc32` (SHA-256
|
||||||
|
`60a6c5187f1e208dcf763913d4d6a98840bc934d238f25d660c8ff3b5ea241d9`).
|
||||||
|
The [review record](../../../commerce-canon/infospace/models/counterparty/import-review-2026-09-06.md)
|
||||||
|
advances the upstream source from `361c944325934ccdb190470baf6f55440b6b486e` to
|
||||||
|
`372f671eef861e3f180eb5f9fc2fbd8c479ef8b7`. Only the organization source changed:
|
||||||
|
the social-collective extension and incremental ownership metadata. All 25
|
||||||
|
imported concepts remain the same. Current kernel references acknowledge the
|
||||||
|
completed extension and Family seed without adopting either as a new Counterparty
|
||||||
|
import. Eight source blobs verify both revisions and their hashes.
|
||||||
|
|
||||||
|
The T06 reproducer now recognizes explicit legacy definitions alongside
|
||||||
|
incremental frontmatter; bare retained import anchors never establish ownership.
|
||||||
|
No historical workplan, ADR, original research or frozen assimilation source was
|
||||||
|
rewritten.
|
||||||
|
|
||||||
|
## Validation
|
||||||
|
|
||||||
|
[Machine-readable result](2026-09-06-interface-cards.json) records G7 pass.
|
||||||
|
Reproduce from this repository with adjacent canon checkouts:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 tools/validate_interfaces.py --workspace ..
|
||||||
|
python3 -m unittest discover -s tools -p 'test*.py'
|
||||||
|
python3 tools/validate_ownership.py --source-repo ../commerce-canon
|
||||||
|
python3 tools/validate_corpus.py --commerce-repo ../commerce-canon --info-tech-repo ../info-tech-canon
|
||||||
|
python3 docs/evidence/2026-09-05-counterparty-validate.py --commerce-repo ../commerce-canon --info-tech-repo ../info-tech-canon
|
||||||
|
make -C ../info-tech-canon check
|
||||||
|
```
|
||||||
|
|
||||||
|
- Three schema-valid cards; six reciprocal peer links; 59 ledger concept/seed
|
||||||
|
assignments covered; 25 imports from four models; zero source drift.
|
||||||
|
- Six G7 rejection tests check missing reciprocity, duplicate Evidence ownership,
|
||||||
|
Family model promotion, Custodian domain claims, invalid schema shape and
|
||||||
|
undeclared imports. Seven existing ownership tests also pass (13 total).
|
||||||
|
- InfoTechCanon: 46 tests pass, generated discovery surfaces current, canon
|
||||||
|
validation and small-saas proof pass. 81 artifacts, 14 models and one Family
|
||||||
|
seed; the interface adds one discoverable artifact and no model. Existing
|
||||||
|
exact reciprocal model-import cycle review remains in force.
|
||||||
|
- Counterparty: 18 owned concepts, 25 imports and 53 protected files unchanged.
|
||||||
|
- Corpus: 45 unchanged originals, 69 snapshots, 153 exact fragments and 479 links
|
||||||
|
still verify. Ownership ledger has zero unowned or multiply owned targets.
|
||||||
|
|
||||||
|
G7 is complete after publishing these revisions. CFED-WP-0001-T09 retains the
|
||||||
|
fleet reference sweep and REUSE-WP-0021 dependency; T10 retains residual review.
|
||||||
|
|
||||||
|
## State Hub synchronization limitation and live handoff
|
||||||
|
|
||||||
|
InfoTech and Commerce native records synchronized successfully. Custodian also
|
||||||
|
created THE-WP-0001 and its two completed tasks, but its repository-wide checker
|
||||||
|
reported 13 historical assessment failures: ten missing archived CUST-WP-0054
|
||||||
|
task bindings, missing archived CUST-WP-0057/0058 workplan bindings, and one
|
||||||
|
active retired ad-hoc orphan. Prefix warnings expose the explicit AGENTS file
|
||||||
|
convention disagreeing with header/database prefixes (THE/CUST and INFO/ITC).
|
||||||
|
|
||||||
|
Live [CUST-IN-0017](../../../the-custodian/intakes.md), origin residual from
|
||||||
|
THE-WP-0001, owns triage and evidence-backed disposition. Archived records and
|
||||||
|
accepted ADR were preserved. G7 passes; a clean whole-Custodian State Hub
|
||||||
|
assessment is not claimed. Decision: `689eeb84-8b46-4dae-be5d-baa8e654f6ee`.
|
||||||
|
|
||||||
|
## Publication
|
||||||
|
|
||||||
|
- InfoTechCanon implementation `28c624b`, synchronized index `9e89a19`.
|
||||||
|
- CommerceCanon implementation `482fc1d`, repository-manager verified publication
|
||||||
|
and primary projection `1ac87592904be384dd1230e9b4ad5c9c10cc5da3`.
|
||||||
|
- Custodian interface and live residual `1df777b`.
|
||||||
|
- CUST-IN-0017 indexed as `01a073cf-51ca-7fa7-a432-658ba3718382`.
|
||||||
|
|
||||||
|
All native interface workplans are finished and their tasks are done. Project
|
||||||
|
T08 is done; T09 is ready to execute, with T10 still waiting on final residual
|
||||||
|
review. Overall foundation progress is 11/13 tasks.
|
||||||
|
|
@ -71,3 +71,6 @@ The [corpus distribution ledger](corpus-distribution.json) records T07's frozen
|
||||||
research destinations and exact shared fragments. Reproduce G6 with
|
research destinations and exact shared fragments. Reproduce G6 with
|
||||||
`python3 tools/validate_corpus.py --commerce-repo ../commerce-canon --info-tech-repo ../info-tech-canon`
|
`python3 tools/validate_corpus.py --commerce-repo ../commerce-canon --info-tech-repo ../info-tech-canon`
|
||||||
from the project root. Historical source assertions are not current definitions.
|
from the project root. Historical source assertions are not current definitions.
|
||||||
|
|
||||||
|
[Reciprocal interface evidence](../docs/evidence/2026-09-06-interface-cards.md)
|
||||||
|
records the three published canon cards and explicit upstream import review (G7).
|
||||||
|
|
|
||||||
60
tools/test_interfaces.py
Normal file
60
tools/test_interfaces.py
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
"""Regression checks for G7 rejection paths; run beside the three canon checkouts."""
|
||||||
|
from pathlib import Path
|
||||||
|
import unittest
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
import jsonschema
|
||||||
|
|
||||||
|
from validate_interfaces import validate
|
||||||
|
|
||||||
|
WORKSPACE = Path(__file__).resolve().parents[2]
|
||||||
|
READ_TEXT = Path.read_text
|
||||||
|
|
||||||
|
|
||||||
|
class InterfaceGateTests(unittest.TestCase):
|
||||||
|
def reject_card(self, repo, mutate, message, error=ValueError):
|
||||||
|
suffix = 'canon/interfaces/federation.yaml' if repo == 'the-custodian' else 'infospace/interfaces/federation.yaml'
|
||||||
|
target = WORKSPACE / repo / suffix
|
||||||
|
|
||||||
|
def read(path, *args, **kwargs):
|
||||||
|
content = READ_TEXT(path, *args, **kwargs)
|
||||||
|
if path == target:
|
||||||
|
card = yaml.safe_load(content)
|
||||||
|
mutate(card)
|
||||||
|
return yaml.safe_dump(card)
|
||||||
|
return content
|
||||||
|
|
||||||
|
with patch.object(Path, 'read_text', read):
|
||||||
|
with self.assertRaisesRegex(error, message):
|
||||||
|
validate(WORKSPACE)
|
||||||
|
|
||||||
|
def test_missing_reciprocal_peer_is_rejected(self):
|
||||||
|
self.reject_card('info-tech-canon', lambda c: c['peers'].pop(), 'peer coverage')
|
||||||
|
|
||||||
|
def test_duplicate_evidence_owner_is_rejected(self):
|
||||||
|
self.reject_card('commerce-canon', lambda c: c['exports'][0]['concepts'].append('Evidence'),
|
||||||
|
'Duplicate domain owner: Evidence')
|
||||||
|
|
||||||
|
def test_family_model_promotion_is_rejected(self):
|
||||||
|
def promote(card):
|
||||||
|
entry = next(e for e in card['exports'] if e['artifact'] == 'family-area')
|
||||||
|
entry['kind'] = 'domain-model'
|
||||||
|
self.reject_card('info-tech-canon', promote, 'Family promoted')
|
||||||
|
|
||||||
|
def test_custodian_domain_claim_is_rejected(self):
|
||||||
|
self.reject_card('the-custodian', lambda c: c['exports'][0]['concepts'].append('Evidence'),
|
||||||
|
'Governance claims domain semantics')
|
||||||
|
|
||||||
|
def test_invalid_schema_shape_is_rejected(self):
|
||||||
|
self.reject_card('info-tech-canon', lambda c: c.update(consumer={'repo': 'info-tech-canon'}),
|
||||||
|
"is not of type 'string'", jsonschema.ValidationError)
|
||||||
|
|
||||||
|
def test_import_exceeding_export_is_rejected(self):
|
||||||
|
def extend(card):
|
||||||
|
card['imports'][1]['concepts'].append('Undeclared concept')
|
||||||
|
self.reject_card('commerce-canon', extend, 'Import exceeds export')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
176
tools/validate_interfaces.py
Normal file
176
tools/validate_interfaces.py
Normal file
|
|
@ -0,0 +1,176 @@
|
||||||
|
"""Check G7 federation cards, reciprocal contracts, ownership and review provenance.
|
||||||
|
|
||||||
|
Run from a project checkout beside the three canons. Requires PyYAML/jsonschema.
|
||||||
|
Repository-qualified card paths resolve below --workspace, never below the card.
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
import jsonschema
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
CARD_PATHS = {
|
||||||
|
'info-tech-canon': 'infospace/interfaces/federation.yaml',
|
||||||
|
'commerce-canon': 'infospace/interfaces/federation.yaml',
|
||||||
|
'the-custodian': 'canon/interfaces/federation.yaml',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def require(condition, message):
|
||||||
|
if not condition:
|
||||||
|
raise ValueError(message)
|
||||||
|
|
||||||
|
|
||||||
|
def sha(data):
|
||||||
|
return hashlib.sha256(data).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def git_blob(repo, commit, path):
|
||||||
|
require(bool(re.fullmatch(r'[0-9a-f]{40}', commit)), 'Source must use a full Git commit')
|
||||||
|
return subprocess.check_output(['git', 'show', f'{commit}:{path}'], cwd=repo)
|
||||||
|
|
||||||
|
|
||||||
|
def declared_concepts(text):
|
||||||
|
"""Support complete metadata and older explicit prose definitions.
|
||||||
|
|
||||||
|
A section heading alone cannot establish ownership: transferred concepts
|
||||||
|
deliberately keep their old anchors as imports.
|
||||||
|
"""
|
||||||
|
fm = yaml.safe_load(text.split('---', 2)[1]) if text.startswith('---\n') else {}
|
||||||
|
return set(fm.get('owned_concepts', [])) | set(
|
||||||
|
re.findall(r'^(?:An? )?\*\*(.+?)\*\* is\b', text, re.M)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def validate(workspace):
|
||||||
|
project = Path(__file__).resolve().parents[1]
|
||||||
|
schema_path = 'infospace/schemas/interface-card.schema.yaml'
|
||||||
|
schema = yaml.safe_load((workspace / 'info-tech-canon' / schema_path).read_text())
|
||||||
|
jsonschema.Draft202012Validator.check_schema(schema)
|
||||||
|
cards = {repo: yaml.safe_load((workspace / repo / path).read_text())
|
||||||
|
for repo, path in CARD_PATHS.items()}
|
||||||
|
ledger = json.loads((project / 'ledger/concept-ownership.json').read_text())
|
||||||
|
targets = [t for e in ledger['entries'] for t in e['targets'] if t['kind'] in {'concept', 'seed'}]
|
||||||
|
targets += ledger['additional_required_concepts']
|
||||||
|
exports = {}
|
||||||
|
ownership = {}
|
||||||
|
import_edges = 0
|
||||||
|
peer_links = 0
|
||||||
|
for repo, card in cards.items():
|
||||||
|
jsonschema.validate(card, schema)
|
||||||
|
require(card['consumer'] == repo, f'{repo}: wrong consumer')
|
||||||
|
require(card['status'] == 'published', f'{repo}: unpublished')
|
||||||
|
require(card['schema_source'] == {'repository': 'info-tech-canon', 'path': schema_path}, 'Schema drift')
|
||||||
|
peers = card['peers']
|
||||||
|
require(len(peers) == 2 and {p['repository'] for p in peers} == set(cards) - {repo}, f'{repo}: peer coverage')
|
||||||
|
for peer in peers:
|
||||||
|
other = peer['repository']
|
||||||
|
require(peer['card'] == CARD_PATHS[other], f'{repo}: bad peer card path')
|
||||||
|
require(any(p['repository'] == repo and p['card'] == CARD_PATHS[repo]
|
||||||
|
for p in cards[other]['peers']), f'{repo}: nonreciprocal peer')
|
||||||
|
peer_links += 1
|
||||||
|
require(card['canon_surfaces'] == [e['artifact'] for e in card['exports']], 'Export index drift')
|
||||||
|
for entry in card['exports']:
|
||||||
|
key = (repo, entry['artifact'])
|
||||||
|
require(key not in exports, f'Duplicate export {key}')
|
||||||
|
exports[key] = entry
|
||||||
|
require((workspace / repo / entry['path']).is_file(), f'Missing export {key}')
|
||||||
|
if entry['kind'] == 'ecosystem-governance':
|
||||||
|
require(repo == 'the-custodian' and entry['concepts'] == [], 'Governance claims domain semantics')
|
||||||
|
require(set(entry['governs']) == set(cards) - {repo}, 'Governance coverage')
|
||||||
|
else:
|
||||||
|
registry = yaml.safe_load((workspace / repo / 'canon.yaml').read_text())
|
||||||
|
matches = [m for m in registry['models'] + registry.get('concept_areas', []) if m['id'] == entry['artifact']]
|
||||||
|
require(len(matches) == 1, f'Unregistered export {key}')
|
||||||
|
for field in ['status', 'path']:
|
||||||
|
require(entry[field] == matches[0][field], f'{key}: registry {field} drift')
|
||||||
|
if entry['artifact'] == 'family-area':
|
||||||
|
require(entry['kind'] == 'concept-area-seed' and entry['availability'] == 'seeded-not-authored', 'Family promoted')
|
||||||
|
for concept in entry['concepts']:
|
||||||
|
require(concept not in ownership, f'Duplicate domain owner: {concept}')
|
||||||
|
ownership[concept] = (repo, entry['ledger_model'])
|
||||||
|
authority = card['authority']
|
||||||
|
require(authority == cards['the-custodian']['authority'], 'Authority mismatch')
|
||||||
|
require(authority['repository'] == 'the-custodian' and authority['artifact'] == 'CUST-ADR-006'
|
||||||
|
and authority['revision'] == 'accepted-1', 'Unreviewed authority')
|
||||||
|
adr = git_blob(workspace / 'the-custodian', authority['source_commit'], authority['path'])
|
||||||
|
require(sha(adr) == authority['sha256'], 'Pinned ADR hash mismatch')
|
||||||
|
require(adr == (workspace / 'the-custodian' / authority['path']).read_bytes(), 'ADR changed since review')
|
||||||
|
for target in targets:
|
||||||
|
require(ownership.get(target['concept']) == (target['owner']['canon'], target['owner']['model']),
|
||||||
|
f"Ledger disagreement: {target['concept']}")
|
||||||
|
for repo, card in cards.items():
|
||||||
|
seen = set()
|
||||||
|
for entry in card['imports']:
|
||||||
|
key = (entry['repository'], entry['artifact'])
|
||||||
|
require(key not in seen, f'{repo}: duplicate import')
|
||||||
|
seen.add(key)
|
||||||
|
require(key in exports and entry['repository'] != repo, f'{repo}: missing upstream export {key}')
|
||||||
|
require(entry['kind'] == exports[key]['kind'], 'Import kind mismatch')
|
||||||
|
require(set(entry['concepts']) <= set(exports[key]['concepts']), 'Import exceeds export')
|
||||||
|
require(not any(ownership[c][0] == repo for c in entry['concepts']), 'Import redefined locally')
|
||||||
|
import_edges += 1
|
||||||
|
require(cards['the-custodian']['imports'] == [], 'Custodian domain dependency introduced')
|
||||||
|
require(len(cards['info-tech-canon']['imports']) == 1, 'Unreviewed reverse domain import')
|
||||||
|
require(len(cards['the-custodian']['exports']) == 1, 'Custodian federation scope drift')
|
||||||
|
commerce = workspace / 'commerce-canon'
|
||||||
|
model_dir = commerce / 'infospace/models/counterparty'
|
||||||
|
manifest_path = model_dir / 'imports.json'
|
||||||
|
current = json.loads(manifest_path.read_text())
|
||||||
|
review = current['review']
|
||||||
|
require((model_dir / review['record']).is_file(), 'Missing import review')
|
||||||
|
previous_bytes = (model_dir / review['previous_manifest']).read_bytes()
|
||||||
|
require(sha(previous_bytes) == review['previous_manifest_sha256'], 'Historical manifest changed')
|
||||||
|
previous = json.loads(previous_bytes)
|
||||||
|
require(previous['source_commit'] == '361c944325934ccdb190470baf6f55440b6b486e', 'Original review pin changed')
|
||||||
|
require(review['concept_changes'] == [], 'Unexpected concept adoption')
|
||||||
|
require([(r['model'], r['concepts']) for r in previous['imports']] ==
|
||||||
|
[(r['model'], r['concepts']) for r in current['imports']], 'Unreviewed import change')
|
||||||
|
checked_blobs = 0
|
||||||
|
drift = []
|
||||||
|
for manifest in [previous, current]:
|
||||||
|
require(manifest['source_repository'] == 'info-tech-canon', 'Wrong import source')
|
||||||
|
for entry in manifest['imports']:
|
||||||
|
blob = git_blob(workspace / 'info-tech-canon', manifest['source_commit'], entry['path'])
|
||||||
|
require(sha(blob) == entry['sha256'], f"Pinned import hash mismatch: {entry['model']}")
|
||||||
|
require(set(entry['concepts']) <= declared_concepts(blob.decode()), f"Import not owned: {entry['model']}")
|
||||||
|
checked_blobs += 1
|
||||||
|
if manifest is current and blob != (workspace / 'info-tech-canon' / entry['path']).read_bytes():
|
||||||
|
drift.append(entry['path'])
|
||||||
|
domain_imports = [e for e in cards['commerce-canon']['imports'] if e['kind'] == 'domain-model']
|
||||||
|
require(len(domain_imports) == len(current['imports']) == 4, 'Import model coverage')
|
||||||
|
for row in current['imports']:
|
||||||
|
exported = exports[('info-tech-canon', row['model'])]
|
||||||
|
require(exported['path'] == row['path'], 'Import/export source mismatch')
|
||||||
|
matches = [e for e in domain_imports if e['artifact'] == row['model']]
|
||||||
|
require(len(matches) == 1 and matches[0]['concepts'] == row['concepts'], 'Card/manifest mismatch')
|
||||||
|
require(commerce / matches[0]['manifest'] == manifest_path, 'Wrong manifest pointer')
|
||||||
|
links = 0
|
||||||
|
for repo, path in CARD_PATHS.items():
|
||||||
|
root = workspace / repo
|
||||||
|
for document in [root / 'README.md', root / Path(path).parent / 'README.md']:
|
||||||
|
for link in re.findall(r'\]\(([^)]+)\)', document.read_text()):
|
||||||
|
if '://' in link or link.startswith('#'):
|
||||||
|
continue
|
||||||
|
require((document.parent / link.split('#')[0]).exists(), f'Broken link: {document}: {link}')
|
||||||
|
links += 1
|
||||||
|
return {'gate': 'G7', 'result': 'pass', 'cards': len(cards), 'reciprocal_peer_links': peer_links,
|
||||||
|
'import_edges': import_edges, 'ledger_concepts_and_seed_covered': len(targets),
|
||||||
|
'imported_concepts': sum(len(e['concepts']) for e in domain_imports),
|
||||||
|
'historical_and_current_import_blobs_checked': checked_blobs,
|
||||||
|
'source_commit': current['source_commit'], 'upstream_changes_since_review': drift,
|
||||||
|
'navigation_links_checked': links, 'custodian_domain_concepts': 0,
|
||||||
|
'family': 'seeded-not-authored'}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
|
parser.add_argument('--workspace', type=Path, default=Path(__file__).resolve().parents[2])
|
||||||
|
args = parser.parse_args()
|
||||||
|
print(json.dumps(validate(args.workspace.resolve()), indent=2))
|
||||||
|
|
@ -299,7 +299,7 @@ does not promote historical assertions. G6 passes; T08 is now todo.
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: CFED-WP-0001-T08
|
id: CFED-WP-0001-T08
|
||||||
status: todo
|
status: done
|
||||||
priority: medium
|
priority: medium
|
||||||
state_hub_task_id: "e0558c32-415f-5563-bca2-438b35fa6b53"
|
state_hub_task_id: "e0558c32-415f-5563-bca2-438b35fa6b53"
|
||||||
```
|
```
|
||||||
|
|
@ -317,11 +317,22 @@ kernel references that still mark upstream extensions pending. Keep historical
|
||||||
import revisions verifiable; do not silently adopt new upstream definitions.
|
import revisions verifiable; do not silently adopt new upstream definitions.
|
||||||
|
|
||||||
|
|
||||||
|
**Result (2026-09-06):** Native INFO-WP-0025, COMMERCE-WP-0004 and THE-WP-0001
|
||||||
|
publish reciprocal interface cards in all three canons. [G7 evidence](../docs/evidence/2026-09-06-interface-cards.md)
|
||||||
|
verifies three schema-valid cards, six reciprocal links, all ledger concept/seed
|
||||||
|
assignments and 25 unchanged imports. Commerce advances its reviewed upstream
|
||||||
|
pin with the previous manifest preserved; kernel references acknowledge T12/T13.
|
||||||
|
InfoTechCanon checks pass (46 tests); project rejection/ownership tests pass (13).
|
||||||
|
Custodian's historical projection failures and conflicting generated prefix
|
||||||
|
instructions have live residual [CUST-IN-0017](../../the-custodian/intakes.md).
|
||||||
|
G7 passes; T09 is now todo. Whole-fleet consistency is not claimed by this gate.
|
||||||
|
|
||||||
|
|
||||||
## Sweep fleet references
|
## Sweep fleet references
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: CFED-WP-0001-T09
|
id: CFED-WP-0001-T09
|
||||||
status: wait
|
status: todo
|
||||||
priority: medium
|
priority: medium
|
||||||
state_hub_task_id: "42ebf476-6a45-5e23-b507-eb90bc4f5c07"
|
state_hub_task_id: "42ebf476-6a45-5e23-b507-eb90bc4f5c07"
|
||||||
```
|
```
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue