Require published FI brief evidence before clearing daily due
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Container Image / build-and-push (push) Successful in 32s

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a09cbd-43c1-79f3-809e-1ee97b40b64d
This commit is contained in:
tegwick 2026-09-14 00:44:58 +02:00
parent 039010f2b8
commit 289aff3dbf
6 changed files with 110 additions and 22 deletions

View file

@ -43,8 +43,9 @@ from __future__ import annotations
import json
import logging
import os
import re
import time
from datetime import datetime, timezone
from datetime import date, datetime, timezone
from typing import Any
import httpx
@ -655,10 +656,10 @@ def _fi_brief_status(params: dict[str, Any]) -> dict[str, Any]:
Params: repo (default "freedom-intelligence"), timezone (IANA name,
default Europe/Berlin — "today" is evaluated in this zone).
due is true when no progress event with event_type=fi_daily_brief and
detail.repo matching the target repo exists for today. Executing sessions
must post that event on completion (see freedom-intelligence
docs/daily-brief-playbook.md).
Only a pushed completion with an immutable origin SHA and the canonical
brief path can clear due. Compare detail.date, not event arrival date, so
late delivery of yesterday's brief cannot suppress today's work. Git tree
verification is performed by freedom-intelligence's durability audit.
"""
repo = str(params.get("repo") or _FI_BRIEF_DEFAULT_REPO)
kind = str(params.get("kind") or "daily_brief")
@ -670,15 +671,23 @@ def _fi_brief_status(params: dict[str, Any]) -> dict[str, Any]:
today = now_local.date()
events = _binky_progress_events(_FI_BRIEF_EVENT_TYPE, repo)
timestamps = [
ts
for ts in (
_parse_progress_timestamp(item.get("created_at")) for item in events
)
if ts > datetime.min.replace(tzinfo=timezone.utc)
]
last_run = max(timestamps, default=None)
due = last_run is None or last_run.astimezone(tz).date() != today
valid = []
for event in events:
detail = _progress_detail(event)
day = detail.get("date")
try:
parsed_day = date.fromisoformat(day)
except (ValueError, TypeError):
continue
if (parsed_day.isoformat() != day or detail.get("repo") != repo
or detail.get("pushed") is not True
or not re.fullmatch(r"[0-9a-f]{40}", str(detail.get("origin_sha", "")))
or detail.get("path") != f"briefs/{day[:4]}/{day[5:7]}/{day}.md"):
continue
valid.append(event)
timestamps = [_parse_progress_timestamp(event.get("created_at")) for event in valid]
last_run = max((ts for ts in timestamps if ts > datetime.min.replace(tzinfo=timezone.utc)), default=None)
due = not any(_progress_detail(event)["date"] == today.isoformat() for event in valid)
return {
"items": [