diff --git a/examples/traceos-itself/observations/2026-09.jsonl b/examples/traceos-itself/observations/2026-09.jsonl index 3b98bf0..969deb9 100644 --- a/examples/traceos-itself/observations/2026-09.jsonl +++ b/examples/traceos-itself/observations/2026-09.jsonl @@ -323,3 +323,5 @@ {"assertion": "assert.reconcile.unverifiable-is-not-verified", "reference": "traceos/engine.py#Git", "observed_at": "2026-09-11T18:26:51.128266Z", "observed_ref": "03c9e6937f7b43525007da01fe2bb234d8c41712", "observed_blob": "a870a87f68df6f8f3608f43fe3e353e63c56e170", "observed_norm": "8d3e91f52e26d5b2f015b02c910bef33b0ea54e0", "supports": "supports", "observer": "agent", "kind": "implementation", "observed_symbol": "ab57e29fc8ce1e431dc098f762decf18e309ef3e"} {"assertion": "assert.understand.observes-before-asserting", "reference": "skills/understanding-system/SKILL.md#Record Evidence references, then observe", "observed_at": "2026-09-11T18:26:51.264951Z", "observed_ref": "03c9e6937f7b43525007da01fe2bb234d8c41712", "observed_blob": "7d4ed02c376c5ef0facae5ec50e75069e92355a2", "observed_norm": "cae3a5732f59f4ca4c57d9c39a483e748566b39d", "supports": "supports", "observer": "agent", "kind": "documentation", "observed_symbol": "9062a1bf06b12d7e23b7cdd9b7774c4de38d04a0"} {"assertion": "assert.understand.observes-before-asserting", "reference": "traceos/engine.py#observe", "observed_at": "2026-09-11T18:26:51.398497Z", "observed_ref": "03c9e6937f7b43525007da01fe2bb234d8c41712", "observed_blob": "a870a87f68df6f8f3608f43fe3e353e63c56e170", "observed_norm": "8d3e91f52e26d5b2f015b02c910bef33b0ea54e0", "supports": "supports", "observer": "agent", "kind": "implementation", "observed_symbol": "d4a3dae251d0a995e6decdb6ce84fd030ec7f3cd"} +{"assertion": "assert.render.no-second-implementation", "reference": "traceos/explore.py#build", "observed_at": "2026-09-11T18:32:03.938884Z", "observed_ref": "4c34ce50d7b9682d0a9f9f669bae32da51c7925c", "observed_blob": "1574df8387a10f539acf564db1d2bba1815e0fd1", "observed_norm": "268333d35517dc625b97afe48071c6c420e6c7cf", "supports": "supports", "observer": "agent", "kind": "implementation", "observed_symbol": "6efad87df1b56fd5471729be3f974b6e22e5d7d8"} +{"assertion": "assert.render.no-second-implementation", "reference": "tests/run_tests.py#tool_explore", "observed_at": "2026-09-11T18:32:04.072064Z", "observed_ref": "4c34ce50d7b9682d0a9f9f669bae32da51c7925c", "observed_blob": "a606ebde9c7623449f35cf98c6cfce3aa0252d17", "observed_norm": "dfce6a969090055d37d4a2d9ff0e571705741370", "supports": "supports", "observer": "agent", "kind": "test", "observed_symbol": "f058ed9593e81cf743f1153c09d6b227eca935e3"} diff --git a/tests/run_tests.py b/tests/run_tests.py index f41cbce..a606ebd 100644 --- a/tests/run_tests.py +++ b/tests/run_tests.py @@ -1429,6 +1429,34 @@ def tool_explore(): page = E.build(EXAMPLE, None, repo_files, contexts) model = T.Model(EXAMPLE) + # INV-027 / INV-028 in the one artifact a reader looks at first. Three outcome + # states must be distinguishable, not two: a checked outcome, a check nobody has + # run, and no check at all. + itself = E.build(ROOT / "examples" / "traceos-itself", ROOT, None, [{}]) + check( + "TOOL explore", + "a Flow's Intents are rendered, labelled as provenance not truth", + "provenance, never truth" in itself and "intent.a-view-is-not-a-source" in itself, + ) + check( + "TOOL explore", + "an outcome shows the check that verifies it", + 'class="conf confirmed">' in itself or "checked" in itself, + ) + check( + "TOOL explore", + "a Flow with no Intent says so rather than rendering an empty list", + "no Intent declares why this Flow exists" in itself, + ) + # The third state, which traceos-itself no longer has: an outcome nobody checks. + # Asserting only against a model where every outcome is checked is a test that + # cannot fail for the case it is named after. + check( + "TOOL explore", + "an outcome with no declared check is drawn differently, not omitted", + "no check declared" in page, + ) + embedded = json.loads(re.search(r"const IMPACT = (\{.*?\});\n", page, re.S).group(1)) drifted = [ loc for loc, result in embedded.items() if T.impact(model, [loc]) != result diff --git a/traceos/explore.py b/traceos/explore.py index 3a189cd..1574df8 100644 --- a/traceos/explore.py +++ b/traceos/explore.py @@ -236,15 +236,56 @@ def conf_of(aid: str) -> str: for fid, flow in ordered: trig = flow.get("trigger", {}) trig_text = trig.get("ref") or trig.get("semantic") or trig.get("actor") or "" + + def outcome_check(outcome: dict) -> str: + """INV-027 rendered as three states, never two. + + A declared check, a declared check nobody has run, and no check at all are + different situations, and an explorer that drew them the same way would be + the silent boundary INV-025 forbids - in the one place a reader looks first. + """ + verified_by = outcome.get("verified_by") + if not verified_by: + return 'no check declared' + conf = conf_of(verified_by) if verified_by in model.assertions else None + if conf is None: + return ( + f'check missing: {e(verified_by)}' + ) + latest = T.latest_observation(model, verified_by) + if latest is None: + return ( + f'never checked ' + f'{e(verified_by)}' + ) + if latest.get("supports") == "refutes": + return ( + f'REFUTED ' + f'{e(verified_by)}' + ) + return ( + f'{CONF_GLYPH[conf]} checked ' + f'{e(verified_by)}' + ) + outcomes = "".join( f'
{e(s['subject'])}={e(str(s['value']))}"
for s in o.get("states") or []
)
+ + f"