# Gates

> Every built-in gate, which phase runs it, what each result word means, the seeker, retries, waivers and the baseline for old code.

A gate is a check that runs at a phase. If a blocking gate fails, the run
stays in that phase until it is fixed.

## The built-in gates

| Gate | What it checks | Needs |
|---|---|---|
| `phpcs` | code style (the Drupal standard by default) | `drupal/coder` |
| `phpstan` | mistakes in PHP code, at a level from 0 to max | `phpstan/phpstan` |
| `phpunit` | the PHP tests | a `phpunit.xml(.dist)` |
| `playwright` | the browser tests in your repository | `@playwright/test` |
| `parity` | the site against the design it copies | a captured reference ([Parity](https://droost.org/docs/parity.md)) |
| `coverage` | how much code the tests run | phpunit with a coverage driver |
| `mutation` | whether the tests catch deliberate bugs | Infection |
| `eslint`, `stylelint`, `prettier` | JavaScript, CSS and formatting | the tools, in `node_modules` |
| `house_rules` | your own rules | [House rules](https://droost.org/docs/hooking-in.md#house-rules) |
| `wiki_fresh` | the project's notes still match the code | `droost/wiki/` |

phpcs, phpstan and phpunit look only at your own code: `modules/custom` and
`themes/custom` on a Drupal site, never core, contrib or `vendor/`. Set
`paths:` to point them elsewhere.

## Which phase runs what

At `high` and above, and at `custom` (the strict flow):

```text
plan:      no gates (but the agent must have looked at the code)
code:      phpcs, phpstan, eslint, stylelint, prettier, house_rules
test:      phpcs, phpstan, eslint, prettier, phpunit, mutation, playwright, parity, coverage
complete:  everything above, plus wiki_fresh
```

At `low` and `medium` (the fast flow), each gate runs once: the code checks
and the PHP tests at code, the browser tests, parity and house rules at test,
and only `wiki_fresh` at complete, and the test suites run only the tests the
run changed. At every level the code checks read only the files the run
changed, never the whole project.

## What the results mean

Each gate's result is one of seven words (passed, labelled, failed, reported,
off, waived, could not run). [How it works](https://droost.org/docs/how-it-works.md#the-report)
explains each.

## Retries

A failing gate does not end the run. The agent fixes the cause and the gate
runs again, up to `max_gate_retries` times (the file `init` writes says 2; a
level left to decide says 1 at `low`, 3 at `max`, 2 otherwise). After that the
phase stops and the run says why.

At `low` and `medium`, a failure at test sends the run back to code to fix it
(up to 2 times at `low`, 3 at `medium`). If the whole browser suite runs there
and fails only in tests this run never touched, droost files a follow-up
ticket instead of blocking the run.

## Waiving a gate

If a gate is wrong for this one change, you can let it through:

```bash
droost workflow:gate-waive phpstan "the false positive is upstream, issue #123"
```

Only from your own terminal. The report shows the gate as **waived**, with your
reason, never as passed. phpcs, phpstan and phpunit can only be waived at
`preset: custom`.

## The seeker

The seeker is a second agent that reads each change looking for what gates
cannot see: dead code, weak tests, drift from the spec, security smells,
broken house rules, and attempts to get around the workflow. It looks at the
change and one step out from it, never the whole codebase.

```yaml
seekers: { on: true, rounds: 1, holds: critical, at_complete: false }
```

| Option | What it does |
|---|---|
| `rounds` | how many inspections the code phase needs (1 to 5) |
| `holds` | which open findings hold the run: `critical`, `high`, `medium` or `none` |
| `at_complete` | also inspect at complete |

The report shows each finding and how it closed, and says when the closing was
the author's own word rather than a second inspection.

## Old code: the baseline

An old site fails the gates on problems nobody is fixing this month. A
baseline records those once, so new runs are judged only on what they add:

```bash
droost workflow:baseline --measure   # what each gate would inherit (read only)
droost workflow:baseline             # write it (your terminal); commit droost/baseline/
```

From then on a gate reads, for example, `passed: 0 new, 123 inherited`. An
edited line becomes new; a line that only moved stays inherited. Refresh it
with `--refresh` as debt is paid off. The baseline is frozen with each run, and
the agent cannot write it. [On an existing site](https://droost.org/docs/existing-site.md) has the
whole order, and what to do when you raise the level later.

## Running gates without a run

```bash
droost workflow:gate --phase=test
```

runs one phase's gates now, records nothing, and spends no retries. Useful in
CI, or to try a new gate.
