Skip to content

Releases

v1.4.0 — LLM ladder reordered: free OpenRouter router serves first

Choose a tag to compare

@d-oit d-oit released this 17 Sep 12:29

Operator decision 2026-09-17: the free OpenRouter router serves first. Ladder: openrouter → gemini → opencode (was Gemini → Zen → OpenRouter).

Why

The first full runtime dispatch (v1.3.0) proved the old order cannot serve CI: the Zen free tier refused the GitHub Actions runner — "OpenCode's free tier can only be used from within OpenCode". OpenRouter's free router (openrouter/free, 20 req/min, 50 req/day) works from any runner, and a once-daily runtime fits its limits.

Changed

  • Spec §4 + LLM-path table, capture_transcripts.LADDER, llm_model.resolve_model, rehearsal registry wording, docs/runtime.md, and every test pinning the old order — all moved together
  • Failover semantics unchanged: first configured rung serves; LLM_MODEL overrides; --check-rungs remains the gate

Verification

  • pytest 1617 passed · product graders ✅ · do-harness verify --strict ✅

🤖 Generated with Codebuff
Co-Authored-By: Codebuff noreply@codebuff.com

v1.3.0 — Phase 0 runs with zero secrets (free keyless Exa MCP rung)

Choose a tag to compare

@d-oit d-oit released this 17 Sep 12:03

The hosted Exa MCP server (https://mcp.exa.ai/mcp) serves rate-limited search with no API key — Exa's documented "Keyless" mode, verified live against the real endpoint (real BBL results returned; the recorded response is now the parser's unit-test fixture).

Added

  • exa-mcp-keyless rung in run_daily.py's Phase 0 ladder: exa-mcp → exa-mcp-keyless → tinyfish. Paid Exa outranks keyless (same provider, better limits — serving twice would duplicate rows); TinyFish stays last as the independent index.
  • The Phase 0 preflight now passes with zero secrets — the daily runtime works on a fresh fork on day one.
  • Registry surface search:exa-mcp-keyless in the rehearsal; transport parser pinned against the recorded live SSE response; 429 rate limits land in the run's failure detail, never silent.

Fixed

  • --offline in rehearse.py derived its check set from an empty env tuple, so the keyless (network!) check would have been probed in the mode that promises not to touch the network. "Structural" is now a declared property of Check; env-free no longer implies offline.

Verification

  • pytest 1617 passed · product graders ✅ · do-harness verify --strict ✅ · live smoke: 5 candidates from the keyless rung

🤖 Generated with Codebuff
Co-Authored-By: Codebuff noreply@codebuff.com

v1.2.1 — hotfix: runtime-daily.yml failed GitHub's parser; every trigger was dead

Choose a tag to compare

@d-oit d-oit released this 17 Sep 11:08

Patch release, minutes after v1.2.0: the first workflow_dispatch of runtime-daily.yml was refused with HTTP 422 — "An expression was expected" (line 578) — which means the file failed GitHub's workflow parser and every trigger, including the daily cron, was dead on arrival in v1.2.0.

Root cause

Five comments carried a literal empty workflow expression — prose about expressions, written inside comments warning about expressions. GitHub scans run: block values for expressions even inside comments, and an empty one is a parse error. Nothing offline could catch it: PyYAML parses the file fine, and workflow-refs checks paths, not expressions.

Fixed

  • The five comments now say "a workflow expression" instead of the token

Added

  • tests/test_workflow_expressions.py — tripwire asserting no workflow contains an empty expression (with a non-empty-workflow-list guard so it cannot be silently disarmed)

Verification

  • pytest 1607 passed · validate / runtime_eval / synthesise all green · do-harness verify --strict green
  • workflow_dispatch of runtime-daily.yml now accepted

🤖 Generated with Codebuff
Co-Authored-By: Codebuff noreply@codebuff.com

v1.2.0 — live stream runtime with self-improving link lifecycle

Choose a tag to compare

@d-oit d-oit released this 17 Sep 10:54

Full runtime for the basketball-streams skill: source discovery, the calendar write path, the audit ledger, and a closed self-improvement loop — plus adoption of do-harness so "done" is a computed claim rather than an assertion.

Added

  • Runtime core — Phase 0 source discovery, render-evidence corpus, calendar write path, audit ledger, telemetry
  • Ops — daily GitHub Actions workflow, write-mode switch (pure-function matrix), model ladder, rehearsal harness
  • References — magenta.tv fetch ladder, YouTube live-only search contract, free search/LLM backends, self-learning loop
  • Scripts — youtube_live.py (live-only/future-only gate), link_check.py, upsert_events.py, run_daily.py, and the rest of the runtime surface
  • Self-improve loop — audit-to-eval feedback, findings filing, link revalidation with a real producer

Fixed

  • Runtime records the link an event was built from; stale BBL locators repaired; link_check --json stdout kept payload-only
  • CI: pyyaml declared in requirements-dev.txt so the suite is green on a fresh checkout

Verification

  • Product gate: validate.py --check all · runtime_eval.py · synthesise_eval_case.py --verify (36 cases) · pytest (1605 passed) — all green on a fresh clone of this tag
  • do-harness: all 19 sensors green (verification recorded, --strict)

🤖 Generated with Codebuff
Co-Authored-By: Codebuff noreply@codebuff.com