From 43c3f0503b1bca667ee96f4912bcf7384ed13597 Mon Sep 17 00:00:00 2001 From: bboonnee Date: Fri, 7 Aug 2026 22:26:57 +0800 Subject: [PATCH] Give test_script verify failures their own blocked_reason --- src/scheduler.py | 19 +++++++++++++++++++ src/test_scheduler.py | 14 ++++++++++++++ 2 files changed, 33 insertions(+), 0 deletions(-) diff --git a/src/scheduler.py b/src/scheduler.py index b6fe870..7fe2b3e 100644 --- a/src/scheduler.py +++ b/src/scheduler.py @@ -89,6 +89,25 @@ _ROUTABLE_EXCEPTIONS = tuple(exc for exc, _ in _BLOCKED_REASON_FOR_EXCEPTION) def _blocked_reason_for(exc): + """2026-08-07: `ConsistencyCheckFailedError` used to be raised only by + the PRD-internal-contradiction check, but commit 07a0a27 (2026-08-06) + generalized the same exception/retry machinery to the test_script + mechanical compile-check too -- without this, both show up in the + console as the same misleading 'prd_consistency_check_failed' label + (see docs/todo/validator-test-script-narrative-output-issue.md), even + when the real failure has nothing to do with the PRD. + ponytail: distinguishes by substring-matching the failing node's LLM- + chosen node_id (e.g. 'n_test_script'/'validator_test_script') rather + than a real typed discriminator threaded through verify_fn -- good + enough because every real graph_manifest observed so far names its + test_script node descriptively; ceiling is a node named ambiguously + silently falling back to the PRD label. Upgrade path if that's ever + wrong in practice: have verify_fn return a third 'kind' value instead + of inferring from node_id text.""" + if isinstance(exc, work_graph_orchestrate.ConsistencyCheckFailedError): + if "test_script" in (exc.node_id or ""): + return "test_script_verification_failed" + return "prd_consistency_check_failed" for exc_type, reason in _BLOCKED_REASON_FOR_EXCEPTION: if isinstance(exc, exc_type): return reason diff --git a/src/test_scheduler.py b/src/test_scheduler.py index d6fa2bf..3051903 100644 --- a/src/test_scheduler.py +++ b/src/test_scheduler.py @@ -349,6 +349,20 @@ class ConsistencyCheckFailedRoutingTest(RoutableExceptionTestBase): self.assertEqual(result["blocked_reason"], "prd_consistency_check_failed") self._assert_task_blocked(result["task_id"], "prd_consistency_check_failed") + def test_test_script_node_gets_its_own_reason_not_the_prd_one(self): + # 2026-08-07: same exception class, but raised by the test_script + # mechanical compile-check (docs/todo/validator-test-script- + # narrative-output-issue.md), not the PRD-consistency check -- the + # console must not blame the PRD for an unrelated failure. + result = self._run_with_raising_lifecycle( + scheduler.work_graph_orchestrate.ConsistencyCheckFailedError( + "boom", node_id="validator_test_script" + ) + ) + self.assertEqual(result["final_status"], "blocked_pending_human") + self.assertEqual(result["blocked_reason"], "test_script_verification_failed") + self._assert_task_blocked(result["task_id"], "test_script_verification_failed") + class UnroutedExceptionStillBlocksTaskTest(RoutableExceptionTestBase): def test_other_exceptions_block_the_task_instead_of_leaving_it_stuck(self): -- libgit2 0.21.4