skip to content
Replays

Declared Gate Work

Declared Gates in the Pattern Runtime

Gantry made gate commands explicit across pattern loading, run boundaries, and run reports.

Gantry milestones

3 milestones 0 tasks

4 plan 10 execute 17 review

Gantry made gate commands explicit across pattern loading, run boundaries, and run reports.

4h 13m total

This run removed the last implicit gate path from Gantry's default build path. The work changed the pattern format, the bundled build and milestone patterns, the agent prompts that author gates, and the run record that reports what a gate covered.

How this walkthrough is structured

Feature

What did the run build and ship?

The current tree requires explicit gate commands, runs declared run-scoped gates at run boundaries, and persists parsed gate coverage when a supported log format appears.

Build

How did Gantry structure the work?

The cut kept the format change, boundary rewrite, and reporting add-on separate, and every recorded stage completed without recovery or re-plan.

Milestone 1

Declared Gate Language

The pattern spec now says `gate.command` is required and defines `agent.judging_gate`. The bundled patterns use that key where an agent is followed by a gate. The loader and interpreter behavior still enforce declared gate resolution rather than searching for a gate file.

This milestone carried the incompatible pattern-language change. Its brief tied the normative spec, loader validation, runtime gate resolution, compatibility marker, and tests together because a declared gate is not useful unless every layer agrees on the same contract. The run facts show no retry or repair here, so the boundary held as a single format migration.

Declared Gate Format

The pattern reference still documents `judging_gate` for agent steps and a required `command` for gate steps. The compatibility marker in the pattern spec is current. The website's mirrored pattern documents carry the same declared-gate contract.

This sprint was the documentation and format edge of the language change. It could fit in one fresh context because it dealt with the written contract before later work relied on runtime behavior. The stage record has no red gate or re-plan attached to the run, so this part did not force the decomposition to change.

Runtime Declared Gates

`config/patterns/sprint.toml` passes `declared_gate_command` into the sprint pipeline and assigns it to `judging_gate`. Gate steps in that pipeline run the same declared command. The older fallback path is not visible in the current `src/engine/run/gate.rs` surface.

This sprint owned the runtime interpretation of the new language. The task was bounded around reading declared gate data and passing it to execute, troubleshoot, and review positions. The absence of recovery in the run facts means the new runtime path reached review without a recorded repair loop.

Declared Patterns And Fixtures

The shipped pattern files use declared gate commands instead of bare gate steps. Pattern tests still cover a matching declaration and the current docs describe the same vocabulary. Later commits changed surrounding files, but the declared-gate pattern shape remains present.

This sprint was the propagation pass for fixtures and existing tests. That is a narrow boundary: once the format and runtime existed, the remaining work was to make shipped pattern examples and tests speak the new contract. The run completed it without a retry, which fits a mechanical follow-through slice.

Milestone 2

Run Gate Boundaries

The default build pattern authors a run-scoped `project_gate`, proves it before milestone work, runs it after each milestone body, and runs it after all milestone bodies. The milestone pattern still authors a task gate for its inner loop. Resume and merge code now ask for the declared run-scoped gate and skip that boundary only when none exists.

This milestone moved declared gates from language support into the default build topology. Its brief separated the run-scoped gate from the milestone gate and removed execution fallbacks that could choose a gate by location. The full milestone stayed green in the run record, so no review forced a new cut.

Gate Author Contracts

The gate-authoring prompts are now split by boundary. `write-project-gate.md` asks for the project's full gate at the run root. `write-milestone-gate.md` asks for the scoped command that covers one milestone's tasks.

This sprint owned the prompts that write gate scripts. It was small enough for one agent because it changed instructions, not the execution engine. The run facts record no red gate for the run, so the prompt split did not trigger a repair path.

Bundled Gate Boundaries

`config/patterns/build.toml` contains the run-scoped gate path through `prepare_project_gate`, `milestone_boundary_gate`, and `project_final_gate`. `config/patterns/milestone.toml` keeps a milestone-level gate for the sprint loop and for milestone review edits. The pattern gallery and generated reference data were refreshed after that structure changed.

This sprint carried the bundled pattern topology. The task was large in files but narrow in concept: move the default build and milestone patterns onto explicit gate boundaries and regenerate the derived pattern references. The absence of recovery says the generated surface and source pattern stayed consistent enough for the gate.

Boundary Gate Runtime

`src/engine/run/gate.rs` resolves the run-scoped gate through `declared_run_scoped_gate_command`. Merge, post-merge, and resume checks call that declared path. When no run-scoped gate exists, the code returns the explicit no-declared-gate outcome instead of searching child orchestration directories.

This sprint removed the runtime side of undeclared gate discovery. It was bounded around execution decisions after the pattern files had already declared which gate belonged at each boundary. The recorded run did not need a retry, so the removal did not expose a missing fallback during this run.

Resume Boundary Coverage

The resume path admits a run with no declared run-scoped gate and uses the declared run-scoped gate when one exists. The current docs still record the closed resume-baseline issue and the map merge-boundary decision. Pattern tests cover resume and boundary-gate cases around milestone layout.

This sprint handled the audit and resume cases left after the boundary rewrite. The brief tied together run admission, map mode, and every path that can make work permanent, which made it a verification slice rather than another format change. The run facts show no re-plan, so the audit findings did not rewrite later work.

Milestone 3

Gate Coverage Record

The tree now has `src/engine/gate_coverage.rs` for best-effort parsing and aggregation. Gate completion can carry a `GateCoverageRecord`, and unsupported output leaves the field absent. `about.md`, repository run records, status output, and the TUI read the same optional record.

This milestone was deliberately severable from the declared-gate behavior. Its brief limited the work to parsing gate logs, persisting the parsed fact, and showing it in reports without changing the subprocess contract. It also completed without recovery, so the reporting layer did not disturb the boundary change it depended on.

Gate Coverage Parser

`src/engine/gate_coverage.rs` parses supported `cargo-nextest` and `cargo test` summaries and returns no fact for unsupported output. `src/engine/goal.rs` attaches parsed coverage to command output. The parser remains best-effort and does not require a gate script to write a new artifact.

This sprint isolated the parser from storage and display. That made the work suitable for a fresh agent because the input was just captured gate output and the output was an optional fact. No run recovery was recorded, so the parser contract passed without changing the remaining plan.

Gate Coverage Record

Gate events can now include `gate_coverage` on finished gate stages. The pattern runtime persists coverage for milestone-level and run-scoped gates by boundary identity. Existing gate events without parsed coverage still serialize with the field absent.

This sprint connected parsed coverage to the run record. Its boundary was persistence: gate execution already produced output, and reporting had not yet consumed it. The run stayed green, so no recorded repair was needed to preserve the existing gate subprocess contract.

Gate Coverage Reports

`stage_finished_with_gate_coverage` records parsed coverage into the root about sidecar when the fact exists. Tests show nested gate coverage updates the root run report rather than a child report. `gantry status` and repository run records render the same aggregated gate coverage when data is available.

This sprint took the stored gate coverage into user-visible reports. It was the last step because it depended on parser output and persisted boundary identity being present first. The run facts show it closed without a retry or re-plan, so the reporting surface did not force a storage redesign.