FI-WP-0005-T06: retire the break-glass host timer.

Removes scripts/railiance-rhythm (units, installer, runner); the host
units were uninstalled from railiance01. Docs now name the claim loop as
the only scheduled executor, a manual one-shot for recovery until the
legacy expiry, and profile-pin rollback after cutover.

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:
tegwick 2026-09-22 16:19:48 +02:00
parent 7145fbc997
commit d96abacb1c
9 changed files with 31 additions and 164 deletions

View file

@ -62,8 +62,8 @@ action:
2. [x] ConfigMap projection + Temporal schedule (weekdays 07:30 Europe/Berlin)
3. [x] Completion event `fi_daily_brief` proven
4. [x] `enabled: true` / `status: active`
5. [x] Executor: `rein-aharness fi-research-brief` + `scripts/railiance-rhythm/`
(install on railiance01; not workstation cron)
5. [x] Executor: `rein-aharness fi-research-brief` via the rein-aharness claim
loop on railiance01 (host timer removed 2026-09-22, FI-WP-0005-T06)
Migration (FI-WP-0005): the owner declaration for the profiled replacement is
`fi-daily-research-brief.declaration.yaml` (status `proposed`). This definition

View file

@ -92,7 +92,7 @@ full resurveys.
When activity-core emits `activity_task_spawn` with
`target_repo: freedom-intelligence` and labels including `research-brief`:
1. Railiance host timer (or manual) runs
1. rein-aharness claim loop on railiance01 claims the `ops_run` and runs
`rein-aharness fi-research-brief --target-repo ~/freedom-intelligence`
2. llm-connect drafts the brief; harness **commits, pushes to origin**, then
posts **`fi_daily_brief`** with `pushed=true`
@ -105,7 +105,7 @@ Do **not** install Claude Code / Codex on railiance01 for this rhythm.
| ----- | -------- |
| Definition | `activity-definitions/fi-daily-research-brief.md` |
| Ops | `docs/recurrence-ops.md` |
| Executor install | `scripts/railiance-rhythm/install-on-railiance.sh` |
| Executor | rein-aharness claim loop; manual recovery in `docs/recurrence-ops.md` |
| Workplan | FI-WP-0002 (finished) |
| Resolver | `fi_brief_status` in activity-core |

View file

@ -18,7 +18,7 @@ activity-core (when / what / where)
rein-aharness on railiance01 (does the work)
primary: claim-loop → ops_run → fi-research-brief (REIN-A-0002)
break-glass only: host timer 07:35 (disabled 2026-08-05; re-enable if claim loop down)
no host timer (removed 2026-09-22, FI-WP-0005-T06); recovery = manual one-shot below
llm-connect drafts brief → commit → git push origin → fi_daily_brief
(fi_daily_brief is forbidden until origin has the file)
@ -47,7 +47,7 @@ freedom-intelligence repo
| Sink | `ISSUE_SINK_TYPE=state-hub``activity_task_spawn` |
| Executor | `rein-aharness fi-research-brief` |
| Claim loop | `rein-aharness claim-loop` (ops_run; REIN-A-0002) |
| Host timer | `scripts/railiance-rhythm/` (**break-glass** after T05 proof) |
| Host timer | none (removed 2026-09-22, FI-WP-0005-T06) |
---
@ -76,19 +76,24 @@ After definition edits:
---
## Install executor on railiance01
## Recovery: manual one-shot (until 2026-12-31)
There is no host timer. The claim loop is the only scheduled executor. If it
is down and a day must be produced, run the compatibility command once on
railiance01. The launcher loads `claim-loop.env` and resolves the llm-connect
and hub URLs:
```bash
# On railiance01
git clone forgejo-remote:coulomb/freedom-intelligence.git ~/freedom-intelligence
cd ~/freedom-intelligence && ./scripts/railiance-rhythm/install-on-railiance.sh
# rein-aharness must expose fi-research-brief (deploy/pull rein-aharness)
# Logs: ~/.cache/freedom-intelligence/rhythm/
cd ~/freedom-intelligence && git pull --ff-only
~/bin/rein-aharness-claim fi-research-brief \
--target-repo ~/freedom-intelligence --date YYYY-MM-DD
```
Timer is **07:35** Berlin — five minutes after activity-cores 07:30 schedule
(**break-glass** once claim-loop is proven).
This path ends at the FI-WP-0005 cutover or the legacy expiry (2026-12-31),
whichever comes first. After cutover, rollback means pinning the previous
Glas profile version or reverting the definition revision
(`activity-definitions/fi-daily-research-brief.declaration.yaml`), not
re-installing a timer.
### Preferred: claim-loop (REIN-A-0002)

View file

@ -1,23 +0,0 @@
#!/usr/bin/env bash
# Install host-side FI research brief timer on railiance01 (user systemd).
# Run ON railiance01 from a freedom-intelligence checkout:
# ./scripts/railiance-rhythm/install-on-railiance.sh
#
# Prerequisites:
# - activity-core definition fi-daily-research-brief enabled (cluster)
# - rein-aharness installed with fi-research-brief command
# - freedom-intelligence clone with write access for brief commits
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
UNIT_DIR="${HOME}/.config/systemd/user"
mkdir -p "${UNIT_DIR}"
chmod +x "${ROOT}/scripts/railiance-rhythm/"*.sh
cp -f "${ROOT}/scripts/railiance-rhythm/systemd/fi-research-brief-daily.service" "${UNIT_DIR}/"
cp -f "${ROOT}/scripts/railiance-rhythm/systemd/fi-research-brief-daily.timer" "${UNIT_DIR}/"
systemctl --user daemon-reload
systemctl --user enable --now fi-research-brief-daily.timer
systemctl --user list-timers --all | grep fi-research || true
echo "Installed. Logs: ~/.cache/freedom-intelligence/rhythm/"
echo "Cadence truth: activity-core (07:30). Executor: this timer (07:35) → rein-aharness."

View file

@ -1,86 +0,0 @@
#!/usr/bin/env bash
# Shared env for Railiance host-side Freedom Intelligence research brief.
#
# activity-core owns cadence (Temporal + fi_brief_status + activity_task_spawn).
# This host timer is the *executor* path (same pattern as binky-control):
# rein-aharness consumes the work and posts fi_daily_brief.
#
# ISSUE_SINK_TYPE=state-hub writes progress only (not claimable issues), so a
# host timer remains the interim executor until rein-aharness poll/claim of
# activity_task_spawn is fully wired. Cadence truth still lives in activity-core.
set -euo pipefail
: "${HOME:=/home/tegwick}"
# Prefer rein-aharness venv (current name); fall back to legacy agent-harness path.
if [[ -x "${HOME}/.local/rein-aharness/venv/bin/rein-aharness" ]]; then
export PATH="${HOME}/.local/rein-aharness/venv/bin:${HOME}/.local/bin:${PATH}"
# shellcheck disable=SC1091
[[ -f "${HOME}/.local/rein-aharness/env" ]] && source "${HOME}/.local/rein-aharness/env"
elif [[ -x "${HOME}/.local/agent-harness/venv/bin/rein-aharness" ]]; then
export PATH="${HOME}/.local/agent-harness/venv/bin:${HOME}/.local/bin:${PATH}"
# shellcheck disable=SC1091
[[ -f "${HOME}/.local/agent-harness/env" ]] && source "${HOME}/.local/agent-harness/env"
else
export PATH="${HOME}/.local/bin:${PATH}"
fi
export STATE_HUB_URL="${STATE_HUB_URL:-http://127.0.0.1:18000}"
export PYTHONPATH="${HOME}/rein-aharness:${HOME}/llm-connect${PYTHONPATH:+:$PYTHONPATH}"
export FI_REPO="${FI_REPO:-${HOME}/freedom-intelligence}"
export LOG_DIR="${LOG_DIR:-${HOME}/.cache/freedom-intelligence/rhythm}"
mkdir -p "${LOG_DIR}"
log() { echo "$(date -Iseconds) $*" | tee -a "${LOG_DIR}/railiance-rhythm.log"; }
require_repo() {
if [[ ! -d "${FI_REPO}/.git" ]]; then
log "ERROR: freedom-intelligence missing at ${FI_REPO}; clone with deploy key"
exit 1
fi
git -C "${FI_REPO}" fetch --quiet origin main || true
git -C "${FI_REPO}" checkout --quiet main
git -C "${FI_REPO}" pull --ff-only --quiet origin main || log "WARN: pull failed (continuing on local)"
}
require_llm_connect() {
if [[ -z "${LLM_CONNECT_URL:-}" ]]; then
local candidates=()
candidates+=("http://127.0.0.1:18080")
if command -v kubectl >/dev/null 2>&1; then
local cip
cip="$(kubectl -n activity-core get svc llm-connect \
-o jsonpath='{.spec.clusterIP}' 2>/dev/null || true)"
if [[ -n "${cip}" ]]; then
candidates+=("http://${cip}:8080")
fi
fi
candidates+=("http://llm-connect.activity-core.svc.cluster.local:8080")
local u
for u in "${candidates[@]}"; do
if curl -sf -m 2 "${u}/health" >/dev/null 2>&1; then
export LLM_CONNECT_URL="${u}"
break
fi
done
if [[ -z "${LLM_CONNECT_URL:-}" ]]; then
export LLM_CONNECT_URL="${candidates[-1]}"
log "WARN: no llm-connect health probe succeeded; using ${LLM_CONNECT_URL}"
fi
fi
log "LLM_CONNECT_URL=${LLM_CONNECT_URL}"
}
ensure_git_identity() {
git -C "${FI_REPO}" config user.email >/dev/null 2>&1 \
|| git -C "${FI_REPO}" config user.email "rein-aharness@railiance.local"
git -C "${FI_REPO}" config user.name >/dev/null 2>&1 \
|| git -C "${FI_REPO}" config user.name "rein-aharness"
}
require_harness() {
if ! command -v rein-aharness >/dev/null 2>&1; then
log "ERROR: rein-aharness not on PATH. Install rein-aharness venv on this host."
exit 2
fi
}

View file

@ -1,17 +0,0 @@
#!/usr/bin/env bash
# Weekday 07:35 Europe/Berlin — FI research brief executor (rein-aharness).
#
# Cadence authority: activity-core definition fi-daily-research-brief
# (Temporal 07:30 Europe/Berlin, fi_brief_status due check, activity_task_spawn).
# This timer is the host executor, 5 minutes after the schedule fire window.
set -euo pipefail
# shellcheck disable=SC1091
source "$(dirname "$0")/run-common.sh"
require_repo
ensure_git_identity
require_harness
require_llm_connect
log "START fi-research-brief (rein-aharness / llm-connect)"
rein-aharness fi-research-brief --target-repo "${FI_REPO}" \
2>&1 | tee -a "${LOG_DIR}/daily.log"
log "END fi-research-brief rc=${PIPESTATUS[0]}"

View file

@ -1,10 +0,0 @@
[Unit]
Description=Freedom Intelligence daily research brief (rein-aharness on Railiance)
After=network-online.target
[Service]
Type=oneshot
Environment=HOME=%h
WorkingDirectory=%h/freedom-intelligence
ExecStart=%h/freedom-intelligence/scripts/railiance-rhythm/run-daily.sh
Nice=10

View file

@ -1,10 +0,0 @@
[Unit]
Description=Timer: FI research brief weekdays 07:35 Europe/Berlin
[Timer]
OnCalendar=Mon..Fri *-*-* 07:35:00 Europe/Berlin
Persistent=true
Unit=fi-research-brief-daily.service
[Install]
WantedBy=timers.target

View file

@ -191,7 +191,7 @@ host-install question. Awaiting reply.
```task
id: FI-WP-0005-T06
status: todo
status: done
priority: medium
state_hub_task_id: "69abf6cf-95af-51b2-8874-120f30cb4b0a"
```
@ -200,8 +200,7 @@ Delete `scripts/railiance-rhythm/systemd/*`, `install-on-railiance.sh` and
`run-daily.sh` (keep `run-common.sh` only if it is still referenced). Replace
`docs/recurrence-ops.md` and playbook references with a manual one-shot
recovery command, valid until the legacy expiry, and the post-cutover
rollback (T08). Confirm the timer is absent on railiance01 (`not-found` on
2026-09-22).
rollback (T08). Remove the timer from railiance01.
Rationale: the timer is a second scheduler outside activity-core. It runs
the profile-absent legacy command with no grant, and its installer runs
@ -213,6 +212,15 @@ brief closes it (FI-WP-0004-T05 precedent).
**Done when:** the files are removed, the docs name the one-shot command and
the profile-pin rollback, and the host has no FI timer.
**2026-09-22:** Done. The earlier "not-found" check used the wrong unit names.
`fi-research-brief-daily.{timer,service}` were installed but disabled and had
never fired (`LastTriggerUSec` empty). They are now removed from
`~/.config/systemd/user` and systemd has been reloaded; no FI brief unit remains. The whole
`scripts/railiance-rhythm/` directory is deleted (`run-common.sh` had no other
caller). `docs/recurrence-ops.md` documents the manual one-shot
(`~/bin/rein-aharness-claim fi-research-brief --target-repo ... --date ...`)
and the post-cutover rollback.
### T07 — Disabled canary definition
```task