CI and boundary enforcement
#An agent produces far better work when its environment tells it, immediately and automatically, what "correct" means. Pre-flight checks are that environment: linting, type-checking, tests, and — the part most teams skip — automated enforcement of architectural boundaries, so a module that reaches across a forbidden seam fails a check rather than slipping through review.
In the reference project's frontend module, those checks run twice: in the pre-commit hook and again in the CI pipeline. The hook catches a whole class of errors before anything lands, and the agent is capable enough to read a failed check, understand what it flagged, repair the issue in the same run, and re-run the checks. The result is a single coding pass that lands at markedly higher quality, because the checks — not the human — do the first review.
The boundaries are enforced the same way. Rather than trusting that an architectural rule will be remembered, the rule is encoded as a check that fails the build when it is crossed. The agent then works inside the guardrails by construction. Pre-flight checks are cheap to add and compound with every run; they are the highest-leverage investment in agent-assisted quality.
Concretely, every commit runs the same gate. It opens by checking the formatting of the changed files and running lint, type-check and tests for the packages the change touches and every package that depends on them, then runs thirty further checks, at most four at a time — each one a project-specific rule that no generic linter would know to look for:
- Navigation registryEvery navigation entry resolves to a route that exists, none is duplicated, and no platform exceeds its tab budget.
- Route parityEvery shared route in the reference app also exists in each whitelabel app.
- App iconsIcon and splash assets are present at the required dimensions, and the app manifests point at the files that are actually there.
- Admin guardsEvery admin page and layout imports the session guard, every admin layout forces dynamic rendering, and each page registered as naming a tenant in its URL also checks that the caller administers that tenant.
- Sticky footer coverageEvery infinite-scroll page is registered for the sticky footer, so the imprint and privacy links stay reachable below an endlessly loading list.
- Docs coverageThe documentation site carries a page for every catalogued feature.
- Locale parityThe supported-language set agrees across all four places it is independently declared.
- Brand completenessEvery brand is wired into every registry that must know about it, down to its logo, secret reference and test project.
- Brand SEOSEO blocks are present per brand, distinct from one another, and carry no leftover test sentinels.
- Brand contrastEvery whitelabel brand's colours meet WCAG contrast in light and dark mode, pressed states stand visibly apart from the resting state, and an approved exception holds only until its expiry date.
- Agent-docs structureThe agent documentation satisfies thirteen structural rules, including size budgets and a lifecycle status per document.
- Agent-docs truthThe repository paths and commands those docs cite still exist.
- Shell script lintThe commit gate's shell scripts are linted with ShellCheck, and the check refuses any version below a pinned minimum, so an older local binary cannot pass what CI rejects.
- Legal documentsEvery brand's legal content set exists, covers each language that brand advertises, and stays inside the permitted HTML vocabulary.
- Legal versionsA legal document cannot change without its version moving forward, and for terms and privacy the change classification must fit the size of that move and cannot be relabelled within a release line, judged against the previous commit.
- Mobile channel localesNotification-channel strings exist in every required language, with identical key sets.
- Design tokensNo web-only design token leaks into mobile code, where it would silently resolve to nothing.
- Text opacityNo contrast-checked text colour is dimmed with an opacity modifier, which would push it below its minimum contrast.
- Import firewallThe public SDK packages import nothing from the internal packages and only types from the shared message contract, so no internal code ships to a third party.
- Widget tierThe embeddable widget routes keep what they promise a third-party page: no client component outside the allowlist, no inbound message listener, no provider stack, and no import escaping the group.
- API prefixesEvery URL prefix the generated clients call is classified as browser-facing or service-internal, and the backend proxy's allowlist holds exactly the browser-facing ones: no wider, no narrower.
- Availability filtersEvery file that sets availability filters either uses a shared complete preset or is explicitly classified after review, because the backend switches some omitted filters on by default, and certain partial sets then return an empty list without an error.
- Dockerfile dependenciesEvery workspace dependency the web app declares is actually copied in the image build.
- Notification routesEvery notification event is explicitly mapped to a screen or explicitly marked as having none, and every mapped screen exists on both web and mobile and is registered as an app link.
- End-to-end test typesThe browser test suite is type-checked too — it sits outside the workspace, so the repository-wide type-check never reaches it.
- End-to-end test lintDedicated lint rules for the browser test suite find assertions that never run and tests still skipped by accident.
- Generated config freshnessThe committed generated configuration still matches the source it was generated from.
- Mock handler indexThe index of API mock handlers matches the handlers actually generated, so no endpoint can quietly drop out of the tests.
- Test mock isolationHand-written test mocks never sit in code other packages reuse, where they would replace the real module in every dependent package's tests.
- CI driftThe pull-request and main-branch pipelines are triggered by the same paths, and every check CI runs also runs on every local commit unless it is excluded by name with a stated reason, so no check can end up in CI alone by accident.
The list is worth reading as a shape rather than an inventory. Almost none of it is generic code quality; it is institutional knowledge — the things a reviewer would otherwise have to remember — encoded so that forgetting them is not possible.