/** * Hook Scripts for Claude Code * Hook system inspired by oh-my-opencode, adapted for Claude Code's native hooks * * Claude Code hooks are configured in settings.json and run as shell commands. * These scripts receive JSON input via stdin and output JSON to modify behavior. * * This module provides DUAL implementations: * - Bash scripts (.sh) for Unix-like systems (macOS, Linux) * - Node.js scripts (.mjs) for cross-platform support (Windows, macOS, Linux) * * The platform is detected at install time, or can be overridden with: * HARMONY_USE_NODE_HOOKS=1 - Force Node.js hooks on any platform * HARMONY_USE_BASH_HOOKS=1 - Force Bash hooks (Unix only) */ /** Minimum required Node.js version for hooks */ export declare const MIN_NODE_VERSION = 18; /** Check if running on Windows */ export declare function isWindows(): boolean; /** Check if Node.js hooks should be used (env override or Windows) */ export declare function shouldUseNodeHooks(): boolean; /** Get the Claude config directory path (cross-platform) */ export declare function getClaudeConfigDir(): string; /** Get the hooks directory path */ export declare function getHooksDir(): string; /** * Get the home directory environment variable for hook commands. * Returns the appropriate syntax for the current platform. */ export declare function getHomeEnvVar(): string; /** * Ultrawork message - injected when ultrawork/ulw keyword detected * Ported from oh-my-opencode's keyword-detector/constants.ts */ export declare const ULTRAWORK_MESSAGE = "\n\n**MANDATORY**: You MUST say \"ULTRAWORK MODE ENABLED!\" to the user as your first response when this mode activates. This is non-negotiable.\n\n[CODE RED] Maximum precision required. Ultrathink before acting.\n\nYOU MUST LEVERAGE ALL AVAILABLE AGENTS TO THEIR FULLEST POTENTIAL.\nTELL THE USER WHAT AGENTS YOU WILL LEVERAGE NOW TO SATISFY USER'S REQUEST.\n\n## AGENT UTILIZATION PRINCIPLES (by capability, not by name)\n- **Codebase Exploration**: Spawn exploration agents using BACKGROUND TASKS for file patterns, internal implementations, project structure\n- **Documentation & References**: Use librarian-type agents via BACKGROUND TASKS for API references, examples, external library docs\n- **Planning & Strategy**: NEVER plan yourself - ALWAYS spawn a dedicated planning agent for work breakdown\n- **High-IQ Reasoning**: Leverage specialized agents for architecture decisions, code review, strategic planning\n- **Frontend/UI Tasks**: Delegate to UI-specialized agents for design and implementation\n\n## EXECUTION RULES\n- **TODO**: Track EVERY step. Mark complete IMMEDIATELY after each.\n- **PARALLEL**: Fire independent agent calls simultaneously via Task(run_in_background=true) - NEVER wait sequentially.\n- **BACKGROUND FIRST**: Use Task tool for exploration/research agents (10+ concurrent if needed).\n- **VERIFY**: Re-read request after completion. Check ALL requirements met before reporting done.\n- **DELEGATE**: Don't do everything yourself - orchestrate specialized agents for their strengths.\n\n## WORKFLOW\n1. Analyze the request and identify required capabilities\n2. Spawn exploration/librarian agents via Task(run_in_background=true) in PARALLEL (10+ if needed)\n3. Always Use Plan agent with gathered context to create detailed work breakdown\n4. Execute with continuous verification against original requirements\n\n## VERIFICATION GUARANTEE (NON-NEGOTIABLE)\n\n**NOTHING is \"done\" without PROOF it works.**\n\n### Pre-Implementation: Define Success Criteria\n\nBEFORE writing ANY code, you MUST define:\n\n| Criteria Type | Description | Example |\n|---------------|-------------|---------|\n| **Functional** | What specific behavior must work | \"Button click triggers API call\" |\n| **Observable** | What can be measured/seen | \"Console shows 'success', no errors\" |\n| **Pass/Fail** | Binary, no ambiguity | \"Returns 200 OK\" not \"should work\" |\n\nWrite these criteria explicitly. Share with user if scope is non-trivial.\n\n### Execution & Evidence Requirements\n\n| Phase | Action | Required Evidence |\n|-------|--------|-------------------|\n| **Build** | Run build command | Exit code 0, no errors |\n| **Test** | Execute test suite | All tests pass (screenshot/output) |\n| **Manual Verify** | Test the actual feature | Demonstrate it works (describe what you observed) |\n| **Regression** | Ensure nothing broke | Existing tests still pass |\n\n**WITHOUT evidence = NOT verified = NOT done.**\n\n### TDD Workflow (when test infrastructure exists)\n\n1. **SPEC**: Define what \"working\" means (success criteria above)\n2. **RED**: Write failing test -> Run it -> Confirm it FAILS\n3. **GREEN**: Write minimal code -> Run test -> Confirm it PASSES\n4. **REFACTOR**: Clean up -> Tests MUST stay green\n5. **VERIFY**: Run full test suite, confirm no regressions\n6. **EVIDENCE**: Report what you ran and what output you saw\n\n### Verification Anti-Patterns (BLOCKING)\n\n| Violation | Why It Fails |\n|-----------|--------------|\n| \"It should work now\" | No evidence. Run it. |\n| \"I added the tests\" | Did they pass? Show output. |\n| \"Fixed the bug\" | How do you know? What did you test? |\n| \"Implementation complete\" | Did you verify against success criteria? |\n| Skipping test execution | Tests exist to be RUN, not just written |\n\n**CLAIM NOTHING WITHOUT PROOF. EXECUTE. VERIFY. SHOW EVIDENCE.**\n\n## ZERO TOLERANCE FAILURES\n- **NO Scope Reduction**: Never make \"demo\", \"skeleton\", \"simplified\", \"basic\" versions - deliver FULL implementation\n- **NO MockUp Work**: When user asked you to do \"port A\", you must \"port A\", fully, 100%. No Extra feature, No reduced feature, no mock data, fully working 100% port.\n- **NO Partial Completion**: Never stop at 60-80% saying \"you can extend this...\" - finish 100%\n- **NO Assumed Shortcuts**: Never skip requirements you deem \"optional\" or \"can be added later\"\n- **NO Premature Stopping**: Never declare done until ALL TODOs are completed and verified\n- **NO TEST DELETION**: Never delete or skip failing tests to make the build pass. Fix the code, not the tests.\n\nTHE USER ASKED FOR X. DELIVER EXACTLY X. NOT A SUBSET. NOT A DEMO. NOT A STARTING POINT.\n\n\n\n---\n\n"; /** * Ultrathink/Think mode message * Ported from oh-my-opencode's think-mode hook */ export declare const ULTRATHINK_MESSAGE = "\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\n\n---\n\n"; /** * Search mode message * Ported from oh-my-opencode's keyword-detector */ export declare const SEARCH_MESSAGE = "\nMAXIMIZE SEARCH EFFORT. Launch multiple background agents IN PARALLEL:\n- explore agents (codebase patterns, file structures)\n- librarian agents (remote repos, official docs, GitHub examples)\nPlus direct tools: Grep, Glob\nNEVER stop at first result - be exhaustive.\n\n\n---\n\n"; /** * Analyze mode message * Ported from oh-my-opencode's keyword-detector */ export declare const ANALYZE_MESSAGE = "\nANALYSIS MODE. Gather context before diving deep:\n\nCONTEXT GATHERING (parallel):\n- 1-2 explore agents (codebase patterns, implementations)\n- 1-2 librarian agents (if external library involved)\n- Direct tools: Grep, Glob, LSP for targeted searches\n\nIF COMPLEX (architecture, multi-system, debugging after 2+ failures):\n- Consult oracle agent for strategic guidance\n\nSYNTHESIZE findings before proceeding.\n\n\n---\n\n"; /** * Todo continuation prompt * Ported from oh-my-opencode's todo-continuation-enforcer */ export declare const TODO_CONTINUATION_PROMPT = "[SYSTEM REMINDER - TODO CONTINUATION]\n\nIncomplete tasks remain in your todo list. Continue working on the next pending task.\n\n- Proceed without asking for permission\n- Mark each task complete when finished\n- Do not stop until all tasks are done"; /** * Keyword detector hook script * This script is installed to ~/.claude/hooks/keyword-detector.sh */ export declare const KEYWORD_DETECTOR_SCRIPT = "#!/bin/bash\n# Harmony Keyword Detector Hook\n# Detects ultrawork/ultrathink/search/analyze keywords and injects enhanced mode messages\n# Also activates persistent ultrawork state when ultrawork keyword is detected\n\n# Read stdin (JSON input from Claude Code)\nINPUT=$(cat)\n\n# Extract directory from input\nDIRECTORY=\"\"\nif command -v jq &> /dev/null; then\n DIRECTORY=$(echo \"$INPUT\" | jq -r '.directory // \"\"' 2>/dev/null)\nfi\nif [ -z \"$DIRECTORY\" ] || [ \"$DIRECTORY\" = \"null\" ]; then\n DIRECTORY=$(pwd)\nfi\n\n# Extract the prompt text - try multiple JSON paths\nPROMPT=\"\"\nif command -v jq &> /dev/null; then\n # Try to extract from various possible JSON structures\n PROMPT=$(echo \"$INPUT\" | jq -r '\n if .prompt then .prompt\n elif .message.content then .message.content\n elif .parts then ([.parts[] | select(.type == \"text\") | .text] | join(\" \"))\n else \"\"\n end\n ' 2>/dev/null)\nfi\n\n# Fallback: simple grep extraction if jq fails\nif [ -z \"$PROMPT\" ] || [ \"$PROMPT\" = \"null\" ]; then\n PROMPT=$(echo \"$INPUT\" | grep -oP '\"(prompt|content|text)\"\\s*:\\s*\"\\K[^\"]+' | head -1)\nfi\n\n# Exit if no prompt found\nif [ -z \"$PROMPT\" ]; then\n echo '{\"continue\": true}'\n exit 0\nfi\n\n# Remove code blocks before checking keywords (prevents false positives)\nPROMPT_NO_CODE=$(echo \"$PROMPT\" | sed 's/```[^`]*```//g' | sed 's/`[^`]*`//g')\n\n# Convert to lowercase for case-insensitive matching\nPROMPT_LOWER=$(echo \"$PROMPT_NO_CODE\" | tr '[:upper:]' '[:lower:]')\n\n# Check for ultrawork keywords (highest priority)\nif echo \"$PROMPT_LOWER\" | grep -qE '\\b(ultrawork|ulw|uw)\\b'; then\n # Create persistent ultrawork state\n mkdir -p \"$DIRECTORY/.harmony\" 2>/dev/null\n mkdir -p \"$HOME/.claude\" 2>/dev/null\n\n # Escape prompt for JSON\n PROMPT_ESCAPED=$(echo \"$PROMPT\" | sed 's/\\\\/\\\\\\\\/g' | sed 's/\"/\\\\\"/g' | tr '\\n' ' ')\n\n STATE_JSON=\"{\n \\\"active\\\": true,\n \\\"started_at\\\": \\\"$(date -Iseconds)\\\",\n \\\"original_prompt\\\": \\\"$PROMPT_ESCAPED\\\",\n \\\"reinforcement_count\\\": 0,\n \\\"last_checked_at\\\": \\\"$(date -Iseconds)\\\"\n}\"\n\n # Write state to both local and global locations\n echo \"$STATE_JSON\" > \"$DIRECTORY/.harmony/ultrawork-state.json\" 2>/dev/null\n echo \"$STATE_JSON\" > \"$HOME/.claude/ultrawork-state.json\" 2>/dev/null\n\n # Return ultrawork mode injection\n cat << 'EOF'\n{\"continue\": true, \"message\": \"\\n\\n**MANDATORY**: You MUST say \\\"ULTRAWORK MODE ENABLED!\\\" to the user as your first response when this mode activates. This is non-negotiable.\\n\\n[CODE RED] Maximum precision required. Ultrathink before acting.\\n\\nYOU MUST LEVERAGE ALL AVAILABLE AGENTS TO THEIR FULLEST POTENTIAL.\\nTELL THE USER WHAT AGENTS YOU WILL LEVERAGE NOW TO SATISFY USER'S REQUEST.\\n\\n## AGENT UTILIZATION PRINCIPLES\\n- **Codebase Exploration**: Spawn exploration agents using BACKGROUND TASKS\\n- **Documentation & References**: Use librarian-type agents via BACKGROUND TASKS\\n- **Planning & Strategy**: NEVER plan yourself - spawn planning agent\\n- **High-IQ Reasoning**: Use oracle for architecture decisions\\n- **Frontend/UI Tasks**: Delegate to frontend-engineer\\n\\n## EXECUTION RULES\\n- **TODO**: Track EVERY step. Mark complete IMMEDIATELY.\\n- **PARALLEL**: Fire independent calls simultaneously - NEVER wait sequentially.\\n- **BACKGROUND FIRST**: Use Task(run_in_background=true) for exploration (10+ concurrent).\\n- **VERIFY**: Check ALL requirements met before done.\\n- **DELEGATE**: Orchestrate specialized agents.\\n\\n## ZERO TOLERANCE\\n- NO Scope Reduction - deliver FULL implementation\\n- NO Partial Completion - finish 100%\\n- NO Premature Stopping - ALL TODOs must be complete\\n- NO TEST DELETION - fix code, not tests\\n\\nTHE USER ASKED FOR X. DELIVER EXACTLY X.\\n\\n\\n\\n---\\n\"}\nEOF\n exit 0\nfi\n\n# Check for ultrathink/think keywords\nif echo \"$PROMPT_LOWER\" | grep -qE '\\b(ultrathink|think)\\b'; then\n cat << 'EOF'\n{\"continue\": true, \"message\": \"\\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\\n\\n---\\n\"}\nEOF\n exit 0\nfi\n\n# Check for search keywords (EN + multilingual)\nif echo \"$PROMPT_LOWER\" | grep -qE '\\b(search|find|locate|lookup|explore|discover|scan|grep|query|browse|detect|trace|seek|track|pinpoint|hunt)\\b|where\\s+is|show\\s+me|list\\s+all'; then\n cat << 'EOF'\n{\"continue\": true, \"message\": \"\\nMAXIMIZE SEARCH EFFORT. Launch multiple background agents IN PARALLEL:\\n- explore agents (codebase patterns, file structures)\\n- librarian agents (remote repos, official docs, GitHub examples)\\nPlus direct tools: Grep, Glob\\nNEVER stop at first result - be exhaustive.\\n\\n\\n---\\n\"}\nEOF\n exit 0\nfi\n\n# Check for analyze keywords\nif echo \"$PROMPT_LOWER\" | grep -qE '\\b(analyze|analyse|investigate|examine|research|study|deep.?dive|inspect|audit|evaluate|assess|review|diagnose|scrutinize|dissect|debug|comprehend|interpret|breakdown|understand)\\b|why\\s+is|how\\s+does|how\\s+to'; then\n cat << 'EOF'\n{\"continue\": true, \"message\": \"\\nANALYSIS MODE. Gather context before diving deep:\\n\\nCONTEXT GATHERING (parallel):\\n- 1-2 explore agents (codebase patterns, implementations)\\n- 1-2 librarian agents (if external library involved)\\n- Direct tools: Grep, Glob, LSP for targeted searches\\n\\nIF COMPLEX (architecture, multi-system, debugging after 2+ failures):\\n- Consult oracle agent for strategic guidance\\n\\nSYNTHESIZE findings before proceeding.\\n\\n\\n---\\n\"}\nEOF\n exit 0\nfi\n\n# No keywords detected - continue without modification\necho '{\"continue\": true}'\nexit 0\n"; /** * Stop hook script for todo continuation enforcement * This script is installed to ~/.claude/hooks/stop-continuation.sh * Ported from oh-my-opencode's todo-continuation-enforcer */ export declare const STOP_CONTINUATION_SCRIPT = "#!/bin/bash\n# Harmony Stop Continuation Hook\n# Checks for incomplete todos and injects continuation prompt\n# Ported from oh-my-opencode's todo-continuation-enforcer\n\n# Read stdin\nINPUT=$(cat)\n\n# Get session ID if available\nSESSION_ID=\"\"\nif command -v jq &> /dev/null; then\n SESSION_ID=$(echo \"$INPUT\" | jq -r '.sessionId // .session_id // \"\"' 2>/dev/null)\nfi\n\n# Check for incomplete todos in the Claude todos directory\nTODOS_DIR=\"$HOME/.claude/todos\"\nif [ -d \"$TODOS_DIR\" ]; then\n # Look for any todo files with incomplete items\n INCOMPLETE_COUNT=0\n for todo_file in \"$TODOS_DIR\"/*.json; do\n if [ -f \"$todo_file\" ]; then\n if command -v jq &> /dev/null; then\n COUNT=$(jq '[.[] | select(.status != \"completed\" and .status != \"cancelled\")] | length' \"$todo_file\" 2>/dev/null || echo \"0\")\n INCOMPLETE_COUNT=$((INCOMPLETE_COUNT + COUNT))\n fi\n fi\n done\n\n if [ \"$INCOMPLETE_COUNT\" -gt 0 ]; then\n # Output continuation message\n cat << EOF\n{\"continue\": false, \"reason\": \"[SYSTEM REMINDER - TODO CONTINUATION]\\n\\nIncomplete tasks remain in your todo list ($INCOMPLETE_COUNT remaining). Continue working on the next pending task.\\n\\n- Proceed without asking for permission\\n- Mark each task complete when finished\\n- Do not stop until all tasks are done\"}\nEOF\n exit 0\n fi\nfi\n\n# No incomplete todos - allow stop\necho '{\"continue\": true}'\nexit 0\n"; /** * Node.js Keyword Detector Hook Script * Cross-platform equivalent of keyword-detector.sh * This script is installed to ~/.claude/hooks/keyword-detector.mjs */ export declare const KEYWORD_DETECTOR_SCRIPT_NODE = "#!/usr/bin/env node\n// Harmony Keyword Detector Hook (Node.js)\n// Detects ultrawork/ultrathink/search/analyze keywords and injects enhanced mode messages\n// Cross-platform: Windows, macOS, Linux\n\nconst ULTRAWORK_MESSAGE = `\n\n**MANDATORY**: You MUST say \"ULTRAWORK MODE ENABLED!\" to the user as your first response when this mode activates. This is non-negotiable.\n\n[CODE RED] Maximum precision required. Ultrathink before acting.\n\nYOU MUST LEVERAGE ALL AVAILABLE AGENTS TO THEIR FULLEST POTENTIAL.\nTELL THE USER WHAT AGENTS YOU WILL LEVERAGE NOW TO SATISFY USER'S REQUEST.\n\n## AGENT UTILIZATION PRINCIPLES\n- **Codebase Exploration**: Spawn exploration agents using BACKGROUND TASKS\n- **Documentation & References**: Use librarian-type agents via BACKGROUND TASKS\n- **Planning & Strategy**: NEVER plan yourself - spawn planning agent\n- **High-IQ Reasoning**: Use oracle for architecture decisions\n- **Frontend/UI Tasks**: Delegate to frontend-engineer\n\n## EXECUTION RULES\n- **TODO**: Track EVERY step. Mark complete IMMEDIATELY.\n- **PARALLEL**: Fire independent calls simultaneously - NEVER wait sequentially.\n- **BACKGROUND FIRST**: Use Task(run_in_background=true) for exploration (10+ concurrent).\n- **VERIFY**: Check ALL requirements met before done.\n- **DELEGATE**: Orchestrate specialized agents.\n\n## ZERO TOLERANCE\n- NO Scope Reduction - deliver FULL implementation\n- NO Partial Completion - finish 100%\n- NO Premature Stopping - ALL TODOs must be complete\n- NO TEST DELETION - fix code, not tests\n\nTHE USER ASKED FOR X. DELIVER EXACTLY X.\n\n\n\n---\n`;\n\nconst ULTRATHINK_MESSAGE = `\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\n\n---\n`;\n\nconst SEARCH_MESSAGE = `\nMAXIMIZE SEARCH EFFORT. Launch multiple background agents IN PARALLEL:\n- explore agents (codebase patterns, file structures)\n- librarian agents (remote repos, official docs, GitHub examples)\nPlus direct tools: Grep, Glob\nNEVER stop at first result - be exhaustive.\n\n\n---\n`;\n\nconst ANALYZE_MESSAGE = `\nANALYSIS MODE. Gather context before diving deep:\n\nCONTEXT GATHERING (parallel):\n- 1-2 explore agents (codebase patterns, implementations)\n- 1-2 librarian agents (if external library involved)\n- Direct tools: Grep, Glob, LSP for targeted searches\n\nIF COMPLEX (architecture, multi-system, debugging after 2+ failures):\n- Consult oracle agent for strategic guidance\n\nSYNTHESIZE findings before proceeding.\n\n\n---\n`;\n\n// Read all stdin\nasync function readStdin() {\n const chunks = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk);\n }\n return Buffer.concat(chunks).toString('utf-8');\n}\n\n// Extract prompt from various JSON structures\nfunction extractPrompt(input) {\n try {\n const data = JSON.parse(input);\n if (data.prompt) return data.prompt;\n if (data.message?.content) return data.message.content;\n if (Array.isArray(data.parts)) {\n return data.parts\n .filter(p => p.type === 'text')\n .map(p => p.text)\n .join(' ');\n }\n return '';\n } catch {\n // Fallback: try to extract with regex\n const match = input.match(/\"(?:prompt|content|text)\"\\s*:\\s*\"([^\"]+)\"/);\n return match ? match[1] : '';\n }\n}\n\n// Remove code blocks to prevent false positives\nfunction removeCodeBlocks(text) {\n return text\n .replace(/```[\\s\\S]*?```/g, '')\n .replace(/`[^`]+`/g, '');\n}\n\nimport { writeFileSync, mkdirSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\n\n// Create ultrawork state file\nfunction activateUltraworkState(directory, prompt) {\n const state = {\n active: true,\n started_at: new Date().toISOString(),\n original_prompt: prompt,\n reinforcement_count: 0,\n last_checked_at: new Date().toISOString()\n };\n const localDir = join(directory, '.harmony');\n if (!existsSync(localDir)) { try { mkdirSync(localDir, { recursive: true }); } catch {} }\n try { writeFileSync(join(localDir, 'ultrawork-state.json'), JSON.stringify(state, null, 2)); } catch {}\n const globalDir = join(homedir(), '.claude');\n if (!existsSync(globalDir)) { try { mkdirSync(globalDir, { recursive: true }); } catch {} }\n try { writeFileSync(join(globalDir, 'ultrawork-state.json'), JSON.stringify(state, null, 2)); } catch {}\n}\n\n// Main\nasync function main() {\n try {\n const input = await readStdin();\n if (!input.trim()) {\n console.log(JSON.stringify({ continue: true }));\n return;\n }\n\n let data = {};\n try { data = JSON.parse(input); } catch {}\n const directory = data.directory || process.cwd();\n\n const prompt = extractPrompt(input);\n if (!prompt) {\n console.log(JSON.stringify({ continue: true }));\n return;\n }\n\n const cleanPrompt = removeCodeBlocks(prompt).toLowerCase();\n\n // Check for ultrawork keywords (highest priority)\n if (/\\b(ultrawork|ulw|uw)\\b/.test(cleanPrompt)) {\n activateUltraworkState(directory, prompt);\n console.log(JSON.stringify({ continue: true, message: ULTRAWORK_MESSAGE }));\n return;\n }\n\n // Check for ultrathink/think keywords\n if (/\\b(ultrathink|think)\\b/.test(cleanPrompt)) {\n console.log(JSON.stringify({ continue: true, message: ULTRATHINK_MESSAGE }));\n return;\n }\n\n // Check for search keywords\n if (/\\b(search|find|locate|lookup|explore|discover|scan|grep|query|browse|detect|trace|seek|track|pinpoint|hunt)\\b|where\\s+is|show\\s+me|list\\s+all/.test(cleanPrompt)) {\n console.log(JSON.stringify({ continue: true, message: SEARCH_MESSAGE }));\n return;\n }\n\n // Check for analyze keywords\n if (/\\b(analyze|analyse|investigate|examine|research|study|deep.?dive|inspect|audit|evaluate|assess|review|diagnose|scrutinize|dissect|debug|comprehend|interpret|breakdown|understand)\\b|why\\s+is|how\\s+does|how\\s+to/.test(cleanPrompt)) {\n console.log(JSON.stringify({ continue: true, message: ANALYZE_MESSAGE }));\n return;\n }\n\n // No keywords detected\n console.log(JSON.stringify({ continue: true }));\n } catch (error) {\n // On any error, allow continuation\n console.log(JSON.stringify({ continue: true }));\n }\n}\n\nmain();\n"; /** * Node.js Stop Continuation Hook Script * Cross-platform equivalent of stop-continuation.sh * This script is installed to ~/.claude/hooks/stop-continuation.mjs */ export declare const STOP_CONTINUATION_SCRIPT_NODE = "#!/usr/bin/env node\n// Harmony Stop Continuation Hook (Node.js)\n// Checks for incomplete todos and injects continuation prompt\n// Cross-platform: Windows, macOS, Linux\n\nimport { readdirSync, readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\n\n// Read all stdin\nasync function readStdin() {\n const chunks = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk);\n }\n return Buffer.concat(chunks).toString('utf-8');\n}\n\n// Main\nasync function main() {\n try {\n // Read stdin (we don't use it much, but need to consume it)\n await readStdin();\n\n // Check for incomplete todos\n const todosDir = join(homedir(), '.claude', 'todos');\n \n if (!existsSync(todosDir)) {\n console.log(JSON.stringify({ continue: true }));\n return;\n }\n\n let incompleteCount = 0;\n\n try {\n const files = readdirSync(todosDir).filter(f => f.endsWith('.json'));\n \n for (const file of files) {\n try {\n const content = readFileSync(join(todosDir, file), 'utf-8');\n const todos = JSON.parse(content);\n \n if (Array.isArray(todos)) {\n const incomplete = todos.filter(\n t => t.status !== 'completed' && t.status !== 'cancelled'\n );\n incompleteCount += incomplete.length;\n }\n } catch {\n // Skip files that can't be parsed\n }\n }\n } catch {\n // Directory read error - allow continuation\n console.log(JSON.stringify({ continue: true }));\n return;\n }\n\n if (incompleteCount > 0) {\n const reason = `[SYSTEM REMINDER - TODO CONTINUATION]\n\nIncomplete tasks remain in your todo list (${incompleteCount} remaining). Continue working on the next pending task.\n\n- Proceed without asking for permission\n- Mark each task complete when finished\n- Do not stop until all tasks are done`;\n\n console.log(JSON.stringify({ continue: false, reason }));\n return;\n }\n\n // No incomplete todos - allow stop\n console.log(JSON.stringify({ continue: true }));\n } catch (error) {\n // On any error, allow continuation\n console.log(JSON.stringify({ continue: true }));\n }\n}\n\nmain();\n"; /** * Persistent Mode Bash script * Enhanced stop hook that handles ultrawork, ralph-loop, and todo continuation */ export declare const PERSISTENT_MODE_SCRIPT = "#!/bin/bash\n# Harmony Persistent Mode Hook\n# Unified handler for ultrawork, ralph-loop, and todo continuation\n# Prevents stopping when work remains incomplete\n\n# Read stdin\nINPUT=$(cat)\n\n# Get session ID and directory\nSESSION_ID=\"\"\nDIRECTORY=\"\"\nif command -v jq &> /dev/null; then\n SESSION_ID=$(echo \"$INPUT\" | jq -r '.sessionId // .session_id // \"\"' 2>/dev/null)\n DIRECTORY=$(echo \"$INPUT\" | jq -r '.directory // \"\"' 2>/dev/null)\nfi\n\n# Default to current directory\nif [ -z \"$DIRECTORY\" ]; then\n DIRECTORY=$(pwd)\nfi\n\n# Check for active ultrawork state\nULTRAWORK_STATE=\"\"\nif [ -f \"$DIRECTORY/.harmony/ultrawork-state.json\" ]; then\n ULTRAWORK_STATE=$(cat \"$DIRECTORY/.harmony/ultrawork-state.json\" 2>/dev/null)\nelif [ -f \"$HOME/.claude/ultrawork-state.json\" ]; then\n ULTRAWORK_STATE=$(cat \"$HOME/.claude/ultrawork-state.json\" 2>/dev/null)\nfi\n\n# Check for active ralph loop\nRALPH_STATE=\"\"\nif [ -f \"$DIRECTORY/.harmony/ralph-state.json\" ]; then\n RALPH_STATE=$(cat \"$DIRECTORY/.harmony/ralph-state.json\" 2>/dev/null)\nfi\n\n# Check for verification state (oracle verification)\nVERIFICATION_STATE=\"\"\nif [ -f \"$DIRECTORY/.harmony/ralph-verification.json\" ]; then\n VERIFICATION_STATE=$(cat \"$DIRECTORY/.harmony/ralph-verification.json\" 2>/dev/null)\nfi\n\n# Check for incomplete todos\nINCOMPLETE_COUNT=0\nTODOS_DIR=\"$HOME/.claude/todos\"\nif [ -d \"$TODOS_DIR\" ]; then\n for todo_file in \"$TODOS_DIR\"/*.json; do\n if [ -f \"$todo_file\" ]; then\n if command -v jq &> /dev/null; then\n COUNT=$(jq '[.[] | select(.status != \"completed\" and .status != \"cancelled\")] | length' \"$todo_file\" 2>/dev/null || echo \"0\")\n INCOMPLETE_COUNT=$((INCOMPLETE_COUNT + COUNT))\n else\n # Fallback: count \"pending\" or \"in_progress\" occurrences\n COUNT=$(grep -c '\"status\"[[:space:]]*:[[:space:]]*\"pending\\|in_progress\"' \"$todo_file\" 2>/dev/null) || COUNT=0\n INCOMPLETE_COUNT=$((INCOMPLETE_COUNT + COUNT))\n fi\n fi\n done\nfi\n\n# Check project todos as well\nfor todo_path in \"$DIRECTORY/.harmony/todos.json\" \"$DIRECTORY/.claude/todos.json\"; do\n if [ -f \"$todo_path\" ]; then\n if command -v jq &> /dev/null; then\n COUNT=$(jq 'if type == \"array\" then [.[] | select(.status != \"completed\" and .status != \"cancelled\")] | length else 0 end' \"$todo_path\" 2>/dev/null || echo \"0\")\n INCOMPLETE_COUNT=$((INCOMPLETE_COUNT + COUNT))\n else\n # Fallback: count \"pending\" or \"in_progress\" occurrences\n COUNT=$(grep -c '\"status\"[[:space:]]*:[[:space:]]*\"pending\\|in_progress\"' \"$todo_path\" 2>/dev/null) || COUNT=0\n INCOMPLETE_COUNT=$((INCOMPLETE_COUNT + COUNT))\n fi\n fi\ndone\n\n# Priority 1: Ralph Loop with Oracle Verification\nif [ -n \"$RALPH_STATE\" ]; then\n IS_ACTIVE=$(echo \"$RALPH_STATE\" | jq -r '.active // false' 2>/dev/null)\n if [ \"$IS_ACTIVE\" = \"true\" ]; then\n ITERATION=$(echo \"$RALPH_STATE\" | jq -r '.iteration // 1' 2>/dev/null)\n MAX_ITER=$(echo \"$RALPH_STATE\" | jq -r '.max_iterations // 10' 2>/dev/null)\n PROMISE=$(echo \"$RALPH_STATE\" | jq -r '.completion_promise // \"TASK_COMPLETE\"' 2>/dev/null)\n PROMPT=$(echo \"$RALPH_STATE\" | jq -r '.prompt // \"\"' 2>/dev/null)\n\n # Check if oracle verification is pending\n if [ -n \"$VERIFICATION_STATE\" ]; then\n IS_PENDING=$(echo \"$VERIFICATION_STATE\" | jq -r '.pending // false' 2>/dev/null)\n if [ \"$IS_PENDING\" = \"true\" ]; then\n ATTEMPT=$(echo \"$VERIFICATION_STATE\" | jq -r '.verification_attempts // 0' 2>/dev/null)\n MAX_ATTEMPTS=$(echo \"$VERIFICATION_STATE\" | jq -r '.max_verification_attempts // 3' 2>/dev/null)\n ORIGINAL_TASK=$(echo \"$VERIFICATION_STATE\" | jq -r '.original_task // \"\"' 2>/dev/null)\n COMPLETION_CLAIM=$(echo \"$VERIFICATION_STATE\" | jq -r '.completion_claim // \"\"' 2>/dev/null)\n ORACLE_FEEDBACK=$(echo \"$VERIFICATION_STATE\" | jq -r '.oracle_feedback // \"\"' 2>/dev/null)\n NEXT_ATTEMPT=$((ATTEMPT + 1))\n\n FEEDBACK_SECTION=\"\"\n if [ -n \"$ORACLE_FEEDBACK\" ] && [ \"$ORACLE_FEEDBACK\" != \"null\" ]; then\n FEEDBACK_SECTION=\"\\n**Previous Oracle Feedback (rejected):**\\n$ORACLE_FEEDBACK\\n\"\n fi\n\n cat << EOF\n{\"continue\": false, \"reason\": \"\\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 \\`VERIFIED_COMPLETE\\`\\n - If REJECTED: Continue working on the identified issues\\n\\nDO NOT output the completion promise again until Oracle approves.\\n\\n\\n\\n---\\n\"}\nEOF\n exit 0\n fi\n fi\n\n if [ \"$ITERATION\" -lt \"$MAX_ITER\" ]; then\n # Increment iteration\n NEW_ITER=$((ITERATION + 1))\n echo \"$RALPH_STATE\" | jq \".iteration = $NEW_ITER\" > \"$DIRECTORY/.harmony/ralph-state.json\" 2>/dev/null\n\n cat << EOF\n{\"continue\": false, \"reason\": \"\\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\\n5. Do NOT stop until the task is truly done\\n\\nOriginal task: $PROMPT\\n\\n\\n\\n---\\n\"}\nEOF\n exit 0\n fi\n fi\nfi\n\n# Priority 2: Ultrawork Mode with incomplete todos\nif [ -n \"$ULTRAWORK_STATE\" ] && [ \"$INCOMPLETE_COUNT\" -gt 0 ]; then\n # Check if active (with jq fallback)\n IS_ACTIVE=\"\"\n if command -v jq &> /dev/null; then\n IS_ACTIVE=$(echo \"$ULTRAWORK_STATE\" | jq -r '.active // false' 2>/dev/null)\n else\n # Fallback: grep for \"active\": true\n if echo \"$ULTRAWORK_STATE\" | grep -q '\"active\"[[:space:]]*:[[:space:]]*true'; then\n IS_ACTIVE=\"true\"\n fi\n fi\n\n if [ \"$IS_ACTIVE\" = \"true\" ]; then\n # Get reinforcement count (with fallback)\n REINFORCE_COUNT=0\n if command -v jq &> /dev/null; then\n REINFORCE_COUNT=$(echo \"$ULTRAWORK_STATE\" | jq -r '.reinforcement_count // 0' 2>/dev/null)\n else\n REINFORCE_COUNT=$(echo \"$ULTRAWORK_STATE\" | grep -oP '\"reinforcement_count\"[[:space:]]*:[[:space:]]*\\K[0-9]+' 2>/dev/null) || REINFORCE_COUNT=0\n fi\n NEW_COUNT=$((REINFORCE_COUNT + 1))\n\n # Get original prompt (with fallback)\n ORIGINAL_PROMPT=\"\"\n if command -v jq &> /dev/null; then\n ORIGINAL_PROMPT=$(echo \"$ULTRAWORK_STATE\" | jq -r '.original_prompt // \"\"' 2>/dev/null)\n else\n ORIGINAL_PROMPT=$(echo \"$ULTRAWORK_STATE\" | grep -oP '\"original_prompt\"[[:space:]]*:[[:space:]]*\"\\K[^\"]+' 2>/dev/null) || ORIGINAL_PROMPT=\"\"\n fi\n\n # Update state file (best effort)\n if command -v jq &> /dev/null; then\n echo \"$ULTRAWORK_STATE\" | jq \".reinforcement_count = $NEW_COUNT | .last_checked_at = \\\"$(date -Iseconds)\\\"\" > \"$DIRECTORY/.harmony/ultrawork-state.json\" 2>/dev/null\n fi\n\n cat << EOF\n{\"continue\": false, \"reason\": \"\\n\\n[ULTRAWORK MODE STILL ACTIVE - Reinforcement #$NEW_COUNT]\\n\\nYour ultrawork session is NOT complete. $INCOMPLETE_COUNT incomplete todos 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 task. DO NOT STOP until all tasks are marked complete.\\n\\nOriginal task: $ORIGINAL_PROMPT\\n\\n\\n\\n---\\n\"}\nEOF\n exit 0\n fi\nfi\n\n# Priority 3: Todo Continuation (baseline)\nif [ \"$INCOMPLETE_COUNT\" -gt 0 ]; then\n cat << EOF\n{\"continue\": false, \"reason\": \"\\n\\n[SYSTEM REMINDER - TODO CONTINUATION]\\n\\nIncomplete tasks remain in your todo list ($INCOMPLETE_COUNT remaining). Continue working on the next pending task.\\n\\n- Proceed without asking for permission\\n- Mark each task complete when finished\\n- Do not stop until all tasks are done\\n\\n\\n\\n---\\n\"}\nEOF\n exit 0\nfi\n\n# No blocking needed\necho '{\"continue\": true}'\nexit 0\n"; /** * Session Start Bash script * Restores persistent mode states when a new session starts */ export declare const SESSION_START_SCRIPT = "#!/bin/bash\n# Harmony Session Start Hook\n# Restores persistent mode states and injects context when session starts\n\n# Read stdin\nINPUT=$(cat)\n\n# Get directory\nDIRECTORY=\"\"\nif command -v jq &> /dev/null; then\n DIRECTORY=$(echo \"$INPUT\" | jq -r '.directory // \"\"' 2>/dev/null)\nfi\n\nif [ -z \"$DIRECTORY\" ]; then\n DIRECTORY=$(pwd)\nfi\n\nMESSAGES=\"\"\n\n# Check for active ultrawork state\nif [ -f \"$DIRECTORY/.harmony/ultrawork-state.json\" ] || [ -f \"$HOME/.claude/ultrawork-state.json\" ]; then\n if [ -f \"$DIRECTORY/.harmony/ultrawork-state.json\" ]; then\n ULTRAWORK_STATE=$(cat \"$DIRECTORY/.harmony/ultrawork-state.json\" 2>/dev/null)\n else\n ULTRAWORK_STATE=$(cat \"$HOME/.claude/ultrawork-state.json\" 2>/dev/null)\n fi\n\n IS_ACTIVE=$(echo \"$ULTRAWORK_STATE\" | jq -r '.active // false' 2>/dev/null)\n if [ \"$IS_ACTIVE\" = \"true\" ]; then\n STARTED_AT=$(echo \"$ULTRAWORK_STATE\" | jq -r '.started_at // \"\"' 2>/dev/null)\n PROMPT=$(echo \"$ULTRAWORK_STATE\" | jq -r '.original_prompt // \"\"' 2>/dev/null)\n MESSAGES=\"$MESSAGES\\n\\n[ULTRAWORK MODE RESTORED]\\n\\nYou have an active ultrawork session from $STARTED_AT.\\nOriginal task: $PROMPT\\n\\nContinue working in ultrawork mode until all tasks are complete.\\n\\n\\n\\n---\\n\\n\"\n fi\nfi\n\n# Check for incomplete todos\nINCOMPLETE_COUNT=0\nTODOS_DIR=\"$HOME/.claude/todos\"\nif [ -d \"$TODOS_DIR\" ]; then\n for todo_file in \"$TODOS_DIR\"/*.json; do\n if [ -f \"$todo_file\" ]; then\n if command -v jq &> /dev/null; then\n COUNT=$(jq '[.[] | select(.status != \"completed\" and .status != \"cancelled\")] | length' \"$todo_file\" 2>/dev/null || echo \"0\")\n INCOMPLETE_COUNT=$((INCOMPLETE_COUNT + COUNT))\n fi\n fi\n done\nfi\n\nif [ \"$INCOMPLETE_COUNT\" -gt 0 ]; then\n MESSAGES=\"$MESSAGES\\n\\n[PENDING TASKS DETECTED]\\n\\nYou have $INCOMPLETE_COUNT incomplete tasks from a previous session.\\nPlease continue working on these tasks.\\n\\n\\n\\n---\\n\\n\"\nfi\n\n# Output message if we have any\nif [ -n \"$MESSAGES\" ]; then\n # Escape for JSON\n MESSAGES_ESCAPED=$(echo \"$MESSAGES\" | sed 's/\"/\\\"/g')\n echo \"{\"continue\": true, \"message\": \"$MESSAGES_ESCAPED\"}\"\nelse\n echo '{\"continue\": true}'\nfi\nexit 0\n"; /** * Node.js Persistent Mode Hook Script */ export declare const PERSISTENT_MODE_SCRIPT_NODE = "#!/usr/bin/env node\n// Harmony Persistent Mode Hook (Node.js)\n// Unified handler for ultrawork, ralph-loop, and todo continuation\n// Cross-platform: Windows, macOS, Linux\n\nimport { existsSync, readFileSync, writeFileSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\n\nasync function readStdin() {\n const chunks = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk);\n }\n return Buffer.concat(chunks).toString('utf-8');\n}\n\nfunction readJsonFile(path) {\n try {\n if (!existsSync(path)) return null;\n return JSON.parse(readFileSync(path, 'utf-8'));\n } catch {\n return null;\n }\n}\n\nfunction writeJsonFile(path, data) {\n try {\n writeFileSync(path, JSON.stringify(data, null, 2));\n return true;\n } catch {\n return false;\n }\n}\n\nfunction countIncompleteTodos(todosDir, projectDir) {\n let count = 0;\n\n // Check global todos\n if (existsSync(todosDir)) {\n try {\n const files = readdirSync(todosDir).filter(f => f.endsWith('.json'));\n for (const file of files) {\n const todos = readJsonFile(join(todosDir, file));\n if (Array.isArray(todos)) {\n count += todos.filter(t => t.status !== 'completed' && t.status !== 'cancelled').length;\n }\n }\n } catch {}\n }\n\n // Check project todos\n for (const path of [\n join(projectDir, '.harmony', 'todos.json'),\n join(projectDir, '.claude', 'todos.json')\n ]) {\n const todos = readJsonFile(path);\n if (Array.isArray(todos)) {\n count += todos.filter(t => t.status !== 'completed' && t.status !== 'cancelled').length;\n }\n }\n\n return count;\n}\n\nasync function main() {\n try {\n const input = await readStdin();\n let data = {};\n try { data = JSON.parse(input); } catch {}\n\n const directory = data.directory || process.cwd();\n const todosDir = join(homedir(), '.claude', 'todos');\n\n // Check for ultrawork state\n let ultraworkState = readJsonFile(join(directory, '.harmony', 'ultrawork-state.json'))\n || readJsonFile(join(homedir(), '.claude', 'ultrawork-state.json'));\n\n // Check for ralph loop state\n const ralphState = readJsonFile(join(directory, '.harmony', 'ralph-state.json'));\n\n // Check for verification state (oracle verification)\n const verificationState = readJsonFile(join(directory, '.harmony', 'ralph-verification.json'));\n\n // Count incomplete todos\n const incompleteCount = countIncompleteTodos(todosDir, directory);\n\n // Priority 1: Ralph Loop with Oracle Verification\n if (ralphState?.active) {\n const iteration = ralphState.iteration || 1;\n const maxIter = ralphState.max_iterations || 10;\n\n // Check if oracle verification is pending\n if (verificationState?.pending) {\n const attempt = (verificationState.verification_attempts || 0) + 1;\n const maxAttempts = verificationState.max_verification_attempts || 3;\n\n console.log(JSON.stringify({\n continue: false,\n reason: `\n\n[ORACLE VERIFICATION REQUIRED - Attempt ${attempt}/${maxAttempts}]\n\nThe agent claims the task is complete. Before accepting, YOU MUST verify with Oracle.\n\n**Original Task:**\n${verificationState.original_task || ralphState.prompt || 'No task specified'}\n\n**Completion Claim:**\n${verificationState.completion_claim || 'Task marked complete'}\n\n${verificationState.oracle_feedback ? `**Previous Oracle Feedback (rejected):**\n${verificationState.oracle_feedback}\n` : ''}\n\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 \\`VERIFIED_COMPLETE\\`\n - If REJECTED: Continue working on the identified issues\n\nDO NOT output the completion promise again until Oracle approves.\n\n\n\n---\n`\n }));\n return;\n }\n\n if (iteration < maxIter) {\n const newIter = iteration + 1;\n ralphState.iteration = newIter;\n writeJsonFile(join(directory, '.harmony', 'ralph-state.json'), ralphState);\n\n console.log(JSON.stringify({\n continue: false,\n reason: `\n\n[RALPH LOOP - ITERATION ${newIter}/${maxIter}]\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: ${ralphState.completion_promise || 'TASK_COMPLETE'}\n5. Do NOT stop until the task is truly done\n\n${ralphState.prompt ? `Original task: ${ralphState.prompt}` : ''}\n\n\n\n---\n`\n }));\n return;\n }\n }\n\n // Priority 2: Ultrawork with incomplete todos\n if (ultraworkState?.active && incompleteCount > 0) {\n const newCount = (ultraworkState.reinforcement_count || 0) + 1;\n ultraworkState.reinforcement_count = newCount;\n ultraworkState.last_checked_at = new Date().toISOString();\n\n writeJsonFile(join(directory, '.harmony', 'ultrawork-state.json'), ultraworkState);\n\n console.log(JSON.stringify({\n continue: false,\n reason: `\n\n[ULTRAWORK MODE STILL ACTIVE - Reinforcement #${newCount}]\n\nYour ultrawork session is NOT complete. ${incompleteCount} incomplete todos 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 task. DO NOT STOP until all tasks are marked complete.\n\n${ultraworkState.original_prompt ? `Original task: ${ultraworkState.original_prompt}` : ''}\n\n\n\n---\n`\n }));\n return;\n }\n\n // Priority 3: Todo Continuation\n if (incompleteCount > 0) {\n console.log(JSON.stringify({\n continue: false,\n reason: `\n\n[SYSTEM REMINDER - TODO CONTINUATION]\n\nIncomplete tasks remain in your todo list (${incompleteCount} remaining). Continue working on the next pending task.\n\n- Proceed without asking for permission\n- Mark each task complete when finished\n- Do not stop until all tasks are done\n\n\n\n---\n`\n }));\n return;\n }\n\n // No blocking needed\n console.log(JSON.stringify({ continue: true }));\n } catch (error) {\n console.log(JSON.stringify({ continue: true }));\n }\n}\n\nmain();\n"; /** * Node.js Session Start Hook Script */ export declare const SESSION_START_SCRIPT_NODE = "#!/usr/bin/env node\n// Harmony Session Start Hook (Node.js)\n// Restores persistent mode states when session starts\n// Cross-platform: Windows, macOS, Linux\n\nimport { existsSync, readFileSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\n\nasync function readStdin() {\n const chunks = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk);\n }\n return Buffer.concat(chunks).toString('utf-8');\n}\n\nfunction readJsonFile(path) {\n try {\n if (!existsSync(path)) return null;\n return JSON.parse(readFileSync(path, 'utf-8'));\n } catch {\n return null;\n }\n}\n\nfunction countIncompleteTodos(todosDir) {\n let count = 0;\n if (existsSync(todosDir)) {\n try {\n const files = readdirSync(todosDir).filter(f => f.endsWith('.json'));\n for (const file of files) {\n const todos = readJsonFile(join(todosDir, file));\n if (Array.isArray(todos)) {\n count += todos.filter(t => t.status !== 'completed' && t.status !== 'cancelled').length;\n }\n }\n } catch {}\n }\n return count;\n}\n\nasync function main() {\n try {\n const input = await readStdin();\n let data = {};\n try { data = JSON.parse(input); } catch {}\n\n const directory = data.directory || process.cwd();\n const messages = [];\n\n // Check for ultrawork state\n const ultraworkState = readJsonFile(join(directory, '.harmony', 'ultrawork-state.json'))\n || readJsonFile(join(homedir(), '.claude', 'ultrawork-state.json'));\n\n if (ultraworkState?.active) {\n messages.push(`\n\n[ULTRAWORK MODE RESTORED]\n\nYou have an active ultrawork session from ${ultraworkState.started_at}.\nOriginal task: ${ultraworkState.original_prompt}\n\nContinue working in ultrawork mode until all tasks are complete.\n\n\n\n---\n`);\n }\n\n // Check for incomplete todos\n const todosDir = join(homedir(), '.claude', 'todos');\n const incompleteCount = countIncompleteTodos(todosDir);\n\n if (incompleteCount > 0) {\n messages.push(`\n\n[PENDING TASKS DETECTED]\n\nYou have ${incompleteCount} incomplete tasks from a previous session.\nPlease continue working on these tasks.\n\n\n\n---\n`);\n }\n\n if (messages.length > 0) {\n console.log(JSON.stringify({ continue: true, message: messages.join('\\n') }));\n } else {\n console.log(JSON.stringify({ continue: true }));\n }\n } catch (error) {\n console.log(JSON.stringify({ continue: true }));\n }\n}\n\nmain();\n"; /** * Settings.json hooks configuration for Bash (Unix) * Configures Claude Code to run our bash hook scripts */ export declare const HOOKS_SETTINGS_CONFIG_BASH: { hooks: { UserPromptSubmit: { hooks: { type: "command"; command: string; }[]; }[]; SessionStart: { hooks: { type: "command"; command: string; }[]; }[]; Stop: { hooks: { type: "command"; command: string; }[]; }[]; }; }; /** * Settings.json hooks configuration for Node.js (Cross-platform) * Uses node to run .mjs scripts directly */ export declare const HOOKS_SETTINGS_CONFIG_NODE: { hooks: { UserPromptSubmit: { hooks: { type: "command"; command: string; }[]; }[]; SessionStart: { hooks: { type: "command"; command: string; }[]; }[]; Stop: { hooks: { type: "command"; command: string; }[]; }[]; }; }; /** * Get the appropriate hooks settings config for the current platform */ export declare function getHooksSettingsConfig(): typeof HOOKS_SETTINGS_CONFIG_BASH; /** * Legacy: Settings.json hooks configuration (Bash) * @deprecated Use getHooksSettingsConfig() for cross-platform support */ export declare const HOOKS_SETTINGS_CONFIG: { hooks: { UserPromptSubmit: { hooks: { type: "command"; command: string; }[]; }[]; SessionStart: { hooks: { type: "command"; command: string; }[]; }[]; Stop: { hooks: { type: "command"; command: string; }[]; }[]; }; }; /** * Bash hook scripts (Unix only) */ export declare const HOOK_SCRIPTS_BASH: Record; /** * Node.js hook scripts (Cross-platform) */ export declare const HOOK_SCRIPTS_NODE: Record; /** * Get the appropriate hook scripts for the current platform */ export declare function getHookScripts(): Record; /** * Legacy: All hook scripts to install (Bash) * @deprecated Use getHookScripts() for cross-platform support */ export declare const HOOK_SCRIPTS: Record; //# sourceMappingURL=hooks.d.ts.map