FI-WP-0005 T01-T03: owner declaration, publication decision, egress hosts.
- Owner declaration for the profiled fi-daily-research-brief (proposed): inputs, single-commit briefs/** grant, fast-forward-only publication, quality rules, model requirements without env selection, completion evidence and rollback pins. - Decision: origin publication is a typed grant on the run, not an executor default. - docs/sources-egress.yaml: 17 exact host:443 entries for the sandbox, tested for sand-boxer format and drift against the prose allowlist. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 51320@bnt-lap001 Assistant-Session: 9d40b4c7-8e3c-42ee-b755-d658d4640d6c
This commit is contained in:
parent
7009521fdc
commit
5c5c298643
8 changed files with 396 additions and 4 deletions
113
activity-definitions/fi-daily-research-brief.declaration.yaml
Normal file
113
activity-definitions/fi-daily-research-brief.declaration.yaml
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
# Owner declaration — fi-daily-research-brief (FI-WP-0005-T01)
|
||||||
|
#
|
||||||
|
# Answers rein-aharness d0b45acb / REINAH-WP-0003-T04: the owner-approved
|
||||||
|
# replacement for the profile-absent `fi-research-brief` route. This file is
|
||||||
|
# FI's authority over WHAT runs and under WHICH grant. It does not schedule
|
||||||
|
# (activity-core), pick a rein/sandbox/model (glas-harness) or execute
|
||||||
|
# (rein-aharness). Where another layer has not shipped the needed piece yet,
|
||||||
|
# the field names the FI-WP-0005 task that tracks it.
|
||||||
|
declaration_version: "1"
|
||||||
|
definition_id: fi-daily-research-brief
|
||||||
|
owner: freedom-intelligence
|
||||||
|
approved_by: Bernd Worsch
|
||||||
|
approved_at: "2026-09-22"
|
||||||
|
status: proposed # -> active at FI-WP-0005-T08 cutover
|
||||||
|
|
||||||
|
execution:
|
||||||
|
shape: agent # operator decision 2026-09-22 (option B)
|
||||||
|
harness_profile_ref: harness.fi-research-brief@1.0.0 # requested, FI-WP-0005-T05; not yet in the Glas catalog
|
||||||
|
selection: harness_profile_ref only. No label or approach_hint routing, no
|
||||||
|
fallback to the compatibility executor once cut over.
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
# Read from the checked-out workspace at the run's base commit.
|
||||||
|
brief_date:
|
||||||
|
type: date
|
||||||
|
tz: Europe/Berlin
|
||||||
|
source: activity-core due item (context.item.date)
|
||||||
|
repository_files:
|
||||||
|
- docs/sources-allowlist.md
|
||||||
|
- docs/daily-brief-playbook.md
|
||||||
|
- briefs/_template.md
|
||||||
|
- inventory/RESERVE-STATUS.md
|
||||||
|
- research/2026-07-24-baseline-field-survey.md
|
||||||
|
- research/2026-07-24-nas-strategic-collection-plan.md
|
||||||
|
repository_globs:
|
||||||
|
- inventory/catalog/*.yaml # authority for sizes, licenses, collection status
|
||||||
|
prior_briefs:
|
||||||
|
names: last 5 by date, excluding brief_date
|
||||||
|
full_text: most recent 1
|
||||||
|
git_log: last 12 commits, oneline
|
||||||
|
network:
|
||||||
|
egress_hosts: docs/sources-egress.yaml # FI-WP-0005-T03; model route is profile-owned
|
||||||
|
secrets: none. The run reads no FI credential. Model credentials stay with
|
||||||
|
the profile's owner route (Glas / sand-boxer).
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
artifact: briefs/{yyyy}/{mm}/{date}.md
|
||||||
|
format: briefs/_template.md, axes A–D, collection-candidate section
|
||||||
|
exactly_one_new_file: true
|
||||||
|
must_not_modify_existing_files: true
|
||||||
|
|
||||||
|
repository_grant:
|
||||||
|
# Grant v1 fields (activity-core RepositoryGrant). v1 rejects publish=true,
|
||||||
|
# so publication rides on grant v2 (FI-WP-0005-T04).
|
||||||
|
version: "2" # requested; v1 shape below validated against activity-core b63131e+
|
||||||
|
allowed_paths:
|
||||||
|
- briefs/**
|
||||||
|
commit_count: {min: 1, max: 1}
|
||||||
|
publication:
|
||||||
|
remote: origin
|
||||||
|
ref: main
|
||||||
|
mode: fast-forward-only
|
||||||
|
decision: docs/decisions/2026-09-22-brief-origin-publication.md
|
||||||
|
commit_message: "FI daily research brief {date}"
|
||||||
|
|
||||||
|
quality_rules:
|
||||||
|
# Acceptance for canary comparison (FI-WP-0005-T07) and prompt contract.
|
||||||
|
- inventory/catalog is the authority. Do not re-announce cataloged models
|
||||||
|
as new, and never state sizes or licenses that contradict the catalog.
|
||||||
|
- Every parameter count, size, price or benchmark claim cites a primary
|
||||||
|
source that was fetched in this run. If it is not verifiable, say so
|
||||||
|
instead of estimating.
|
||||||
|
- Deltas only, measured against prior briefs and the baseline, not a resurvey.
|
||||||
|
- Cover axes A–D, or state explicitly that an axis had no delta.
|
||||||
|
- Rumor (social media, unsourced aggregators) is not reported as confirmed.
|
||||||
|
- No credentials, customer data or model weights in the brief.
|
||||||
|
|
||||||
|
model:
|
||||||
|
# FI states requirements; the Glas profile pins provider/model/route.
|
||||||
|
model_class: frontier
|
||||||
|
required_capabilities: [tool_use, web_fetch_via_https_proxy, long_context]
|
||||||
|
limits_hint: {timeout_seconds: 1800, max_turns: 60}
|
||||||
|
constraints:
|
||||||
|
- No Binky-named variables (BRIEF_DAILY_MODEL, MAIL_TRIAGE_MODEL) and no
|
||||||
|
process-environment model selection. The profile version is the only selector.
|
||||||
|
- The playbook rule "no Claude Code / Codex on railiance01" means no
|
||||||
|
host-installed agent. A pinned agent executable inside the Glas sandbox is
|
||||||
|
acceptable only if the profile owner confirms it is not a host
|
||||||
|
installation. Operator to confirm (FI-WP-0005-T05).
|
||||||
|
|
||||||
|
completion:
|
||||||
|
event: fi_daily_brief
|
||||||
|
required_detail:
|
||||||
|
date: brief_date
|
||||||
|
path: outputs.artifact
|
||||||
|
pushed: true
|
||||||
|
origin_sha: 40-hex commit on origin/main that contains the artifact
|
||||||
|
harness_profile_ref: execution.harness_profile_ref
|
||||||
|
due_resolution: published-artifact resolver (FI-WP-0005-T04). The day
|
||||||
|
clears only if the artifact is on origin/main AND the event says
|
||||||
|
pushed=true. In the interim, fi_brief_status (activity-core 289aff3), same semantics.
|
||||||
|
on_failure: executor_run ok=false, no fi_daily_brief, day stays due.
|
||||||
|
independent_audit: scripts/verify_brief_durability.py --require-date {date}
|
||||||
|
|
||||||
|
rollback:
|
||||||
|
pins:
|
||||||
|
- glas profile version (previous harness.fi-research-brief@x.y.z)
|
||||||
|
- this declaration and the definition, by git revision in this repo
|
||||||
|
procedure: pin the previous profile version or revert the definition
|
||||||
|
revision, then sync activity-core definitions. Until the legacy expiry
|
||||||
|
(2026-12-31) the compatibility executor rein-aharness@11020e8 remains a
|
||||||
|
manual one-shot recovery. There is no host timer (FI-WP-0005-T06).
|
||||||
|
evidence_required: one exercised rollback at cutover (FI-WP-0005-T08)
|
||||||
|
|
@ -65,5 +65,9 @@ action:
|
||||||
5. [x] Executor: `rein-aharness fi-research-brief` + `scripts/railiance-rhythm/`
|
5. [x] Executor: `rein-aharness fi-research-brief` + `scripts/railiance-rhythm/`
|
||||||
(install on railiance01; not workstation cron)
|
(install on railiance01; not workstation cron)
|
||||||
|
|
||||||
|
Migration (FI-WP-0005): the owner declaration for the profiled replacement is
|
||||||
|
`fi-daily-research-brief.declaration.yaml` (status `proposed`). This definition
|
||||||
|
stays on the compatibility route until the T08 cutover.
|
||||||
|
|
||||||
Layers: activity-core (when/what/where) → rein-aharness (execute) → this repo.
|
Layers: activity-core (when/what/where) → rein-aharness (execute) → this repo.
|
||||||
See `docs/recurrence-ops.md` and `activity-core/docs/recurring-automations-playbook.md`.
|
See `docs/recurrence-ops.md` and `activity-core/docs/recurring-automations-playbook.md`.
|
||||||
|
|
|
||||||
60
docs/decisions/2026-09-22-brief-origin-publication.md
Normal file
60
docs/decisions/2026-09-22-brief-origin-publication.md
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
# Decision: Origin publication of daily briefs is an explicit, typed grant
|
||||||
|
|
||||||
|
**Date:** 2026-09-22
|
||||||
|
**Status:** accepted
|
||||||
|
**Decided by:** Bernd Worsch (operator), FI owner
|
||||||
|
**Affects:** `activity-definitions/fi-daily-research-brief.md`,
|
||||||
|
`activity-definitions/fi-daily-research-brief.declaration.yaml`, FI-WP-0005
|
||||||
|
**Supersedes:** the grant wording in FI-WP-0004-T04, which granted "origin
|
||||||
|
publication as a named capability of `fi-research-brief`". That capability
|
||||||
|
lived inside one rein command. This decision moves it to the queued run's
|
||||||
|
repository grant.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
A brief day counts only when the brief is on `origin/main` (FI-WP-0004). The
|
||||||
|
executor therefore has to push. rein-aharness (`d0b45acb`, REINAH-WP-0003-T04)
|
||||||
|
requires that publication be a separate, owner-approved decision, not a
|
||||||
|
default of the executor. activity-core repository-grant v1 is local-only and
|
||||||
|
rejects `publish: true`.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
1. **FI grants publication, scoped exactly:**
|
||||||
|
- remote `origin`, ref `main`
|
||||||
|
- mode **fast-forward only**: no force push, no other refs, no tags
|
||||||
|
- only commits whose changes stay within `briefs/**`
|
||||||
|
- at most one commit per run
|
||||||
|
2. **The grant rides on the run, not the executor.** It is carried as
|
||||||
|
activity-core repository-grant v2 `publication` (requested in FI-WP-0005-T04).
|
||||||
|
No rein, profile or tool may publish FI content without that grant on the
|
||||||
|
claimed `ops_run`.
|
||||||
|
3. **Failure semantics:**
|
||||||
|
- Push rejected or failed: the run fails, no `fi_daily_brief` is posted,
|
||||||
|
and the day stays due.
|
||||||
|
- Non-fast-forward (origin moved): the executor may rebase its single
|
||||||
|
brief commit onto the new origin head once, then retry. A second failure
|
||||||
|
is a failed run. It never merges and never forces.
|
||||||
|
- Success requires `origin_sha` evidence, and activity-core close
|
||||||
|
reconciliation checks it against the grant.
|
||||||
|
4. **Until grant v2 is live**, the compatibility path (`rein-aharness
|
||||||
|
fi-research-brief`, commit `11020e8`) continues under FI-WP-0004-T04 semantics.
|
||||||
|
It ends at cutover (FI-WP-0005-T08) or at the legacy expiry, whichever
|
||||||
|
comes first.
|
||||||
|
|
||||||
|
## Not granted
|
||||||
|
|
||||||
|
- Writes outside `briefs/**`. The catalog, inventory, workplans and docs stay
|
||||||
|
human- or workplan-driven.
|
||||||
|
- Publication to any other remote or mirror.
|
||||||
|
- Opening PRs or issues, or posting to other external systems.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
- activity-core needs grant v2 and origin-SHA close evidence (FI-WP-0005-T04).
|
||||||
|
- The Glas tool profile must be able to push, but only under a grant
|
||||||
|
(FI-WP-0005-T05).
|
||||||
|
- `scripts/verify_brief_durability.py` remains the independent audit of the
|
||||||
|
result.
|
||||||
|
|
@ -3,6 +3,11 @@
|
||||||
Standing channels for Freedom Intelligence briefs (axes A–D). Prefer **primary**
|
Standing channels for Freedom Intelligence briefs (axes A–D). Prefer **primary**
|
||||||
sources over aggregators. This is a watchlist, not a scrape mandate.
|
sources over aggregators. This is a watchlist, not a scrape mandate.
|
||||||
|
|
||||||
|
Automated runs reach the network only through the hosts in
|
||||||
|
[`sources-egress.yaml`](sources-egress.yaml) (FI-WP-0005-T03). Adding a
|
||||||
|
channel here that needs a new host means adding that host there too;
|
||||||
|
`scripts/test_sources_egress.py` checks the two stay in step.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Axis A — Frontier & commercial
|
## Axis A — Frontier & commercial
|
||||||
|
|
|
||||||
99
docs/sources-egress.yaml
Normal file
99
docs/sources-egress.yaml
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
# Network egress for the daily research brief sandbox (FI-WP-0005-T03).
|
||||||
|
#
|
||||||
|
# Machine-readable companion to docs/sources-allowlist.md. The Glas profile
|
||||||
|
# for fi-daily-research-brief declares exactly these hosts in
|
||||||
|
# network.egress (default: deny). The model provider route is NOT listed
|
||||||
|
# here; it belongs to the profile (glas-harness), not to FI.
|
||||||
|
#
|
||||||
|
# sand-boxer rules (docs/bwrap-egress.md): exact lowercase DNS names, port 443
|
||||||
|
# only, no wildcards, no IP literals. Enforcement is by destination, not by
|
||||||
|
# path: every host below is a whole-host trust decision. Keep the list minimal.
|
||||||
|
#
|
||||||
|
# `channel` must appear verbatim in docs/sources-allowlist.md
|
||||||
|
# (scripts/test_sources_egress.py enforces this so the two cannot drift).
|
||||||
|
version: 1
|
||||||
|
hosts:
|
||||||
|
# Axis A — frontier & commercial
|
||||||
|
- host: openai.com:443
|
||||||
|
axes: [A]
|
||||||
|
channel: OpenAI / Anthropic / Google / xAI / DeepSeek blogs & release notes
|
||||||
|
why: Release notes, model pages, API pricing. Returned 403 to a plain
|
||||||
|
client on 2026-09-22 (bot protection); may be unreadable unattended.
|
||||||
|
- host: www.anthropic.com:443
|
||||||
|
axes: [A]
|
||||||
|
channel: OpenAI / Anthropic / Google / xAI / DeepSeek blogs & release notes
|
||||||
|
why: News and model announcements (apex redirects here).
|
||||||
|
- host: platform.claude.com:443
|
||||||
|
axes: [A]
|
||||||
|
channel: Model cards for API models
|
||||||
|
why: Model overview, context limits, pricing tables (docs.anthropic.com
|
||||||
|
now 301-redirects here, 2026-09-22).
|
||||||
|
- host: blog.google:443
|
||||||
|
axes: [A]
|
||||||
|
channel: OpenAI / Anthropic / Google / xAI / DeepSeek blogs & release notes
|
||||||
|
why: Gemini release announcements.
|
||||||
|
- host: ai.google.dev:443
|
||||||
|
axes: [A]
|
||||||
|
channel: Official pricing pages
|
||||||
|
why: Gemini API models and pricing.
|
||||||
|
- host: x.ai:443
|
||||||
|
axes: [A]
|
||||||
|
channel: OpenAI / Anthropic / Google / xAI / DeepSeek blogs & release notes
|
||||||
|
why: Grok release notes. Returned 403 to a plain client on 2026-09-22.
|
||||||
|
- host: api-docs.deepseek.com:443
|
||||||
|
axes: [A, B]
|
||||||
|
channel: OpenAI / Anthropic / Google / xAI / DeepSeek blogs & release notes
|
||||||
|
why: DeepSeek news, API pricing and model list.
|
||||||
|
- host: arena.ai:443
|
||||||
|
axes: [A]
|
||||||
|
channel: LMSYS / Arena / artificialanalysis-class charts
|
||||||
|
why: Directional leaderboard only; note gaming risk (lmarena.ai
|
||||||
|
301-redirects here, 2026-09-22).
|
||||||
|
- host: artificialanalysis.ai:443
|
||||||
|
axes: [A]
|
||||||
|
channel: LMSYS / Arena / artificialanalysis-class charts
|
||||||
|
why: Price/performance charts, directional.
|
||||||
|
- host: www.swebench.com:443
|
||||||
|
axes: [A, D]
|
||||||
|
channel: SWE-bench Verified / Live leaderboards
|
||||||
|
why: Harness+model pairs.
|
||||||
|
# Axis B — edge / local / open
|
||||||
|
- host: huggingface.co:443
|
||||||
|
axes: [B, C]
|
||||||
|
channel: Hugging Face org feeds
|
||||||
|
why: Model cards, licenses, sizes via /api/models. No weight download
|
||||||
|
(weight CDN hosts are deliberately absent).
|
||||||
|
- host: ollama.com:443
|
||||||
|
axes: [B]
|
||||||
|
channel: llama.cpp, vLLM, MLX, Ollama release notes
|
||||||
|
why: Ollama library and release notes.
|
||||||
|
# Axes B/C/D — GitHub-hosted releases (llama.cpp, vLLM, MLX, Unsloth, TRL,
|
||||||
|
# OpenHands, Aider, SWE-agent, OpenCode, Cline, ...)
|
||||||
|
- host: github.com:443
|
||||||
|
axes: [B, C, D]
|
||||||
|
channel: OpenHands, Aider, SWE-agent, OpenCode, Cline repos/releases
|
||||||
|
why: Release pages for runtimes, training tools and harnesses.
|
||||||
|
- host: api.github.com:443
|
||||||
|
axes: [B, C, D]
|
||||||
|
channel: llama.cpp, vLLM, MLX, Ollama release notes
|
||||||
|
why: Structured release listing instead of scraping HTML.
|
||||||
|
# Axis C — training & specialization
|
||||||
|
- host: arxiv.org:443
|
||||||
|
axes: [C]
|
||||||
|
channel: arXiv cs.LG, cs.CL, cs.AI (recent)
|
||||||
|
why: Abstracts and listings.
|
||||||
|
- host: export.arxiv.org:443
|
||||||
|
axes: [C]
|
||||||
|
channel: arXiv cs.LG, cs.CL, cs.AI (recent)
|
||||||
|
why: arXiv query API (the sanctioned programmatic endpoint).
|
||||||
|
# Axis D — harness & fleet
|
||||||
|
- host: modelcontextprotocol.io:443
|
||||||
|
axes: [D]
|
||||||
|
channel: MCP / tool-protocol standards
|
||||||
|
why: MCP specification and changelog.
|
||||||
|
# Deliberately absent:
|
||||||
|
# - Model provider API hosts (profile-owned route).
|
||||||
|
# - Hugging Face / GitHub content CDNs (no weight or asset download in briefs).
|
||||||
|
# - Social media / X (allowlist: rumor is not confirmation).
|
||||||
|
# - Internal Coulomb repos (sand-boxer, activity-core): read from the
|
||||||
|
# checked-out workspace or hub, not over the network.
|
||||||
42
scripts/test_declaration.py
Normal file
42
scripts/test_declaration.py
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
"""The fi-daily-research-brief owner declaration parses and its references resolve."""
|
||||||
|
from pathlib import Path
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parent.parent
|
||||||
|
DECLARATION = ROOT / 'activity-definitions' / 'fi-daily-research-brief.declaration.yaml'
|
||||||
|
|
||||||
|
|
||||||
|
class DeclarationTests(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.doc = yaml.safe_load(DECLARATION.read_text(encoding='utf-8'))
|
||||||
|
|
||||||
|
def test_referenced_files_exist(self):
|
||||||
|
inputs = self.doc['inputs']
|
||||||
|
paths = list(inputs['repository_files'])
|
||||||
|
paths.append(inputs['network']['egress_hosts'])
|
||||||
|
paths.append(self.doc['repository_grant']['publication']['decision'])
|
||||||
|
for rel in paths:
|
||||||
|
self.assertTrue((ROOT / rel).is_file(), rel)
|
||||||
|
|
||||||
|
def test_grant_is_single_commit_within_briefs(self):
|
||||||
|
grant = self.doc['repository_grant']
|
||||||
|
self.assertEqual(grant['allowed_paths'], ['briefs/**'])
|
||||||
|
self.assertEqual(grant['commit_count'], {'min': 1, 'max': 1})
|
||||||
|
self.assertEqual(grant['publication'],
|
||||||
|
{'remote': 'origin', 'ref': 'main', 'mode': 'fast-forward-only',
|
||||||
|
'decision': grant['publication']['decision']})
|
||||||
|
|
||||||
|
def test_completion_requires_published_evidence(self):
|
||||||
|
detail = self.doc['completion']['required_detail']
|
||||||
|
self.assertIs(detail['pushed'], True)
|
||||||
|
self.assertIn('origin_sha', detail)
|
||||||
|
|
||||||
|
def test_no_environment_model_selection(self):
|
||||||
|
self.assertNotIn('env', self.doc['model'])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
51
scripts/test_sources_egress.py
Normal file
51
scripts/test_sources_egress.py
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
"""docs/sources-egress.yaml stays valid for sand-boxer and in step with the prose allowlist."""
|
||||||
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parent.parent
|
||||||
|
EGRESS = ROOT / 'docs' / 'sources-egress.yaml'
|
||||||
|
ALLOWLIST = ROOT / 'docs' / 'sources-allowlist.md'
|
||||||
|
# sand-boxer bwrap-egress: exact lowercase DNS name, port 443, no wildcard or IP literal.
|
||||||
|
HOST = re.compile(r'^(?=.{1,253}:443$)([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}:443$')
|
||||||
|
MAX_HOSTS = 24 # every host is a whole-host trust decision; raise only deliberately
|
||||||
|
|
||||||
|
|
||||||
|
class SourcesEgressTests(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.doc = yaml.safe_load(EGRESS.read_text(encoding='utf-8'))
|
||||||
|
cls.hosts = cls.doc['hosts']
|
||||||
|
cls.prose = ALLOWLIST.read_text(encoding='utf-8')
|
||||||
|
|
||||||
|
def test_version(self):
|
||||||
|
self.assertEqual(self.doc['version'], 1)
|
||||||
|
|
||||||
|
def test_host_format(self):
|
||||||
|
for entry in self.hosts:
|
||||||
|
self.assertRegex(entry['host'], HOST)
|
||||||
|
|
||||||
|
def test_no_duplicates_and_bounded(self):
|
||||||
|
names = [e['host'] for e in self.hosts]
|
||||||
|
self.assertEqual(len(names), len(set(names)))
|
||||||
|
self.assertLessEqual(len(names), MAX_HOSTS)
|
||||||
|
|
||||||
|
def test_entries_complete(self):
|
||||||
|
for entry in self.hosts:
|
||||||
|
self.assertEqual(set(entry), {'host', 'axes', 'channel', 'why'}, entry['host'])
|
||||||
|
self.assertTrue(entry['why'].strip(), entry['host'])
|
||||||
|
self.assertTrue(set(entry['axes']) <= set('ABCD'), entry['host'])
|
||||||
|
|
||||||
|
def test_every_axis_covered(self):
|
||||||
|
covered = {axis for e in self.hosts for axis in e['axes']}
|
||||||
|
self.assertEqual(covered, set('ABCD'))
|
||||||
|
|
||||||
|
def test_channel_named_in_prose_allowlist(self):
|
||||||
|
for entry in self.hosts:
|
||||||
|
self.assertIn(entry['channel'], self.prose, entry['host'])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
|
|
@ -70,7 +70,7 @@ network egress beyond a model provider.
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: FI-WP-0005-T01
|
id: FI-WP-0005-T01
|
||||||
status: todo
|
status: done
|
||||||
priority: high
|
priority: high
|
||||||
state_hub_task_id: "bf8c1870-bdca-51d6-beaf-c5f000037205"
|
state_hub_task_id: "bf8c1870-bdca-51d6-beaf-c5f000037205"
|
||||||
```
|
```
|
||||||
|
|
@ -86,27 +86,39 @@ publication policy (reference T02), and rollback. No Binky-named env vars.
|
||||||
**Done when:** the declaration is committed, and every field rein listed in
|
**Done when:** the declaration is committed, and every field rein listed in
|
||||||
`d0b45acb` maps to a concrete value or to a named follow-up task here.
|
`d0b45acb` maps to a concrete value or to a named follow-up task here.
|
||||||
|
|
||||||
|
**2026-09-22:** Done. `activity-definitions/fi-daily-research-brief.declaration.yaml`
|
||||||
|
(status `proposed`). It covers profile ref (pending T05), inputs, outputs, grant
|
||||||
|
(its v1 fields validate against activity-core `RepositoryGrant`; publication pending
|
||||||
|
T04), quality rules, model requirements without env selection, completion
|
||||||
|
evidence and rollback pins. `scripts/test_declaration.py` checks it. Open
|
||||||
|
operator question: whether a pinned agent executable inside the Glas sandbox
|
||||||
|
satisfies the playbook's "no Claude Code / Codex on railiance01" rule.
|
||||||
|
|
||||||
### T02 — Publication decision record
|
### T02 — Publication decision record
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: FI-WP-0005-T02
|
id: FI-WP-0005-T02
|
||||||
status: todo
|
status: done
|
||||||
priority: high
|
priority: high
|
||||||
state_hub_task_id: "25475ede-ebd9-5c31-8c22-718e30acf8ac"
|
state_hub_task_id: "25475ede-ebd9-5c31-8c22-718e30acf8ac"
|
||||||
```
|
```
|
||||||
|
|
||||||
`docs/decisions/2026-09-XX-brief-origin-publication.md`: FI grants
|
`docs/decisions/2026-09-22-brief-origin-publication.md`: FI grants
|
||||||
fast-forward-only publication of `briefs/**` to `origin/main`; no force, no
|
fast-forward-only publication of `briefs/**` to `origin/main`; no force, no
|
||||||
other refs; publication failure fails the run and leaves the day due. Supersedes
|
other refs; publication failure fails the run and leaves the day due. Supersedes
|
||||||
the implicit grant wording in FI-WP-0004-T04.
|
the implicit grant wording in FI-WP-0004-T04.
|
||||||
|
|
||||||
**Done when:** the decision is committed and cited by T01 and T04.
|
**Done when:** the decision is committed and cited by T01 and T04.
|
||||||
|
|
||||||
|
**2026-09-22:** Done. Adds a single rebase-and-retry on non-fast-forward;
|
||||||
|
it never merges or forces. Cited by the declaration and the activity-core
|
||||||
|
proposal `8ee9a6ab`.
|
||||||
|
|
||||||
### T03 — Machine-readable source host list
|
### T03 — Machine-readable source host list
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: FI-WP-0005-T03
|
id: FI-WP-0005-T03
|
||||||
status: todo
|
status: done
|
||||||
priority: high
|
priority: high
|
||||||
state_hub_task_id: "9b92d7f4-f4c8-5ce5-9367-462653515e90"
|
state_hub_task_id: "9b92d7f4-f4c8-5ce5-9367-462653515e90"
|
||||||
```
|
```
|
||||||
|
|
@ -120,6 +132,12 @@ path, so every host is a trust decision.
|
||||||
**Done when:** the list is committed with a test, and the host count and the
|
**Done when:** the list is committed with a test, and the host count and the
|
||||||
rationale for each host are recorded.
|
rationale for each host are recorded.
|
||||||
|
|
||||||
|
**2026-09-22:** Done. `docs/sources-egress.yaml` has 17 hosts covering axes A–D.
|
||||||
|
`scripts/test_sources_egress.py` checks sand-boxer format, the 24-host cap and
|
||||||
|
that each channel is named in the prose allowlist. A live check replaced
|
||||||
|
redirecting hosts (docs.anthropic.com → platform.claude.com, lmarena.ai →
|
||||||
|
arena.ai). openai.com and x.ai return 403 to plain clients, which is noted.
|
||||||
|
|
||||||
### T04 — activity-core handoff: grant v2 publication + generic due resolver
|
### T04 — activity-core handoff: grant v2 publication + generic due resolver
|
||||||
|
|
||||||
```task
|
```task
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue