Publish FI briefs to origin or fail the day
Some checks failed
Governed runtime contract / contract (push) Failing after 26s
Some checks failed
Governed runtime contract / contract (push) Failing after 26s
FI-WP-0004 grants origin publication. Local commit without push no longer posts fi_daily_brief (that cleared due while losing the file). Prompt/context refuse re-announcing cataloged models and invented sizes. Assistant: grok Assistant-Session: 01a09c6a-1cfc-75b1-a78d-c13eaf22241d
This commit is contained in:
parent
ee3800f26d
commit
11020e8f00
4 changed files with 136 additions and 42 deletions
|
|
@ -59,14 +59,13 @@ constraint rather than a grant-bearing path.
|
||||||
| Inputs | FI sources allowlist, daily playbook, reserve status, two fixed research baselines/plans, recent briefs, and recent git log |
|
| Inputs | FI sources allowlist, daily playbook, reserve status, two fixed research baselines/plans, recent briefs, and recent git log |
|
||||||
| Model/credential lane | HTTP `LLM_CONNECT_URL`; model from `FI_RESEARCH_BRIEF_MODEL`, then Binky-named `BRIEF_DAILY_MODEL` / `MAIL_TRIAGE_MODEL`; provider credential remains behind llm-connect |
|
| Model/credential lane | HTTP `LLM_CONNECT_URL`; model from `FI_RESEARCH_BRIEF_MODEL`, then Binky-named `BRIEF_DAILY_MODEL` / `MAIL_TRIAGE_MODEL`; provider credential remains behind llm-connect |
|
||||||
| Output | `briefs/YYYY/MM/YYYY-MM-DD.md`; model JSON is rendered deterministically |
|
| Output | `briefs/YYYY/MM/YYYY-MM-DD.md`; model JSON is rendered deterministically |
|
||||||
| Repository mutation | Stages only the brief path and creates one local commit |
|
| Repository mutation | Stages the brief path, one local commit, then `git push origin` |
|
||||||
| Publication | Local commit only. The former `FI_RESEARCH_BRIEF_PUSH` path was removed 2026-09-04; publication requires a separate owner/grant. |
|
| Publication | Origin publication is a **FI-owned grant** (FI-WP-0004, 2026-09-13). The 2026-09-04 local-only commit was losing durable memory. |
|
||||||
| Completion | Best-effort State Hub `fi_daily_brief` with path/date/candidate count; `fi_brief_status` uses it to clear due state |
|
| Completion | State Hub `fi_daily_brief` only after `pushed=true` + `origin_sha`. Push failure posts `executor_run` and leaves `due=true`. |
|
||||||
| Failure/retry | Normal generation/commit failure reopens; an existing daily path succeeds idempotently |
|
| Failure/retry | Normal generation/commit failure reopens; an existing daily path succeeds idempotently |
|
||||||
| Current rollback material | Disable/pause the Activity Core definition. FI documents a disabled 07:35 host timer as break-glass, but its installer still enables that timer and must not be invoked casually |
|
| Current rollback material | Disable/pause the Activity Core definition. FI documents a disabled 07:35 host timer as break-glass, but its installer still enables that timer and must not be invoked casually |
|
||||||
|
|
||||||
Publication, if still needed, must become a separately named and granted
|
Origin publication is the named grant: FI-WP-0004-T04 in freedom-intelligence.
|
||||||
capability with remote-ref and result evidence.
|
|
||||||
The Binky-named fallback model environment variables must not survive in an FI
|
The Binky-named fallback model environment variables must not survive in an FI
|
||||||
owned declaration.
|
owned declaration.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -313,6 +313,8 @@ def _run_fi(target: Path, *, report_to_hub: bool, commit: bool) -> ApproachResul
|
||||||
"path": r.path,
|
"path": r.path,
|
||||||
"wrote": r.wrote,
|
"wrote": r.wrote,
|
||||||
"committed": r.committed,
|
"committed": r.committed,
|
||||||
|
"pushed": r.pushed,
|
||||||
|
"origin_sha": r.origin_sha,
|
||||||
"skipped_existing": r.skipped_existing,
|
"skipped_existing": r.skipped_existing,
|
||||||
"collection_candidates": r.collection_candidates,
|
"collection_candidates": r.collection_candidates,
|
||||||
"head_after": r.head_after,
|
"head_after": r.head_after,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
activity-core owns *when* (Temporal schedule + fi_brief_status).
|
activity-core owns *when* (Temporal schedule + fi_brief_status).
|
||||||
This rein command owns *execution*: draft brief from playbook context,
|
This rein command owns *execution*: draft brief from playbook context,
|
||||||
commit under freedom-intelligence, post fi_daily_brief for idempotence.
|
commit under freedom-intelligence, **push to origin**, then post
|
||||||
|
fi_daily_brief. A local-only commit is a failed day (FI-WP-0004).
|
||||||
|
|
||||||
No Claude Code / host coding agent — llm-connect only.
|
No Claude Code / host coding agent — llm-connect only.
|
||||||
"""
|
"""
|
||||||
|
|
@ -53,6 +54,8 @@ class FiResearchBriefResult:
|
||||||
model_meta: dict[str, Any] = field(default_factory=dict)
|
model_meta: dict[str, Any] = field(default_factory=dict)
|
||||||
skipped_existing: bool = False
|
skipped_existing: bool = False
|
||||||
collection_candidates: int = 0
|
collection_candidates: int = 0
|
||||||
|
pushed: bool = False
|
||||||
|
origin_sha: str = ""
|
||||||
|
|
||||||
|
|
||||||
def _berlin_today() -> date:
|
def _berlin_today() -> date:
|
||||||
|
|
@ -93,6 +96,17 @@ def collect_context(repo: Path, day: date) -> str:
|
||||||
f"{_truncate(last.read_text(encoding='utf-8', errors='replace'), 3500)}\n"
|
f"{_truncate(last.read_text(encoding='utf-8', errors='replace'), 3500)}\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
catalog = repo / "inventory" / "catalog"
|
||||||
|
if catalog.is_dir():
|
||||||
|
lines = [
|
||||||
|
"## Catalog (DO NOT re-announce these as new releases; "
|
||||||
|
"DO NOT invent sizes that contradict these entries)\n"
|
||||||
|
]
|
||||||
|
for p in sorted(catalog.glob("*.yaml")):
|
||||||
|
text = p.read_text(encoding="utf-8", errors="replace")
|
||||||
|
lines.append(f"### {p.name}\n{_truncate(text, 900)}\n")
|
||||||
|
chunks.append("\n".join(lines))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
log = _git(repo, "log", f"-{_MAX_GIT_LOG}", "--oneline")
|
log = _git(repo, "log", f"-{_MAX_GIT_LOG}", "--oneline")
|
||||||
chunks.append(f"## Recent git log\n{log}\n")
|
chunks.append(f"## Recent git log\n{log}\n")
|
||||||
|
|
@ -114,6 +128,12 @@ Rules:
|
||||||
- Cover axes when there is signal: A frontier/commercial, B open/local,
|
- Cover axes when there is signal: A frontier/commercial, B open/local,
|
||||||
C training/FT, D harness/fleet.
|
C training/FT, D harness/fleet.
|
||||||
- Flag collection candidates only when license/size/rationale are clear.
|
- Flag collection candidates only when license/size/rationale are clear.
|
||||||
|
- NEVER re-announce a model that already has a catalog YAML as a "new release".
|
||||||
|
- NEVER invent parameter counts or file sizes. If the card is not in context,
|
||||||
|
write "unknown — verify card" rather than guessing. DeepSeek-V4-Flash-0731
|
||||||
|
is a ~304B / ~13B-active MIT MoE (~167 GiB), NOT a 12B dense model.
|
||||||
|
- Every non-empty axis row needs a primary URL in "sources".
|
||||||
|
- Scan axes C (training) and D (harness) even if the result is an empty array.
|
||||||
- Prefer primary sources; mark unverified claims as "unverified".
|
- Prefer primary sources; mark unverified claims as "unverified".
|
||||||
- "No material delta" is allowed **only** when you have considered the prior
|
- "No material delta" is allowed **only** when you have considered the prior
|
||||||
brief + allowlist + reserve status and still find nothing. Even then:
|
brief + allowlist + reserve status and still find nothing. Even then:
|
||||||
|
|
@ -317,12 +337,12 @@ def _truncate(text: str, n: int) -> str:
|
||||||
return text[: n - 20] + "\n…(truncated)…\n"
|
return text[: n - 20] + "\n…(truncated)…\n"
|
||||||
|
|
||||||
|
|
||||||
def _git(repo: Path, *args: str) -> str:
|
def _git(repo: Path, *args: str, timeout: int = 60) -> str:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["git", "-C", str(repo), *args],
|
["git", "-C", str(repo), *args],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
timeout=60,
|
timeout=timeout,
|
||||||
)
|
)
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
raise FiResearchBriefError(
|
raise FiResearchBriefError(
|
||||||
|
|
@ -331,6 +351,15 @@ def _git(repo: Path, *args: str) -> str:
|
||||||
return result.stdout.strip()
|
return result.stdout.strip()
|
||||||
|
|
||||||
|
|
||||||
|
def _publish_origin(repo: Path) -> str:
|
||||||
|
"""Push HEAD to origin. FI-owned grant: origin is the durable brief store."""
|
||||||
|
branch = _git(repo, "rev-parse", "--abbrev-ref", "HEAD")
|
||||||
|
if not branch or branch == "HEAD":
|
||||||
|
branch = "main"
|
||||||
|
_git(repo, "push", "-u", "origin", f"HEAD:{branch}", timeout=120)
|
||||||
|
return _git(repo, "rev-parse", "HEAD")
|
||||||
|
|
||||||
|
|
||||||
def run_fi_research_brief(
|
def run_fi_research_brief(
|
||||||
target_repo: Path,
|
target_repo: Path,
|
||||||
*,
|
*,
|
||||||
|
|
@ -357,6 +386,7 @@ def run_fi_research_brief(
|
||||||
result.head_after = _git(repo, "rev-parse", "HEAD")
|
result.head_after = _git(repo, "rev-parse", "HEAD")
|
||||||
except FiResearchBriefError:
|
except FiResearchBriefError:
|
||||||
pass
|
pass
|
||||||
|
_finalize_publish(result, repo, commit=commit)
|
||||||
_hub(result, report_to_hub, repo)
|
_hub(result, report_to_hub, repo)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
@ -448,22 +478,41 @@ def run_fi_research_brief(
|
||||||
model_meta=meta,
|
model_meta=meta,
|
||||||
collection_candidates=n_cands,
|
collection_candidates=n_cands,
|
||||||
)
|
)
|
||||||
|
_finalize_publish(result, repo, commit=commit)
|
||||||
_hub(result, report_to_hub, repo)
|
_hub(result, report_to_hub, repo)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def _finalize_publish(
|
||||||
|
result: FiResearchBriefResult, repo: Path, *, commit: bool
|
||||||
|
) -> None:
|
||||||
|
"""Origin push is required for a successful brief day when we commit."""
|
||||||
|
if not commit or not result.ok:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
sha = _publish_origin(repo)
|
||||||
|
result.pushed = True
|
||||||
|
result.origin_sha = sha
|
||||||
|
result.head_after = sha
|
||||||
|
except FiResearchBriefError as exc:
|
||||||
|
result.ok = False
|
||||||
|
result.reason = f"origin publish failed: {exc}"[:300]
|
||||||
|
|
||||||
|
|
||||||
def _hub(result: FiResearchBriefResult, report_to_hub: bool, repo: Path) -> None:
|
def _hub(result: FiResearchBriefResult, report_to_hub: bool, repo: Path) -> None:
|
||||||
if not report_to_hub:
|
if not report_to_hub:
|
||||||
return
|
return
|
||||||
if result.ok:
|
# fi_daily_brief clears activity-core due. Only fire it when origin has
|
||||||
# Idempotence for activity-core fi_brief_status resolver
|
# the brief (FI-WP-0004). Local commit without push is a failed day.
|
||||||
|
published = result.ok and result.pushed
|
||||||
|
if published:
|
||||||
event_type = "fi_daily_brief"
|
event_type = "fi_daily_brief"
|
||||||
summary = (
|
summary = (
|
||||||
f"FI daily brief {result.date}"
|
f"FI daily brief {result.date}"
|
||||||
+ (
|
+ (
|
||||||
" (already present)"
|
" (already present, pushed)"
|
||||||
if result.skipped_existing
|
if result.skipped_existing
|
||||||
else f" wrote={result.wrote} committed={result.committed}"
|
else f" wrote={result.wrote} committed={result.committed} pushed={result.pushed}"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
detail = {
|
detail = {
|
||||||
|
|
@ -473,18 +522,23 @@ def _hub(result: FiResearchBriefResult, report_to_hub: bool, repo: Path) -> None
|
||||||
"collection_candidates": result.collection_candidates,
|
"collection_candidates": result.collection_candidates,
|
||||||
"wrote": result.wrote,
|
"wrote": result.wrote,
|
||||||
"committed": result.committed,
|
"committed": result.committed,
|
||||||
|
"pushed": result.pushed,
|
||||||
|
"origin_sha": result.origin_sha,
|
||||||
"skipped_existing": result.skipped_existing,
|
"skipped_existing": result.skipped_existing,
|
||||||
"executor": "rein-aharness",
|
"executor": "rein-aharness",
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
event_type = "executor_run"
|
event_type = "executor_run"
|
||||||
summary = f"FI daily research brief failed: {result.reason}"
|
summary = f"FI daily research brief failed: {result.reason or 'not published to origin'}"
|
||||||
detail = {
|
detail = {
|
||||||
"repo": "freedom-intelligence",
|
"repo": "freedom-intelligence",
|
||||||
"ok": False,
|
"ok": False,
|
||||||
"date": result.date,
|
"date": result.date,
|
||||||
"reason": result.reason,
|
"reason": result.reason,
|
||||||
"model_meta": result.model_meta,
|
"model_meta": result.model_meta,
|
||||||
|
"wrote": result.wrote,
|
||||||
|
"committed": result.committed,
|
||||||
|
"pushed": result.pushed,
|
||||||
"executor": "rein-aharness",
|
"executor": "rein-aharness",
|
||||||
}
|
}
|
||||||
hub.post_progress_event(summary=summary, event_type=event_type, detail=detail)
|
hub.post_progress_event(summary=summary, event_type=event_type, detail=detail)
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,14 @@ from pathlib import Path
|
||||||
from rein_aharness import fi_research_brief
|
from rein_aharness import fi_research_brief
|
||||||
|
|
||||||
|
|
||||||
|
def _git(cwd: Path, *args: str) -> None:
|
||||||
|
subprocess.run(["git", "-C", str(cwd), *args], check=True, capture_output=True)
|
||||||
|
|
||||||
|
|
||||||
def _repo(tmp_path: Path) -> Path:
|
def _repo(tmp_path: Path) -> Path:
|
||||||
repo = tmp_path / "freedom-intelligence"
|
repo = tmp_path / "freedom-intelligence"
|
||||||
repo.mkdir()
|
repo.mkdir()
|
||||||
subprocess.run(["git", "init", "-q"], cwd=repo, check=True)
|
subprocess.run(["git", "init", "-q", "-b", "main"], cwd=repo, check=True)
|
||||||
(repo / "README.md").write_text("baseline\n", encoding="utf-8")
|
(repo / "README.md").write_text("baseline\n", encoding="utf-8")
|
||||||
subprocess.run(["git", "add", "."], cwd=repo, check=True)
|
subprocess.run(["git", "add", "."], cwd=repo, check=True)
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
|
|
@ -31,25 +35,16 @@ def _repo(tmp_path: Path) -> Path:
|
||||||
return repo
|
return repo
|
||||||
|
|
||||||
|
|
||||||
def test_fi_brief_never_pushes_even_when_legacy_env_requests_it(
|
def _with_origin(tmp_path: Path, repo: Path) -> Path:
|
||||||
tmp_path: Path,
|
remote = tmp_path / "origin.git"
|
||||||
monkeypatch,
|
subprocess.run(["git", "init", "--bare", "-q", "-b", "main", str(remote)], check=True)
|
||||||
) -> None:
|
_git(repo, "remote", "add", "origin", str(remote))
|
||||||
repo = _repo(tmp_path)
|
_git(repo, "push", "-u", "origin", "HEAD:main")
|
||||||
monkeypatch.setenv("FI_RESEARCH_BRIEF_PUSH", "1")
|
return remote
|
||||||
original_git = fi_research_brief._git
|
|
||||||
calls: list[tuple[str, ...]] = []
|
|
||||||
|
|
||||||
def observed_git(target: Path, *args: str) -> str:
|
|
||||||
calls.append(args)
|
|
||||||
return original_git(target, *args)
|
|
||||||
|
|
||||||
monkeypatch.setattr(fi_research_brief, "_git", observed_git)
|
def _complete(_prompt: str) -> str:
|
||||||
result = fi_research_brief.run_fi_research_brief(
|
return json.dumps(
|
||||||
repo,
|
|
||||||
day=date(2026, 9, 4),
|
|
||||||
report_to_hub=False,
|
|
||||||
complete_fn=lambda _prompt: json.dumps(
|
|
||||||
{
|
{
|
||||||
"headline_deltas": ["No material delta after allowlist review."],
|
"headline_deltas": ["No material delta after allowlist review."],
|
||||||
"axis_a": [],
|
"axis_a": [],
|
||||||
|
|
@ -59,9 +54,53 @@ def test_fi_brief_never_pushes_even_when_legacy_env_requests_it(
|
||||||
"collection_candidates": [],
|
"collection_candidates": [],
|
||||||
"lab_implications": ["Recheck tomorrow."],
|
"lab_implications": ["Recheck tomorrow."],
|
||||||
}
|
}
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_fi_brief_pushes_to_origin_and_records_sha(tmp_path: Path) -> None:
|
||||||
|
repo = _repo(tmp_path)
|
||||||
|
_with_origin(tmp_path, repo)
|
||||||
|
result = fi_research_brief.run_fi_research_brief(
|
||||||
|
repo,
|
||||||
|
day=date(2026, 9, 13),
|
||||||
|
report_to_hub=False,
|
||||||
|
complete_fn=_complete,
|
||||||
|
)
|
||||||
assert result.ok is True
|
assert result.ok is True
|
||||||
assert result.committed is True
|
assert result.committed is True
|
||||||
assert not any(args and args[0] == "push" for args in calls)
|
assert result.pushed is True
|
||||||
|
assert result.origin_sha
|
||||||
|
remote_head = subprocess.run(
|
||||||
|
["git", "-C", str(tmp_path / "origin.git"), "rev-parse", "HEAD"],
|
||||||
|
check=True,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
).stdout.strip()
|
||||||
|
assert remote_head == result.origin_sha
|
||||||
|
brief = repo / "briefs" / "2026" / "09" / "2026-09-13.md"
|
||||||
|
assert brief.is_file()
|
||||||
|
|
||||||
|
|
||||||
|
def test_fi_brief_push_failure_is_not_a_completed_day(
|
||||||
|
tmp_path: Path, monkeypatch
|
||||||
|
) -> None:
|
||||||
|
repo = _repo(tmp_path)
|
||||||
|
posted: list[dict] = []
|
||||||
|
|
||||||
|
def fake_post(**kwargs):
|
||||||
|
posted.append(kwargs)
|
||||||
|
|
||||||
|
monkeypatch.setattr(fi_research_brief.hub, "post_progress_event", fake_post)
|
||||||
|
result = fi_research_brief.run_fi_research_brief(
|
||||||
|
repo,
|
||||||
|
day=date(2026, 9, 13),
|
||||||
|
report_to_hub=True,
|
||||||
|
complete_fn=_complete,
|
||||||
|
)
|
||||||
|
assert result.ok is False
|
||||||
|
assert result.committed is True
|
||||||
|
assert result.pushed is False
|
||||||
|
assert "origin publish failed" in result.reason
|
||||||
|
assert posted
|
||||||
|
assert posted[-1]["event_type"] == "executor_run"
|
||||||
|
assert posted[-1]["detail"]["pushed"] is False
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue