odd-studio 2.4.1 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/odd-studio.js CHANGED
@@ -41,8 +41,8 @@ program
41
41
  // ── init ──────────────────────────────────────────────────────────────────────
42
42
  program
43
43
  .command('init [project-name]')
44
- .description('Scaffold a new ODD project and install the /odd skill into Claude Code')
45
- .option('--skip-skill', 'Skip installing the /odd skill globally (advanced)')
44
+ .description('Scaffold a new ODD project and install /odd + excalidraw skills into Claude Code')
45
+ .option('--skip-skill', 'Skip installing the /odd and excalidraw skills globally (advanced)')
46
46
  .option('--skip-hooks', 'Skip installing safety hooks (not recommended)')
47
47
  .option('--yes', 'Accept all defaults without prompting')
48
48
  .action(async (projectName, options) => {
@@ -74,18 +74,24 @@ program
74
74
  process.exit(1);
75
75
  }
76
76
 
77
- // 2. Install /odd skill
77
+ // 2. Install /odd skill and excalidraw skill
78
78
  if (!options.skipSkill) {
79
- print.step(2, 5, 'Installing /odd skill into Claude Code...');
79
+ print.step(2, 5, 'Installing /odd skill and excalidraw skill into Claude Code...');
80
80
  const spinner2 = ora({ text: '', indent: 4 }).start();
81
81
  try {
82
- const result = await installSkill(PACKAGE_ROOT);
82
+ const { default: installExcalidraw } = await import('../scripts/install-excalidraw.js');
83
+ await Promise.all([
84
+ installSkill(PACKAGE_ROOT),
85
+ installExcalidraw(PACKAGE_ROOT)
86
+ ]);
83
87
  spinner2.stop();
84
- print.ok('Skill installed → ' + chalk.cyan(result.destination));
88
+ print.ok('/odd skill installed → ' + chalk.cyan('~/.claude/skills/odd/'));
89
+ print.ok('excalidraw skill installed → ' + chalk.cyan('~/.claude/skills/excalidraw/'));
85
90
  } catch (e) {
86
91
  spinner2.stop();
87
- print.warn('Could not install skill automatically: ' + e.message);
92
+ print.warn('Could not install skills automatically: ' + e.message);
88
93
  print.info('Manual install: copy ' + chalk.dim('skill/') + ' to ' + chalk.dim('~/.claude/skills/odd/'));
94
+ print.info('excalidraw skill: available via ' + chalk.dim('/excalidraw') + ' command in Claude Code');
89
95
  }
90
96
  } else {
91
97
  print.step(2, 5, 'Skipping skill install (--skip-skill)');
@@ -198,10 +204,11 @@ program
198
204
  // ── upgrade ───────────────────────────────────────────────────────────────────
199
205
  program
200
206
  .command('upgrade')
201
- .description('Upgrade the /odd skill and hooks to the latest version')
207
+ .description('Upgrade the /odd skill, excalidraw skill, and hooks to the latest version')
202
208
  .action(async () => {
203
209
  print.logo();
204
210
  const { default: installSkill } = await import('../scripts/install-skill.js');
211
+ const { default: installExcalidraw } = await import('../scripts/install-excalidraw.js');
205
212
  const { default: setupHooks } = await import('../scripts/setup-hooks.js');
206
213
 
207
214
  console.log(chalk.bold(' Upgrading ODD Studio...\n'));
@@ -214,6 +221,14 @@ program
214
221
  s1.fail('Skill update failed: ' + e.message);
215
222
  }
216
223
 
224
+ const s1b = ora({ text: 'Updating excalidraw skill...', indent: 4 }).start();
225
+ try {
226
+ await installExcalidraw(PACKAGE_ROOT, { force: true });
227
+ s1b.succeed('Excalidraw skill updated');
228
+ } catch (e) {
229
+ s1b.fail('Excalidraw skill update failed: ' + e.message);
230
+ }
231
+
217
232
  const s2 = ora({ text: 'Updating hooks...', indent: 4 }).start();
218
233
  try {
219
234
  await setupHooks(PACKAGE_ROOT, { force: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "odd-studio",
3
- "version": "2.4.1",
3
+ "version": "2.6.0",
4
4
  "description": "Outcome-Driven Development for Claude Code — a planning and build harness for domain experts building serious software with AI.",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -0,0 +1,208 @@
1
+ ---
2
+ name: excalidraw
3
+ description: Wireframe and diagram generation for UI/design planning
4
+ version: 1.1.0
5
+ author: ODD Studio
6
+ source: https://github.com/excalidraw/excalidraw
7
+ tags:
8
+ - ui-design
9
+ - wireframing
10
+ - planning
11
+ - visualization
12
+ ---
13
+
14
+ # Excalidraw Wireframe Generator
15
+
16
+ Generate `.excalidraw` wireframe files that can be opened in excalidraw.com or the VS Code Excalidraw extension.
17
+
18
+ ## How This Skill Works
19
+
20
+ When invoked, you MUST generate a valid `.excalidraw` JSON file. This is not a documentation skill — it is a generation skill. You produce output.
21
+
22
+ ## Output Format
23
+
24
+ Every invocation produces a `.excalidraw` file saved to `docs/wireframes/` in the project directory. The file is valid Excalidraw JSON that can be:
25
+ - Dragged into https://excalidraw.com for interactive editing
26
+ - Opened in VS Code with the Excalidraw extension
27
+ - Exported as PNG or SVG from either tool
28
+
29
+ ## Excalidraw JSON Schema
30
+
31
+ An `.excalidraw` file is JSON with this structure:
32
+
33
+ ```json
34
+ {
35
+ "type": "excalidraw",
36
+ "version": 2,
37
+ "source": "odd-studio",
38
+ "elements": [ ... ],
39
+ "appState": {
40
+ "gridSize": null,
41
+ "viewBackgroundColor": "#0a0a0f",
42
+ "theme": "dark"
43
+ },
44
+ "files": {}
45
+ }
46
+ ```
47
+
48
+ ### Element Types
49
+
50
+ Every element in the `elements` array has these common fields:
51
+
52
+ ```json
53
+ {
54
+ "id": "unique-id",
55
+ "type": "rectangle|ellipse|diamond|text|line|arrow",
56
+ "x": 0,
57
+ "y": 0,
58
+ "width": 100,
59
+ "height": 50,
60
+ "angle": 0,
61
+ "strokeColor": "#495057",
62
+ "backgroundColor": "#1e1e2e",
63
+ "fillStyle": "solid",
64
+ "strokeWidth": 1,
65
+ "roughness": 0,
66
+ "opacity": 100,
67
+ "roundness": { "type": 3 },
68
+ "seed": 1001,
69
+ "version": 1,
70
+ "isDeleted": false,
71
+ "boundElements": null,
72
+ "link": null,
73
+ "locked": false
74
+ }
75
+ ```
76
+
77
+ **Rectangle** — Use for containers, cards, buttons, inputs, navigation bars, progress bars:
78
+ - Set `roundness: { "type": 3 }` for rounded corners (cards, buttons)
79
+ - Set `roundness: null` for sharp corners (sidebars, headers)
80
+ - For buttons: small height (28-36), accent `backgroundColor`, `"transparent"` `strokeColor`
81
+ - For cards: `backgroundColor: "#313244"`, `strokeColor: "#495057"`
82
+ - For progress bars: two overlapping rectangles (background + fill)
83
+
84
+ **Text** — Use for labels, headings, body text:
85
+ ```json
86
+ {
87
+ "type": "text",
88
+ "text": "Your label here",
89
+ "fontSize": 14,
90
+ "fontFamily": 1,
91
+ "textAlign": "left",
92
+ "verticalAlign": "top"
93
+ }
94
+ ```
95
+ - Headings: `fontSize: 20-28`, `strokeColor: "#cdd6f4"`
96
+ - Body text: `fontSize: 13-14`, `strokeColor: "#cdd6f4"`
97
+ - Muted/secondary: `fontSize: 12-13`, `strokeColor: "#6c7086"`
98
+ - Accent text: `strokeColor: "#a78bfa"` (or project accent colour)
99
+
100
+ **Ellipse** — Use for avatars, status indicators:
101
+ - Equal width/height for circles
102
+
103
+ **Diamond** — Use for badges, decorative icons:
104
+ - Good for achievement/badge indicators
105
+
106
+ **Line** — Use for separators, connectors:
107
+ ```json
108
+ {
109
+ "type": "line",
110
+ "points": [[0, 0], [200, 0]]
111
+ }
112
+ ```
113
+
114
+ **Arrow** — Use for flow indicators, data flow diagrams:
115
+ ```json
116
+ {
117
+ "type": "arrow",
118
+ "points": [[0, 0], [200, 0]],
119
+ "startArrowhead": null,
120
+ "endArrowhead": "arrow"
121
+ }
122
+ ```
123
+
124
+ ### Colour Palettes
125
+
126
+ **Dark mode (Catppuccin Mocha — default for ODD Studio):**
127
+ - Background: `#1e1e2e`
128
+ - Surface/cards: `#313244`
129
+ - Surface darker: `#181825`
130
+ - Border: `#495057`
131
+ - Muted surface: `#45475a`
132
+ - Text primary: `#cdd6f4`
133
+ - Text muted: `#6c7086`
134
+ - Accent purple: `#a78bfa`
135
+ - Success green: `#a6e3a1`
136
+ - Warning amber: `#fab387`
137
+ - Error red: `#f38ba8`
138
+ - Canvas background: `#0a0a0f`
139
+
140
+ **Light mode:**
141
+ - Background: `#ffffff`
142
+ - Surface/cards: `#f8f9fa`
143
+ - Border: `#dee2e6`
144
+ - Text primary: `#212529`
145
+ - Text muted: `#6c757d`
146
+ - Accent blue: `#3b82f6`
147
+ - Canvas background: `#f5f5f5`
148
+
149
+ ### Layout Patterns
150
+
151
+ **Desktop (1280x800):**
152
+ - Sidebar: x=0, width=240, full height
153
+ - Main content: x=280 (240 sidebar + 40 padding)
154
+ - Content width: ~960px
155
+ - Card grid: 3 columns at 300px each with 30px gaps
156
+
157
+ **Mobile (375x812):**
158
+ - Full-width cards with 16px padding each side (x=16, width=343)
159
+ - Header bar: height=60, full width
160
+ - Bottom tab bar: y=752, height=60, full width
161
+ - Stack cards vertically with 16px gaps
162
+
163
+ **Tablet (768x1024):**
164
+ - 2-column card grid
165
+ - Collapsible sidebar or top navigation
166
+
167
+ ### Wireframe Composition Rules
168
+
169
+ 1. **Always include a label** above each wireframe frame identifying it (e.g., "DESKTOP — Student Dashboard (1280x800)")
170
+ 2. **Use realistic content** — not "Lorem ipsum". Use domain-specific text from the specification.
171
+ 3. **Show the key outcome flow** — the most important screen the persona interacts with.
172
+ 4. **Include navigation** — sidebar on desktop, bottom tabs on mobile.
173
+ 5. **Show data states** — progress bars should show realistic percentages, cards should have real titles.
174
+ 6. **Use the project's accent colour** consistently for interactive elements (buttons, active tabs, links).
175
+ 7. **Keep `roughness: 0`** for clean wireframes. Use `roughness: 1` only if a hand-drawn sketch style is requested.
176
+
177
+ ### Generating Multiple Views
178
+
179
+ When generating wireframes for Step 9b (UI & Design Decision), create separate files for each design approach:
180
+
181
+ - `docs/wireframes/minimalist-dark.excalidraw` — dark mode, minimal, shadcn/ui
182
+ - `docs/wireframes/dense-dashboard-light.excalidraw` — light mode, data-dense, tables
183
+ - `docs/wireframes/minimal-accessible.excalidraw` — high contrast, large targets, WCAG AAA
184
+ - `docs/wireframes/brand-driven.excalidraw` — custom palette, domain-specific visual language
185
+
186
+ Each file should contain both desktop and mobile views side-by-side on the same canvas:
187
+ - Desktop frame at x=0
188
+ - Mobile frame at x=(desktop width + 120)
189
+
190
+ ### Seed Values
191
+
192
+ Every element needs a unique `seed` value (integer). Use a simple incrementing counter:
193
+ - Desktop elements: 1001, 1002, 1003...
194
+ - Mobile elements: 2001, 2002, 2003...
195
+ - Additional views: 3001, 3002, 3003...
196
+
197
+ ## Usage
198
+
199
+ When the `/excalidraw` command is invoked with arguments, parse the arguments to understand:
200
+ 1. What to wireframe (which screen, which persona, which outcome)
201
+ 2. Which design approach (dark/light, minimal/dense, accessible, brand-driven)
202
+ 3. Which devices (desktop, mobile, tablet)
203
+
204
+ Then generate the `.excalidraw` JSON file using the schema above and save it to `docs/wireframes/[design-approach-name].excalidraw`.
205
+
206
+ After generating, tell the user:
207
+ - The file path
208
+ - How to open it: "Drag this file into excalidraw.com to view and edit interactively, or open it with the VS Code Excalidraw extension."
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+ import fs from 'fs-extra';
3
+ import path from 'path';
4
+ import os from 'os';
5
+
6
+ /**
7
+ * Installs the excalidraw skill into Claude Code.
8
+ *
9
+ * Copies the SKILL.md (with full generation logic) from the bundled
10
+ * excalidraw-skill directory to ~/.claude/skills/excalidraw/
11
+ */
12
+ export default async function installExcalidraw(packageRoot, options = {}) {
13
+ const source = path.join(packageRoot, 'scripts', 'excalidraw-skill');
14
+ const destination = path.join(os.homedir(), '.claude', 'skills', 'excalidraw');
15
+
16
+ // Ensure ~/.claude/skills/ exists
17
+ await fs.ensureDir(path.join(os.homedir(), '.claude', 'skills'));
18
+
19
+ // If destination exists and not forcing, back it up
20
+ if (fs.existsSync(destination) && !options.force) {
21
+ const backup = destination + '.backup-' + Date.now();
22
+ await fs.move(destination, backup);
23
+ }
24
+
25
+ // Copy the excalidraw skill directory (contains SKILL.md with generation logic)
26
+ await fs.copy(source, destination);
27
+
28
+ return { destination };
29
+ }
@@ -17,11 +17,12 @@ const pkg = new URL('..', import.meta.url).pathname.replace(/\/$/, '');
17
17
 
18
18
  Promise.all([
19
19
  import('./install-skill.js').then(({ default: installSkill }) => installSkill(pkg)),
20
+ import('./install-excalidraw.js').then(({ default: installExcalidraw }) => installExcalidraw(pkg)),
20
21
  import('./setup-hooks.js').then(({ default: setupHooks }) => setupHooks(pkg)),
21
22
  import('./setup-mcp.js').then(({ default: setupMcp }) => setupMcp()),
22
23
  ])
23
24
  .then(() => {
24
- console.log('✓ ODD Studio: /odd skill, safety hooks, and ruflo memory installed into Claude Code');
25
+ console.log('✓ ODD Studio: /odd skill, excalidraw skill, safety hooks, and ruflo memory installed into Claude Code');
25
26
  console.log(' → Restart Claude Code now to activate ruflo memory and hooks.');
26
27
  console.log(' Run: npx odd-studio init [project-name] to scaffold your first project.');
27
28
  })
@@ -41,6 +41,18 @@ export default async function scaffoldProject(targetDir, projectName) {
41
41
  await fs.writeJson(stateFile, state, { spaces: 2 });
42
42
  }
43
43
 
44
+ // Create .vscode/extensions.json with recommended extensions
45
+ const vscodeDir = path.join(targetDir, '.vscode');
46
+ const extensionsFile = path.join(vscodeDir, 'extensions.json');
47
+ if (!fs.existsSync(extensionsFile)) {
48
+ await fs.ensureDir(vscodeDir);
49
+ await fs.writeJson(extensionsFile, {
50
+ recommendations: [
51
+ 'pomdtr.excalidraw-editor'
52
+ ]
53
+ }, { spaces: 2 });
54
+ }
55
+
44
56
  // Initialise git if not already a repo
45
57
  const gitDir = path.join(targetDir, '.git');
46
58
  if (!fs.existsSync(gitDir)) {
package/skill/SKILL.md CHANGED
@@ -250,17 +250,23 @@ Type `*build` to begin, or `*status` to see the full phase progress.
250
250
 
251
251
  Generate the IDE Session Brief. This is a standalone document that a developer or AI coding agent can use to execute a build session without needing to ask planning questions.
252
252
 
253
- Load `docs/plan.md` and all outcome files from `docs/outcomes/`. Generate `docs/session-brief.md` with:
253
+ Load `docs/plan.md` and all outcome files from `docs/outcomes/`. Check `.odd/state.json` for the current `sessionBriefCount` (default 0 if not set). Generate `docs/session-brief-[N].md` where N is the current count.
254
+
255
+ Include:
254
256
 
255
257
  - Project overview (one paragraph)
256
258
  - Active persona(s) for this session
257
259
  - Outcomes in scope (with full 6-field specification)
258
260
  - Contracts in play (what is produced, what is consumed)
261
+ - Available from previous phases (contracts already built)
259
262
  - Verification steps for each outcome
260
263
  - Build sequence (which outcome to start, which depends on which)
261
264
  - Any known constraints or failure paths to handle
265
+ - Changes from original plan (if any reconciliation has occurred)
266
+
267
+ Increment `sessionBriefCount` in `.odd/state.json`.
262
268
 
263
- After writing the file, display: "Your Session Brief has been written to docs/session-brief.md. Open it in your IDE or share it with your build AI to begin the session."
269
+ After writing the file, display: "Session Brief [N] has been written to docs/session-brief-[N].md. Open it in your IDE or share it with your build AI to begin the session."
264
270
 
265
271
  ---
266
272
 
@@ -587,7 +593,7 @@ At key moments in the methodology, proactively explain why the current step matt
587
593
  "Checkpoint runs automatically every time you confirm an outcome. It scans what was just built for security issues — exposed secrets, missing authentication checks, injection vulnerabilities — and briefs the build agent to fix anything it finds before you move on. You do not need to understand what it found or how it was fixed. Security is not a separate concern in ODD Studio. It is built into the rhythm of the build."
588
594
 
589
595
  **Phase complete:**
590
- "Phase complete. All outcomes in this phase have been verified and cleared by Checkpoint. The contracts they exposed are now available to the next phase. Well done — this is exactly how a well-planned build should progress."
596
+ "Phase complete. All outcomes in this phase have been verified and cleared by Checkpoint. The plan has been reconciled with changes from this phase, and Session Brief [N] has been generated for the next phase. Review it at `docs/session-brief-[N].md` or type `*build` to continue. All previous session briefs are retained. Well done — this is exactly how a well-planned build should progress."
591
597
 
592
598
  ---
593
599
 
@@ -83,7 +83,182 @@ Three checks run:
83
83
 
84
84
  **Cross-persona check.** Confirm each persona sees what they should see and cannot access what they should not. Navigate as a customer to a page that should only be accessible to an organiser. Confirm it is blocked.
85
85
 
86
- When all three checks pass, the phase is complete. ODD Studio marks it so, updates ruflo memory, and confirms which phase is next.
86
+ When all three checks pass, the phase is complete. ODD Studio runs the Phase Transition procedure.
87
+
88
+ ---
89
+
90
+ ## Phase Transition
91
+
92
+ When a phase is complete and all integration checks pass, ODD Studio advances to the next phase. This is a four-step process: mark complete, reconcile the plan, generate the next numbered brief, and confirm with the domain expert.
93
+
94
+ ---
95
+
96
+ ### Transition Step 1: Mark the current phase complete
97
+
98
+ Update `.odd/state.json`:
99
+ - Set the current phase status to `"complete"`
100
+ - Update `lastSessionDate`
101
+
102
+ Store completion in ruflo memory:
103
+
104
+ Call `mcp__ruflo__memory_store`:
105
+ - Key: `odd-phase-[phase-name]-complete`
106
+ - Namespace: `odd-project`
107
+ - Value: phase name, completion date, outcomes verified, integration checks passed
108
+
109
+ ---
110
+
111
+ ### Transition Step 2: Plan Reconciliation
112
+
113
+ During the build, things change. Specification gaps are discovered. The domain expert requests new features. A contract turns out to need a different shape. An outcome gets split into two. A service that was planned for a later phase gets pulled forward because the current phase needed it.
114
+
115
+ These changes happen *during* the build — they are recorded in ruflo memory as specification gaps, outcome updates, and contract changes. But `docs/plan.md` still reflects the original plan. If the next phase's brief is generated from a stale plan, it will conflict with reality.
116
+
117
+ **Before generating the next phase's brief, reconcile the plan.**
118
+
119
+ **2a. Gather all changes from the completed phase.**
120
+
121
+ Read from ruflo memory all changes recorded during the phase:
122
+
123
+ Call `mcp__ruflo__memory_search`:
124
+ - Query: `phase [completed-phase-name] changes`
125
+ - Namespace: `odd-project`
126
+
127
+ Also check:
128
+ - All outcome files in `docs/outcomes/` — compare current versions against the plan's original descriptions. Look for updated walkthroughs, new verification steps, changed contracts.
129
+ - The contract map in ruflo memory (`odd-contract-map`) — compare against `docs/contract-map.md`. Look for new contracts, changed data shapes, removed dependencies.
130
+ - Any `*outcome` edits made during the phase (specification gap fixes).
131
+ - Any new outcomes added during the build that were not in the original plan.
132
+
133
+ **2b. Classify each change.**
134
+
135
+ For each change found, classify it:
136
+
137
+ 1. **Contained change** — affects only the completed phase. No impact on future phases. Example: a verification step was reworded, a UI layout was adjusted, an error message was improved.
138
+
139
+ 2. **Contract change** — a contract's shape, name, or data flow was altered. This affects any future outcome that consumes this contract. Example: the mastery level contract now includes a `confidence_score` field that wasn't in the original plan.
140
+
141
+ 3. **New outcome** — a new outcome was identified during the build that needs to be added to a future phase. Example: during Phase 1, the domain expert realised students need a "review mistakes" feature that wasn't originally planned.
142
+
143
+ 4. **Moved outcome** — an outcome originally in a later phase was partially or fully built during this phase because it was needed earlier than planned. Example: basic parent notifications were built in Phase 1 because the teacher dashboard needed to reference them.
144
+
145
+ 5. **Removed or deferred outcome** — an outcome was removed from scope or moved to a later phase. Example: the gamification system was deprioritised to focus on core learning.
146
+
147
+ 6. **Dependency change** — a dependency between phases changed. Example: Phase 3 no longer depends on Phase 2's grouping feature because the parent dashboard was redesigned to use individual student data instead.
148
+
149
+ **2c. Update `docs/plan.md`.**
150
+
151
+ For each change that is NOT contained (types 2-6), update `docs/plan.md`:
152
+
153
+ - **Contract changes**: Update the contract descriptions in the plan. Note what changed and why.
154
+ - **New outcomes**: Add them to the appropriate phase. Re-run the dependency logic — does this new outcome depend on something that hasn't been built yet? If so, assign it to the correct phase.
155
+ - **Moved outcomes**: Update their phase assignment. Mark what was already built and what remains.
156
+ - **Removed/deferred outcomes**: Move them to a "Deferred" section at the bottom of the plan, with the reason.
157
+ - **Dependency changes**: Update the phase dependency descriptions.
158
+
159
+ Add a **Change Log** section at the bottom of `docs/plan.md`:
160
+
161
+ ```markdown
162
+ ## Change Log
163
+
164
+ ### After Phase [completed phase name] — [date]
165
+ - [Change type]: [description of what changed and why]
166
+ - [Change type]: [description]
167
+ - [Change type]: [description]
168
+ ```
169
+
170
+ **2d. Store the reconciled plan in ruflo memory.**
171
+
172
+ Call `mcp__ruflo__memory_store`:
173
+ - Key: `odd-plan`
174
+ - Namespace: `odd-project`
175
+ - Value: the full updated Master Implementation Plan
176
+
177
+ Call `mcp__ruflo__memory_store`:
178
+ - Key: `odd-plan-reconciliation-phase-[phase-name]`
179
+ - Namespace: `odd-project`
180
+ - Value: summary of all changes made during reconciliation, with classification and reasoning
181
+
182
+ **2e. Present the reconciliation to the domain expert.**
183
+
184
+ "Before I generate the next phase's brief, I need to account for what changed during the build. Here is what I found:
185
+
186
+ **Changes that affect future phases:**
187
+ - [list each non-contained change with its classification and impact]
188
+
189
+ **Changes contained to the completed phase (no impact on future phases):**
190
+ - [list contained changes — for information only]
191
+
192
+ **Updated plan:**
193
+ - [summary of how `docs/plan.md` was updated]
194
+ - [any outcomes added, moved, removed, or deferred]
195
+ - [any contract shapes that changed]
196
+
197
+ Does this reconciliation look correct? Are there any other changes from this phase that I missed?"
198
+
199
+ Wait for the domain expert to confirm before proceeding to Step 3.
200
+
201
+ ---
202
+
203
+ ### Transition Step 3: Generate the next numbered Session Brief
204
+
205
+ Session briefs are numbered sequentially. The first brief is `session-brief-0.md`. Each subsequent phase gets the next number.
206
+
207
+ Read `.odd/state.json` to get the current `sessionBriefCount`. The next brief is `docs/session-brief-[N].md` where N is the current count.
208
+
209
+ Generate the brief from the **reconciled** `docs/plan.md` (not the original plan). The brief must reflect any changes from Transition Step 2.
210
+
211
+ The brief follows the same structure as Step 10, with these additions:
212
+
213
+ - **"Available From Previous Phases"** section listing all contracts and infrastructure produced by completed phases
214
+ - **"Changes From Original Plan"** section listing any reconciliation changes that affect this phase — new outcomes added, contracts that changed shape, dependencies that shifted. If none: "No changes — this phase matches the original plan."
215
+
216
+ Save to `docs/session-brief-[N].md`.
217
+
218
+ Store in ruflo memory:
219
+
220
+ Call `mcp__ruflo__memory_store`:
221
+ - Key: `odd-session-brief-[N]`
222
+ - Namespace: `odd-project`
223
+ - Value: the contents of the new session brief
224
+
225
+ Update `.odd/state.json`:
226
+ - Set `currentBuildPhase` to the next phase
227
+ - Increment `sessionBriefCount`
228
+
229
+ ---
230
+
231
+ ### Transition Step 4: Confirm the transition
232
+
233
+ "Phase [completed phase name] is complete. All outcomes verified. All integration checks passed.
234
+
235
+ [If reconciliation found changes]: The plan has been updated to reflect [N] changes from this phase. Review the updated plan at `docs/plan.md`.
236
+
237
+ Session Brief [N] has been generated for Phase [next phase name]: [phase description]. This phase contains [n] outcomes: [list outcome names].
238
+
239
+ [If changes affect this phase]: Note: this phase has been updated since the original plan — [brief summary of what changed].
240
+
241
+ All previous session briefs are retained:
242
+ [list: session-brief-0.md through session-brief-[N-1].md]
243
+
244
+ Type `*build` to begin Phase [next phase name], or review the Session Brief at `docs/session-brief-[N].md` first."
245
+
246
+ ---
247
+
248
+ ### Transition Step 5: If this was the final phase
249
+
250
+ If no phases remain, the project build is complete. Update `.odd/state.json`:
251
+ - Set `currentPhase` to `"complete"`
252
+ - Set `buildComplete` to `true`
253
+
254
+ Confirm:
255
+
256
+ "All phases are complete. Every outcome has been verified and every integration check has passed. Your project is built.
257
+
258
+ Session briefs retained: [list all numbered briefs].
259
+ Plan reconciliation history: [list all reconciliation entries from the change log].
260
+
261
+ Review the full system end-to-end against your original personas. Does Alex experience what you documented? Does Sarah see what you specified? Does Jennifer receive what you described? If yes, your ODD project is done."
87
262
 
88
263
  ---
89
264
 
@@ -197,99 +197,142 @@ This is not a test. It is a check that the plan makes intuitive sense to the dom
197
197
 
198
198
  ---
199
199
 
200
- ## Step 9: Technical Architecture
200
+ ## Step 9: Technical Architecture — Component-by-Component Decision-Making
201
201
 
202
- The plan is structurally complete. Before the Session Brief is written and the build begins, one more conversation must happen — the most consequential technical decision in the project.
202
+ The plan is structurally complete. Before the Session Brief is written and the build begins, the most consequential technical decisions in the project must happen — and you and the domain expert will make them together, one layer at a time.
203
203
 
204
- Until now, every question you asked was a domain question. You were drawing out knowledge the domain expert already held. This step is different. You Rachel are now the expert. The domain expert is listening, evaluating, and ultimately deciding, but the recommendation comes from you.
204
+ This step is fundamentally different from the previous eight. Until now, you drew out knowledge the domain expert already held. Now you bring technical expertise to the table. But expertise does not mean autonomous decision-making. It means presenting options with clear trade-offs, then stepping back while the domain expert chooses.
205
205
 
206
- **Read the full specification before making any recommendation.**
206
+ **Do NOT present a matrix of pre-bundled stacks.** Technology choices are independent — the domain expert should be able to choose Next.js with Supabase and NextAuth, or SvelteKit with Neon and Clerk, or any other valid combination. Each layer is its own decision.
207
207
 
208
- You already have the contract map. Now read everything else:
208
+ **Phase 1: Research and Prepare**
209
+
210
+ Read the full specification to understand the constraints:
209
211
  - Every persona: their context, technical confidence, devices, volume
210
212
  - Every walkthrough: load implications, real-time requirements, data complexity, integration needs
211
213
  - Every contract: data relationships, how deeply interconnected the outcomes are
212
214
  - The phase structure: scale and depth of what is being built
213
215
 
214
- Do not generate a generic recommendation. Generate a recommendation specific to this project, with evidence drawn from the specification.
216
+ **Phase 2: Walk Through Each Decision One at a Time**
215
217
 
216
- **Make a concrete recommendation not a list of options.**
218
+ Present each technology layer as its own decision. For each layer, present 3-4 credible options with trade-offs tied to THIS project's specification. Wait for the domain expert to choose before moving to the next layer.
217
219
 
218
- Do not say "here are some technologies you might consider." Say "this is what I recommend, and here is why." Name specific tools. Justify each one using what the specification reveals.
220
+ **The sequence:**
219
221
 
220
- Structure the recommendation as follows:
222
+ 1. Framework
223
+ 2. Database
224
+ 3. Authentication
225
+ 4. Hosting & Deployment
226
+ 5. Specialist Services (if needed — email, payments, real-time, etc.)
221
227
 
222
- ---
228
+ For each layer, follow this pattern:
223
229
 
224
- **My recommendation for [project name]:**
230
+ ---
225
231
 
226
- [Name the complete stack — framework, database, hosting, any key third-party services such as payments, email, authentication]
232
+ **Decision [N]: [Layer Name]**
227
233
 
228
- **Why this stack:**
234
+ "Now we choose your [layer]. Based on your specification, here are the realistic options:"
229
235
 
230
- For each component, give a specific reason tied to the specification. Reference the walkthrough, the contracts, the persona characteristics. For example:
236
+ **[Option A]**
237
+ - What it is: [one sentence]
238
+ - Why it fits your project: [specific evidence from the specification — reference a persona, outcome, or contract]
239
+ - Trade-off: [what you give up — cost, complexity, lock-in, learning curve]
231
240
 
232
- - "Your data is deeply relational — [Outcome A] produces a record that [Outcome B], [Outcome C], and [Outcome D] all consume, with different fields from each. A relational database handles this natively."
233
- - "Your [persona]'s walkthrough requires real-time availability counts — the number must update immediately when another user acts. This requires [specific approach]."
234
- - "You have [n] outcomes with payment flows. [Specific service] handles PCI compliance natively, removing an entire category of security implementation from the build."
241
+ **[Option B]**
242
+ - What it is: [one sentence]
243
+ - Why it fits your project: [specific evidence from the specification]
244
+ - Trade-off: [what you give up]
235
245
 
236
- **What I considered and rejected:**
246
+ **[Option C]**
247
+ - What it is: [one sentence]
248
+ - Why it fits your project: [specific evidence from the specification]
249
+ - Trade-off: [what you give up]
237
250
 
238
- Name the alternatives that a reasonable person might suggest for this kind of project, and explain specifically why they do not fit this specification.
251
+ "Which of these fits best for your project? Are there constraints I don't know about that rule any of these out?"
239
252
 
240
253
  ---
241
254
 
242
- **Always include in the recommendation: Drizzle and Vitest.**
255
+ **Do not recommend. Offer. Let the domain expert choose.**
243
256
 
244
- Regardless of the other stack choices, these two tools are always part of every recommendation. Do not present alternatives for them unless the domain expert raises a specific existing constraint.
257
+ Wait for their answer. Record it. Move to the next layer.
245
258
 
246
- **Drizzle ORM** always recommended as the database layer.
259
+ If the domain expert raises a concern:
260
+ - If the concern reveals a constraint you missed: "You are right — I did not weight [constraint] heavily enough. Let me revise."
261
+ - If the concern is a misunderstanding: "I want to clarify — [option] actually handles [capability] this way."
262
+ - If the concern reveals a preference: "That preference carries a trade-off: [concrete consequence]. If you are comfortable with that, we proceed."
247
263
 
248
- Drizzle defines the database structure in the same language as the rest of the project. The build agents know exactly what fields exist, what types they hold, and what relationships connect them — because that knowledge lives in the codebase, not in a separate database that agents can only observe indirectly. Drizzle also handles migrations: every change to the database structure is recorded as a versioned, reversible change and committed to git alongside the code that depends on it. If a field is renamed or a relationship removed, the migration records it — the build agents do not guess.
264
+ **Important rules for each decision:**
265
+ - Never bundle choices together. Framework is independent of database is independent of auth.
266
+ - Never exclude valid combinations. If someone wants Next.js + Supabase + NextAuth, that is a valid stack.
267
+ - Always tie reasoning to the specification. "This fits because Outcome 2.1 requires real-time updates for 90 students" — not "This is popular."
268
+ - If a previous choice constrains the next (e.g., choosing Supabase for database means Supabase Auth is available as an auth option), mention it as context but do not force it.
249
269
 
250
- Explain to the domain expert: "Drizzle is the tool that keeps the AI honest about your data. Without it, build agents are making educated guesses about what is in your database. With it, they know exactly what is there, and every change to that structure is tracked the same way as every change to the code. Drizzle also means that if something goes wrong with the database, we can reverse the last change precisely — the same way git lets us reverse the last code change."
270
+ **Phase 3: Confirm the Fixed Layers**
251
271
 
252
- **Vitest** always recommended as the testing framework.
272
+ After all choices are made, explain the two components that are included in every ODD Studio project regardless of choice:
253
273
 
254
- Every outcome has a verification checklist steps the domain expert follows in the browser to confirm the outcome works. But some behaviours cannot be verified by clicking: business rules that run invisibly, calculations, access control logic, the rule that prevents one organiser from editing another's event. Vitest runs automated checks for these. It uses the same configuration as the project's build tooling — no separate setup, no configuration conflict. It runs tests in parallel and completes in seconds. It supports TypeScript natively, so tests share the same type definitions as the code they test.
274
+ **Drizzle ORM** — the database layer that keeps the AI honest.
255
275
 
256
- Explain to the domain expert: "Vitest runs the checks that you cannot run by clicking through the browser the business rules and calculations that happen invisibly inside the system. Every time an outcome is built, Vitest runs these checks automatically. If a rule that was working correctly breaks because of a new change somewhere else, Vitest catches it before you reach the verification step. Think of it as a safety net underneath the verification you do yourself."
276
+ "Drizzle is the tool that ensures the build agents always know the exact shape of your data. Every field, every type, every relationship lives in your codebase as versioned migrations. When something goes wrong, we can reverse the last change precisely the same way git lets us reverse code changes. Without Drizzle, agents are guessing about your database. With it, they know."
257
277
 
258
- **Invite genuine pushback.**
278
+ **Vitest** automated checks for invisible behaviours.
259
279
 
260
- After presenting the recommendation, explicitly invite the domain expert to challenge it:
280
+ "Vitest runs the business rules and calculations you cannot verify by clicking — access control logic, pricing calculations, workflow state transitions. Every outcome built triggers Vitest automatically. If a rule breaks because of a change somewhere else, Vitest catches it before you reach the verification step."
261
281
 
262
- "That is my recommendation based on everything in your specification. I want you to push back if anything does not fit. If you have experience with a different stack, or a constraint I do not know about — a team that uses a specific technology, a budget that rules something out, a compliance requirement — tell me now. This decision is harder to change after the build starts than before."
282
+ These are not negotiable. They exist because the build agents need them, not because of preference.
263
283
 
264
- **Respond to challenges with reasoning, not capitulation.**
284
+ **Phase 4: Summarise and Confirm**
265
285
 
266
- If the domain expert suggests an alternative, engage with it seriously:
267
- - If the alternative is genuinely suitable: "You are right — [reason]. I had not weighted [factor] heavily enough. Let me revise the recommendation."
268
- - If the alternative creates a risk: "I understand the preference for [alternative]. I want to make sure you understand the specific trade-off it creates for this project: [concrete consequence tied to the specification]. If you are comfortable with that trade-off, we proceed with [alternative]. If not, [original recommendation] avoids it."
286
+ After all decisions are made, present the complete stack as a summary:
269
287
 
270
- Do not abandon a recommendation simply because the domain expert expresses a preference. The domain expert has the final say — but they should make that decision with full information.
288
+ "Here is the technical stack you have chosen, decision by decision:
271
289
 
272
- **Record the decision in CLAUDE.md.**
290
+ - **Framework**: [chosen] because [reason from their decision]
291
+ - **Database**: [chosen] — because [reason from their decision]
292
+ - **ORM**: Drizzle (fixed — build agent requirement)
293
+ - **Auth**: [chosen] — because [reason from their decision]
294
+ - **Hosting**: [chosen] — because [reason from their decision]
295
+ - **Testing**: Vitest (fixed — build agent requirement)
296
+ - [Any specialist services]: [chosen] — because [reason from their decision]
273
297
 
274
- When consensus is reached, append a technical decisions section to `CLAUDE.md`:
298
+ Does this look right? Any second thoughts before I record it?"
275
299
 
276
- ```
277
- ## Technical Stack
300
+ Wait for confirmation. If they want to change a layer, go back to that specific decision — do not re-run the entire sequence.
301
+
302
+ **Phase 5: Record the Decision**
278
303
 
279
- Chosen stack: [list each component]
280
- ORM: Drizzle
281
- Testing: Vitest
304
+ When the domain expert confirms, record the complete stack in CLAUDE.md and project memory.
282
305
 
283
- Reasoning:
284
- - [Component]: [why, tied to the specification]
285
- - [Component]: [why, tied to the specification]
286
- - Drizzle: type-safe database layer with versioned migrations — build agents always know the exact shape of the data and every change is tracked
287
- - Vitest: fast, co-located testing with native TypeScript support — catches business rule regressions automatically before verification
306
+ Append a technical decisions section to `CLAUDE.md`:
288
307
 
289
- Considered and rejected:
290
- - [Alternative]: [why it does not fit this project]
308
+ ```
309
+ ## Technical Stack
291
310
 
292
- Domain expert constraints applied: [any preferences or constraints the domain expert specified, or "none"]
311
+ **Chosen stack:**
312
+ - Framework: [chosen]
313
+ - Database: [chosen]
314
+ - ORM: Drizzle
315
+ - Auth: [chosen]
316
+ - Testing: Vitest
317
+ - Hosting: [chosen]
318
+ - [Other services]: [chosen]
319
+
320
+ **Decision reasoning (tied to specification):**
321
+ - Framework: [why, with reference to specific outcome or persona]
322
+ - Database: [why, with reference to specific outcome or persona]
323
+ - Auth: [why, with reference to specific outcome or persona]
324
+ - Hosting: [why, with reference to specific outcome or persona]
325
+ - Drizzle: type-safe database layer with versioned migrations — build agents always know the exact shape of the data and every change is tracked alongside code changes
326
+ - Vitest: automated testing for invisible business rules — catches regressions before verification
327
+
328
+ **Alternatives considered (per layer):**
329
+ - Framework: [rejected options and why — specific constraint from the specification]
330
+ - Database: [rejected options and why]
331
+ - Auth: [rejected options and why]
332
+ - Hosting: [rejected options and why]
333
+
334
+ **Domain expert decision notes:**
335
+ [Any specific preferences, constraints, or reasoning the domain expert expressed across the decisions]
293
336
  ```
294
337
 
295
338
  **Store the decision in ruflo memory.**
@@ -297,30 +340,177 @@ Domain expert constraints applied: [any preferences or constraints the domain ex
297
340
  Call `mcp__ruflo__memory_store`:
298
341
  - Key: `odd-tech-stack`
299
342
  - Namespace: `odd-project`
300
- - Value: the complete technical stack decision including chosen tools, ORM, testing framework, reasoning, and rejected alternatives
343
+ - Value: the complete technical stack decision with per-layer reasoning tied to the specification
301
344
 
302
345
  **Update `.odd/state.json`:**
303
346
  - Set `techStackDecided: true`
304
- - Set `techStack` to the chosen framework
347
+ - Set `techStack` to the chosen stack description (e.g., "Next.js 16 + Supabase + NextAuth + Vercel")
305
348
  - Set `orm` to "Drizzle"
306
349
  - Set `testingFramework` to "Vitest"
307
- - Update `nextStep` to "Set up the project — type *build to scaffold the project and configure your services"
350
+ - Update `nextStep` to "Review UI and Design approach — type *build to continue"
308
351
 
309
- Confirm to the user: "Technical stack recorded in CLAUDE.md and project memory. Every build agent will read this before writing a line of code. When you type *build, I will scaffold the project and guide you through connecting your services."
352
+ Confirm to the user: "Technical stack chosen and recorded. Every build agent will read this before writing a line of code."
353
+
354
+ ---
355
+
356
+ ## Step 9b: UI & Design Decision — Collaborative Visual Planning
357
+
358
+ With the technical stack decided, the next decision shapes how your personas experience the system: the design approach, layout strategy, visual language, and component philosophy.
359
+
360
+ This step mirrors Step 9's collaborative structure — you will identify design options, generate wireframes for visual review, and choose the approach that best serves your personas and your domain.
361
+
362
+ **Phase 1: Understand Design Context**
363
+
364
+ Read the full specification to identify design constraints:
365
+
366
+ - **Personas**: Who is using this? What is their technical confidence? Do they need minimal, focused interfaces or rich, data-dense dashboards?
367
+ - **Outcomes**: Which outcomes have screens the persona interacts with? What information must be present, and what can be secondary?
368
+ - **Devices**: Desktop, mobile, tablet, kiosk? Are there accessibility or compliance requirements?
369
+ - **Volume**: High-frequency routine use or occasional intensive sessions? Does interface consistency matter more than density?
370
+ - **Domain language**: Is this a specialized domain with particular conventions (e.g., clinical, financial, legal)? The UI should speak that language.
371
+
372
+ **Phase 2: Identify Realistic Design Approaches**
373
+
374
+ Based on the specification, define 3-4 credible design strategies. Include:
375
+
376
+ 1. **Minimalist + Dark (Recommended Default)**
377
+ - Dark background (slate/zinc), single accent colour, clear borders
378
+ - Single-column on mobile, grid on desktop
379
+ - Component library: shadcn/ui + Geist
380
+ - Philosophy: clarity through space and type
381
+
382
+ 2. **Dense Dashboard + Light**
383
+ - Light background, information-rich tables and charts
384
+ - Multi-column layouts designed for desktop-first use
385
+ - Keyboard shortcuts, advanced filters, inline editing
386
+ - Philosophy: power users who live in the interface
387
+
388
+ 3. **Minimal + Accessible**
389
+ - WCAG AAA compliance (not just AA)
390
+ - High contrast, large touch targets, full keyboard navigation
391
+ - Screen-reader optimized semantic HTML
392
+ - Philosophy: inclusive design that serves all personas equally
393
+
394
+ 4. **Brand-Driven + Custom**
395
+ - Custom design system (if the domain demands visual distinction)
396
+ - Domain-specific visual language (e.g., clinical software → muted greens, financial → professional grays)
397
+ - Hand-crafted components specific to this domain
398
+ - Philosophy: interface as part of the brand experience
399
+
400
+ Do NOT include absurd alternatives. Every option must be defensible based on your specification.
401
+
402
+ **Phase 3: Generate Wireframes with Excalidraw**
403
+
404
+ For each design approach, use the excalidraw skill to generate wireframes showing:
405
+
406
+ - One key outcome flow (the most important persona interaction)
407
+ - Layout: how information is organized, where navigation lives, how forms and data are presented
408
+ - Component style: buttons, inputs, cards, modals — representative of the chosen approach
409
+ - Mobile variant (if relevant to specification)
410
+
411
+ Call the excalidraw skill (via `/excalidraw` command) with a prompt like:
412
+
413
+ ```
414
+ Generate wireframes for [Design Approach Name] for our [project name] platform.
415
+
416
+ Context:
417
+ - Primary persona: [name], a [role]
418
+ - Key outcome: [outcome name] — [one-sentence description of what they do]
419
+ - Approach philosophy: [brief description of this design approach]
420
+ - Devices: [desktop/mobile/both]
421
+ - Visual style: [dark/light, minimalist/dense, etc.]
422
+
423
+ Show:
424
+ 1. Desktop layout of the main interaction
425
+ 2. Mobile layout (if applicable)
426
+ 3. Key UI components (buttons, inputs, cards) in this style
427
+ 4. Navigation pattern
428
+
429
+ Keep wireframes simple — focus on layout and information hierarchy, not pixel-perfect design.
430
+ ```
431
+
432
+ The excalidraw skill will generate interactive wireframes you can review, iterate on, and export.
433
+
434
+ **Phase 4: The Domain Expert Reviews and Decides**
435
+
436
+ Present the wireframes side-by-side and ask:
437
+
438
+ "I have generated wireframes for four design approaches. Each matches a different priority from your specification:
439
+
440
+ - **Option A** prioritizes clarity and simplicity — perfect if your personas are occasional users or if the domain is already complex.
441
+ - **Option B** is information-dense — best if your personas spend hours in the system and need to see patterns and relationships at once.
442
+ - **Option C** emphasizes accessibility — ensures every persona, regardless of ability, can use the system equally.
443
+ - **Option D** is custom and domain-specific — creates a visual identity that positions your platform as specialized.
444
+
445
+ Review the wireframes. Tell me:
446
+ - Which design approach feels most natural for how [persona name] would work?
447
+ - Are there any constraints I missed — device types, accessibility requirements, team design preferences?
448
+ - If you could describe the 'feel' of the interface in three words, what would they be?"
449
+
450
+ **Do not push a recommendation. Let the domain expert choose based on the wireframes they see.**
451
+
452
+ **Phase 5: Record the Design Decision**
453
+
454
+ When the domain expert chooses, record the decision.
455
+
456
+ Append to `CLAUDE.md`:
457
+
458
+ ```
459
+ ## Design Approach
460
+
461
+ **Chosen design approach:**
462
+ [Design approach name]
463
+
464
+ **Reasoning (tied to specification):**
465
+ - [Persona]: [why this design serves them, with specific reference to an outcome]
466
+ - [Persona]: [why this design serves them]
467
+ - Information architecture: [how the chosen approach organizes information for this domain]
468
+ - Component library: [shadcn/ui + custom theming OR domain-specific components]
469
+ - Accessibility: [WCAG AA / AAA / custom standards]
470
+
471
+ **Alternatives considered:**
472
+ - [Option X]: [why it did not fit — specific constraint from the specification]
473
+ - [Option Y]: [why it did not fit — specific constraint from the specification]
474
+
475
+ **Domain expert decision notes:**
476
+ [Any specific preferences, constraints, or reasoning the domain expert expressed]
477
+ ```
478
+
479
+ Store in ruflo memory:
480
+
481
+ Call `mcp__ruflo__memory_store`:
482
+ - Key: `odd-design-approach`
483
+ - Namespace: `odd-project`
484
+ - Value: the complete design decision with reasoning tied to the specification and wireframe references
485
+
486
+ Update `.odd/state.json`:
487
+ - Set `designApproachDecided: true`
488
+ - Set `designApproach` to the chosen approach name
489
+ - Update `nextStep` to "Type *export to generate the Session Brief, or *build to scaffold and start Phase A"
490
+
491
+ Confirm to the user: "Design approach chosen and recorded. [Design approach name] will guide all screens in this project. Every build agent will reference these wireframes when implementing the UI."
310
492
 
311
493
  ---
312
494
 
313
495
  ## Step 10: Session Brief Export
314
496
 
315
- After the plan is approved, generate the Session Brief — the document a developer or build AI reads at the start of each build session.
497
+ After the plan is approved, generate the first Session Brief — the document a developer or build AI reads at the start of each build session.
498
+
499
+ **Session briefs are numbered.** Every phase gets its own brief, and all briefs are retained so the project has a complete history:
316
500
 
317
- The Session Brief is saved to `docs/session-brief.md`.
501
+ - `docs/session-brief-0.md` — Phase A (Foundation)
502
+ - `docs/session-brief-1.md` — Phase B (first outcomes)
503
+ - `docs/session-brief-2.md` — Phase C
504
+ - ...and so on.
505
+
506
+ The first brief generated here is always `docs/session-brief-0.md`.
318
507
 
319
508
  Structure:
320
509
 
321
510
  ```markdown
322
- # Session Brief — [Project Name] — Phase [X]: [Phase Name]
511
+ # Session Brief [N] — [Project Name] — Phase [X]: [Phase Name]
323
512
  Generated: [date]
513
+ Phase: [N] of [total]
324
514
 
325
515
  ## Overview
326
516
  [One paragraph describing the project, its domain, and its primary personas]
@@ -334,6 +524,9 @@ Generated: [date]
334
524
  ## Contracts In Play
335
525
  [Shared contracts needed for this phase, contracts produced by this phase, contracts consumed from previous phases]
336
526
 
527
+ ## Available From Previous Phases
528
+ [Contracts and infrastructure produced by completed phases — "None" for Phase A]
529
+
337
530
  ## Verification Steps
338
531
  [For each outcome: the complete verification checklist from the outcome specification]
339
532
 
@@ -345,9 +538,13 @@ Generated: [date]
345
538
 
346
539
  ## Not In Scope
347
540
  [Explicit list of things that are NOT to be built in this phase, to prevent scope creep]
541
+
542
+ ## Changes From Original Plan
543
+ [If this brief was generated after a plan reconciliation: list what changed and why.
544
+ "None — this is the original plan" for the first brief.]
348
545
  ```
349
546
 
350
- After writing the Session Brief, confirm: "Session Brief written to docs/session-brief.md. This is the primary input for your build agents. Share it with Claude or any other build AI to start the session."
547
+ After writing the Session Brief, confirm: "Session Brief 0 written to docs/session-brief-0.md. This is the primary input for your build agents."
351
548
 
352
549
  ---
353
550
 
@@ -365,14 +562,15 @@ Confirm to the user: "Master Implementation Plan saved to project memory. All bu
365
562
  Also store the Session Brief:
366
563
 
367
564
  Call `mcp__ruflo__memory_store`:
368
- - Key: `odd-session-brief-phase-[phase-name]`
565
+ - Key: `odd-session-brief-0`
369
566
  - Namespace: `odd-project`
370
- - Value: the contents of `docs/session-brief.md`
567
+ - Value: the contents of `docs/session-brief-0.md`
371
568
 
372
569
  Then update `.odd/state.json`:
373
570
  - Set `planApproved: true`
374
571
  - Populate `planPhases` with the array of phase names in build order
375
572
  - Set `currentBuildPhase` to Phase A
573
+ - Set `sessionBriefCount` to 1
376
574
  - Update `nextStep` to "Type *build — ODD Studio will scaffold the project, connect your services, and begin Phase A"
377
575
 
378
576
  ---