Require published FI brief evidence before clearing daily due
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a09cbd-43c1-79f3-809e-1ee97b40b64d
This commit is contained in:
parent
039010f2b8
commit
289aff3dbf
6 changed files with 110 additions and 22 deletions
|
|
@ -34,7 +34,7 @@
|
|||
| workplan | ACTIVITY-WP-0028 | finished | — | workplans/ACTIVITY-WP-0028-activity-review-cli.md |
|
||||
| workplan | ACTIVITY-WP-0029 | finished | — | workplans/ACTIVITY-WP-0029-hub-port-alignment.md |
|
||||
| workplan | ACTIVITY-WP-0030 | finished | — | workplans/ACTIVITY-WP-0030-daily-sbom-catchup.md |
|
||||
| workplan | ACTIVITY-WP-0031 | active | — | workplans/ACTIVITY-WP-0031-production-execution-reliability-cleanup.md |
|
||||
| workplan | ACTIVITY-WP-0031 | finished | — | workplans/ACTIVITY-WP-0031-production-execution-reliability-cleanup.md |
|
||||
| workplan | ACTIVITY-WP-0032 | active | — | workplans/ACTIVITY-WP-0032-glas-profile-execution-contract.md |
|
||||
| workplan | ACTIVITY-WP-0033 | finished | — | workplans/ACTIVITY-WP-0033-sbom-catchup-retry-boundary.md |
|
||||
| workplan | ACTIVITY-WP-0034 | finished | — | workplans/ACTIVITY-WP-0034-sbom-controlled-source-reference.md |
|
||||
|
|
@ -44,6 +44,7 @@
|
|||
| workplan | ACTIVITY-WP-ADHOC-2026-06-01 | finished | — | workplans/ADHOC-2026-06-01.md |
|
||||
| workplan | ACTIVITY-WP-ADHOC-2026-08-20 | finished | — | workplans/ADHOC-2026-08-20.md |
|
||||
| workplan | ACTIVITY-WP-ADHOC-2026-08-23 | finished | — | workplans/ADHOC-2026-08-23.md |
|
||||
| workplan | ACTIVITY-WP-ADHOC-2026-09-14 | finished | — | workplans/ADHOC-2026-09-14.md |
|
||||
| workplan | custodian-WP-0001 | done | — | workplans/custodian-WP-0001-temporal-backbone.md |
|
||||
| workplan | custodian-WP-0002 | done | — | workplans/custodian-WP-0002-triggers-ops.md |
|
||||
| workplan | custodian-WP-0003a | done | — | workplans/custodian-WP-0003a-event-bridge-model-rules-registry.md |
|
||||
|
|
@ -199,7 +200,7 @@
|
|||
| task | ACTIVITY-WP-0031-T02 | done | — | workplans/ACTIVITY-WP-0031-production-execution-reliability-cleanup.md |
|
||||
| task | ACTIVITY-WP-0031-T03 | done | — | workplans/ACTIVITY-WP-0031-production-execution-reliability-cleanup.md |
|
||||
| task | ACTIVITY-WP-0031-T04 | done | — | workplans/ACTIVITY-WP-0031-production-execution-reliability-cleanup.md |
|
||||
| task | ACTIVITY-WP-0031-T05 | wait | — | workplans/ACTIVITY-WP-0031-production-execution-reliability-cleanup.md |
|
||||
| task | ACTIVITY-WP-0031-T05 | done | — | workplans/ACTIVITY-WP-0031-production-execution-reliability-cleanup.md |
|
||||
| task | ACTIVITY-WP-0032-T01 | done | — | workplans/ACTIVITY-WP-0032-glas-profile-execution-contract.md |
|
||||
| task | ACTIVITY-WP-0032-T02 | done | — | workplans/ACTIVITY-WP-0032-glas-profile-execution-contract.md |
|
||||
| task | ACTIVITY-WP-0032-T03 | done | — | workplans/ACTIVITY-WP-0032-glas-profile-execution-contract.md |
|
||||
|
|
@ -231,6 +232,8 @@
|
|||
| task | ACTIVITY-WP-ADHOC-2026-06-01-T03 | done | — | workplans/ADHOC-2026-06-01.md |
|
||||
| task | ACTIVITY-WP-ADHOC-2026-08-20-T01 | done | — | workplans/ADHOC-2026-08-20.md |
|
||||
| task | ACTIVITY-WP-ADHOC-2026-08-23-T01 | done | — | workplans/ADHOC-2026-08-23.md |
|
||||
| task | ACTIVITY-WP-ADHOC-2026-09-14-T01 | done | — | workplans/ADHOC-2026-09-14.md |
|
||||
| task | ACTIVITY-WP-ADHOC-2026-09-14-T02 | done | — | workplans/ADHOC-2026-09-14.md |
|
||||
| task | T01 | done | — | workplans/custodian-WP-0001-temporal-backbone.md |
|
||||
| task | T02 | done | — | workplans/custodian-WP-0001-temporal-backbone.md |
|
||||
| task | T03 | done | — | workplans/custodian-WP-0001-temporal-backbone.md |
|
||||
|
|
|
|||
|
|
@ -1202,7 +1202,7 @@ spec:
|
|||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: migrate
|
||||
image: activity-core:railiance01-prod
|
||||
image: activity-core:fi-publication-20260914
|
||||
imagePullPolicy: Never
|
||||
command: ["python", "-m", "alembic", "upgrade", "head"]
|
||||
envFrom:
|
||||
|
|
@ -1230,7 +1230,7 @@ spec:
|
|||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: sync
|
||||
image: activity-core:railiance01-prod
|
||||
image: activity-core:fi-publication-20260914
|
||||
imagePullPolicy: Never
|
||||
command:
|
||||
- sh
|
||||
|
|
@ -1287,7 +1287,7 @@ spec:
|
|||
spec:
|
||||
containers:
|
||||
- name: api
|
||||
image: activity-core:railiance01-prod
|
||||
image: activity-core:fi-publication-20260914
|
||||
imagePullPolicy: Never
|
||||
command: ["uvicorn", "activity_core.api:app", "--host", "0.0.0.0", "--port", "8010"]
|
||||
ports:
|
||||
|
|
@ -1363,7 +1363,7 @@ spec:
|
|||
fsGroup: 1000
|
||||
containers:
|
||||
- name: worker
|
||||
image: activity-core:railiance01-prod
|
||||
image: activity-core:fi-publication-20260914
|
||||
imagePullPolicy: Never
|
||||
command: ["python", "-m", "activity_core.worker"]
|
||||
ports:
|
||||
|
|
@ -1458,7 +1458,7 @@ spec:
|
|||
spec:
|
||||
containers:
|
||||
- name: event-router
|
||||
image: activity-core:railiance01-prod
|
||||
image: activity-core:fi-publication-20260914
|
||||
imagePullPolicy: Never
|
||||
command: ["python", "-m", "activity_core.event_router"]
|
||||
envFrom:
|
||||
|
|
|
|||
|
|
@ -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": [
|
||||
|
|
|
|||
|
|
@ -1150,7 +1150,9 @@ def test_fi_brief_status_not_due_after_todays_run(monkeypatch) -> None:
|
|||
{
|
||||
"event_type": "fi_daily_brief",
|
||||
"created_at": "2026-07-17T05:30:00+00:00",
|
||||
"detail": {"repo": "freedom-intelligence"},
|
||||
"detail": {"repo": "freedom-intelligence", "date": "2026-07-17",
|
||||
"path": "briefs/2026/07/2026-07-17.md",
|
||||
"pushed": True, "origin_sha": "a" * 40},
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -1195,3 +1197,27 @@ def test_fi_brief_status_unknown_kind(monkeypatch) -> None:
|
|||
|
||||
assert result["items"] == []
|
||||
assert "unknown kind" in result["error"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("override", [
|
||||
{"pushed": False}, {"pushed": "true"}, {"origin_sha": ""},
|
||||
{"origin_sha": "main"}, {"path": "briefs/wrong.md"}, {"date": "bad-date"},
|
||||
{"repo": None},
|
||||
])
|
||||
def test_fi_brief_rejects_unpublished_or_malformed_completion(monkeypatch, override):
|
||||
detail = dict(repo="freedom-intelligence", date="2026-07-17",
|
||||
path="briefs/2026/07/2026-07-17.md", pushed=True, origin_sha="a" * 40)
|
||||
detail.update(override)
|
||||
_binky_resolver_env(monkeypatch, {"fi_daily_brief": [dict(
|
||||
event_type="fi_daily_brief", created_at="2026-07-17T05:30:00+00:00", detail=detail)]})
|
||||
result = StateHubContextResolver().resolve("fi_brief_status", None, {"repo": "freedom-intelligence"})
|
||||
assert result["items"][0]["due"] is True
|
||||
|
||||
|
||||
def test_fi_brief_late_yesterday_event_does_not_clear_today(monkeypatch):
|
||||
detail = dict(repo="freedom-intelligence", date="2026-07-16",
|
||||
path="briefs/2026/07/2026-07-16.md", pushed=True, origin_sha="a" * 40)
|
||||
_binky_resolver_env(monkeypatch, {"fi_daily_brief": [dict(
|
||||
event_type="fi_daily_brief", created_at="2026-07-17T05:30:00+00:00", detail=detail)]})
|
||||
result = StateHubContextResolver().resolve("fi_brief_status", None, {"repo": "freedom-intelligence"})
|
||||
assert result["items"][0]["due"] is True
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ owner: custodian
|
|||
topic_slug: custodian
|
||||
created: "2026-06-01"
|
||||
updated: "2026-06-03"
|
||||
state_hub_workstream_id: "4b5abcd1-e1a2-5840-a852-2d14c867c5f8"
|
||||
---
|
||||
|
||||
# ACTIVITY-WP-ADHOC-2026-06-01 — activity-core opportunistic fixes
|
||||
|
|
|
|||
49
workplans/ADHOC-2026-09-14.md
Normal file
49
workplans/ADHOC-2026-09-14.md
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
---
|
||||
id: ACTIVITY-WP-ADHOC-2026-09-14
|
||||
type: workplan
|
||||
title: Require publication evidence for the FI daily due gate
|
||||
domain: infotech
|
||||
repo: activity-core
|
||||
status: finished
|
||||
owner: codex
|
||||
created: "2026-09-14"
|
||||
updated: "2026-09-14"
|
||||
state_hub_workstream_id: "5434dcd8-f1a4-5869-a306-dfa7eaff5885"
|
||||
---
|
||||
|
||||
## Reject unpublished and misdated FI completion events
|
||||
|
||||
```task
|
||||
id: ACTIVITY-WP-ADHOC-2026-09-14-T01
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "78b343f0-4059-5df6-b4e3-2187a97dccef"
|
||||
```
|
||||
|
||||
Only pushed=true, full origin SHA and canonical date/path can clear due.
|
||||
Use detail.date rather than created_at, so late delivery cannot suppress the
|
||||
next day. The FI verifier checks actual origin objects. Resolver suite: 47
|
||||
passed, including invalid publication and delayed-delivery regression cases.
|
||||
|
||||
## Deploy and verify the production resolver
|
||||
|
||||
```task
|
||||
id: ACTIVITY-WP-ADHOC-2026-09-14-T02
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "0d1d729c-ce48-5784-99cc-dea4a5e5b587"
|
||||
```
|
||||
|
||||
Use image activity-core:fi-publication-20260914, layered over the exact live
|
||||
baseline (container image ID sha256:e6e9f0171e36ce0f50a970435ea55f10d428f1743050d1629a94ff4fd19cec37).
|
||||
The baseline resolver module was byte-identical to pre-change repo HEAD;
|
||||
only the tested module is replaced. No schema or other application changes.
|
||||
Keep the remote checkout's unrelated dirty files untouched.
|
||||
|
||||
Roll API, worker and event-router; verify rollout, live due=true for the
|
||||
September 14 brief, and Temporal next action 05:30 UTC / 07:30 Berlin.
|
||||
Future run completion must be proven separately by FI's --require-date audit.
|
||||
|
||||
Live verification: API, worker and event-router run the new image and are ready.
|
||||
API imports the patched resolver; September 14 remains due until publication.
|
||||
The three image smoke cases (unpublished, published, late delivery) passed.
|
||||
Loading…
Add table
Add a link
Reference in a new issue