-
Notifications
You must be signed in to change notification settings - Fork 0
Design Contracts
Session summaries (.serp/ai/summaries/**) are working notes an AI session keeps for itself and its children — useful, but not durable, not user-approved, and nothing gates implementation on them. Design Contracts are the durable layer above summaries: specs/**/*.design.yaml files, checked into the repo next to the .sidl/.suml files whose meaning they document, holding blocks with an explicit approval lifecycle. They're what lets an approved design — not just a chat transcript — be the thing that authorizes an AI session to write code, across as many services as a project has.
draft → proposed → approved / rejected / needs_update (approval)
not_started → generated → implemented → validated / stale / blocked (implementation)
Rule: an AI session may create draft/proposed blocks and propose changes, but only the user moves a block to approved — that's a human action a session must never take on itself, no exception. Marking a block generated/implemented/validated is looser: it's refused only for a draft/rejected block (a deliberate exception lets this also apply to a proposed block — see Design Sync below, where code can legitimately predate a design contract ever being reviewed). Evidence (which files implement a block) is optional, not required — the agent is trusted to have actually read the code, not mechanically forced to attach a fixed structure.
Design files follow spec ownership, not session kind — an interface's design file is named after the interface, not the service that implements it. A sequence/scenario has no design file of its own: its behavior is a block inside the owning service's design file.
| Scope | Path |
|---|---|
| Root / project | specs/serp.design.yaml |
| Common/shared type | specs/common/<module>.design.yaml |
| Service | specs/services/<group>/<service>/<service>.design.yaml |
| Interface | specs/services/<group>/<service>/<interface>.design.yaml |
| HMI component | same tree as a service |
| Deployment | specs/deployments/<deployment>.design.yaml |
| Sequence/scenario | no file of its own — a block inside the owning service's design file |
A design file, taken from a real generated example (AudioFocusService.design.yaml):
schema: serp.design.v1
scope:
kind: service
name: AudioFocusService
spec: specs/services/system/AudioFocusService/AudioFocusService.sidl
blocks:
- id: SVC-AudioFocusService
approval: proposed
description: "The AudioFocusService is the sole arbiter of audio focus for the
MultimediaPlayer system. It maintains which owner currently holds focus,
whether audio is being ducked by navigation, and which media source last
held focus — and it fires notifications as those states change. ..."
implementation_refs:
files:
- src/services/system/AudioFocusService/AudioFocusService.cpp
- src/services/system/AudioFocusService/AudioFocusService.hpp
symbols:
- MultimediaPlayer::AudioFocusServiceApproval and implementation status are split into a separate file, <same-name>.state.yaml, so an approved design and its current implementation truth don't fight over the same lines in review:
schema: serp.state.v1
scope:
kind: service
name: AudioFocusService
spec: services/system/AudioFocusService/AudioFocusService.sidl
blocks:
SVC-AudioFocusService:
implementation: implemented
refs:
files:
- src/services/system/AudioFocusService/AudioFocusService.cpp
- src/services/system/AudioFocusService/AudioFocusService.hpp
symbols:
- MultimediaPlayer::AudioFocusService
design_hash: sha256:cb63a1f9...
updated_at: 2026-07-15T15:57:13.111Z
updated_by:
role: service
session_id: service::system/AudioFocusService@mrm9e5f8q42qdesign_hash is what lets tooling notice a block's design changed underneath an already-implemented state (see Implementation Runs, which is built directly on this file pair).
Edits go through serp.design.patchBlock (and the approve/reject/propose tools, thin wrappers around it), never a raw file write — it mutates only the target block's fields in place and writes atomically, so every other block and every untouched comment survives byte-for-byte. A design file is meant to be reviewed as a diff.
Right-click a service/HMI/Architecture node in the SERP AI panel for:
-
Open Design Contract — opens the
*.design.yamlfile directly -
Approve / Reject / Request Changes Design Block… — prompts for a block, then copies a ready-to-paste
@serp designinstruction for you to hand to a session (the extension itself never talks to the MCP server — same pattern as Sync Session) - Show Design Diff — HEAD vs. working tree, in the built-in diff editor
A N stale / design drift: N badge can appear on Architecture/service/HMI nodes once a Sync Design or Show Design Drift run has populated the index — see below.
Pending decisions (serp.design.requestDecision/answerDecision) are for questions that genuinely need your input before a block can move forward. A decision raised inside a session's workflow also gets recorded as a critical workflow question, so the session can't advance past it silently.
Six validators back all of this: design_schema, design_approval_gate, design_status_consistency (catches impossible combinations, e.g. rejected + implemented), design_context_staleness, design_coverage (flags services/interfaces/HMI components with no design file yet), and design_reference_integrity.
Design Contracts assume greenfield order — design, then specs, then code. A project that already has specs and code before adopting this feature needs the reverse. Sync Design — one command, on the Architecture/service/HMI/sequence tree nodes (also a visible inline icon, not just right-click) — scans what already exists and proposes design blocks from it. Inferred design is never auto-approved: every block it writes starts at approval: proposed.
Running it on a single node syncs just that component. Running it on Architecture is a global sync — every component under specs/services/ plus the root project block, in one review.
The block a sync creates is a deliberately minimal skeleton — just an id, proposed, not_started — no guessed title, no guessed implementation status. Deciding what a block is for, and whether it's genuinely implemented, is left to a real read of the code, not a regex. That's the next step:
Right after you accept a Sync Design proposal ("Apply as Proposed"), the extension groups the newly created blocks by service/interface and spawns one headless AI session per scope to do the part a script can't: write a description in its own words (why the thing exists, how it behaves, notable specifics), and decide — from actually reading the code — whether each block is genuinely implemented, calling markImplemented/markGenerated itself when confident. It's explicitly forbidden from touching approval or approveBlock (a human decision, never the agent's), from creating/deleting blocks, or from editing anything outside its own scope.
These sessions are invisible under their own service node by construction (a distinct design-draft:: id prefix keeps them out of the service's session list) but visible in the Temp branch of the SERP AI tree while they run, plus a status-bar spinner (Drafting design text (N)). They disappear once finished — no history kept. A completion toast fires per scope. Disable auto-spawn with the serp.ai.design.autoDraftText setting.
Intake is a lightweight session kind for greenfield or pre-code work: discussing what you want at the domain level and proposing initial design contracts before any .sidl/.suml/source file exists. Its write scope is specs/**/*.design.yaml only.
Show Design Drift cross-references specs/design/code evidence and opens a markdown report on demand — this is a filesystem scan, so it's not run on every session's context load, only explicitly. A cheap advisory line ("Design contract is missing or stale for this scope — use Sync Design first") is added to session context from whatever the index last computed, without blocking anything.
Stale detection only covers "the member no longer exists" — a member whose signature changed while keeping its name (e.g. Double→Float) isn't separately flagged; re-running Sync Design will pick it up as part of the normal scan.
- SERP AI Sessions — session kinds, MCP tools, the Configuration and Settings panels
-
Implementation Runs — turns non-implemented/
needs_updatedesign blocks into spawned implementation sessions, project-wide - AI-Driven Development — how this fits into the overall spec → design → implementation flow
Getting Started
The Development Model
Architecture Language
Code Generator
- Generator Overview
- Generated Code Layout
- Deployment Configurations
- Lifecycle Backends
- CMake Integration
Framework Internals
- Core Concepts
- Services & Lifecycle
- Methods
- Properties
- Notifications
- Timers & Watchdog
- Promises & Async
- Streams
- Commands
- Logging
- Test Engine
- Transports
- Runtime & Debug Tools
VS Code Plugin
Examples