Appearance
Repository and gates
This page: how the scaffolder repository is organized and what keeps it honest. For the anatomy of a generated app, see Project structure.
This repository produces one publishable artifact — the create-dpas-app CLI — and the application it generates.
packages/create-dpas-app/ the CLI (prompts, flags, safe generation)
templates/default/ the golden app — a real, tested workspace member
examples/generated-default/ committed generator output, drift-gated in CI
docs/ this documentation + ADRs
scripts/ example regen/drift check + scaffold smoke testThe template-first rule
templates/default is a normal, running application, not a bag of files with placeholders. It has its own tests, lint, typecheck and build, and it is a workspace member you can pnpm dev directly. The CLI's build step copies it verbatim into the package (renaming .gitignore → gitignore, which npm would otherwise strip), and generation is name substitution plus .env creation — nothing more.
That is the property that keeps the scaffolder honest: anything the generated app can do, the template can do here, in this repository, with the same tests.
Verification pyramid
- Contract tests —
pnpm test. Capability discovery, lifecycle, staleness, binding, confirmation; domain governance; host protocol units; CLI unit tests. No model, no network, no browser. - End-to-end —
pnpm test:e2e. Playwright against a production build: the live pipeline under a scriptedLanguageModelV2(MODEL_PROVIDER=mock), URL-synced narrowing, the chase dialog, and role authority. - Scaffold smoke —
pnpm test:scaffold. Builds the CLI, generates a fresh app in a temp directory, installs it standalone, and runs that app's lint, typecheck, tests, build and deterministic browser tests. - Drift gate —
pnpm check:example. The committedexamples/generated-defaultmust equal current generator output byte-for-byte. After changing the template, runpnpm regen:example. - View gate —
pnpm view:check. The capability contract compiled from the template's source must equal the committed.agent-surface/contract.json, and each difference is reported as widening, narrowing or neutral.pnpm view:inspectprints the same contract to read rather than to gate. After changing a capability, runpnpm view:snapshotintemplates/defaultand commit the artifact. - Domain gate —
pnpm domain:check. The same bargain for the other plane: the inventory read fromserver/runtime.ts'sgovernanceexport must equal the committedcapabilities.snapshot.json.pnpm domain:inspectprints it as a table, runtime policies included. Update withpnpm domain:snapshot.
Review a diff in either artifact like an API diff, because it is one — a changed description is a changed prompt, and a capability that gains a surface has gained an audience. What the domain gate does not do is evaluate policies: it reports that gate-model-writes and analyst-hides-writes exist and in which phases, never which capabilities they gate. A 0 in its APPROVAL column is a statement about metadata, not about reachability.
CI runs lint, typecheck, tests, build and the three gates on Node 22 and 24; the e2e and scaffold-smoke suites run once, on 22. A separate job installs a generated app with npm to catch pnpm-only assumptions, and the docs site is built on every run so a dead link fails the build.
Working on the template
bash
pnpm install
pnpm dev # templates/default on :3000
pnpm lint && pnpm typecheck && pnpm test && pnpm build
pnpm test:e2e
pnpm test:scaffold
pnpm view:inspect # what an agent can reach in the view plane
pnpm view:check # …and whether the committed contract still says so
pnpm domain:inspect # the same two questions for the domain plane
pnpm domain:check
pnpm regen:example # after any template changeTwo review habits carry unusual weight here:
- Both inventories are API.
templates/default/.agent-surface/contract.jsonrecords the view plane andcapabilities.snapshot.jsonthe domain plane;pnpm view:checkandpnpm domain:checkgate them. Review their diffs like API diffs — a changed description is a changed prompt. - Exposure is an architectural decision, not a flag. If you add a domain operation, decide direct tool or contextual reference and never both; the host rejects the catalog either way, but the decision belongs in review.
Documentation
Three guides ship inside every generated app, in templates/default/docs/, and are the single source for their pages on this site: Architecture, Adding a capability and Security model are @included from there, so the app and the site can never drift. Edit them in the template, never twice.
Everything else — this page, the concepts, the reference and the ADRs — lives in docs/. Root markdown (README, CONTRIBUTING, SECURITY, CODE_OF_CONDUCT) is @included by wrapper pages under /project, for the same reason.
bash
pnpm docs:dev # local docs site with hot reload
pnpm docs:build # static build (also checks for dead links)
pnpm docs:preview # serve the built siteArchitectural decisions get an ADR: Decision records. Contribution workflow and release process: Contributing.