hool-cli 0.4.0 → 0.5.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.
@@ -1,17 +1,25 @@
1
1
  #!/bin/bash
2
2
  # Hook: Post-agent operational checklist reminder
3
3
  # Type: Stop and SubagentStop
4
- # Injects a reminder asking if the agent completed its operational duties
4
+ # Outputs JSON with additionalContext so the agent actually sees and acts on it
5
+ # (plain text to stdout was often ignored — JSON injection ensures visibility)
5
6
 
6
- echo "OPERATIONAL CHECKLIST Did you complete these before finishing?"
7
- echo "[ ] Updated memory/cold.md with work log entries"
8
- echo "[ ] Rebuilt memory/hot.md from cold log"
9
- echo "[ ] Moved [GOTCHA]/[PATTERN] entries to best-practices.md"
10
- echo "[ ] Logged any issues to operations/issues.md"
11
- echo "[ ] Logged any inconsistencies to operations/inconsistencies.md"
12
- echo "[ ] Marked task complete on operations/task-board.md"
13
- echo "[ ] Verified no governor-feedback.md violations in your output"
14
- echo ""
15
- echo "If any items are incomplete, address them now before returning."
7
+ PROJECT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo '.')"
8
+ HOOL_DIR="$PROJECT_ROOT/.hool"
9
+
10
+ # Check if task-board was recently updated (within last 5 minutes)
11
+ STALE_WARNING=""
12
+ if [ -f "$HOOL_DIR/operations/task-board.md" ]; then
13
+ TASK_BOARD_MOD=$(stat -f %m "$HOOL_DIR/operations/task-board.md" 2>/dev/null || stat -c %Y "$HOOL_DIR/operations/task-board.md" 2>/dev/null || echo "0")
14
+ NOW=$(date +%s)
15
+ AGE=$((NOW - TASK_BOARD_MOD))
16
+ if [ "$AGE" -gt 300 ]; then
17
+ STALE_WARNING=" WARNING: task-board.md not updated in ${AGE}s."
18
+ fi
19
+ fi
20
+
21
+ CHECKLIST="OPERATIONAL CHECKLIST — Before finishing, verify: (1) Updated .hool/memory/<agent>/cold.md with work log entries (2) Rebuilt .hool/memory/<agent>/hot.md from cold log (3) Moved [GOTCHA]/[PATTERN] entries to best-practices.md (4) Logged issues to .hool/operations/issues.md (5) Logged inconsistencies to .hool/operations/inconsistencies.md (6) Marked task complete on .hool/operations/task-board.md (7) Verified no governor-feedback.md violations in output.${STALE_WARNING} If any items are incomplete, address them now."
22
+
23
+ printf '{"hookSpecificOutput":{"hookEventName":"Stop","additionalContext":"%s"}}\n' "$CHECKLIST"
16
24
 
17
25
  exit 0
@@ -23,8 +23,75 @@ if [ -f "$PROJECT_ROOT/.hool/operations/needs-human-review.md" ]; then
23
23
  REVIEW_ITEMS=$(grep -c '^##\|^- ' "$PROJECT_ROOT/.hool/operations/needs-human-review.md" 2>/dev/null | tr -d '\n' || echo "0")
24
24
  fi
25
25
 
26
+ # Phase-specific guidance — different advice depending on where we are
27
+ PHASE_LOWER=$(echo "$PHASE" | tr '[:upper:]' '[:lower:]')
28
+ PHASE_GUIDANCE=""
29
+ case "$PHASE_LOWER" in
30
+ *onboard*)
31
+ PHASE_GUIDANCE="ONBOARDING: Complete ALL onboarding tasks immediately. Reverse-engineer docs from code. Do not wait for explicit instruction."
32
+ ;;
33
+ *phase*0*|*init*)
34
+ PHASE_GUIDANCE="PHASE 0: Ask what we're building, determine project type and mode, capture preferences."
35
+ ;;
36
+ *phase*1*|*brainstorm*)
37
+ PHASE_GUIDANCE="PHASE 1: Interactive brainstorm with user. Explore ideas, constraints, scope. Get explicit sign-off."
38
+ ;;
39
+ *phase*2*|*spec*)
40
+ PHASE_GUIDANCE="PHASE 2: Define user stories and acceptance criteria. Get sign-off (interactive) or advance (full-hool)."
41
+ ;;
42
+ *phase*3*|*design*)
43
+ PHASE_GUIDANCE="PHASE 3: Design screens, components, visual language. Get sign-off (interactive) or advance (full-hool)."
44
+ ;;
45
+ *phase*4*|*arch*)
46
+ PHASE_GUIDANCE="PHASE 4: FINAL HUMAN GATE. Define tech stack, contracts, schema, flows. Get sign-off before autonomous."
47
+ ;;
48
+ *phase*5*|*fe*scaffold*|*fe*lld*)
49
+ PHASE_GUIDANCE="PHASE 5: Autonomous. Dispatch FE Tech Lead for scaffold + LLD. Verify output."
50
+ ;;
51
+ *phase*6*|*be*scaffold*|*be*lld*)
52
+ PHASE_GUIDANCE="PHASE 6: Autonomous. Dispatch BE Tech Lead for scaffold + LLD. Verify output."
53
+ ;;
54
+ *phase*7*|*test*plan*)
55
+ PHASE_GUIDANCE="PHASE 7: Autonomous. Dispatch QA for test plan. Verify coverage of all spec criteria."
56
+ ;;
57
+ *phase*8*|*impl*)
58
+ PHASE_GUIDANCE="PHASE 8: Autonomous. Dispatch FE/BE Devs per task. Check output, route issues."
59
+ ;;
60
+ *phase*9*|*review*)
61
+ PHASE_GUIDANCE="PHASE 9: Autonomous. Dispatch Tech Leads for code review. Route inconsistencies."
62
+ ;;
63
+ *phase*10*|*test*)
64
+ PHASE_GUIDANCE="PHASE 10: Autonomous. Dispatch QA for testing. Route bugs to Forensic."
65
+ ;;
66
+ *phase*11*|*forensic*)
67
+ PHASE_GUIDANCE="PHASE 11: Autonomous. Dispatch Forensic for root cause. Route fixes to Devs."
68
+ ;;
69
+ *phase*12*|*retro*)
70
+ PHASE_GUIDANCE="PHASE 12: Run retrospective. Read all agents' memory. Write findings to needs-human-review.md."
71
+ ;;
72
+ *standby*)
73
+ PHASE_GUIDANCE="STANDBY: Wait for user request. Route to appropriate phase/agent based on request type."
74
+ ;;
75
+ esac
76
+
77
+ # Check for unresolved inconsistencies
78
+ INCONSISTENCIES=0
79
+ if [ -f "$PROJECT_ROOT/.hool/operations/inconsistencies.md" ]; then
80
+ INCONSISTENCIES=$(grep -c '^- ' "$PROJECT_ROOT/.hool/operations/inconsistencies.md" 2>/dev/null | tr -d '\n' || echo "0")
81
+ fi
82
+
83
+ # Check governor dispatch count
84
+ DISPATCH_COUNT=0
85
+ if [ -f "$PROJECT_ROOT/.hool/metrics/dispatch-count.txt" ]; then
86
+ DISPATCH_COUNT=$(cat "$PROJECT_ROOT/.hool/metrics/dispatch-count.txt" 2>/dev/null | tr -d '\n' || echo "0")
87
+ fi
88
+ GOVERNOR_DUE=""
89
+ if [ "$DISPATCH_COUNT" -gt 0 ] && [ $(( DISPATCH_COUNT % 3 )) -ge 2 ]; then
90
+ GOVERNOR_DUE=" Governor audit due after next dispatch."
91
+ fi
92
+
26
93
  # Build context as a single line (JSON-safe)
27
- CONTEXT="HOOL PRODUCT LEAD CONTEXT | Current: ${PHASE} | Pending tasks: ${PENDING} | Human review items: ${REVIEW_ITEMS} | RULES: (1) NEVER edit src/ or tests/ - dispatch agents via .claude/agents/{name}.md (2) Read .hool/operations/current-phase.md and task-board.md FIRST (3) All state in .hool/ (memory/, phases/, operations/) (4) After every 3 agent dispatches, run the governor (5) No task too small for dispatch (6) If pending tasks exist, tell user and ask if you should proceed"
94
+ CONTEXT="HOOL PRODUCT LEAD CONTEXT | Current: ${PHASE} | Pending tasks: ${PENDING} | Human review: ${REVIEW_ITEMS} | Inconsistencies: ${INCONSISTENCIES} | Dispatches: ${DISPATCH_COUNT}${GOVERNOR_DUE} | ${PHASE_GUIDANCE} | RULES: (1) NEVER edit src/ or tests/ - dispatch agents (2) Read .hool/operations/current-phase.md and task-board.md FIRST (3) All state in .hool/ (4) After every 3 dispatches, run governor (5) No task too small for dispatch (6) If pending tasks, tell user and ask to proceed"
28
95
 
29
96
  # Output valid JSON
30
97
  printf '{"hookSpecificOutput":{"hookEventName":"UserPromptSubmit","additionalContext":"%s"}}\n' "$CONTEXT"
@@ -0,0 +1,75 @@
1
+ #!/bin/bash
2
+ # Hook: Save HOOL state snapshot before context compaction
3
+ # Type: PreCompact
4
+ # Why: Context compaction can lose critical phase/task state.
5
+ # This hook preserves a snapshot so the agent can recover on resume.
6
+
7
+ PROJECT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo '.')"
8
+ HOOL_DIR="$PROJECT_ROOT/.hool"
9
+ SNAPSHOTS_DIR="$HOOL_DIR/metrics/snapshots"
10
+ mkdir -p "$SNAPSHOTS_DIR"
11
+
12
+ TIMESTAMP=$(date +"%Y%m%d-%H%M%S")
13
+ SNAPSHOT_FILE="$SNAPSHOTS_DIR/pre-compact-$TIMESTAMP.md"
14
+
15
+ # Capture current phase
16
+ PHASE="unknown"
17
+ if [ -f "$HOOL_DIR/operations/current-phase.md" ]; then
18
+ PHASE=$(head -10 "$HOOL_DIR/operations/current-phase.md")
19
+ fi
20
+
21
+ # Capture pending task count and first 5 pending tasks
22
+ PENDING_TASKS=""
23
+ if [ -f "$HOOL_DIR/operations/task-board.md" ]; then
24
+ PENDING_TASKS=$(grep '^\- \[ \]' "$HOOL_DIR/operations/task-board.md" 2>/dev/null | head -5)
25
+ fi
26
+
27
+ # Capture last 10 entries from PL cold log
28
+ RECENT_LOG=""
29
+ if [ -f "$HOOL_DIR/memory/product-lead/cold.md" ]; then
30
+ RECENT_LOG=$(tail -10 "$HOOL_DIR/memory/product-lead/cold.md")
31
+ fi
32
+
33
+ # Capture items needing human review
34
+ REVIEW_COUNT=0
35
+ if [ -f "$HOOL_DIR/operations/needs-human-review.md" ]; then
36
+ REVIEW_COUNT=$(grep -c '^##\|^- ' "$HOOL_DIR/operations/needs-human-review.md" 2>/dev/null | tr -d '\n' || echo "0")
37
+ fi
38
+
39
+ # Capture dispatch count
40
+ DISPATCH_COUNT=0
41
+ if [ -f "$HOOL_DIR/metrics/dispatch-count.txt" ]; then
42
+ DISPATCH_COUNT=$(cat "$HOOL_DIR/metrics/dispatch-count.txt" 2>/dev/null | tr -d '\n' || echo "0")
43
+ fi
44
+
45
+ # Write snapshot
46
+ cat > "$SNAPSHOT_FILE" << SNAPSHOT
47
+ # HOOL Pre-Compaction Snapshot
48
+ **Timestamp:** $TIMESTAMP
49
+ **Dispatch count:** $DISPATCH_COUNT
50
+ **Human review items:** $REVIEW_COUNT
51
+
52
+ ## Current Phase
53
+ $PHASE
54
+
55
+ ## Pending Tasks (first 5)
56
+ $PENDING_TASKS
57
+
58
+ ## Recent Activity (last 10 cold log entries)
59
+ $RECENT_LOG
60
+ SNAPSHOT
61
+
62
+ # Also inject context into the conversation so the agent doesn't lose state
63
+ PHASE_ONELINER=$(echo "$PHASE" | head -1 | tr -d '\n')
64
+ TASK_COUNT=$(echo "$PENDING_TASKS" | grep -c '.' 2>/dev/null | tr -d '\n' || echo "0")
65
+
66
+ cat << JSONEOF
67
+ {
68
+ "hookSpecificOutput": {
69
+ "hookEventName": "PreCompact",
70
+ "additionalContext": "HOOL STATE SNAPSHOT (pre-compaction): Phase: ${PHASE_ONELINER} | Pending tasks: ${TASK_COUNT} | Dispatches: ${DISPATCH_COUNT} | Review items: ${REVIEW_COUNT} | IMPORTANT: After compaction, re-read .hool/operations/current-phase.md and .hool/operations/task-board.md to restore full context. Snapshot saved to ${SNAPSHOT_FILE}"
71
+ }
72
+ }
73
+ JSONEOF
74
+
75
+ exit 0
@@ -0,0 +1,43 @@
1
+ #!/bin/bash
2
+ # Hook Profile Wrapper — conditionally runs a hook based on HOOL_HOOK_PROFILE
3
+ # Usage: run-if-profile.sh <required-profiles-csv> <actual-hook-script>
4
+ # Example: run-if-profile.sh "standard,strict" ".hool/hooks/suggest-compact.sh"
5
+ #
6
+ # Profile levels:
7
+ # minimal — only safety-critical hooks (block-pl-src-write, pre-compact)
8
+ # standard — default: safety + operational (all hooks except strict-only)
9
+ # strict — maximum guardrails: all hooks active
10
+ #
11
+ # Set via: export HOOL_HOOK_PROFILE=minimal|standard|strict
12
+ # Default: standard
13
+
14
+ REQUIRED_PROFILES="$1"
15
+ HOOK_SCRIPT="$2"
16
+
17
+ if [ -z "$HOOK_SCRIPT" ]; then
18
+ echo "Usage: run-if-profile.sh <profiles-csv> <hook-script>" >&2
19
+ exit 0
20
+ fi
21
+
22
+ # Default profile
23
+ CURRENT_PROFILE="${HOOL_HOOK_PROFILE:-standard}"
24
+
25
+ # Check if current profile is in the required list
26
+ ENABLED=false
27
+ IFS=',' read -ra PROFILES <<< "$REQUIRED_PROFILES"
28
+ for profile in "${PROFILES[@]}"; do
29
+ profile=$(echo "$profile" | tr -d ' ')
30
+ if [ "$profile" = "$CURRENT_PROFILE" ]; then
31
+ ENABLED=true
32
+ break
33
+ fi
34
+ done
35
+
36
+ if [ "$ENABLED" = false ]; then
37
+ # Pass through stdin unchanged
38
+ cat
39
+ exit 0
40
+ fi
41
+
42
+ # Profile matches — run the actual hook, passing stdin through
43
+ exec bash "$HOOK_SCRIPT"
@@ -0,0 +1,50 @@
1
+ #!/bin/bash
2
+ # Hook: Load HOOL state on new session start
3
+ # Type: PreToolUse (first invocation) or UserPromptSubmit
4
+ # Why: When a new session begins, the agent needs to know where it left off.
5
+ # This hook injects the most recent pre-compact snapshot + current state.
6
+
7
+ PROJECT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo '.')"
8
+ HOOL_DIR="$PROJECT_ROOT/.hool"
9
+ SNAPSHOTS_DIR="$HOOL_DIR/metrics/snapshots"
10
+ SESSION_MARKER="$HOOL_DIR/metrics/session-active.txt"
11
+
12
+ # Only run once per session — check if we already injected
13
+ if [ -f "$SESSION_MARKER" ]; then
14
+ MARKER_AGE=$(( $(date +%s) - $(stat -f %m "$SESSION_MARKER" 2>/dev/null || stat -c %Y "$SESSION_MARKER" 2>/dev/null || echo "0") ))
15
+ # If marker is less than 60 seconds old, skip (already ran this session)
16
+ if [ "$MARKER_AGE" -lt 60 ]; then
17
+ exit 0
18
+ fi
19
+ fi
20
+
21
+ # Mark session as active
22
+ date +%s > "$SESSION_MARKER" 2>/dev/null
23
+
24
+ # Find the most recent snapshot
25
+ LATEST_SNAPSHOT=""
26
+ if [ -d "$SNAPSHOTS_DIR" ]; then
27
+ LATEST_SNAPSHOT=$(ls -t "$SNAPSHOTS_DIR"/pre-compact-*.md 2>/dev/null | head -1)
28
+ fi
29
+
30
+ # Build session context
31
+ PHASE="unknown"
32
+ if [ -f "$HOOL_DIR/operations/current-phase.md" ]; then
33
+ PHASE=$(head -3 "$HOOL_DIR/operations/current-phase.md" | tr '\n' ' ' | sed 's/[[:space:]]*$//')
34
+ fi
35
+
36
+ PENDING=0
37
+ if [ -f "$HOOL_DIR/operations/task-board.md" ]; then
38
+ PENDING=$(grep -c '^\- \[ \]' "$HOOL_DIR/operations/task-board.md" 2>/dev/null | tr -d '\n' || echo "0")
39
+ fi
40
+
41
+ SNAPSHOT_INFO=""
42
+ if [ -n "$LATEST_SNAPSHOT" ]; then
43
+ SNAPSHOT_INFO=" | Last snapshot: $(basename "$LATEST_SNAPSHOT")"
44
+ fi
45
+
46
+ CONTEXT="HOOL SESSION RESUMED | Phase: ${PHASE} | Pending tasks: ${PENDING}${SNAPSHOT_INFO} | ACTION: Read .hool/operations/current-phase.md and .hool/operations/task-board.md immediately. If there are pending tasks, tell the user and ask if you should proceed."
47
+
48
+ printf '{"hookSpecificOutput":{"hookEventName":"UserPromptSubmit","additionalContext":"%s"}}\n' "$CONTEXT"
49
+
50
+ exit 0
@@ -0,0 +1,32 @@
1
+ #!/bin/bash
2
+ # Hook: Suggest strategic /compact at logical intervals
3
+ # Type: PreToolUse on Edit|Write
4
+ # Why: Auto-compact happens at arbitrary points, often mid-task.
5
+ # Strategic compaction between phases preserves better context.
6
+
7
+ PROJECT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo '.')"
8
+ METRICS_DIR="$PROJECT_ROOT/.hool/metrics"
9
+ mkdir -p "$METRICS_DIR"
10
+
11
+ COUNTER_FILE="$METRICS_DIR/tool-call-count.txt"
12
+ THRESHOLD="${HOOL_COMPACT_THRESHOLD:-50}"
13
+
14
+ # Read and increment counter
15
+ CURRENT=$(cat "$COUNTER_FILE" 2>/dev/null || echo "0")
16
+ NEXT=$((CURRENT + 1))
17
+ echo "$NEXT" > "$COUNTER_FILE"
18
+
19
+ # Suggest at threshold
20
+ if [ "$NEXT" -eq "$THRESHOLD" ]; then
21
+ echo "HOOL: ${THRESHOLD} tool calls reached. Consider running /compact if you're between phases or tasks." >&2
22
+ fi
23
+
24
+ # Suggest every 25 calls after threshold
25
+ if [ "$NEXT" -gt "$THRESHOLD" ]; then
26
+ OVER=$((NEXT - THRESHOLD))
27
+ if [ $((OVER % 25)) -eq 0 ]; then
28
+ echo "HOOL: ${NEXT} tool calls. Good checkpoint for /compact if context feels stale." >&2
29
+ fi
30
+ fi
31
+
32
+ exit 0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hool-cli",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Agent-Driven SDLC — scaffold and configure HOOL for any project",
5
5
  "bin": {
6
6
  "hool": "./dist/index.js"
@@ -9,7 +9,19 @@
9
9
  "command": ".hool/hooks/block-pl-src-write.sh",
10
10
  "timeout": 5
11
11
  }
12
- ]
12
+ ],
13
+ "description": "Block Product Lead from editing src/ or tests/ directly"
14
+ },
15
+ {
16
+ "matcher": "Edit|Write",
17
+ "hooks": [
18
+ {
19
+ "type": "command",
20
+ "command": ".hool/hooks/suggest-compact.sh",
21
+ "timeout": 3
22
+ }
23
+ ],
24
+ "description": "Suggest strategic /compact at logical intervals"
13
25
  }
14
26
  ],
15
27
  "PostToolUse": [
@@ -21,7 +33,8 @@
21
33
  "command": ".hool/hooks/track-prompt-count.sh",
22
34
  "timeout": 5
23
35
  }
24
- ]
36
+ ],
37
+ "description": "Track dispatch count, trigger governor every 3 dispatches"
25
38
  }
26
39
  ],
27
40
  "UserPromptSubmit": [
@@ -33,7 +46,21 @@
33
46
  "command": ".hool/hooks/inject-pl-context.sh",
34
47
  "timeout": 5
35
48
  }
36
- ]
49
+ ],
50
+ "description": "Inject phase-aware PL context on every user prompt"
51
+ }
52
+ ],
53
+ "PreCompact": [
54
+ {
55
+ "matcher": "",
56
+ "hooks": [
57
+ {
58
+ "type": "command",
59
+ "command": ".hool/hooks/pre-compact.sh",
60
+ "timeout": 10
61
+ }
62
+ ],
63
+ "description": "Save HOOL state snapshot before context compaction"
37
64
  }
38
65
  ],
39
66
  "Stop": [
@@ -45,7 +72,8 @@
45
72
  "command": ".hool/hooks/agent-checklist.sh",
46
73
  "timeout": 5
47
74
  }
48
- ]
75
+ ],
76
+ "description": "Operational checklist reminder after each response"
49
77
  }
50
78
  ],
51
79
  "SubagentStop": [
@@ -57,7 +85,8 @@
57
85
  "command": ".hool/hooks/agent-checklist.sh",
58
86
  "timeout": 5
59
87
  }
60
- ]
88
+ ],
89
+ "description": "Operational checklist reminder after subagent completes"
61
90
  }
62
91
  ]
63
92
  }