Tested rather than relayed: OpenRouter answers 'User not found' for the
delivered key, which means no account resolves it — an existing-account key
reissue, not a new account. Ruled out credits (402), model permissions (403),
provider config, and pod health.
Also records a latent delivery defect: the secret carries a trailing newline,
harmless today only because llm_connect/config.py:53 strips it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
scripts/prod_automation_status.sh took a positional since value, so the
Makefile's own `SINCE=sunday` form passed the literal string into timestamptz:
all five sections errored while the run still looked like it produced a report.
Now `SINCE=` is accepted and the value is parsed and normalised to UTC up
front, failing fast with usage and exit 2 instead of five parse errors.
ACTIVITY-WP-0032 plans adoption of the glas-harness contract 1.0 reported in
GLAS-WP-0004. WP-0026 is finished, so this gets its own plan. The motivation is
concrete: ops_run.approach_hint binds at claim time, which produced a failed
run on 2026-08-17 ("no approach matched labels/definition") after it had
already consumed a claim and a lease.
T01 is deliberately blocking: our claim path is pull-based and the Glas
contract is a call, so the invocation shape is an architectural decision, not a
port. Two questions are outstanding with glas-harness.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
llm-connect maps every provider API error onto HTTP 502 and puts the real
cause in the body (llm_connect/server.py::_error_response: error,
provider_status). LLMConnectClient.complete called raise_for_status() and threw
that body away, so a revoked OpenRouter key was indistinguishable from a downed
gateway — four days of production evidence read as "llm-connect is down".
Live check confirms one fault, not two: the llm-connect pod is Running 1/1 with
healthy endpoints, and today's FI/Binky/triage runs still 502 after yesterday's
rollout, matching the sanitized upstream 401 railiance-platform reported.
The client now raises with error, provider_status, provider, model and a
bounded copy of llm-connect's already-sanitized message, under a field
allowlist so no provider blob or key material reaches the run artefact.
Refs ACTIVITY-WP-0031-T01, T03.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Add the sbom-nexus catch_up resolver contract and the daily replacement for
weekly-sbom-staleness, both disabled until CUST-WP-0062-T03 lands.
The weekly check used `for_each: context.repos.repos` and emitted one task per
stale repo — 75 tasks on 2026-08-17 against 111/111 stale repos. The
replacement asks sbom-nexus for only the N oldest-stale repos in one ranked
call and carries no rule block at all, so tasks_spawned is 0 by construction.
- context_resolvers/sbom_nexus.py: source type `sbom-nexus`, query `catch_up`,
GET /sbom/catch-up?limit=N. Read-only; ingest is T02. Limit bounded 1..25 and
the response truncated to it so an over-long reply cannot widen T02's
side-effect.
- activity-definitions/daily-sbom-catchup.md: weekdays 09:15 Berlin, enabled:
false, deterministic sbom_catchup progress sink.
- rules/executor.py: the deterministic report builder only special-cased
context.repos, which would have emitted a contentless progress event for this
definition. _sbom_catchup_report names the selected repos and reads
updated/skipped from context when T02 populates them.
- 17 tests against a test double; no live nexus exists yet.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Map every State Hub/core-hub caller to a post-retirement owner. Keep the
15-minute sweep schedule here and point the engine at repo-manager
(State Hub dual-run by default, REPO_MANAGER_URL when present). Publish
GET /execution/semantics and 410 workplan launch routes so State Hub
/execution/* is not re-homed as a task database. T03 still waits on
HUB-WP-0004.
Review ACTIVITY-WP-0029 against info-tech-canon, policy-nexus, and
State Hub retirement: activity-core keeps schedule and ops_run;
repo-manager owns consistency; hub-core owns progress ports.
Mark WP-0026 finished. Refresh INTENT, SCOPE, and repo-boundary.
Bare make lists targets. make install-cli installs the activity tool via uv.
Named activity-core backends live in ~/.config/activity/services.json with
list/add/use/default/which; -s/--service selects one call without changing
the default; --activity-url is a one-shot override.
Ship the activity console script for consumer-repo morning review: list,
status, runs, deliverables, inbox, checkpoint, and ack. Offline-first with
git + local defs; enriches from ops API and State Hub. Multi-source trust
matrix never reports did-not-run when git has the artefact. Adds
target_repo filter on GET /ops/automations.
ACTIVITY-WP-0027: document durable ClusterIP host access for llm-connect;
join activity_runs to ops_runs; surface Forgejo artefact links on
/ops/ui automation detail and new run detail pages.
Capture post-FI-cutover reliability caveats: durable host llm-connect for
rein-aharness, and operator review of deliverables from activity.coulomb.social
without SSH.
Cron schedules always passed trigger_key="scheduled", so ops_run
idempotency collapsed every weekday into one key. After the first fire,
create_ops_run was a silent no-op, the claim loop starved, and dual-clock
host timers produced empty FI briefs.
Map scheduled fires to run_id (or scheduled:{iso}) via
emit_triggering_event_id; log duplicate skips; document the contract.
Add deploy-ops-run-queue-railiance.md (image, migrate 0007, smoke, dual-path
residual), wire OPS_RUN_* into runtime ConfigMap, and cross-link runbook/README.
T07 stays open until prod smoke is executed.