codecruise 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +111 -0
  3. package/bin/codecruise.js +68 -0
  4. package/config/CLAUDE.md +107 -0
  5. package/config/agents/analyst.md +48 -0
  6. package/config/agents/architect-reviewer.md +161 -0
  7. package/config/agents/architect.md +119 -0
  8. package/config/agents/critic.md +63 -0
  9. package/config/agents/developer.md +96 -0
  10. package/config/agents/devops.md +81 -0
  11. package/config/agents/orchestrator.md +91 -0
  12. package/config/agents/planner.md +139 -0
  13. package/config/agents/retro.md +52 -0
  14. package/config/agents/reviewer.md +101 -0
  15. package/config/agents/security-reviewer.md +57 -0
  16. package/config/agents/stack/expo/AGENT.md +473 -0
  17. package/config/agents/stack/expo/rules/critical.md +427 -0
  18. package/config/agents/stack/expo/rules/native.md +455 -0
  19. package/config/agents/stack/expo/rules/navigation.md +445 -0
  20. package/config/agents/stack/expo/rules/performance.md +415 -0
  21. package/config/agents/stack/fastify/AGENT.md +397 -0
  22. package/config/agents/stack/fastify/rules/api-design.md +283 -0
  23. package/config/agents/stack/fastify/rules/critical.md +232 -0
  24. package/config/agents/stack/fastify/rules/queues.md +303 -0
  25. package/config/agents/stack/fastify/rules/security.md +384 -0
  26. package/config/agents/stack/index.yaml +48 -0
  27. package/config/agents/stack/nextjs/AGENT.md +421 -0
  28. package/config/agents/stack/nextjs/rules/components.md +413 -0
  29. package/config/agents/stack/nextjs/rules/critical.md +391 -0
  30. package/config/agents/stack/nextjs/rules/performance.md +403 -0
  31. package/config/agents/stack/nextjs/rules/styling.md +334 -0
  32. package/config/agents/stack/shared-ts/AGENT.md +384 -0
  33. package/config/agents/stack/shared-ts/rules/critical.md +315 -0
  34. package/config/agents/stack/shared-ts/rules/patterns.md +384 -0
  35. package/config/agents/stack/shared-ts/rules/zod.md +427 -0
  36. package/config/agents/tester.md +79 -0
  37. package/config/commands/architect-discuss.md +366 -0
  38. package/config/commands/architect-list.md +160 -0
  39. package/config/commands/architect-review.md +111 -0
  40. package/config/commands/architect.md +118 -0
  41. package/config/commands/compact.md +118 -0
  42. package/config/commands/companion.md +279 -0
  43. package/config/commands/dashboard.md +152 -0
  44. package/config/commands/doctor.md +227 -0
  45. package/config/commands/dogfood-report.md +101 -0
  46. package/config/commands/flags/run-autonomous.md +110 -0
  47. package/config/commands/flags/run-pause.md +80 -0
  48. package/config/commands/ingest.md +173 -0
  49. package/config/commands/init.md +128 -0
  50. package/config/commands/metrics.md +87 -0
  51. package/config/commands/parallel.md +320 -0
  52. package/config/commands/pause.md +55 -0
  53. package/config/commands/plan-review.md +130 -0
  54. package/config/commands/plan.md +216 -0
  55. package/config/commands/production-check.md +308 -0
  56. package/config/commands/refine.md +323 -0
  57. package/config/commands/resume.md +72 -0
  58. package/config/commands/retro.md +121 -0
  59. package/config/commands/retry.md +75 -0
  60. package/config/commands/role.md +310 -0
  61. package/config/commands/run.md +417 -0
  62. package/config/commands/scope.md +85 -0
  63. package/config/commands/setup-permissions.md +104 -0
  64. package/config/commands/skip.md +75 -0
  65. package/config/commands/spec-forge.md +213 -0
  66. package/config/commands/spec-help.md +194 -0
  67. package/config/commands/spec-patch.md +342 -0
  68. package/config/commands/spec-resolve.md +110 -0
  69. package/config/commands/spec-review.md +153 -0
  70. package/config/commands/status.md +114 -0
  71. package/config/commands/sync.md +131 -0
  72. package/config/commands/task.md +138 -0
  73. package/config/commands/verify.md +124 -0
  74. package/config/hooks/README.md +632 -0
  75. package/config/hooks/activity-log.sh +187 -0
  76. package/config/hooks/anti-rationalize.sh +52 -0
  77. package/config/hooks/capture-verification.sh +112 -0
  78. package/config/hooks/collect-metrics.sh +135 -0
  79. package/config/hooks/enforce-file-scope.sh +75 -0
  80. package/config/hooks/enforce-state-machine.sh +161 -0
  81. package/config/hooks/enforce-tdd.sh +180 -0
  82. package/config/hooks/format.sh +40 -0
  83. package/config/hooks/lib/activity-helpers.sh +162 -0
  84. package/config/hooks/lib/read-settings.sh +71 -0
  85. package/config/hooks/load-context-skills.sh +95 -0
  86. package/config/hooks/notify.sh +81 -0
  87. package/config/hooks/pre-commit.sample +35 -0
  88. package/config/hooks/protect-files.sh +63 -0
  89. package/config/hooks/track-agents.sh +41 -0
  90. package/config/hooks/track-commands.sh +37 -0
  91. package/config/hooks/track-enforcement.sh +44 -0
  92. package/config/hooks/track-ooda.sh +77 -0
  93. package/config/hooks/validate-commit-msg.sh +35 -0
  94. package/config/hooks/validate-plan.sh +213 -0
  95. package/config/hooks/verify-criteria.sh +46 -0
  96. package/config/hooks/verify-todo-completion.sh +140 -0
  97. package/config/rules/comments.md +25 -0
  98. package/config/rules/decision-rules.md +308 -0
  99. package/config/rules/hygiene.md +247 -0
  100. package/config/rules/pattern-detection.md +372 -0
  101. package/config/rules/profiles.md +193 -0
  102. package/config/rules/recovery.md +83 -0
  103. package/config/rules/scope-detection.md +213 -0
  104. package/config/rules/standards.md +127 -0
  105. package/config/rules/workflow.md +121 -0
  106. package/config/schemas.md +767 -0
  107. package/config/settings.json +195 -0
  108. package/config/skills/backend/SKILL.md +734 -0
  109. package/config/skills/database/SKILL.md +426 -0
  110. package/config/skills/frontend/SKILL.md +434 -0
  111. package/config/skills/git/SKILL.md +396 -0
  112. package/config/skills/index.yaml +36 -0
  113. package/config/skills/observability/SKILL.md +430 -0
  114. package/config/skills/package-dev/SKILL.md +498 -0
  115. package/config/skills/performance/SKILL.md +378 -0
  116. package/config/skills/resilience/SKILL.md +573 -0
  117. package/config/skills/testing/SKILL.md +398 -0
  118. package/config/skills/testing-patterns/SKILL.md +276 -0
  119. package/config/skills/typescript/SKILL.md +152 -0
  120. package/config/templates/CLAUDE.md +70 -0
  121. package/config/templates/README.md +117 -0
  122. package/config/templates/steering/adr-template.md +102 -0
  123. package/config/templates/steering/product.md +60 -0
  124. package/config/templates/steering/rfc-template.md +159 -0
  125. package/config/templates/steering/structure.md +146 -0
  126. package/config/templates/steering/tech.md +85 -0
  127. package/package.json +40 -0
  128. package/src/install.js +163 -0
  129. package/src/report.js +310 -0
@@ -0,0 +1,95 @@
1
+ #!/bin/bash
2
+ # SessionStart hook - Loads relevant skills based on current TODO context
3
+ #
4
+ # P2: Context-aware skill loading
5
+ #
6
+ # Reads current TODO from progress.yaml, checks file patterns,
7
+ # and outputs relevant skill content to inject into Claude's context.
8
+ #
9
+ # Skill triggers:
10
+ # - .ts/.tsx files → TypeScript skill
11
+ # - React/Next.js patterns → Frontend skill
12
+ # - API/route files → Backend skill
13
+ # - Prisma/database files → Database skill
14
+ # - Test files → Testing skill
15
+
16
+ # Check if we're in a codecruise project
17
+ if [[ ! -f "progress.yaml" ]]; then
18
+ exit 0
19
+ fi
20
+
21
+ # Get current TODO
22
+ CURRENT_TODO=$(grep -A5 "current:" progress.yaml 2>/dev/null | grep "todo:" | sed 's/.*todo: //' | tr -d ' "' || echo "")
23
+
24
+ if [[ -z "$CURRENT_TODO" || "$CURRENT_TODO" == "null" ]]; then
25
+ exit 0
26
+ fi
27
+
28
+ # Find the roadmap file containing this TODO
29
+ ROADMAP_FILE=$(grep -rl "id: $CURRENT_TODO" roadmap/ 2>/dev/null | head -1 || echo "")
30
+
31
+ if [[ -z "$ROADMAP_FILE" ]]; then
32
+ exit 0
33
+ fi
34
+
35
+ # Extract files from TODO
36
+ TODO_FILES=$(awk "/id: $CURRENT_TODO/,/^[[:space:]]*- id:/" "$ROADMAP_FILE" | grep -E "^\s+-\s+" | grep -v "id:" | sed 's/.*- //' || echo "")
37
+
38
+ # Determine which skills to load based on file patterns
39
+ SKILLS_TO_LOAD=""
40
+
41
+ # Check file patterns
42
+ for file in $TODO_FILES; do
43
+ # TypeScript
44
+ if [[ "$file" == *.ts || "$file" == *.tsx ]]; then
45
+ SKILLS_TO_LOAD="$SKILLS_TO_LOAD typescript"
46
+ fi
47
+
48
+ # Frontend (React/Next.js)
49
+ if [[ "$file" == *"/components/"* || "$file" == *"/app/"* || "$file" == *"/pages/"* || "$file" == *.tsx ]]; then
50
+ SKILLS_TO_LOAD="$SKILLS_TO_LOAD frontend"
51
+ fi
52
+
53
+ # Backend (API routes)
54
+ if [[ "$file" == *"/api/"* || "$file" == *"/routes/"* || "$file" == *"/server/"* || "$file" == *"/services/"* ]]; then
55
+ SKILLS_TO_LOAD="$SKILLS_TO_LOAD backend"
56
+ fi
57
+
58
+ # Database
59
+ if [[ "$file" == *"prisma"* || "$file" == *"/db/"* || "$file" == *"/database/"* || "$file" == *"/models/"* ]]; then
60
+ SKILLS_TO_LOAD="$SKILLS_TO_LOAD database"
61
+ fi
62
+
63
+ # Testing
64
+ if [[ "$file" == *.test.* || "$file" == *.spec.* || "$file" == *"__tests__"* ]]; then
65
+ SKILLS_TO_LOAD="$SKILLS_TO_LOAD testing"
66
+ fi
67
+ done
68
+
69
+ # Remove duplicates
70
+ SKILLS_TO_LOAD=$(echo "$SKILLS_TO_LOAD" | tr ' ' '\n' | sort -u | tr '\n' ' ')
71
+
72
+ # Output loaded skills (this gets injected into Claude's context)
73
+ if [[ -n "$SKILLS_TO_LOAD" ]]; then
74
+ echo "=== Context Skills Loaded for TODO: $CURRENT_TODO ==="
75
+ echo ""
76
+
77
+ for skill in $SKILLS_TO_LOAD; do
78
+ SKILL_FILE="$HOME/.claude/skills/${skill}/patterns.md"
79
+ SKILL_FILE_ALT="$HOME/.claude/skills/${skill}.md"
80
+
81
+ if [[ -f "$SKILL_FILE" ]]; then
82
+ echo "--- $skill patterns ---"
83
+ head -100 "$SKILL_FILE" # First 100 lines to avoid context bloat
84
+ echo ""
85
+ elif [[ -f "$SKILL_FILE_ALT" ]]; then
86
+ echo "--- $skill patterns ---"
87
+ head -100 "$SKILL_FILE_ALT"
88
+ echo ""
89
+ fi
90
+ done
91
+
92
+ echo "=== End Context Skills ==="
93
+ fi
94
+
95
+ exit 0
@@ -0,0 +1,81 @@
1
+ #!/bin/bash
2
+ # Sends notifications to configured channel
3
+ # Used by autonomous mode for blockers, completions, and alerts
4
+
5
+ INPUT=$(cat)
6
+ EVENT_TYPE=$(echo "$INPUT" | jq -r '.event // "info"')
7
+ MESSAGE=$(echo "$INPUT" | jq -r '.message // "Notification from codecruise"')
8
+ TODO_ID=$(echo "$INPUT" | jq -r '.todo_id // empty')
9
+ CHANNEL=${PILOT_NOTIFY_CHANNEL:-none}
10
+
11
+ # Skip if no channel configured
12
+ if [[ "$CHANNEL" == "none" || -z "$CHANNEL" ]]; then
13
+ exit 0
14
+ fi
15
+
16
+ # Build notification payload
17
+ EMOJI="ℹ️"
18
+ case "$EVENT_TYPE" in
19
+ blocker)
20
+ EMOJI="🚨"
21
+ ;;
22
+ complete)
23
+ EMOJI="✅"
24
+ ;;
25
+ error)
26
+ EMOJI="❌"
27
+ ;;
28
+ warning)
29
+ EMOJI="⚠️"
30
+ ;;
31
+ esac
32
+
33
+ PAYLOAD="$EMOJI PILOT: $MESSAGE"
34
+ if [[ -n "$TODO_ID" ]]; then
35
+ PAYLOAD="$PAYLOAD\n📍 TODO: $TODO_ID"
36
+ fi
37
+
38
+ case "$CHANNEL" in
39
+ slack)
40
+ if [[ -z "$SLACK_WEBHOOK_URL" ]]; then
41
+ echo "Error: SLACK_WEBHOOK_URL not set" >&2
42
+ exit 1
43
+ fi
44
+
45
+ curl -s -X POST "$SLACK_WEBHOOK_URL" \
46
+ -H "Content-Type: application/json" \
47
+ -d "{\"text\": \"$PAYLOAD\"}" \
48
+ > /dev/null 2>&1
49
+ ;;
50
+
51
+ webhook)
52
+ if [[ -z "$PILOT_WEBHOOK_URL" ]]; then
53
+ echo "Error: PILOT_WEBHOOK_URL not set" >&2
54
+ exit 1
55
+ fi
56
+
57
+ curl -s -X POST "$PILOT_WEBHOOK_URL" \
58
+ -H "Content-Type: application/json" \
59
+ -d "{\"event\": \"$EVENT_TYPE\", \"message\": \"$MESSAGE\", \"todo_id\": \"$TODO_ID\", \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" \
60
+ > /dev/null 2>&1
61
+ ;;
62
+
63
+ telegram)
64
+ if [[ -z "$TELEGRAM_BOT_TOKEN" || -z "$TELEGRAM_CHAT_ID" ]]; then
65
+ echo "Error: TELEGRAM_BOT_TOKEN or TELEGRAM_CHAT_ID not set" >&2
66
+ exit 1
67
+ fi
68
+
69
+ curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage" \
70
+ -H "Content-Type: application/json" \
71
+ -d "{\"chat_id\": \"$TELEGRAM_CHAT_ID\", \"text\": \"$PAYLOAD\", \"parse_mode\": \"HTML\"}" \
72
+ > /dev/null 2>&1
73
+ ;;
74
+
75
+ *)
76
+ echo "Unknown notification channel: $CHANNEL" >&2
77
+ exit 1
78
+ ;;
79
+ esac
80
+
81
+ exit 0
@@ -0,0 +1,35 @@
1
+ #!/bin/sh
2
+ # Pre-commit hook - runs quality checks before allowing commit
3
+ #
4
+ # Installation:
5
+ # cp ~/.claude/hooks/pre-commit.sample .git/hooks/pre-commit
6
+ # chmod +x .git/hooks/pre-commit
7
+ #
8
+ # Or with Husky:
9
+ # npx husky add .husky/pre-commit "npm run check"
10
+
11
+ # Detect package manager and run quality command
12
+ if [ -f "package.json" ]; then
13
+ if [ -f "pnpm-lock.yaml" ]; then
14
+ pnpm run check || exit 1
15
+ elif [ -f "yarn.lock" ]; then
16
+ yarn check || exit 1
17
+ elif [ -f "bun.lockb" ]; then
18
+ bun run check || exit 1
19
+ else
20
+ npm run check || exit 1
21
+ fi
22
+ elif [ -f "pyproject.toml" ]; then
23
+ # Python projects
24
+ if command -v ruff &> /dev/null; then
25
+ ruff check . || exit 1
26
+ fi
27
+ if command -v mypy &> /dev/null; then
28
+ mypy . || exit 1
29
+ fi
30
+ if command -v pytest &> /dev/null; then
31
+ pytest --tb=short || exit 1
32
+ fi
33
+ fi
34
+
35
+ echo "✓ Pre-commit checks passed"
@@ -0,0 +1,63 @@
1
+ #!/bin/bash
2
+ # PreToolUse hook - blocks modification of critical files
3
+ # Prevents accidental corruption of state, secrets, and lock files
4
+
5
+ INPUT=$(cat)
6
+ TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty')
7
+ FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
8
+
9
+ # Skip if not a write operation
10
+ if [[ "$TOOL" != "Edit" && "$TOOL" != "Write" ]]; then
11
+ exit 0
12
+ fi
13
+
14
+ # Skip if no file path
15
+ if [[ -z "$FILE" ]]; then
16
+ exit 0
17
+ fi
18
+
19
+ # Default protected patterns
20
+ PROTECTED=(
21
+ "progress.yaml"
22
+ "roadmap/"
23
+ ".env"
24
+ ".env.*"
25
+ "package-lock.json"
26
+ "pnpm-lock.yaml"
27
+ "yarn.lock"
28
+ "Gemfile.lock"
29
+ "poetry.lock"
30
+ "Cargo.lock"
31
+ ".git/"
32
+ ".ssh/"
33
+ ".aws/"
34
+ ".gnupg/"
35
+ "credentials"
36
+ "secrets"
37
+ )
38
+
39
+ # Add custom patterns from environment
40
+ if [[ -n "$PILOT_PROTECTED_FILES" ]]; then
41
+ IFS=',' read -ra CUSTOM <<< "$PILOT_PROTECTED_FILES"
42
+ PROTECTED+=("${CUSTOM[@]}")
43
+ fi
44
+
45
+ # Check if file matches any protected pattern
46
+ for pattern in "${PROTECTED[@]}"; do
47
+ # Handle glob patterns
48
+ if [[ "$FILE" == *"$pattern"* ]]; then
49
+ cat <<EOF
50
+ {
51
+ "hookSpecificOutput": {
52
+ "hookEventName": "PreToolUse",
53
+ "permissionDecision": "deny",
54
+ "permissionDecisionReason": "Cannot modify protected file matching pattern: $pattern. Use dedicated commands (/run, /found) or edit config/hooks/protect-files.sh to adjust."
55
+ }
56
+ }
57
+ EOF
58
+ exit 0
59
+ fi
60
+ done
61
+
62
+ # Allow the operation
63
+ exit 0
@@ -0,0 +1,41 @@
1
+ #!/bin/bash
2
+ # track-agents.sh — PostToolUse hook for tracking agent delegations
3
+ #
4
+ # Logs when Task tool is used to spawn subagents
5
+ # Answers: "Which of the 12 agents actually get used?"
6
+ #
7
+ # Writes to .codecruise/metrics/agents.jsonl
8
+
9
+ AGENTS_LOG="${CODECRUISE_AGENTS_LOG:-.codecruise/metrics/agents.jsonl}"
10
+
11
+ mkdir -p "$(dirname "$AGENTS_LOG")"
12
+
13
+ INPUT=$(cat)
14
+
15
+ TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty')
16
+
17
+ # Only track Task tool usage (agent delegation)
18
+ if [[ "$TOOL_NAME" != "Task" ]]; then
19
+ exit 0
20
+ fi
21
+
22
+ TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
23
+ PROJECT=$(basename "$PWD")
24
+
25
+ # Extract agent info from tool input
26
+ SUBAGENT_TYPE=$(echo "$INPUT" | jq -r '.tool_input.subagent_type // "unknown"')
27
+ DESCRIPTION=$(echo "$INPUT" | jq -r '.tool_input.description // ""' | cut -c1-100)
28
+ MODEL=$(echo "$INPUT" | jq -r '.tool_input.model // "default"')
29
+
30
+ # Get current TODO if available
31
+ CURRENT_TODO=""
32
+ if [[ -f "progress.yaml" ]]; then
33
+ CURRENT_TODO=$(grep -oE "todo-[0-9]+\.[0-9]+[a-z]?-[0-9]+" progress.yaml 2>/dev/null | head -1 || echo "")
34
+ fi
35
+
36
+ # Escape description for JSON
37
+ ESCAPED_DESC=$(echo "$DESCRIPTION" | sed 's/"/\\"/g')
38
+
39
+ echo "{\"timestamp\":\"$TIMESTAMP\",\"project\":\"$PROJECT\",\"agent\":\"$SUBAGENT_TYPE\",\"model\":\"$MODEL\",\"todo\":\"$CURRENT_TODO\",\"description\":\"$ESCAPED_DESC\"}" >> "$AGENTS_LOG"
40
+
41
+ exit 0
@@ -0,0 +1,37 @@
1
+ #!/bin/bash
2
+ # track-commands.sh — Tracks which codecruise commands are actually used
3
+ #
4
+ # PostToolUse hook that detects Skill tool invocations
5
+ # Answers: "Which of the 34 commands actually get used?"
6
+ #
7
+ # Writes to .codecruise/metrics/commands.jsonl
8
+
9
+ COMMANDS_LOG="${CODECRUISE_COMMANDS_LOG:-.codecruise/metrics/commands.jsonl}"
10
+
11
+ mkdir -p "$(dirname "$COMMANDS_LOG")"
12
+
13
+ INPUT=$(cat)
14
+
15
+ TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty')
16
+
17
+ # Only track Skill tool usage (command invocation)
18
+ if [[ "$TOOL_NAME" != "Skill" ]]; then
19
+ exit 0
20
+ fi
21
+
22
+ TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
23
+ PROJECT=$(basename "$PWD")
24
+
25
+ # Extract command info
26
+ SKILL_NAME=$(echo "$INPUT" | jq -r '.tool_input.skill // "unknown"')
27
+ ARGS=$(echo "$INPUT" | jq -r '.tool_input.args // ""' | cut -c1-50)
28
+
29
+ # Get current TODO if available
30
+ CURRENT_TODO=""
31
+ if [[ -f "progress.yaml" ]]; then
32
+ CURRENT_TODO=$(grep -oE "todo-[0-9]+\.[0-9]+[a-z]?-[0-9]+" progress.yaml 2>/dev/null | head -1 || echo "")
33
+ fi
34
+
35
+ echo "{\"timestamp\":\"$TIMESTAMP\",\"project\":\"$PROJECT\",\"command\":\"$SKILL_NAME\",\"args\":\"$ARGS\",\"todo\":\"$CURRENT_TODO\"}" >> "$COMMANDS_LOG"
36
+
37
+ exit 0
@@ -0,0 +1,44 @@
1
+ #!/bin/bash
2
+ # track-enforcement.sh — Logs enforcement events for dogfooding analysis
3
+ #
4
+ # Called by other hooks when they block or warn
5
+ # Writes to .codecruise/metrics/enforcement.jsonl
6
+ #
7
+ # Usage (from other hooks):
8
+ # source "$(dirname "$0")/track-enforcement.sh"
9
+ # track_enforcement "tdd_block" "No test file for src/auth.ts"
10
+ # track_enforcement "rationalization_caught" "detected: 'good enough for now'"
11
+ # track_enforcement "state_invalid" "pending -> done not allowed"
12
+ # track_enforcement "quality_block" "tests failed, cannot mark done"
13
+
14
+ ENFORCEMENT_LOG="${CODECRUISE_ENFORCEMENT_LOG:-.codecruise/metrics/enforcement.jsonl}"
15
+
16
+ track_enforcement() {
17
+ local event_type="$1"
18
+ local detail="$2"
19
+ local hook_name="${3:-unknown}"
20
+
21
+ mkdir -p "$(dirname "$ENFORCEMENT_LOG")"
22
+
23
+ local timestamp
24
+ timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
25
+
26
+ # Get current TODO if available
27
+ local current_todo=""
28
+ if [[ -f "progress.yaml" ]]; then
29
+ current_todo=$(grep -oE "todo-[0-9]+\.[0-9]+[a-z]?-[0-9]+" progress.yaml 2>/dev/null | head -1 || echo "")
30
+ fi
31
+
32
+ # Get project name from directory
33
+ local project
34
+ project=$(basename "$PWD")
35
+
36
+ # Escape detail for JSON
37
+ local escaped_detail
38
+ escaped_detail=$(echo "$detail" | sed 's/"/\\"/g' | tr '\n' ' ')
39
+
40
+ echo "{\"timestamp\":\"$timestamp\",\"project\":\"$project\",\"event\":\"$event_type\",\"hook\":\"$hook_name\",\"todo\":\"$current_todo\",\"detail\":\"$escaped_detail\"}" >> "$ENFORCEMENT_LOG"
41
+ }
42
+
43
+ # Export function for sourcing
44
+ export -f track_enforcement 2>/dev/null || true
@@ -0,0 +1,77 @@
1
+ #!/bin/bash
2
+ # track-ooda.sh — Tracks OODA loop phases and decisions
3
+ #
4
+ # PostToolUse hook that detects OODA-related patterns in tool results
5
+ # Answers: "Is OODA's ORIENT phase actually calculating meaningful confidence?"
6
+ #
7
+ # Detects patterns like:
8
+ # - "OBSERVE:" / "ORIENT:" / "DECIDE:" / "ACT:" in outputs
9
+ # - Confidence levels mentioned
10
+ # - Decisions made (execute, skip, replan, escalate)
11
+ #
12
+ # Writes to .codecruise/metrics/ooda.jsonl
13
+
14
+ OODA_LOG="${CODECRUISE_OODA_LOG:-.codecruise/metrics/ooda.jsonl}"
15
+
16
+ mkdir -p "$(dirname "$OODA_LOG")"
17
+
18
+ INPUT=$(cat)
19
+
20
+ TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty')
21
+ TOOL_RESULT=$(echo "$INPUT" | jq -r '.tool_result // empty' 2>/dev/null || echo "")
22
+
23
+ # Skip if no result to analyze
24
+ if [[ -z "$TOOL_RESULT" ]]; then
25
+ exit 0
26
+ fi
27
+
28
+ TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
29
+ PROJECT=$(basename "$PWD")
30
+
31
+ # Get current TODO
32
+ CURRENT_TODO=""
33
+ if [[ -f "progress.yaml" ]]; then
34
+ CURRENT_TODO=$(grep -oE "todo-[0-9]+\.[0-9]+[a-z]?-[0-9]+" progress.yaml 2>/dev/null | head -1 || echo "")
35
+ fi
36
+
37
+ # Detect OODA phases in output
38
+ PHASE=""
39
+ if echo "$TOOL_RESULT" | grep -qiE "OBSERVE:"; then
40
+ PHASE="observe"
41
+ elif echo "$TOOL_RESULT" | grep -qiE "ORIENT:"; then
42
+ PHASE="orient"
43
+ elif echo "$TOOL_RESULT" | grep -qiE "DECIDE:"; then
44
+ PHASE="decide"
45
+ elif echo "$TOOL_RESULT" | grep -qiE "ACT:"; then
46
+ PHASE="act"
47
+ fi
48
+
49
+ # Skip if no OODA phase detected
50
+ if [[ -z "$PHASE" ]]; then
51
+ exit 0
52
+ fi
53
+
54
+ # Extract confidence if in ORIENT phase
55
+ CONFIDENCE=""
56
+ if [[ "$PHASE" == "orient" ]]; then
57
+ CONFIDENCE=$(echo "$TOOL_RESULT" | grep -oiE "confidence[=: ]*(high|medium|low|[0-9.]+)" | head -1 | sed 's/.*[=: ]//')
58
+ fi
59
+
60
+ # Extract decision if in DECIDE phase
61
+ DECISION=""
62
+ if [[ "$PHASE" == "decide" ]]; then
63
+ if echo "$TOOL_RESULT" | grep -qiE "execute"; then
64
+ DECISION="execute"
65
+ elif echo "$TOOL_RESULT" | grep -qiE "skip"; then
66
+ DECISION="skip"
67
+ elif echo "$TOOL_RESULT" | grep -qiE "replan"; then
68
+ DECISION="replan"
69
+ elif echo "$TOOL_RESULT" | grep -qiE "escalate"; then
70
+ DECISION="escalate"
71
+ fi
72
+ fi
73
+
74
+ # Log the event
75
+ echo "{\"timestamp\":\"$TIMESTAMP\",\"project\":\"$PROJECT\",\"todo\":\"$CURRENT_TODO\",\"phase\":\"$PHASE\",\"confidence\":\"$CONFIDENCE\",\"decision\":\"$DECISION\"}" >> "$OODA_LOG"
76
+
77
+ exit 0
@@ -0,0 +1,35 @@
1
+ #!/bin/bash
2
+ # Validates commit message follows conventional commit format
3
+ # Used by PreToolUse hook for git commit commands
4
+ #
5
+ # Format: type(scope): description
6
+ # Types: feat, fix, docs, style, refactor, test, chore
7
+ #
8
+ # Exit codes:
9
+ # 0 - Valid commit message
10
+ # 2 - Invalid (blocks the tool)
11
+
12
+ MSG="$1"
13
+
14
+ # Pattern: type(optional-scope): description (max 50 chars for description)
15
+ PATTERN='^(feat|fix|docs|style|refactor|test|chore)(\([a-z0-9_-]+\))?: .{1,50}$'
16
+
17
+ if [[ -z "$MSG" ]]; then
18
+ # No message provided, let git handle it
19
+ exit 0
20
+ fi
21
+
22
+ if [[ ! "$MSG" =~ $PATTERN ]]; then
23
+ echo "Blocked: Commit message must follow conventional format" >&2
24
+ echo "" >&2
25
+ echo "Format: type(scope): description" >&2
26
+ echo "Types: feat, fix, docs, style, refactor, test, chore" >&2
27
+ echo "" >&2
28
+ echo "Examples:" >&2
29
+ echo " feat(auth): add password reset flow" >&2
30
+ echo " fix(cart): resolve quantity update bug" >&2
31
+ echo " docs: update README installation steps" >&2
32
+ exit 2
33
+ fi
34
+
35
+ exit 0