From bc480c043124dbfb075b2dd1852c8a7cea46dc05 Mon Sep 17 00:00:00 2001 From: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com> Date: Fri, 9 Oct 2026 16:08:12 +0300 Subject: [PATCH] fix(review): complete cost reporting and dependency inventory --- docs/inventories/FACADE_INVENTORY.md | 4 ++-- scripts/run_external_review.py | 6 +++--- tests/test_external_review_script.py | 19 +++++++++++++++---- tests/test_module_handle_extraction.py | 2 +- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/docs/inventories/FACADE_INVENTORY.md b/docs/inventories/FACADE_INVENTORY.md index 5197bca70..c52f648c4 100644 --- a/docs/inventories/FACADE_INVENTORY.md +++ b/docs/inventories/FACADE_INVENTORY.md @@ -2,7 +2,7 @@ AST-derived inventory of compatibility facades, regenerated by `python scripts/regenerate_inventories.py`. Do not edit. A facade row is any runtime module whose top-level `from import ...` statements carry the `noqa: F401` re-export marker — the codebase's declared "this binding exists for its binding, not for this module's own use" convention (reference FACADE_CONSUMERS method). Leaf domains come from `ouroboros/domains.toml`; a leaf outside the facade's domain is marked ✗ (that edge also appears in the manifest's pinned direction matrix). `tests/test_generated_inventories.py` pins byte-identity, so any re-export surface change must regenerate this file. -- facade modules: **64**; marked re-export bindings: **2330**; cross-domain facade→leaf pairs: **129** +- facade modules: **64**; marked re-export bindings: **2333**; cross-domain facade→leaf pairs: **129** | facade | domain | bindings | leaves | |---|---|---:|---| @@ -34,7 +34,7 @@ AST-derived inventory of compatibility facades, regenerated by `python scripts/r | `ouroboros/review_cycles.py` | D06 | 1 | `ouroboros/outcomes.py` (1 ✗D01) | | `ouroboros/review_evidence.py` | D06 | 37 | `ouroboros/review_evidence_sections.py` (34)
`ouroboros/tool_capabilities.py` (1 ✗D04)
`ouroboros/utils.py` (2 ✗D18) | | `ouroboros/review_execution.py` | D06 | 11 | `ouroboros/review_slot_cancel.py` (5)
`ouroboros/review_verdict_extraction.py` (6) | -| `ouroboros/review_state.py` | D06 | 54 | `ouroboros/review_state_custody.py` (9)
`ouroboros/review_state_model.py` (1)
`ouroboros/review_state_records.py` (44) | +| `ouroboros/review_state.py` | D06 | 57 | `ouroboros/review_state_custody.py` (9)
`ouroboros/review_state_model.py` (1)
`ouroboros/review_state_records.py` (47) | | `ouroboros/review_substrate.py` | D06 | 74 | `ouroboros/_outcome_receipts.py` (1 ✗D01)
`ouroboros/observability.py` (3 ✗D16)
`ouroboros/outcomes.py` (3 ✗D01)
`ouroboros/provider_models.py` (1 ✗D02)
`ouroboros/review_dispatch.py` (9)
`ouroboros/review_execution.py` (15)
`ouroboros/review_execution_projection.py` (3)
`ouroboros/review_projection.py` (8)
`ouroboros/review_records.py` (9)
`ouroboros/review_verdict.py` (20)
`ouroboros/reviewer_slot_config.py` (1)
`ouroboros/task_results.py` (1 ✗D17) | | `ouroboros/skill_loader.py` | D14 | 3 | `ouroboros/skill_conflicts.py` (3) | | `ouroboros/skill_review.py` | D14 | 59 | `ouroboros/skill_review_cycles.py` (8)
`ouroboros/skill_review_history.py` (5)
`ouroboros/skill_review_output.py` (4)
`ouroboros/skill_review_packs.py` (8)
`ouroboros/skill_review_prompt.py` (7)
`ouroboros/skill_review_rebuttals.py` (4)
`ouroboros/skill_review_status.py` (8)
`ouroboros/tools/review_helpers.py` (8 ✗D06)
`ouroboros/triad_review.py` (3 ✗D06)
`ouroboros/utils.py` (4 ✗D18) | diff --git a/scripts/run_external_review.py b/scripts/run_external_review.py index ea3f6e541..4c3f431e3 100755 --- a/scripts/run_external_review.py +++ b/scripts/run_external_review.py @@ -718,8 +718,8 @@ def _contributor_execution_receipts( def _review_evidence_and_cost(actors: list[tuple[str, dict]]) -> tuple[list[dict], dict]: """A neutral seat-level evidence/cost report. - A zero or missing seat cost is never presented as proof that the call was - free: every dispatched seat without a reported positive cost is unreported. + Reported zero and positive amounts stay known independently of lifecycle; + missing amounts stay unknown. The report does not establish billing finality. """ evidence: list[dict] = [] reported_cost = 0.0 @@ -735,7 +735,7 @@ def _review_evidence_and_cost(actors: list[tuple[str, dict]]) -> tuple[list[dict "response_ref": actor["response_ref"], }) cost = actor.get("usd") - if isinstance(cost, (int, float)) and not isinstance(cost, bool) and cost > 0: + if isinstance(cost, (int, float)) and not isinstance(cost, bool) and cost >= 0: reported_cost += float(cost) reported_slots.append(slot) else: diff --git a/tests/test_external_review_script.py b/tests/test_external_review_script.py index e1479e4e8..c2ec2b326 100644 --- a/tests/test_external_review_script.py +++ b/tests/test_external_review_script.py @@ -1045,14 +1045,25 @@ def test_external_review_cost_report_never_turns_unknown_into_zero(): assert [(surface, actor["slot_id"]) for surface, actor in actors][-1] == ("pool", "scope_slot_1") assert evidence[0]["prompt_ref"] == {"manifest_ref": "prompt-1"} assert report["reported_actor_cost_usd"] == 0.03 - assert report["unreported_or_unknown_cost_slots"] == ["scope_slot_1"] + assert report["reported_cost_slots"] == ["slot_1", "slot_2", "slot_3", "scope_slot_1"] + assert report["unreported_or_unknown_cost_slots"] == [] assert "not treated as $0" in report["note"] - # An open seat has no cost yet (unknown, never $0); a seat never dispatched is no actor. - pending = _actors([{**triad[0], "status": "pending"}]) - assert _review_evidence_and_cost(pending)[1]["unreported_or_unknown_cost_slots"] == ["slot_1"] + # A seat never dispatched remains outside the actor report. assert _record_actors({"rows": [{"seat_id": "x", "status": "not_dispatched"}]}) == [] +@pytest.mark.parametrize("status", ["pending", "responded"]) +@pytest.mark.parametrize("cost", [0.01, 0.0, None]) +def test_external_review_cost_report_keeps_amount_knowledge_separate_from_lifecycle(status, cost): + actors = _actors([{"slot_id": "slot_1", "model_id": "reviewer", "status": status, "cost_usd": cost}]) + evidence, report = _review_evidence_and_cost(actors) + assert evidence[0]["status"] == status + assert report["reported_actor_cost_usd"] == (cost if cost is not None else 0.0) + assert report["reported_cost_slots"] == (["slot_1"] if cost is not None else []) + assert report["unreported_or_unknown_cost_slots"] == ([] if cost is not None else ["slot_1"]) + assert "core usage ledger remains the monetary authority" in report["note"] + + def test_exit_classification_separates_infra_from_genuine_blocks(): assert _classify_exit({"status": "passed"}) == 0 assert _classify_exit({"status": "blocked", "block_reason": "critical_findings"}) == 1 diff --git a/tests/test_module_handle_extraction.py b/tests/test_module_handle_extraction.py index 06238686a..52d8c5179 100644 --- a/tests/test_module_handle_extraction.py +++ b/tests/test_module_handle_extraction.py @@ -387,7 +387,7 @@ LEAVES: dict[str, tuple[str, str, frozenset[str]]] = { "ouroboros/review_projection.py": ("ouroboros/review_substrate.py", "_sub", frozenset({ "DIALOGUE_STATUS_VALUES", "HARDNESS_ADVISORY_VISIBLE", "HARDNESS_HARD_GATE", "MAX_PROJECTED_ACTOR_FINDINGS", "OUTCOME_TIER_BEST_EFFORT", "OUTCOME_TIER_BLOCKED", - "OUTCOME_TIER_SOLVED", "disclosed_list_projection", "panel_reason", + "OUTCOME_TIER_SOLVED", "TYPED_FAILURE_FACT_KEYS", "disclosed_list_projection", "panel_reason", "projected_finding_row", "provider_for_model", "redact_projection", "review_binding_hash", "review_executions_from_actor_usage", })),