From dd51ffb6ace4f38c14a278e584455929dbd81596 Mon Sep 17 00:00:00 2001 From: agentson Date: Sat, 28 Feb 2026 09:37:16 +0900 Subject: [PATCH] process: enforce forbidden runtime invariants in monitor (#316) --- docs/commands.md | 5 +++- docs/workflow.md | 5 ++++ scripts/runtime_verify_monitor.sh | 42 ++++++++++++++++++++++++++++--- workflow/session-handover.md | 8 ++++++ 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/docs/commands.md b/docs/commands.md index aeb0210..f70a844 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -157,9 +157,12 @@ python -m src.main --mode=paper # Run with dashboard enabled python -m src.main --mode=paper --dashboard -# Runtime verification monitor (NOT_OBSERVED detection) +# Runtime verification monitor (coverage + forbidden invariants) bash scripts/runtime_verify_monitor.sh +# Runtime monitor with explicit policy timezone (example: KST) +POLICY_TZ=Asia/Seoul bash scripts/runtime_verify_monitor.sh + # Session handover gate (must pass before implementation) python3 scripts/session_handover_check.py --strict diff --git a/docs/workflow.md b/docs/workflow.md index 9fb3c24..288fe70 100644 --- a/docs/workflow.md +++ b/docs/workflow.md @@ -195,6 +195,11 @@ Use `run_in_background=True` for independent tasks that don't block subsequent w - `NOT_OBSERVED`는 운영상 `FAIL`과 동일하게 처리 - `NOT_OBSERVED`가 하나라도 있으면 승인/머지 금지 +`FORBIDDEN` 처리 규칙: +- 정책 위반 신호(예: 주말 `session=KRX_REG`)는 `FORBIDDEN=HIT`으로 별도 기록한다 +- `FORBIDDEN=HIT`은 즉시 `P0 FAIL`로 간주하고 모니터링 승인 불가 +- 실시간 모니터는 `alive`만으로 정상 판정하지 않는다(정책 불변식 통과가 필수) + ### Process-Change-First Rule (Mandatory) 재발 방지/운영 규칙 변경이 결정되면, 기능 구현 티켓보다 먼저 서버(feature branch)에 반영해야 한다. diff --git a/scripts/runtime_verify_monitor.sh b/scripts/runtime_verify_monitor.sh index 6c878a4..c2fbd58 100755 --- a/scripts/runtime_verify_monitor.sh +++ b/scripts/runtime_verify_monitor.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Runtime verification monitor with NOT_OBSERVED detection. +# Runtime verification monitor with coverage + forbidden invariant checks. set -euo pipefail @@ -7,6 +7,7 @@ ROOT_DIR="${ROOT_DIR:-/home/agentson/repos/The-Ouroboros}" LOG_DIR="${LOG_DIR:-$ROOT_DIR/data/overnight}" INTERVAL_SEC="${INTERVAL_SEC:-60}" MAX_HOURS="${MAX_HOURS:-24}" +POLICY_TZ="${POLICY_TZ:-Asia/Seoul}" cd "$ROOT_DIR" @@ -30,7 +31,20 @@ check_signal() { return 1 } -log "[INFO] runtime verify monitor started interval=${INTERVAL_SEC}s max_hours=${MAX_HOURS}" +check_forbidden() { + local name="$1" + local pattern="$2" + local run_log="$3" + + if rg -q "$pattern" "$run_log"; then + log "[FORBIDDEN] ${name}=HIT pattern=${pattern}" + return 1 + fi + log "[FORBIDDEN] ${name}=CLEAR pattern=${pattern}" + return 0 +} + +log "[INFO] runtime verify monitor started interval=${INTERVAL_SEC}s max_hours=${MAX_HOURS} policy_tz=${POLICY_TZ}" while true; do now=$(date +%s) @@ -73,6 +87,28 @@ while true; do log "[OK] coverage complete (NOT_OBSERVED=0)" fi + # Forbidden invariants: must never happen under given policy context. + forbidden_hits=0 + policy_dow="$(TZ="$POLICY_TZ" date +%u)" # 1..7 (Mon..Sun) + is_weekend=0 + if [ "$policy_dow" -ge 6 ]; then + is_weekend=1 + fi + + if [ "$is_weekend" -eq 1 ]; then + # Weekend policy: KR regular session loop must never appear. + check_forbidden "WEEKEND_KR_SESSION_ACTIVE" \ + "Market session active: KR|session=KRX_REG|Processing market: Korea Exchange" \ + "$latest_run" || forbidden_hits=$((forbidden_hits+1)) + else + log "[FORBIDDEN] WEEKEND_KR_SESSION_ACTIVE=SKIP reason=weekday" + fi + + if [ "$forbidden_hits" -gt 0 ]; then + log "[P0] forbidden_invariant_hits=$forbidden_hits (treat as immediate FAIL)" + else + log "[OK] forbidden invariants clear" + fi + sleep "$INTERVAL_SEC" done - diff --git a/workflow/session-handover.md b/workflow/session-handover.md index 89d09c8..a3fd61b 100644 --- a/workflow/session-handover.md +++ b/workflow/session-handover.md @@ -81,3 +81,11 @@ - next_ticket: #314 - process_gate_checked: process_ticket=#306,#308 merged_to_feature_branch=yes - risks_or_notes: 백테스트 자동 게이트 도입 티켓 브랜치 strict gate 통과용 엔트리 + +### 2026-02-28 | session=codex-issue316-forbidden-monitor +- branch: feature/issue-316-weekend-forbidden-monitor +- docs_checked: docs/workflow.md, docs/commands.md, docs/agent-constraints.md +- open_issues_reviewed: #316 +- next_ticket: #316 +- process_gate_checked: process_ticket=#306,#308 merged_to_feature_branch=yes +- risks_or_notes: 모니터 판정을 liveness 중심에서 policy invariant(FORBIDDEN) 중심으로 전환