Delivery Factory · Part 4 · Conventions, Serve and Baseline
Conventions, serve and baseline: the project before the build
Three stages run before the pipeline builds or designs anything. conventions researches how this project does things. serve makes sure a preview answers. baseline captures what a component looks like now, so the end of the run has something to compare against. Repo: agentic-eds
Checked in README + code
Read in the agentic-eds README, pack.yaml, and the skills and scripts of these three stages. Source: agenticDraft/plugins, folder plugins/agentic-eds/. Paths are relative to that folder unless said otherwise.
Each step runs as its own isolated agent and returns a short result block. The next post covers the browser plugin that baseline uses. This post covers what the three steps themselves do.
Conventions
How this project does things
The stage eds-conventions always runs. It needs no tracker, design or browser: everything it reads was already written by the stages before it.
styles: design values against the design systemGrades each design value the extract stage retrieved against the project's adopted design system,
styles/design-system.md. A value either matches the system's token for that role, or drifts. When it drifts, the design wins, as an override scoped to the block the ticket touches. It also names font families the design uses that the project declares no@font-facefor. It never adds, downloads or substitutes a font. Runs only when a design reference is present or was requested.markup: how existing blocks scope their CSSClassifies every existing block's CSS by form: the
.blockname .childform, the bare tag form a header or footer block uses, an@scoperule, or amain .prefix. It reports which files drift from the form most blocks use, and which could not be classified at all. Always runs.component reuse: create or extendFor every component the ticket names, a script checks in a fixed order: the project's own
blocks/first, then the pack's pinned copy of the upstream block collection, and only then marks it new. When the upstream manifest cannot be read, the block is reported as unknown upstream, which is not the same as not there. It always names example blocks a new unit should follow, even when no component is named. Always runs.
Dispatched together. The three subagents are called in the same turn, because none of them depends on another's result. The stage waits for every dispatched one before it decides its own verdict.
One file for the plan. The stage writes design-conventions.md: one section per dispatched subagent, with its summary, and a final ## Exemplars section that is never empty. The plan stage reads this file as its only source of project conventions and does no research of its own. A finding that is not written here is lost to the rest of the run.
Its own words. Each subagent ends with a small outcome block (success, warning or failure). The stage writes its own result from them and never returns a subagent's outcome unchanged.
# design-conventions.md
## styles
<the subagent's summary, verbatim>
## markup
<the subagent's summary, verbatim>
## component reuse
<the subagent's summary, verbatim>
## Exemplars
blocks/<name>/
blocks/<name>/
Serve
Poll first, then start
The job of eds-serve is that something answers at the project's preview URL by the time it returns. It runs on every ticket.
- Clean up earlier runs' drafts: delete the drafts of items whose change is merged or closed, and stop the draft server once no recorded change is open. The result is written into the report but never changes this stage's verdict.
- Read
commands.serveandpaths.previewfrom.ai/project-config.yaml. No preview URL configured: fail. The stage never guesses one. poll-preview.shagainst the URL. If something already answers, pass. Nothing is started, and the report says this stage did not start what is running.- Nothing answered and a serve command is configured:
start-serve.shstarts it, writing a log and the process id. - Poll again on the ladder: five polls, at 0, 2, 4, 8 and 16 seconds, about thirty seconds in all.
- An answer before the ladder ends: pass. No answer: fail, naming this as a transient failure, with the process id and the log in the report.
Any HTTP status is an answer. A 404 or a 500 included. The question is whether the origin is bound, not whether one path exists. A preview path is configuration, and a poll that demanded a particular status would fail forever on a project whose configured path is not a served one.
Poll before starting. A server may already be up from an earlier run. Starting a second one against a bound port makes a process that dies on startup while the poll still succeeds against the first.
The server outlives the stage. It has to: every later stage that renders a page runs in a different isolated agent. The stage cleans up drafts, but nothing in the route stops the preview server. The report is the only record of the process that is left running, and the process id in it is the only handle.
Loopback needs the sandbox off. The default command sandbox denies connections to localhost every time, so the stage runs its three commands with the sandbox disabled, as the skill states, rather than trying sandboxed first.
Baseline
The before picture
eds-baseline runs only when the fact record names at least one component. It captures what each component looks like now, so the verify stage can compare before against after, not only after against the design.
- Resolve the browser plugin from the project config and read its operations:
render,captureandmeasure. Any of them missing: fail. - Take the component names from the fact record, or from the
blocks/<name>/paths the ticket names. find-baseline-target.pylists the pages git knows about and prints the first one that holds the component, as a page path and a URL. It never searchesdrafts/. The model adds no page the script did not print.renderthe page.captureit at 375, 768 and 1440 pixels.measurethe selector.<component>.- Write
baseline-capture.json: the URL, the components, each width's screenshot path (or that width's failure) and the measurements as the browser plugin reported them.
Same widths later. 375, 768 and 1440 are the widths the verify stage uses for its own capture, so the two runs line up.
Content outside the checkout. If a project's authored content is mounted from an external source, the search can see nothing even when a page genuinely exists live. The stage does not reach outside the checkout, and says that nothing was found.
# baseline-capture.json, the fields
target URL
components captured
per width: screenshot path, or that width's failure
per selector: the browser plugin's measurement,
unchanged, including found: false
Pass, warn, stop
Three stages, three sets of verdicts
Each stage ends with a result block: pass, warn or fail. Warn does not stop the route.
Conventions · pass
Every dispatched subagent succeeded.
Conventions · warn
At least one subagent warned. For example, the project has no blocks yet, or no design system is adopted, so there is nothing to grade against. The stage does not rank one warning above another.
Conventions · fail
The fact record is missing or empty, or a subagent failed. For example, the design reference file the extract stage should have written is missing. A subagent that cannot be resolved counts as a failure, not a gap to route around.
Serve · pass
The preview answered, whether it was already up or this stage started it.
Serve · fail
No preview URL configured. Or nothing answered and no serve command is configured. Or the command exited on startup. Or nothing answered before the ladder ran out.
Baseline · pass
All three widths were captured and every component's selector was found.
Baseline · warn
A width failed or a selector was not found, so the baseline is partial and says so. Or no page in the checkout holds the component, and nothing is written. That is a gap in the fixture content, not evidence the change broke anything. Verify treats a missing baseline as one of its own downgrade conditions.
Baseline · fail
The browser plugin or one of its operations is missing, no component can be identified, the search script errors, or the render fails.
What it doesn't cover
The limits, as stated
From the skills and the pack's README.
No teardown
The route has no step that stops the preview server. It runs until a human ends it.
Fonts
Conventions names missing font families and never adds one. Fonts are added by a human, once, with their license.
Drafts
Baseline never renders
drafts/. A ticket that compares against the current state is refused at readiness when a named component has no page outsidedrafts/.Next
The browser plugin behind baseline: four operations against a real Chromium.