oh-my-claude-sisyphus 3.8.2 → 3.8.4

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,268 +0,0 @@
1
- #!/bin/bash
2
- # OMC Keyword Detector Hook (Bash)
3
- # Detects magic keywords and invokes skill tools
4
- # Linux/macOS compatible
5
- #
6
- # Supported keywords (in priority order):
7
- # 1. cancel: Stop active modes
8
- # 2. ralph: Persistence mode until task completion
9
- # 3. autopilot: Full autonomous execution
10
- # 4. ultrapilot: Parallel autopilot
11
- # 5. ultrawork/ulw: Maximum parallel execution
12
- # 6. ecomode/eco: Token-efficient execution
13
- # 7. swarm: N coordinated agents
14
- # 8. pipeline: Sequential agent chaining
15
- # 9. ralplan: Iterative planning with consensus
16
- # 10. plan: Planning interview mode
17
- # 11. tdd: Test-driven development
18
- # 12. research: Research orchestration
19
- # 13. ultrathink/think: Extended reasoning
20
- # 14. deepsearch: Codebase search (restricted patterns)
21
- # 15. analyze: Analysis mode (restricted patterns)
22
-
23
- # Read stdin (JSON input from Claude Code)
24
- INPUT=$(cat)
25
-
26
- # Extract directory from input
27
- DIRECTORY=""
28
- if command -v jq &> /dev/null; then
29
- DIRECTORY=$(echo "$INPUT" | jq -r '.directory // ""' 2>/dev/null)
30
- fi
31
- if [ -z "$DIRECTORY" ] || [ "$DIRECTORY" = "null" ]; then
32
- DIRECTORY=$(pwd)
33
- fi
34
-
35
- # Extract the prompt text - try multiple JSON paths
36
- PROMPT=""
37
- if command -v jq &> /dev/null; then
38
- # Try to extract from various possible JSON structures
39
- PROMPT=$(echo "$INPUT" | jq -r '
40
- if .prompt then .prompt
41
- elif .message.content then .message.content
42
- elif .parts then ([.parts[] | select(.type == "text") | .text] | join(" "))
43
- else ""
44
- end
45
- ' 2>/dev/null)
46
- fi
47
-
48
- # Fallback: simple grep extraction if jq fails
49
- if [ -z "$PROMPT" ] || [ "$PROMPT" = "null" ]; then
50
- PROMPT=$(echo "$INPUT" | grep -oP '"(prompt|content|text)"\s*:\s*"\K[^"]+' | head -1)
51
- fi
52
-
53
- # Exit if no prompt found
54
- if [ -z "$PROMPT" ]; then
55
- echo '{"continue": true}'
56
- exit 0
57
- fi
58
-
59
- # Remove code blocks before checking keywords (prevents false positives)
60
- PROMPT_NO_CODE=$(echo "$PROMPT" | sed 's/```[^`]*```//g' | sed 's/`[^`]*`//g')
61
-
62
- # Convert to lowercase for case-insensitive matching
63
- PROMPT_LOWER=$(echo "$PROMPT_NO_CODE" | tr '[:upper:]' '[:lower:]')
64
-
65
- # Create a skill invocation message that tells Claude to use the Skill tool
66
- create_skill_invocation() {
67
- local skill_name="$1"
68
- local original_prompt="$2"
69
- local args="$3"
70
-
71
- local args_section=""
72
- if [ -n "$args" ]; then
73
- args_section="\\nArguments: $args"
74
- fi
75
-
76
- local skill_upper=$(echo "$skill_name" | tr '[:lower:]' '[:upper:]')
77
-
78
- cat << EOF
79
- [MAGIC KEYWORD: ${skill_upper}]
80
-
81
- You MUST invoke the skill using the Skill tool:
82
-
83
- Skill: oh-my-claudecode:${skill_name}${args_section}
84
-
85
- User request:
86
- ${original_prompt}
87
-
88
- IMPORTANT: Invoke the skill IMMEDIATELY. Do not proceed without loading the skill instructions.
89
- EOF
90
- }
91
-
92
- # Clear state files for cancel operation
93
- clear_state_files() {
94
- local directory="$1"
95
- local modes=("ralph" "autopilot" "ultrapilot" "ultrawork" "ecomode" "swarm" "pipeline")
96
-
97
- for mode in "${modes[@]}"; do
98
- rm -f "$directory/.omc/state/${mode}-state.json" 2>/dev/null
99
- rm -f "$HOME/.omc/state/${mode}-state.json" 2>/dev/null
100
- done
101
- }
102
-
103
- # Activate state for a mode
104
- activate_state() {
105
- local directory="$1"
106
- local prompt="$2"
107
- local state_name="$3"
108
-
109
- # Create directories
110
- mkdir -p "$directory/.omc/state" 2>/dev/null
111
- mkdir -p "$HOME/.omc/state" 2>/dev/null
112
-
113
- # Escape prompt for JSON
114
- local prompt_escaped=$(echo "$prompt" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | tr '\n' ' ')
115
- local timestamp=$(date -Iseconds 2>/dev/null || date +%Y-%m-%dT%H:%M:%S%z)
116
-
117
- local state_json="{
118
- \"active\": true,
119
- \"started_at\": \"$timestamp\",
120
- \"original_prompt\": \"$prompt_escaped\",
121
- \"reinforcement_count\": 0,
122
- \"last_checked_at\": \"$timestamp\"
123
- }"
124
-
125
- # Write state to both local and global locations
126
- echo "$state_json" > "$directory/.omc/state/${state_name}-state.json" 2>/dev/null
127
- echo "$state_json" > "$HOME/.omc/state/${state_name}-state.json" 2>/dev/null
128
- }
129
-
130
- # Output JSON with skill invocation message
131
- output_skill() {
132
- local skill_name="$1"
133
- local prompt="$2"
134
- local args="$3"
135
-
136
- local message=$(create_skill_invocation "$skill_name" "$prompt" "$args")
137
- # Escape for JSON: backslashes, quotes, and newlines
138
- local escaped_message=$(echo "$message" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | awk '{printf "%s\\n", $0}' | sed 's/\\n$//')
139
-
140
- echo "{\"continue\": true, \"message\": \"$escaped_message\"}"
141
- }
142
-
143
- # Priority 1: Cancel (BEFORE other modes - clears states)
144
- if echo "$PROMPT_LOWER" | grep -qE '\b(stop|cancel|abort)\b'; then
145
- clear_state_files "$DIRECTORY"
146
- output_skill "cancel" "$PROMPT"
147
- exit 0
148
- fi
149
-
150
- # Priority 2: Ralph keywords
151
- if echo "$PROMPT_LOWER" | grep -qE '\b(ralph|don'\''t stop|must complete|until done)\b'; then
152
- activate_state "$DIRECTORY" "$PROMPT" "ralph"
153
- activate_state "$DIRECTORY" "$PROMPT" "ultrawork"
154
- output_skill "ralph" "$PROMPT"
155
- exit 0
156
- fi
157
-
158
- # Priority 3: Autopilot keywords
159
- if echo "$PROMPT_LOWER" | grep -qE '\b(autopilot|auto pilot|auto-pilot|autonomous|full auto|fullsend)\b' || \
160
- echo "$PROMPT_LOWER" | grep -qE '\bbuild\s+me\s+' || \
161
- echo "$PROMPT_LOWER" | grep -qE '\bcreate\s+me\s+' || \
162
- echo "$PROMPT_LOWER" | grep -qE '\bmake\s+me\s+' || \
163
- echo "$PROMPT_LOWER" | grep -qE '\bi\s+want\s+a\s+' || \
164
- echo "$PROMPT_LOWER" | grep -qE '\bi\s+want\s+an\s+' || \
165
- echo "$PROMPT_LOWER" | grep -qE '\bhandle\s+it\s+all\b' || \
166
- echo "$PROMPT_LOWER" | grep -qE '\bend\s+to\s+end\b' || \
167
- echo "$PROMPT_LOWER" | grep -qE '\be2e\s+this\b'; then
168
- activate_state "$DIRECTORY" "$PROMPT" "autopilot"
169
- output_skill "autopilot" "$PROMPT"
170
- exit 0
171
- fi
172
-
173
- # Priority 4: Ultrapilot
174
- if echo "$PROMPT_LOWER" | grep -qE '\b(ultrapilot|ultra-pilot)\b' || \
175
- echo "$PROMPT_LOWER" | grep -qE '\bparallel\s+build\b' || \
176
- echo "$PROMPT_LOWER" | grep -qE '\bswarm\s+build\b'; then
177
- activate_state "$DIRECTORY" "$PROMPT" "ultrapilot"
178
- output_skill "ultrapilot" "$PROMPT"
179
- exit 0
180
- fi
181
-
182
- # Priority 5: Ultrawork keywords
183
- if echo "$PROMPT_LOWER" | grep -qE '\b(ultrawork|ulw|uw)\b'; then
184
- activate_state "$DIRECTORY" "$PROMPT" "ultrawork"
185
- output_skill "ultrawork" "$PROMPT"
186
- exit 0
187
- fi
188
-
189
- # Priority 6: Ecomode keywords
190
- if echo "$PROMPT_LOWER" | grep -qE '\b(eco|ecomode|eco-mode|efficient|save-tokens|budget)\b'; then
191
- activate_state "$DIRECTORY" "$PROMPT" "ecomode"
192
- output_skill "ecomode" "$PROMPT"
193
- exit 0
194
- fi
195
-
196
- # Priority 7: Swarm - parse N from "swarm N agents"
197
- SWARM_MATCH=$(echo "$PROMPT_LOWER" | grep -oE '\bswarm\s+[0-9]+\s+agents?\b' | grep -oE '[0-9]+')
198
- if [ -n "$SWARM_MATCH" ]; then
199
- output_skill "swarm" "$PROMPT" "$SWARM_MATCH"
200
- exit 0
201
- fi
202
- if echo "$PROMPT_LOWER" | grep -qE '\bcoordinated\s+agents\b'; then
203
- output_skill "swarm" "$PROMPT" "3"
204
- exit 0
205
- fi
206
-
207
- # Priority 8: Pipeline
208
- if echo "$PROMPT_LOWER" | grep -qE '\b(pipeline)\b' || \
209
- echo "$PROMPT_LOWER" | grep -qE '\bchain\s+agents\b'; then
210
- output_skill "pipeline" "$PROMPT"
211
- exit 0
212
- fi
213
-
214
- # Priority 9: Ralplan keyword (before plan to avoid false match)
215
- if echo "$PROMPT_LOWER" | grep -qE '\b(ralplan)\b'; then
216
- output_skill "ralplan" "$PROMPT"
217
- exit 0
218
- fi
219
-
220
- # Priority 10: Plan keywords
221
- if echo "$PROMPT_LOWER" | grep -qE '\b(plan this|plan the)\b'; then
222
- output_skill "plan" "$PROMPT"
223
- exit 0
224
- fi
225
-
226
- # Priority 11: TDD
227
- if echo "$PROMPT_LOWER" | grep -qE '\b(tdd)\b' || \
228
- echo "$PROMPT_LOWER" | grep -qE '\btest\s+first\b' || \
229
- echo "$PROMPT_LOWER" | grep -qE '\bred\s+green\b'; then
230
- output_skill "tdd" "$PROMPT"
231
- exit 0
232
- fi
233
-
234
- # Priority 12: Research
235
- if echo "$PROMPT_LOWER" | grep -qE '\b(research)\b' || \
236
- echo "$PROMPT_LOWER" | grep -qE '\banalyze\s+data\b' || \
237
- echo "$PROMPT_LOWER" | grep -qE '\bstatistics\b'; then
238
- output_skill "research" "$PROMPT"
239
- exit 0
240
- fi
241
-
242
- # Priority 13: Ultrathink/think keywords (keep inline message)
243
- if echo "$PROMPT_LOWER" | grep -qE '\b(ultrathink|think hard|think deeply)\b'; then
244
- cat << 'EOF'
245
- {"continue": true, "message": "<think-mode>\n\n**ULTRATHINK MODE ENABLED** - Extended reasoning activated.\n\nYou are now in deep thinking mode. Take your time to:\n1. Thoroughly analyze the problem from multiple angles\n2. Consider edge cases and potential issues\n3. Think through the implications of each approach\n4. Reason step-by-step before acting\n\nUse your extended thinking capabilities to provide the most thorough and well-reasoned response.\n\n</think-mode>\n\n---\n"}
246
- EOF
247
- exit 0
248
- fi
249
-
250
- # Priority 14: Deepsearch (RESTRICTED patterns)
251
- if echo "$PROMPT_LOWER" | grep -qE '\b(deepsearch)\b' || \
252
- echo "$PROMPT_LOWER" | grep -qE '\bsearch\s+(the\s+)?(codebase|code|files|project)\b' || \
253
- echo "$PROMPT_LOWER" | grep -qE '\bfind\s+(in\s+)?(codebase|code|all\s+files)\b'; then
254
- output_skill "deepsearch" "$PROMPT"
255
- exit 0
256
- fi
257
-
258
- # Priority 15: Analyze (RESTRICTED patterns)
259
- if echo "$PROMPT_LOWER" | grep -qE '\bdeep\s*analyze\b' || \
260
- echo "$PROMPT_LOWER" | grep -qE '\binvestigate\s+(the|this|why)\b' || \
261
- echo "$PROMPT_LOWER" | grep -qE '\bdebug\s+(the|this|why)\b'; then
262
- output_skill "analyze" "$PROMPT"
263
- exit 0
264
- fi
265
-
266
- # No keywords detected - continue without modification
267
- echo '{"continue": true}'
268
- exit 0
@@ -1,244 +0,0 @@
1
- #!/bin/bash
2
- # OMC Persistent Mode Hook
3
- # Unified handler for ultrawork, ralph-loop, and todo continuation
4
- # Prevents stopping when work remains incomplete
5
-
6
- # Validate session ID to prevent path traversal attacks
7
- # Returns 0 (success) for valid, 1 for invalid
8
- is_valid_session_id() {
9
- local id="$1"
10
- if [ -z "$id" ]; then
11
- return 1
12
- fi
13
- # Allow alphanumeric, hyphens, and underscores only
14
- # Must not start with dot or hyphen, max 256 chars
15
- if echo "$id" | grep -qE '^[a-zA-Z0-9][a-zA-Z0-9_-]{0,255}$'; then
16
- return 0
17
- fi
18
- return 1
19
- }
20
-
21
- # Read stdin
22
- INPUT=$(cat)
23
-
24
- # Get session ID and directory
25
- SESSION_ID=""
26
- DIRECTORY=""
27
- if command -v jq &> /dev/null; then
28
- SESSION_ID=$(echo "$INPUT" | jq -r '.sessionId // .session_id // ""' 2>/dev/null)
29
- DIRECTORY=$(echo "$INPUT" | jq -r '.directory // ""' 2>/dev/null)
30
- fi
31
-
32
- # Default to current directory
33
- if [ -z "$DIRECTORY" ]; then
34
- DIRECTORY=$(pwd)
35
- fi
36
-
37
- # Check for incomplete tasks in new Task system (priority over todos)
38
- TASKS_DIR="$HOME/.claude/tasks"
39
- TASK_COUNT=0
40
- JQ_AVAILABLE=false
41
- if command -v jq &> /dev/null; then
42
- JQ_AVAILABLE=true
43
- fi
44
-
45
- if [ -n "$SESSION_ID" ] && is_valid_session_id "$SESSION_ID" && [ -d "$TASKS_DIR/$SESSION_ID" ]; then
46
- for task_file in "$TASKS_DIR/$SESSION_ID"/*.json; do
47
- if [ -f "$task_file" ] && [ "$(basename "$task_file")" != ".lock" ]; then
48
- if [ "$JQ_AVAILABLE" = "true" ]; then
49
- STATUS=$(jq -r '.status // "pending"' "$task_file" 2>/dev/null)
50
- # Match TypeScript isTaskIncomplete(): only pending/in_progress are incomplete
51
- # 'deleted' and 'completed' are both treated as done
52
- if [ "$STATUS" = "pending" ] || [ "$STATUS" = "in_progress" ]; then
53
- TASK_COUNT=$((TASK_COUNT + 1))
54
- fi
55
- else
56
- # Fallback: grep for incomplete status values (pending or in_progress)
57
- # This is less accurate but provides basic functionality
58
- if grep -qE '"status"[[:space:]]*:[[:space:]]*"(pending|in_progress)"' "$task_file" 2>/dev/null; then
59
- TASK_COUNT=$((TASK_COUNT + 1))
60
- fi
61
- fi
62
- fi
63
- done
64
-
65
- # Warn if using fallback (only once per invocation, to stderr)
66
- if [ "$JQ_AVAILABLE" = "false" ] && [ "$TASK_COUNT" -gt 0 ]; then
67
- echo "[OMC WARNING] jq not installed - Task counting may be less accurate. Install jq for best results." >&2
68
- fi
69
- fi
70
-
71
- # Extract stop reason for abort detection
72
- STOP_REASON=""
73
- USER_REQUESTED=""
74
- if command -v jq &> /dev/null; then
75
- STOP_REASON=$(echo "$INPUT" | jq -r '.stop_reason // .stopReason // ""' 2>/dev/null)
76
- USER_REQUESTED=$(echo "$INPUT" | jq -r '.user_requested // .userRequested // "false"' 2>/dev/null)
77
- fi
78
-
79
- # Check for user abort before continuation checks
80
- # NOTE: Abort patterns are assumed - verify against actual Claude Code API values
81
- if [ "$USER_REQUESTED" = "true" ] || echo "$STOP_REASON" | grep -qiE "(abort|cancel|interrupt|ctrl_c|manual_stop)"; then
82
- echo '{"continue": true}'
83
- exit 0
84
- fi
85
-
86
- # Check for active ultrawork state
87
- ULTRAWORK_STATE=""
88
- if [ -f "$DIRECTORY/.omc/state/ultrawork-state.json" ]; then
89
- ULTRAWORK_STATE=$(cat "$DIRECTORY/.omc/state/ultrawork-state.json" 2>/dev/null)
90
- elif [ -f "$HOME/.omc/state/ultrawork-state.json" ]; then
91
- ULTRAWORK_STATE=$(cat "$HOME/.omc/state/ultrawork-state.json" 2>/dev/null)
92
- fi
93
-
94
- # Check for active ralph loop
95
- RALPH_STATE=""
96
- if [ -f "$DIRECTORY/.omc/state/ralph-state.json" ]; then
97
- RALPH_STATE=$(cat "$DIRECTORY/.omc/state/ralph-state.json" 2>/dev/null)
98
- fi
99
-
100
- # Check for verification state (oracle verification)
101
- VERIFICATION_STATE=""
102
- if [ -f "$DIRECTORY/.omc/state/ralph-verification.json" ]; then
103
- VERIFICATION_STATE=$(cat "$DIRECTORY/.omc/state/ralph-verification.json" 2>/dev/null)
104
- fi
105
-
106
- # Check for incomplete todos
107
- INCOMPLETE_COUNT=0
108
- TODOS_DIR="$HOME/.claude/todos"
109
- if [ -d "$TODOS_DIR" ]; then
110
- for todo_file in "$TODOS_DIR"/*.json; do
111
- if [ -f "$todo_file" ]; then
112
- if command -v jq &> /dev/null; then
113
- COUNT=$(jq '[.[] | select(.status != "completed" and .status != "cancelled")] | length' "$todo_file" 2>/dev/null || echo "0")
114
- INCOMPLETE_COUNT=$((INCOMPLETE_COUNT + COUNT))
115
- else
116
- # Fallback: count "pending" or "in_progress" occurrences
117
- COUNT=$(grep -c '"status"[[:space:]]*:[[:space:]]*"pending\|in_progress"' "$todo_file" 2>/dev/null) || COUNT=0
118
- INCOMPLETE_COUNT=$((INCOMPLETE_COUNT + COUNT))
119
- fi
120
- fi
121
- done
122
- fi
123
-
124
- # Check project todos as well
125
- for todo_path in "$DIRECTORY/.omc/todos.json" "$DIRECTORY/.claude/todos.json"; do
126
- if [ -f "$todo_path" ]; then
127
- if command -v jq &> /dev/null; then
128
- COUNT=$(jq 'if type == "array" then [.[] | select(.status != "completed" and .status != "cancelled")] | length else 0 end' "$todo_path" 2>/dev/null || echo "0")
129
- INCOMPLETE_COUNT=$((INCOMPLETE_COUNT + COUNT))
130
- else
131
- # Fallback: count "pending" or "in_progress" occurrences
132
- COUNT=$(grep -c '"status"[[:space:]]*:[[:space:]]*"pending\|in_progress"' "$todo_path" 2>/dev/null) || COUNT=0
133
- INCOMPLETE_COUNT=$((INCOMPLETE_COUNT + COUNT))
134
- fi
135
- fi
136
- done
137
-
138
- # Combine Task and todo counts
139
- TOTAL_INCOMPLETE=$((TASK_COUNT + INCOMPLETE_COUNT))
140
-
141
- # Priority 1: Ralph Loop with Oracle Verification
142
- if [ -n "$RALPH_STATE" ]; then
143
- IS_ACTIVE=$(echo "$RALPH_STATE" | jq -r '.active // false' 2>/dev/null)
144
- if [ "$IS_ACTIVE" = "true" ]; then
145
- ITERATION=$(echo "$RALPH_STATE" | jq -r '.iteration // 1' 2>/dev/null)
146
- MAX_ITER=$(echo "$RALPH_STATE" | jq -r '.max_iterations // 10' 2>/dev/null)
147
- PROMISE=$(echo "$RALPH_STATE" | jq -r '.completion_promise // "TASK_COMPLETE"' 2>/dev/null)
148
- PROMPT=$(echo "$RALPH_STATE" | jq -r '.prompt // ""' 2>/dev/null)
149
-
150
- # Check if oracle verification is pending
151
- if [ -n "$VERIFICATION_STATE" ]; then
152
- IS_PENDING=$(echo "$VERIFICATION_STATE" | jq -r '.pending // false' 2>/dev/null)
153
- if [ "$IS_PENDING" = "true" ]; then
154
- ATTEMPT=$(echo "$VERIFICATION_STATE" | jq -r '.verification_attempts // 0' 2>/dev/null)
155
- MAX_ATTEMPTS=$(echo "$VERIFICATION_STATE" | jq -r '.max_verification_attempts // 3' 2>/dev/null)
156
- ORIGINAL_TASK=$(echo "$VERIFICATION_STATE" | jq -r '.original_task // ""' 2>/dev/null)
157
- COMPLETION_CLAIM=$(echo "$VERIFICATION_STATE" | jq -r '.completion_claim // ""' 2>/dev/null)
158
- ORACLE_FEEDBACK=$(echo "$VERIFICATION_STATE" | jq -r '.oracle_feedback // ""' 2>/dev/null)
159
- NEXT_ATTEMPT=$((ATTEMPT + 1))
160
-
161
- FEEDBACK_SECTION=""
162
- if [ -n "$ORACLE_FEEDBACK" ] && [ "$ORACLE_FEEDBACK" != "null" ]; then
163
- FEEDBACK_SECTION="\\n**Previous Oracle Feedback (rejected):**\\n$ORACLE_FEEDBACK\\n"
164
- fi
165
-
166
- cat << EOF
167
- {"continue": false, "reason": "<ralph-verification>\\n\\n[ORACLE VERIFICATION REQUIRED - Attempt $NEXT_ATTEMPT/$MAX_ATTEMPTS]\\n\\nThe agent claims the task is complete. Before accepting, YOU MUST verify with Oracle.\\n\\n**Original Task:**\\n$ORIGINAL_TASK\\n\\n**Completion Claim:**\\n$COMPLETION_CLAIM\\n$FEEDBACK_SECTION\\n## MANDATORY VERIFICATION STEPS\\n\\n1. **Spawn Oracle Agent** for verification:\\n \`\`\`\\n Task(subagent_type=\"oracle\", prompt=\"Verify this task completion claim...\")\\n \`\`\`\\n\\n2. **Oracle must check:**\\n - Are ALL requirements from the original task met?\\n - Is the implementation complete, not partial?\\n - Are there any obvious bugs or issues?\\n - Does the code compile/run without errors?\\n - Are tests passing (if applicable)?\\n\\n3. **Based on Oracle's response:**\\n - If APPROVED: Output \`<oracle-approved>VERIFIED_COMPLETE</oracle-approved>\`\\n - If REJECTED: Continue working on the identified issues\\n\\nDO NOT output the completion promise again until Oracle approves.\\n\\n</ralph-verification>\\n\\n---\\n"}
168
- EOF
169
- exit 0
170
- fi
171
- fi
172
-
173
- if [ "$ITERATION" -lt "$MAX_ITER" ]; then
174
- # Increment iteration
175
- NEW_ITER=$((ITERATION + 1))
176
- echo "$RALPH_STATE" | jq ".iteration = $NEW_ITER" > "$DIRECTORY/.omc/state/ralph-state.json" 2>/dev/null
177
-
178
- cat << EOF
179
- {"continue": false, "reason": "<ralph-loop-continuation>\\n\\n[RALPH LOOP - ITERATION $NEW_ITER/$MAX_ITER]\\n\\nYour previous attempt did not output the completion promise. The work is NOT done yet.\\n\\nCRITICAL INSTRUCTIONS:\\n1. Review your progress and the original task\\n2. Check your todo list - are ALL items marked complete?\\n3. Continue from where you left off\\n4. When FULLY complete, output: <promise>$PROMISE</promise>\\n5. Do NOT stop until the task is truly done\\n\\nOriginal task: $PROMPT\\n\\n</ralph-loop-continuation>\\n\\n---\\n"}
180
- EOF
181
- exit 0
182
- fi
183
- fi
184
- fi
185
-
186
- # Priority 2: Ultrawork Mode with incomplete todos
187
- if [ -n "$ULTRAWORK_STATE" ] && [ "$TOTAL_INCOMPLETE" -gt 0 ]; then
188
- # Check if active (with jq fallback)
189
- IS_ACTIVE=""
190
- if command -v jq &> /dev/null; then
191
- IS_ACTIVE=$(echo "$ULTRAWORK_STATE" | jq -r '.active // false' 2>/dev/null)
192
- else
193
- # Fallback: grep for "active": true
194
- if echo "$ULTRAWORK_STATE" | grep -q '"active"[[:space:]]*:[[:space:]]*true'; then
195
- IS_ACTIVE="true"
196
- fi
197
- fi
198
-
199
- if [ "$IS_ACTIVE" = "true" ]; then
200
- # Get reinforcement count (with fallback)
201
- REINFORCE_COUNT=0
202
- if command -v jq &> /dev/null; then
203
- REINFORCE_COUNT=$(echo "$ULTRAWORK_STATE" | jq -r '.reinforcement_count // 0' 2>/dev/null)
204
- else
205
- REINFORCE_COUNT=$(echo "$ULTRAWORK_STATE" | grep -oP '"reinforcement_count"[[:space:]]*:[[:space:]]*\K[0-9]+' 2>/dev/null) || REINFORCE_COUNT=0
206
- fi
207
- NEW_COUNT=$((REINFORCE_COUNT + 1))
208
-
209
- # Get original prompt (with fallback)
210
- ORIGINAL_PROMPT=""
211
- if command -v jq &> /dev/null; then
212
- ORIGINAL_PROMPT=$(echo "$ULTRAWORK_STATE" | jq -r '.original_prompt // ""' 2>/dev/null)
213
- else
214
- ORIGINAL_PROMPT=$(echo "$ULTRAWORK_STATE" | grep -oP '"original_prompt"[[:space:]]*:[[:space:]]*"\K[^"]+' 2>/dev/null) || ORIGINAL_PROMPT=""
215
- fi
216
-
217
- # Update state file (best effort)
218
- if command -v jq &> /dev/null; then
219
- echo "$ULTRAWORK_STATE" | jq ".reinforcement_count = $NEW_COUNT | .last_checked_at = \"$(date -Iseconds)\"" > "$DIRECTORY/.omc/state/ultrawork-state.json" 2>/dev/null
220
- fi
221
-
222
- cat << EOF
223
- {"continue": false, "reason": "<ultrawork-persistence>\\n\\n[ULTRAWORK MODE STILL ACTIVE - Reinforcement #$NEW_COUNT]\\n\\nYour ultrawork session is NOT complete. $TOTAL_INCOMPLETE incomplete items remain.\\n\\nREMEMBER THE ULTRAWORK RULES:\\n- **PARALLEL**: Fire independent calls simultaneously - NEVER wait sequentially\\n- **BACKGROUND FIRST**: Use Task(run_in_background=true) for exploration (10+ concurrent)\\n- **TODO**: Track EVERY step. Mark complete IMMEDIATELY after each\\n- **VERIFY**: Check ALL requirements met before done\\n- **NO Premature Stopping**: ALL TODOs must be complete\\n\\nContinue working on the next pending item. DO NOT STOP until all items are marked complete.\\n\\nOriginal task: $ORIGINAL_PROMPT\\n\\n</ultrawork-persistence>\\n\\n---\\n"}
224
- EOF
225
- exit 0
226
- fi
227
- fi
228
-
229
- # Priority 3: Todo/Task Continuation (baseline)
230
- if [ "$TOTAL_INCOMPLETE" -gt 0 ]; then
231
- if [ "$TASK_COUNT" -gt 0 ]; then
232
- ITEM_TYPE="Tasks"
233
- else
234
- ITEM_TYPE="todos"
235
- fi
236
- cat << EOF
237
- {"continue": false, "reason": "<todo-continuation>\\n\\n[SYSTEM REMINDER - CONTINUATION]\\n\\nIncomplete $ITEM_TYPE remain ($TOTAL_INCOMPLETE remaining). Continue working on the next pending item.\\n\\n- Proceed without asking for permission\\n- Mark each item complete when finished\\n- Do not stop until all items are done\\n\\n</todo-continuation>\\n\\n---\\n"}
238
- EOF
239
- exit 0
240
- fi
241
-
242
- # No blocking needed
243
- echo '{"continue": true}'
244
- exit 0
@@ -1,90 +0,0 @@
1
- #!/bin/bash
2
- # OMC Post-Tool-Use Hook
3
- # Processes <remember> tags from Task agent output
4
- # Saves to .omc/notepad.md for compaction-resilient memory
5
-
6
- # Read stdin
7
- INPUT=$(cat)
8
-
9
- # Get directory and tool info
10
- DIRECTORY=""
11
- TOOL_NAME=""
12
- TOOL_OUTPUT=""
13
- if command -v jq &> /dev/null; then
14
- DIRECTORY=$(echo "$INPUT" | jq -r '.directory // ""' 2>/dev/null)
15
- TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName // ""' 2>/dev/null)
16
- TOOL_OUTPUT=$(echo "$INPUT" | jq -r '.toolOutput // ""' 2>/dev/null)
17
- else
18
- # Fallback: use grep/sed for extraction
19
- DIRECTORY=$(echo "$INPUT" | grep -oP '"directory"\s*:\s*"\K[^"]+' | head -1)
20
- TOOL_NAME=$(echo "$INPUT" | grep -oP '"toolName"\s*:\s*"\K[^"]+' | head -1)
21
- TOOL_OUTPUT=$(echo "$INPUT" | grep -oP '"toolOutput"\s*:\s*"\K[^"]+' | head -1)
22
- fi
23
-
24
- if [ -z "$DIRECTORY" ]; then
25
- DIRECTORY=$(pwd)
26
- fi
27
-
28
- # Only process Task tool output
29
- if [ "$TOOL_NAME" != "Task" ] && [ "$TOOL_NAME" != "task" ]; then
30
- echo '{"continue": true}'
31
- exit 0
32
- fi
33
-
34
- # Check for <remember> tags
35
- if ! echo "$TOOL_OUTPUT" | grep -q '<remember'; then
36
- echo '{"continue": true}'
37
- exit 0
38
- fi
39
-
40
- # Create .omc directory if needed
41
- OMC_DIR="$DIRECTORY/.omc"
42
- NOTEPAD_FILE="$OMC_DIR/notepad.md"
43
- mkdir -p "$OMC_DIR" 2>/dev/null
44
-
45
- # Initialize notepad.md if it doesn't exist
46
- if [ ! -f "$NOTEPAD_FILE" ]; then
47
- cat > "$NOTEPAD_FILE" << 'NOTEPAD_INIT'
48
- # Notepad
49
- <!-- Auto-managed by OMC. Manual edits preserved in MANUAL section. -->
50
-
51
- ## Priority Context
52
- <!-- ALWAYS loaded. Keep under 500 chars. Critical discoveries only. -->
53
-
54
- ## Working Memory
55
- <!-- Session notes. Auto-pruned after 7 days. -->
56
-
57
- ## MANUAL
58
- <!-- User content. Never auto-pruned. -->
59
- NOTEPAD_INIT
60
- fi
61
-
62
- # Process priority remember tags
63
- PRIORITY_CONTENT=$(echo "$TOOL_OUTPUT" | grep -oP '<remember\s+priority>\K[\s\S]*?(?=</remember>)' | head -1)
64
- if [ -n "$PRIORITY_CONTENT" ]; then
65
- # Read current notepad
66
- NOTEPAD_CONTENT=$(cat "$NOTEPAD_FILE")
67
- # Replace Priority Context section
68
- NEW_NOTEPAD=$(echo "$NOTEPAD_CONTENT" | sed '/## Priority Context/,/## Working Memory/{
69
- /## Priority Context/!{/## Working Memory/!d}
70
- }' | sed "/## Priority Context/a\\<!-- ALWAYS loaded. Keep under 500 chars. Critical discoveries only. -->\\n$PRIORITY_CONTENT")
71
- echo "$NEW_NOTEPAD" > "$NOTEPAD_FILE"
72
- fi
73
-
74
- # Process regular remember tags
75
- while IFS= read -r CONTENT; do
76
- if [ -n "$CONTENT" ]; then
77
- TIMESTAMP=$(date '+%Y-%m-%d %H:%M')
78
- # Append to Working Memory section (before MANUAL)
79
- sed -i "/## MANUAL/i\\### $TIMESTAMP\\n$CONTENT\\n" "$NOTEPAD_FILE" 2>/dev/null || {
80
- # macOS sed fallback
81
- sed -i '' "/## MANUAL/i\\
82
- ### $TIMESTAMP\\
83
- $CONTENT\\
84
- " "$NOTEPAD_FILE"
85
- }
86
- fi
87
- done < <(echo "$TOOL_OUTPUT" | grep -oP '<remember>\K[\s\S]*?(?=</remember>)')
88
-
89
- echo '{"continue": true}'
90
- exit 0