4.9 KiB
SYSTEM.md — the semantic contract graph
SYSTEM.md is an optional repo-root file declaring what each component
is, what it owns, and the role-level contracts between components.
Its consumer is /plan-rollout. The skill reads it to sharpen slice
ordering and surface coordinated-deploy edges; it falls back to path
heuristics when absent.
Not a package manifest. Not an import graph. Those are discovered at runtime (AST, grep, manifests) and would go stale within a week if declared. SYSTEM.md captures only what a human knows: "auth mints session tokens middleware enforces; session-format change without middleware redeploy breaks sessions."
Schema (v1 — intra-repo)
---
version: 1
components:
- name: <unique identifier>
path: <repo-relative path>
kind: component # or: leaf-util | types-only (default: component)
role: <one-line job description>
owns:
- <data surface, table, API, or feature this component owns>
contracts:
- with: <other component name>
nature: <plain-English relationship>
breaks-if: <specific human action that violates the contract>
rollout-edge: <hard | soft>
note: <runtime-only | types-only | legacy | free text> # optional
rollout-order: <integer; lower ships first; equal = parallel>
---
# System Map
<Free-form human notes: stability, anti-patterns, deploy-edge lessons
from past incidents. Not parsed.>
Field reference
| Field | Meaning |
|---|---|
name |
Unique identifier referenced by other components' contracts. Renames cascade. |
path |
File or dir under the repo root. Used for component-membership lookups. |
kind |
component (default), leaf-util (utils dirs, no contracts), types-only (interfaces, no runtime). leaf/types are skipped during reconciliation. |
role |
One sentence: what this component does in the system. Not what it contains. |
owns |
Data surfaces / tables / APIs / features this component is source-of-truth for. Dual ownership is a design smell. |
contracts[].with |
Other component's name. Must match a declared component. |
contracts[].nature |
Plain-English description of the relationship. |
contracts[].breaks-if |
Specific human action that violates the contract. This is what /plan-rollout reads to detect coordinated-deploy stages. |
contracts[].rollout-edge |
hard = must deploy together. soft = can lag. |
contracts[].note |
runtime-only (DB/HTTP/bus coupling — no import edge expected), types-only, legacy, or free text. |
rollout-order |
Integer. Lower ships first. Equal values can ship in parallel. |
Example
---
version: 1
components:
- name: auth
path: src/auth
role: authentication + session lifecycle
owns: [user table, session table, JWT minting]
contracts:
- with: middleware
nature: middleware enforces session tokens auth mints
breaks-if: session payload schema changes without middleware redeploy
rollout-edge: hard
rollout-order: 1
- name: middleware
path: src/middleware
role: request routing + auth enforcement
owns: [request context shape]
contracts:
- with: gateway
nature: gateway consumes req.user set by middleware
breaks-if: req.user shape changes without gateway redeploy
rollout-edge: hard
rollout-order: 2
- name: gateway
path: src/gateway
role: external HTTP surface
owns: [public API schema]
contracts: []
rollout-order: 3
- name: utils
path: src/utils
kind: leaf-util
role: shared helpers — imported freely without contracts
owns: []
contracts: []
rollout-order: 0
---
# System Map
auth and middleware are the security boundary. Session-format or
user-context shape changes are coordinated deploys (rollout-edge: hard).
We learned this in Feb 2025 when a session serializer change shipped
40 minutes ahead of middleware and logged everyone out.
How /plan-rollout uses it
- File → component mapping. Changed files are bucketed into the
slice for their component (matched by
path, longest-match wins). Without SYSTEM.md, the skill falls back to top-level-dir bucketing. - Slice ordering. Slices are sorted by
rollout-order.leaf-utilandtypes-onlycomponents float to slice 0. - Hard-edge enforcement. When a changed-file set spans both sides
of a
rollout-edge: hardcontract, those files merge into one slice tagged "coordinated deploy required — <breaks-if reason>". - Reconciliation flags (informational). Mismatches between declared
contracts and discovered imports surface in the output:
import-without-contract,contract-without-imports,rollout-order-inversion. Never blocking.
Out of scope (v1)
No scaffolder. Write SYSTEM.md by hand or copy the example. Scaffolding
that walks top-level dirs and infers role from README/package.json
is a v2 follow-up.