Skip to Content
Concepts

Core concepts

The five ideas that make PDS Stack different from every other AI workflow.

The memory

The part that compounds, and the reason the stack exists.

memory/ ├── identity.md the visual story, the floor, and what this product is NOT ├── design-system/ registries extracted from Figma — tokens, components, text styles ├── references/ annotated screenshots — WHY it works, what we took, what we did not ├── directions/ every direction judged — retained AND refused, with the reason └── decisions/ structural decisions, design-shaped

Reading order in the DIRECTION phase, and never the reverse: identity → directions → design-system → references → decisions. Starting from references before the directions already settled is how you repropose what was refused.

A refused direction is worth more than a retained one. It is the only artefact that stops the next brief re-suggesting what this product has already rejected. Nothing is ever deleted from directions/.

setup builds the memory from Figma, from your code, from four declared answers — or, when there is nothing at all, through a genesis that writes identity.md with you. No empty store ever blocks a phase: it is signalled and filled.

The direction brief

A creative contract, written by BOB’s brief half and approved — gate ① — before the scope is frozen and before anything is generated. It captures visual direction, three defining words, constraints, and references, read out of the memory. This is the system’s core gate — it turns taste from a hope into a requirement.

The three lanes

Ceremony matches stakes. The lane is the first question asked, and the default is Sketch.

LaneWhenPhasesHuman gates
Sketch (default)explore, iterate — the 80 %DIRECTION → PRODUIRE1
Standarda screen or component going to review or devall four2
Systemit touches the design systemall four + written decision3

Hard budget: three human gates, about twelve steps. Any rule that does not fit is cut, not documented. In Sketch there is no spec file, no score, no written decision — relaunching is cheaper than documenting.

The cycle

(recherche) → DIRECTION → CADRE → PRODUIRE → (handoff) → JUGER + MÉMORISER

Direction first, and the scope is framed by it — not before it. /pds asks the lane first (Sketch by default) and never crosses a gate for you. Production starts with a clickable HTML prototype in every lane (/bob --proto) — Sketch stops there; Standard and System go on to a Figma frame, then code when modules.code is on. Judgment writes back into the memory the next direction reads.

Research and handoff bookend the cycle without ever gating it. EVE (discovery, optional) preps interviews, synthesizes research and restitutes findings before DIRECTION exists to read them. A handoff skill (optional) turns an approved Figma frame into a dev-ready spec after PRODUIRE, when the implementation leaves this cycle.

Two verdicts, never averaged

Conformance is a /20 computed against what was written — spec, design system, ADRs. Direction is binary, blocking, and the designer alone renders it. Neither overrides the other, and they are never merged into a single number.

P-001 cycle 1 scored 18/20 = SHIPPED and was rejected outright by the designer. With four conformance dimensions and no aesthetic one, that was the only possible outcome. The case is now a regression test for the gate itself.

A refused direction goes back to DIRECTION, never to the builder. It is not a list of bugs to fix; it is a direction to retake.

Hard constraints

These are enforced by the agents, not left to discipline:

  • No code without statut: VALIDATED in the spec
  • Nothing produced before the direction brief is approved — gate ①
  • TypeScript strict — zero any, zero @ts-ignore
  • Components cap at 150 lines
  • /components/ui/ is read-only (Shadcn owns it) — the pre-commit guard warns on it, and ANALYZER scores a hand edit there as a blocker
  • Consult the ADR index before any architecture or dependency decision

Guardrails

A constraint an agent honours is only as strong as the agent’s attention. Three of the above are also checked by tooling, so they hold under a careless operator too.

Two git hooks, installed on request and bypassable with --no-verify:

  • commit-msg — product code needs a Ref: feature_<id> trailer, and the spec it names must be VALIDATED. A commit that can’t reference a spec is outside the frozen scope, which is a new RAY cycle, not a commit.
  • pre-commit — any and @ts-ignore, the line cap from your STACK.md, and tsc --noEmit. Type errors are filtered to the files in the commit, so pre-existing breakage elsewhere warns instead of blocking. hook_exclude in STACK.md lists paths the guards should ignore.

Sessions and the context budget

Everything that enters a conversation is paid again on every turn after it. Measured on nine sessions before V5, the main conversation was ~75 % of the spend, up to 669k of context. Three rules follow (ADR-014):

  • One phase, one conversation. At each gate the conductor writes agent-system/sessions/state_<feature>.md — lane, what was approved, what was produced — and proposes /pds reprendre <feature> in a new session. Past ~150k of context it says so.
  • Session 0 for a project (ADR-017). /pds cadrer <project> gathers the context once and writes project_<project>.md — context and dispatch plan, ~60 lines — plus a state file per feature. No gate is crossed there. Every later session reads that file and its own state file, never another session’s history.
  • Relay, never fork. A long or drifting conversation is cut by updating the state file and opening a fresh session. A fork keeps the whole history — the cost ADR-014 cut.
  • A context thermostat (ADR-018). The threshold is not left to memory: a UserPromptSubmit hook measures the context on every prompt. At 120k it reminds Claude to finish the step and propose the relay; at 150k the relay comes before anything else. You see one line (⬡ Contexte 160k — relais demandé); the hook never blocks your prompt.
  • One lot, one fresh builder. RAY cuts the spec into lots of about 50 turns; each lot, and each correction round, gets a new bob-build — never a resumed one.
  • A context budget. Text before images (find, snapshot <ref>, eval); large files read by section; heavy inputs (a PDF, a site) digested once into memory/references/. bob-build cannot read an image at all: a PreToolUse guard in .claude/settings.json, scoped to its agent_type, blocks it — and check-parity executes that guard on three cases at every release.

The guard used to live in bob-build’s frontmatter. Pulse run 6 showed a frontmatter hook never fires when the agent runs as a subagent; the same hook in .claude/settings.json does. A mechanical claim is only mechanical once something has run it.

Each agent carries its model, effort and turn cap in its frontmatter:

AgentModelEffortMax turns
bob-briefopushigh25
bob-buildsonnetmedium80 (budget ~50 per lot)
rayopusmedium40
analyzeropusmedium60

Chat output follows output: short in STACK.md — the result first, the file path, the decision expected. Say « détaille » or pass --full for the long form once.

What these rules cost and save, measured on real projects: Cost.

Verification tools

ToolUsed byFor
Playwright CLIBOB (prototype), ANALYZERstructure, states and measured values, in text
impeccableBOB (prototype), ANALYZER (/20, dimension B)a mechanical anti-slop floor — waived where it contradicts the approved direction

A tool that is not installed blocks nothing: the agent says so in one line and goes on (ADR-015).

Proof over inspection

Every acceptance criterion a machine can decide carries exactly one assertion, and BOB runs it before handing over — no test framework is installed, and there is no coverage target. Criteria come back proven, unproven (visual, with the reason) or failed. “Believed OK” is not a status: that phrasing is precisely how a real defect once reached ANALYZER instead of being caught at build time. ANALYZER re-runs the assertions rather than trusting the output it was handed, and deducts a point per code-decidable criterion shipped without one.

Assertions live in a [feature].check.ts next to the logic they prove. If the project already has a runner (vitest, jest, node:test), BOB uses it. If it has none, nothing gets installed — the file compiles through the TypeScript compiler strict_mode already requires:

npx tsc lib/[feature]/*.ts --outDir .proof --module commonjs --target ES2022 --strict --skipLibCheck node .proof/[feature].check.js

.proof/ is disposable, and check files use a local equality helper rather than node:assert — that import needs @types/node, which plenty of front-end projects do not carry.

That command is in the docs because the first version of this rule was not runnable. It said “run it with whatever the project can already execute”, which in a moduleResolution: bundler project is nothing. Pulse run 3 found it after three failed attempts.

Last updated on