Skip to content

Releases: mrsirg97-rgb/rig

v1.5.8

Choose a tag to compare

@github-actions github-actions released this 26 Sep 18:59
8b5b8c6

frontend/tui gains WithStatusTick(d time.Duration): while the TUI
waits for input (no turn streaming, no compaction), the status function
is re-read every d on the Input loop and the region redraws only when
the rows changed. The embedder's rows used to change at command time
only — a background fire wrote a snapshot the next command would show;
now a write the status function sees lands on the next idle tick. Zero
is off (the default; rig's own main never sets it), and the recapture
rides the Input loop, which a turn's start leaves, so the tick never
fires mid-turn; a buffered tick lands immediately when the next Input
starts. The Used reset stays at the session boundaries (/new,
sessions resume).

Tests: a status callback that flips a row after two 10 ms ticks
redraws with the new row under a 10 ms tick without any command, the
unchanged rows never repaint, and a streaming turn blocks the tick
until it ends.

v1.5.7

Choose a tag to compare

@github-actions github-actions released this 25 Sep 19:13
3ec493b

provider/openai retried 429/5xx with backoff only for hosted rows; a
local llama-swap proxy could answer 502 with an empty body before the
first token (a keep-alive race with llama-server — nothing reached the
model), and the local row faulted the turn. A 5xx whose body is empty
now retries for every row under the hosted policy: the identical request
body, exponential backoff from RetryBase (500ms, 1s, 2s by default)
with the row's jitter, under the hosted 3-retry bound. The retry lives
at the status gate before the stream: once any streamed byte has
arrived a failure is never retried, and a 5xx carrying a body is still
a real error — it faults immediately on a local row.

v1.5.6

Choose a tag to compare

@github-actions github-actions released this 25 Sep 17:02
76baccb

tui.StatusIn gains Rows []string: the embedder's footer band. The
rows render under the status line behind the same four-cell dim rule the
swarm band uses (nothing when empty, so rig's own main is unchanged).
The status recaptures after every successful command — the embedder's
commands included — with the Used reset staying at the session
boundaries (/new, sessions resume); docs/EMBED.md lists the field
beside WithCommands and WithStatus. Rows recapture at command time
only: a mid-turn tool effect shows stale until the next command, while
the swarm band stays live because it rides a notify event. A turn-end
hook is a later version.

v1.5.5

Choose a tag to compare

@github-actions github-actions released this 25 Sep 04:39
790d4bc

frontend/tui gains WithTitle(name string, rows []string, tagline string): an embedder replaces the welcome block's block-letter rows
with their own and adds a line under them (default: the rig rows, no
tagline). The ascii glyph fallback prints the plain name (name,
"rig" for the default), never the first art row, and docs/EMBED.md
lists the option beside WithCommands and WithStatus.

v1.5.4

Choose a tag to compare

@github-actions github-actions released this 24 Sep 05:29

The TUI band moves below the existing footer rows behind a short dim
rule and densifies each row (workers 1 · +7 ✓0 ✗0 · w1 t423 12s /
reviewer 1 · ⧗0 ✓0 ✗0 · w2 — —); /swarm's replies say added N agents and stopped N agents; and every abnormal spawn end records a
reason on the run.

  • The band (frontend/tui, SPEC_TUI 3a): one row per role below
    the status rows, separated by a four-cell dim rule (no rule and no
    rows when nothing runs). No new colors: labels, markers and
    separators dim, counts text, ✓ the success slot, ✕ the fault slot;
    the glyph switch carries the ascii fallback (...., ~ for the
    review clock).
  • The replies (swarm/, SPEC_SWARM 4): swarm: added N agents (role X · model M) — one phrasing whether the swarm was empty or
    running (agent for one, agents for more, never started) — and
    swarm: stopped N agents.
  • The heartbeat resets on each spawn: a restarted task shows a
    fresh age (— until the new run's first beat) instead of the dead
    run's last heartbeat.
  • Run reasons (store/scheduler, the j23 investigation): the
    runner captured no signal and recorded no reason when a spawn's
    process group died — the only proof of a stall or timeout was a log
    marker, and a cancel or external signal was a bare exit -1 with
    reason NULL. RealSpawn now captures the signal from the wait
    status, Delegate and RunJob record the reason on the run
    (killed after timeout, killed after stall, canceled, killed by signal N), the spawn's process group carries Pdeathsig (a hard
    runner death does not orphan the worker), the swarm controller's
    context derives from the session context, and cmd/rig stops the
    swarm on session teardown so those deaths are recorded before the
    process ends.
  • README.md: the measured stats refresh (720 swarm lines, 34,336 of
    Go, 53,815 of tests).

v1.5.3

Choose a tag to compare

@github-actions github-actions released this 24 Sep 02:57
6333b3f

The README, the docs, and the landing page now say what rig is: a small
operating system for agents.

  • README (README.md): the top screen becomes the thesis, "A small
    operating system for agents. The kernel is a few hundred lines.", with
    ## measured (each number names its mechanism: 99.1% cache hit over
    2,925 turns, 297M of 299M prompt tokens, 208M on 2026-09-22, 7k
    byte-stable preamble, swarm 723 lines, 34,301 lines of Go, 53,626 of
    tests), ## what's different, and an OS mapping table. A new
    a day with rig walkthrough covers first prompt, tools, the queue,
    memory, schedules, the swarm, and resume. The tools section says the
    default menu is 17 built-in tools (view vision-gated, scheduler
    and delegate fleet-gated), and the dashboard bullets match the real
    web surface (plain-text create, start/complete/retry, transcript open).
  • docs/EMBED.md (new): rig as a Go module, the core seams,
    loop.Run, the five seams the root wires, a worked HTTP-service
    example (kernel, board-backed job, in-process worker, one process),
    the freeze, and local vs hosted. The example compiles.
  • docs/SETUP.md: the models.json block gains a hosted row example
    (remote, provider, baseUrl, apiKey, concurrency,
    reasoning, providerPin, cacheControl, retries).
  • docs/USAGE.md: the /swarm section names the hosted-row path (a
    remote worker skips the local swap and the busy probe, riding the
    row's concurrency tokens) and gains a short hosted-rows paragraph
    (auth, retry, cost in the usage line, reasoning field names).
  • site/index.html: the title, og:title, and hero become "a small
    operating system for agents"; the stats refresh (417 loop lines,
    34k/53k code/tests, commit count) and the freeze line names the real
    story (core frozen at 1.5.0's bytes, loop open to pure addition with
    named reopenings).
  • core/PACKAGE.md: the 1.5.0 hosted extension is the named reopening,
    closed when the gate re-froze core at 1.5.0's bytes, not "the named
    reopening of the frozen surface" (the re-freeze, 8441fd8).
  • The freeze gate (frontend/tui/freeze_test.go): the frozen-surface
    loop honors the allowlist's PACKAGE.md entry, a PACKAGE.md change in
    core/ or loop/ is a docs change, not a reopening.

v1.5.2

Choose a tag to compare

@github-actions github-actions released this 24 Sep 00:30
40534fc

The task queue's one dependency became two named links, requires and
blocks, and read stopped inlining note text.

  • Two edges per task (store/todo, tool/todo, SPEC_TODO_EDGES): a
    task carries requires and blocks, one each, each an id (tN) or
    exact text, null clears. requires tN: I cannot start until tN is
    done; blocks tN: tN cannot complete until I am done. Blocked
    means a task's requires target is unfinished or any task whose blocks
    names it is unfinished (pending, in_progress, review, failed), so
    claim takes only unblocked pending tasks and complete/accept on
    a blocked task refuse naming what it waits for. create refuses
    loudly naming the tasks: an unknown link, a self-link, and a cycle
    through either relation (cyclePath walks both). The waits-for graph
    is requires t -> required and blocks target -> blocker; the read
    line shows · requires tN, · blocks tN, and · waits for k on a
    target. Old dependsOn payloads (create events and compact
    snapshots) fold as requires at replay; the snapshot carries both
    links and note times.
  • The notes door (store/todo, tool/todo, /todo): read no
    longer inlines note text — a task with notes shows · N notes under
    it, and the new notes <id> action lists them in order with their
    session and time, headed by the task's link lines; a task with none
    replies no notes on tN. read <id> renders one task, summary-only,
    and points at notes. The swarm brief's TaskInfo still carries the
    full notes; workers need them.
  • Schema 4 (store/todo): task_deps gains the kind column
    (requires|blocks), the disposable projection rebuilt from the log in
    every transaction. EdgeMigration (3->4) drops and recreates the
    projection table; the log carries the edges, so replay is total.
  • The TUI's todo render (frontend/tui): the parser dims the new
    suffixes (requires/blocks/waits for/claimed by) and keeps the
    note-count line.
  • Tests: seven leaves blocking a root (claim and complete of the
    root refused until the last leaf is done), a requires-chain, both
    links on one task, cycles refused with the task names, old
    dependsOn payloads folding, replay across compaction, note counts
    and the notes action (order, session, time, the no-notes reply), and
    read-one's summary-only pointer.

v1.5.1

Choose a tag to compare

@github-actions github-actions released this 23 Sep 22:18
d609931

The controller captured the frontend at wiring time (Frontend: r.rec),
but r.rec is assigned later and swapIn replaces it on /new and
/resume — the first SwarmStatus frame hit a typed-nil recorder and
panicked in Recorder.ensure, crashing the session.

  • The swarm's frontend is a resolver (swarm): Opts.Frontend is
    func() core.Frontend (the Models idiom), resolved on every notify,
    so a controller wired before the recorder exists emits safely once it
    does and a session swap routes its frames to the new recorder. A
    panicking frontend is recovered into a stderr line — the drain worker
    keeps draining.
  • The recorder tolerates a nil receiver (store/state): Notify on
    a nil *Recorder is a no-op, so a seam wired before the recorder
    exists cannot crash on ensure.
  • The delegate's notice seam resolves at call time (cmd/rig): the
    delegate's Notify no longer captures the recorder's method value at
    wiring time.
  • Tests: a controller wired with no recorder drains a task and
    routes the next frames once the recorder appears; a session swap
    routes notices to the new recorder; a panicking frontend leaves the
    drain loop running with the panic loud on stderr; Recorder.Notify on
    a nil receiver is a no-op.

v1.5.0

Choose a tag to compare

@github-actions github-actions released this 23 Sep 20:37

The provider already spoke the OpenAI wire; hosted endpoints (OpenRouter,
DeepSeek's API, any remote OpenAI-compatible server) needed what a local
llama-server does not: auth, retry, cost, per-provider reasoning field
names, and a remote spawn path that never touches the local swap. Model
rows now carry where they run, and swarms and scheduled jobs take dollar
budgets.

  • Model rows gain their run site (models, config): remote (bool),
    provider (a name implies remote), baseUrl (required for a remote
    row), apiKey (never logged or rendered), concurrency (the row's
    token bound, default 1), reasoning (reasoning_content default,
    reasoning for OpenRouter), providerPin and cacheControl
    (openrouter-only), and retries (default 3 for remote rows). The env
    overlay gains RIG_MODEL_BASE_URL, RIG_MODEL_API_KEY,
    RIG_MODEL_REMOTE, RIG_MODEL_CONCURRENCY, RIG_MODEL_REASONING, and
    RIG_MODEL_RETRIES, so a key can live in the environment and never in
    a file.
  • The provider's hosted behavior (provider/openai): NewWithConfig
    sends Authorization: Bearer <key>, retries 429 and 5xx with
    exponential backoff and jitter under the row's bound (the loop sees no
    event until the bound is exhausted, then the existing loud fault),
    parses usage.cost into core.Usage.Cost, reads reasoning under the
    row's field names (delta.reasoning / delta.reasoning_details for
    OpenRouter, delta.reasoning_content otherwise), echoes both back on
    later turns, omits chat_template_kwargs for remote rows, and sends
    the OpenRouter provider.order pin and cache_control switch when
    the row asks for them.
  • Cost lands in the usage column (store/state, core, loop):
    usage.cost (schema v4), RecordUsage/AddUsage take it,
    SessionUsage/SessionCost read it, the sessions list carries it,
    and the TUI footer shows the session's dollars beside the token
    totals.
  • Remote spawns (store/scheduler, tool/delegate, swarm): a
    remote row's delegate and job fire skip the llama-swap busy probe and
    WaitBusy entirely; parallelism is the row's concurrency token
    flock beside the per-session slot bound. The worker resolves the row
    from the shared models.json, so a remote row's baseUrl and key
    ride the worker without the parent passing them.
  • Budgets (swarm, store/scheduler): swarm <n> budget=<dollars>
    stops claiming at the cap with a notice; scheduled jobs take budget
    on create/update and record a skip at the cap. The delegate and the
    runner record each run's cost (read from the cost column), so
    scheduler runs shows the spend and the job's sum is auditable.
  • Tests: a fake OpenAI-compatible server asserts the bearer, the
    bounded 429/5xx backoff (deterministic base and jitter), cost parsing,
    reasoning echoed under the row's field names, and the remote wire
    (no chat_template_kwargs, pin, cache switch); the cost column is
    recorded and summed; a remote delegate and a remote swarm fire never
    consult the swap; a swarm budget and a scheduled job budget stop at
    the cap.

v1.4.4

Choose a tag to compare

@github-actions github-actions released this 23 Sep 18:09
60147a7

The swarm ran silently beside the session: the transcript showed nothing
when a task failed or a reviewer bounced the work, and the only progress
read was the bare /swarm. The TUI now gets two surfaces, both through
the frontend's existing Notify door.

  • The transcript notices (core.SwarmNotice, swarm): the
    controller emits one line per decision-worthy event and nothing else —
    a task failed with its note (swarm: t1 failed — the worker died twice), a reviewer rejected with the reason (swarm: t1 rejected — tests are missing), a worker died and was restarted or exited
    (swarm: w1 died — t1 restarted / swarm: w1 died — t1 exited), and
    the board emptied or the swarm exited (swarm: the board emptied — all workers exited / swarm: /swarm exited — N workers stopped). The
    worker failure now notes the reason on the task too.
  • The status band (core.SwarmStatus, swarm, frontend/tui): the
    controller emits a snapshot on claim, stream bytes, complete, verdict,
    and exit — throttled to a few per second, the exit's last frame always
    landing — carrying the roster and the bound queue's fold counts
    (store/todo.Counts, the new structured read). The TUI folds the
    latest into the footer: two rows above the existing status line while a
    swarm runs (workers 2 · todo 3 · done 5 · failed 1 · w2 t388 12s,
    reviewer 1 · review 1 · done 1 · failed 0 · w3 t386 4m), zero rows
    when nothing runs, one row for a delegate.
  • The delegate's row (tool/delegate): the optional Notify seam —
    an interactive delegate emits the same snapshot shape (one worker row,
    zero queue counts), so the band shows the worker row only. CLI and
    oneshot ignore both events (the compat rule).
  • The band is a status-string extension: no live.go line, no loop
    line — the region's existing height-changing machinery covers the two
    extra rows, and the mid-swarm resize test replays the stream under the
    freeze harness.
  • Tests: each notice with the fake spawn (failed, rejected, died,
    board/stop), the throttled status emission, todo.Counts, the band's
    exact rows, the footer growing/updating/returning, the resize under the
    freeze harness, the delegate's snapshot.