Skip to content

Releases: coe0718/diaktoros

v0.3.0: reviews you can hold to account

Choose a tag to compare

@coe0718 coe0718 released this 10 Oct 23:37
777458f

Diaktoros v0.3.0: reviews you can hold to account. One agent reviews a PR, another fixes what it finds, unattended; rounds are capped, disputes are adjudicated, and the loop never merges. This release makes every verdict accountable: findings are numbered and tracked across rounds, a block must cite the diff, the reviewer checks the linked issue's requirements, and the adjudicator rules on the head's real CI. Red CI gets its own budget, small issues reach the fixer on their own, an install can be backed up and restored, and hermes dk show lists every setting and where it came from. 61 pull requests since v0.2.0.

hermes plugins install diaktoros
hermes dk setup --repo owner/name

The catalog serves v0.3.0 once its re-pin PR merges. Until then, install this release directly:

hermes plugins install coe0718/diaktoros --ref 777458fb0ab7cdcea7fe4b2c032f6eebcb83b52e

Findings you can track

  • Findings are numbered and followed across rounds (#506, #534). A blocking finding is F1: path: what is wrong. Every later review states each open one fixed, open or withdrawn, or the broker refuses it. A new finding must name a file changed that round or say missed earlier. An APPROVE with a finding still open is refused, and a state for a finding that never existed is refused too (#603).
  • A block must cite the diff (#536). A REQUEST_CHANGES needs a numbered finding at a path:line inside the PR's hunks, or, for something missing (a test, the docs), the changed file it belongs to.
  • The reviewer checks the linked issue (#516). Both seats read the issue a PR closes and its maintainers' comments (strangers' comments are left out). The review needs a Requirements section marking each one met, not met or deferred to #N; a not met blocks.
  • Every review ends with Not verified: (#519), so what the reviewer didn't check is stated, not implied.
  • An APPROVE no body could save is refused first (#610): a partial view or red CI is the reason given, not a missing section.

The adjudicator

  • It rules on the head's CI and the issue's requirements (#586). It used to rule from the verdicts alone, and once ruled a green head red on an earlier head's failure.
  • A spent cap at a new head goes to adjudication without you (#578), when the loop has an adjudicator.
  • A ruling isn't a stall (#584). After the adjudicator rules, explain says the decision is yours, and the watchdog stops reporting it.

Red CI has its own budget

  • A red head goes to the fixer first (#576). With fix_ci on, the reviewer's turn is held and a CI-fix turn queued at once, so no verdict is spent saying "CI is red". CI fixes have their own budget, ci_fix_cap per PR (default 3, outside the verdict cap). Once it's spent, the reviewer reviews the red head with the failing jobs' logs and the CI-fix commits it hasn't seen; a fix that weakened a test blocks. explain shows CI fixes N/CAP.
  • A fix round on a red head gets the failing jobs' steps and log tails (#570).
  • Stale approvals are flagged (#529): a required check that goes red, is cancelled or never reports after an approval sends one stale_approval notice.
  • Main is checked after merges (#501): one main_red notice when the base branch goes red, naming the PRs merged since it was last green.
  • An approval after main moves says so (#599): "main moved since this PR's base: its CI ran against the older main", instead of "unverified".
  • Long check names are kept whole, so two checks sharing a 100-character prefix stay apart (#596); a runner-shutdown marker on a later annotation page is found (#593); fix_ci is settable from every path (#530).

Small issues reach the fixer on their own

  • Triage offers small issues to the fixer (#497). Name the labels with triage --auto-fix-label (for example P3, documentation; never P0–P2) and a daily limit with --auto-fix-daily (default 25). Off unless you name labels.
  • One shared hand-off guards both triggers: an issue naming an open PR waits for it, and one already fixed by an open PR is skipped (#499).
  • triage no longer drops a change flag given without --enable (#531), and init refuses --fix-daily-turns, which it used to accept and drop (#600).

Paths only a person approves

  • human_paths (#568). List glob patterns (set --human-path '.github/**'). The loop never approves a diff touching one: the broker holds the approval for a person, sends one human_paths notice, and the PR waits for you at that head.

Backup and restore

  • hermes dk backup and hermes dk restore (#537). One archive of what the plugin owns: loop files, runtime file, run ledger (a consistent copy while live), each loop's state, this plugin's routes and the watchdog job. migrate now backs up first. Tokens, profiles and model logins stay out; restore checks the token files exist.
    • The archive is 0600 and holds route secrets; nothing secret is printed.
    • Restore treats an archive as outside input: it refuses a file outside the plugin's places or behind a symlink, a route that isn't this plugin's gate, someone else's live route (even with --force), and any restore while runs are in flight. --dry-run writes nothing.
    • A loop state directory outside the Hermes home is written only when you name that exact directory with --allow-state-dir DIR (#588). The directory comes from the archive, so check it in the dry run first.
    • A restored install passes doctor with every check verified.

See every setting

  • hermes dk show --loop ID (#621) lists every setting with its value, where it came from (loop file, default or derived) and what it means; --json for scripts. Read-only; token rows show paths only.
  • A misspelt loop-file key is refused (#613) instead of loading and never taking effect, with the nearest known key suggested. See Upgrading below.

The agents learn from their misses

  • The fixer's prompt carries five rules (#519, #583, #607): reuse before writing; test the enforcing entry point; say what can't fire; make every path that decides the same question agree; prove a test fails without the fix.
  • A fixer publishes what it did (#607). If the always-run check still fails or is cut off, it publishes anyway and says what didn't pass, instead of ending the turn with the work lost.
  • The reviewer makes three checks a change's own tests rarely make (#583): every path agrees, a wait has an end, a filter leaves out what it should.
  • Fixer turns get a registry checklist (#582): a change that adds a command or flag, an observer event, a doctor check, a setting or a broker refusal is told what else to update and which test checks it.

Measure the loop

  • Each turn records its prompt revision, model and seat (#502), and its thinking level (#523, #528). stats groups verdicts and rounds by prompt revision and model; stats --github reads every review page (#590), and "missed earlier" findings follow --since (#591).
  • hermes dk corpus replays historical PRs (#514, #609, #608) as a first look through a no-write reviewer turn, and scores each finding caught by verdict and finding line, per prompt revision. On demand, not CI.
  • doctor checks the GitHub side (#535): token expiry and scopes, triage labels, and branch protection against required_checks.

Under load and at the limits

  • Ledger lock waits are a minute, and a lock timeout is retried (#605). Turns failed with "database is locked" when the host was busy; now every connection waits up to 60 s, a timeout during a turn retries, and the error names the operation it hit.
  • A provider's usage limit holds the seat until the full window resets (#622). Codex reports every window on every answer; a full 5-hour window used t...
Read more

Diaktoros v0.2.0

Choose a tag to compare

@coe0718 coe0718 released this 08 Oct 01:48
64dd337

hermes-review-loop is now Diaktoros — "the Guide," an epithet of Hermes. Same loop, new name: one agent reviews a PR, another fixes what it finds, unattended. Rounds are capped, disputes get adjudicated, and it never merges. This release also ships the three big items v0.1.1 listed as "planned next": review after CI, red CI handed to the fixer, and keeping loop PRs current with main.

hermes plugins install diaktoros
hermes dk setup --repo owner/name

(hermes dk is short for hermes diaktoros.)

The rename

  • The plugin is Diaktoros now (#444, #452). Everything the user sees — package name, commands, notices, docs — moved in stages; the old hermes-review-loop spelling still reads where it has to (#450).
  • hermes dk migrate moves an existing install (#429, #446, #448, #454).
    • What moves: settings, file names, the watchdog job and a renamed repository move to the new name. --rename-loop OLD=NEW renames a loop too, moving and pinging each GitHub hook before its old route goes.
    • The install is paused while it runs. Deliveries wait and are replayed afterwards, and every route runs the new code before the first file moves.
    • Safe to repeat: --dry-run previews first, two migrates can't both start (#451), and a re-run finishes what an interrupted one began.

Review after CI

  • The reviewer sees CI before it verdicts (#349). The loop waits for checks and the reviewer reads the results.
  • The broker refuses an APPROVE on a failed check (#348). Even if a seat tries, the write is denied.
  • A required check that never reports now refuses approval and holds the review (#383). Silent checks can't be waved through anymore.
  • Operators can own required checks (#370). Name the checks that must pass for your repo.

Red CI goes to the fixer

  • Red CI on a loop PR is noticed and handed to the fixer (#421). The failure becomes a fixing turn instead of a stuck PR. The failing job logs are read through GitHub's redirect without the token ever reaching the log host (#470).
  • A cancelled check gets a re-run, not a fix (#365). The loop tells the difference between broken code and a dead runner.
  • Runner-shutdown "failures" are held as cancelled (#426), and the failed guard is scoped to cancelled/missing with the pending wait pinned (#424).

Loop PRs stay current with main

  • The loop says once when a PR conflicts with its base (#405), then the host merges the base and pushes a merge commit (#408).
  • A conflicted PR gets a resolving fixer turn (#411); the notice says the fixer will try and when it hands back (#417).
  • Review holds while a PR conflicts (#439) — but not for closed or draft PRs (#442).
  • An issue fix waits until the PR its finding came from is merged (#400, #443). No fixes stacked on unmerged work.

Disputes and adjudication

  • A fixer that finds no defect can hand the dispute back (#427). The dispute notice waits for the fixer's comment and states the outcome (#436); the write-ahead order is pinned by test (#437).
  • Adjudication toggles with set, and setup offers it (#381).
  • hermes dk escalate --pr N sends a PR to the adjudicator now (#462), without waiting for the cap. Its head is parked like a spent cap: no more reviews or fixes there, and anything queued for it is retired.

Notices

  • Observer gains an urgent tier, a per-PR digest, and an optional urgent route (#423).
  • Closed notices now only cover PRs the loop worked on (#420).

The fixer proves its work

  • The fixer runs the tests that depend on its change (#380), with affected-module detection running the way CI does — from the repo root, where no-tests is not a failure (#406). The prompt names the modules the check didn't run (#432).
  • Every fix ships with a test that fails without it — and the reviewer blocks when it's missing (#434).

On demand

  • Maintainers can ask for a fresh review (#376) via review --pr N (#386); the command pins both queued branches, reports gate timeouts, and takes --loop (#415).
  • Review-only authors (#412): some authors get reviewed, never fixed.
    • Their PRs have a verdict cap too (#460). review_only_cap defaults to the loop's cap; at it the reviewer stops, says so once, and review --pr N --another-round allows one more verdict after the next push (#465). An optional review_only_daily keeps them from using up the reviewer's day; the docs no longer say there's no cap (#464).
  • stats summarizes a loop (#359).

Robustness

  • Skipped reviewer turns when a review already exists at the same head (#344); issue fixes skip when an open PR already claims the issue (#346).
  • The broker records HTTP status and message on failed writes (#347); worker connections close on any exception (#385).
  • Watchdog sweeps serialize per loop (#378); gate decisions are recorded so a declining gate's reason is visible (#384); the loop waits for a PR's head to follow a confirmed push before quarantining (#360).
  • owner_state reports unreadable when ledger paths fail (#351).
  • The watchdog shim heals itself when its template changes (#458).
  • Retry the wait comment when a GitHub POST fails (#449); fixed the crash enqueueing an issue fix (#433).

Setup, doctor, config

  • init/setup honour reviewer/fixer max steps and the daily turn cap (#422); the settings docs count 23 fields (#398).
  • Init papercuts fixed: token check, empty-loop hint, cron delivery (#343).
  • doctor fails the differential gate when the agreement cases empty (#353), shows the configured model (#379), and refuses cleanly when the watchdog shim can't be written (#352).
  • triage --enable says whether the hook was kept or created (#397); dry-run names the hook reconciliation keeps (#428).
  • Guard registry checks the parsed manifest, not its text (#345); gate shim restores TMPDIR/TMP/TEMP (#393).
  • Seats are told /work is the head export with no .git (#357); a distinct reviewed_pr_ineligible outcome (#358); id-less watchdog remedy and clearer repair wording (#356).
  • Remedies now say set/apply instead of "re-run init" (#419).
  • CI pinned to ubuntu-24.04 (#366).
  • DirectSDK follow-ups: config-dir secret probes, other launch routes closed (#418).
  • Trace: issues joins --event choices; issue payloads no longer print PR-shaped (#382).

Docs and tests

Read more

v0.1.1

Choose a tag to compare

@coe0718 coe0718 released this 05 Oct 09:32
431e785

hermes-review-loop v0.1.1

hermes-review-loop is now in the Hermes plugin catalog. This release is the first re-pin there. It carries the follow-up the catalog review asked for, plus what we learned from running the loop on its own issues.

hermes plugins install hermes-review-loop
hermes review-loop setup --repo owner/name

A catalog install also works from Desktop and needs no scanner prompt. The catalog serves v0.1.1 once the re-pin PR merges; until then it installs v0.1.0. To get this release directly:

hermes plugins install coe0718/hermes-review-loop --ref 431e7853c9ea99f22c81c8ec060b23d027b4e3bc

To upgrade an existing install, run the same install with --force.

Catalog review

  • The unused Discord start-ping is removed (#341). gate.ping_start was never called, but it read a seat profile's .env for a Discord bot token and posted to discord.com. It's gone, along with its helper. No code now reads a profile's .env for a token, and notices go only through the gateway's observer route.

Fixer turns

  • A turn must end with its write (#338). A fixer once finished an issue fix and then wrote "a person with write access can publish them from /work", which discarded the work. The prompts now say plainly that nobody can see the sandbox and unpublished work is lost. A turn that exits without ever calling the broker is retried once automatically, with a nudge. A refused write is still final.
  • Always-run checks (#339). Fixers run only the tests their change touches, so suite-wide checks went red in CI after they published. A loop can now name one command (chain several with &&) that fixer and issue-fix turns run and pass before publishing. You can set it from the settings form, init, setup, set --fixer-check or the loop file.
  • Refusal reasons reach the seat (#336). The broker passes its fixed refusal reasons through, instead of a bare "write denied", so a fixer can tell what to correct.

Setup and health

  • One loop per repository (#335). init refuses a second loop for a repository that already has one, and doctor flags existing duplicates.
  • Hooks (#337). A hook whose state can't be read is swept, with a warning, instead of being left alone. Hook URLs are compared after normalising (default ports, user info), so the same gateway always matches.
  • Settings form (#321). Agent steps per turn (reviewer and fixer) and the issue-fix daily cap are in the Desktop settings form.
  • set --host points you to apply when that's the right tool (#331).
  • doctor renders legacy cron schedules correctly (#316).

Runs and the proxy

  • The run ledger (#332, #333). It enforces capacity per repository and reconciles runs correctly when the OS reuses a PID. A refused connection no longer leaves a drain entry stuck as uncertain.
  • The inference proxy (#328). A model request asking for more output tokens than the proxy allows is clamped to the cap in every mode, instead of killing the turn.
  • Sandbox exports (#327, #329). A PR's symlinks, submodules and .gitmodules are skipped when its tree is exported. The skipped names are passed to the model as quoted PR data, not as a host fact.
  • Tests: pacing never parks a run that has already written (#319). The empty-reply fix is scoped to model completions (#317).

Known limits

  • Linux only (macOS: #256).
  • Agent turns are contained, but that isn't a security audit; see security.
  • Planned next:
    • keeping loop PRs current with main (#303);
    • handing red CI to the fixer (#306);
    • review after CI (#241);
    • tiered notices with a per-PR digest (#330).

hermes-review-loop v0.1.0

Choose a tag to compare

@coe0718 coe0718 released this 04 Oct 23:33
59eab1f

hermes-review-loop v0.1.0

The first release. An unattended GitHub pull-request loop between two Hermes agents: one pushes fixes, a different one reviews, rounds are capped in verdicts, and the loop never merges.

hermes plugins install coe0718/hermes-review-loop --ref 59eab1f0070ff9671682c975ad58c172d0245ead
hermes review-loop setup --repo owner/name

Linux only (every turn runs in bubblewrap); on macOS, run Hermes in a Linux VM. Requires Hermes 0.21.5 (v2026.9.24) or newer. Start with the getting-started guide.

What it does

  • Review loop. A PR from the fixer account is reviewed by a different reviewer account. Changes requested go back to the fixer, who answers and re-requests review. Rounds are capped in verdicts; when the cap is spent, an optional adjudicator rules. A person always merges.
  • Isolation. Every agent turn runs inside bubblewrap: no GitHub or model credentials, no network, none of your secret files, a read-only root. A host-side broker makes every GitHub write, re-checked against live state: reviews pinned to the exact head, and leased fast-forward pushes. selftest proves the sandbox on your machine.
  • Fixes that fit real repositories. A fix is published whole when small and as a diff otherwise, so a one-line change to a 1 MB file costs one line. Deletions and renames work.
  • Issue triage (opt-in). New issues from authors you allow get labels from your list.
  • Issue fixes (opt-in). A maintainer applies a label, and the fixer opens a PR that fixes the issue, which the loop then reviews. It's capped per day, and a fix that can't be done becomes a comment instead of a junk PR.
  • The reviewer files its findings. Non-blocking findings become issues, filed as the reviewer's own account, with labels from your list only. Each issue records the PR it came from and its depth, so automatic chains stay bounded.
  • Notices. An optional Telegram (or other) feed covers every transition: opened, verdicts, approvals, escalations, issue triage and fixes, a run's first failure, and holds (a daily cap or a provider's usage window), each with what to do next. A watchdog reports silent stalls.
  • Pacing. A provider's 429 holds the seat until its window reopens instead of burning retries. There are daily turn caps per seat, and per-seat agent-step and time budgets.
  • Signed. Everything the loop posts says "Automated by hermes-review-loop".

Proven live before release

This release was tested by running the loop on its own repository: the reviewer and fixer seats reviewed and fixed the plugin's own issues. Along the way the run found and fixed:

  • a profile flag that Hermes itself consumes;
  • step caps too small for real fixes;
  • whole-file-only pushes;
  • a read-only /dev/shm that broke multiprocessing tests;
  • a proxy request limit too small for long reviews;
  • silent holds.

Known limits

  • Linux only (macOS: #256).
  • Agent turns are contained but not a security audit; see security.
  • Planned next:
    • automatic hand-off of reviewer-filed issues (bounded by their lineage);
    • keeping loop PRs current with main (#303);
    • handing red CI to the fixer (#306);
    • review after CI (#241).