Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save grahama1970/1dcbebe40a08d606ffce06c2e4c3dca9 to your computer and use it in GitHub Desktop.

Select an option

Save grahama1970/1dcbebe40a08d606ffce06c2e4c3dca9 to your computer and use it in GitHub Desktop.

Background Verification with Polling POC

Objective

Prove that we can use a background Claude Code process to verify results and block task progression until verification completes.

Important

This is a self-contained POC. All required command files are in the commands/ subdirectory.

Tasks

Task 1: Setup Environment

  • Read /home/graham/.claude/CLAUDE.md and /home/graham/workspace/experiments/llm_call/CLAUDE.md
  • Verify virtual environment is active (which python contains .venv)
  • Archive existing logs and initialize fresh logging
  • Helper: commands/logging-setup.md for loguru configuration

Task 2: Create and Run Function

  • Write simple_add.py that adds 2 + 3
  • The script should NOT log its own source code (prevents recursive logging)
  • Execute the script and capture output
  • Verify add_results.txt contains "The sum of 2 and 3 is 5"

Task 3: Launch Background Verification

  • Create verification_status.json with status "in-progress"
  • Use template: commands/claude-verify.md with parameters:
    • code_file=simple_add.py, result_file=add_results.txt, status_file=verification_status.json, log_file=task_execution.log, expected_result=5
  • Launch in background subprocess (don't wait)

Task 4: Poll for Completion

  • Use template: commands/claude-poll.md with parameters:
    • status_file=verification_status.json, expected_status=pass, timeout=600, log_file=task_execution.log
  • MUST block until verification completes

Task 5: Continue After Verification

  • Write "Paris" to final_answer.txt
  • This task proves sequential execution - only runs after polling completes

Task 6: Validate with Gemini

  • Create execution_summary.txt with all results
  • Use template: commands/ask-gemini-flash.md to verify results are real

Success Criteria

  • All tasks execute in sequence (no parallel execution)
  • Task 5 only runs after Task 4 confirms verification passed
  • Gemini confirms all results are real

Ask Gemini Flash Command

Ask Gemini Flash this question and get a quick, balanced response: $ARGUMENTS

Expected Output:

  • Provide clear, concise answers (limit ~500 tokens)
  • Use creative but accurate tone
  • For complex code tasks, suggest using ask-gemini-pro instead
  • If unable to answer, explain why clearly

Code Example:

from dotenv import load_dotenv
load_dotenv('/home/graham/workspace/experiments/llm_call/.env')
import os
from litellm import completion

model = os.getenv('SLASHCMD_ASK_GEMINI_FLASH_MODEL')  # Gets configured Gemini Flash model
response = completion(
    model=model,
    messages=[{"role": "user", "content": "YOUR_QUERY"}],
    temperature=0.7,  # Balanced creativity
    max_tokens=500    # Reasonable response length
)
print(response.choices[0].message.content)

Model Information:

  • vertex_ai/gemini-1.5-flash: Fast, cost-efficient version of Gemini 1.5
  • Good for: Code generation, analysis, general questions, quick responses
  • Features: Multi-modal support, function calling, safety settings

Environment Requirements:

  • GOOGLE_APPLICATION_CREDENTIALS: Path to service account JSON file
  • VERTEX_PROJECT: Google Cloud project ID (optional, can be in credentials)
  • VERTEX_LOCATION: Region like 'us-central1' (optional)

Helpful Documentation:

Usage Examples:

  • /user:ask-gemini-flash Write a Python function to calculate fibonacci
  • /user:ask-gemini-flash Explain quantum computing in simple terms
  • /user:ask-gemini-flash Debug this code: [paste code]

Notes:

  • Ensure Google Cloud credentials are properly configured
  • Flash model is optimized for speed and cost-efficiency
  • For complex reasoning tasks, consider using gemini-1.5-pro instead

Claude Poll Command

Generate a Python polling script that waits for a background Claude Code process to write a JSON status file: $ARGUMENTS

Expected Output:

  • Generate a Python script that polls for a JSON status file based on $ARGUMENTS
  • Wait for specified file to exist, then parse and check status
  • Log all polling attempts and results to the specified log file
  • Exit with appropriate code when expected status is reached or timeout occurs
  • Use $ARGUMENTS to determine file name, expected status, timeout, log file, etc.

Code Example:

# Generate a Python polling script with clear logging
# Parameters extracted from $ARGUMENTS

import json
import time
import os
import sys
from datetime import datetime
from loguru import logger

# Extract parameters from command arguments
status_file = "$status_file"
expected_status = "$expected_status"
timeout = int("$timeout")
log_file = "$log_file"

# Configure logger with clear format
# Remove default handler to prevent stderr output
logger.remove()
# Add only file handler
logger.add(log_file, rotation="1 MB", enqueue=True, backtrace=True, diagnose=True,
           format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {message}")

logger.info("πŸ”„ POLLING STARTED: Waiting for verification completion")
logger.info("-" * 80)

start_time = time.time()
attempt = 0

while True:
    attempt += 1
    current_time = datetime.now().strftime("%H:%M:%S.%f")[:-3]
    logger.info(f"[POLL_ATTEMPT] #{attempt} at {current_time}")
    
    # Check if file exists
    if os.path.exists(status_file):
        try:
            with open(status_file, 'r') as f:
                data = json.load(f)
            
            # Log the file content
            logger.info(f"[FILE_READ] {status_file}:")
            logger.info("```json")
            logger.info(json.dumps(data, indent=2))
            logger.info("```")
            
            # Check status
            status = data.get('status', 'unknown')
            
            if status == expected_status:
                logger.info(f"[POLL_RESULT] Status: {status} (SUCCESS!)")
                logger.info("βœ… POLLING COMPLETED: Verification passed")
                logger.info("=" * 80)
                sys.exit(0)
            else:
                logger.info(f"[POLL_RESULT] Status: {status} (waiting...)")
        
        except json.JSONDecodeError as e:
            logger.error(f"[ERROR] Invalid JSON in {status_file}: {e}")
        except Exception as e:
            logger.error(f"[ERROR] Failed to read status file: {e}")
    else:
        logger.info(f"[POLL_RESULT] File not found (waiting...)")
    
    # Check timeout
    elapsed = time.time() - start_time
    if elapsed > timeout:
        logger.error(f"[ERROR] Timeout after {timeout} seconds")
        logger.info("❌ POLLING FAILED: Timeout reached")
        logger.info("=" * 80)
        sys.exit(1)
    
    # Wait before next poll
    time.sleep(1)

Usage for Claude Code Background Tasks:

This command generates polling scripts specifically for Claude Code instances running in the background that write JSON status files when complete.

Common Status Values:

  • "in-progress": Background task is still running
  • "pass": Verification completed successfully
  • "fail": Verification failed
  • "completed": General completion status
  • "success": Alternative success status

Environment Requirements:

  • python3: Python 3.x interpreter
  • loguru: Python logging library (install with uv add loguru or pip install loguru)

Usage Examples:

  • /user:claude-poll status_file=verification_status.json expected_status=pass timeout=600 log_file=task_execution.log
  • /user:claude-poll status_file=verification_status.json expected_status=pass timeout=300 log_file=task_execution.log
  • /user:claude-poll status_file=completion.json expected_status=completed timeout=600 log_file=task_execution.log
  • /user:claude-poll status_file=background_verification.json expected_status=success timeout=300 log_file=task_execution.log

Notes:

  • Designed specifically for Claude Code background task polling
  • Simple, reliable approach without complex features
  • Validates JSON before parsing
  • Provides clear, structured logging for all polling attempts
  • Logs are parseable by agents, humans, and verification models
  • Timeout prevents infinite waiting on stuck Claude processes
  • 1-second polling interval for simplicity (no exponential backoff in this POC)

/user:claude-verify

Run a background verification of a Python script and its output file, logging every step and writing a structured JSON status file. This command uses Claude Code as a language model to critique the code quality, verify outputs, and suggest improvements, all driven by a flexible prompt with no reliance on the ast module or hardcoded scripts.


Usage

/user:claude-verify code_file=simple_add.py result_file=add_results.txt status_file=verification_status.json log_file=task_execution.log expected_result=5

Prompt Template

Replace the variables with the arguments provided to the slash command.

Verify the correctness of a Python script and its output, and critique the code quality as a language model with suggested improvements.

**Instructions:**
- Use Loguru for logging. At the top of the generated script, include:
  ```python
  from loguru import logger
  # Remove default handler to prevent stderr output
  logger.remove()
  # Add only file handler
  logger.add('$log_file', rotation="1 MB", enqueue=True, backtrace=True, diagnose=True,
             format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {message}")
  • Log: "πŸ”¬ BACKGROUND CLAUDE VERIFICATION STARTED"
  • Log: "-" * 80 (sub-separator for clarity)
  • Read the Python file $code_file as raw text and critique its quality as a language model, focusing on:
    • Readability: Are variable names descriptive (e.g., avoid single-letter names like a or b)? Are comments present and clear?
    • Structure: Is the code logically organized? Is the function add_numbers clearly defined with appropriate inputs and outputs?
    • Error Handling: Are try-except blocks used for file operations or other risky actions?
    • Style: Does the code follow PEP 8 guidelines (e.g., indentation, line length under 79 characters)?
    • Correctness: Does the code appear to perform the intended task (add two numbers and write the result to $result_file)?
  • When reading the code file, log:
    logger.info("[CODE_ANALYSIS] Reading $code_file")
    logger.info("```python")
    logger.info(code_content)
    logger.info("```")
    
  • Run the script using python $code_file, capturing stdout, stderr, and return code with a 10-second timeout.
  • When executing, log:
    logger.info("[EXECUTION] Running python $code_file")
    logger.info("[EXECUTION_OUTPUT]")
    logger.info(f"stdout: {stdout}")
    logger.info(f"stderr: {stderr}")
    logger.info(f"return_code: {return_code}")
    
  • Read the output file $result_file and check if the result matches $expected_result.
  • When verifying output, log:
    logger.info("[FILE_VERIFICATION] Reading $result_file")
    logger.info("```")
    logger.info(file_content)
    logger.info("```")
    
  • Suggest specific code tweaks to address any issues found (e.g., add comments, improve variable names, add error handling). Format tweaks as code snippets for clarity.
  • Write a JSON status file $status_file with the following keys:
    • datetime: Current UTC timestamp in ISO format (e.g., "2025-06-18T15:37:00.123456Z").
    • critique: Detailed analysis of code quality and output verification.
    • tweaks: Suggested code improvements (code snippets or full code).
    • status: "pass" if the output in $result_file matches $expected_result and no errors occur, "fail" otherwise.
    • stdout: Output from running the code.
    • stderr: Any error messages.
  • Before writing the JSON, log it:
    logger.info("[JSON_UPDATE] Writing final verification status")
    logger.info("```json")
    logger.info(json.dumps(verification_data, indent=2))
    logger.info("```")
    
  • Write the JSON file atomically (use a temporary file and rename) to avoid race conditions with polling.
  • Log completion: "πŸ”¬ BACKGROUND VERIFICATION COMPLETE: [status]"
  • Log: "=" * 80 (section separator)

Example Generated Script Behavior:

  • Read $code_file and check for:
    • Presence of def add_numbers( to confirm the function exists.
    • Comments (e.g., # or ''') for readability.
    • Single-letter variable names (e.g., a, b) and suggest descriptive names (e.g., num1, num2).
    • Try-except blocks for file operations.
    • Line lengths exceeding 79 characters (PEP 8).
  • Run python $code_file and capture outputs.
  • Compare $result_file content with $expected_result.
  • Example critique: "Function add_numbers found. No comments found; consider adding explanatory comments. Single-letter variable names (a, b) reduce readability."
  • Example tweaks:
    Add comments:
    ```python
    # Add two numbers and return the sum
    def add_numbers(a, b):
    Use descriptive names:
    def add_numbers(num1, num2):
        return num1 + num2
  • Write $status_file atomically with critique, tweaks, status, stdout, and stderr.

Constraints:

  • Do not use the ast module or other parsing libraries for code analysis; rely on raw text analysis and language model capabilities.
  • Ensure all file paths and parameters ($code_file, $result_file, $status_file, $log_file, $expected_result) are substituted from the slash command.
  • Handle errors gracefully (e.g., file not found, invalid output) and include them in the critique.
  • Keep the generated script self-contained with no external dependencies beyond loguru, subprocess, json, datetime, sys, and os.

Logging Setup Helper

Standard loguru configuration for all scripts in this POC.

from loguru import logger
import datetime
import os

# Remove default handler to prevent stderr output
logger.remove()

# Add only file handler
logger.add('task_execution.log', 
           rotation='1 MB', 
           enqueue=True, 
           backtrace=True, 
           diagnose=True,
           format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {message}")

For archiving old logs:

if os.path.exists("task_execution.log"):
    archive_name = f"task_execution_archive_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.log"
    os.rename("task_execution.log", archive_name)
    logger.info(f"[LOG_ARCHIVED] Previous log moved to {archive_name}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment