ADR-063: Agent-Facing Background Dev Server Contract
Status
Section titled “Status”Accepted
Context
Section titled “Context”This template’s differentiator is its agent-first workflow: a layered constitution, generated
AGENTS.md, and halt-on-violation gates. Coding agents working in cloned projects routinely need
a dev server they can start, verify, and stop programmatically — historically done by holding a
terminal open, parsing human-formatted logs, and guessing at readiness.
Astro 7 ships first-class support for exactly this workflow:
astro dev --backgroundstarts the server as a detached background process and prints JSON-formatted status linesastro dev stop,astro dev status, andastro dev logs [--follow]manage it- a
/_astro/statushealth endpoint answers liveness ({"ok":true})
All of the above was smoke-tested against astro 7.1.4 in this repository before adoption.
One capability limit matters: /_astro/status is liveness-only. It does not identify which
project is serving. This repository has twice been bitten by port-4321 collisions (Playwright’s
reuseExistingServer and local Lighthouse both silently measured an unrelated site occupying the
port). The health endpoint does not fix that class of bug, and documentation claiming otherwise
would recreate it.
Decision Drivers
Section titled “Decision Drivers”- Agent ergonomics: start/verify/stop without a held terminal or log-scraping
- Discoverability: the capability exists in Astro 7 regardless; undocumented, cloned projects’ agents won’t find it (ADR-052 — the everyday surface must be obvious)
- Honest contracts: document what
/_astro/statusanswers and what it does not - Minimal surface: no new dependencies, no config changes, no runtime code
Considered Options
Section titled “Considered Options”Option 1: Scripts + documented contract
Section titled “Option 1: Scripts + documented contract”Description: Add dev:agent / dev:agent:stop to the cloner-facing script section and
document the full contract (subcommands, health endpoint, port-collision caveat) in
.claude/stack.md, flowing into the generated AGENTS.md.
Pros:
- Two package.json lines and documentation; nothing to maintain beyond upstream Astro
- Agents in cloned projects discover the capability through
AGENTS.md
Cons:
- Slightly widens the everyday script surface (ADR-052 traded exactly this against discoverability)
Option 2: Do nothing — the flags exist upstream
Section titled “Option 2: Do nothing — the flags exist upstream”Description: Rely on agents knowing Astro 7’s CLI.
Pros:
- Zero surface added
Cons:
- Discoverability failure: agent context is built from
AGENTS.md, not Astro’s CLI help - The port-collision caveat — the part that actually prevents bugs — would live nowhere
Option 3: Full logHandlers.json() config integration
Section titled “Option 3: Full logHandlers.json() config integration”Description: Also wire logHandlers.json() into astro.config.mjs so all dev output is
structured JSON.
Pros:
- Machine-readable logs in every mode, not just background
Cons:
- Changes the human dev experience (
pnpm devoutput becomes JSON) to serve the agent case that--backgroundalready covers - Config surface for a need not yet demonstrated
Decision
Section titled “Decision”We will go with Option 1. The scripts sit in the everyday section (ADR-052: cloner-facing above the separator) because agents working in cloned projects are this template’s primary audience for them. Option 3 is available to any cloner in one config line if they want it; defaulting it would trade human ergonomics for no additional agent capability.
Implementation Details
Section titled “Implementation Details”pnpm dev:agent # astro dev --background — detached, JSON status linespnpm dev:agent:stop # astro dev stoppnpm exec astro dev status # running? pid?pnpm exec astro dev logs --followcurl -s http://localhost:4321/_astro/status # {"ok":true} — liveness ONLYThe contract documented in .claude/stack.md (and therefore AGENTS.md) states explicitly:
/_astro/status proves a dev server answers on the port, not that it is this project’s
server. Before driving tests against a port, agents must verify ownership (e.g. check
astro dev status reports a pid, or request a route unique to this site).
Consequences
Section titled “Consequences”Positive
Section titled “Positive”- Agents manage the dev server lifecycle with two scripts and structured output
- The port-collision trap is documented at the exact place agents read before starting servers
- Zero dependencies, zero runtime code, zero config changes
Negative
Section titled “Negative”- Two more scripts in the everyday section (accepted trade under ADR-052)
- The contract tracks upstream CLI behavior; an Astro change to the subcommands would need a doc update (drift is caught by humans, not a gate — accepted for a two-line surface)
Enforcement
Section titled “Enforcement”- Testable consequences:
- TC-1:
dev:agentanddev:agent:stopexist inpackage.jsonand wrap the documentedastro devsubcommands.
- TC-1:
- Checks:
- TC-1 → check
script-contract(status: warn)
- TC-1 → check
- Not machine-checkable: upstream CLI behavior drift is caught by humans, not a gate (accepted above for a two-line surface).
- Graduation log: (empty at creation; entries added when a check changes status)