all-for-claudecode 2.0.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 (56) hide show
  1. package/.claude-plugin/marketplace.json +21 -0
  2. package/.claude-plugin/plugin.json +12 -0
  3. package/LICENSE +21 -0
  4. package/MIGRATION.md +180 -0
  5. package/README.md +216 -0
  6. package/agents/afc-architect.md +49 -0
  7. package/agents/afc-security.md +49 -0
  8. package/bin/cli.mjs +111 -0
  9. package/commands/analyze.md +126 -0
  10. package/commands/architect.md +142 -0
  11. package/commands/auto.md +304 -0
  12. package/commands/checkpoint.md +88 -0
  13. package/commands/clarify.md +78 -0
  14. package/commands/debug.md +126 -0
  15. package/commands/doctor.md +179 -0
  16. package/commands/implement.md +206 -0
  17. package/commands/init.md +272 -0
  18. package/commands/plan.md +195 -0
  19. package/commands/principles.md +107 -0
  20. package/commands/research.md +109 -0
  21. package/commands/resume.md +81 -0
  22. package/commands/review.md +205 -0
  23. package/commands/security.md +131 -0
  24. package/commands/spec.md +149 -0
  25. package/commands/tasks.md +137 -0
  26. package/commands/test.md +123 -0
  27. package/docs/critic-loop-rules.md +104 -0
  28. package/docs/nfr-templates.md +40 -0
  29. package/docs/phase-gate-protocol.md +44 -0
  30. package/hooks/hooks.json +211 -0
  31. package/package.json +62 -0
  32. package/scripts/afc-auto-format.sh +70 -0
  33. package/scripts/afc-bash-guard.sh +85 -0
  34. package/scripts/afc-config-change.sh +58 -0
  35. package/scripts/afc-failure-hint.sh +78 -0
  36. package/scripts/afc-notify.sh +64 -0
  37. package/scripts/afc-parallel-validate.sh +158 -0
  38. package/scripts/afc-permission-request.sh +91 -0
  39. package/scripts/afc-pipeline-manage.sh +186 -0
  40. package/scripts/afc-preflight-check.sh +195 -0
  41. package/scripts/afc-session-end.sh +45 -0
  42. package/scripts/afc-stop-gate.sh +78 -0
  43. package/scripts/afc-subagent-context.sh +65 -0
  44. package/scripts/afc-subagent-stop.sh +60 -0
  45. package/scripts/afc-task-completed-gate.sh +66 -0
  46. package/scripts/afc-teammate-idle.sh +49 -0
  47. package/scripts/afc-timeline-log.sh +97 -0
  48. package/scripts/afc-user-prompt-submit.sh +35 -0
  49. package/scripts/pre-compact-checkpoint.sh +112 -0
  50. package/scripts/session-start-context.sh +80 -0
  51. package/scripts/track-afc-changes.sh +48 -0
  52. package/templates/afc.config.express-api.md +99 -0
  53. package/templates/afc.config.monorepo.md +98 -0
  54. package/templates/afc.config.nextjs-fsd.md +107 -0
  55. package/templates/afc.config.react-spa.md +96 -0
  56. package/templates/afc.config.template.md +90 -0
@@ -0,0 +1,66 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ # TaskCompleted Gate Hook: Block task completion while pipeline is active and CI has not passed
4
+ # Physically prevents Claude from skipping CI and completing a task
5
+ #
6
+ # Gap fix: "Prompts are not enforcement" -> Physical enforcement via exit 2
7
+
8
+ # trap: Preserve exit code on abnormal termination + stderr message
9
+ # shellcheck disable=SC2329
10
+ cleanup() {
11
+ local exit_code=$?
12
+ if [ "$exit_code" -ne 0 ] && [ "$exit_code" -ne 2 ]; then
13
+ echo "AFC TASK GATE: Abnormal exit (exit code: $exit_code)" >&2
14
+ fi
15
+ exit "$exit_code"
16
+ }
17
+ trap cleanup EXIT
18
+
19
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
20
+ PIPELINE_FLAG="${PROJECT_DIR}/.claude/.afc-active"
21
+ CI_FLAG="${PROJECT_DIR}/.claude/.afc-ci-passed"
22
+ PHASE_FLAG="${PROJECT_DIR}/.claude/.afc-phase"
23
+
24
+ # Consume stdin (required -- pipe breaks if not consumed)
25
+ cat > /dev/null
26
+
27
+ # If pipeline is not active -> pass through
28
+ if [ ! -f "$PIPELINE_FLAG" ]; then
29
+ exit 0
30
+ fi
31
+
32
+ FEATURE="$(head -1 "$PIPELINE_FLAG" | tr -d '\n\r')"
33
+
34
+ # Check current Phase if phase file exists
35
+ CURRENT_PHASE=""
36
+ if [ -f "$PHASE_FLAG" ]; then
37
+ CURRENT_PHASE="$(head -1 "$PHASE_FLAG" | tr -d '\n\r')"
38
+ fi
39
+ CURRENT_PHASE="${CURRENT_PHASE:-}"
40
+
41
+ # Spec/Plan/Tasks Phase (1-3) do not require CI -> pass through
42
+ case "${CURRENT_PHASE:-}" in
43
+ spec|plan|tasks)
44
+ exit 0
45
+ ;;
46
+ esac
47
+
48
+ # Implement/Review/Clean Phase (4-6) require CI to pass
49
+ if [ ! -f "$CI_FLAG" ]; then
50
+ echo "AFC TASK GATE: CI has not been run. Pipeline '${FEATURE:-unknown}' Phase '${CURRENT_PHASE:-unknown}' requires passing the CI gate. Run your CI command and record the timestamp in .claude/.afc-ci-passed." >&2
51
+ exit 2
52
+ fi
53
+
54
+ # Verify CI passed within the last 10 minutes (prevent stale results)
55
+ CI_TIME="$(cat "$CI_FLAG" 2>/dev/null | head -1 | tr -dc '0-9' || true)"
56
+ CI_TIME="${CI_TIME:-0}"
57
+ NOW="$(date +%s)"
58
+ if [ "$CI_TIME" -gt 0 ]; then
59
+ DIFF=$(( NOW - CI_TIME ))
60
+ if [ "$DIFF" -gt 600 ]; then
61
+ echo "AFC TASK GATE: CI results are stale (${DIFF} seconds ago). Please run your CI command again." >&2
62
+ exit 2
63
+ fi
64
+ fi
65
+
66
+ exit 0
@@ -0,0 +1,49 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ # TeammateIdle Hook: Block idle during implement/review Phase while pipeline is active
4
+ # Physically prevents Claude from stopping mid-task
5
+ #
6
+ # Gap fix: "Prompts are not enforcement" -> Physical enforcement via exit 2
7
+
8
+ # trap: Preserve exit code on abnormal termination + stderr message
9
+ # shellcheck disable=SC2329
10
+ cleanup() {
11
+ local exit_code=$?
12
+ if [ "$exit_code" -ne 0 ] && [ "$exit_code" -ne 2 ]; then
13
+ echo "AFC TEAMMATE GATE: Abnormal exit (exit code: $exit_code)" >&2
14
+ fi
15
+ exit "$exit_code"
16
+ }
17
+ trap cleanup EXIT
18
+
19
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
20
+ PIPELINE_FLAG="${PROJECT_DIR}/.claude/.afc-active"
21
+ PHASE_FLAG="${PROJECT_DIR}/.claude/.afc-phase"
22
+
23
+ # Consume stdin (required -- pipe breaks if not consumed)
24
+ cat > /dev/null
25
+
26
+ # If pipeline is not active -> pass through
27
+ if [ ! -f "$PIPELINE_FLAG" ]; then
28
+ exit 0
29
+ fi
30
+
31
+ FEATURE="$(head -1 "$PIPELINE_FLAG" | tr -d '\n\r')"
32
+
33
+ # Check current Phase if phase file exists
34
+ CURRENT_PHASE=""
35
+ if [ -f "$PHASE_FLAG" ]; then
36
+ CURRENT_PHASE="$(head -1 "$PHASE_FLAG" | tr -d '\n\r')"
37
+ fi
38
+ CURRENT_PHASE="${CURRENT_PHASE:-}"
39
+
40
+ # Block idle during implement/review Phase -> force work to continue
41
+ case "${CURRENT_PHASE:-}" in
42
+ implement|review)
43
+ echo "AFC TEAMMATE GATE: Pipeline '${FEATURE:-unknown}' Phase '${CURRENT_PHASE:-unknown}' is active. Please complete the task." >&2
44
+ exit 2
45
+ ;;
46
+ *)
47
+ exit 0
48
+ ;;
49
+ esac
@@ -0,0 +1,97 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ # JSONL Event Logger: Appends structured events to .claude/.afc-timeline.jsonl
4
+ #
5
+ # Usage:
6
+ # afc-timeline-log.sh <event_type> <message> [extra_json_fields]
7
+ #
8
+ # event_type: phase-start, phase-end, gate-pass, gate-fail, error,
9
+ # pipeline-start, pipeline-end
10
+ # message: human-readable description
11
+ # extra_json_fields: optional JSON object string to merge (e.g. '{"tool":"bash"}')
12
+
13
+ # shellcheck disable=SC2329
14
+ cleanup() {
15
+ :
16
+ }
17
+ trap cleanup EXIT
18
+
19
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
20
+ FLAG_DIR="$PROJECT_DIR/.claude"
21
+ TIMELINE_FILE="$FLAG_DIR/.afc-timeline.jsonl"
22
+ ROTATE_FILE="$FLAG_DIR/.afc-timeline.jsonl.1"
23
+ MAX_BYTES=1048576 # 1 MB
24
+
25
+ EVENT_TYPE="${1:-}"
26
+ MESSAGE="${2:-}"
27
+ EXTRA="${3:-}"
28
+
29
+ # Validate required arguments
30
+ if [ -z "$EVENT_TYPE" ] || [ -z "$MESSAGE" ]; then
31
+ printf 'Usage: %s <event_type> <message> [extra_json_fields]\n' "$0" >&2
32
+ exit 0
33
+ fi
34
+
35
+ # Sanitize inputs (strip newlines; limit length)
36
+ EVENT_TYPE=$(printf '%s' "$EVENT_TYPE" | tr -d '\n\r' | cut -c1-64)
37
+ MESSAGE=$(printf '%s' "$MESSAGE" | tr -d '\n\r' | cut -c1-500)
38
+
39
+ # Read pipeline state (gracefully handle missing files)
40
+ FEATURE="none"
41
+ PHASE="none"
42
+ if [ -f "$FLAG_DIR/.afc-active" ]; then
43
+ FEATURE=$(head -1 "$FLAG_DIR/.afc-active" | tr -d '\n\r' | cut -c1-100)
44
+ fi
45
+ if [ -f "$FLAG_DIR/.afc-phase" ]; then
46
+ PHASE=$(head -1 "$FLAG_DIR/.afc-phase" | tr -d '\n\r' | cut -c1-64)
47
+ fi
48
+
49
+ # Timestamp (no jq dependency)
50
+ TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)
51
+
52
+ # Escape a string for JSON (handle backslash, double-quote, and control chars)
53
+ json_escape() {
54
+ printf '%s' "$1" \
55
+ | sed 's/\\/\\\\/g' \
56
+ | sed 's/"/\\"/g' \
57
+ | tr -d '\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017' \
58
+ | tr -d '\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037'
59
+ }
60
+
61
+ TS_ESC=$(json_escape "$TS")
62
+ EVENT_ESC=$(json_escape "$EVENT_TYPE")
63
+ MSG_ESC=$(json_escape "$MESSAGE")
64
+ FEATURE_ESC=$(json_escape "$FEATURE")
65
+ PHASE_ESC=$(json_escape "$PHASE")
66
+
67
+ # Build the base JSON line
68
+ BASE="{\"ts\":\"${TS_ESC}\",\"event\":\"${EVENT_ESC}\",\"msg\":\"${MSG_ESC}\",\"feature\":\"${FEATURE_ESC}\",\"phase\":\"${PHASE_ESC}\"}"
69
+
70
+ # Merge extra JSON fields if provided (append before closing brace)
71
+ if [ -n "$EXTRA" ]; then
72
+ # Strip outer braces from EXTRA and append, only if it looks like a JSON object
73
+ INNER=$(printf '%s' "$EXTRA" | sed 's/^[[:space:]]*{//;s/}[[:space:]]*$//')
74
+ if [ -n "$INNER" ]; then
75
+ LINE="${BASE%\}},${INNER}}"
76
+ else
77
+ LINE="$BASE"
78
+ fi
79
+ else
80
+ LINE="$BASE"
81
+ fi
82
+
83
+ # Ensure the flag directory exists
84
+ mkdir -p "$FLAG_DIR"
85
+
86
+ # Auto-rotate if the timeline file exceeds MAX_BYTES
87
+ if [ -f "$TIMELINE_FILE" ]; then
88
+ FILE_SIZE=$(wc -c < "$TIMELINE_FILE" | tr -d ' ')
89
+ if [ "$FILE_SIZE" -ge "$MAX_BYTES" ]; then
90
+ mv "$TIMELINE_FILE" "$ROTATE_FILE"
91
+ fi
92
+ fi
93
+
94
+ # Append the JSONL line
95
+ printf '%s\n' "$LINE" >> "$TIMELINE_FILE"
96
+
97
+ exit 0
@@ -0,0 +1,35 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+
4
+ # UserPromptSubmit Hook: Inject pipeline Phase/Feature context on every prompt
5
+ # Exit 0 immediately if pipeline is inactive (minimize overhead)
6
+
7
+ # shellcheck disable=SC2329
8
+ cleanup() {
9
+ :
10
+ }
11
+ trap cleanup EXIT
12
+
13
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
14
+ PIPELINE_FLAG="$PROJECT_DIR/.claude/.afc-active"
15
+ PHASE_FLAG="$PROJECT_DIR/.claude/.afc-phase"
16
+
17
+ # Consume stdin (required -- pipe breaks if not consumed)
18
+ cat > /dev/null
19
+
20
+ # Exit silently if pipeline is inactive
21
+ if [ ! -f "$PIPELINE_FLAG" ]; then
22
+ exit 0
23
+ fi
24
+
25
+ # Read Feature/Phase + JSON-safe processing (strip special characters)
26
+ FEATURE="$(head -1 "$PIPELINE_FLAG" | tr -d '\n\r' | tr -d '"' | cut -c1-100)"
27
+ PHASE="unknown"
28
+ if [ -f "$PHASE_FLAG" ]; then
29
+ PHASE="$(head -1 "$PHASE_FLAG" | tr -d '\n\r' | tr -d '"' | cut -c1-100)"
30
+ fi
31
+
32
+ # Output additionalContext to stdout (injected into Claude context)
33
+ printf '{"hookSpecificOutput":{"additionalContext":"[Pipeline: %s] [Phase: %s]"}}\n' "$FEATURE" "$PHASE"
34
+
35
+ exit 0
@@ -0,0 +1,112 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ # Pre-Compact Hook: Auto-checkpoint before context compaction
4
+ # Prevents loss of progress state during session interruption/compaction
5
+ #
6
+ # Gap fix: Enforces OMC auto-state-save via physical script
7
+
8
+ # shellcheck disable=SC2329
9
+ cleanup() {
10
+ # Extend here if temporary file cleanup is needed
11
+ :
12
+ }
13
+ trap cleanup EXIT
14
+
15
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
16
+
17
+ # Consume stdin (required -- pipe breaks if not consumed)
18
+ cat > /dev/null
19
+
20
+ # Dynamically derive auto-memory directory from project path
21
+ PROJECT_PATH=$(cd "$PROJECT_DIR" 2>/dev/null && pwd || true)
22
+ PROJECT_PATH="${PROJECT_PATH:-$PROJECT_DIR}"
23
+ ENCODED_PATH="${PROJECT_PATH//\//-}"
24
+ MEMORY_DIR="$HOME/.claude/projects/$ENCODED_PATH/memory"
25
+ CHECKPOINT="$MEMORY_DIR/checkpoint.md"
26
+
27
+ # Create memory directory if it doesn't exist
28
+ mkdir -p "$MEMORY_DIR"
29
+
30
+ # Collect current git status
31
+ BRANCH=$(cd "$PROJECT_DIR" 2>/dev/null && git branch --show-current 2>/dev/null || echo "unknown")
32
+
33
+ ALL_MODIFIED=$(cd "$PROJECT_DIR" 2>/dev/null && git diff --name-only 2>/dev/null || true)
34
+ MODIFIED=$(printf '%s\n' "$ALL_MODIFIED" | head -10)
35
+
36
+ ALL_STAGED=$(cd "$PROJECT_DIR" 2>/dev/null && git diff --cached --name-only 2>/dev/null || true)
37
+ STAGED=$(printf '%s\n' "$ALL_STAGED" | head -10)
38
+
39
+ # Count files (capture into variable instead of piping wc -l)
40
+ MODIFIED_COUNT=0
41
+ if [ -n "$ALL_MODIFIED" ]; then
42
+ MODIFIED_RAW=$(printf '%s\n' "$ALL_MODIFIED" | wc -l)
43
+ MODIFIED_COUNT=$(printf '%s' "$MODIFIED_RAW" | tr -d ' ')
44
+ fi
45
+
46
+ STAGED_COUNT=0
47
+ if [ -n "$ALL_STAGED" ]; then
48
+ STAGED_RAW=$(printf '%s\n' "$ALL_STAGED" | wc -l)
49
+ STAGED_COUNT=$(printf '%s' "$STAGED_RAW" | tr -d ' ')
50
+ fi
51
+
52
+ # Check afc pipeline active status
53
+ PIPELINE_FLAG="$PROJECT_DIR/.claude/.afc-active"
54
+ PIPELINE_FEATURE=""
55
+ if [ -f "$PIPELINE_FLAG" ]; then
56
+ PIPELINE_FEATURE=$(head -1 "$PIPELINE_FLAG" 2>/dev/null | tr -d '\n\r' || true)
57
+ fi
58
+
59
+ # Check tasks.md progress status
60
+ TASKS_DONE=0
61
+ TASKS_TOTAL=0
62
+ if [ -n "$PIPELINE_FEATURE" ] && [ -d "$PROJECT_DIR/.claude/afc/specs/$PIPELINE_FEATURE" ]; then
63
+ TASKS_FILE="$PROJECT_DIR/.claude/afc/specs/$PIPELINE_FEATURE/tasks.md"
64
+ if [ -f "$TASKS_FILE" ]; then
65
+ TASKS_DONE=$(grep -cE '\[x\]' "$TASKS_FILE" 2>/dev/null || echo 0)
66
+ TASKS_TOTAL=$(grep -cE '\[(x| )\]' "$TASKS_FILE" 2>/dev/null || echo 0)
67
+ fi
68
+ fi
69
+
70
+ # Guard against empty lists
71
+ if [ -n "$MODIFIED" ]; then
72
+ # shellcheck disable=SC2001
73
+ MODIFIED_LIST=$(echo "$MODIFIED" | sed 's/^/ - /')
74
+ else
75
+ MODIFIED_LIST=" (none)"
76
+ fi
77
+
78
+ if [ -n "$STAGED" ]; then
79
+ # shellcheck disable=SC2001
80
+ STAGED_LIST=$(echo "$STAGED" | sed 's/^/ - /')
81
+ else
82
+ STAGED_LIST=" (none)"
83
+ fi
84
+
85
+ # Write checkpoint.md
86
+ cat > "$CHECKPOINT" << EOF
87
+ # Auto Checkpoint (Pre-Compact)
88
+ > Auto-generated: $(date '+%Y-%m-%d %H:%M:%S')
89
+ > Trigger: context compaction
90
+
91
+ ## Git Status
92
+ - Branch: $BRANCH
93
+ - Modified files: ${MODIFIED_COUNT}
94
+ $MODIFIED_LIST
95
+
96
+ ## Staged Files (${STAGED_COUNT})
97
+ $STAGED_LIST
98
+
99
+ ## Pipeline Status
100
+ - Active: $([ -f "$PIPELINE_FLAG" ] && echo "Yes ($PIPELINE_FEATURE)" || echo "No")
101
+ - Task progress: $TASKS_DONE/$TASKS_TOTAL
102
+
103
+ ## Restore Command
104
+ \`\`\`
105
+ /afc:resume
106
+ \`\`\`
107
+ EOF
108
+
109
+ # Inject context via stdout (Claude can see this info after compaction)
110
+ echo "Auto-checkpoint saved to .claude/afc/memory/checkpoint.md (branch: $BRANCH, pipeline: ${PIPELINE_FEATURE:-inactive})"
111
+
112
+ exit 0
@@ -0,0 +1,80 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+
4
+ # Session Start Hook: Restore pipeline state on session start
5
+ # Inject context so progress state is not lost after resume/compact
6
+ #
7
+ # Gap fix: Enforces OMC session continuity via physical script
8
+
9
+ # shellcheck disable=SC2329
10
+ cleanup() {
11
+ local exit_code=$?
12
+ if [ "$exit_code" -ne 0 ]; then
13
+ echo "[all-for-claudecode] session-start-context.sh exited abnormally" >&2
14
+ fi
15
+ exit "$exit_code"
16
+ }
17
+ trap cleanup EXIT
18
+
19
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
20
+
21
+ # Consume stdin (required -- pipe breaks if not consumed)
22
+ cat > /dev/null
23
+
24
+ # Dynamically derive auto-memory directory from project path
25
+ PROJECT_PATH=$(cd "$PROJECT_DIR" 2>/dev/null && pwd || echo "$PROJECT_DIR")
26
+ ENCODED_PATH="${PROJECT_PATH//\//-}"
27
+ MEMORY_DIR="$HOME/.claude/projects/$ENCODED_PATH/memory"
28
+ CHECKPOINT="$MEMORY_DIR/checkpoint.md"
29
+ PIPELINE_FLAG="$PROJECT_DIR/.claude/.afc-active"
30
+
31
+ OUTPUT=""
32
+
33
+ # 1. Check for active pipeline
34
+ if [ -f "$PIPELINE_FLAG" ]; then
35
+ FEATURE=$(head -1 "$PIPELINE_FLAG" 2>/dev/null | tr -d '\n\r' || true)
36
+ OUTPUT="[AFC PIPELINE ACTIVE] Feature: $FEATURE"
37
+
38
+ # tasks.md progress
39
+ TASKS_FILE="$PROJECT_DIR/.claude/afc/specs/$FEATURE/tasks.md"
40
+ if [ -f "$TASKS_FILE" ]; then
41
+ DONE=$(grep -cE '\[x\]' "$TASKS_FILE" 2>/dev/null || echo 0)
42
+ TOTAL=$(grep -cE '\[(x| )\]' "$TASKS_FILE" 2>/dev/null || echo 0)
43
+ OUTPUT="$OUTPUT | Tasks: $DONE/$TOTAL"
44
+ fi
45
+
46
+ # CI pass status
47
+ CI_FLAG="$PROJECT_DIR/.claude/.afc-ci-passed"
48
+ if [ -f "$CI_FLAG" ]; then
49
+ OUTPUT="$OUTPUT | Last CI: PASSED ($(cat "$CI_FLAG" 2>/dev/null || true))"
50
+ fi
51
+ fi
52
+
53
+ # 2. Check if checkpoint exists
54
+ if [ -f "$CHECKPOINT" ]; then
55
+ RAW_LINE=$(grep 'Auto-generated:' "$CHECKPOINT" 2>/dev/null || echo "")
56
+ FIRST_LINE=$(echo "$RAW_LINE" | head -1)
57
+ CHECKPOINT_DATE="${FIRST_LINE##*Auto-generated: }"
58
+ if [ -n "$CHECKPOINT_DATE" ]; then
59
+ if [ -n "$OUTPUT" ]; then
60
+ OUTPUT="$OUTPUT | Checkpoint: $CHECKPOINT_DATE"
61
+ else
62
+ OUTPUT="[CHECKPOINT EXISTS] Date: $CHECKPOINT_DATE — Run /afc:resume to restore"
63
+ fi
64
+ fi
65
+ fi
66
+
67
+ # 3. Check for safety tag
68
+ HAS_SAFETY_TAG=$(cd "$PROJECT_DIR" 2>/dev/null && git tag -l 'afc/pre-*' 2>/dev/null | head -1 || echo "")
69
+ if [ -n "$HAS_SAFETY_TAG" ]; then
70
+ if [ -n "$OUTPUT" ]; then
71
+ OUTPUT="$OUTPUT | Safety tag: $HAS_SAFETY_TAG"
72
+ fi
73
+ fi
74
+
75
+ # Output (stdout -> injected into Claude context)
76
+ if [ -n "$OUTPUT" ]; then
77
+ printf '%s\n' "$OUTPUT"
78
+ fi
79
+
80
+ exit 0
@@ -0,0 +1,48 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ # PostToolUse Hook: Track file changes
4
+ # Record changed files after Edit/Write tool usage
5
+ # Track which files have changed for the CI gate
6
+
7
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
8
+ PIPELINE_FLAG="$PROJECT_DIR/.claude/.afc-active"
9
+ CHANGES_LOG="$PROJECT_DIR/.claude/.afc-changes.log"
10
+ CI_FLAG="$PROJECT_DIR/.claude/.afc-ci-passed"
11
+
12
+ # shellcheck disable=SC2329
13
+ cleanup() {
14
+ # Placeholder for temporary resource cleanup if needed
15
+ :
16
+ }
17
+ trap cleanup EXIT
18
+
19
+ # If pipeline is inactive -> skip
20
+ if [ ! -f "$PIPELINE_FLAG" ]; then
21
+ exit 0
22
+ fi
23
+
24
+ # Parse tool input from stdin
25
+ INPUT=$(cat)
26
+
27
+ # Skip if stdin is empty
28
+ if [ -z "$INPUT" ]; then
29
+ exit 0
30
+ fi
31
+
32
+ # Extract file_path with jq if available, otherwise grep/sed fallback
33
+ if command -v jq &> /dev/null; then
34
+ FILE_PATH=$(printf '%s\n' "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null || true)
35
+ else
36
+ FILE_PATH=$(printf '%s\n' "$INPUT" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*:[[:space:]]*"//;s/"$//' 2>/dev/null || true)
37
+ fi
38
+
39
+ if [ -n "$FILE_PATH" ]; then
40
+ # Append to change log (deduplicate)
41
+ printf '%s\n' "$FILE_PATH" >> "$CHANGES_LOG"
42
+ sort -u -o "$CHANGES_LOG" "$CHANGES_LOG"
43
+
44
+ # Invalidate CI results since a file was changed
45
+ rm -f "$CI_FLAG"
46
+ fi
47
+
48
+ exit 0
@@ -0,0 +1,99 @@
1
+ # AFC Configuration
2
+
3
+ > This file defines project-specific settings for the afc command system.
4
+ > All afc commands reference this file to determine project-specific behavior.
5
+
6
+ ## CI Commands
7
+
8
+ ```yaml
9
+ ci: "npm run build && npm run lint && npm run test" # Full CI (build + lint + test)
10
+ typecheck: "npx tsc --noEmit" # Typecheck only
11
+ lint: "npx eslint src/" # Lint only
12
+ lint_fix: "npx eslint src/ --fix" # Auto-fix lint
13
+ gate: "npx tsc --noEmit && npx eslint src/" # Phase gate (run repeatedly during implement)
14
+ test: "npx jest --runInBand" # Tests
15
+ ```
16
+
17
+ ## Architecture
18
+
19
+ ```yaml
20
+ style: "Layered" # Layered architecture
21
+ layers: # Top → bottom order
22
+ - src/routes
23
+ - src/controllers
24
+ - src/services
25
+ - src/repositories
26
+ - src/models
27
+ - src/middleware
28
+ - src/lib
29
+ - src/types
30
+ - src/config
31
+ import_rule: "Upper layers (routes) depend only in order: controllers → services → repositories"
32
+ segments: []
33
+ path_alias: "@/* → ./src/*"
34
+ ```
35
+
36
+ ## Framework
37
+
38
+ ```yaml
39
+ name: "Express.js"
40
+ runtime: "Node.js (CommonJS or ESM)"
41
+ client_directive: "" # Server-only — not applicable
42
+ server_client_boundary: false # Server-only application
43
+ ```
44
+
45
+ ## Code Style
46
+
47
+ ```yaml
48
+ language: "TypeScript"
49
+ strict_mode: true
50
+ type_keyword: "type" # Use type instead of interface
51
+ import_type: true # Use import type { ... }
52
+ component_style: "" # No UI components
53
+ props_position: "" # No UI components
54
+ handler_naming: "camelCase"
55
+ boolean_naming: "is/has/can[State]"
56
+ constant_naming: "UPPER_SNAKE_CASE"
57
+ any_policy: "banned (use unknown with strict mode)"
58
+ ```
59
+
60
+ ## State Management
61
+
62
+ ```yaml
63
+ global_state: "" # Server — stateless
64
+ server_state: ""
65
+ local_state: ""
66
+ store_location: ""
67
+ query_location: ""
68
+ ```
69
+
70
+ ## Styling
71
+
72
+ ```yaml
73
+ framework: "" # Not applicable
74
+ ```
75
+
76
+ ## Testing
77
+
78
+ ```yaml
79
+ framework: "Jest + Supertest"
80
+ ```
81
+
82
+ ## Project-Specific Risks
83
+
84
+ > Project-specific risk patterns that must be checked in the Plan's RISK Critic
85
+
86
+ 1. Prisma migration and schema mismatch
87
+ 2. Express middleware ordering errors (auth → validation → handler)
88
+ 3. Missing async/await error handling (try-catch or wrapper)
89
+ 4. Runtime errors when environment variables (.env) are not set
90
+ 5. SQL injection (caution with raw queries when using Prisma)
91
+
92
+ ## Mini-Review Checklist
93
+
94
+ > Items to inspect for each file in the Mini-Review of the Implement Phase gate
95
+
96
+ 1. TypeScript strict mode violations
97
+ 2. Error handling (try-catch or asyncHandler on async routes)
98
+ 3. Input validation (type checking of req.body/params/query)
99
+ 4. Unused imports / dead code
@@ -0,0 +1,98 @@
1
+ # AFC Configuration
2
+
3
+ > This file defines project-specific settings for the afc command system.
4
+ > All afc commands reference this file to determine project-specific behavior.
5
+
6
+ ## CI Commands
7
+
8
+ ```yaml
9
+ ci: "pnpm turbo build lint test" # Full CI (lint + typecheck + build)
10
+ typecheck: "pnpm turbo typecheck" # Typecheck only
11
+ lint: "pnpm turbo lint" # Lint only
12
+ lint_fix: "pnpm turbo lint -- --fix" # Auto-fix lint
13
+ gate: "pnpm turbo typecheck lint" # Phase gate (run repeatedly during implement)
14
+ test: "pnpm turbo test" # Tests
15
+ ```
16
+
17
+ ## Architecture
18
+
19
+ ```yaml
20
+ style: "Monorepo"
21
+ layers: # Root → package order
22
+ - apps/
23
+ - packages/
24
+ import_rule: "apps/ may only import from packages/. packages/ must declare explicit dependencies (package.json)"
25
+ segments:
26
+ - apps/web # Web app
27
+ - apps/api # API server
28
+ - packages/ui # Shared UI components
29
+ - packages/config # Shared configuration (ESLint, Prettier, etc.)
30
+ - packages/tsconfig # Shared TypeScript configuration
31
+ - packages/utils # Shared utilities
32
+ path_alias: "@repo/* → packages/*"
33
+ ```
34
+
35
+ ## Framework
36
+
37
+ ```yaml
38
+ name: "Turborepo + pnpm workspace"
39
+ runtime: "Multiple (varies per app)"
40
+ client_directive: "Varies per app"
41
+ server_client_boundary: "Varies per app" # Determined by each app's framework
42
+ ```
43
+
44
+ ## Code Style
45
+
46
+ ```yaml
47
+ language: "TypeScript"
48
+ strict_mode: true
49
+ type_keyword: "type" # Use type instead of interface
50
+ import_type: true # Use import type { ... }
51
+ component_style: "PascalCase"
52
+ props_position: "above component" # Define Props type above the component
53
+ handler_naming: "handle[Event]"
54
+ boolean_naming: "is/has/can[State]"
55
+ constant_naming: "UPPER_SNAKE_CASE"
56
+ any_policy: "minimize (especially strict for shared packages)"
57
+ ```
58
+
59
+ ## State Management
60
+
61
+ ```yaml
62
+ global_state: "Varies per app"
63
+ server_state: "Varies per app"
64
+ local_state: "Varies per app"
65
+ store_location: "Within each app"
66
+ query_location: "Within each app"
67
+ ```
68
+
69
+ ## Styling
70
+
71
+ ```yaml
72
+ framework: "Varies per app (shared UI package uses Tailwind CSS)"
73
+ ```
74
+
75
+ ## Testing
76
+
77
+ ```yaml
78
+ framework: "Varies per app (Vitest or Jest)"
79
+ ```
80
+
81
+ ## Project-Specific Risks
82
+
83
+ > Project-specific risk patterns that must be checked in the Plan's RISK Critic
84
+
85
+ 1. Circular dependencies between packages (turborepo detects, but runtime errors possible)
86
+ 2. Build failures in dependent apps when shared packages change
87
+ 3. npm publish errors when pnpm workspace protocol (workspace:*) is missing
88
+ 4. tsconfig inheritance chain mismatch (extends path errors)
89
+ 5. Stale builds due to incorrect pipeline cache settings in turbo.json
90
+
91
+ ## Mini-Review Checklist
92
+
93
+ > Items to inspect for each file in the Mini-Review of the Implement Phase gate
94
+
95
+ 1. Dependency direction between packages (apps → packages only)
96
+ 2. Shared package export paths (package.json exports field)
97
+ 3. TypeScript strict mode + path alias consistency
98
+ 4. turbo.json pipeline configuration matches actual scripts