odd-studio 3.7.1 → 3.7.5
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/hooks/odd-studio.sh +52 -134
- package/hooks/post-commit-hook.sh +7 -35
- package/package.json +1 -1
- package/scripts/setup-hooks.js +0 -5
- package/skill/SKILL.md +17 -49
package/hooks/odd-studio.sh
CHANGED
|
@@ -12,17 +12,13 @@
|
|
|
12
12
|
# swarm-write Write|Edit — blocks source writes without swarm + agent token
|
|
13
13
|
# verify-gate Edit|Write — blocks marking outcomes verified without checklist
|
|
14
14
|
# confirm-gate Edit|Write — blocks briefConfirmed without odd-flow store
|
|
15
|
-
# checkpoint-gate Bash — blocks commits until a fresh Checkpoint scan clears the latest source changes
|
|
16
|
-
# commit-gate Bash — blocks git commit without odd-flow state stored
|
|
17
15
|
#
|
|
18
16
|
# PostToolUse (exit 0 + stderr = coaching):
|
|
19
|
-
# session-save Bash —
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
# sync-validate mcp__odd-flow__coordination_sync — creates agents-ready marker
|
|
17
|
+
# session-save Bash — updates last-commit metadata after git commit
|
|
18
|
+
# store-validate mcp__odd-flow__memory_store — touches brief-stored marker
|
|
19
|
+
# sync-validate mcp__odd-flow__coordination_sync — activates swarm markers
|
|
23
20
|
# code-quality Write|Edit — code elegance check
|
|
24
|
-
# security-quality Write|Edit — security baseline
|
|
25
|
-
# checkpoint-validate Bash — marks checkpoint clear after a successful scan
|
|
21
|
+
# security-quality Write|Edit — security baseline warnings (non-blocking)
|
|
26
22
|
# brief-quality Write — session brief quality check
|
|
27
23
|
# outcome-quality Write — outcome/persona quality check
|
|
28
24
|
#
|
|
@@ -86,7 +82,7 @@ is_source_file() {
|
|
|
86
82
|
return 1
|
|
87
83
|
fi
|
|
88
84
|
# Non-source locations — allow
|
|
89
|
-
if echo "$fp" | grep -qE '(\.odd/|docs/|memory/|MEMORY\.md|CLAUDE\.md|\.odd-flow)'; then
|
|
85
|
+
if echo "$fp" | grep -qE '(\.odd/|docs/|memory/|MEMORY\.md|CLAUDE\.md|\.odd-flow|\.claude/)'; then
|
|
90
86
|
return 1
|
|
91
87
|
fi
|
|
92
88
|
# Hook/skill/script files — allow
|
|
@@ -140,6 +136,12 @@ build-gate)
|
|
|
140
136
|
[ "$TOOL_NAME" = "Agent" ] || exit 0
|
|
141
137
|
[ "$CURRENT_PHASE" = "build" ] || exit 0
|
|
142
138
|
|
|
139
|
+
# Quick-fix bypass: orchestrator can dispatch agents for small fixes without full swarm init.
|
|
140
|
+
# Marker has 1h TTL and must be explicitly created via `touch .odd/.odd-quick-fix`.
|
|
141
|
+
if marker_valid ".odd/.odd-quick-fix" 3600; then
|
|
142
|
+
exit 0
|
|
143
|
+
fi
|
|
144
|
+
|
|
143
145
|
# Allow brief-generation and sync agents through
|
|
144
146
|
AGENT_PROMPT=$(echo "$INPUT" | jq -r '.tool_input.prompt // empty' | head -c 300)
|
|
145
147
|
if echo "$AGENT_PROMPT" | grep -qiE '(session.brief|session-brief|generate.*brief|odd-sync|fix.*hook|update.*hook)'; then
|
|
@@ -183,6 +185,13 @@ swarm-write)
|
|
|
183
185
|
exit 0
|
|
184
186
|
fi
|
|
185
187
|
|
|
188
|
+
# Quick-fix bypass: orchestrator can edit source directly for small fixes.
|
|
189
|
+
# Marker has 1h TTL and must be explicitly created via `touch .odd/.odd-quick-fix`.
|
|
190
|
+
# Use for single-file typo/type fixes where full swarm ceremony is overkill.
|
|
191
|
+
if marker_valid ".odd/.odd-quick-fix" 3600; then
|
|
192
|
+
exit 0
|
|
193
|
+
fi
|
|
194
|
+
|
|
186
195
|
# Gate 2: Agent write token must be fresh (120s TTL)
|
|
187
196
|
# Only Task agents create this token — the orchestrator must NOT.
|
|
188
197
|
if ! marker_valid ".odd/.odd-flow-agent-token" 120; then
|
|
@@ -230,11 +239,7 @@ verify-gate)
|
|
|
230
239
|
exit 2
|
|
231
240
|
fi
|
|
232
241
|
|
|
233
|
-
|
|
234
|
-
echo "ODD STUDIO [verify-gate]: Verification blocked — a fresh Checkpoint scan has not cleared the latest source changes." >&2
|
|
235
|
-
echo "Run: npx @darrenjcoxon/vibeguard --security-only -o json" >&2
|
|
236
|
-
exit 2
|
|
237
|
-
fi
|
|
242
|
+
# Checkpoint pre-check removed in v3.7.3 (see checkpoint-gate note below).
|
|
238
243
|
|
|
239
244
|
VERIFIED_CONFIRMED=$(get_state_field "verificationConfirmed")
|
|
240
245
|
if [ "$VERIFIED_CONFIRMED" != "true" ]; then
|
|
@@ -246,27 +251,12 @@ verify-gate)
|
|
|
246
251
|
;;
|
|
247
252
|
|
|
248
253
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
249
|
-
#
|
|
254
|
+
# checkpoint-gate — REMOVED in v3.7.3
|
|
255
|
+
# Vibeguard/Checkpoint was treating dependency-lockfile CVEs as equivalent to
|
|
256
|
+
# code vulnerabilities, making every commit impossible while any transitive
|
|
257
|
+
# dep had an open advisory. Re-introduce only with a scoped scanner that
|
|
258
|
+
# ignores lockfile-only findings.
|
|
250
259
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
251
|
-
checkpoint-gate)
|
|
252
|
-
[ "$TOOL_NAME" = "Bash" ] || exit 0
|
|
253
|
-
[ "$CURRENT_PHASE" = "build" ] || exit 0
|
|
254
|
-
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
|
|
255
|
-
echo "$COMMAND" | grep -qE 'git\s+commit' || exit 0
|
|
256
|
-
|
|
257
|
-
if [ "$BUILD_MODE" = "debug" ]; then
|
|
258
|
-
echo "ODD STUDIO [checkpoint-gate]: Commit blocked — debug mode is active." >&2
|
|
259
|
-
echo "Resolve the failure, return to verify mode, then commit only after verification passes." >&2
|
|
260
|
-
exit 2
|
|
261
|
-
fi
|
|
262
|
-
|
|
263
|
-
if [ -f ".odd/.checkpoint-dirty" ] || [ ! -f ".odd/.checkpoint-clear" ]; then
|
|
264
|
-
echo "ODD STUDIO [checkpoint-gate]: Commit blocked — latest source changes have not passed Checkpoint." >&2
|
|
265
|
-
echo "Run: npx @darrenjcoxon/vibeguard --security-only -o json" >&2
|
|
266
|
-
exit 2
|
|
267
|
-
fi
|
|
268
|
-
exit 0
|
|
269
|
-
;;
|
|
270
260
|
|
|
271
261
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
272
262
|
# PreToolUse: Edit|Write — blocks briefConfirmed without odd-flow store
|
|
@@ -279,7 +269,7 @@ confirm-gate)
|
|
|
279
269
|
NEW_CONTENT=$(echo "$INPUT" | jq -r '.tool_input.new_string // .tool_input.content // empty')
|
|
280
270
|
echo "$NEW_CONTENT" | grep -qE '"briefConfirmed"\s*:\s*true' || exit 0
|
|
281
271
|
|
|
282
|
-
if [ ! -f ".odd/.odd-flow-brief-stored" ]
|
|
272
|
+
if [ ! -f ".odd/.odd-flow-brief-stored" ]; then
|
|
283
273
|
echo "ODD STUDIO [confirm-gate]: Brief not stored in odd-flow memory. Store it first." >&2
|
|
284
274
|
exit 2
|
|
285
275
|
fi
|
|
@@ -287,26 +277,12 @@ confirm-gate)
|
|
|
287
277
|
;;
|
|
288
278
|
|
|
289
279
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
290
|
-
#
|
|
280
|
+
# commit-gate — REMOVED in v3.7.4
|
|
281
|
+
# The dirty/ready marker treadmill was creating more friction than value.
|
|
282
|
+
# State persistence to odd-flow is now the orchestrator's responsibility at
|
|
283
|
+
# genuine persistence points (session end, outcome verified) rather than a
|
|
284
|
+
# hard-block on every commit.
|
|
291
285
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
292
|
-
commit-gate)
|
|
293
|
-
[ "$TOOL_NAME" = "Bash" ] || exit 0
|
|
294
|
-
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
|
|
295
|
-
echo "$COMMAND" | grep -qE 'git\s+commit' || exit 0
|
|
296
|
-
[ "$CURRENT_PHASE" = "build" ] || exit 0
|
|
297
|
-
|
|
298
|
-
if [ ! -f ".odd/.odd-flow-state-ready" ]; then
|
|
299
|
-
echo "" >&2
|
|
300
|
-
echo "ODD STUDIO [commit-gate]: Commit blocked — odd-flow state not stored." >&2
|
|
301
|
-
echo "Call mcp__odd-flow__memory_store key=odd-project-state first." >&2
|
|
302
|
-
echo "" >&2
|
|
303
|
-
exit 2
|
|
304
|
-
fi
|
|
305
|
-
|
|
306
|
-
# Marker consumed — next commit requires a fresh store
|
|
307
|
-
rm -f ".odd/.odd-flow-state-ready"
|
|
308
|
-
exit 0
|
|
309
|
-
;;
|
|
310
286
|
|
|
311
287
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
312
288
|
# UserPromptSubmit — warns every turn if build phase without swarm
|
|
@@ -318,24 +294,7 @@ swarm-guard)
|
|
|
318
294
|
DEBUG_SESSION=$(get_state_field "debugSession")
|
|
319
295
|
[ "$DEBUG_SESSION" = "true" ] && exit 0
|
|
320
296
|
|
|
321
|
-
#
|
|
322
|
-
if [ -f ".odd/.odd-flow-state-dirty" ]; then
|
|
323
|
-
echo ""
|
|
324
|
-
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
325
|
-
echo "ODD STUDIO — STATE NOT SAVED TO ODD-FLOW"
|
|
326
|
-
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
327
|
-
echo ""
|
|
328
|
-
echo " A git commit was made but .odd/state.json was NOT stored to odd-flow."
|
|
329
|
-
echo " DO THIS NOW:"
|
|
330
|
-
echo " 1. mcp__odd-flow__memory_store key=odd-project-state namespace=odd-project upsert=true value=<.odd/state.json>"
|
|
331
|
-
echo " 2. Bash: rm -f .odd/.odd-flow-state-dirty"
|
|
332
|
-
echo ""
|
|
333
|
-
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
334
|
-
echo ""
|
|
335
|
-
exit 0
|
|
336
|
-
fi
|
|
337
|
-
|
|
338
|
-
# Gate 2: Swarm not initialised
|
|
297
|
+
# Swarm not initialised
|
|
339
298
|
if marker_valid ".odd/.odd-flow-swarm-active" 86400; then
|
|
340
299
|
exit 0
|
|
341
300
|
fi
|
|
@@ -380,28 +339,14 @@ session-save)
|
|
|
380
339
|
} catch(e) {}
|
|
381
340
|
" 2>/dev/null
|
|
382
341
|
|
|
383
|
-
# Refresh sync marker
|
|
342
|
+
# Refresh phase sync marker. Dirty-marker touching removed in v3.7.4.
|
|
384
343
|
touch .odd/.odd-flow-phase-synced 2>/dev/null
|
|
385
|
-
touch .odd/.odd-flow-state-dirty 2>/dev/null
|
|
386
344
|
exit 0
|
|
387
345
|
;;
|
|
388
346
|
|
|
389
347
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
390
|
-
#
|
|
348
|
+
# checkpoint-validate — REMOVED in v3.7.3 (see checkpoint-gate note above)
|
|
391
349
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
392
|
-
checkpoint-validate)
|
|
393
|
-
[ "$TOOL_NAME" = "Bash" ] || exit 0
|
|
394
|
-
[ "$CURRENT_PHASE" = "build" ] || exit 0
|
|
395
|
-
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
|
|
396
|
-
echo "$COMMAND" | grep -qE '@darrenjcoxon/vibeguard|vibeguard' || exit 0
|
|
397
|
-
|
|
398
|
-
EXIT_CODE=$(echo "$INPUT" | jq -r '.tool_response.exit_code // .tool_output.exit_code // .exitCode // empty' 2>/dev/null || true)
|
|
399
|
-
if [ -z "$EXIT_CODE" ] || [ "$EXIT_CODE" = "0" ]; then
|
|
400
|
-
touch .odd/.checkpoint-clear 2>/dev/null
|
|
401
|
-
rm -f .odd/.checkpoint-dirty 2>/dev/null
|
|
402
|
-
fi
|
|
403
|
-
exit 0
|
|
404
|
-
;;
|
|
405
350
|
|
|
406
351
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
407
352
|
# PostToolUse: Write|Edit state.json — blocks phase transition without Steps 9, 9b, 9d
|
|
@@ -445,60 +390,27 @@ plan-complete-gate)
|
|
|
445
390
|
;;
|
|
446
391
|
|
|
447
392
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
448
|
-
#
|
|
393
|
+
# state-dirty-mark — REMOVED in v3.7.4 (dirty/ready treadmill eliminated)
|
|
449
394
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
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
395
|
|
|
460
396
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
461
|
-
# PostToolUse: mcp__odd-flow__memory_store —
|
|
397
|
+
# PostToolUse: mcp__odd-flow__memory_store — brief-stored marker only
|
|
462
398
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
399
|
+
# v3.7.4: the state-ready / dirty treadmill has been removed. This hook now
|
|
400
|
+
# only creates the brief-stored marker after a session brief is persisted.
|
|
401
|
+
# odd-project-state stores are logged but do not touch any marker — state
|
|
402
|
+
# persistence is no longer gated by a marker state machine.
|
|
463
403
|
store-validate)
|
|
464
404
|
[ "$TOOL_NAME" = "mcp__odd-flow__memory_store" ] || exit 0
|
|
465
405
|
[ "$CURRENT_PHASE" = "build" ] || exit 0
|
|
466
406
|
|
|
467
407
|
KEY=$(echo "$INPUT" | jq -r '.tool_input.key // empty')
|
|
468
408
|
|
|
469
|
-
# MCP responses may be nested under tool_response or at root — check both
|
|
470
409
|
if ! echo "$INPUT" | grep -qE '"success"[[:space:]]*:[[:space:]]*true'; then
|
|
471
410
|
exit 0
|
|
472
411
|
fi
|
|
473
412
|
|
|
474
|
-
# Create the right marker based on what was stored
|
|
475
413
|
case "$KEY" in
|
|
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
|
|
499
|
-
touch .odd/.odd-flow-state-ready 2>/dev/null
|
|
500
|
-
rm -f .odd/.odd-flow-state-dirty 2>/dev/null
|
|
501
|
-
;;
|
|
502
414
|
odd-session-brief-*)
|
|
503
415
|
touch .odd/.odd-flow-brief-stored 2>/dev/null
|
|
504
416
|
;;
|
|
@@ -507,12 +419,22 @@ store-validate)
|
|
|
507
419
|
;;
|
|
508
420
|
|
|
509
421
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
510
|
-
# PostToolUse: mcp__odd-flow__coordination_sync —
|
|
422
|
+
# PostToolUse: mcp__odd-flow__coordination_sync — completes swarm init
|
|
511
423
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
424
|
+
# coordination_sync is the LAST step of the 9-step swarm init sequence.
|
|
425
|
+
# When it fires successfully in build phase, the swarm is initialised — so we
|
|
426
|
+
# create all three markers atomically rather than relying on the orchestrator
|
|
427
|
+
# to remember a stray Bash `touch` step buried in a numbered list.
|
|
428
|
+
#
|
|
429
|
+
# Markers created:
|
|
430
|
+
# .odd-flow-swarm-active — gates source writes (24h TTL)
|
|
431
|
+
# .odd-flow-agents-ready — unblocks build-gate for Task agents
|
|
432
|
+
# .odd-flow-phase-synced — confirms agents have phase context
|
|
512
433
|
sync-validate)
|
|
513
434
|
[ "$TOOL_NAME" = "mcp__odd-flow__coordination_sync" ] || exit 0
|
|
514
435
|
[ "$CURRENT_PHASE" = "build" ] || exit 0
|
|
515
436
|
|
|
437
|
+
touch .odd/.odd-flow-swarm-active 2>/dev/null
|
|
516
438
|
touch .odd/.odd-flow-agents-ready 2>/dev/null
|
|
517
439
|
touch .odd/.odd-flow-phase-synced 2>/dev/null
|
|
518
440
|
exit 0
|
|
@@ -579,7 +501,8 @@ code-quality)
|
|
|
579
501
|
;;
|
|
580
502
|
|
|
581
503
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
582
|
-
# PostToolUse: Write|Edit — security baseline warnings
|
|
504
|
+
# PostToolUse: Write|Edit — security baseline warnings (stderr, non-blocking)
|
|
505
|
+
# Checkpoint dirty-marking was removed in v3.7.3 along with checkpoint-gate.
|
|
583
506
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
584
507
|
security-quality)
|
|
585
508
|
[ "$TOOL_NAME" = "Write" ] || [ "$TOOL_NAME" = "Edit" ] || exit 0
|
|
@@ -588,11 +511,6 @@ security-quality)
|
|
|
588
511
|
echo "$FILE_PATH" | grep -qiE '(\.config\.|\.d\.ts|node_modules|\.next|dist/|build/|\.test\.|\.spec\.|__tests__)' && exit 0
|
|
589
512
|
[ -f "$FILE_PATH" ] || exit 0
|
|
590
513
|
|
|
591
|
-
if [ "$CURRENT_PHASE" = "build" ]; then
|
|
592
|
-
touch .odd/.checkpoint-dirty 2>/dev/null
|
|
593
|
-
rm -f .odd/.checkpoint-clear 2>/dev/null
|
|
594
|
-
fi
|
|
595
|
-
|
|
596
514
|
ISSUES=""
|
|
597
515
|
|
|
598
516
|
grep -qEi '\b(api[_-]?key|secret|token|password)\b[^=\n]{0,40}[:=][[:space:]]*["'\''][^"'\'']{8,}["'\'']' "$FILE_PATH" 2>/dev/null \
|
|
@@ -1,39 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# ODD Studio — git post-commit hook
|
|
2
|
+
# ODD Studio — git post-commit hook (no-op)
|
|
3
3
|
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
4
|
+
# This hook existed in earlier versions to set .odd-flow-state-dirty on every
|
|
5
|
+
# build-phase commit so the swarm-guard would nag until state was stored.
|
|
6
|
+
# In v3.7.4 the dirty/ready marker treadmill was removed because it created
|
|
7
|
+
# more friction than value, so this hook is now a no-op kept only for
|
|
8
|
+
# backwards compatibility with projects that have it installed in .git/hooks.
|
|
7
9
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
# Why this exists:
|
|
11
|
-
# odd-session-save.sh (PostToolUse) covers commits made BY Claude.
|
|
12
|
-
# This hook covers commits made by the developer directly in the terminal.
|
|
13
|
-
# Together they ensure .odd-flow-state-dirty is always set after a build-phase commit,
|
|
14
|
-
# regardless of who made it.
|
|
15
|
-
#
|
|
16
|
-
# The dirty marker is cleared only after:
|
|
17
|
-
# 1. mcp__odd-flow__memory_store key=odd-project-state (saves state to odd-flow)
|
|
18
|
-
# 2. rm -f .odd/.odd-flow-state-dirty
|
|
19
|
-
#
|
|
20
|
-
# odd-swarm-guard.sh (UserPromptSubmit) blocks EVERY Claude turn until cleared.
|
|
21
|
-
|
|
22
|
-
STATE_FILE=".odd/state.json"
|
|
23
|
-
|
|
24
|
-
if [ ! -f "$STATE_FILE" ]; then
|
|
25
|
-
exit 0
|
|
26
|
-
fi
|
|
27
|
-
|
|
28
|
-
CURRENT_PHASE=$(ODD_STATE_FILE="$STATE_FILE" node -e "
|
|
29
|
-
try {
|
|
30
|
-
const s = JSON.parse(require('fs').readFileSync(process.env.ODD_STATE_FILE, 'utf8'));
|
|
31
|
-
console.log(s.currentPhase || '');
|
|
32
|
-
} catch(e) { console.log(''); }
|
|
33
|
-
" 2>/dev/null)
|
|
34
|
-
|
|
35
|
-
if [ "$CURRENT_PHASE" = "build" ]; then
|
|
36
|
-
touch .odd/.odd-flow-state-dirty
|
|
37
|
-
fi
|
|
38
|
-
|
|
10
|
+
# Safe to delete from .git/hooks/post-commit if you want.
|
|
39
11
|
exit 0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "odd-studio",
|
|
3
|
-
"version": "3.7.
|
|
3
|
+
"version": "3.7.5",
|
|
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",
|
package/scripts/setup-hooks.js
CHANGED
|
@@ -48,8 +48,6 @@ const GATES = [
|
|
|
48
48
|
event: 'PreToolUse',
|
|
49
49
|
matcher: 'Bash',
|
|
50
50
|
gates: [
|
|
51
|
-
{ name: 'checkpoint-gate', timeout: 5, status: 'ODD checkpoint gate...' },
|
|
52
|
-
{ name: 'commit-gate', timeout: 5, status: 'ODD commit gate...' },
|
|
53
51
|
],
|
|
54
52
|
},
|
|
55
53
|
// ── UserPromptSubmit ────────────────────────────────────────────────────
|
|
@@ -66,7 +64,6 @@ const GATES = [
|
|
|
66
64
|
matcher: 'Write',
|
|
67
65
|
gates: [
|
|
68
66
|
{ name: 'plan-complete-gate', timeout: 5, status: 'ODD plan complete gate...' },
|
|
69
|
-
{ name: 'state-dirty-mark', timeout: 5, status: 'ODD state dirty mark...' },
|
|
70
67
|
],
|
|
71
68
|
},
|
|
72
69
|
{
|
|
@@ -74,14 +71,12 @@ const GATES = [
|
|
|
74
71
|
matcher: 'Edit',
|
|
75
72
|
gates: [
|
|
76
73
|
{ name: 'plan-complete-gate', timeout: 5, status: 'ODD plan complete gate...' },
|
|
77
|
-
{ name: 'state-dirty-mark', timeout: 5, status: 'ODD state dirty mark...' },
|
|
78
74
|
],
|
|
79
75
|
},
|
|
80
76
|
{
|
|
81
77
|
event: 'PostToolUse',
|
|
82
78
|
matcher: 'Bash',
|
|
83
79
|
gates: [
|
|
84
|
-
{ name: 'checkpoint-validate', timeout: 10, status: 'ODD checkpoint validate...' },
|
|
85
80
|
{ name: 'session-save', timeout: 10, status: 'ODD session save...' },
|
|
86
81
|
],
|
|
87
82
|
},
|
package/skill/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "odd"
|
|
3
|
-
version: "3.7.
|
|
3
|
+
version: "3.7.5"
|
|
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
|
|
@@ -106,7 +106,7 @@ Display this when no existing state is found:
|
|
|
106
106
|
|
|
107
107
|
---
|
|
108
108
|
|
|
109
|
-
Welcome to ODD Studio v3.7.
|
|
109
|
+
Welcome to ODD Studio v3.7.5.
|
|
110
110
|
|
|
111
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:
|
|
112
112
|
|
|
@@ -130,7 +130,7 @@ Display this when existing state is found. Replace the bracketed values with act
|
|
|
130
130
|
|
|
131
131
|
---
|
|
132
132
|
|
|
133
|
-
Welcome back to ODD Studio v3.7.
|
|
133
|
+
Welcome back to ODD Studio v3.7.5.
|
|
134
134
|
|
|
135
135
|
**Project:** [project.name]
|
|
136
136
|
**Current Phase:** [state.currentPhase]
|
|
@@ -267,11 +267,11 @@ Execute these steps in order:
|
|
|
267
267
|
|
|
268
268
|
7. **INITIALISES THE ODD_FLOW SWARM — MANDATORY FIRST ACTION.**
|
|
269
269
|
|
|
270
|
-
> **This step happens BEFORE loading any files, BEFORE reading source code, BEFORE planning any build work. Swarm init is not a step buried in a checklist — it is the gate that unlocks everything else. If you have not completed the swarm initialisation sequence (all
|
|
270
|
+
> **This step happens BEFORE loading any files, BEFORE reading source code, BEFORE planning any build work. Swarm init is not a step buried in a checklist — it is the gate that unlocks everything else. If you have not completed the swarm initialisation sequence (all 8 steps in the odd-flow Swarm Initialisation section below), STOP and do it NOW.**
|
|
271
271
|
>
|
|
272
272
|
> The `odd-swarm-guard.sh` hook fires on every user message when in build phase without the swarm marker. If you are reading this and `.odd/.odd-flow-swarm-active` does not exist, the hook is injecting a warning into every response. Do not ignore it. Initialise the swarm now.
|
|
273
273
|
|
|
274
|
-
See: **odd-flow Swarm Initialisation** section below. Execute all
|
|
274
|
+
See: **odd-flow Swarm Initialisation** section below. Execute all 8 steps, then proceed.
|
|
275
275
|
|
|
276
276
|
8. Loads `docs/build/build-protocol.md` and `docs/build/code-excellence.md` into context. The Code Excellence standard is mandatory — the build agent applies the Design-It-Twice protocol to every function, component, and module it writes.
|
|
277
277
|
9. Confirms to the user which phase is being worked on and which outcomes are in scope.
|
|
@@ -398,33 +398,9 @@ The verification walkthrough MUST have been completed in the current session. Th
|
|
|
398
398
|
|
|
399
399
|
Execute the following steps in order:
|
|
400
400
|
|
|
401
|
-
**1.
|
|
401
|
+
**1. Commit the verified state** via git with message: `feat: verified [outcome name] — [phase]`
|
|
402
402
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
Display to the domain expert: "Checkpoint running..."
|
|
406
|
-
|
|
407
|
-
Parse the JSON output. Look for findings with severity `critical`, `high`, or `secret`.
|
|
408
|
-
|
|
409
|
-
**If Checkpoint is not installed** (command fails or returns an error): skip silently and display "Checkpoint not installed — type `npx @darrenjcoxon/vibeguard --install-tools` in your terminal to enable security scanning." Then proceed to step 3.
|
|
410
|
-
|
|
411
|
-
**2. If Checkpoint finds critical, high, or secret findings:**
|
|
412
|
-
|
|
413
|
-
Do NOT advance to the next outcome.
|
|
414
|
-
|
|
415
|
-
Translate each finding from technical language to a plain-language fix instruction. Do not show raw scanner output to the domain expert.
|
|
416
|
-
|
|
417
|
-
Brief the build agent directly with the fix instructions. Do not ask the domain expert to review them.
|
|
418
|
-
|
|
419
|
-
Display: "Checkpoint found [N] security issue(s) in this outcome. The build agent is fixing them now. This does not affect your verification — the outcome behaves correctly. Once the security fix is complete, Checkpoint will run again automatically."
|
|
420
|
-
|
|
421
|
-
After the build agent applies fixes, re-run Checkpoint automatically (repeat step 1). Repeat until Checkpoint is clear. Then proceed to step 3.
|
|
422
|
-
|
|
423
|
-
**3. If Checkpoint is clear:**
|
|
424
|
-
|
|
425
|
-
Display: "Checkpoint clear."
|
|
426
|
-
|
|
427
|
-
Commit the verified state via git with message: `feat: verified [outcome name] — [phase]`
|
|
403
|
+
> **Note:** Automated Checkpoint/vibeguard scanning was removed in v3.7.5. The scanner flagged dep-lockfile CVEs as code vulnerabilities and made every commit impossible. Security scanning is reintroduced only with a scanner that can distinguish code findings from lockfile findings. In the meantime, domain experts remain responsible for flagging anything suspicious during the verification walkthrough.
|
|
428
404
|
|
|
429
405
|
Call `mcp__odd-flow__memory_store` key `odd-outcome-[name]` with status `verified`, namespace `odd-project`.
|
|
430
406
|
|
|
@@ -438,8 +414,6 @@ Display:
|
|
|
438
414
|
|
|
439
415
|
**[Outcome name] — verified and committed.**
|
|
440
416
|
|
|
441
|
-
Checkpoint: clear.
|
|
442
|
-
|
|
443
417
|
**Next:** [next outcome name and one-sentence description]
|
|
444
418
|
|
|
445
419
|
Type `*build` to begin, or `*status` to see the full phase progress.
|
|
@@ -707,29 +681,23 @@ Call `mcp__odd-flow__agent_spawn`:
|
|
|
707
681
|
- Role: qa
|
|
708
682
|
- Instructions: `"Read verification steps per outcome from odd-flow. Run all steps after each outcome completes. Report failures in domain language only. Flag as verified or failed."`
|
|
709
683
|
|
|
710
|
-
### 8.
|
|
711
|
-
|
|
712
|
-
Create the swarm marker file that unlocks source code writes:
|
|
684
|
+
### 8. Sync All Agents — automatically activates the write gate
|
|
713
685
|
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
686
|
+
Call `mcp__odd-flow__coordination_sync`:
|
|
687
|
+
- Namespace: `odd-project`
|
|
688
|
+
- Message: "Phase [n] build started. All agents: retrieve your assignments from odd-flow memory key odd-project-state and begin execution according to the Build Protocol."
|
|
717
689
|
|
|
718
|
-
**
|
|
690
|
+
**This step is the LAST init action.** When `coordination_sync` succeeds in build phase, the `sync-validate` hook automatically creates all three swarm markers:
|
|
719
691
|
|
|
720
|
-
1. **`.odd/.odd-flow-swarm-active`** —
|
|
692
|
+
1. **`.odd/.odd-flow-swarm-active`** — gates source writes (24-hour TTL)
|
|
693
|
+
2. **`.odd/.odd-flow-agents-ready`** — unblocks build-gate for Task agents
|
|
694
|
+
3. **`.odd/.odd-flow-phase-synced`** — confirms agents have phase context
|
|
721
695
|
|
|
722
|
-
|
|
696
|
+
You do NOT manually `touch` these markers. The hook handles it. Steps 1–7 store state and spawn agents in parallel; step 8 finalises and unlocks the build. If the marker is missing after coordination_sync succeeds, the hook is broken — fix the hook, do not manually touch the marker.
|
|
723
697
|
|
|
724
698
|
The marker TTL is 24 hours (86400 seconds) because build sessions can last many hours. If the marker expires, run `*build` again to refresh it.
|
|
725
699
|
|
|
726
|
-
### 9.
|
|
727
|
-
|
|
728
|
-
Call `mcp__odd-flow__coordination_sync`:
|
|
729
|
-
- Namespace: `odd-project`
|
|
730
|
-
- Message: "Phase [n] build started. All agents: retrieve your assignments from odd-flow memory key odd-project-state and begin execution according to the Build Protocol."
|
|
731
|
-
|
|
732
|
-
### 10. Confirm to User
|
|
700
|
+
### 9. Confirm to User
|
|
733
701
|
|
|
734
702
|
Display:
|
|
735
703
|
|