Skip to content

Sync Claude annotations from my-claude-code#1

Open
leonj1 wants to merge 1 commit into
masterfrom
sync-claude-annotations-20260110-230309
Open

Sync Claude annotations from my-claude-code#1
leonj1 wants to merge 1 commit into
masterfrom
sync-claude-annotations-20260110-230309

Conversation

@leonj1

@leonj1 leonj1 commented Jan 10, 2026

Copy link
Copy Markdown
Owner

Summary

This PR syncs the .claude folder from leonj1/my-claude-code to keep Claude Code configurations consistent across repositories.

Changes

  • Updated .claude/ folder contents to match the source repository

This PR was automatically generated by the sync-claude-annotations script.

Summary by CodeRabbit

  • New Features

    • Added comprehensive agent-based development orchestration system supporting BDD-TDD workflow.
    • Introduced forensic debugging infrastructure (CRASH-RCA) for structured root-cause analysis.
    • Added automated testing and code-standards validation pipeline.
    • Introduced multi-stage architecture evaluation with alternative solution generation.
  • Documentation

    • Added extensive coding standards for Python, TypeScript, Go, and .NET Core.
    • Added comprehensive workflow and agent specifications.
    • Added general coding principles and testing standards.

✏️ Tip: You can customize this high-level summary in your review settings.

This commit syncs the .claude folder from leonj1/my-claude-code
to keep Claude Code configurations consistent across repos.
@coderabbitai

coderabbitai Bot commented Jan 10, 2026

Copy link
Copy Markdown

Walkthrough

This PR introduces a comprehensive multi-agent orchestration framework for Claude Code, defining architecture specification, BDD-TDD pipelines, code quality validation, forensic debugging protocols, coding standards across languages, and webhook-based state management to coordinate feature implementation and debugging workflows.

Changes

Cohort / File(s) Summary
Core Framework & Configuration
CLAUDE.md, config.json
Establishes foundational protocols including session continuity, decomposition validation modes, skill discovery integration, and event-driven hook configuration for agent coordination.
Architecture & Design Agents
agents/architect.md, agents/alternate-solutions.md, agents/architecture-evaluator.md, agents/request-fidelity-validator.md
Defines multi-phase architecture workflow: green-field design, alternative solution generation, fidelity-weighted evaluation, and traceability validation from root request through decomposition.
BDD & Test Specification Agents
agents/bdd-agent.md, agents/behavioral-language-validator.md, agents/gherkin-to-test.md, agents/requirements-qa.md, agents/scope-manager.md
Converts user requirements to Gherkin scenarios with behavioral-language enforcement, validates alignment with draft specs, gates task size, and bridges BDD specs to test-driven implementation.
Test Creation & Evaluation Agents
agents/test-creator.md, agents/test-consistency-validator.md, agents/test-evaluator.md, agents/test-pattern-detector.md
Implements TDD red-phase: writes failing tests first, validates test naming consistency, assesses assertion quality, and detects framework patterns across languages.
Implementation & Code Quality Agents
agents/coder.md, agents/coder-orchestrator.md, agents/strict-coder.md, agents/coding-standards-checker.md, agents/refactorer.md, agents/refactor-decision-engine.md
Orchestrates single-task implementation with code quality gates, enforces strict architecture constraints (500-line files, DI patterns), validates coding standards, and manages refactoring before feature addition.
Testing Infrastructure Agents
agents/tester.md, agents/tester-backend.md, agents/tester-frontend.md, agents/bdd-test-runner.md
Routes test tasks by code type, validates test environment setup (Dockerfile.test, Makefile), executes backend/frontend tests independently, and verifies BDD test executability.
Code Analysis & Verification Agents
agents/codebase-analyst.md, agents/code-searcher.md, agents/verifier.md, agents/tech-stack-analyzer.md, agents/violation-scanner.md
Performs gap analysis, locates code patterns across languages, investigates claims with evidence chains, profiles project tech stacks, and scans for standards violations.
Forensic Debugging Agents
agents/debugger.md, agents/forensic.md, agents/analyst.md, agents/acceptance-qa.md
Establishes CRASH-RCA session management, read-only investigation workflows, root cause analysis with justification, and user-centric acceptance criteria validation.
Support & Escalation Agents
agents/stuck.md, agents/stuck-original.md, agents/stuck-terragon.md, agents/init-explorer.md
Provides human escalation pathways for blocking issues with environment-driven rules (Terragon), initializes project context, and manages uncertainty escalation.
Command Workflows
commands/architect.md, commands/coder.md, commands/debugger.md, commands/init-explorer.md, commands/refactor.md, commands/verifier.md, commands/fix-failing-tests.md, commands/build-and-restart.md, commands/commit-all.md, commands/sync-claude.md
Defines orchestration workflows combining agents into feature-implementation pipelines (init → architect → BDD → test → code → quality → test), debugging sessions, and utility commands.
Coding Standards by Language
coding-standards/general.md, coding-standards/python.md, coding-standards/golang.md, coding-standards/typescript.md, coding-standards/dotnetcore.md, coding-standards/markdown.md, coding-standards/testing-standards.md
Enforces language-agnostic principles (500-line limits, DI patterns, no env-var access in business logic) and language-specific guidelines (FastAPI layering, Go interfaces, TypeScript strictness).
Event Hooks & State Management
hooks/post-*.sh, hooks/crash-guardrail.py, hooks/post-coder-orchestrator-loop.py, hooks/post-todowrite-task-check.py, hooks/pre-write-governance.py
Implements event-triggered state transitions (post-architect, post-coder, post-tester, etc.), tracks completion flags, enforces forensic-mode write restrictions, validates task completion, and governs file size/env-var constraints.
Utility Scripts
scripts/agent-summary.py, scripts/crash.py, scripts/skill_discovery_hook.py
Analyzes agent execution metrics, manages CRASH-RCA session state with investigation history, and discovers required skills via external API before task execution.
Hook Configuration & Documentation
hooks/README.md
Documents hook infrastructure, state file management, and testing instructions for post-execution and pre-tool-use governance.
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and specifically describes the primary change: syncing Claude configuration annotations from an external repository.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch sync-claude-annotations-20260110-230309

Comment @coderabbitai help to get the list of available commands and usage tips.

@ai-reviewer2

ai-reviewer2 Bot commented Jan 10, 2026

Copy link
Copy Markdown

Note

🔄 Code Review #1 in Progress

AI-powered code review is currently analyzing your changes. This comment will be updated when the review is complete.

@ai-reviewer2

ai-reviewer2 Bot commented Jan 10, 2026

Copy link
Copy Markdown

Note

🔄 Code Review #2 in Progress

AI-powered code review is currently analyzing your changes. This comment will be updated when the review is complete.

@ai-reviewer2

ai-reviewer2 Bot commented Jan 10, 2026

Copy link
Copy Markdown

Note

🔄 Code Review #3 in Progress

AI-powered code review is currently analyzing your changes. This comment will be updated when the review is complete.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Note

Due to the large number of review comments, Critical severity comments were prioritized as inline comments.

🤖 Fix all issues with AI agents
In @.claude/hooks/post-coder-orchestrator-loop.py:
- Around line 26-33: Add "from __future__ import annotations" to the top of the
imports to defer PEP 585 style annotations; update count_incomplete_features and
any other functions using "tuple[int, list[str]]" to rely on deferred evaluation
rather than changing types. In count_incomplete_features, tighten the regex to
only match documented "Incomplete:" checklist items (e.g., use r"^\s*-\s*\[
\]\s*Incomplete:\s*(.+)$" for the variable that builds the pattern) instead of
matching any unchecked box. Wrap all Path.read_text() calls in try-except and
handle OSError/UnicodeDecodeError by returning/propagating a clear error or an
empty result so the hook doesn't crash on encoding/permission issues (locate
uses in count_incomplete_features and any helper functions that call
Path.read_text()).

In @.claude/hooks/post-coder-standards-check.sh:
- Around line 17-34: Current checks validate SESSION_ID but trust CWD; update
the script to harden CWD before any writes: resolve CWD to an absolute canonical
path (realpath or readlink -f), verify it is a directory (-d), confirm it
contains a ".claude" subdirectory, and ensure the canonical CWD is under the
expected workspace root (for example $PWD or a configured WORKSPACE_ROOT) to
prevent path traversal or writes outside the repo; additionally reject or fail
if the resolved path differs from the original due to symlinks (prevent symlink
traversal) and optionally verify ownership matches the current user (stat/uid)
before proceeding.

In @.claude/hooks/post-test-consistency-validator.sh:
- Around line 24-35: The CWD validation currently only rejects '..' but still
allows absolute or symlinked paths outside the workspace; update the validator
to resolve CWD to its physical path (using pwd -P or realpath) and verify that
the resolved CWD is inside the expected workspace root (or equals `pwd -P`), and
additionally check that the directory contains the required marker `.claude`
(i.e., ensure `$CWD/.claude` exists and is a directory/file); if either check
fails, print a clear error and exit non‑zero.

In @.claude/scripts/crash.py:
- Around line 31-36: The load_state function should gracefully handle corrupt
JSON in STATE_FILE: wrap json.load(f) in a try/except that catches
json.JSONDecodeError (and optionally ValueError), log an error including the
filename and exception (use existing logger or print if none), optionally
move/rename or back up the corrupted STATE_FILE for inspection, and return None
instead of letting the exception propagate; keep the function name load_state
and the STATE_FILE symbol so the change is easy to locate.
🟠 Major comments (16)
.claude/hooks/post-tester-infrastructure.sh-46-50 (1)

46-50: Make the timestamp portable (date -Iseconds is not macOS/BSD compatible) and consider atomic write.
On macOS, date -Iseconds typically fails; with set -e this will abort the hook.

Proposed fix
 STATE_DIR="$CWD/.claude/.state"
 mkdir -p "$STATE_DIR"
-echo "$(date -Iseconds)" > "$STATE_DIR/testing-completed-${SESSION_ID}"
+NOW="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
+tmp="$(mktemp "${STATE_DIR}/testing-completed-${SESSION_ID}.XXXXXX")"
+printf '%s\n' "$NOW" > "$tmp"
+mv "$tmp" "$STATE_DIR/testing-completed-${SESSION_ID}"
.claude/hooks/post-tester-infrastructure.sh-7-16 (1)

7-16: Harden shell safety + JSON parsing (avoid "null" and improve jq failure behavior).
Right now missing keys become "null" (jq -r), and 2>&1 can smear error text into variables; also jq isn’t validated as a dependency.

Proposed fix
-set -e
+set -euo pipefail
+
+command -v jq >/dev/null 2>&1 || { echo "❌ jq is required for this hook" >&2; exit 1; }
 
 # Parse the hook input from stdin
 HOOK_INPUT=$(cat)
 
 # Extract session info
-SESSION_ID=$(echo "$HOOK_INPUT" | jq -r '.session_id' 2>&1) || { echo "❌ Failed to parse session_id from input" >&2; exit 1; }
-CWD=$(echo "$HOOK_INPUT" | jq -r '.cwd' 2>&1) || { echo "❌ Failed to parse cwd from input" >&2; exit 1; }
-SUBAGENT_NAME=$(echo "$HOOK_INPUT" | jq -r '.subagent_name // empty' 2>&1) || { echo "❌ Failed to parse subagent_name from input" >&2; exit 1; }
+SESSION_ID=$(jq -er '.session_id' <<<"$HOOK_INPUT") || { echo "❌ Failed to parse session_id from input" >&2; exit 1; }
+CWD=$(jq -er '.cwd' <<<"$HOOK_INPUT") || { echo "❌ Failed to parse cwd from input" >&2; exit 1; }
+SUBAGENT_NAME=$(jq -r '.subagent_name // ""' <<<"$HOOK_INPUT") || { echo "❌ Failed to parse subagent_name from input" >&2; exit 1; }
.claude/hooks/post-tester-infrastructure.sh-17-34 (1)

17-34: Fix validation gaps: reject empty/null session_id/cwd; validate CWD is an existing absolute directory.
The current checks allow SESSION_ID="null" and CWD="null" to pass, and allow relative/non-existent CWD values (risking state written to unintended locations).

Proposed fix
-# Validate SESSION_ID to prevent path traversal
-if [[ "$SESSION_ID" =~ [^a-zA-Z0-9_-] ]]; then
-  echo "❌ Invalid session_id: contains disallowed characters" >&2
-  exit 1
-fi
-
-# Validate session_id format (alphanumeric, hyphen, underscore only)
-if ! [[ "$SESSION_ID" =~ ^[a-zA-Z0-9_-]+$ ]]; then
+# Validate session_id format (alphanumeric, hyphen, underscore only)
+if [ -z "$SESSION_ID" ] || ! [[ "$SESSION_ID" =~ ^[a-zA-Z0-9_-]+$ ]]; then
   echo "❌ Invalid session_id format" >&2
   exit 1
 fi
 
 # Validate CWD is not empty
-if [ -z "$CWD" ]; then
-  echo "❌ CWD is empty" >&2
+if [ -z "$CWD" ] || [ "$CWD" = "null" ]; then
+  echo "❌ CWD is empty/invalid" >&2
+  exit 1
+fi
+if [[ "$CWD" != /* ]] || [ ! -d "$CWD" ]; then
+  echo "❌ CWD must be an existing absolute directory: $CWD" >&2
   exit 1
 fi
.claude/hooks/post-standards-testing.sh-29-33 (1)

29-33: Add path traversal validation for CWD.

The script validates that CWD is non-empty but doesn't check for path traversal sequences (..). This is present in post-bdd-agent.sh (lines 29-33) and should be consistent across hooks.

🔒 Proposed security fix
 # Validate CWD is not empty
 if [ -z "$CWD" ]; then
   echo "❌ CWD is empty" >&2
   exit 1
 fi
+
+# Validate CWD does not contain path traversal sequences
+if [[ "$CWD" =~ \.\. ]]; then
+  echo "❌ Invalid CWD: path traversal detected" >&2
+  exit 1
+fi
.claude/agents/refactorer.md-74-74 (1)

74-74: Use proper heading syntax instead of bold emphasis.

Lines 74, 80, 87, 93, 99, and 105 use bold text (**Step X:**) instead of markdown heading syntax (### Step X). This affects document structure and accessibility.

Convert emphasis to proper headings
-   **Step A: Structural Refactoring**
+   ### Step A: Structural Refactoring

Apply this change to all step headings throughout the workflow sections.

Also applies to: 80-80, 87-87, 93-93, 99-99, 105-105

.claude/agents/refactorer.md-22-31 (1)

22-31: Fix unordered list indentation to meet markdown standards.

The list formatting has inconsistent indentation. Unordered lists should use 0 or 2-space indentation, not 3-5 spaces as currently shown.

Fix markdown list indentation
## Environment Detection

-**CRITICAL**: Check if the environment variable `TERRAGON` exists and is set to `"true"`.
+**CRITICAL**: Check if the environment variable `TERRAGON` exists and is set to `"true"`.

-- **When `TERRAGON` is NOT set or is `false`**: Follow the **Standard Environment** workflow (see `stuck-original.md`)
-- **When `TERRAGON` is set to `"true"`**: Follow the **Terragon Environment** workflow (see `stuck-terragon.md`)
+- **When `TERRAGON` is NOT set or is `false`**: Follow the **Standard Environment** workflow (see `stuck-original.md`)
+- **When `TERRAGON` is set to `"true"`**: Follow the **Terragon Environment** workflow (see `stuck-terragon.md`)

Apply this pattern throughout the document to normalize list indentation to 0 or 2 spaces.

Also applies to: 35-41, 45-60

.claude/agents/refactorer.md-42-42 (1)

42-42: Specify language for fenced code blocks.

Code blocks at lines 42, 131, 206, 215, 222, and 238 are missing language identifiers. This impacts syntax highlighting and renders inconsistently.

Add language specifiers to code blocks
-   ```
+   ```bash
     skill: "fastapi-clean-architecture"
-   ```
+   ```

-Provide a detailed refactoring report in this format:
-    ```
+   ```markdown
     **Refactoring Complete**
     
     **Files Refactored**:
-    ```
+   ```

Identify each code block's language (bash, python, markdown, makefile, etc.) and add the appropriate specifier.

Also applies to: 131-131, 206-206, 215-215, 222-222, 238-238

.claude/agents/bdd-test-runner.md-145-155 (1)

145-155: Fix Makefile syntax for fallback test commands.

Lines 149 and 155 in the Makefile template use shell OR logic (||) across mutually exclusive commands (pytest, npm, go), which won't work as intended. The test-local and test-bdd targets need language-specific variants, not generic fallbacks.

Fix Makefile test target syntax
# Run tests locally (faster, requires local setup)
test-local:
	@echo "Running tests locally..."
-	# Framework-specific command goes here
-	pytest -v tests/ || npm test || go test -v ./...
+	# Framework-specific command - select based on detected language
+	@if [ -f "requirements.txt" ]; then \
+		pytest -v tests/; \
+	elif [ -f "package.json" ]; then \
+		npm test; \
+	elif [ -f "go.mod" ]; then \
+		go test -v ./...; \
+	else \
+		echo "No recognized test framework found"; \
+		exit 1; \
+	fi

# Run BDD tests specifically
test-bdd:
	@echo "Running BDD tests..."
-	# BDD-specific command
-	pytest -v tests/bdd/ || npm run test:bdd || go test -v ./tests/bdd/...
+	@if [ -f "requirements.txt" ]; then \
+		pytest -v tests/bdd/; \
+	elif [ -f "package.json" ]; then \
+		npm run test:bdd; \
+	elif [ -f "go.mod" ]; then \
+		go test -v ./tests/bdd/...; \
+	fi

This ensures the template actually works in any language context rather than failing with syntax errors.

.claude/hooks/skill_discovery_hook.py-8-10 (1)

8-10: Consider validating the SKILL_API_URL scheme.

The URL is read from the environment, which could allow unexpected schemes (like file:). For security, validate that SKILL_API_URL uses https:// before making the request.

🔒 Suggested URL scheme validation
 SKILL_API_URL = os.environ.get(
     "SKILL_API_URL", "https://external-claude-skills-production.up.railway.app/"
 )
+
+# Validate URL scheme for security
+if not SKILL_API_URL.startswith("https://"):
+    raise ValueError("SKILL_API_URL must use https:// scheme")
.claude/scripts/crash.py-76-113 (1)

76-113: Validate confidence score range.

The function accepts any float value for confidence without validating that it's between 0.0 and 1.0. Invalid values (e.g., -1, 5, 100) would be accepted and could produce misleading HIGH/MED/LOW indicators.

🔒 Proposed fix to validate confidence range
 def log_step(hypothesis, action, confidence):
     """Log an investigation step with hypothesis and planned action."""
     state = load_state()
     if not state or state['status'] != 'active':
         print("ERROR: No active CRASH session.")
         print("Run 'crash.py start \"issue description\"' first.")
         sys.exit(1)
 
+    confidence_float = float(confidence)
+    if not 0.0 <= confidence_float <= 1.0:
+        print(f"ERROR: Confidence must be between 0.0 and 1.0, got {confidence_float}")
+        sys.exit(1)
+
     step_id = len(state['steps']) + 1
     new_step = {
         "id": step_id,
         "timestamp": datetime.now().isoformat(),
         "hypothesis": hypothesis,
         "action": action,
-        "confidence": float(confidence)
+        "confidence": confidence_float
     }
.claude/commands/refactor.md-17-32 (1)

17-32: Empty-ARGUMENTS behavior is dangerously broad; consider confirmation gate.

“If $ARGUMENTS is empty, refactor all code in the current project” can trigger massive, low-signal diffs; recommend requiring explicit confirmation or switching the default to “analyze + propose plan” when empty.

.claude/hooks/post-gherkin-to-test.sh-7-16 (1)

7-16: Same JSON parsing hardening needed (null fields + jq dependency + pipefail).

As written, missing session_id/cwd can become "null" and pass, and set -e won’t catch pipe failures. Mirror the fixes from the other hooks (set -euo pipefail, jq ... // empty, explicit empty checks, command -v jq).

.claude/hooks/post-coder-standards-check.sh-7-16 (1)

7-16: Harden bash mode + dependency/“null” handling for JSON fields.

  • set -e without -u/pipefail + jq -r returning null can silently accept missing fields (SESSION_ID="null", CWD="null").
  • 2>&1 inside the jq command substitutions can leak parse errors into captured values.
Proposed patch
-set -e
+set -euo pipefail

 # Parse the hook input from stdin
 HOOK_INPUT=$(cat)
 
 # Extract session info
-SESSION_ID=$(echo "$HOOK_INPUT" | jq -r '.session_id' 2>&1) || { echo "❌ Failed to parse session_id from input" >&2; exit 1; }
-CWD=$(echo "$HOOK_INPUT" | jq -r '.cwd' 2>&1) || { echo "❌ Failed to parse cwd from input" >&2; exit 1; }
-SUBAGENT_NAME=$(echo "$HOOK_INPUT" | jq -r '.subagent_name // empty' 2>&1) || { echo "❌ Failed to parse subagent_name from input" >&2; exit 1; }
+command -v jq >/dev/null 2>&1 || { echo "❌ jq is required but not found" >&2; exit 1; }
+SESSION_ID=$(echo "$HOOK_INPUT" | jq -r '.session_id // empty' 2>/dev/null) || { echo "❌ Failed to parse session_id from input" >&2; exit 1; }
+CWD=$(echo "$HOOK_INPUT" | jq -r '.cwd // empty' 2>/dev/null) || { echo "❌ Failed to parse cwd from input" >&2; exit 1; }
+SUBAGENT_NAME=$(echo "$HOOK_INPUT" | jq -r '.subagent_name // empty' 2>/dev/null) || { echo "❌ Failed to parse subagent_name from input" >&2; exit 1; }
+if [ -z "$SESSION_ID" ] || [ "$SESSION_ID" = "null" ]; then
+  echo "❌ session_id is missing" >&2
+  exit 1
+fi
+if [ -z "$CWD" ] || [ "$CWD" = "null" ]; then
+  echo "❌ cwd is missing" >&2
+  exit 1
+fi
.claude/hooks/post-test-consistency-validator.sh-7-17 (1)

7-17: Treat missing JSON fields as errors (avoid SESSION_ID="null" / CWD="null").

jq -r '.session_id' returns null when absent and your regex allows it, so missing session_id will pass validation.

Proposed patch
-set -e
+set -euo pipefail
+
+command -v jq >/dev/null 2>&1 || { echo "❌ jq is required but not found" >&2; exit 1; }

-SESSION_ID=$(echo "$HOOK_INPUT" | jq -r '.session_id' 2>/dev/null) || { echo "❌ Failed to parse session_id from input" >&2; exit 1; }
-CWD=$(echo "$HOOK_INPUT" | jq -r '.cwd' 2>/dev/null) || { echo "❌ Failed to parse cwd from input" >&2; exit 1; }
+SESSION_ID=$(echo "$HOOK_INPUT" | jq -r '.session_id // empty' 2>/dev/null) || { echo "❌ Failed to parse session_id from input" >&2; exit 1; }
+CWD=$(echo "$HOOK_INPUT" | jq -r '.cwd // empty' 2>/dev/null) || { echo "❌ Failed to parse cwd from input" >&2; exit 1; }
 SUBAGENT_NAME=$(echo "$HOOK_INPUT" | jq -r '.subagent_name // empty' 2>/dev/null) || { echo "❌ Failed to parse subagent_name from input" >&2; exit 1; }
 TRANSCRIPT=$(echo "$HOOK_INPUT" | jq -r '.transcript // empty' 2>/dev/null) || TRANSCRIPT=""
+
+if [ -z "$SESSION_ID" ] || [ "$SESSION_ID" = "null" ]; then
+  echo "❌ session_id is missing" >&2
+  exit 1
+fi
+if [ -z "$CWD" ] || [ "$CWD" = "null" ]; then
+  echo "❌ cwd is missing" >&2
+  exit 1
+fi
.claude/hooks/post-coder-orchestrator-loop.py-45-51 (1)

45-51: feature_list.md matcher is broader than the documented contract; risk of false-positive infinite loop.
Docs say it looks for "[ ] Incomplete" entries, but the regex counts any unchecked list item (- [ ] ...). If feature_list.md contains unchecked checklists unrelated to “incomplete features”, this will keep forcing exit code 1. Either tighten the regex or update the doc to match behavior.

Proposed fix (tighten to “Incomplete:” only)
-    # Match "[ ] Incomplete" or just "[ ]" followed by feature text
-    # Pattern: - [ ] Incomplete: Feature name OR - [ ] Feature name
-    incomplete_pattern = r"^\s*-\s*\[ \]\s*(?:Incomplete:\s*)?(.+)$"
+    # Match: - [ ] Incomplete: Feature name
+    incomplete_pattern = r"^\s*-\s*\[ \]\s*Incomplete:\s*(.+)$"
     matches = re.findall(incomplete_pattern, content, re.MULTILINE)
 
-    return len(matches), matches[:5]  # Return first 5 for display
+    cleaned = [m.strip() for m in matches]
+    return len(cleaned), cleaned[:5]  # Return first 5 for display

Also applies to: 109-136

.claude/commands/coder.md-1-52 (1)

1-52: Filename mismatch: .claude/commands/coder.md contains orchestrator instructions instead of coder role guidance.

When invoked as /coder, this file will instruct the agent to orchestrate tasks rather than implement them—a functional misalignment. A separate .claude/agents/coder-orchestrator.md file exists with the proper orchestrator role. Either rename coder.md to reflect its orchestrator purpose or move/rewrite its content for the actual coder role.

Additionally, lines 113, 150, and 285 contain fenced code blocks without language specifiers, violating MD040 (fenced-code-languages). The repo's markdownlint config (coderabbit.markdownlint-cli2.jsonc) has MD040 enabled, so these will fail linting checks.

🟡 Minor comments (20)
.claude/agents/code-searcher.md-54-54 (1)

54-54: Add language specifiers to fenced code blocks.

Multiple fenced code blocks are missing language specifiers, which reduces readability and prevents proper syntax highlighting. Consider adding appropriate specifiers:

  • Lines 54, 128: Use markdown for response format templates
  • Lines 75, 83, 91, 98: Use regex for search pattern examples
  • Line 120: Use text or yaml for the example request
📝 Proposed fixes
 ## Response Format
 
-```
+```markdown
 ## Code Search Results
 ### Python
-```
+```regex
 class \w+Service
 ### TypeScript/JavaScript
-```
+```regex
 class \w+
 ### Go
-```
+```regex
 type \w+ struct
 ### .NET
-```
+```regex
 class \w+
 ## Example Search Request
 
-```
+```text
 Search for: User authentication service
 ## Example Response
 
-```
+```markdown
 ## Code Search Results

Also applies to: 75-75, 83-83, 91-91, 98-98, 120-120, 128-128

.claude/agents/acceptance-qa.md-47-54 (1)

47-54: Add language specifiers to example code blocks.

The fenced code blocks showing example report formats should include markdown as the language specifier for proper syntax highlighting and rendering.

📝 Proposed fixes
 #### If PASSED:
-```markdown
+```markdown
 # Acceptance QA Report
 #### If FAILED:
-```markdown
+```markdown
 # Acceptance QA Report

Also applies to: 57-68

.claude/commands/build-and-restart.md-5-5 (1)

5-5: Improve grammar and sentence structure.

The description has a minor grammar issue and runs on without proper punctuation, affecting readability.

📝 Proposed fix
-Build and restart this project first check if Makefile exists to use targets in this file, otherwise default by checking the project type to determine how to build and restart it.
+Build and restart this project. First check if a Makefile exists to use targets in this file; otherwise, default to checking the project type to determine how to build and restart it.
.claude/agents/debugger.md-165-193 (1)

165-193: Add language specifier to code fence in example session.

Line 165 contains a bare code fence without a language specifier. Per markdown standards (MD040), code blocks should specify a language. Since this example shows session output/interaction flow, consider using text or plaintext as the language identifier.

📝 Suggested fix
  ## Example Session
  
- ```
+ ```plaintext
  User: "The login API returns 500 errors intermittently"
.claude/agents/tech-stack-analyzer.md-64-64 (1)

64-64: Convert emphasis formatting to proper headings.

Five section labels use bold emphasis (**...**) when they should be proper markdown headings (###). This applies to: "Language & Runtime" (line 64), "Framework" (line 68), "Test Framework" (line 72), "Build Tools" (line 76), and "Key Dependencies" (line 80).

📝 Proposed fixes
- **Language & Runtime**
+ ### Language & Runtime

- **Framework**
+ ### Framework

- **Test Framework**
+ ### Test Framework

- **Build Tools**
+ ### Build Tools

- **Key Dependencies**
+ ### Key Dependencies

Also applies to: 68-68, 72-72, 76-76, 80-80

.claude/agents/stuck-terragon.md-52-52 (1)

52-52: Add language identifiers to fenced code blocks.

Four fenced code blocks are missing language specifications. This is a markdown linting requirement that should be addressed for consistency with documentation standards.

📝 Proposed fixes for code block language specifications
# Line 52 - Build error example
- ```
+ ```markdown

# Line 79 - Test failure example
- ```
+ ```markdown

# Line 107 - Uncertainty example
- ```
+ ```markdown

# Line 176 - Phase 2 response format
- ```
+ ```markdown

Also applies to: 79-79, 107-107, 176-176

.claude/agents/tech-stack-analyzer.md-27-27 (1)

27-27: Add language identifiers to fenced code blocks.

Three fenced code blocks are missing language specifications. Lines 27 and 89 contain manifest file lists, and line 137 contains a markdown example response.

📝 Proposed fixes for code block language specifications
# Line 27 - Manifest file list
- ```
+ ```text

# Line 89 - Output format template
- ```
+ ```markdown

# Line 137 - Example response
- ```
+ ```markdown

Also applies to: 89-89, 137-137

.claude/agents/forensic.md-21-21 (1)

21-21: Convert emphasis to a proper heading.

Line 21 uses emphasis formatting (**...**) for "CRITICAL: You are in FORENSIC MODE" when this should be a section heading (##) for proper markdown structure.

📝 Proposed fix
- **CRITICAL: You are in FORENSIC MODE**
+ ## CRITICAL: You are in FORENSIC MODE
.claude/agents/forensic.md-132-132 (1)

132-132: Add language identifier to code block at line 132.

The fenced code block in the evidence collection format example is missing a language specification.

📝 Proposed fix
- ```
+ ```markdown
  **Investigation**: [What was being searched for]
.claude/coding-standards/python.md-63-63 (1)

63-63: Use heading syntax instead of emphasis for section headers.

Line 63 uses bold emphasis (**Exception: FastAPI Optional Form Parameters**) but should use markdown heading syntax (###) to maintain proper document structure for the coding-standards documentation.

Fix markdown heading syntax
-**Exception: FastAPI Optional Form Parameters**
+### Exception: FastAPI Optional Form Parameters
.claude/coding-standards/python.md-590-592 (1)

590-592: Specify language identifier for code block.

The code block at line 590 is missing a language identifier. This helps with syntax highlighting and follows markdown best practices. The block appears to reference a skill invocation with YAML-like key-value syntax.

Add language identifier to code block
-```
+```yaml
 skill: "fastapi-clean-architecture"
-```
+```
.claude/scripts/crash.py-156-201 (1)

156-201: Add error handling for file removal in diagnose.

Similar to cancel_session, the os.remove() call can fail due to permission issues or if the file has already been deleted. Adding error handling ensures graceful degradation.

🛡️ Proposed fix for robust file removal
     print("---")
     print("")
     print("Session Complete. Write/Edit tools are now re-enabled.")
 
-    os.remove(STATE_FILE)
+    try:
+        os.remove(STATE_FILE)
+    except OSError as e:
+        print(f"WARNING: Could not remove state file: {e}", file=sys.stderr)
.claude/scripts/crash.py-142-153 (1)

142-153: Add error handling for file removal.

os.remove() can raise OSError if the file doesn't exist or due to permission issues. While unlikely in normal usage, this could cause an unexpected crash.

🛡️ Proposed fix for robust file removal
 def cancel_session():
     """Cancel the current session without diagnosis."""
     state = load_state()
     if not state:
         print("No active session to cancel.")
         return
 
     session_id = state['session_id']
     if os.path.exists(STATE_FILE):
-        os.remove(STATE_FILE)
+        try:
+            os.remove(STATE_FILE)
+        except OSError as e:
+            print(f"WARNING: Could not remove state file: {e}", file=sys.stderr)
     print(f"Session #{session_id} cancelled.")
     print("Write/Edit tools are now re-enabled.")
.claude/hooks/post-gherkin-to-test.sh-52-57 (1)

52-57: Comment doesn’t match behavior (filename pattern vs file content).

The comment claims content-based detection (“files containing executor: bdd”), but the code only matches *-bdd-* filenames. Either update the comment or actually grep file content.

.claude/agents/coding-standards-checker.md-213-217 (1)

213-217: Line 217 needs shell portability clarification; line 214 pattern is correct.

Line 217's **/*.{py,ts,js,go} glob requires shopt -s globstar (bash) or zsh and won't work in basic sh. For portability, recommend using find . -name "*.py" -o -name "*.ts" -o -name "*.js" -o -name "*.go" or clarifying the shell requirement.

Line 214's pattern def.*=.*: works as intended—it correctly identifies default arguments without false positives from comments or docstrings on separate lines.

.claude/config.json-10-15 (1)

10-15: Consolidate hook paths to repository-relative format.

Line 13 references ~/.claude/hooks/skill_discovery_hook.py using home directory expansion, while all other hooks in this config use repository-relative paths like .claude/hooks/.... This file does not exist in the repository, creating an external system dependency.

Ensure the path uses the same repository-relative format as other hooks: .claude/hooks/skill_discovery_hook.py.

.claude/commands/architect.md-37-41 (1)

37-41: Fix minor doc inconsistencies: filename + duplicate step number.

  • .feature_list.md.example looks like a typo (leading dot).
  • “### 6.” is used twice; makes referencing steps harder during execution.
Proposed fix
-1. Create .feature_list.md.example if feature_list.md doesn't exist
+1. Create feature_list.md.example if feature_list.md doesn't exist
@@
-### 6. **Completion & Continuation**
+### 7. **Completion & Continuation**

Also applies to: 148-166

.claude/hooks/post-coder-orchestrator-loop.py-39-44 (1)

39-44: Fail-open on file read errors (and prefer explicit UTF-8).
read_text() can raise (permissions, encoding). A hook crash here is worse than skipping the check. Consider encoding="utf-8" and catching OSError/UnicodeDecodeError to return (0, []) (continue).

Proposed fix
-    content = feature_file.read_text()
+    try:
+        content = feature_file.read_text(encoding="utf-8")
+    except (OSError, UnicodeDecodeError):
+        return 0, []
@@
-    content = digest_file.read_text()
+    try:
+        content = digest_file.read_text(encoding="utf-8")
+    except (OSError, UnicodeDecodeError):
+        return 0, []

Also applies to: 60-65

.claude/commands/coder.md-113-146 (1)

113-146: Fix markdownlint MD040: add languages to fenced code blocks.
This is flagged by static analysis and is easy to address.

Proposed fix
-```
+```text
 User: "Build a React todo app"
@@
-```
+```text
 USER gives project
@@
-```
+```text
 coder completes → SubagentStop event

Also applies to: 150-188, 285-307

.claude/agents/gherkin-to-test.md-181-197 (1)

181-197: Example prompt filenames use .feature extension (but prompt format is .md).
This reads like a copy/paste slip and can confuse the orchestrator’s “report prompt numbers” step.

Proposed doc fix
-006-bdd-user-registration.feature  → 006 (foundation)
-007-bdd-user-authentication.feature → 007 (depends on registration)
-008-bdd-password-reset.feature     → 008 (depends on auth)
+006-bdd-user-registration.md       → 006 (foundation)
+007-bdd-user-authentication.md     → 007 (depends on registration)
+008-bdd-password-reset.md          → 008 (depends on auth)

Comment on lines +26 to +33
import json
import re
import sys
from pathlib import Path


def count_incomplete_features(cwd: str) -> tuple[int, list[str]]:
"""

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's read the full file to see the annotations and context
cat -n ".claude/hooks/post-coder-orchestrator-loop.py"

Repository: leonj1/3camels

Length of output: 5789


🏁 Script executed:

# Check for Python version requirements in the project
find . -maxdepth 2 -type f \( -name "*.toml" -o -name "*.cfg" -o -name "*.yaml" -o -name "*.yml" -o -name "setup.py" -o -name ".python-version" \) | head -20

Repository: leonj1/3camels

Length of output: 69


🏁 Script executed:

# Look for any CI/workflow files that might specify Python version
find . -path "*/.github/workflows/*" -type f -o -path "*/\.circleci/*" -type f 2>/dev/null | head -10

Repository: leonj1/3camels

Length of output: 40


🏁 Script executed:

# Check ruff.toml for Python version requirements
cat ruff.toml

Repository: leonj1/3camels

Length of output: 964


🏁 Script executed:

# Also check pyproject.toml or any other config files
ls -la | grep -E "(pyproject|setup|requirements|python)"
cat pyproject.toml 2>/dev/null || echo "No pyproject.toml"

Repository: leonj1/3camels

Length of output: 144


🏁 Script executed:

# Check if __future__ annotations is used anywhere in the project
rg "from __future__ import annotations" --type py | head -20

Repository: leonj1/3camels

Length of output: 206


🏁 Script executed:

# Search for Python version specification more broadly
find . -type f \( -name "*.md" -o -name "*.txt" -o -name "*.toml" -o -name "*.yaml" \) -exec grep -l "python" {} \; | head -10

Repository: leonj1/3camels

Length of output: 144


🏁 Script executed:

# Check README or similar for Python requirements
head -50 README.md 2>/dev/null || head -50 readme.md 2>/dev/null || echo "No README found"

Repository: leonj1/3camels

Length of output: 67


🏁 Script executed:

# Verify the annotation syntax is actually on lines 32 and 53
grep -n "tuple\[" ".claude/hooks/post-coder-orchestrator-loop.py"

Repository: leonj1/3camels

Length of output: 189


🏁 Script executed:

# Check if there's any Python version requirement documentation
find . -maxdepth 3 -type f -name "*.md" -exec grep -l "python.*3\.[0-9]" {} \; 2>/dev/null | head -5

Repository: leonj1/3camels

Length of output: 93


🏁 Script executed:

# Let's check what Python version the project actually targets
# Look for any .python-version files or GitHub Actions workflows
find . -name ".python-version" -type f

Repository: leonj1/3camels

Length of output: 40


🏁 Script executed:

# Check if there are any workflows that run tests
find . -type f \( -name "*.yml" -o -name "*.yaml" \) | head -10

Repository: leonj1/3camels

Length of output: 184


🏁 Script executed:

# Verify the regex pattern behavior - does it match ANY unchecked item or only "Incomplete:"?
# The pattern is: r"^\s*-\s*\[ \]\s*(?:Incomplete:\s*)?(.+)$"
# Let's verify the docstring claim
grep -A 5 "Looks for" ".claude/hooks/post-coder-orchestrator-loop.py"

Repository: leonj1/3camels

Length of output: 243


🏁 Script executed:

# Check error handling for Path.read_text() calls
grep -B 2 -A 2 "read_text()" ".claude/hooks/post-coder-orchestrator-loop.py"

Repository: leonj1/3camels

Length of output: 292


🏁 Script executed:

# Let's check if there's any indication of Python 3.8 support in the project
# Search for any setup.py, pyproject.toml, or tox.ini
ls -la setup.py setup.cfg pyproject.toml tox.ini 2>/dev/null || echo "No standard config found"

Repository: leonj1/3camels

Length of output: 82


🏁 Script executed:

# Check the actual docstring claim vs regex behavior
# The docstring says "Looks for '[ ] Incomplete' entries"
# But the regex makes "Incomplete:" optional
# Let's confirm what the comment says in the regex
sed -n '45,48p' ".claude/hooks/post-coder-orchestrator-loop.py"

Repository: leonj1/3camels

Length of output: 330


🏁 Script executed:

# Double-check: does the regex actually match ALL [ ] items or only those with Incomplete:?
python3 << 'EOF'
import re

# The pattern from the file
pattern = r"^\s*-\s*\[ \]\s*(?:Incomplete:\s*)?(.+)$"

# Test cases
test_strings = [
    "- [ ] Incomplete: Feature X",
    "- [ ] Some random unchecked item",
    "- [ ] Bug fix needed",
    "- [x] Completed feature"
]

for test in test_strings:
    match = re.search(pattern, test, re.MULTILINE)
    print(f"Pattern matches '{test}': {bool(match)}")
EOF

Repository: leonj1/3camels

Length of output: 260


Fix PEP 585 annotation incompatibility and regex over-matching for hook reliability.

The tuple[int, list[str]] annotations (lines 32, 53) require Python 3.9+ and will crash at import time on Python 3.8, breaking the entire hook. Additionally, the regex pattern at line 47 matches any unchecked item ([ ]), not only "Incomplete:" entries as documented, which can cause the hook to perpetually re-trigger on legitimate incomplete tasks. Finally, Path.read_text() calls lack exception handling for encoding or permission errors.

Add from __future__ import annotations at the top of imports to defer annotation evaluation, make the regex explicitly require "Incomplete:" prefix (or document the broader matching), and wrap read_text() calls in try-except to handle IO errors gracefully:

Proposed changes
 #!/usr/bin/env python3
 """
 Coder Orchestrator Loop Hook
@@ -23,6 +23,7 @@ Output format:
 - If tasks remain: {"error": "..."} with exit code 1
 - If complete: {"continue": true, "systemMessage": "..."} with exit code 0
 """
+from __future__ import annotations
 import json
 import re
 import sys
@@ -40,7 +41,12 @@ def count_incomplete_features(cwd: str) -> tuple[int, list[str]]:
     feature_file = Path(cwd) / "feature_list.md"
     if not feature_file.exists():
         return 0, []
-    content = feature_file.read_text()
+    try:
+        content = feature_file.read_text()
+    except (UnicodeDecodeError, PermissionError, OSError):
+        # If file is unreadable, assume no incomplete features
+        return 0, []

Also update regex to r"^\s*-\s*\[ \]\s*Incomplete:\s*(.+)$" (line 47) to match documented behavior, or update docstring to reflect that all unchecked items are flagged.

🤖 Prompt for AI Agents
In @.claude/hooks/post-coder-orchestrator-loop.py around lines 26 - 33, Add
"from __future__ import annotations" to the top of the imports to defer PEP 585
style annotations; update count_incomplete_features and any other functions
using "tuple[int, list[str]]" to rely on deferred evaluation rather than
changing types. In count_incomplete_features, tighten the regex to only match
documented "Incomplete:" checklist items (e.g., use r"^\s*-\s*\[
\]\s*Incomplete:\s*(.+)$" for the variable that builds the pattern) instead of
matching any unchecked box. Wrap all Path.read_text() calls in try-except and
handle OSError/UnicodeDecodeError by returning/propagating a clear error or an
empty result so the hook doesn't crash on encoding/permission issues (locate
uses in count_incomplete_features and any helper functions that call
Path.read_text()).

Comment on lines +17 to +34
# Validate SESSION_ID to prevent path traversal
if [[ "$SESSION_ID" =~ [^a-zA-Z0-9_-] ]]; then
echo "❌ Invalid session_id: contains disallowed characters" >&2
exit 1
fi

# Validate session_id format (alphanumeric, hyphen, underscore only)
if ! [[ "$SESSION_ID" =~ ^[a-zA-Z0-9_-]+$ ]]; then
echo "❌ Invalid session_id format" >&2
exit 1
fi

# Validate CWD is not empty
if [ -z "$CWD" ]; then
echo "❌ CWD is empty" >&2
exit 1
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

CWD is trusted input; add traversal + realpath/ownership checks (avoid arbitrary file writes).

Right now any caller controlling .cwd can steer the state-file write. At minimum, ensure CWD is a directory, contains .claude/, and resolves inside the current working directory (or inside a configured workspace root).

Proposed patch (minimal safety checks)
-# Validate CWD is not empty
-if [ -z "$CWD" ]; then
-  echo "❌ CWD is empty" >&2
-  exit 1
-fi
+# Validate CWD is a safe directory
+if [[ "$CWD" =~ \.\. ]]; then
+  echo "❌ Invalid CWD: path traversal detected" >&2
+  exit 1
+fi
+if [ ! -d "$CWD" ]; then
+  echo "❌ Invalid CWD: not a directory" >&2
+  exit 1
+fi
+if [ ! -d "$CWD/.claude" ]; then
+  echo "❌ Invalid CWD: missing .claude directory" >&2
+  exit 1
+fi
+# Optional: pin writes to the *actual* current directory
+if [ "$(cd "$CWD" && pwd -P)" != "$(pwd -P)" ]; then
+  echo "❌ Invalid CWD: does not match current working directory" >&2
+  exit 1
+fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Validate SESSION_ID to prevent path traversal
if [[ "$SESSION_ID" =~ [^a-zA-Z0-9_-] ]]; then
echo "❌ Invalid session_id: contains disallowed characters" >&2
exit 1
fi
# Validate session_id format (alphanumeric, hyphen, underscore only)
if ! [[ "$SESSION_ID" =~ ^[a-zA-Z0-9_-]+$ ]]; then
echo "❌ Invalid session_id format" >&2
exit 1
fi
# Validate CWD is not empty
if [ -z "$CWD" ]; then
echo "❌ CWD is empty" >&2
exit 1
fi
# Validate SESSION_ID to prevent path traversal
if [[ "$SESSION_ID" =~ [^a-zA-Z0-9_-] ]]; then
echo "❌ Invalid session_id: contains disallowed characters" >&2
exit 1
fi
# Validate session_id format (alphanumeric, hyphen, underscore only)
if ! [[ "$SESSION_ID" =~ ^[a-zA-Z0-9_-]+$ ]]; then
echo "❌ Invalid session_id format" >&2
exit 1
fi
# Validate CWD is a safe directory
if [[ "$CWD" =~ \.\. ]]; then
echo "❌ Invalid CWD: path traversal detected" >&2
exit 1
fi
if [ ! -d "$CWD" ]; then
echo "❌ Invalid CWD: not a directory" >&2
exit 1
fi
if [ ! -d "$CWD/.claude" ]; then
echo "❌ Invalid CWD: missing .claude directory" >&2
exit 1
fi
# Optional: pin writes to the *actual* current directory
if [ "$(cd "$CWD" && pwd -P)" != "$(pwd -P)" ]; then
echo "❌ Invalid CWD: does not match current working directory" >&2
exit 1
fi
🤖 Prompt for AI Agents
In @.claude/hooks/post-coder-standards-check.sh around lines 17 - 34, Current
checks validate SESSION_ID but trust CWD; update the script to harden CWD before
any writes: resolve CWD to an absolute canonical path (realpath or readlink -f),
verify it is a directory (-d), confirm it contains a ".claude" subdirectory, and
ensure the canonical CWD is under the expected workspace root (for example $PWD
or a configured WORKSPACE_ROOT) to prevent path traversal or writes outside the
repo; additionally reject or fail if the resolved path differs from the original
due to symlinks (prevent symlink traversal) and optionally verify ownership
matches the current user (stat/uid) before proceeding.

Comment on lines +23 to +34
# Validate CWD is not empty
if [ -z "$CWD" ]; then
echo "CWD is empty" >&2
exit 1
fi

# Validate CWD does not contain path traversal sequences
if [[ "$CWD" =~ \.\. ]]; then
echo "Invalid CWD: path traversal detected" >&2
exit 1
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

CWD validation still enables redirected writes; pin to workspace/current dir.

Same core issue: .cwd is trusted. Consider verifying CWD equals pwd -P (or is under an allowed root) and contains .claude/ before writing under $CWD/.claude/.state.

Comment on lines +24 to +35
# Validate CWD is not empty
if [ -z "$CWD" ]; then
echo "❌ CWD is empty" >&2
exit 1
fi

# Validate CWD does not contain path traversal sequences
if [[ "$CWD" =~ \.\. ]]; then
echo "❌ Invalid CWD: path traversal detected" >&2
exit 1
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

CWD validation still allows writing outside the repo/workspace.

Rejecting .. helps, but an absolute path like /tmp/somewhere (or a symlinked dir) can still be used to redirect state writes. Consider verifying CWD matches pwd -P (or realpath is under a known workspace root) and that $CWD/.claude exists.

🤖 Prompt for AI Agents
In @.claude/hooks/post-test-consistency-validator.sh around lines 24 - 35, The
CWD validation currently only rejects '..' but still allows absolute or
symlinked paths outside the workspace; update the validator to resolve CWD to
its physical path (using pwd -P or realpath) and verify that the resolved CWD is
inside the expected workspace root (or equals `pwd -P`), and additionally check
that the directory contains the required marker `.claude` (i.e., ensure
`$CWD/.claude` exists and is a directory/file); if either check fails, print a
clear error and exit non‑zero.

Comment thread .claude/scripts/crash.py
Comment on lines +31 to +36
def load_state():
"""Load the current session state from disk."""
if os.path.exists(STATE_FILE):
with open(STATE_FILE, 'r') as f:
return json.load(f)
return None

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Add error handling for corrupt JSON state file.

If the state file exists but contains invalid JSON, json.load() will raise an unhandled JSONDecodeError, causing the script to crash. This could happen if the file is corrupted or manually edited.

🛡️ Proposed fix to handle JSON decode errors
 def load_state():
     """Load the current session state from disk."""
     if os.path.exists(STATE_FILE):
-        with open(STATE_FILE, 'r') as f:
-            return json.load(f)
+        try:
+            with open(STATE_FILE, 'r') as f:
+                return json.load(f)
+        except json.JSONDecodeError:
+            print(f"ERROR: State file {STATE_FILE} is corrupted.", file=sys.stderr)
+            print("Use 'crash.py cancel' to reset, or manually delete the file.", file=sys.stderr)
+            sys.exit(1)
     return None
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def load_state():
"""Load the current session state from disk."""
if os.path.exists(STATE_FILE):
with open(STATE_FILE, 'r') as f:
return json.load(f)
return None
def load_state():
"""Load the current session state from disk."""
if os.path.exists(STATE_FILE):
try:
with open(STATE_FILE, 'r') as f:
return json.load(f)
except json.JSONDecodeError:
print(f"ERROR: State file {STATE_FILE} is corrupted.", file=sys.stderr)
print("Use 'crash.py cancel' to reset, or manually delete the file.", file=sys.stderr)
sys.exit(1)
return None
🤖 Prompt for AI Agents
In @.claude/scripts/crash.py around lines 31 - 36, The load_state function
should gracefully handle corrupt JSON in STATE_FILE: wrap json.load(f) in a
try/except that catches json.JSONDecodeError (and optionally ValueError), log an
error including the filename and exception (use existing logger or print if
none), optionally move/rename or back up the corrupted STATE_FILE for
inspection, and return None instead of letting the exception propagate; keep the
function name load_state and the STATE_FILE symbol so the change is easy to
locate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant