project_agent_call_liveness_brd_written.md 3.15 KB

name: project-agent-call-liveness-brd-written description: BRD for "agent call timeout must be liveness-based, not fixed-duration" written 2026-08-13; call-site inventory and open questions for SDD stage metadata:

type: project

BRD written 2026-08-13 at docs/todo/agent-call-liveness-not-fixed-duration-timeout-brd.md, based on requirements doc docs/todo/agent-call-liveness-not-fixed-duration-timeout-requirements.md. Triggered by a real incident: task bfd3ee82's Validator planning call (large embedded SDD/PRD prompt) hit the 300s fixed timeout in trigger_org_node_structured and was misclassified as blocked_reason='execution_error' via scheduler.py's catch-all (not a real hang).

Why: this closes the gap already flagged in [feedback_agent_call_liveness_not_fixed_timeout] — the "no fixed-duration timeout" rule had been agreed before but never implemented; bfd3ee82 is the first real incident it caused, not the first time the rule was stated.

How to apply (facts verified 2026-08-13, re-check before trusting long-term):

  • Only e2e_pipeline.py:1131 (run_test_script_for_real) catches subprocess.TimeoutExpired specifically — everywhere else it falls through to the execution_error catch-all (task_execution.py::_mark_blocked line 223, scheduler.py line 255-256).
  • Full call-site inventory with fixed timeout= values (300/600/1200/180 etc, all fixed-duration wall-clock): org_node_trigger.py (the two entry points), e2e_pipeline.py (plan/review/ implement/validate, several call sites), work_graph_plan.py::plan_work_graph, work_graph_orchestrate.py (judgment/reflection/skill-fix, several), org_level_loop.py:: run_fix_loop, root_cause_trace.py::real_validator_perspective, org_node_lifecycle.py:: trigger_org_node_full, work_graph_execute.py::execute_work_graph (separate — Dynamic Workflow script exec, not a direct claude -p call, scoped as an open question not pre-included).
  • scheduler.py::_BLOCKED_REASON_FOR_EXCEPTION (line 82-89) is the existing exception-type → blocked_reason registry to extend with a new "real stall" exception type → agent_call_stalled, rather than inventing a parallel routing mechanism.
  • schema.py's blocked_reason column is unconstrained TEXT (no CHECK), and frontend/app.js only escapes/displays the raw string generically (no hardcoded enum switch beyond user_paused/user_stopped) — adding agent_call_stalled needs no schema migration and no frontend enum sync, unlike the drift pattern in [[project_task_status_enum_drift_gap]].
  • BRD deliberately left the core technical question open for SDD: what "liveness signal" is even observable, given claude -p --output-format json is one-shot, not streaming (needs real research, not an assumption) — see BRD's 阻塞未知/open-questions section before writing PRD/SDD.
  • Related but independent Goal: docs/todo/boss-agent-autonomous-blocked-task-arbiter- requirements.md (handles what to do once a task IS truly stuck in blocked_pending_human) — this BRD's fix should land first to reduce false-positive noise Boss Agent would otherwise have to triage.