odd-studio 3.6.0 → 3.7.1

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.
@@ -17,6 +17,7 @@
17
17
  #
18
18
  # PostToolUse (exit 0 + stderr = coaching):
19
19
  # session-save Bash — auto-save state after git commit
20
+ # state-dirty-mark Write|Edit — marks state.json edits as needing odd-flow store
20
21
  # store-validate mcp__odd-flow__memory_store — creates ready marker
21
22
  # sync-validate mcp__odd-flow__coordination_sync — creates agents-ready marker
22
23
  # code-quality Write|Edit — code elegance check
@@ -176,6 +177,12 @@ swarm-write)
176
177
  exit 2
177
178
  fi
178
179
 
180
+ # Debug session bypass: orchestrator writes allowed when *debug mode is active
181
+ DEBUG_SESSION=$(get_state_field "debugSession")
182
+ if [ "$DEBUG_SESSION" = "true" ]; then
183
+ exit 0
184
+ fi
185
+
179
186
  # Gate 2: Agent write token must be fresh (120s TTL)
180
187
  # Only Task agents create this token — the orchestrator must NOT.
181
188
  if ! marker_valid ".odd/.odd-flow-agent-token" 120; then
@@ -307,6 +314,10 @@ commit-gate)
307
314
  swarm-guard)
308
315
  [ "$CURRENT_PHASE" = "build" ] || exit 0
309
316
 
317
+ # Suppress all warnings during active debug session — reduced ceremony is the point
318
+ DEBUG_SESSION=$(get_state_field "debugSession")
319
+ [ "$DEBUG_SESSION" = "true" ] && exit 0
320
+
310
321
  # Gate 1: Dirty state (commit without odd-flow store)
311
322
  if [ -f ".odd/.odd-flow-state-dirty" ]; then
312
323
  echo ""
@@ -433,6 +444,19 @@ plan-complete-gate)
433
444
  exit 0
434
445
  ;;
435
446
 
447
+ # ─────────────────────────────────────────────────────────────────────────────
448
+ # PostToolUse: Write|Edit state.json — mark dirty so swarm-guard nags until stored
449
+ # ─────────────────────────────────────────────────────────────────────────────
450
+ # This catches the gap between commit-triggered dirty marking and actual edits.
451
+ # Any edit to state.json (by Claude or by another tool) sets the dirty marker.
452
+ # It's cleared only when mcp__odd-flow__memory_store key=odd-project-state succeeds.
453
+ state-dirty-mark)
454
+ [ "$TOOL_NAME" = "Write" ] || [ "$TOOL_NAME" = "Edit" ] || exit 0
455
+ echo "$FILE_PATH" | grep -q '\.odd/state\.json$' || exit 0
456
+ touch .odd/.odd-flow-state-dirty 2>/dev/null
457
+ exit 0
458
+ ;;
459
+
436
460
  # ─────────────────────────────────────────────────────────────────────────────
437
461
  # PostToolUse: mcp__odd-flow__memory_store — creates ready marker
438
462
  # ─────────────────────────────────────────────────────────────────────────────
@@ -442,12 +466,36 @@ store-validate)
442
466
 
443
467
  KEY=$(echo "$INPUT" | jq -r '.tool_input.key // empty')
444
468
 
445
- SUCCESS=$(echo "$INPUT" | jq -r '.tool_response.success // false' 2>/dev/null || echo "false")
446
- [ "$SUCCESS" = "true" ] || exit 0
469
+ # MCP responses may be nested under tool_response or at root check both
470
+ if ! echo "$INPUT" | grep -qE '"success"[[:space:]]*:[[:space:]]*true'; then
471
+ exit 0
472
+ fi
447
473
 
448
474
  # Create the right marker based on what was stored
449
475
  case "$KEY" in
450
476
  odd-project-state)
477
+ # Reject partial snapshots — the value MUST contain the full state.json shape.
478
+ # Without this, callers can store {currentBuildPhase: "X"} and silently drift.
479
+ VALUE=$(echo "$INPUT" | jq -c '.tool_input.value // empty' 2>/dev/null)
480
+ if [ -n "$VALUE" ] && [ "$VALUE" != "null" ] && [ "$VALUE" != "empty" ]; then
481
+ MISSING=$(echo "$VALUE" | jq -r '
482
+ [
483
+ (if has("personas") then empty else "personas" end),
484
+ (if has("outcomes") then empty else "outcomes" end),
485
+ (if has("currentBuildPhase") then empty else "currentBuildPhase" end),
486
+ (if has("currentPhase") then empty else "currentPhase" end)
487
+ ] | join(", ")
488
+ ' 2>/dev/null)
489
+ if [ -n "$MISSING" ]; then
490
+ echo "" >&2
491
+ echo "ODD STUDIO [store-validate]: Partial odd-project-state rejected." >&2
492
+ echo "Missing required keys: $MISSING" >&2
493
+ echo "Store the FULL contents of .odd/state.json, not a hand-built object." >&2
494
+ echo "" >&2
495
+ # Do NOT clear the dirty marker — the next store must include the full file
496
+ exit 0
497
+ fi
498
+ fi
451
499
  touch .odd/.odd-flow-state-ready 2>/dev/null
452
500
  rm -f .odd/.odd-flow-state-dirty 2>/dev/null
453
501
  ;;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "odd-studio",
3
- "version": "3.6.0",
3
+ "version": "3.7.1",
4
4
  "description": "Outcome-Driven Development for AI coding agents — a planning and build harness for domain experts building serious software with AI. Works with Claude Code, OpenCode, and Codex.",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -66,6 +66,7 @@ const GATES = [
66
66
  matcher: 'Write',
67
67
  gates: [
68
68
  { name: 'plan-complete-gate', timeout: 5, status: 'ODD plan complete gate...' },
69
+ { name: 'state-dirty-mark', timeout: 5, status: 'ODD state dirty mark...' },
69
70
  ],
70
71
  },
71
72
  {
@@ -73,6 +74,7 @@ const GATES = [
73
74
  matcher: 'Edit',
74
75
  gates: [
75
76
  { name: 'plan-complete-gate', timeout: 5, status: 'ODD plan complete gate...' },
77
+ { name: 'state-dirty-mark', timeout: 5, status: 'ODD state dirty mark...' },
76
78
  ],
77
79
  },
78
80
  {
package/skill/SKILL.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: "odd"
3
- version: "3.6.0"
3
+ version: "3.7.1"
4
4
  description: "Outcome-Driven Development planning and build coach. Use /odd to start or resume an ODD project — building personas, writing outcomes, mapping contracts, creating a Master Implementation Plan, and directing a odd-flow-powered build. Designed for domain experts who are not developers. Works with Claude Code, OpenCode, and Codex."
5
5
  metadata:
6
6
  priority: 10
@@ -84,8 +84,15 @@ Before doing anything else, run this state check silently:
84
84
  2. Check whether `docs/plan.md` exists.
85
85
  3. Attempt to retrieve project state from odd-flow memory:
86
86
  - Call `mcp__odd-flow__memory_retrieve` with key `odd-project-state`, namespace `odd-project`
87
- - If successful, merge odd-flow state with any local state found in `.odd/state.json`, with odd-flow taking precedence for any field where it has richer data (more personas, outcomes, or a later phase)
88
- 4. **If odd-flow state is richer than local state** (odd-flow has personas/outcomes/approvals that local does not): write the merged state back to `.odd/state.json` immediately using the Write tool. This keeps local state in sync so the next session starts correctly without a mismatch.
87
+ 4. **Reconciliation — strict, no silent merging.** If both local and odd-flow state exist, compare them field-by-field. Specifically check `currentBuildPhase`, `currentPhase`, `briefConfirmed`, `sessionBriefCount`, `personas.length`, and `outcomes.length`. If ANY of these disagree:
88
+ - **STOP.** Do not display the welcome or status message yet.
89
+ - Show the user a side-by-side diff of the disagreeing fields (local value vs odd-flow value).
90
+ - Ask explicitly: "Local state and odd-flow state have drifted. Which should I trust as authoritative? Type `local`, `odd-flow`, or `inspect` to see the full diff."
91
+ - On `local`: store the full local `state.json` to odd-flow with `mcp__odd-flow__memory_store` and proceed.
92
+ - On `odd-flow`: write the odd-flow value to `.odd/state.json` and proceed.
93
+ - On `inspect`: print the full diff and ask again.
94
+ - Do NOT use heuristics like "richer wins" or "later phase wins" — they hide bugs. The user decides.
95
+ 5. If local exists and odd-flow does not: store local to odd-flow immediately. If odd-flow exists and local does not: write odd-flow to local immediately.
89
96
 
90
97
  **If this is a new project** (no state found anywhere), display the welcome message below.
91
98
 
@@ -99,7 +106,7 @@ Display this when no existing state is found:
99
106
 
100
107
  ---
101
108
 
102
- Welcome to ODD Studio v3.6.0.
109
+ Welcome to ODD Studio v3.7.1.
103
110
 
104
111
  You are about to plan and build something real — using a methodology called Outcome-Driven Development. Before we write a single line of code, we are going to get precise about three things:
105
112
 
@@ -123,7 +130,7 @@ Display this when existing state is found. Replace the bracketed values with act
123
130
 
124
131
  ---
125
132
 
126
- Welcome back to ODD Studio v3.6.0.
133
+ Welcome back to ODD Studio v3.7.1.
127
134
 
128
135
  **Project:** [project.name]
129
136
  **Current Phase:** [state.currentPhase]
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: "odd-debug"
3
- version: "1.0.0"
4
- description: "ODD Studio debug command. Keeps debugging inside the active outcome, selects the correct debug strategy, and routes back to verification instead of drifting outside the ODD flow."
3
+ version: "2.0.0"
4
+ description: "ODD Studio debug command. Activates a lightweight debug session (no full swarm init required), selects the correct debug strategy, and routes back to verification instead of drifting outside the ODD flow."
5
5
  metadata:
6
6
  priority: 9
7
7
  pathPatterns:
@@ -43,18 +43,124 @@ retrieval:
43
43
 
44
44
  You are executing the ODD Studio `*debug` command.
45
45
 
46
- Read these two files now:
47
- 1. `.claude/skills/odd/SKILL.md` — the full ODD Studio coach and build protocol
48
- 2. `.claude/skills/odd/docs/build/debug-protocol.md` — the Debug Protocol detail
46
+ ## What this command does
49
47
 
50
- Then execute the `*debug` protocol exactly as documented in those files, starting from the state check and selecting the explicit debug strategy before any fix is attempted.
48
+ `*debug` activates a lightweight build session optimised for debugging, hotfixes, and security remediation work. It bypasses the full 9-step swarm init that `*build` requires — there is no agent dispatch, no task creation, no swarm spawn. The orchestrator writes code directly.
51
49
 
52
- You must classify the failure into exactly one debug strategy before reading implementation details:
53
- - `ui-behaviour`
54
- - `full-stack`
55
- - `auth-security`
56
- - `integration-contract`
57
- - `background-process`
58
- - `performance-state`
50
+ This is not a shortcut around ODD. The brief-gate, verify-gate, commit-gate, and outcome verification protocol are all still enforced. What is relaxed is the agent-token requirement in `swarm-write` the requirement that forces every source write through a background Task agent. That requirement exists to enable parallel multi-agent outcome builds. For a single targeted fix it is pure ceremony.
59
51
 
60
- If the correct strategy is not yet clear, gather evidence first. Never guess. Never jump straight to a fix.
52
+ **When to use `*debug` instead of `*build`:**
53
+ - Fixing a failing test suite
54
+ - Applying a security patch
55
+ - Investigating and resolving a verification failure
56
+ - Any single-file or few-file change that does not require parallel agent execution
57
+
58
+ **When to use `*build` instead:**
59
+ - Building a new outcome from scratch
60
+ - Work that benefits from parallel backend + UI + QA agents
61
+ - Phase transitions
62
+
63
+ ---
64
+
65
+ ## Session Activation
66
+
67
+ Execute these steps before any investigation or fix work. Do them in order.
68
+
69
+ ### Step 1 — State check
70
+
71
+ Read `.odd/state.json`. Confirm:
72
+ - `currentPhase` is `"build"` — if not, explain that `*debug` requires an active build phase
73
+ - `planApproved` is `true` — if not, route to `*plan`
74
+
75
+ If either check fails, stop here and explain what is needed.
76
+
77
+ ### Step 2 — Activate the debug session marker
78
+
79
+ ```bash
80
+ touch .odd/.odd-flow-swarm-active
81
+ ```
82
+
83
+ This creates or refreshes the 24-hour build session marker. The `swarm-write` gate will now allow direct orchestrator writes (because `debugSession: true` bypasses Gate 2).
84
+
85
+ ### Step 3 — Set debug session state
86
+
87
+ Update `.odd/state.json`:
88
+ - `debugSession: true`
89
+ - `buildMode: "debug"`
90
+ - `verificationConfirmed: false`
91
+ - `debugStartedAt: <current ISO timestamp>`
92
+ - `debugSummary: <one-sentence description of the issue — or "unknown" if not yet classified>`
93
+
94
+ ### Step 4 — Store state to odd-flow
95
+
96
+ Call `mcp__odd-flow__memory_store`:
97
+ - Key: `odd-project-state`
98
+ - Namespace: `odd-project`
99
+ - Value: full contents of `.odd/state.json`
100
+ - upsert: true
101
+
102
+ This single store call satisfies the `commit-gate` requirement (via `store-validate` hook) for subsequent commits in this session.
103
+
104
+ ### Step 5 — Confirm to user
105
+
106
+ Display:
107
+
108
+ ---
109
+
110
+ Debug session active.
111
+
112
+ Source writes are unlocked. No agent dispatch required.
113
+ Brief gate, verify gate, and commit gate remain enforced.
114
+
115
+ State stored to odd-flow. Ready to investigate.
116
+
117
+ ---
118
+
119
+ Then proceed immediately to Strategy Selection below.
120
+
121
+ ---
122
+
123
+ ## Strategy Selection
124
+
125
+ Read `.odd/state.json` to identify the active outcome and the latest failure. If the failure was described in the user's message, use that. If not yet clear, ask for a one-sentence description.
126
+
127
+ Choose exactly one debug strategy before inspecting code. State the chosen strategy and the reason.
128
+
129
+ - Choose `ui-behaviour` when the problem is visible in the interface and you do not yet have evidence of a backend or data fault
130
+ - Choose `full-stack` when the failure crosses a user action, server boundary, and persisted state
131
+ - Choose `auth-security` when access, identity, trust, or validation boundaries might be wrong
132
+ - Choose `integration-contract` when one part of the system expects data or sequencing another part does not produce
133
+ - Choose `background-process` when the failure depends on async handoff, jobs, retries, or event delivery
134
+ - Choose `performance-state` when the issue depends on timing, staleness, cache invalidation, or repeated actions
135
+
136
+ If more than one strategy seems plausible, do not fix anything yet. Gather one more piece of evidence, then choose the narrowest strategy that still explains the failure.
137
+
138
+ ---
139
+
140
+ ## Fix Protocol
141
+
142
+ After choosing the strategy, load `docs/build/debug-protocol.md` for the detailed investigation procedure for that strategy.
143
+
144
+ When the fix is complete:
145
+
146
+ 1. Run the relevant automated checks (tests, lint)
147
+ 2. Update `.odd/state.json`:
148
+ - `debugSession: false`
149
+ - `buildMode: "verify"`
150
+ - `debugStrategy: <chosen strategy>`
151
+ - `debugTarget: <affected file or surface>`
152
+ - `debugSummary: <resolved — one sentence>`
153
+ 3. Call `mcp__odd-flow__memory_store` with key `odd-project-state` to store final state
154
+ 4. Return to the verification walkthrough from step one
155
+
156
+ Setting `debugSession: false` re-enables Gate 2 for subsequent work, returning to full swarm protocol.
157
+
158
+ ---
159
+
160
+ ## Non-negotiable rules
161
+
162
+ - Never mark an outcome verified during a debug session
163
+ - Never change multiple layers at once before reproducing the fault
164
+ - Never skip the reproduction step
165
+ - Never broaden the strategy after starting unless new evidence proves the original classification wrong
166
+ - Always clear `debugSession: false` when the fix is complete