A new site has no old code, so every problem a check finds is new. An existing site is different: run phpcs or phpstan over it and you will usually get hundreds of problems nobody wrote this week. If droost judged every run on all of them, the first change that touched an old file would fail, and keep failing, on work that is not the agent's.
The fix is a baseline: a record of the problems the site has today, so a run is judged only on what it adds. Write it before the first run.
The order
Install droost the usual way first (Set up by hand or with AI), then:
- Commit or stash any work in progress.
- Pick the level.
- Install the tools the checks use.
- Measure the old problems.
- Write the baseline, and commit it.
- Start your first run.
The order matters. The baseline records only the checks the level turns on, and a later refresh can only remove problems, not add them (see Raising the level later). Set the level first.
1. Start from a clean tree
droost does not count changes it finds in your working folder when a run begins as the run's own. Leftover edits make the first run's checks look at the wrong files. Commit or stash them first.
2. Pick the level
From your own terminal:
droost workflow:effort highdroost workflow:effort high --preview shows what a level turns on without
writing anything. Settings has the table.
3. Install the tools
composer require --dev drupal/core-dev # phpcs, phpstan, phpunit
npm i -D @playwright/test && npx playwright install chromiumIf the project already has its own phpcs.xml(.dist) or phpstan.neon,
droost's checks use it, and the baseline is measured with it too.
4. Measure the old problems
droost workflow:baseline --measureThis runs each check the level turns on over the whole site, so on a big
site it takes as long as a code step. It writes nothing, and prints (as JSON)
the level, the bill (how many problems each check would record) and
skipped: each check it could not measure, and why. A tool that is missing
or crashes is listed there, never recorded as clean.
Read the numbers before you write them down. A check with thousands of
problems may be pointed at the wrong folders (vendor/, a contrib module
copied into modules/custom/).
5. Write the baseline
From your own terminal, between runs (the agent cannot write it, since a baseline the agent could write is a problem it could hide; and it is refused while a run is open):
droost workflow:baseline
git add droost/baseline/
git commit -m "droost: record the baseline"It is written to droost/baseline/, one file per check, and committed like
any other code, so the team sees what was accepted.
droost workflow:baseline --status shows what is recorded.
What a run sees now
A check that passes says how much of what it found was already there:
phpcs passed: 0 new, 312 inherited- Only new problems fail a run.
- For phpcs, eslint and stylelint, a problem belongs to its line's text. A line the change edited counts as new, even if its problem is old, so the agent fixes what it touches; a line that only moved, or was re-indented, stays inherited.
- For prettier, an unformatted file stays inherited until a run touches it.
- phpstan uses its own baseline file, which droost writes and points phpstan at.
- The baseline is frozen when each run starts, so it cannot change under a run.
What it covers: phpcs, phpstan, eslint, stylelint, prettier, and the coverage and mutation floors. Tests are not baselined. A failing phpunit or Playwright test is broken, not old, and fails the run until it is fixed or skipped in the test itself.
Paying it off
As the team fixes old problems, record the smaller number:
droost workflow:baseline --refreshA refresh only ever shrinks the baseline: fixed problems drop out, and if it finds more than before it refuses and names them.
Raising the level later
A higher level turns on more checks, or makes one stricter (phpstan's level, for example), and those find old problems the baseline never recorded. A refresh refuses to add them unless you say why:
droost workflow:baseline --refresh --grow --reason="raised to xhigh"The reason is kept in the baseline's record for good.
Your team, alongside the agent
- People are not blocked. The guard holds the agent, not your editor. Anyone can still edit and commit as before.
- The agent edits custom code only inside a run. With
require_run: hard(whatinitwrites), an agent asked for a quick fix outside a run is refused. To let it, rundroost workflow:bypass "<why>"in your terminal, anddroost workflow:bypass --offafter; or setrequire_run: softin Settings. - Your own instructions are kept.
initadds droost's section toAGENTS.mdandCLAUDE.mdbetween marker comments and leaves the rest of each file alone. - The wiki starts thin. On day one droost knows your modules and your
code from the files, but has none of your team's notes. Each run adds what
it built to
droost/wiki/; you can add pages of your own there too.
When the first run still fails on old code
Read the gate's message. If the problems are in files the run did not touch, it names them. Usually that means the baseline was written at another level, or before a tool was installed; measure again and refresh. See Troubleshooting.