@c-d-cc/reap 0.1.2 → 0.2.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.
- package/README.ja.md +321 -0
- package/README.ko.md +11 -5
- package/README.md +11 -5
- package/README.zh-CN.md +321 -0
- package/dist/cli.js +545 -259
- package/dist/templates/commands/reap.help.md +70 -45
- package/dist/templates/commands/reap.status.md +12 -2
- package/dist/templates/commands/reap.update.md +40 -0
- package/dist/templates/hooks/opencode-session-start.js +206 -0
- package/dist/templates/hooks/session-start.sh +45 -8
- package/package.json +2 -2
|
@@ -4,58 +4,83 @@ description: "REAP Help — Contextual help based on current state"
|
|
|
4
4
|
|
|
5
5
|
# Help
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**ARGUMENTS**: $ARGUMENTS
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## File Access Rules
|
|
10
|
+
- ONLY read `.reap/life/current.yml` and `.reap/config.yml`. No other files for basic help.
|
|
11
|
+
- For topic help: also read `reap.{name}.md` from the same directory as this file.
|
|
12
|
+
- Do NOT access global node_modules. Do NOT guess file paths.
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
- Read `.reap/life/current.yml`
|
|
13
|
-
- Read `.reap/config.yml` for strict mode status
|
|
14
|
+
## If ARGUMENTS is provided → skip to "Topic Help" section below.
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
## Basic Help (no arguments)
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
- "No active Generation. To get started:"
|
|
19
|
-
- " `/reap.start` — Start a new Generation with a goal"
|
|
20
|
-
- " `/reap.evolve` — Start and run the full lifecycle autonomously"
|
|
21
|
-
- If there are items in `.reap/life/backlog/`, mention them
|
|
18
|
+
Read `.reap/life/current.yml` and `.reap/config.yml`, then output EXACTLY this format with values filled in. Use markdown formatting. Do NOT add extra explanation.
|
|
22
19
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
**REAP** — Recursive Evolutionary Autonomous Pipeline
|
|
23
|
+
|
|
24
|
+
AI와 사람이 협업하여 소프트웨어를 세대(Generation) 단위로 진화시키는 개발 파이프라인입니다.
|
|
25
|
+
각 세대는 5단계 lifecycle을 거칩니다:
|
|
26
|
+
|
|
27
|
+
`Objective` → `Planning` → `Implementation` → `Validation` → `Completion`
|
|
28
|
+
|
|
29
|
+
Genome(`.reap/genome/`)에 프로젝트의 설계 원칙과 규칙을 기록하고, 세대를 거듭하며 점진적으로 진화합니다.
|
|
27
30
|
|
|
28
|
-
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
[If active generation exists, show:]
|
|
34
|
+
> 🔄 **{id}** — {goal}
|
|
35
|
+
> Stage: `{stage}` → 다음: `/reap.{stage}` 또는 `/reap.next`
|
|
36
|
+
|
|
37
|
+
[If no active generation, show:]
|
|
38
|
+
> No active Generation → `/reap.start` 또는 `/reap.evolve`
|
|
39
|
+
|
|
40
|
+
---
|
|
29
41
|
|
|
30
|
-
|
|
42
|
+
### 커맨드
|
|
31
43
|
|
|
32
44
|
| Command | Description |
|
|
33
45
|
|---------|-------------|
|
|
34
|
-
| `/reap.start` |
|
|
35
|
-
| `/reap.evolve` |
|
|
36
|
-
| `/reap.objective` |
|
|
37
|
-
| `/reap.planning` |
|
|
38
|
-
| `/reap.implementation` |
|
|
39
|
-
| `/reap.validation` |
|
|
40
|
-
| `/reap.completion` |
|
|
41
|
-
| `/reap.next` |
|
|
42
|
-
| `/reap.back` |
|
|
43
|
-
| `/reap.status` |
|
|
44
|
-
| `/reap.sync` |
|
|
45
|
-
| `/reap.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
46
|
+
| `/reap.start` | 새 Generation을 시작하고 goal을 설정 |
|
|
47
|
+
| `/reap.evolve` | ⚡ 전체 lifecycle을 자율적으로 실행 (사람 개입 최소화) |
|
|
48
|
+
| `/reap.objective` | 이번 Generation의 목표, 요구사항, 완료 기준을 정의 |
|
|
49
|
+
| `/reap.planning` | 태스크를 분해하고 구현 계획을 수립 |
|
|
50
|
+
| `/reap.implementation` | 계획에 따라 코드를 구현하고 진행 상황을 기록 |
|
|
51
|
+
| `/reap.validation` | 테스트 실행, 완료 기준 충족 여부를 검증 |
|
|
52
|
+
| `/reap.completion` | 회고, Genome 변경 반영, Generation 마무리 |
|
|
53
|
+
| `/reap.next` | 다음 stage로 전진 (completion → archiving + commit) |
|
|
54
|
+
| `/reap.back` | 이전 stage로 회귀 (regression 사유 기록) |
|
|
55
|
+
| `/reap.status` | 프로젝트 상태, Generation 진행도, backlog, Genome 건강도 표시 |
|
|
56
|
+
| `/reap.sync` | 현재 소스코드와 Genome 간 차이를 분석하고 동기화 |
|
|
57
|
+
| `/reap.update` | REAP 최신 버전 확인 및 업그레이드 |
|
|
58
|
+
| `/reap.help` | 도움말. `/reap.help {topic}`으로 주제별 상세 설명 |
|
|
59
|
+
|
|
60
|
+
💡 `/reap.help {topic}` — workflow, genome, backlog, strict, agents, hooks, config, evolve, regression, author ...
|
|
61
|
+
|
|
62
|
+
**Config**: Strict: {on/off} · Auto-Update: {on/off} · Language: {value}
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Topic Help
|
|
67
|
+
|
|
68
|
+
If ARGUMENTS contains a topic, look up from the list below. **If NOT in the list, respond: "Unknown topic: '{topic}'. `/reap.help`로 available topics를 확인하세요."**
|
|
69
|
+
|
|
70
|
+
For command-name topics: read `reap.{name}.md` from the same directory as this file, then explain.
|
|
71
|
+
|
|
72
|
+
#### Topics
|
|
73
|
+
|
|
74
|
+
- **workflow** / **lifecycle** — 5-stage lifecycle: objective → planning → implementation → validation → completion. Gate → Steps → Artifact. `/reap.next`로 전진, `/reap.back`으로 회귀.
|
|
75
|
+
- **genome** — `.reap/genome/`: principles.md, conventions.md, constraints.md, domain/*.md. 불변 원칙: 현재 세대에서 직접 수정 금지 → backlog → completion에서 반영.
|
|
76
|
+
- **backlog** — `.reap/life/backlog/`. genome-change, environment-change, task. status: pending/consumed. consumed → lineage, pending → 이월.
|
|
77
|
+
- **strict** — `strict: true`: no generation = 코드 수정 차단, non-implementation = 차단, implementation = plan scope만. Escape: "override"/"bypass strict".
|
|
78
|
+
- **agents** — AgentAdapter 추상화. auto-detect (Claude Code, OpenCode). config.yml `agents` 오버라이드.
|
|
79
|
+
- **hooks** — config.yml: onGenerationStart, onStageTransition, onGenerationComplete, onRegression. command/prompt 타입.
|
|
80
|
+
- **config** — `.reap/config.yml`: version, project, entryMode, strict, language, agents, autoUpdate, hooks.
|
|
81
|
+
- **evolve** — `/reap.evolve`: 전체 lifecycle 자율 실행. 사람 확인 없이 objective~completion 순차 진행.
|
|
82
|
+
- **regression** — `/reap.back`: 이전 stage 회귀. timeline + artifact에 Regression 섹션 기록.
|
|
83
|
+
- **minor-fix** — 5분 이내, 설계 변경 없는 수정. stage 전환 없이 현재 artifact에 기록.
|
|
84
|
+
- **compression** — 10,000줄 + 5세대 이상 시 lineage 자동 압축. L1(40줄), L2(60줄).
|
|
85
|
+
- **author** — HyeonIL Choi (At C to D). hichoi@c-d.cc / https://reap.cc / https://github.com/c-d-cc/reap
|
|
86
|
+
- **start** / **objective** / **planning** / **implementation** / **validation** / **completion** / **next** / **back** / **sync** / **status** / **update** / **help** — Read `reap.{name}.md` from same directory, explain.
|
|
@@ -6,11 +6,19 @@ description: "REAP Status — Show current generation state and project health"
|
|
|
6
6
|
|
|
7
7
|
Display a comprehensive overview of the current REAP project state.
|
|
8
8
|
|
|
9
|
+
## IMPORTANT: File Access Rules
|
|
10
|
+
- ONLY read files explicitly listed in the steps below. Do NOT guess or infer file paths.
|
|
11
|
+
- If a file read fails or the file does not exist, skip it silently and continue.
|
|
12
|
+
- Do NOT attempt to read files like `reaprc.json`, `.reaprc`, or any file not specified in this command.
|
|
13
|
+
- The REAP project structure uses ONLY: `.reap/config.yml`, `.reap/life/current.yml`, `.reap/life/backlog/`, `.reap/life/0X-*.md`, `.reap/genome/`, `.reap/lineage/`
|
|
14
|
+
|
|
9
15
|
## Steps
|
|
10
16
|
|
|
11
|
-
### 1. Project Info
|
|
12
|
-
- Read `.reap/config.yml` for project name, entryMode,
|
|
17
|
+
### 1. Project Info (MUST execute all of these)
|
|
18
|
+
- Read `.reap/config.yml` for project name, entryMode, strict, autoUpdate, language
|
|
13
19
|
- Count completed generations in `.reap/lineage/`
|
|
20
|
+
- **REQUIRED**: Run the shell command `reap --version` to get the installed version. You MUST actually execute this command, do not skip it.
|
|
21
|
+
- Show "REAP: v{installed}" — do NOT run `npm view` here (slow network call). Users can run `/reap.update` to check for updates.
|
|
14
22
|
|
|
15
23
|
### 2. Current Generation
|
|
16
24
|
- Read `.reap/life/current.yml`
|
|
@@ -48,7 +56,9 @@ Present as a structured summary the human can quickly scan:
|
|
|
48
56
|
```
|
|
49
57
|
📊 REAP Status
|
|
50
58
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
59
|
+
REAP: v[installed] (run `/reap.update` to check for updates)
|
|
51
60
|
Project: [name] ([entryMode])
|
|
61
|
+
Strict: [on/off] Auto-Update: [on/off] Language: [lang]
|
|
52
62
|
Genome Version: v[N]
|
|
53
63
|
Completed Generations: [count]
|
|
54
64
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "REAP Update — Check for updates and upgrade REAP"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Update
|
|
6
|
+
|
|
7
|
+
Check for REAP updates and upgrade to the latest version.
|
|
8
|
+
|
|
9
|
+
## IMPORTANT: File Access Rules
|
|
10
|
+
- Do NOT access global node_modules or any path outside the project.
|
|
11
|
+
- If a command fails, report the error and stop.
|
|
12
|
+
|
|
13
|
+
## Steps
|
|
14
|
+
|
|
15
|
+
### 1. Check Current Version
|
|
16
|
+
- Run `reap --version` to get the installed version
|
|
17
|
+
- Run `npm view @c-d-cc/reap version` to get the latest published version
|
|
18
|
+
- Compare the two versions
|
|
19
|
+
|
|
20
|
+
### 2. Update Decision
|
|
21
|
+
**If installed == latest:**
|
|
22
|
+
- "REAP v{version} is already up to date. (latest)"
|
|
23
|
+
- Then skip to Step 4.
|
|
24
|
+
|
|
25
|
+
**If installed < latest:**
|
|
26
|
+
- Show: "Update available: v{installed} → v{latest}"
|
|
27
|
+
- Ask the user: "Update now? (yes/no)"
|
|
28
|
+
- If yes: proceed to Step 3
|
|
29
|
+
- If no: "Skipped. Run `/reap.update` anytime to update."
|
|
30
|
+
|
|
31
|
+
### 3. Perform Update
|
|
32
|
+
- Run: `npm update -g @c-d-cc/reap`
|
|
33
|
+
- If the command fails, suggest: `sudo npm update -g @c-d-cc/reap` or `npm install -g @c-d-cc/reap@latest`
|
|
34
|
+
- After npm update, run: `reap update` to sync commands, templates, and hooks to all detected agents
|
|
35
|
+
- Show the update result summary
|
|
36
|
+
|
|
37
|
+
### 4. Sync Check
|
|
38
|
+
- Run: `reap update --dry-run` to check if commands/templates need syncing
|
|
39
|
+
- If changes detected: run `reap update` and show results
|
|
40
|
+
- If no changes: "All commands and templates are up to date."
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
// REAP SessionStart plugin for OpenCode
|
|
2
|
+
// Injects REAP guide + Genome + current generation context into every OpenCode session
|
|
3
|
+
// Installed to ~/.config/opencode/plugins/reap-session-start.js
|
|
4
|
+
|
|
5
|
+
const { execSync } = require("child_process");
|
|
6
|
+
const fs = require("fs");
|
|
7
|
+
const path = require("path");
|
|
8
|
+
|
|
9
|
+
module.exports = async (ctx) => {
|
|
10
|
+
return {
|
|
11
|
+
"session.start": async ({ trigger }) => {
|
|
12
|
+
const projectRoot = process.cwd();
|
|
13
|
+
const reapDir = path.join(projectRoot, ".reap");
|
|
14
|
+
|
|
15
|
+
// Check if this is a REAP project
|
|
16
|
+
if (!fs.existsSync(reapDir)) return;
|
|
17
|
+
|
|
18
|
+
// Auto-update check (with PATH resolution for non-shell environments)
|
|
19
|
+
let autoUpdateMessage = "";
|
|
20
|
+
try {
|
|
21
|
+
const autoConfigPath = path.join(reapDir, "config.yml");
|
|
22
|
+
if (fs.existsSync(autoConfigPath)) {
|
|
23
|
+
const configRaw = fs.readFileSync(autoConfigPath, "utf8");
|
|
24
|
+
const autoUpdateMatch = configRaw.match(/^autoUpdate:\s*(.+)$/m);
|
|
25
|
+
if (autoUpdateMatch && autoUpdateMatch[1].trim() === "true") {
|
|
26
|
+
try {
|
|
27
|
+
// Resolve PATH: OpenCode plugin runs in Node.js context which may lack shell PATH
|
|
28
|
+
const userShell = process.env.SHELL || "/bin/bash";
|
|
29
|
+
const shellPath = execSync(`${userShell} -l -c 'echo $PATH' 2>/dev/null`, { encoding: "utf8" }).trim();
|
|
30
|
+
const execOpts = { encoding: "utf8", env: { ...process.env, PATH: shellPath || process.env.PATH } };
|
|
31
|
+
|
|
32
|
+
const installed = execSync("reap --version 2>/dev/null", execOpts).trim();
|
|
33
|
+
const latest = execSync("npm view @c-d-cc/reap version 2>/dev/null", execOpts).trim();
|
|
34
|
+
if (installed && latest && installed !== latest) {
|
|
35
|
+
execSync("npm update -g @c-d-cc/reap >/dev/null 2>&1", { ...execOpts, stdio: "ignore" });
|
|
36
|
+
execSync("reap update >/dev/null 2>&1", { ...execOpts, stdio: "ignore" });
|
|
37
|
+
autoUpdateMessage = `REAP auto-updated: v${installed} → v${latest}`;
|
|
38
|
+
}
|
|
39
|
+
} catch { /* update check failed, skip */ }
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
} catch { /* config read failed, skip */ }
|
|
43
|
+
|
|
44
|
+
const scriptDir = __dirname;
|
|
45
|
+
// Look for reap-guide.md relative to the package hooks dir
|
|
46
|
+
// The guide is installed alongside this plugin's source package
|
|
47
|
+
const guideLocations = [
|
|
48
|
+
path.join(scriptDir, "..", "hooks", "reap-guide.md"),
|
|
49
|
+
path.join(scriptDir, "reap-guide.md"),
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
let reapGuide = "";
|
|
53
|
+
for (const loc of guideLocations) {
|
|
54
|
+
if (fs.existsSync(loc)) {
|
|
55
|
+
reapGuide = fs.readFileSync(loc, "utf8");
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// If guide not found from package, try to get it via the reap CLI
|
|
61
|
+
if (!reapGuide) {
|
|
62
|
+
try {
|
|
63
|
+
// Find the package hooks dir by looking up from the plugin location
|
|
64
|
+
const possiblePaths = [
|
|
65
|
+
path.join(require.resolve("@c-d-cc/reap/package.json"), "..", "dist", "templates", "hooks", "reap-guide.md"),
|
|
66
|
+
];
|
|
67
|
+
for (const p of possiblePaths) {
|
|
68
|
+
if (fs.existsSync(p)) {
|
|
69
|
+
reapGuide = fs.readFileSync(p, "utf8");
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} catch { /* package not found */ }
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Read Genome files
|
|
77
|
+
const genomeDir = path.join(reapDir, "genome");
|
|
78
|
+
let genomeContent = "";
|
|
79
|
+
const L1_LIMIT = 500;
|
|
80
|
+
const L2_LIMIT = 200;
|
|
81
|
+
let l1Lines = 0;
|
|
82
|
+
|
|
83
|
+
if (fs.existsSync(genomeDir)) {
|
|
84
|
+
for (const file of ["principles.md", "conventions.md", "constraints.md"]) {
|
|
85
|
+
const filePath = path.join(genomeDir, file);
|
|
86
|
+
if (fs.existsSync(filePath)) {
|
|
87
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
88
|
+
const lines = content.split("\n").length;
|
|
89
|
+
l1Lines += lines;
|
|
90
|
+
if (l1Lines <= L1_LIMIT) {
|
|
91
|
+
genomeContent += `\n### ${file}\n${content}\n`;
|
|
92
|
+
} else {
|
|
93
|
+
genomeContent += `\n### ${file} [TRUNCATED]\n${content.split("\n").slice(0, 20).join("\n")}\n...\n`;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// L2: domain/ files
|
|
99
|
+
const domainDir = path.join(genomeDir, "domain");
|
|
100
|
+
if (fs.existsSync(domainDir)) {
|
|
101
|
+
let l2Lines = 0;
|
|
102
|
+
let l2Overflow = false;
|
|
103
|
+
const domainFiles = fs.readdirSync(domainDir).filter(f => f.endsWith(".md"));
|
|
104
|
+
for (const file of domainFiles) {
|
|
105
|
+
const filePath = path.join(domainDir, file);
|
|
106
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
107
|
+
const lines = content.split("\n").length;
|
|
108
|
+
l2Lines += lines;
|
|
109
|
+
if (!l2Overflow && l2Lines <= L2_LIMIT) {
|
|
110
|
+
genomeContent += `\n### domain/${file}\n${content}\n`;
|
|
111
|
+
} else {
|
|
112
|
+
l2Overflow = true;
|
|
113
|
+
const firstLine = content.split("\n").find(l => l.startsWith(">")) || content.split("\n")[0];
|
|
114
|
+
genomeContent += `\n### domain/${file} [summary]\n${firstLine}\n`;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Read config (strict mode + language)
|
|
121
|
+
let strictMode = false;
|
|
122
|
+
let language = "";
|
|
123
|
+
const configPath = path.join(reapDir, "config.yml");
|
|
124
|
+
if (fs.existsSync(configPath)) {
|
|
125
|
+
const configContent = fs.readFileSync(configPath, "utf8");
|
|
126
|
+
const strictMatch = configContent.match(/^strict:\s*(.+)$/m);
|
|
127
|
+
if (strictMatch && strictMatch[1].trim() === "true") {
|
|
128
|
+
strictMode = true;
|
|
129
|
+
}
|
|
130
|
+
const langMatch = configContent.match(/^language:\s*(.+)$/m);
|
|
131
|
+
if (langMatch) {
|
|
132
|
+
language = langMatch[1].trim();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Read current.yml
|
|
137
|
+
const currentPath = path.join(reapDir, "life", "current.yml");
|
|
138
|
+
let genStage = "none";
|
|
139
|
+
let generationContext = "No active Generation. Run `/reap.start` to start one.";
|
|
140
|
+
|
|
141
|
+
if (fs.existsSync(currentPath)) {
|
|
142
|
+
const content = fs.readFileSync(currentPath, "utf8").trim();
|
|
143
|
+
if (content) {
|
|
144
|
+
const idMatch = content.match(/^id:\s*(.+)$/m);
|
|
145
|
+
const goalMatch = content.match(/^goal:\s*(.+)$/m);
|
|
146
|
+
const stageMatch = content.match(/^stage:\s*(.+)$/m);
|
|
147
|
+
if (idMatch && goalMatch && stageMatch) {
|
|
148
|
+
genStage = stageMatch[1].trim();
|
|
149
|
+
generationContext = `Active Generation: ${idMatch[1].trim()} | Goal: ${goalMatch[1].trim()} | Stage: ${genStage}`;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Map stage to command
|
|
155
|
+
const stageCommandMap = {
|
|
156
|
+
objective: "/reap.objective",
|
|
157
|
+
planning: "/reap.planning",
|
|
158
|
+
implementation: "/reap.implementation",
|
|
159
|
+
validation: "/reap.validation",
|
|
160
|
+
completion: "/reap.completion",
|
|
161
|
+
};
|
|
162
|
+
const nextCmd = stageCommandMap[genStage] || "/reap.start";
|
|
163
|
+
|
|
164
|
+
// Build strict mode section
|
|
165
|
+
let strictSection = "";
|
|
166
|
+
if (strictMode) {
|
|
167
|
+
if (genStage === "implementation") {
|
|
168
|
+
strictSection = "\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.\n</HARD-GATE>";
|
|
169
|
+
} else if (genStage === "none") {
|
|
170
|
+
strictSection = "\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.\n</HARD-GATE>";
|
|
171
|
+
} else {
|
|
172
|
+
strictSection = `\n\n## Strict Mode (ACTIVE — CODE MODIFICATION BLOCKED)\n<HARD-GATE>\nStrict mode is enabled. Current stage is '${genStage}', which is NOT the implementation stage.\nYou MUST NOT write, edit, or create any source code files.\n</HARD-GATE>`;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Detect genome staleness
|
|
177
|
+
let staleSection = "";
|
|
178
|
+
try {
|
|
179
|
+
const lastCommit = execSync(`git -C "${projectRoot}" log -1 --format="%H" -- ".reap/genome/" 2>/dev/null`, { encoding: "utf8" }).trim();
|
|
180
|
+
if (lastCommit) {
|
|
181
|
+
const commitsSince = parseInt(execSync(`git -C "${projectRoot}" rev-list --count "${lastCommit}..HEAD" 2>/dev/null`, { encoding: "utf8" }).trim(), 10);
|
|
182
|
+
if (commitsSince > 10) {
|
|
183
|
+
staleSection = `\n\n## Genome Staleness\nWARNING: Genome may be stale — ${commitsSince} commits since last Genome update. Consider running /reap.sync.`;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
} catch { /* git not available or not a repo */ }
|
|
187
|
+
|
|
188
|
+
// Build language instruction
|
|
189
|
+
let langSection = "";
|
|
190
|
+
if (language) {
|
|
191
|
+
langSection = `\n\n## Language\nAlways respond in ${language}. Use ${language} for all explanations, comments, and communications with the user. Technical terms and code identifiers should remain in their original form.`;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Build auto-update section
|
|
195
|
+
let updateSection = "";
|
|
196
|
+
if (autoUpdateMessage) {
|
|
197
|
+
updateSection = `\n\n## Auto-Update\n${autoUpdateMessage}. Tell the user: "${autoUpdateMessage}"`;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const context = `<REAP_WORKFLOW>\n${reapGuide}\n\n---\n\n## Genome (Project Knowledge)\n${genomeContent}\n\n---\n\n## Current State\n${generationContext}${staleSection}${strictSection}${updateSection}${langSection}\n\n## Rules\n1. ALL development work MUST follow the REAP lifecycle.\n2. Before writing any code, check if a Generation is active and what stage it is in.\n3. If a Generation is active, use \`${nextCmd}\` 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 outside of the REAP lifecycle unless explicitly asked.\n6. Genome is the authoritative knowledge source.\n</REAP_WORKFLOW>`;
|
|
201
|
+
|
|
202
|
+
// Inject context into session via return value
|
|
203
|
+
return { systemPrompt: context };
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
};
|
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
# This script runs from the package directory but uses cwd to find the project's .reap/
|
|
4
4
|
set -euo pipefail
|
|
5
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
|
+
|
|
6
15
|
# Script directory (package-internal) for guide file
|
|
7
16
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
|
|
8
17
|
|
|
@@ -13,17 +22,43 @@ CURRENT_YML="${REAP_DIR}/life/current.yml"
|
|
|
13
22
|
GUIDE_FILE="${SCRIPT_DIR}/reap-guide.md"
|
|
14
23
|
GENOME_DIR="${REAP_DIR}/genome"
|
|
15
24
|
|
|
25
|
+
_reap_log "Starting..."
|
|
26
|
+
|
|
16
27
|
# Check if this is a REAP project
|
|
17
28
|
if [ ! -d "$REAP_DIR" ]; then
|
|
29
|
+
_reap_log "Not a REAP project, exiting"
|
|
18
30
|
exit 0
|
|
19
31
|
fi
|
|
20
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
|
+
|
|
21
54
|
# Read REAP guide
|
|
55
|
+
_reap_log "Loading REAP guide..."
|
|
22
56
|
reap_guide=""
|
|
23
57
|
if [ -f "$GUIDE_FILE" ]; then
|
|
24
58
|
reap_guide=$(cat "$GUIDE_FILE")
|
|
25
59
|
fi
|
|
26
60
|
|
|
61
|
+
_reap_log "Loading Genome..."
|
|
27
62
|
# Read Genome files with tiered loading
|
|
28
63
|
# L1 (~500 lines max): principles.md, conventions.md, constraints.md — always full load
|
|
29
64
|
# L2 (~200 lines max): domain/*.md — full load if within budget, otherwise title+summary only
|
|
@@ -120,13 +155,7 @@ esac
|
|
|
120
155
|
|
|
121
156
|
# Escape for JSON
|
|
122
157
|
escape_for_json() {
|
|
123
|
-
|
|
124
|
-
s="${s//\\/\\\\}"
|
|
125
|
-
s="${s//\"/\\\"}"
|
|
126
|
-
s="${s//$'\n'/\\n}"
|
|
127
|
-
s="${s//$'\r'/\\r}"
|
|
128
|
-
s="${s//$'\t'/\\t}"
|
|
129
|
-
printf '%s' "$s"
|
|
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)))'
|
|
130
159
|
}
|
|
131
160
|
|
|
132
161
|
# Build strict mode section
|
|
@@ -147,9 +176,17 @@ if [ -n "$genome_stale_warning" ]; then
|
|
|
147
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."
|
|
148
177
|
fi
|
|
149
178
|
|
|
150
|
-
|
|
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>"
|
|
151
186
|
|
|
187
|
+
_reap_log "Building context..."
|
|
152
188
|
escaped_context=$(escape_for_json "$reap_context")
|
|
189
|
+
_reap_log "Done. Outputting JSON."
|
|
153
190
|
|
|
154
191
|
cat <<EOF
|
|
155
192
|
{
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c-d-cc/reap",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Recursive Evolutionary Autonomous Pipeline — AI and humans evolve software across generations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
|
-
"author": "
|
|
7
|
+
"author": "HyeonIL Choi <hichoi@c-d.cc> (C to D)",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "git+https://github.com/c-d-cc/reap.git"
|