github uditgoenka/autoresearch v2.3.0
v2.3.0 — pi, Muse and Fork-and-Flush

3 hours ago

What's new in v2.3.0

Highlights

pi extension (#122, thanks @jbanety)

  • autoresearch now runs in the pi coding agent. The extension ports the Claude hooks to pi events: scout, privacy and dangerous-command blocks, iteration context, dev rules, simplify gate, session init, stop notification and subagent context.
  • Every hook fails open and honors the same AR_DISABLE_* env flags as the Claude hooks.
  • The 14 autoresearch commands ship as pi prompt templates (/autoresearch, /autoresearch_debug, ...). The dispatcher is a pi skill (/skill:autoresearch).
  • Subagent context works with the pi-subagents extension when it is installed, and is skipped when it is not.
  • The pi bundle is generated from .claude/ by scripts/transform.sh --pi, like the OpenCode and Codex ports.
  • Install: ./scripts/install.sh --pi --global, or pi install git:github.com/uditgoenka/autoresearch.

Muse support (#124, thanks @zorrobyte)

  • Muse is now a supported harness. scripts/transform.sh --muse generates .muse/skills/autoresearch from the canonical .claude source. Commands are merged into the skill directory. Muse has no hooks.
  • scripts/install.sh --muse installs it. Global installs use MUSE_CONFIG_DIR, then XDG_CONFIG_HOME, then the default. Local installs use .agents/skills.
  • New tests/test-install.sh suite. release.sh now runs it and checks Muse version parity.

Fork-and-flush rounds (#126, thanks @philipk19238)

  • When a metric loop stalls inside one family of ideas, autoresearch now forks K fresh-context branches from the best commit (default 4), runs each for a short budget, and keeps the best. This follows "Fork-and-Flush: Escaping Idea Basins in Autoresearch Agents" (Cai et al.).
  • Rounds run at 33% and 66% of the iteration budget (50% when N is under 12, every 20 when unbounded). A round also runs after 5 iterations with no keep; it replaces the next scheduled round.
  • Branches are random or guided. A random branch gets only the task. A guided branch gets one experiment from a stateless Advisor that reads the results TSV and git log and never edits files. Guided: R sets the split; the default 0.5 gives 2 + 2 at K = 4. Guided: 0 is plain fork-and-flush.
  • orchestrate.sh verdict returns FORK (with ship=no) before PLATEAU while fork_rounds_since_progress is under 2. After 2 rounds with no progress it returns PLATEAU.
  • Flags: --no-fork turns rounds off. Forks: K sets the branch count (use 2 for slow or shared-resource Verify commands).

Behavior-preserving optimization reference (#114, thanks @64andrewwalker)

  • New reference for performance goals: latency, throughput, runtime, CPU, memory, allocation, binary size, power, bandwidth and compute cost.
  • It separates the working search metric from final acceptance. A keep marks a better exploratory result, not proof that behavior survived.
  • It asks for independent guards that fail on a known-bad change, held-out or adversarial confirmation, comparable provenance, resource limits and rollback.
  • Routed from the skill router, the classic loop and the plan command, and copied to the Claude, Codex/Agents and OpenCode mirrors.

Fixes and hardening

Orchestrator

  • Goal classification matches keywords at the start of a word. "prefix" is no longer read as "fix", and "address" is no longer read as "add". Compounds such as debug, hotfix, bugfix and rebuild still match.
  • A metric target of 0 is detected numerically, so 0.0 and similar forms no longer cause a divide-by-zero.
  • screen-cmd now refuses:
    • curl or wget piped through sudo, env and similar launchers into a shell or interpreter;
    • process substitution such as bash <(curl ...) and source <(curl ...);
    • sh -c "$(curl ...)" and eval "$(curl ...)";
    • abbreviated rm long options such as --rec and --for.
  • Every database URL in a command is checked. A safe first URL no longer vouches for a second one.
  • A password with & in it, or a quoted user name, no longer hides the database host from the check.
  • bash --noprofile -c "$(curl ...)" and other interpreter flags before -c are refused too.
  • A goal that starts with "debug" routes to fix-broken. "add debug logging" stays a build goal. "redeploy" routes to ship-ready and "reimplement" to build-feature.
  • Database URLs are now read by an allow-list. Only localhost, 127.0.0.1 or a plain container name (starting with a letter) count as local. Any other host needs a database name ending in _test or _ci.
  • URLs the check cannot read safely are refused: % encoding, several hosts, a backslash, two @ signs, quotes inside the URL, an empty host, and the host, hostaddr, dbname and service query keys.
  • Destructive commands are caught after ;, &, |, ( and backticks, and when the name is quoted or escaped ('rm', \rm).
  • Brace lists ({rm,-rf,/}) and $IFS spacing (rm${IFS}-rf${IFS}/) are read the way bash runs them. $'...' quoting is refused.
  • The curl, launcher, process-substitution and dd checks also see quoted names, such as sudo "bash" and of="/dev/sda".
  • A quoted or escaped URL scheme ('postgres'ql://), an empty URL, a ? or # before the @, a # anywhere in the URL, and a database name built from $ or wildcards are refused.
  • Variables, command substitution and brace lists can build any command name ($X, ${X}m, r``m, `printf rm`, r{m,}), so screen-cmd now refuses them as a whole kind. It reads quotes the way bash does, so escaped quotes and quotes inside quotes cannot hide them.
  • The command checks also stop at < and >, so rm>x -rf / and bash<<<"rm -rf /" are seen.
  • A glob in a command name (r? -rf /, sudo /bin/r[m]), $"..." strings, a backslash before a newline, control bytes and env -S are refused as whole kinds. A script passed to bash -c, sh, su -c, . or eval is screened on its own, and an escaped \$ or backtick next to one of them is refused. A glob after sudo option values (sudo -u root /bin/r?) or after if, then and do is caught too.
  • The find -delete, chmod -R 000, truncate -s 0 and curl-to-shell checks also see a separator right after the command (find / -delete;true).

pi extension

  • Ignore patterns treat regex characters literally. Bracket classes still work.
  • rm long-option prefixes are blocked, as in the orchestrator.
  • Quotes in the Windows toast notification are escaped.
  • A heredoc body is checked when a shell reads it (bash <<EOF, cat <<EOF | sh). A quote in the body cannot hide the lines after it.
  • A heredoc end word the check cannot read safely (split by a backslash-newline, or holding $, a backtick or a carriage return) no longer hides the commands after it.
  • A heredoc ends only on a line that equals its end word exactly, and several heredocs on one line end in order.
  • A redirect before the command name (<<EOF rm ..., 2>/dev/null rm ..., <>f rm ...) no longer hides the command. The redirect target is still checked by the privacy and scout hooks (<.env cat).
  • &> is checked both the way bash reads it (a redirect, so rm &>/dev/null -rf / is caught) and the way sh reads it (run in the background, then a redirect).
  • Ignore patterns with a leading / now match from the project root.
  • install.sh --pi --global reads PI_CODING_AGENT_DIR, the variable pi uses.
  • The pi guardrail tests now run on Windows: temp paths use the C:/ form, and test snippets use import instead of require.
  • Blocked file paths are no longer written to the hook log.
  • A subagent started in a subfolder still finds the run's results file.

Upgrade notes

  • Claude Code: claude plugin marketplace update autoresearch && claude plugin update autoresearch@autoresearch
  • Codex: npx skills update
  • pi: ./scripts/install.sh --pi --global, or pi install git:github.com/uditgoenka/autoresearch
  • Muse: ./scripts/install.sh --muse
  • Fork-and-flush is on by default for every metric loop. It costs more. Each round runs K sub-agent branches (default 4), each for max(2, round(0.06 × N)) iterations, so one round at K = 4 is about 24% of the loop's iteration budget. With the two scheduled rounds, that is roughly half the budget again, plus any early rounds after 5 iterations with no keep. Each branch also uses its own worktree. To lower the cost, set Forks: 2. To turn it off, add --no-fork. Turn it off for mechanical sweeps, or when one Verify run is slow or uses a shared resource.
  • Goal classification changed. A goal that relied on a keyword inside a longer word may now route differently.
  • Commands that the orchestrator now refuses (remote scripts run through launchers or process substitution) need to be run by hand.
  • screen-cmd now refuses some harmless commands to stay on the safe side. A loop that ran them before will now stop with refuse. Run these by hand:
    • any backtick, and any $ outside single quotes that is followed by a name, a digit, {, ( or a quote. This covers npm test $FILE, cd "$HOME", echo $(date) and printf $'a\nb'. A $ right before a closing double quote, a space or the line end is fine (grep "ok$" log), and so is anything inside single quotes;
    • a brace list outside quotes, such as cp file{,.bak};
    • a glob in a command name (./build-*.sh), a backslash at the end of a line, and env -S. Globs in arguments (ls *.txt) are fine;
    • a $ or backtick inside the script given to bash -c, sh -c or eval, such as bash -c 'echo $HOME'. When a command runs a shell or eval anywhere, every quoted part is checked as a command, so bash run.sh '*.ts' and bash x | awk '{print $1}' are refused too;
    • a glob in any word after a launcher such as sudo or nice (nice -n 19 ls *.txt);
    • a database name with $, {, }, *, [ or ~ in it, even on localhost (postgres://localhost/$DB);
    • a database URL with # anywhere in it, or ? before the @, even when they are only part of the password;
    • a database URL with an empty value, or a quoted URL that contains a space.
  • screen-cmd is extra protection, not a security wall. It matches text patterns, and shell commands can be written in endless ways, so some risky commands will still get past it. Keep reviewing what the loop runs, and keep production credentials out of reach of the agent.
  • Known limit: a database URL with a dotted user name and & in the password (for example postgres://first.last:p&ss@localhost/app) is refused even on localhost. Run it by hand.
  • Known limit: screen-cmd reads the host from the URL only. A host set by PGHOST, PGHOSTADDR, PGSERVICE or psql -h, or by a host= connection string, is not checked. It also reads only lower-case postgres:// and postgresql://, so POSTGRES:// and postgresql+psycopg:// are not checked.
  • Known limit: the nested-script check knows sh, bash, zsh, dash, ksh, fish, source, su, . and eval. Other programs that run a command or script for you (ssh, watch, xargs, find -exec, setsid, flock, chroot, csh, tcsh) are not looked into, and neither is text built at run time and piped into a shell (base64 -d x | sh).
  • Known limit: goal keywords now match only at the start of a word. A goal such as "undocumented API" no longer routes to the document archetype, and "fixture" still reads as "fix".

Contributors

Thank you to:

Full change: v2.2.3...v2.3.0

Don't miss a new autoresearch release

NewReleases is sending notifications on new releases.