跳到正文
GitHub·· 7 天前AI 评分62

enallagi 发布单二进制编码智能体任务循环工具

thmsmtylr/enallagi

AI 导读

enallagi 是一个以单个静态二进制分发的自主任务循环工具,读取任务队列并逐个执行,每个任务都在全新的智能体进程中运行而非长期会话。它把工作拆给五个不能互相评分的角色,每次 done 结论都从代码树重新推导而非采信声明,每条泳道在独立 git worktree 中运行并在成功后快进。

正文

The fractional harness that could.

An autonomous task loop for a coding agent, in one static binary.

Highlights

  • Reads a queue of tasks and works them one at a time.
  • Runs each task in a fresh agent process, never a long-lived session.
  • Splits the work across five roles that cannot grade each other.
  • Re-derives every done from the tree instead of trusting a claim.
  • Runs each lane in its own git worktree and fast-forwards on success.
  • Wraps any headless agent CLI, with thirteen presets shipped.
  • Pins every vendored skill by commit and hash.

Install

curl -fsSL https://raw.githubusercontent.com/thmsmtylr/enallagi/main/install.sh | sh

From source:

cargo install --locked --git https://github.com/thmsmtylr/enallagi enallagi

Releasing is one procedure, stated in .github/workflows/release.yml.

From install to a landed task

docs/setup.md walks the same path on a real repository, step by step.

enallagi init                  # one pass: detects the check, asks what it cannot decide, writes and commits everything
enallagi init --yes            # or takes every default, as a stdin that is not a terminal does

Turn an issue into a task:

enallagi issue owner/repo#12   # appends a proposed block to .enallagi/TASKS.md; `init --issue <url>` does the same

The block quotes the issue in notes:. The first run's adjudicator writes what done means and sets it ready; $EDITOR .enallagi/TASKS.md does the same by hand.

Or write a task into .enallagi/TASKS.md by hand:

## [T-001] the date parser drops a timezone
scope: src/date.ts, src/date.test.ts
blockedBy:
status: ready
rows: none — harness
criteria:
  - `npm test -- date` passes with a case for `+10:00`
notes:

Run it:

enallagi run --pipeline task --iterations 1   # one task, in this checkout
enallagi worktree 1                          # or one task, in its own worktree
enallagi watch                               # attach read-only to the live loop
enallagi pr T-001 --push                     # one pull request for the landed task
enallagi run --pr-per-task --iterations 3    # or one pull request per task, opened as each lands

--pr-per-task stacks a task on the branch of a blocker landed earlier in the same run.

How a run works

Each iteration takes the first ready task whose blockers are done.

  • The implementer edits only the paths on the task's scope: line.
  • It commits, writes its notes, and sets the task to review.
  • The verifier reads the criteria and returns done or a rejection.
  • Gates then re-run behind that verdict and can overturn it.

A done the gates disagree with goes back to ready. A question the criteria do not answer becomes needs-spec and halts the run.

enallagi run --pipeline task runs only the pipeline named. Repeat the flag to name more than one. With none named, every pipeline in .enallagi/enallagi.toml is eligible.

The pipeline, gate, probe, key and file tables are in docs/reference.md. Changing a skill, a pipeline or a stage is in docs/pipeline.md.

Configuration

.enallagi/enallagi.toml holds the whole configuration. Every key and its default is in docs/configuration.md.

enallagi init writes only the keys whose value differs from the embedded defaults. A key left out takes its default.

A re-run names every key that still equals one. enallagi init --prune-defaults deletes those keys.

A first enallagi init also detects the test runner from the files the repository already carries. Seven runners ship: cargo, node, bun, vitest, jest, pytest and go. Detection writes check.command, check.fail_name and the layout test keys.

Each detected value is printed with the file:line it came from. A tree that matches more than one runner keeps the defaults and names the candidates. A tree that matches none has the agent propose a check, written only once the check proves it.

  • agent.preset names the CLI to drive, or custom with your own agent.command.
  • agent.model and agent.effort set defaults. A role or a task can override both.
  • A claude lane runs sandboxed with edits accepted, so it needs no bypass flag. See docs/configuration.md.
  • agent.dangerously_skip_permissions adds the preset's bypass flag to every lane. Default false.
  • enallagi run --dangerously-skip-permissions does the same for one run. A preset that declares no bypass flag refuses the run.
  • run.start records the choice as permissions_skipped, and enallagi events prints it.
  • check.command is the single command that decides green.
  • [[skill]] declares a skill to vendor, with its rev and the gate that enforces it.

Budgets come from the environment. Set BUDGET_USD, BUDGET_SECONDS, or BUDGET_TOKENS. BUDGET_TOKENS counts every token lane [agent.usage] names, cached reads and cache writes included.

Commands

  • init installs into a repository. eject removes it and keeps the record outside it. Both commit one change to the product's .gitignore: init adds /.enallagi/, and eject removes it.
  • run drives the pipelines in place. worktree drives them in an isolated checkout.
  • run prints its version and build commit first, and binary predates HEAD when HEAD descends from that commit.
  • watch attaches to a live loop. events queries the log. Each event carries sha, the product HEAD, and run.start carries binary.
  • events --summary prints one row per task: stages, verify rounds, rejections, overturned verdicts, seconds, cost and token lanes.
  • tasks reads and edits the queue. base prints the commit a task was queued against.
  • tasks landed lists each done task, its commits, and no branch, built <branch> or pushed <url>. --built keeps the branches waiting on a push.
  • issue appends a GitHub issue, and review a pull request's review comments, as proposed tasks.
  • probe reports findings. gate runs one gate. hook is the agent's lifecycle entry point.
  • audit proposes a learning for each class of finding that recurs. skills resolves declared skills. eval runs the evals.
  • pr builds a pull request. It builds a task whose commits conflict with the default branch on the newest task/<id> branch, built this run or on the remote, that changed a conflicting file and takes the commits, and its description names that task. A blockedBy: task whose branch is on the remote is a base the same way. When no branch takes the commits, the refusal names the conflicting files.

enallagi pr --push reads the target's contribution guide first. A sentence there that refuses or conditions generated changes stops the push.

Pass --policy-read once you have read it. enallagi pr records either outcome in the description file, and commits it under <harness directory>/pr/.

Run enallagi <command> --help for the flags.

License

MIT

来源:GitHub · github.com