Skip to content

Decision Tree

When you ship a change, ask these questions in order. The first "yes" tells you which gate(s) to write or extend. You can stop at the first match or continue if your change touches multiple layers — gates compound.

Did your change touch the OpenAPI spec or any of its generated artifacts?

Yes →

  • openapi-validation already runs; if your edit introduces a new MCP-exposed operation, the gate enforces tool_name + min_tier + x-matter-lifecycle.primary for it. Run bun run gates --gate=openapi-validation locally.
  • openapi-mcp-drift runs generate-mcp-tools.ts against the new spec. If your edit changes the catalog, regenerate via bun run --filter matter-mcp-server generate-tools and commit. Don't manually edit apps/mcp/src/tools/generated.ts.

Did your change add or rename a route in apps/app?

Yes →

  • card-action-targets already runs. Any new navigate.to target in an exemplar CardSpec must resolve. If you added a new route, no action needed. If you renamed one, update any exemplar that referenced the old path.
  • route-manifest-property runs against the framework's own matcher; nothing to do unless you changed route-manifest.ts itself.

Did your change add a new typed Matter resource ID prefix (abc_...)?

Yes →

  • Add the prefix to packages/components/src/cards/resource-urls.ts RESOURCE_URL_BUILDERS. Map it to its canonical dashboard URL. card-action-targets will then resolve open_resource actions for that prefix.

Did your change touch the brand tokens (TS or CSS)?

Yes →

  • brand-tokens-drift asserts TS-CSS parity for the signature colors. If you added a new canonical color, extend the checks array in the gate. If you changed an existing color value in TS, update tokens.css to match (or vice versa).

Did your change touch the Prisma schema?

Yes →

  • Run bun run migrate locally. prisma-schema-drift asserts the schema is canonically formatted.
  • For schema-to-client drift, the standard bun run migrate workflow regenerates the client; no extra gate yet.

Did your change add or modify an AI emission (CardSpec, MCP tool output, document draft)?

Yes →

  • agent-output-schema asserts every exemplar parses against CardZ. If your change modifies CardZ, every exemplar must still validate; update them in lockstep.
  • For new AI capabilities, add a case to __evals__/<your-flow>-cases.json and write an eval-mode gate (template at packages/testing/templates/eval.template.ts).

Did your change touch the assistant's voice (marketing copy, brand README, docs index pages)?

Yes →

  • voice-judge runs in shadow mode against packages/brand/README.md + CLAUDE.md. Add your surface to the SURFACES array in the gate if it's load-bearing voice copy.
  • Set ANTHROPIC_API_KEY locally to activate the judge.

Did your change introduce a new third-party dependency?

Yes →

  • dependency-audit wraps bun audit and runs on every PR. No action needed unless a finding appears — then either upgrade the dep, swap it, or add an allowlist entry tied to a tracking issue + expiration.

Did your change touch the dispatcher's resolveResourceUrl or any pure parsing / matching function?

Yes →

  • dispatcher-fuzz and route-manifest-property cover those two specifically. For new pure functions, write a property gate using packages/testing/templates/property.template.ts. Property gates catch invariant violations example-based tests don't reach.

Did your change add or change a security-sensitive surface (auth, secrets, key handling)?

Yes →

  • secret-scan already runs on every commit and PR. If your change adds a new key prefix Matter mints, extend the patterns in packages/testing/src/gates/secret-scan.gate.ts.
  • Consider writing a mode: "static" + category: "security" gate that asserts your specific invariant (e.g. "no sk_live_* ever flows through this code path").

Nothing above matched my change

That's a signal in itself. If your change touches a surface no gate covers, ask:

  1. Could a small static check have caught the most likely regression class? (Often yes — emit a Finding when condition X is violated.)
  2. Could a property test assert an invariant over your function's input domain?
  3. Is there an "X must stay in sync with Y" relationship a drift gate would catch?

Write the gate. Templates at packages/testing/templates/. The framework's interface is complete — new gates just need a *.gate.ts file anywhere.

On this page