Rename Monitors and Runners to Evals and Agents

Claude Code·Opus 5.5·matthiaswenz·6d ago·1hr 23min·1 Checkpoint·7 file changes·+612/-35·240.9K tokens

pick up https://entire.com/et/entirehq/-/trails/620 - some things to redo:

  1. rename monitors -> evals
  2. rename runners -> agents

the underlying idea is still the same, only some things have changed besides naming: runners are replaced by agents - agents are a new concept that is fully configured in the database and at the project level instead of the repo level.

the gate should still be configured at the repo setting level and infer the score type and logical threshold definition from the agent config. the link between an agent config and the repo gate setting will be if the agent is active for the repo in its config (i.e. scope)

this introduces or changes of course the vectors for config drift:

  1. an agent that is used for a eval gate could be disabled -> the gate should fail open
  2. an agent used for an eval gate in a repo could remove the repo from its config -> fail open as above
  3. an agent used for an eval gate could change the scoring mechanism or polarity -> allow saving the agent config - do not try to stay compatible - clearly show the config issue in gate evals on trails

in terms of visualizing the evals on a trail: they should get their own row in the gates titled "Evals" with an item per eval - we can later discuss a visual connection to the eval boxes in the trail view, but for now: keep it simple and consistent

an agent "qualifies" for being used for eval gates in a repo if the repo is in its scope - no matter the trigger type for the agent - doesn't matter if push or manual triggers, if the agent can produce an eval for trails on the repo, it should be consumable for the gates

api / settings ux: allow writing a eval gate purely by setting the threshold for the given agent config - in the repo settings gates ux, agent evals should get their own section where a user can add new entries which allows them to pick any unused agent eval in scope and set a matching threshold - then save all as one combined operation to the gates config of the repo

rollout for all this should be staged at the project level, only entire projects should be flagged in via posthog feature flag (agent-evals-gates, to be created) initially

ask clarifying questions where needed, otherwise

/goal trail 620 and linked trails are updated and properly repurposed so they can be implemented in their respective areas (api, frontend, ...)

6d ago·33m

I've rewritten trail 620 and its six linked trails around agents and evals. Changes entire-api/342, 343 and 367 are closed without merging, and trail 622 is closed. I checked that the bodies kept their headings and lists on 620 and 19608.

  • 620 "Eval gates: gate merges on an agent's eval": the design, the deploy order and the rollout behind agent-evals-gates.
  • 621: adds the eval gate type, which already existed as a reserved name, plus PUT /repos/{repo_id}/trails/gates/evals. That one call saves all of a repo's eval gates at once. It still ships together with 623.
  • 623: judges eval gates on the trail head and recomputes after agent runs and pushes. When an agent is paused, removed from the repo, archived or changes its scoring, the gate becomes skipped and says why. skipped already exists and never blocks a merge.
  • 753: now about agent changes. When someone saves an agent, its eval gates are recomputed on open trails at once. Its old content (warnings about runner file changes, versioning monitor values) no longer applies.
  • 622: closed. GET /repos/{repo_id}/agents already lists a repo's agents with their scoring.
  • 19608: the "Agent evals" section in Settings › Gates, saved in one go and checked against the flag by project, like repo-secrets.
  • 19609: one "Evals" row in the trail page's gates. I dropped the threshold bands and badges on the eval boxes that the first plan had.
  • 19610: CLI. entire runner list is dropped, because entire project agent list already lists agents.

Choices I made without asking, so you can push back:

  • One gate per agent per repo: there are no two-tier thresholds like "needs attention at 40, block at 70".
  • Agents with neutral polarity can't be gated: they have no better direction, so settings shows them greyed out with that reason.
  • A paused agent can still be picked: its gate is skipped until the agent is resumed.
  • A failed agent run on the head is an error, not fail open: it blocks a blocking gate, the same as a failed check. Only config changes fail open.
  • The flag is checked in entire.io's BFF only, like repo-secrets: entire-api doesn't read PostHog flags. So the CLI commands that write gates wait until the flag is removed.
  • 19608 keeps the first plan's off / needs attention / blocks merge control for all gates: it's a separate step that can ship on its own.

Before 621 deploys, check that no repo_gate_definitions row has gate_type = 'eval'.

I haven't created the agent-evals-gates flag in PostHog yet; it's step 1 on 620. Should I create it now for et/entirehq and gh/entirehq?

Base directory for this skill: /Users/matthiaswenz/.claude/skills/build-trail

Build Trail

Take one trail and its changes across repos from its intent to a mergeable state, across as many repos as the work needs. The trail's intent is the contract. Everything else serves it.

Inputs

  • <trail>: a trail URL (e.g. https://entire.io/gh/entirehq/entire.io/trails/3766) or a number in the current repo.
  • --defaults: don't ask clarifying questions. Pick the sane option yourself and record each pick under "Decisions" in the trail body.

Done means, for every trail this run touched: CI checks green, no open high- or medium-severity findings, no open slop monitor verdicts, no merge conflicts with the base branch, and Entire's gates show it as mergeable. API contracts between different systems are up-to-date and honored. Human approval is the one gate you can't satisfy. Report it as the remaining step. Never merge a trail yourself unless the user says so.

Step 0: Read and clarify the intent

  1. entire trail show <trail> --json → title, body, branch, base, repo. Also read linked Linear issues and sibling trails the body mentions.
  2. Restate the intent to yourself in three lines: the problem, who has it, and what "fixed" looks like to that person.
  3. List the open questions. These are gaps where two reasonable builds would differ in what the user sees, the API contract, the data model, or rollout.
    • Without --defaults: ask them in one AskUserQuestion call (max 4), putting your recommended option first. Don't ask what the code or the trail already answers.
    • With --defaults: answer them yourself.
  4. If the answers changed or sharpened the intent, rewrite the trail title and body now (see "Trail body" below) with entire trail update --title … --body …. From here on, the updated body is the intent.

Step 1: Get the workspace

  • Reuse an existing worktree for the branch if git worktree list shows one. Otherwise run entire trail checkout <n> --worktree. A branchless trail needs a branch first: create it, then entire trail update --branch.
  • Merge origin/<base> in before starting. Resolve conflicts on the side of the intent.
  • Run entire session current --json and keep the session_id for Step 3.

Step 2: Build

  • Implement what the intent asks, and nothing adjacent. If you spot a related problem, note it for the report or a follow-up trail. Don't fix it here.
  • Commit after each working step (tests pass for what you touched), with a message saying what changed and why. Push often, so the trail's checks and reviewers run on real code.
  • Keep code comments to a minimum. Write one only when the code can't say it itself. The reasoning lives in the session and its checkpoints.
  • Run the repo's local checks (lint, types, the tests you touched) before each push.

Step 3: Other repos

When the trail has changes listed for different repositories or the intent needs changes in another repo (entiredb = Core, entire-api, entire.io = web app/BFF, etc. under ~/Development/entire/):

  1. git -C ~/Development/entire/<repo> fetch origin, then add a worktree on a new branch from origin/main.
  2. Build there under the same rules as Step 2.
  3. After the first commit and before the first push: cd <worktree> && entire session attach <session_id> --force. Attach amends HEAD, so pushing first would need a force-push.
  4. Open the trail with the CLI, not the MCP trail_create, which drops the branch: entire trail create --branch <branch> --title … --body ….
  5. Link all the trails and changes together. Trails are at the project level and link changes from multiple repositories.
  6. Only create new trails if the changes span into different repositories which live in a different project (i.e. et/entirehq/ vs gh/entirehq/ owned)
  7. Every trail body or change body lists every other trail from this run by full URL, and says the deploy order when one matters (usually entiredb → entire-api → entire.io). Update the earlier trails' and changes' bodies each time you add a new one.

If another Claude session already owns a branch you need changed, send it the change with SendMessage instead of editing its worktree.

Step 4: Loop until done

For each trail, repeat:

  1. Merge origin/<base> if the branch is behind or conflicts.
  2. CI: find failures (GitHub checks, Buildkite for entire-api), then fix them. If a failure isn't caused by this branch, say so and link the evidence. Don't paper over it.
  3. Findings: entire trail finding list <trail> --json. Fix each one that's right and within the intent, then entire trail finding resolve <trail> <id> -m "<what changed>". Dismiss the ones that are out of scope with a reason, and add them to the report as follow-ups. If a finding is not caused by this branch, say so and link the evidence. REQUIRED SUB-SKILL: use address-findings if it's available in the repo.
  4. Slop monitors: read the verdicts with the MCP trail_monitors (entire-prod-us) and treat each one like a finding.
  5. Gates: check trail_gates or entire trail show --json for mergeability.
  6. Wait for CI and reviewers with Monitor or a background command, not sleep. Then go back to step 1. Stop only when every trail meets "Done means".

Staying true to the intent

  • Before each commit, check it against the intent: does this change serve the stated problem? If not, drop it.
  • When a choice comes up that the intent doesn't settle, and the options give different results for the user:
    • Build everything that doesn't depend on the choice first.
    • Then ask one AskUserQuestion with your recommendation, and wait. With --defaults, pick instead and record it under "Decisions".
  • A finding or reviewer asking for more than the intent covers is scope creep. Say so on the finding and dismiss it, or ask the user.

Trail body

Every trail this run writes or rewrites uses this shape, in plain Markdown:

  • The title names the problem or outcome, not the implementation.
  • No GFM tables (trails don't render them), and no discussion-log narrative. Write for a reviewer with little context.
  • Keep existing screenshot and image references when rewriting a body.
  • entire trail update refuses a body that changed since you read it. Re-read and merge rather than passing --overwrite.

Report to the user

Keep it short and in the same order every time:

  1. One line per trail: the trail URL, its state (mergeable / waiting on approval / blocked on X).
  2. Decisions you made, one line each.
  3. Follow-ups you deliberately left out, with a link if you filed them.
  4. Anything you need from the user.

Common mistakes

MistakeFix
Saying "pushed" or "done" without checkingConfirm with git status -sb and entire trail show before claiming it.
Asking about things the trail or code already answersRead first. Ask only real forks.
Growing the change to "clean up" nearby codeOut of scope. Note it as a follow-up.
Sibling trail links only in one directionEvery trail lists every other trail.
Stopping after one pass of findingsNew pushes bring new findings. Loop until the check comes back clean.
Long comments explaining the changeDelete them. The checkpoints hold the reasoning.

ARGUMENTS: https://entire.com/et/entirehq/-/trails/620 --defaults

6d ago·36m

24 open findings across the three Changes. The skill asks for address-findings here; loading it.

Base directory for this skill: /Users/matthiaswenz/Development/entire/entire-api/.claude/skills/address-findings

Address Findings

Fix and resolve the open review findings on an Entire trail. A finding is a review comment posted to a trail on entire.io: it has a file/line location, a body, a severity, and sometimes a suggested unified-diff patch. This skill fetches the open findings, applies or hand-fixes each one in the current worktree, and marks it resolved on the trail.

When to use / not use

Use when the user points at a trail — a URL like https://<host>/<forge>/<owner>/<repo>/trails/<number>/<slug>, or a bare trail number or branch — and asks to address / fix / resolve its findings or review comments.

Do not use this skill for:

  • A code review of the current diff — that is the review skill (read-only).
  • Creating new findings — use entire trail finding add.

Response Format

Begin the first response to this skill invocation with the line:

Entire Address Findings:

followed by a blank line, then the content. Apply the header to the first response only. Omit it on error / early-exit responses (CLI missing, not authenticated, trail not found, branch mismatch, no open findings).

Rules

  1. Make the smallest correct change that addresses each finding. Do not expand scope.
  2. Only mark a finding resolved when you actually addressed it. If a finding is ambiguous or needs a human decision, leave it open and report it.
  3. Do not commit or push. Leave changes in the working tree for the user to review.
  4. Never weaken a test or assertion just to clear a finding.

Process

1. Verify the CLI

Run entire version. If the command is not found, stop and tell the user: "The Entire CLI is required but not installed. Install it from https://entire.io/docs/cli and try again."

2. Resolve the trail selector

  • If the argument is a trail URL, take the number from the /trails/<number>/ path segment and use that number.
  • If it is a bare trail number, id, or branch name, use it as-is.
  • If you cannot determine a trail, stop and ask the user for the trail URL or number.

Use this value as the <trail> selector for every command below. entire trail accepts a trail number, id, or branch name interchangeably, so no number lookup is needed — a branch name works directly.

3. Fetch open findings

  • If the output reports that authentication is required, stop and tell the user: "entire trail finding list requires authentication. Run entire login and try again."
  • If the trail finding subcommand is unavailable, or the API reports the feature is not enabled, stop and tell the user that trail findings may not be enabled for this account or repository. Do not invent findings.
  • Parse the JSON. Each finding has an id, a severity, a status, a body, a location (file path + line range), and may include a suggested change (a unified diff).
  • If there are no open findings, report "No open findings on this trail." and stop.

4. Branch guard (you must be on the trail's branch)

entire trail finding apply edits the local worktree, so you must be on the trail's branch before changing files.

Find the trail whose number or branch matches your selector and read its branch.

  • If the trail's branch differs from the current branch, stop and tell the user: "Trail <trail> targets branch <trail-branch>, but you are on <current-branch>. Check it out first (entire trail checkout <trail>) and re-run." Do not edit files.
  • If you cannot find the trail in the list (e.g. pagination), do not hard-fail: warn that you could not verify the branch, and ask the user to confirm they are on the trail's branch before you continue.

5. Address each finding

Process findings highest severity first (high → medium → low). For each:

  1. If it has a suggested unified-diff change, dry-run it first:

    If it applies cleanly, apply and resolve in one step:

  2. Otherwise (no patch, the patch conflicts, or the fix needs reasoning): read the finding body, open the file at its location, and make the smallest correct edit that addresses it. If a fast, relevant local check exists for the touched code (a build or a focused test), run it. Then resolve:

  3. If you cannot confidently address it (ambiguous, needs a product/design decision, or out of scope): leave it open, do not resolve it, and record it for the report.

6. Report

Summarize:

  • Resolved via suggested patch — list finding ids and files.
  • Resolved via manual edit — list finding ids, files, and a one-line of what changed.
  • Left open for your decision — list finding ids and why.
  • Any errors encountered.

Remind the user the changes are uncommitted and ready for review.

Failure modes

  • CLI not installed → install message (step 1).
  • Not authenticated → "entire trail finding list requires authentication. Run entire login and try again."
  • Trail findings not enabled / API error → tell the user the feature may be unavailable; do not fabricate findings.
  • Trail not found → tell the user to check the URL or number; suggest entire trail list --status any.
  • Wrong branch → stop with the checkout instruction (step 4).
  • Patch does not apply → fall back to a manual edit; if you cannot fix it confidently, leave the finding open and report it.
  • Not a git repository → stop and tell the user to run from inside the trail's repo.

ARGUMENTS: et/entirehq trails 621 (entire-api/749), 623 (entire-api/750), 753 (entire-api/751) — stacked branches matthias/eval-gate-config → matthias/eval-gate-judge → matthias/eval-gate-agent-changes in this worktree

6d ago·3m

Passing. Committing and pushing the 621 fixes, then resolving its findings.