@c-d-cc/reap 0.2.2 → 0.3.1

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.
@@ -1,200 +0,0 @@
1
- #!/usr/bin/env bash
2
- # REAP SessionStart hook — injects REAP guide + Genome + current generation context into every Claude session
3
- # This script runs from the package directory but uses cwd to find the project's .reap/
4
- set -euo pipefail
5
-
6
- # Timing (node is guaranteed since REAP is an npm package)
7
- _reap_ms() { node -e 'process.stdout.write(String(Date.now()))'; }
8
- _reap_start_time=$(_reap_ms)
9
- _reap_log() {
10
- local now=$(_reap_ms)
11
- local elapsed=$(( now - _reap_start_time ))
12
- echo "[REAP hook +${elapsed}ms] $1" >&2
13
- }
14
-
15
- # Script directory (package-internal) for guide file
16
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
17
-
18
- # Project directory is cwd (where Claude Code session started)
19
- PROJECT_ROOT="$(pwd)"
20
- REAP_DIR="${PROJECT_ROOT}/.reap"
21
- CURRENT_YML="${REAP_DIR}/life/current.yml"
22
- GUIDE_FILE="${SCRIPT_DIR}/reap-guide.md"
23
- GENOME_DIR="${REAP_DIR}/genome"
24
-
25
- _reap_log "Starting..."
26
-
27
- # Check if this is a REAP project
28
- if [ ! -d "$REAP_DIR" ]; then
29
- _reap_log "Not a REAP project, exiting"
30
- exit 0
31
- fi
32
-
33
- _reap_log "REAP project detected"
34
-
35
- _reap_log "Checking auto-update..."
36
- CONFIG_FILE="${REAP_DIR}/config.yml"
37
- auto_update_message=""
38
- if [ -f "$CONFIG_FILE" ]; then
39
- auto_update=$(grep "^autoUpdate:" "$CONFIG_FILE" 2>/dev/null | sed 's/^autoUpdate: *//' | tr -d ' ' || true)
40
- if [ "$auto_update" = "true" ]; then
41
- installed=$(reap --version 2>/dev/null || echo "")
42
- latest=$(npm view @c-d-cc/reap version 2>/dev/null || echo "")
43
- if [ -n "$installed" ] && [ -n "$latest" ] && [ "$installed" != "$latest" ]; then
44
- if npm update -g @c-d-cc/reap >/dev/null 2>&1; then
45
- reap update >/dev/null 2>&1 || true
46
- auto_update_message="REAP auto-updated: v${installed} → v${latest}"
47
- fi
48
- fi
49
- fi
50
- fi
51
-
52
- _reap_log "Auto-update check done"
53
-
54
- # Read REAP guide
55
- _reap_log "Loading REAP guide..."
56
- reap_guide=""
57
- if [ -f "$GUIDE_FILE" ]; then
58
- reap_guide=$(cat "$GUIDE_FILE")
59
- fi
60
-
61
- _reap_log "Loading Genome..."
62
- # Read Genome files with tiered loading
63
- # L1 (~500 lines max): principles.md, conventions.md, constraints.md — always full load
64
- # L2 (~200 lines max): domain/*.md — full load if within budget, otherwise title+summary only
65
- L1_LIMIT=500
66
- L2_LIMIT=200
67
-
68
- genome_content=""
69
- l1_lines=0
70
- if [ -d "$GENOME_DIR" ]; then
71
- for f in "$GENOME_DIR"/principles.md "$GENOME_DIR"/conventions.md "$GENOME_DIR"/constraints.md; do
72
- if [ -f "$f" ]; then
73
- file_content=$(cat "$f")
74
- file_lines=$(echo "$file_content" | wc -l | tr -d ' ')
75
- l1_lines=$((l1_lines + file_lines))
76
- if [ "$l1_lines" -le "$L1_LIMIT" ]; then
77
- genome_content="${genome_content}\n### $(basename "$f")\n${file_content}\n"
78
- else
79
- # L1 budget exceeded — include truncated with warning
80
- genome_content="${genome_content}\n### $(basename "$f") [TRUNCATED — L1 budget exceeded, read full file directly]\n$(echo "$file_content" | head -20)\n...\n"
81
- fi
82
- fi
83
- done
84
-
85
- # L2: domain/ files
86
- if [ -d "$GENOME_DIR/domain" ]; then
87
- l2_lines=0
88
- l2_overflow=false
89
- for f in "$GENOME_DIR"/domain/*.md; do
90
- if [ -f "$f" ]; then
91
- file_content=$(cat "$f")
92
- file_lines=$(echo "$file_content" | wc -l | tr -d ' ')
93
- l2_lines=$((l2_lines + file_lines))
94
- if [ "$l2_overflow" = false ] && [ "$l2_lines" -le "$L2_LIMIT" ]; then
95
- genome_content="${genome_content}\n### domain/$(basename "$f")\n${file_content}\n"
96
- else
97
- # L2 budget exceeded — title + first line only
98
- l2_overflow=true
99
- first_line=$(echo "$file_content" | grep -m1 "^>" || echo "$file_content" | head -1)
100
- genome_content="${genome_content}\n### domain/$(basename "$f") [summary — read full file for details]\n${first_line}\n"
101
- fi
102
- fi
103
- done
104
- fi
105
- fi
106
-
107
- # Detect Genome staleness — count commits since last Genome modification
108
- genome_stale_warning=""
109
- if command -v git &>/dev/null && [ -d "$PROJECT_ROOT/.git" ]; then
110
- last_genome_commit=$(git -C "$PROJECT_ROOT" log -1 --format="%H" -- ".reap/genome/" 2>/dev/null || echo "")
111
- if [ -n "$last_genome_commit" ]; then
112
- commits_since=$(git -C "$PROJECT_ROOT" rev-list --count "${last_genome_commit}..HEAD" -- src/ tests/ package.json tsconfig.json scripts/ 2>/dev/null || echo "0")
113
- if [ "$commits_since" -gt 10 ]; then
114
- genome_stale_warning="WARNING: Genome may be stale — ${commits_since} commits since last Genome update. Consider running /reap.sync to synchronize."
115
- fi
116
- fi
117
- fi
118
-
119
- # Read strict mode from config.yml
120
- strict_mode=false
121
- CONFIG_FILE="${REAP_DIR}/config.yml"
122
- if [ -f "$CONFIG_FILE" ]; then
123
- strict_val=$(grep "^strict:" "$CONFIG_FILE" 2>/dev/null | sed 's/^strict: *//' | tr -d ' ' || true)
124
- if [ "$strict_val" = "true" ]; then
125
- strict_mode=true
126
- fi
127
- fi
128
-
129
- # Read current.yml
130
- gen_stage="none"
131
- if [ ! -f "$CURRENT_YML" ]; then
132
- generation_context="No active Generation. Run \`/reap.start\` to start one."
133
- else
134
- content=$(cat "$CURRENT_YML")
135
- if [ -z "$content" ]; then
136
- generation_context="No active Generation. Run \`/reap.start\` to start one."
137
- else
138
- # Parse YAML fields (simple grep-based, no external deps)
139
- gen_id=$(echo "$content" | grep "^id:" | sed 's/^id: *//')
140
- gen_goal=$(echo "$content" | grep "^goal:" | sed 's/^goal: *//')
141
- gen_stage=$(echo "$content" | grep "^stage:" | sed 's/^stage: *//')
142
- generation_context="Active Generation: ${gen_id} | Goal: ${gen_goal} | Stage: ${gen_stage}"
143
- fi
144
- fi
145
-
146
- # Map stage to command
147
- case "${gen_stage}" in
148
- objective) next_cmd="/reap.objective" ;;
149
- planning) next_cmd="/reap.planning" ;;
150
- implementation) next_cmd="/reap.implementation" ;;
151
- validation) next_cmd="/reap.validation" ;;
152
- completion) next_cmd="/reap.completion" ;;
153
- *) next_cmd="/reap.start" ;;
154
- esac
155
-
156
- # Escape for JSON
157
- escape_for_json() {
158
- printf '%s' "$1" | node -e 'let d="";process.stdin.on("data",c=>d+=c);process.stdin.on("end",()=>process.stdout.write(JSON.stringify(d).slice(1,-1)))'
159
- }
160
-
161
- # Build strict mode section
162
- strict_section=""
163
- if [ "$strict_mode" = true ]; then
164
- if [ "$gen_stage" = "implementation" ]; then
165
- strict_section="\n\n## Strict Mode (ACTIVE — SCOPED MODIFICATION ALLOWED)\n<HARD-GATE>\nStrict mode is enabled. Code modification is ALLOWED only within the scope of the current Generation's plan.\n- You MUST read \`.reap/life/02-planning.md\` before writing any code.\n- You may ONLY modify files and modules listed in the plan's task list.\n- Changes outside the plan's scope are BLOCKED. If you discover out-of-scope work is needed, add it to the backlog instead of implementing it.\n- If the user explicitly requests to bypass strict mode (e.g., \"override\", \"bypass strict\"), you may proceed — but inform them that strict mode is being bypassed.\n</HARD-GATE>"
166
- elif [ "$gen_stage" = "none" ]; then
167
- strict_section="\n\n## Strict Mode (ACTIVE — CODE MODIFICATION BLOCKED)\n<HARD-GATE>\nStrict mode is enabled and there is NO active Generation.\nYou MUST NOT write, edit, or create any source code files.\nAllowed actions: reading files, analyzing code, answering questions, running commands.\nTo start coding, the user must first run \`/reap.start\` and advance to the implementation stage.\nIf the user explicitly requests to bypass strict mode (e.g., \"override\", \"bypass strict\", \"just do it\"), you may proceed — but inform them that strict mode is being bypassed.\n</HARD-GATE>"
168
- else
169
- strict_section="\n\n## Strict Mode (ACTIVE — CODE MODIFICATION BLOCKED)\n<HARD-GATE>\nStrict mode is enabled. Current stage is '${gen_stage}', which is NOT the implementation stage.\nYou MUST NOT write, edit, or create any source code files.\nAllowed actions: reading files, analyzing code, answering questions, running commands, writing REAP artifacts.\nAdvance to the implementation stage via the REAP lifecycle to unlock code modification.\nIf the user explicitly requests to bypass strict mode (e.g., \"override\", \"bypass strict\", \"just do it\"), you may proceed — but inform them that strict mode is being bypassed.\n</HARD-GATE>"
170
- fi
171
- fi
172
-
173
- # Build staleness section
174
- stale_section=""
175
- if [ -n "$genome_stale_warning" ]; then
176
- stale_section="\n\n## Genome Staleness\n${genome_stale_warning}\nIf the user wants to proceed without syncing, ask: \"The Genome may be stale. Would you like to run /reap.sync now, or do it later?\" and respect their choice."
177
- fi
178
-
179
- # Build auto-update section
180
- update_section=""
181
- if [ -n "$auto_update_message" ]; then
182
- update_section="\n\n## Auto-Update\n${auto_update_message}. Tell the user: \"${auto_update_message}\""
183
- fi
184
-
185
- reap_context="<REAP_WORKFLOW>\n${reap_guide}\n\n---\n\n## Genome (Project Knowledge — treat as authoritative source of truth)\n${genome_content}\n\n---\n\n## Current State\n${generation_context}${stale_section}${strict_section}${update_section}\n\n## Rules\n1. ALL development work MUST follow the REAP lifecycle. Do NOT bypass it.\n2. Before writing any code, check if a Generation is active and what stage it is in.\n3. If a Generation is active, use \`${next_cmd}\` to proceed with the current stage.\n4. If no Generation is active, use \`/reap.start\` to start a new one.\n5. Do NOT implement features, fix bugs, or make changes outside of the REAP lifecycle unless the user explicitly asks to bypass it.\n6. When the user says \"reap evolve\", \"next stage\", \"proceed\", or similar — invoke the appropriate REAP skill.\n7. **Genome is the authoritative knowledge source.** When making decisions about architecture, conventions, or constraints, ALWAYS reference the Genome first. If code contradicts Genome, flag it as a potential genome-change backlog item.\n8. If you notice the Genome is outdated or missing information relevant to your current task, inform the user and suggest running \`/reap.sync\`.\n</REAP_WORKFLOW>"
186
-
187
- _reap_log "Building context..."
188
- escaped_context=$(escape_for_json "$reap_context")
189
- _reap_log "Done. Outputting JSON."
190
-
191
- cat <<EOF
192
- {
193
- "hookSpecificOutput": {
194
- "hookEventName": "SessionStart",
195
- "additionalContext": "${escaped_context}"
196
- }
197
- }
198
- EOF
199
-
200
- exit 0