#!/usr/bin/env python3 """Filter a verified preview and prepare pinned consumer events; no inference.""" import argparse from datetime import datetime, timezone import hashlib import json import math from pathlib import Path import re from reference_preview import ROOT, build, git_blob, release, require from classification_coverage import section_values, RESPONSIBILITIES HOST = 'https://forgejo.coulomb.social/coulomb/frontend-patterns' SHA = re.compile(r'[0-9a-f]{40}') DIGEST = re.compile(r'[0-9a-f]{64}') IDENTITY = re.compile(r'[A-Za-z0-9][A-Za-z0-9:_.-]{0,159}') def published(root=ROOT, version=None): base, pin, manifest = release(root, version) generated = build(root, version) for name, content in generated.items(): require((root / base / name).read_text() == content, 'Published export changed: ' + name) return json.loads(generated['index.json']), pin, manifest def locator(path, revision): return {'path': path, 'revision': revision, 'url': f'{HOST}/src/commit/{revision}/{path}'} def lookup(index, pin, manifest, candidates=(), forces=(), responsibilities=(), root=ROOT): known = {c['id'] for c in index['candidates']} vocab = git_blob(root, manifest['corpus_revision'], 'canon/vocabulary.yaml').decode() require(set(candidates) <= known, 'Unknown candidate in selected release') require(set(forces) <= set(section_values(vocab, 'forces')), 'Unknown force') require(set(responsibilities) <= set(RESPONSIBILITIES), 'Unknown responsibility') matches = [] if candidates or forces or responsibilities: for candidate in index['candidates']: classification = candidate['classification'] if candidates and candidate['id'] not in candidates: continue if not set(forces) <= set(classification['forces']['improves']): continue if not set(responsibilities) <= set(classification['responsibilities']): continue record = dict(candidate) record['contract'] = locator(candidate['path'], index['corpus_revision']) record['evidence'] = [dict(e, locator=locator(e['ref'], pin['packaging_revision'])) for e in candidate['evidence']] matches.append(record) ids = {c['id'] for c in matches} return { 'schema_version': 1, 'status': 'needs-context' if not (candidates or forces or responsibilities) else ('matches' if matches else 'no-match'), 'reference': {'version': index['version'], 'packaging_revision': pin['packaging_revision'], 'manifest_sha256': pin['manifest_sha256'], 'corpus_revision': index['corpus_revision']}, 'filters': {'candidates': list(candidates), 'improving_forces': list(forces), 'responsibilities': list(responsibilities)}, 'candidates': matches, 'relations': [e for e in index['relations'] if e['source'] in ids or e['target'] in ids], 'entrypoints': {k: locator(v, pin['packaging_revision']) for k, v in index['entrypoints'].items()}, 'limits': ['Metadata filtering is not applicability, ranking or compatible-configuration proof.', 'Read full pinned contracts, force costs, alternatives and gaps before selecting.', 'Relations are conditional proposals; no inverse, transitive or automatic selection.', 'No match means no record satisfies these filters, not that no architecture exists.', 'This preview contains hypotheses; independent usefulness remains unverified.'], } def text_ok(value, limit=1000): return isinstance(value, str) and 0 < len(value.strip()) <= limit def receipt(source, index, pin, now=None): require(isinstance(source, dict), 'Decision input must be an object') fields = {'use_id', 'event_id', 'recorded_at', 'kind', 'consumer', 'context', 'decision', 'outcome'} require(fields <= source.keys() <= fields | {'previous_event_sha256'}, 'Decision input fields mismatch') event = json.loads(json.dumps(source)) event.update(schema_version=1, reference={ 'version': index['version'], 'packaging_revision': pin['packaging_revision'], 'manifest_sha256': pin['manifest_sha256']}) for key in ('use_id', 'event_id'): require(isinstance(event[key], str) and IDENTITY.fullmatch(event[key]), 'Invalid event identity') require(event['kind'] in {'real', 'synthetic'}, 'Explicit real/synthetic kind required') previous = event.setdefault('previous_event_sha256', None) require(previous is None or isinstance(previous, str) and DIGEST.fullmatch(previous), 'Invalid predecessor digest') require(isinstance(event['recorded_at'], str), 'Timestamp required') stamp = datetime.fromisoformat(event['recorded_at'].replace('Z', '+00:00')) require(stamp.tzinfo is not None and stamp <= (now or datetime.now(timezone.utc)), 'Invalid/future timestamp') consumer = event['consumer'] require(isinstance(consumer, dict) and set(consumer) == {'repo', 'revision', 'task_ref', 'producer', 'run_ref'}, 'Consumer fields mismatch') require(isinstance(consumer['repo'], str) and re.fullmatch(r'[a-z0-9][a-z0-9-]{0,79}', consumer['repo']), 'Invalid consumer repo') require(isinstance(consumer['revision'], str) and SHA.fullmatch(consumer['revision']), 'Full consumer revision required') require(all(text_ok(consumer[k]) for k in ('task_ref', 'producer', 'run_ref')), 'Missing consumer provenance') context = event['context'] require(isinstance(context, dict) and set(context) == {'problem', 'constraints', 'considered', 'selected'}, 'Context fields mismatch') require(text_ok(context['problem']), 'Problem required') require(isinstance(context['constraints'], list) and all(text_ok(x, 500) for x in context['constraints']), 'Invalid constraints') known = {c['id'] for c in index['candidates']} for key in ('considered', 'selected'): values = context[key] require(isinstance(values, list) and all(isinstance(v, str) for v in values), 'Invalid candidate list') require(len(values) == len(set(values)) and set(values) <= known, 'Unknown/duplicate candidate in release') require(set(context['selected']) <= set(context['considered']), 'Unconsidered selection') decision = event['decision'] require(isinstance(decision, dict) and set(decision) == {'action', 'reason', 'artifact_ref'}, 'Decision fields mismatch') require(decision['action'] in {'applied', 'adapted', 'rejected', 'no-match'}, 'Invalid decision action') require(bool(context['selected']) == (decision['action'] in {'applied', 'adapted'}), 'Action/selection mismatch') require(text_ok(decision['reason']), 'Decision reason required') require(decision['artifact_ref'] is None or text_ok(decision['artifact_ref']), 'Invalid artifact reference') outcome = event['outcome'] defaults = {'value': 'unknown', 'basis': 'consumer-report', 'stage': 'decision', 'observation': None, 'evidence_refs': [], 'next_observation': None, 'measured_decision_minutes': None, 'measured_rework_minutes': None, 'comparison_ref': None} require(isinstance(outcome, dict) and 'expectation' in outcome and set(outcome) <= set(defaults) | {'expectation'}, 'Outcome fields mismatch') event['outcome'] = outcome = dict(defaults, **outcome) require(text_ok(outcome['expectation']), 'Observable expectation required') require(outcome['value'] in {'helpful', 'harmful', 'mixed', 'no-effect', 'unknown'}, 'Invalid outcome') require(outcome['basis'] in {'consumer-report', 'model-assessment', 'observed-result'}, 'Invalid outcome basis') require(outcome['stage'] in {'decision', 'implementation', 'test', 'operation'}, 'Invalid outcome stage') refs = outcome['evidence_refs'] require(isinstance(refs, list) and len(refs) <= 10 and all(text_ok(v) for v in refs), 'Invalid outcome evidence') require(outcome['observation'] is None or text_ok(outcome['observation']), 'Invalid observation') require(outcome['value'] == 'unknown' or refs and text_ok(outcome['observation']), 'Observed outcome needs evidence') for key in ('next_observation', 'comparison_ref'): require(outcome[key] is None or text_ok(outcome[key]), 'Invalid outcome reference') for key in ('measured_decision_minutes', 'measured_rework_minutes'): value = outcome[key] require(value is None or type(value) in (int, float) and math.isfinite(value) and value >= 0, 'Invalid measured effort') return event def write_receipt(event, relative, consumer_root=None): require(isinstance(relative, str) and 0 < len(relative) <= 240 and re.fullmatch(r'[A-Za-z0-9_./-]+', relative) and all(part not in {'', '.', '..'} for part in relative.split('/')), 'Unsafe receipt path') root = (consumer_root or Path.cwd()).resolve() path = root / relative require(path.resolve().is_relative_to(root), 'Receipt escapes consumer root') content = (json.dumps(event, indent=2, allow_nan=False) + '\n').encode() require(len(content) <= 131072, 'Receipt exceeds collector size limit') path.parent.mkdir(parents=True, exist_ok=True) with path.open('xb') as stream: stream.write(content) return {'path': relative, 'sha256': hashlib.sha256(content).hexdigest()} def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--version', help='Published version; defaults to current pointer') commands = parser.add_subparsers(dest='command', required=True) query = commands.add_parser('lookup', help='Intersect force/responsibility filters; candidate IDs form an explicit allowlist') query.add_argument('--candidate', action='append', default=[]) query.add_argument('--force', action='append', default=[]) query.add_argument('--responsibility', action='append', default=[]) prepare = commands.add_parser('receipt', help='Prepare a consumer-authored event with verified release pins') prepare.add_argument('--input', required=True, type=Path, help='Decision/provenance JSON; see feedback/decision-input.example.json') prepare.add_argument('--output', help='New source-relative receipt path under current consumer directory; never overwrite') args = parser.parse_args() try: index, pin, manifest = published(version=args.version) if args.command == 'lookup': result = lookup(index, pin, manifest, args.candidate, args.force, args.responsibility) else: require(args.input.stat().st_size <= 131072, 'Decision input too large') event = receipt(json.loads(args.input.read_text()), index, pin) result = write_receipt(event, args.output) if args.output else event print(json.dumps(result, indent=2, allow_nan=False)) except (ValueError, TypeError, KeyError, OSError) as exc: parser.exit(1, f'Reference consumption failed: {exc}\n') if __name__ == '__main__': main()