Skip to content

Releases

v0.28.0

Choose a tag to compare

@github-actions github-actions released this 11 Nov 08:06
c678c14

What's changed

Added

  • Guide for plugging in your own skills. docs/custom-skills.md is a two-minute
    read: where a skill can live, what its SKILL.md needs, the gotchas, and how to switch it off.

Fixed

  • Codex sessions can reach the network. Codex blocks network access from shell commands by default, so a
    Codex generator could not install declared dependencies or run checks that need the network. Headless Codex
    sessions that may run shell commands and use the network (implement, apply-feedback) now get network access
    and live web search. Read-only sessions (refine, plan, ideate, readiness, detect) keep shell commands offline
    and use cached web search; PR drafting has both turned off.
  • Claude Code effort settings now always take effect. A CLAUDE_CODE_EFFORT_LEVEL exported in your shell used
    to override every effort ralphctl picked β€” per-flow rows, presets and the escalation ladder β€” without any sign.
    Headless sessions now set it to the same level they pass as --effort. Interactive sessions (refine, plan,
    ideate) leave it alone, so /effort and the /model picker keep working there.
  • The evaluator no longer sees the generator's vendor memory. Claude Code auto memory, Codex memories and
    Grok memory carry notes from one session into the next, so notes from the generator could reach the evaluator
    grading it. Evaluator sessions and the best-of-N judge now run with that memory turned off; the generator keeps
    yours.

Changed

  • Readiness keeps your AGENTS.md rules working under Claude Code. In a repository with an AGENTS.md and no
    CLAUDE.md, the proposed CLAUDE.md now starts with an @AGENTS.md import and adds only Claude-specific
    sections. Before, it copied the whole AGENTS.md body, and the two files drifted apart. Claude Code stops
    reading AGENTS.md once a CLAUDE.md exists, so the import is what keeps those rules loaded.
  • Readiness knows which context files each CLI reads. Codex skips CLAUDE.md unless configured to read it, and OpenCode ignores it
    once an AGENTS.md exists, so readiness for those tools now carries the rules from your CLAUDE.md into the
    proposed AGENTS.md instead of leaving them out. For Copilot and Grok, which read every file, it still avoids
    repeating them.
  • Leaner implement diffs and grounded convention critiques. The generator is now told not to add error
    handling for states the code already rules out, or comments and type annotations to code it did not change.
    When the evaluator fails work on a project convention, it now cites the context file and line that states it,
    and it no longer fails work on a convention no file or criterion states.
  • Retries after a red verify can reuse the rejected work. When a task's verify script fails after an attempt and
    the task retries, ralphctl sets that attempt's changes aside so the retry starts from the last commit. It now
    also saves them as a patch under the sprint's logs/rejected-diff/ folder and tells the retry where it is, as
    an unverified lead it can check and apply, or ignore. Before, the retry had to redo the work from scratch, and
    its prompt wrongly suggested the earlier changes were still in the working tree. Nothing is applied for it.
  • Retries see the first error in a failing verify log. The verify and reproduction output inlined into the
    generator prompt keeps the start and the end of the last 256 KiB of the log, with the middle cut, instead of only the end. A
    compiler or type checker usually prints the root-cause error first, which the old end-only excerpt dropped.
  • CLI commands start about twice as fast. ralphctl --version, sprint list, settings show and the other
    one-shot commands no longer load the TUI (Ink and React), taking roughly 0.25 s instead of 0.55 s. Bare
    ralphctl is unchanged.
  • ralphctl doctor runs its checks concurrently, roughly halving its run time. The report order is unchanged.
  • Fewer needless reproduction runs. Implement decides whether a task is a bug fix from its name first, and reads
    the description only when the name gives no hint. Before, a feature task whose description merely mentioned
    "fix" or "broken" got an extra AI session that tried to write a failing test before any work started.
  • A reproduction test that hangs no longer counts. For bugfix tasks, ralphctl re-runs the reproduction test
    the AI wrote before it accepts it. A re-run that ralphctl had to kill, because it timed out or printed runaway
    output, used to count as a reproduction, and the evaluator then re-ran it every round. It is now discarded, its test
    file moves to the git stash so it can't hang the next verify run, and the task goes on without a reproduction. The reproduce prompt also asks the AI to put a timeout inside a test
    for a hang, to assert the behaviour the report asks for rather than only "not today's wrong output", and not to
    assert details the report never mentions.

Full changelog: v0.28.0...HEAD
npm: https://www.npmjs.com/package/ralphctl/v/0.28.0

v0.27.0

Choose a tag to compare

@github-actions github-actions released this 25 Oct 09:18
709ade8

What's changed

Breaking

  • OpenCode 2 is refused. Reinstall OpenCode 1 (see Added).
  • Saved settings are rewritten on load. Grok none / minimal effort loads as low, and Copilot Opus 4.5, 4.6
    and 4.7 rows load as Opus 5.5.

Added

  • Claude Haiku 5.5. Claude Code gains claude-haiku-5-5 (needs Claude Code 2.1.293 or later): $0.10/$0.50 per
    MTok ($0.50/$2.50 for prompts over 100K tokens), a 1M context window and all five effort levels. claude-fast and claude-economic now run refine,
    readiness and PR drafting on it at low; plan, implement and ideate stay on Sonnet 5.5. It is also the new
    bottom step of the Claude Code escalation ladder (Haiku 5.5 β†’ Sonnet 5.5 β†’ Opus 5.5). An older Claude Code CLI
    fails the spawn on it β€” upgrade, or set those rows to Sonnet 5.5. Haiku 4.5 still works for saved settings.
  • Claude Haiku 5.5 on Copilot. claude-haiku-5.5 is selectable for Copilot rows (needs Copilot CLI 1.0.94 or
    later) and escalates to Sonnet 5.5. No preset uses it.
  • OpenCode 2 is detected at launch. OpenCode 2 installs as the same opencode command but changed the flags
    ralphctl uses, so a flow on OpenCode 2 now stops before it starts and says how to get OpenCode 1 back:
    brew install sst/tap/opencode (Homebrew's own opencode formula is now 2.x), the install script, or
    npm install -g opencode-ai@1. Install suggestions for OpenCode now pin the 1.x line.
  • Security skill for implement. The new bundled ralphctl-security-and-hardening skill loads by default for
    implement: threat-model first, validate untrusted input, keep secrets out of code and logs, check authorization,
    guard destructive file operations, review new dependencies and treat model output as untrusted. Sensitive changes
    the task didn't ask for (auth, permissions, new kinds of personal data) are escalated rather than made silently β€”
    the implementing AI blocks the task with a question, and the reviewer flags it. The Skills catalog also suggests
    it for plan and PR drafting.
  • Spec-driven development skill (opt-in). ralphctl-spec-driven-development is available in the Skills catalog
    for refine and ideate. It helps turn a vague ticket or idea into sharper requirements β€” a clear objective, explicit
    scope, testable criteria and named open questions β€” without adding files or approval steps of its own. It is off
    by default.
  • Ten more bundled skills. API and interface design, performance optimisation, frontend UI engineering,
    deprecation and migration, code simplification, source-driven development, observability, codebase design,
    writing for agents, and a humanizer for PR descriptions and requirements prose. Each is a Skills catalog
    suggestion for the phases where it fits and stays off until you enable it, except ralphctl-writing-for-agents,
    which loads by default for readiness because every later AI session reads the context file readiness drafts.
    Several existing skills also picked up upstream improvements: debugging builds a fast reproduction loop and ranks
    hypotheses before fixing, test-driven development warns about tests that recompute their own expected value, and
    code review asks every bug finding to name a concrete failing case.
  • The README opens with a recording of the loop. A ~10-second capture shows one task going through it: the
    evaluator fails round 1 with a critique, the generator applies it, and round 2 passes and commits.
    ralphctl demo --script replays the same run with no AI CLI and no tokens.

Changed

  • Copilot presets use Opus 5.5. GitHub gives Opus 4.8, 5 and 5.5 to the same Copilot plans, so the Copilot
    presets, the Copilot defaults and the top of the Copilot escalation ladder move from claude-opus-4.8 to the
    cheaper claude-opus-5.5 ($4/$20 vs $5/$25 per MTok). Saved settings on Opus 4.8 or Opus 5 keep working and now
    escalate to 5.5. Applying a preset on an account without 5.5 falls back to Sonnet 5.5.
  • Copilot gets ready for the 2026-11-16 retirements. GitHub retires claude-opus-4.8, claude-opus-5 and
    gpt-5.6-terra on Copilot on 2026-11-16. They stay selectable until then, but ralphctl no longer steers anything
    onto them: escalation from gpt-5.6-luna goes straight to gpt-5.6-sol, and saved settings on the older retired
    Opus ids (4.5, 4.6, 4.7) now load as claude-opus-5.5 instead of 4.8.
  • Claude Code runs without fork subagents. Claude Code 2.1.302 turned fork subagents on by default for
    headless runs. ralphctl turns them off for the sessions it starts, which keeps a run's cost the same as before
    and keeps read-only sessions from handing work to a copy whose tool limits aren't confirmed.
  • OpenCode free models refreshed. The free tier now lists exo-free, ling-3.1-flash-free,
    longcat-2.5-preview-free, mimo-v2.6-flash-free, muse-spark-1.3-contributor-free, space-bunny-free and
    step-5-preview-free. hy3-free, mimo-v2.5-free and muse-spark-1.2-contributor-free are gone; saved
    settings on the last two switch to mimo-v2.6-flash-free and muse-spark-1.3-contributor-free.
  • ralphctl-karpathy-guidelines now loads by default for plan only. On implement it overlapped the
    ralphctl-surgical-simplicity and ralphctl-ponytail skills that already load there, so it moves to a Skills
    catalog suggestion for implement. Enable it from the catalog to keep the old behaviour.

Fixed

  • Grok effort stays within what each model accepts. grok-4.5 takes effort up to high and grok-4.6 /
    grok-4.7 up to xhigh; none takes max. ralphctl now lowers a higher level to the model's highest, the same way
    it already does for Copilot and Codex, so a saved max runs at xhigh on grok-4.7 instead of risking a rejected
    spawn. grok-frontier now uses xhigh on plan, implement and ideate, and xhigh as its global effort. When
    escalating effort on grok-4.5, ralphctl now raises it to high instead of xhigh. The Grok CLI also refuses
    none and minimal, so they are no longer offered; saved Grok rows using them load as low. When the Grok CLI
    does reject an effort, the task stops once with a message naming the setting to change instead of retrying.

Data safety

  • Legacy sprint folders are no longer split or deleted at launch. Existing bare-id sprint directories are merged
    into their slugged folder before any side file is written, and a reconcile never deletes one. A failed rename keeps
    the sprint's data together, and git worktree links are repaired after a sprint folder moves.
  • Migration is harder to block and safer to run. Orphan memory dirs no longer stop the gate, unreadable ledgers
    and rotated files are kept in the memory merge, a stale learnings.md in a drained legacy dir is dropped, a failed
    backup removes its partial copy, and symlinks are backed up as links with worktrees skipped. The gate copy no
    longer promises a full backup.
  • A journal that can't be read is never overwritten. progress.md is not regenerated over an unreadable
    journal, and the quarantine breadcrumb is written under the journal lock.
  • Concurrent edits survive. tasks.json writes carry a lock owner, plan / ideate keep another session's plan
    when they commit and refuse when the sprint changed mid-session, and long sessions no longer clobber ticket edits.

Implement runs

  • Parallel runs record only what landed. A task is marked done after its branch is folded, a landed fold keeps
    its done when a later step fails, attempts survive an abort, and what failed branches persisted is kept.
  • Dependents are no longer stranded when a prerequisite is unsettled.
  • A resume that would exhaust its budget is blocked before the task body runs and no longer stops a serial run.
  • Locking. Manual unblock, close-sprint and sprint updates take the sprint lock, and unblock waits out a live run.
    Done transitions apply to the sprint as it is on disk, and unblock keys on the sprint's current directory.

Git

  • Long hooks are no longer killed at 30 seconds. Hook-running git verbs are bounded separately from network
    verbs, a cancel reaches them, their processes are reaped when ralphctl exits, and git never prompts for
    credentials inside the TUI. The credential hint appears only for SSH key rejections.
  • PR and MR bodies go over stdin instead of argv, and the repo path is shell-quoted in the create-pr commands.
    The PR body closes only issues whose tasks all landed done.

Providers

  • Final error records are no longer lost. Headless spawns settle on close, so the last stdout records land;
    setup and verify scripts settle on exit, a CLI's process group is reaped when it exits cleanly, and a recycled pid
    no longer keeps a stale skill install alive.
  • Codex session resume works again.
  • Claude Code effort follows the model. The level is narrowed to what the chosen model accepts.

Settings and domain

  • Verify-gate prefixes match a leading ./ or /; an empty plan is rejected instead of stranding a planned sprint;
    absolute paths containing ~ or $ are accepted; applying a preset keeps skill opt-outs and agent bindings.
  • Empty values for numeric settings keys are rejected, settings set refuses a retired effort or model, an
    unexpanded RALPHCTL_HOME is refused, and an invalid settings.json gets a repair hint.
  • Pre-release users are told when the stable release ships.

TUI

  • The Execute tasks panel no longer freezes when its buffer slides and shows attempt, commit and ETA chips. Esc
    collapses the narrow layout before popping, and leaves the create-project error step.
  • Ink owns bracketed paste, so the terminal's paste mode is restored on every exit.
  • runs prune rejects an empty or non-decimal --keep-last; the create-project wizard rejects duplicate slugs.

Prompts

  • The prompt contract outranks skills and context files, with a tighter ...
Read more

v0.26.0

Choose a tag to compare

@github-actions github-actions released this 08 Oct 12:11
f89202b

What's changed

Added

  • Unblock asks what to do with a rejected diff. When a blocked or interrupted task left its rejected work in
    git stash, unblocking (u in the Tasks panel and Sprint detail, bulk u on the Sprints list) asks whether the
    next attempt continues from it or starts fresh, suggesting one from why the task stopped. The CLI gets
    ralphctl task unblock <id> --prior-work continue|fresh. Task cards show the stash, its size and what the next
    attempt will do, and whether an attempt restored it or left it in the stash and why.
  • Restoring earlier work is recorded. Each attempt notes whether the rejected diff was restored, kept by choice or
    left in the stash, in the task, progress.md and the card. Resetting an interrupted run warns when the working
    tree holds the only copy of restored work. When an attempt continues from restored work, the AI is told what it
    is and why it was rejected, instead of mistaking it for an unexplained dirty tree.
  • Clearer step display while a flow runs. A one-line strip in the header names the main steps (e.g.
    Prepare β†’ Run tasks β†’ Finish) and which one is running, for every flow. The steps list shows main steps with the
    active one expanded and finished groups collapsed to a summary; each task card shows its own Prepare / Attempt /
    Round / Verify / Commit steps with a pass/fail verdict per review round. Bookkeeping steps stay hidden unless they
    fail, and failures stay pinned in view.

Changed

  • ralphctl task unblock no longer always restores the diff. With no flag it now picks by cause: continue after a
    self-block, a cancel or an interrupted run, start fresh after a failed review. It prints the choice and the flag to
    flip it. Tasks unblocked before this release keep restoring automatically.
  • A blocked task's blockedReason no longer ends with the stash line; the stash is shown from its own field.
  • Review rounds check the tree first. Before each review round, ralphctl stops (before the editor or the AI
    session) when the tree has uncommitted changes, lists the changed files and shows the previous round's commit
    error. The feedback prompt no longer carries its own dirty-tree rule.
  • Plan review shows task-specific evaluator dimensions before you approve a plan.
  • Evaluator prompts follow one set of grading rules. Verdict, blocked-check and critique format live in a single
    shared partial; the continuation evaluator also sees a task's extra dimensions. Critique lines carry a dimension
    tag and a location.
  • Generator prompts match what the harness does. Uncommitted work from the reproduction test or an earlier
    attempt is expected rather than flagged; git stash and other destructive git shortcuts are off limits; a check
    that failed to start no longer counts as verification.
  • No round counts in the generator's view. The plateau notice asks for a fundamentally different fix without
    showing the round number or the stall limit.
  • More inputs are marked as data, not instructions: reproduction output, summaries of earlier attempts,
    candidate summaries, recorded learnings and the ticket summary.
  • Pull-request prompt: every git -C command carries the repository path, and the concealment rules are gone.
  • Readiness reports a note-only result with the note text instead of a generic failure; distill-learnings
    treats an empty result as a no-op; ideate rejects a blocked result and an empty task list; plan,
    ideate and refine validate the draft before presenting it.

Fixed

  • Parallel worktree ref collision. Worktree branches now live under ralphctl-wt/<sprint>/<task> instead of
    nesting under the auto-named sprint branch, which made worktree creation fail while that branch existed.
  • Unlanded worktree commits are rescued, not deleted. A leftover worktree ref holding commits the sprint branch
    lacks is moved to ralphctl-rescue/<sprint>/<task>-<timestamp> and noted in progress.md.
  • Parallel tasks no longer break each other's worktree setup. Concurrent git worktree bookkeeping in one
    repository could fail with failed to read .git/worktrees/…/commondir and leave a task unstarted; those git
    commands now run one at a time per repository.
  • The steps list no longer freezes during a run, and steps skipped after a failure show as skipped instead of
    pending forever.
  • Planned auto criteria no longer make a task impossible to pass. The planner now scopes test criteria to the
    task's own tests, sees each repository's verify gate, and the plan check warns when a criterion repeats it. A whole
    suite that was already red, or that depends on the environment, used to leave tasks that could never pass.
  • A flaky verify gate no longer burns an attempt. A post-task gate that fails once and passes on an immediate
    re-run on the same tree is recorded as flaky in the progress journal instead of being blamed on the task. A gate that
    fails both times is still treated as a regression.

Full changelog: v0.26.0...HEAD
npm: https://www.npmjs.com/package/ralphctl/v/0.26.0

v0.25.0

Choose a tag to compare

@github-actions github-actions released this 04 Oct 21:07
71ee355

What's changed

Added

  • Housekeeping, from Home's SYSTEM group (H). A dry-run scan lists orphaned sprints and memory, old done
    sprints and old runs with their sizes (KiB / MiB / GiB); select what to delete and confirm. Removing a project asks
    separately whether to remove its sprints and memory too.

  • Doctor shows what to fix first. ! groups failing probes ahead of the passing ones, which ↡ reveals.

  • Crash recovery. If ralphctl dies mid-run (crash, kill -9, power loss), an interrupted task shows in
    Home's NEEDS ATTENTION group with its attempt, age and uncommitted changes; ↡ resumes Implement. Active sessions
    lists the dead run (d dismisses it). On a best-effort basis the generator continues its previous provider
    session when provider, model and working directory are unchanged, and starts from the full brief otherwise. An
    interruption does not use up a task attempt (up to three in a row).

  • Quit asks first. q on Home / ctrl+c with runs live asks [y/N] (default No) and stops them cleanly on yes,
    even when a run is waiting on your answer. A run that does not stop within 5s is force-stopped. Stopping a run
    yourself does not use up a task attempt either, and the attempt counter shows Β· resumed after a free restart.

  • Waiting runs say so. A run blocked on your answer shows [WAITING] in NEEDS ATTENTION, the footer and the run
    view, and fires an OS notification (honouring ui.notifications). Runs that finish after two minutes notify too.

  • Presets fit your account. Applying a preset (Settings, ralphctl settings apply-preset, first-run setup)
    now checks which models your account can actually use and swaps in a close stand-in for any it can't β€” e.g. a
    Copilot plan without gpt-6-luna gets gpt-5.6-luna β€” and says which rows changed. Copilot now asks the Copilot
    CLI for your account's models, so the Settings model picker lists only those too.

Changed

  • New models, and the presets use them. Codex and Copilot gain gpt-6.1-sol, which replaces gpt-6-sol as the
    Codex flagship in the Codex presets, the Codex defaults, the default implement evaluator and the top of the Codex
    escalation ladder (same token price). Copilot gains claude-sonnet-5.5, which replaces Sonnet 5 in the Copilot
    presets and its escalation ladder (Haiku β†’ Sonnet 5.5 β†’ Opus 4.8). Copilot's light flows move from gpt-5.6-luna
    to gpt-6-luna (half the price). On Copilot, gpt-6.1-sol is Pro+ only, so no Copilot preset uses it.
  • Copilot models GitHub retired on 2026-10-02 are gone. gemini-3.5-flash / gemini-3.6-flash β†’
    gemini-3.8-flash, kimi-k2.7-code β†’ kimi-k3, claude-opus-4.7 β†’ claude-opus-4.8; a saved setting on one of
    them is moved over on load. The models Copilot retires on 2026-10-19 (gpt-5.5, gpt-5.4, gpt-5.4-mini,
    gpt-5-mini, gemini-3.7-flash, grok-4.5) still work until then, but no preset or escalation step uses them.
  • No more orphaned AI processes. AI CLIs run in their own process group; abort and the idle watchdog stop the
    whole group, and a helper cleans up what a dead ralphctl left behind (on POSIX; on Windows the next launch
    does it). Session ids are saved as soon as the CLI reports them.
  • Stale locks recover faster. A repository lock records its owner; a dead owner on the same machine is reclaimed
    at once, and a held lock names the process that holds it.
  • Overlays outrank prompts. An open overlay stays closable while a prompt is queued, and q never quits through
    one. The header and footer clip to one line at narrow widths.

Fixed

  • Create sprint checks the name as you type. An empty, punctuation-only or too-long name (its slug may not
    exceed 64 characters) stays at the prompt with an inline error instead of failing the run.
  • Project slugs are unique. Creating a project whose slug another project already uses is refused, and the
    wizard says so at the slug step.
  • Review's distill question defaults to No, matching its [y/N] label (close sprint's too). esc on the
    feedback prompt now leaves the sprint in review without journaling a close; an empty submission still closes it.
  • Detect scripts, Detect skills and Review check the AI CLI is on PATH before starting, like the other AI
    flows, instead of failing on a spawn error.
  • progress.md's State: line follows the sprint to active, review and done.
  • Refine's unavailable reason no longer says "add at least one ticket" when every ticket is already approved.
  • Create PR checks the sprint first. An ineligible sprint is refused before anything is pushed, and if any AI
    authoring step fails the PR opens with the template text instead of failing.
  • A PR without a URL is an error. When gh / glab exits 0 without printing a URL, create PR now reports it
    instead of storing the last line of output as the PR URL.
  • Context-file writes never overwrite blind. Readiness and distill refuse to replace an existing file they
    can't read for a backup.
  • Cancelling a task settles its attempt. The running attempt is marked aborted instead of staying running.
  • Parallel implement stops after a failed setup. It no longer runs the closing steps when the prologue failed.
  • Sprint delete respects running flows. ralphctl sprint remove is refused while a flow runs, including a
    flow in another process that holds no lock.
  • A blank task description is rejected instead of silently clearing the field.
  • ralphctl task evaluation prints an error to stderr and exits 1 when the artifact can't be read.
  • Effort follows the model, not just the provider. Copilot claude-haiku-4.5 gets no effort flag (its CLI
    rejects any level), and Copilot / Codex models that support fewer levels get the closest one they accept β€” e.g.
    max becomes high on Copilot gpt-5-mini and xhigh on Codex gpt-5.5. A global max now reaches the Codex
    models that accept it instead of always flooring to xhigh.
  • A rejected effort or model blocks the task once, with the reason. When the AI CLI refuses the configured
    effort or model, the task blocks after one attempt and names the setting to change (e.g.
    ai.implement.generator.effort), instead of retrying until "AI process repeatedly crashed". Codex errors that it
    reports only on stdout are now read too.

Removed

  • scm.postRefinementComment setting. It had no effect; existing settings files still load and drop it.

Full changelog: v0.25.0...HEAD
npm: https://www.npmjs.com/package/ralphctl/v/0.25.0

v0.24.0

Choose a tag to compare

@github-actions github-actions released this 30 Sep 06:54
cf3ecbd

What's changed

Added

  • Claude Sonnet 5.5. claude-sonnet-5-5 joins the Claude Code catalog (1M context, effort
    low..max, CLI default medium), and the Claude presets move to it. The Claude escalation
    ladder is now Haiku β†’ Sonnet 5.5 β†’ Opus 5.5. claude-sonnet-5 stays in the catalog and still
    escalates, so existing settings load unchanged. Copilot stays on claude-sonnet-5 β€” 5.5 isn't
    offered there.
  • Full plan review in the TUI. The plan review screen now renders each task's repository,
    dependencies, steps and every acceptance criterion, in a scroll window sized to the terminal.
    Ideate runs the same plan check and review gate as plan before importing tasks; rejecting
    restores the sprint.
  • Bounded reproduce exit. Implement's reproduce step may report that a failure can't be
    reproduced, with a reason, after two revisions instead of looping.

Changed

  • Every approval gate shows the full document. Refine, ideate and plan put the checklist
    first, the full document verbatim every round, and the question last; the pinned header keeps
    findings and the question visible.
  • Context-file updates emit only the delta. Distill and readiness have the model write just
    the section it owns or new sections; ralphctl splices them into the file. Duplicate headings
    fail safe, and the confirm gate still shows the full resulting file.
  • Candidate judge runs both orders. The pairwise judge scores each pair in both orders; a
    disagreement counts as a tie.
  • Untrusted inputs are marked as data. Ticket text, issue-tracker content, idea text, the
    existing project context file and the generator's output are prefixed with a
    data-not-instructions line in the prompts that consume them.
  • Implement guardrails. The baseline rule no longer blocks the failure a task exists to fix
    or an operator-accepted red baseline; implement prompts add reversibility, no test
    special-casing, scratch cleanup, scope and stop-when-green rules. Harness context is sent only
    to implement, evaluate and their continuations.

Fixed

  • A stale --resume session respawns with the full original prompt instead of a bare
    continuation, across all five providers.
  • Distill writes its proposal to the harness output file and clears a stale one first, so the
    confirm gate and .bak backup are no longer bypassed.
  • The evaluator no longer emits a placeholder verdict that parsed as a real FAIL; evaluate and
    its continuation share one set of grading rules.
  • Detector and helper prompts drop contradictory rules and placeholder timestamps.
  • Scrollable messages re-clamp their scroll offset when the terminal grows.

Removed

  • The entropy and loop-diversity plateau detectors (no preset enabled them). The calibrated
    predicate is the only plateau exit; the entropyPlateauDetector setting is ignored and old
    settings files and records still load.

Full changelog: v0.24.0...HEAD
npm: https://www.npmjs.com/package/ralphctl/v/0.24.0

v0.23.0

Choose a tag to compare

@github-actions github-actions released this 22 Sep 23:38
0a790c0

What's changed

Added

  • GitHub/GitLab issue tracker integration. ralphctl can create a GitHub or GitLab issue from a
    local ticket and post approved requirements as a comment on a linked issue β€” both opt-in, and
    neither rewrites the issue body. The TUI add-ticket wizard asks whether to create a tracker issue
    (default No) when the new ticket has no link and the project's first configured repository
    resolves to GitHub or GitLab; ralphctl ticket add saves locally without asking. Refine's
    approval menu offers Post as comment for a linked ticket (default No, Approve stays the
    default choice; repeating the same approved text does not double-post). Retry with publish
    (ralphctl ticket publish <ticketId> or sprint-detail p) runs the same write with no second
    prompt β€” create when the ticket has no link, comment when it already does.

Changed

  • Grok models. The catalog is grok-4.7 (flagship), grok-4.7-build-fast (same model,
    twice the token price; not a preset pick), grok-4.6, and grok-4.5. Grok now has a preset
    in every family: grok-only, grok-economic, grok-strong-gate, grok-fast, and
    grok-frontier. Plateau escalation climbs grok-4.5 β†’ grok-4.6 β†’ grok-4.7. Probed with
    grok models on Grok Build CLI 1.0.40 (2026-09-22). Mixed presets stay on the Claude author /
    Codex critic split.
  • Opus 5.5 / Fable 5.1 / GPT-6 model refresh. Claude Code's Opus 5.5 is the new default Opus
    and top of the Claude escalation ladder β€” cheaper than Opus 5 ($4/$20 vs $5/$25 per MTok),
    natively 1M context, no [1m] variant (requires Claude Code >= 2.1.280). Fable 5.1 succeeds
    Fable 5 as the frontier tier above Opus, used only by the frontier presets' deep flows. Codex
    adds the GPT-6 family (gpt-6-sol flagship, gpt-6-luna cheap tier, gpt-6-astra
    frontier-only premium) and drops gpt-5.4 / gpt-5.4-mini (retired from Codex 2026-08-31;
    persisted rows remap to their GPT-6 successors). Copilot's curated default Sonnet moves from
    the deprecated claude-sonnet-4.6 to claude-sonnet-5, adds claude-opus-5.5 /
    claude-fable-5.1 / gpt-6-* / gemini-3.8-flash / grok-4.7 to its catalog, and drops six
    models GitHub deprecated on 2026-09-01 (claude-opus-4.5/4.6, claude-sonnet-4.5/4.6,
    gemini-3.1-pro, raptor-mini) with remaps to live successors. The same remaps apply to a
    task escalated before the upgrade (its stored escalated model resumes on the successor) and to
    harness.escalationMap targets β€” an ambiguous target (retired on one backend, live on another,
    like gpt-5.4) is left as written and logged as a warning at startup. OpenCode's free-tier picks
    refresh to opencode-ai 1.18.32 (nemotron-3.5-lightning-free replaces the retired
    deepseek-v4-flash-free as the mini pick).
  • Escalation ladder is now provider-scoped. DEFAULT_ESCALATION_LADDERS replaces the flat
    DEFAULT_ESCALATION_MAP β€” a shared model slug like claude-sonnet-5 now climbs differently on
    Claude Code (β†’ Opus 5.5) than on Copilot (β†’ Opus 4.8), instead of one value winning for both.
    settings.harness.escalationMap is unchanged in shape (still flat, still user-overridable) and
    now merges over whichever provider the generator runs on.
  • Every preset pins an explicit effort on every row β€” no row inherits the global preset
    effort or a provider CLI default anymore. Routing changes alongside the new model ids:
    • mixed runs plan on Claude Code Opus 5.5 at xhigh (was Copilot Sonnet 4.6), and its
      refine moves from gpt-5.6-terra to gpt-6-luna at high.
    • mixed-economic's implement critic is now Codex gpt-6-luna at xhigh β€” a cross-provider
      gate (was Claude Sonnet at high).
    • The frontier family puts the vendor's top model on the deep flows at max: claude-frontier
      and mixed-frontier run plan / implement / ideate on Fable 5.1, codex-frontier on
      gpt-6-astra, and mixed-frontier's critic moves to gpt-6-astra. Light flows no longer
      inherit max: refine / readiness / ideate run at high and createPr at medium
      in every frontier preset.
    • codex-economic drops from gpt-5.6-terra at high to gpt-6-luna at xhigh, and
      codex-strong-gate's generator follows (the gate stays on the flagship, now gpt-6-sol).
    • The per-provider new-install defaults change for two backends: Copilot moves from GPT
      (gpt-5-mini / gpt-5.4) to Claude Sonnet 5 on refine, Opus 4.8 on
      plan / implement / ideate, and gpt-5.6-luna on readiness / createPr; Codex moves
      to gpt-6-luna on the light flows and gpt-6-sol on the deep ones.
  • Dependency maintenance. Routine dev-tooling and lockfile bumps (zod, @types/node,
    eslint-plugin-sonarjs, and others); TypeScript stays held at the 6.x line.

Fixed

  • Effort is now resolved explicitly for every flow, never left to the AI CLI's own default.
    Claude Code silently runs Opus 5.5 at medium effort when no --effort is passed β€” a
    regression from every earlier Opus, which defaulted to high β€” so ralphctl no longer relies on
    any provider's CLI default for an effort-capable row. create-pr --ai and review previously
    dropped their configured effort silently; both now thread it through to the AI session like
    every other flow.

Full changelog: v0.23.0...HEAD
npm: https://www.npmjs.com/package/ralphctl/v/0.23.0

v0.22.0

Choose a tag to compare

@github-actions github-actions released this 17 Sep 11:08
4598747

What's changed

Added

  • Grok Build CLI (xai-grok) as a fifth backend, joining Claude Code, GitHub Copilot,
    OpenAI Codex, and OpenCode. Install the grok binary, sign in with grok login, then
    ralphctl settings apply-preset grok-only (or pick xai-grok per flow). Catalog models
    are grok-4.6 (flagship) and grok-4.5. Doctor cannot check Grok login (no auth-status
    command). Readiness writes the shared AGENTS.md (same file as Codex and OpenCode; later
    writes keep a .bak.<timestamp> copy). Skills/agents live under .grok/. No
    grok-economic / fast / frontier / strong-gate presets; mixed was not rerouted onto Grok.

    Read-only flows deny edit and shell, while creating a file stays possible so signals.json
    can land. Grok has no write tool β€” Write and Edit are aliases of search_replace, the
    only tool that can create a file β€” so the edit gate is the permission rule --deny 'Edit(./**)',
    rooted at --cwd: the repo (or per-task worktree) is edit-denied while the session
    directory outside it, where grok-prompt.md and signals.json live, stays writable. Shell
    is gated twice, by removing both tool spellings (run_terminal_command,run_terminal_cmd)
    and by --deny 'Bash(*)', so a renamed tool id cannot slip through. A no-network session
    also removes web_search / web_fetch, and any closed gate adds --no-subagents. Grok has
    no --add-dir β€” extra roots stay a named over-grant (--sandbox off is forced so operator
    config cannot re-enable a workspace sandbox, and the edit rule is cwd-rooted, so an extra
    root stays writable even in a read-only flow). Because that edit rule is rooted at --cwd, a
    RALPHCTL_HOME pointed inside the repo would put signals.json under it; the adapter detects
    that topology, drops the rule rather than blocking the envelope, and logs the over-grant β€” a
    read-only flow there runs edit-capable. Both Grok surfaces now pass --trust:
    without it Grok skips the AGENTS.md and .grok/skills that ralphctl itself writes. Grok's
    folder trust is one grant, though β€” it also enables a checkout's own project permission
    rules, hooks and repo-local MCP/LSP servers, exactly as opening that repo in Grok yourself
    would, and Grok persists the decision in its trust store per folder (the repo and every
    per-task worktree path a run uses). Run ralphctl on Grok only against checkouts you would
    trust in Grok. Grok's flag surface and permission semantics are verified against
    Grok Build CLI 1.0.30's shipped CLI reference (2026-09-15); the minimum supported version is
    1.0.13, where the interactive -s lands.

    One thing an interactive Grok session leaves on disk is worth knowing about: it writes
    grok-debug.log beside the session's other artifacts β€” a stdio: 'inherit' child hands
    the terminal over and the harness can observe nothing about it, so when a session
    misbehaves that log is the only account of what happened, and it is pruned with the rest
    of the unit.

  • ralphctl sprint reopen <id> β€” the deliberate exit from an otherwise-terminal done
    sprint. Lands it back in review (idempotent β€” an already-review sprint passes through
    unchanged) and enforces the same single-active-per-project invariant as sprint activate, so
    a reopen can't collide with a sprint already live on the project. sprint close also gained
    -y/--yes to skip its new confirmation (see Changed) non-interactively.

  • Blocked work is now visible everywhere an operator looks, not just the task it happened to.
    Home's status card, the sprints list, the cross-project sprint picker, sprint-detail's header,
    the settled-run summary, and the Next steps block all now show a blocked count β€” including
    once a sprint is done, since unblocking there reopens it (see Changed) rather than leaving the
    count meaningless. Sprint-detail gets a B chord that cycles the cursor to the next blocked
    item; u (unblock) is now reachable from the Execute view's own tasks panel, not only
    sprint-detail and the sprints list, and once a run settles with a task left blocked the Execute
    view's hint strip names that chord instead of leaving it discoverable only through the ?
    overlay; and a blocked card can no longer be windowed off-screen. The Flows menu stops
    disagreeing with every other surface about an all-blocked sprint: where it used to advise
    running Plan for a sprint that already has a full task list β€” a flow the menu doesn't even offer
    at planned/active β€” it now says that every remaining task is blocked and unblocking one
    makes it runnable again. On the CLI, sprint progress groups blocked tasks by root cause
    instead of listing a whole cascade as equal-weight rows β€” an upstream-blocked chain collapses
    under the task that's actually broken, each with its reason and a ralphctl task unblock <id>
    hint β€” and task list prints a blocked task's reason plus a recovery hint the same way.

  • The generator can say what, specifically, it's stuck on. The task-blocked signal gains
    optional blockerClass (missing-information / ambiguous-request /
    contradictory-information), question (the one thing that, answered, unblocks it), and
    whatUnblocksMe. When the generator supplies them they're persisted on the task and shown
    alongside the reason in both ralphctl task list and the TUI, instead of free-form reason
    prose being the only clue. All three are optional β€” a plain reason-only block still works.

  • A block now raises a banner and an OS notification the moment a task is saved as
    blocked β€” whether an attempt settled that way, a parallel task's worktree could not be set up,
    its branch hit a fold conflict, or a resumed run found the task's attempt budget already spent.
    Previously the only signs were the Tasks panel and progress.md, which meant an unattended run's
    most common failure mode was also its quietest.

Changed

  • Both doors to done now confirm before closing over blocked work, naming the tasks.
    Closing a sprint has always been able to proceed with blocked tasks left in it β€” that's still
    true, this is a confirm, not a refusal β€” but neither path used to say so. sprint close (the
    TUI launcher and the CLI command) and the review flow's auto-done transition (an empty or
    repeated feedback round) both now load the sprint's tasks and, if any are blocked, ask first. In
    the TUI the pre-flight confirm folds in a blocked/todo count and the in-chain gate names each
    one; on the CLI, sprint close prompts with the same names (-y/--yes skips it) and, once
    the close proceeds either way, prints which tasks stayed blocked and how to recover them.

  • Unblocking a task now archives its history instead of erasing it. A clean restart still
    resets the attempt budget and drops the block classification and escalation stamps, exactly as
    before, but the cleared attempts, per-criterion verdicts, and escalation stamps are now packaged
    into one entry on the task's new retiredAttempts list rather than discarded β€” so
    ralphctl runs stats and the TUI's outcome card keep counting a task's full attempt history
    after an operator intervenes, not just what happened since the last unblock. The archive survives the
    revived task passing, and runs stats folds those runs into everything it reports: a task that
    failed three times, was unblocked and then passed counts as a four-attempt task, not a first-pass
    one, and a retired attempt's model and effort rungs count as granted and fell-through, so the
    attempt totals, the first-pass rate and the escalation rows no longer disagree about a task that
    was unblocked. Existing tasks.json files load unchanged; nothing
    needs migrating.

  • Unblocking a task on a done sprint reopens it (done β†’ review β†’ active) instead of
    reviving a task with nowhere to run β€” closing a sprint with blocked work is a legitimate
    descoping call, but it shouldn't make that work permanently unreachable if someone later
    supplies what it needed. The reopen obeys the same single-active-per-project invariant
    sprint reopen does, rather than walking around it: when another sprint of the project is
    already active or in review, the task is still revived but the sprint stays done, and the
    operator is told so: the CLI prints a note naming the peer that holds the project and the
    ralphctl sprint close that releases it, sprint-detail's u appends the same reason to its
    toast, and the Sprints list's bulk u counts how many sprints stayed closed instead of
    reporting N/N. Whenever an unblock does reopen a sprint, the CLI and the TUI toast say so
    (done β†’ active). A reopen that fails for any other reason (the sprint can't be read or saved)
    fails the unblock and leaves the task blocked, so a plain retry works. Unblocking a task that is
    already todo never reopens a closed sprint β€” nothing is revived, so the close stands. Two sprints of one project can never both hold the working tree β€” their repo locks
    key on the sprint directory, not the project, so they would not mutually exclude.

  • Prompt templates reworked against Anthropic's prompt-engineering guidance. New shared
    partials β€” instructing autonomous operation (decide and proceed instead of asking a question
    nobody is there to answer; a turn that ends on a plan instead of the tool calls that execute it
    is indistinguishable from a turn that did nothing), batching independent tool calls in one turn,
    bounding how much command output gets quoted versus written to a file, an evaluator
    failure-modes checklist (resist being talked out of a finding, rubber-stamping a green verify
    script, and inventing a defect with no evidence), and a mid-run evaluation-checkpoint shape β€”
    now back implement, implement-continuation, evaluate, evaluate-continuation, and
    reproduce; task-field and task-sizing guidance is likewise shared between `...

Read more

v0.21.0

Choose a tag to compare

@github-actions github-actions released this 24 Aug 20:40
4f57691

What's changed

Changed

  • Curated Claude presets no longer default to Haiku 4.5. Haiku 4.5 faces an Anthropic retirement
    horizon with no Haiku 5 successor, so every cheap-flow row that pinned it β€” refine, readiness,
    createPr (and ideate where it applied) across claude-economic, claude-strong-gate,
    claude-fast, and mixed-fast β€” now runs Sonnet 5 pinned at low effort, Claude Code's designated
    cheap tier. The effort is pinned explicitly rather than inherited, so the light rows keep the saving
    they exist for. Haiku stays fully selectable as a model; what changed is the curated preset defaults.
    Existing settings.ai files are untouched β€” only newly applied presets pick up the new rows.

Full changelog: v0.21.0...HEAD
npm: https://www.npmjs.com/package/ralphctl/v/0.21.0

v0.20.0

Choose a tag to compare

@github-actions github-actions released this 21 Aug 19:46
4a6a3d7

What's changed

Added

  • ralphctl runs stats β€” the harness outcome rollup. A read-only report over the sprint data
    ralphctl already persists, answering what used to be unanswerable: the done / done-with-warning /
    blocked mix, first-pass rate, attempts-to-done distribution, plateau rate by source, which
    escalation rung resolved each stall versus fell through, the failed-dimension histogram, and
    per-criterion pass rates. It also reports the regression taxonomy: how many attempts broke a
    green baseline (split clean / fixed-baseline / baseline-broken / unattributed), the full
    warning breakdown by kind instead of one collapsed "done with warning" counter, and abort causes,
    so an operator Ctrl-C is distinguishable from rate-limit exhaustion. Task-based and attempt-based
    rates sit in one report, each labelled with the denominator it is quoting. Scope with
    --sprint <id>, --project <id>, or --since <date>; --json emits the raw rollup for machine
    diffing, so a prompt or settings change can be measured before/after on the same task population.
  • Sprint outcome card in the TUI. Once a sprint reaches review or done, its detail view shows a
    compact outcome report β€” task mix, regressions, warnings by kind, aborts (when any), first-pass
    rate, plateaus, escalation rungs that fired, and criteria pass rate β€” from the same rollup, so the
    TUI and runs stats can never report different numbers. A sprint with a regression takes the
    card's error tone.
  • Attempts now record what they cost. Each settled attempt persists the provider-reported
    inputTokens / outputTokens and the AI-spawn wall-clock durationMs (absent β€” not zero β€” when a
    provider reports no usage; older records load unchanged).
  • Deterministic plan-critic check. A new zero-token pass runs between the AI's proposed task list
    and the human approval gate, catching task-graph faults, an unknown repository, missing verification
    criteria, missing auto commands, placeholder/prose/multi-line commands, and duplicate criterion
    ids. Findings are advisory β€” they're shown above the "Approve plan?" prompt and never block the
    chain; the operator still decides.
  • Doctor now probes provider authentication for all four AI CLIs, not just Codex. Claude Code and
    Codex answer via their own auth status / login status verbs; OpenCode reports whether it has a
    saved credential (its free tier needs none); GitHub Copilot exposes no non-interactive auth-status
    verb, so its row reports the new unknown status β€” never a guess, never a failure.
  • ralphctl demo β€” seeds a throwaway sandbox project (three sprints, one per pre-flow state) and
    launches straight into the TUI, no provider CLI or auth required to look around. --no-launch seeds
    only; --home <dir> relocates the sandbox; --script replays a canned generator β†’ evaluator
    transcript through the real Claude adapter instead of spawning a real CLI, for a fully reproducible
    first-run recording.
  • You can finally read the evaluator's verdict. Every evaluator round has always written an
    operator-readable evaluation.md next to the task's round artifacts β€” the critique, and each
    dimension's pass / fail / n-a with its finding and any command output β€” and nothing in the TUI or
    the CLI ever opened it. A failed attempt read eval failed Β· attempt 2 and stopped there. Press
    v on the focused task, in the Execute tasks panel or on a sprint-detail task row, and the file
    opens in a read-only overlay you can scroll (same chords as the g progress overlay; Esc or v
    closes). ralphctl task evaluation <taskId> prints the same file for scripts and pipes, with the
    attempt / verdict / path header on stderr so > verdict.md yields exactly the artifact.
    Older sprints stay readable: a task whose record predates the artifact, or whose workspace has been
    pruned, degrades to the one-line verdict it shows today β€” never an error.
  • ralphctl prompts list β€” renders every bundled prompt template through the real runtime
    resolver and reports what loaded, so a broken bundle is visible before it breaks a run. CI now
    runs it against the built package on every push, and the release workflow packs and installs the
    tarball and smokes the binary before anything is published.

Changed

  • Preset matrices refreshed ahead of the gpt-5.4-mini retirement (2026-08-31). Every curated
    cheap-tier row on openai-codex and github-copilot β€” including the older gpt-5-mini rows β€”
    now points at gpt-5.6-luna, so no shipped preset stamps a model that stops answering on a known
    date. Two role-fit corrections ride along: mixed and mixed-frontier now grade their Claude
    Opus generator with an independent gpt-5.6-sol evaluator, matching the cross-provider implement
    split the shipped defaults already use, and claude-only moves readiness off Haiku onto Sonnet 5.
    mixed also drops refine to gpt-5.6-terra; the frontier family stays flagship-everywhere.
    Presets are one-shot snapshots, so this only affects an apply from here on β€” a stamped config on
    disk is untouched.

  • A finished run now tells you what to do next. The settled outcome card ends with a Next steps
    block β€” the recommended flow for the sprint's current state, with the key that launches it β€” and a
    failed or cancelled run adds a Post-mortem block listing the artifacts it actually left on disk
    (progress.md, the trace, verify logs, the sprint directory). Every path is existence-checked
    before it is printed, and a run with no sprint of its own β€” a create-sprint that failed before
    creating one β€” shows no paths rather than a guessed one. The settled key set grows to
    ↡ home Β· r re-run Β· g progress; r returns to Flows, which re-checks every launch trigger
    against the sprint's status as it stands now, so a sprint that moved on during the run offers the
    flow that follows rather than a stale repeat.

  • Home and Flows now give the same recommendation, checked against the flow menu's own rules. The
    two screens derived their "next action" separately and disagreed on four of seven sprint states.
    Home's advice at review pointed at create-pr, a flow the Flows menu hides in that state, and it
    said nothing at all once a sprint was done; Flows recommended implement where no task was left
    to run. Both now read one table, review offers the two flows that are genuinely available there,
    and done points at the pull request.

  • Provider port conformance suite. Every headless and interactive AI adapter is now driven over a
    scripted, in-process child process and checked against the same contract table, catching port
    regressions (a dropped root, a prompt inlined into argv, a missing kill rung) at pnpm test instead
    of in a live session. InteractiveProviderSpec.buildEnv now receives the engine's fully-resolved
    session context (the same mounted-root list buildArgs sees) and returns a Result β€” a refused
    grant spawns nothing and logs nothing, rather than silently mounting less than the caller asked for.

  • Releases are gated harder before they reach npm. The packaged-install smoke now boots real
    subcommands (skills list, agents list) under a throwaway home instead of only --version, which
    answered before the bundled prompt/skill/agent assets were ever checked β€” the exact blind spot that
    let the 0.15.0 fresh-install break ship. The release pipeline also validates the changelog section
    for the version before publishing (a missing or empty heading now fails the release instead of
    silently substituting a git log), and runs the same coverage floors and dead-code check as CI β€”
    floors that now cover the TUI, previously excluded from measurement entirely.

  • Welcome view holds on the zero-CLI warning. When first-run setup detects no AI CLI on PATH, the
    view used to auto-route away in the same tick the warning rendered, so it was never actually
    readable. It now waits for ↡ / space / Esc before continuing.

  • A stuck task now samples two candidates before giving up. settings.harness.bestOfNCandidates
    ships enabled at 2 (was 0, off): when a task has already exhausted the model ladder and the
    same-model change-of-approach nudge, it gets one more attempt that samples two candidate solutions
    instead of one and keeps the better β€” selected by verification first, then by judging β€” rather than
    settling done-with-warning right away. The rung fires at most once per task and only for tasks that
    got that far, so the extra spend is bounded to one doubled attempt. To turn it off, set
    harness.bestOfNCandidates to 0 (TUI Harness settings or
    ralphctl settings set harness.bestOfNCandidates 0); the four *-economic presets now pin it to
    0 for you, so cost-sensitive setups keep the previous behaviour by applying one of them.

  • The two in-loop plateau detectors now follow your harness.plateauThreshold. The
    fingerprint-repetition and action-entropy checks that run right after each evaluator turn used to
    use a hardcoded three-turn window (entropy: a single turn) and ignored the exemptions the main
    plateau predicate applies, so they could end a loop earlier than you asked for β€” and precisely
    where the calibrated predicate had judged the run to be making progress. Both now window from
    harness.plateauThreshold and only speak when the work-product fingerprint is unchanged and the
    evaluator's critique has not shifted across that window: an AI that keeps editing the tree, or an
    evaluator raising genuinely new complaints, is no longer cut short. The trade is deliberate β€” a
    loop that is stuck in a way only these detectors can see may now run on to its turn budget instead
    of wrongly burning an escalation rung plus a whole attempt; a genuinely stalled loop still exits at
    your plateauThreshold, now attributed to the main predicate rather than t...

Read more

v0.19.0

Choose a tag to compare

@github-actions github-actions released this 11 Aug 05:49
f8774db

What's changed

Added

  • New provider backend: OpenCode (opencode), joining Claude Code, GitHub Copilot and OpenAI Codex β€”
    and with it, effectively any model you can reach. OpenCode is vendor-neutral: it fronts 75+ model providers
    (Anthropic, OpenAI, Google, Bedrock, Azure, OpenRouter, Groq, DeepSeek, Mistral, …) plus local runtimes
    (Ollama, LM Studio, llama.cpp) on a bring-your-own-key model, so the harness is no longer limited to the
    three vendors it ships adapters for.
    Set it per flow (ralphctl settings set ai.<flow>.provider opencode) or stamp every flow at once with the
    new opencode-only preset. Two things make it different from the other three:

    • It runs with no credentials, if you want. Alongside your own keys, OpenCode ships a free tier, so a
      fresh install can drive a real ralphctl session without signing in to anything β€” useful for a first look
      and for CI jobs without secrets.
    • It aggregates other providers. Model ids are namespaced as <provider>/<model> (e.g.
      opencode/big-pickle on the free tier), and the reachable set depends on which upstream providers you
      have authenticated via opencode providers login. The model picker asks the CLI (opencode models) instead
      of reading a fixed list, so authenticating a provider makes its models selectable with no ralphctl
      upgrade.

    Sessions resume across gen-eval rounds, and a stale session id falls back to a cold spawn rather than
    failing the task. Skills install to .opencode/skills/, agent definitions to .opencode/agents/, and
    readiness writes the shared AGENTS.md. Limitations worth knowing: opencode run has no read-only mode, so
    a READ_ONLY flow is not sandboxed by the CLI (path topology is the boundary, as it already is for OpenAI
    Codex); it has no multi-root flag, so on the headless path external-directory access is auto-approved
    wholesale rather than mounted per root, and on the interactive path a multi-root project's extra roots are
    not mounted at all (tracked in #278); effort is forwarded only on the headless run path (--variant), never on the interactive
    TUI path; and plateau escalation skips the effort rung for OpenCode, since the accepted --variant levels
    belong to the upstream vendor behind your model id.

  • create-pr's AI-authored PR content now leaves the same meta.json attribution sidecar every other
    AI-authoring flow (refine / plan / ideate / readiness) already writes
    β€” a provider/model/effort
    record next to the round's prompt.md, so a create-pr run is no longer the one flow with no
    attributable trace of which provider and model authored the PR content.

  • Implement retries now include a summary of the task's best prior attempts, selected and ranked
    automatically.

  • Progress journal entries now include an auto-derived "Continuation state" block (verify outcomes,
    attribution, resumed-after breadcrumb).

  • Implement now runs a reproduction-first step for bug-fix tasks: before the generator's first turn, a
    harness-verified failing test demonstrating the reported defect is written and handed to both the
    generator and evaluator, along with the existing tests judged relevant to the issue.

  • New opt-in settings.harness.bestOfNCandidates (2-4, default off) grants one best-of-N
    candidate-sampling attempt at the top of the plateau escalation ladder β€” sampling N candidates on the
    unchanged model and selecting among them by verification then judging.

  • Evaluator reasoning effort now escalates in lockstep with every generator model-rung climb, not only the
    same-model effort nudge.

Fixed

  • AI sessions no longer die with spawn ENAMETOOLONG on Windows. The rendered prompt was passed to the
    CLI as a command-line argument, and Windows caps a command line at 32,767 characters β€” which a plan or
    refine prompt reaches on its own once a sprint has some history behind it. The session failed before the
    CLI had started, with nothing in the error pointing at the cause. The prompt now stays in the file the
    harness already writes and the CLI is pointed at it, so command-line size no longer tracks prompt size.
    Affected every interactive flow (plan, refine, ideate, learning-distill) on all four providers, plus
    headless GitHub Copilot. Two related failures were fixed alongside it: a spawn that failed synchronously β€”
    which is how Windows reports this β€” escaped as an unhandled exception instead of failing the round, and an
    oversized command line was retried until the attempt budget ran out even though every retry rebuilt the
    same command. OpenCode needed one extra step, since it has no --add-dir and refuses paths outside its
    project directory: it is now granted read access to the prompt file's directory alone, layered onto your
    own OpenCode config rather than replacing it. Copilot in headless mode gets the same treatment, since it
    is the one CLI that cannot take a prompt on stdin.
  • The OpenCode free-tier default no longer points at a model that refuses every request.
    opencode/north-mini-code-free returns an upstream 401 while its free-tier siblings serve normally, and
    it was the shipped light-tier default in both the per-provider defaults and the opencode-only preset β€” so
    a first run on OpenCode's free tier failed on every flow. The default is now
    opencode/deepseek-v4-flash-free. Note that opencode models still lists ids that no longer serve, so
    enumeration is not a health check; if a free-tier model starts failing, pick another from that list.
  • Interactive AI sessions now honor the configured reasoning effort. refine, plan, ideate, and
    the learning-distill step all hand the terminal over to an interactive AI session, and that path
    silently dropped effort for all three provider CLIs β€” a high or xhigh setting had no effect once
    the session started. Effort now reaches Claude Code, GitHub Copilot, and Codex alike.
  • sprint close from the CLI now produces the same on-disk state as the TUI. The CLI command
    previously transitioned the sprint directly, skipping the memory-mirror refresh, the opt-in
    learning-distill step, and the progress.md closed-separator line the TUI's close-sprint flow runs β€”
    closing a sprint from the CLI silently forfeited all three.
  • OpenAI Codex's stdout parse buffer is now capped like every other provider's. An unterminated
    oversized NDJSON line (a large tool-result embedded in Codex's stream) could grow the in-flight
    line-parse accumulator without bound β€” the same OOM-class issue fixed for Claude and Copilot in 0.18.0,
    which Codex had not picked up. It now reuses the shared capped line-feed the other three adapters use,
    so all four providers behave alike.
  • A gen-eval attempt's action-kind tally no longer leaks into the next attempt. The per-attempt context
    reset is now type-enforced, so the entropy plateau check always starts from a clean count on a fresh
    attempt instead of occasionally inheriting the previous attempt's tally.

Changed

  • Provider membership checks (settings set ai.<flow>.provider, the --implement-<role>-provider CLI flags,
    the TUI Settings view, the per-launch customize picker) now read one domain-owned list derived from the
    settings schema instead of four hard-coded copies. The copies still type-checked as readonly AiProvider[]
    after a provider joined the union, so nothing caught the drift; a liveness suite now asserts every provider
    in the union is settable and offered.
  • Large internal refactor with no user-facing behavior change: ESLint's layering fences now compose
    instead of silently overriding one another, the three interactive provider adapters share one session
    engine and the three headless adapters share one stream-debug emitter, and the CLI's error reporting,
    the task-scheduling rule tables, the TUI's view routing and provider dispatch, and the windowing logic
    behind every scrollable list were each consolidated onto a single shared implementation.
  • Prior-learnings injection now scores relevance to the current task and abstains when nothing qualifies,
    instead of injecting on repo/kind match alone.
  • Learning ledger now merges near-duplicate entries (with supersedes provenance) instead of growing
    unbounded.
  • Implement / plan / evaluate prompts sharpened: reproduce-before-fixing check, periodic phase recitation,
    plan-quality gate, contrastive learning capture, evaluator execution-evidence requirement, structured
    spec shape in planning.

Full changelog: v0.19.0...HEAD
npm: https://www.npmjs.com/package/ralphctl/v/0.19.0