Skip to content
Merged
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
249 changes: 249 additions & 0 deletions tests/test_evidence_profile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
"""Behavior of tools/evidence_profile.py (standard library only; the live graph is read, never written)."""
import contextlib
import hashlib
import importlib.util
import io
import json
import pathlib
import subprocess
import sys
import tempfile
import unittest

ROOT = pathlib.Path(__file__).resolve().parent.parent
GRAPH = ROOT / 'frontiers' / 'downstream_gate_20260925' / 'GRAPH.json'
SPEC = importlib.util.spec_from_file_location('evidence_profile', ROOT / 'tools' / 'evidence_profile.py')
ep = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(ep)
GATE = ep.load_gate()


def node(classification, **fields):
return dict(classification=classification, controlling=False, **fields)


def synthetic():
return {
'schema_version': 1,
'object': 'SYNTHETIC',
'nodes': {
'math.top': node('OPEN_ACTIVE'),
'math.mid': node('PROVED_REVIEWED', author_provider='OpenAI',
review_basis=[{'provider': 'xAI'}, {'provider': 'Anthropic/Claude'}]),
'math.leaf': node('AUTHOR_SIDE_CANDIDATE', author_provider='Anthropic',
review_provider='Anthropic Claude session'),
'math.shared': node('PROVED_REVIEWED', author_provider='OpenAI', review_providers=['nonauthor']),
'math.boundary': node('REFUTED'),
},
'edges': [
{'from': 'math.top', 'to': 'math.mid', 'required': True, 'relation': 'uses'},
{'from': 'math.top', 'to': 'math.shared', 'required': True, 'relation': 'uses'},
{'from': 'math.top', 'to': 'math.boundary', 'required': False, 'relation': 'boundary_only'},
{'from': 'math.mid', 'to': 'math.leaf', 'required': True, 'relation': 'imports'},
{'from': 'math.mid', 'to': 'math.shared', 'required': True, 'relation': 'imports'},
],
}


def run(argv):
out = io.StringIO()
with contextlib.redirect_stdout(out):
code = ep.main(argv)
return code, out.getvalue()


class SyntheticGraph(unittest.TestCase):
def setUp(self):
self.graph = synthetic()
GATE.validate_graph_fail_closed(self.graph)

def test_unsatisfied_required_is_transitive_and_ignores_context_edges(self):
p = ep.profile(GATE, self.graph, 'math.top')
self.assertEqual(p['unsatisfied_required'],
[{'node': 'math.leaf', 'classification': 'AUTHOR_SIDE_CANDIDATE'}])
self.assertEqual(ep.profile(GATE, self.graph, 'math.shared')['unsatisfied_required'], [])

def test_provider_distinct_reads_only_recorded_families(self):
self.assertEqual(ep.provider_distinct(self.graph['nodes']['math.mid']), 'yes')
self.assertEqual(ep.provider_distinct(self.graph['nodes']['math.leaf']), 'no')
self.assertEqual(ep.provider_distinct(self.graph['nodes']['math.shared']), 'not recorded')
self.assertEqual(ep.provider_distinct(self.graph['nodes']['math.top']), 'not recorded')
self.assertIsNone(ep.family('OpenAI reviewed by xAI'))
self.assertEqual(ep.family('xAI/Grok via Cursor'), 'xAI')

def test_unresolved_reviewer_never_yields_no(self):
# 6018400003 item 1: an unresolved or ambiguous reviewer must not be dropped before deciding 'no'.
for reviewers in (['OpenAI', 'unattributed'], ['OpenAI', 'OpenAI / xAI'], ['OpenAI', 'nonauthor']):
with self.subTest(reviewers=reviewers):
self.assertEqual(ep.provider_distinct(node('PROVED_REVIEWED', author_provider='OpenAI',
review_providers=reviewers)), 'not recorded')
self.assertEqual(ep.provider_distinct(node('PROVED_REVIEWED', author_provider='OpenAI',
review_providers=['unattributed', 'xAI'])), 'yes')
self.assertEqual(ep.provider_distinct(node('PROVED_REVIEWED', author_provider='OpenAI',
review_providers=['OpenAI / GPT-6', 'Codex'])), 'no')
self.assertEqual(ep.provider_distinct(node('PROVED_REVIEWED', author_provider='OpenAI',
review_providers=[])), 'not recorded')
# EP381-UNKNOWN-01 (6018473703): the same rule across fields, singular review_provider plus review_basis.
self.assertEqual(ep.provider_distinct(node('PROVED_REVIEWED', author_provider='OpenAI', review_provider='OpenAI',
review_basis=[{'provider': 'unidentified'}])), 'not recorded')
self.assertEqual(ep.provider_distinct(node('PROVED_REVIEWED', author_provider='OpenAI', review_provider='OpenAI',
review_basis=[{'provider': 'xAI'}])), 'yes')
self.assertEqual(ep.provider_distinct(node('PROVED_REVIEWED', author_provider='OpenAI',
review_providers=['OpenAI or xAI'])), 'not recorded')

def test_negated_or_undisclosed_provider_is_unresolved(self):
# EP381-02 (6018548621): non-identities must not be read as a provider.
for text in ('not OpenAI; provider not disclosed', 'no Anthropic involvement', 'other than xAI',
'unidentified', 'provider not disclosed'):
with self.subTest(text=text):
self.assertIsNone(ep.family(text))
self.assertEqual(ep.provider_distinct(node('PROVED_REVIEWED', author_provider='Anthropic',
review_providers=['not OpenAI; provider not disclosed'])),
'not recorded')
self.assertEqual(ep.provider_distinct(node('PROVED_REVIEWED', author_provider='OpenAI',
review_providers=['claudette'])), 'not recorded')
p = ep.profile(GATE, {'schema_version': 1, 'nodes': {'math.x': node(
'PROVED_REVIEWED', author_provider='OpenAI', review_providers=['OpenAI', 'not disclosed'])},
'edges': []}, 'math.x')
self.assertEqual(p['provider_distinct'], 'not recorded')
self.assertEqual(p['unresolved_reviewer_providers'], ['not disclosed'])

def test_default_selection_covers_context_only_cycles(self):
# 6018548621 nonblocking: a component without an edge-free root is still listed.
graph = synthetic()
graph['nodes']['math.a'] = node('OPEN_ACTIVE')
graph['nodes']['math.b'] = node('PROVED_REVIEWED')
graph['edges'] += [{'from': 'math.a', 'to': 'math.b', 'required': False, 'relation': 'context'},
{'from': 'math.b', 'to': 'math.a', 'required': False, 'relation': 'context'}]
GATE.validate_graph_fail_closed(graph)
self.assertEqual(ep.roots(graph), ['math.top', 'math.a'])

def test_positive_identity_grammar(self):
# EP381-02 residual (6018757501): only the documented positive form names a family.
for text, expected in (('OpenAI / GPT-6 Astra Pro', 'OpenAI'), ('Grok 4.7', 'xAI'),
('xAI/Grok via Cursor (D1-A-E, section 9 v1.1, partial slices)', 'xAI'),
('Claude Code session', 'Anthropic'), ('Google DeepMind Gemini', 'Google')):
with self.subTest(text=text):
self.assertEqual(ep.family(text), expected)
for text in ('possibly OpenAI', 'OpenAI or unspecified', 'review requested from OpenAI',
'OpenAI reviewed by xAI', 'OpenAI (a) (b)', 'OpenAI, probably', 'Claude/Grok'):
with self.subTest(text=text):
self.assertIsNone(ep.family(text))

def test_family_matches_whole_tokens_only(self):
# 6018400003 item 2: substring hits such as 'notopenai' or 'claudette' name no family.
for text in ('notopenai', 'claudette', 'xairline', 'grokking-free', 'googleplex', ''):
with self.subTest(text=text):
self.assertIsNone(ep.family(text))
for text, expected in (('OpenAI / GPT-6 Astra Pro', 'OpenAI'), ('Anthropic/Claude (A1-A7)', 'Anthropic'),
('Claude Code session', 'Anthropic'), ('ChatGPT', 'OpenAI'), ('Gemini', 'Google')):
with self.subTest(text=text):
self.assertEqual(ep.family(text), expected)

def test_tree_marks_context_edges_and_expands_shared_nodes_once(self):
lines = ep.tree_lines(GATE, self.graph, 'math.top')
text = '\n'.join(lines)
self.assertIn('context (boundary_only) math.boundary REFUTED', text)
self.assertEqual(sum('math.shared' in line for line in lines[1:-1]), 2)
self.assertEqual(sum('(expanded above)' in line for line in lines), 1)
self.assertEqual(lines[-1], 'Unsatisfied required dependencies (1): math.leaf (AUTHOR_SIDE_CANDIDATE)')

def test_roots_are_math_nodes_without_incoming_edges(self):
self.assertEqual(ep.roots(self.graph), ['math.top'])

def test_cli_on_file_json_and_text(self):
with tempfile.TemporaryDirectory() as tmp:
path = pathlib.Path(tmp) / 'graph.json'
path.write_text(json.dumps(self.graph))
code, text = run(['--graph', str(path)])
self.assertEqual(code, 0)
self.assertTrue(text.startswith('math.top OPEN_ACTIVE'))
self.assertIn('no status authority; scientific effect NONE', text)
code, text = run(['--graph', str(path), '--node', 'math.mid', '--json'])
data = json.loads(text)
self.assertEqual([p['node'] for p in data['profiles']], ['math.mid'])
self.assertIs(data['status_authority'], False)
self.assertIs(data['lemma_closed'], False)
self.assertEqual(data['scientific_effect'], 'NONE')
self.assertIn('blind_reconstruction', data['axes_outside_graph'])

def test_invalid_graphs_and_unknown_nodes_are_rejected(self):
with tempfile.TemporaryDirectory() as tmp:
path = pathlib.Path(tmp) / 'graph.json'
bad = synthetic()
bad['edges'].append({'from': 'math.leaf', 'to': 'math.top', 'required': True, 'relation': 'cycle'})
path.write_text(json.dumps(bad))
with self.assertRaisesRegex(ValueError, 'required dependency cycle'):
run(['--graph', str(path)])
bad = synthetic()
bad['nodes']['math.top']['classification'] = 'CLOSED'
path.write_text(json.dumps(bad))
with self.assertRaisesRegex(ValueError, 'unknown node classification'):
run(['--graph', str(path)])
path.write_text(json.dumps(synthetic()))
with self.assertRaisesRegex(KeyError, 'unknown node'):
run(['--graph', str(path), '--node', 'math.absent'])


class ProviderAttributionCLI(unittest.TestCase):
"""EP381-01/EP381-02 (review 5430026100) through the actual command line, in the current Python mode."""

CASES = {
'math.mixed-unknown': ('OpenAI', ['OpenAI', 'not disclosed'], 'not recorded'),
'math.mixed-ambiguous': ('OpenAI', ['OpenAI', 'OpenAI or Anthropic'], 'not recorded'),
'math.distinct-plus-unknown': ('OpenAI', ['not disclosed', 'xAI'], 'yes'),
'math.negated': ('Anthropic', ['not OpenAI; provider not disclosed'], 'not recorded'),
'math.embedded-name': ('OpenAI', ['claudette'], 'not recorded'),
'math.anthropic-claude': ('OpenAI', ['Anthropic/Claude'], 'yes'),
'math.chatgpt-codex': ('OpenAI', ['ChatGPT/Codex'], 'no'),
'math.xai-grok-cursor': ('OpenAI', ['xAI/Grok via Cursor'], 'yes'),
'math.all-same': ('xAI', ['xAI/Grok via Cursor', 'Grok 4.7'], 'no'),
# Delta 6018757501: prose around a provider name is not a positive identity.
'math.possibly': ('Anthropic', ['possibly OpenAI'], 'not recorded'),
'math.or-unspecified': ('Anthropic', ['OpenAI or unspecified'], 'not recorded'),
'math.invitation': ('Anthropic', ['review requested from OpenAI'], 'not recorded'),
'math.astra-control': ('Anthropic', ['OpenAI / GPT-6 Astra Pro'], 'yes'),
}

def test_cli_json_reports_conservative_provider_attribution(self):
graph = {'schema_version': 1, 'object': 'SYNTHETIC-CLI', 'edges': [],
'nodes': {nid: node('PROVED_REVIEWED', author_provider=a, review_providers=r)
for nid, (a, r, _) in self.CASES.items()}}
with tempfile.TemporaryDirectory() as tmp:
path = pathlib.Path(tmp) / 'graph.json'
path.write_text(json.dumps(graph))
before = path.read_bytes()
flags = ['-O'] if sys.flags.optimize else []
run = subprocess.run([sys.executable, '-B', *flags, '-S', str(ROOT / 'tools' / 'evidence_profile.py'),
'--graph', str(path), '--json'], capture_output=True, text=True, timeout=60)
self.assertEqual((run.returncode, run.stderr), (0, ''))
self.assertEqual(path.read_bytes(), before)
profiles = {p['node']: p for p in json.loads(run.stdout)['profiles']}
self.assertEqual(set(profiles), set(self.CASES))
for nid, (_, reviewers, expected) in self.CASES.items():
with self.subTest(node=nid):
self.assertEqual(profiles[nid]['provider_distinct'], expected)
self.assertEqual(profiles[nid]['reviewer_providers'], reviewers)
self.assertEqual(profiles['math.mixed-unknown'].get('unresolved_reviewer_providers'), ['not disclosed'])
self.assertEqual(profiles['math.negated'].get('unresolved_reviewer_providers'),
['not OpenAI; provider not disclosed'])


class LiveGraph(unittest.TestCase):
def test_live_graph_renders_without_writing(self):
before = hashlib.sha256(GRAPH.read_bytes()).hexdigest()
code, text = run([])
self.assertEqual(code, 0)
graph = GATE.load_graph(GRAPH)
for root in ep.roots(graph):
self.assertIn('\n' + root + ' ' if not text.startswith(root) else root, text)
code, text = run(['--json'])
data = json.loads(text)
self.assertEqual(len(data['profiles']), len(ep.roots(graph)))
for p in data['profiles']:
self.assertEqual(p['classification'], graph['nodes'][p['node']]['classification'])
self.assertEqual(hashlib.sha256(GRAPH.read_bytes()).hexdigest(), before)


if __name__ == '__main__':
unittest.main()
Loading
Loading