fix: #412/#413/#414 runtime stability and PR governance preflight
All checks were successful
Gitea CI / test (push) Successful in 38s
Gitea CI / test (pull_request) Successful in 38s

## #413 — runtime_verify_monitor.sh pipefail fix
- find_live_pids() now captures pgrep output via local variable with || true
  so pipefail never triggers on no-match (pgrep exit 1)
- Regression test added: monitor survives MAX_LOOPS=1 without crash

## #412 — startup crash logging improvement
- Add asyncio.CancelledError catch in sync_positions_from_broker call
  so BaseException-level cancellations are logged before propagating
- Provides evidence in run log if CancelledError causes future startup aborts

## #414 — PR governance preflight
- validate_pr_body.py: add REQ-ID/TASK-ID/TEST-ID pattern checks (--no-governance flag to skip)
- docs/workflow.md: new "PR Governance Preflight (Mandatory)" section
- docs/commands.md: "PR Body Governance Preflight" section before tea pulls create
- Tests: 4 new governance traceability tests in test_validate_pr_body.py

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
agentson
2026-03-04 23:27:12 +09:00
parent 7de2a818e8
commit 4200575c8e
8 changed files with 141 additions and 5 deletions

View File

@@ -37,6 +37,7 @@ def test_validate_pr_body_text_allows_escaped_newline_in_code_blocks() -> None:
[
"## Summary",
"- example uses `\\n` for explanation",
"- REQ-OPS-001 / TASK-OPS-001 / TEST-OPS-001",
"```bash",
"printf 'line1\\nline2\\n'",
"```",
@@ -63,7 +64,7 @@ def test_validate_pr_body_text_passes_with_valid_markdown() -> None:
text = "\n".join(
[
"## Summary",
"- item",
"- REQ-OPS-001 / TASK-OPS-001 / TEST-OPS-001",
"",
"## Validation",
"```bash",
@@ -74,6 +75,34 @@ def test_validate_pr_body_text_passes_with_valid_markdown() -> None:
assert module.validate_pr_body_text(text) == []
def test_validate_pr_body_text_detects_missing_req_id() -> None:
module = _load_module()
text = "## Summary\n- TASK-OPS-001 / TEST-OPS-001 item\n"
errors = module.validate_pr_body_text(text)
assert any("REQ-ID" in err for err in errors)
def test_validate_pr_body_text_detects_missing_task_id() -> None:
module = _load_module()
text = "## Summary\n- REQ-OPS-001 / TEST-OPS-001 item\n"
errors = module.validate_pr_body_text(text)
assert any("TASK-ID" in err for err in errors)
def test_validate_pr_body_text_detects_missing_test_id() -> None:
module = _load_module()
text = "## Summary\n- REQ-OPS-001 / TASK-OPS-001 item\n"
errors = module.validate_pr_body_text(text)
assert any("TEST-ID" in err for err in errors)
def test_validate_pr_body_text_skips_governance_when_disabled() -> None:
module = _load_module()
text = "## Summary\n- item without any IDs\n"
errors = module.validate_pr_body_text(text, check_governance=False)
assert not any("REQ-ID" in err or "TASK-ID" in err or "TEST-ID" in err for err in errors)
def test_fetch_pr_body_reads_body_from_tea_api(monkeypatch) -> None:
module = _load_module()