@c-d-cc/reap 0.11.0 → 0.12.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.
- package/README.ja.md +23 -3
- package/README.ko.md +23 -3
- package/README.md +20 -0
- package/README.zh-CN.md +23 -3
- package/dist/cli.js +527 -107
- package/dist/templates/commands/reap.config.md +5 -0
- package/dist/templates/hooks/reap-guide.md +13 -12
- package/package.json +1 -1
package/README.ja.md
CHANGED
|
@@ -218,8 +218,8 @@ Machine A:
|
|
|
218
218
|
| コマンド | 説明 |
|
|
219
219
|
|----------|------|
|
|
220
220
|
| `reap init <name>` | プロジェクト初期化。`.reap/`構造を作成 |
|
|
221
|
-
| `reap status` | 現在のGeneration
|
|
222
|
-
| `reap update` | コマンド/テンプレート/hook
|
|
221
|
+
| `reap status` | 現在のGeneration状態を確認 |
|
|
222
|
+
| `reap update` | コマンド/テンプレート/hookを最新バージョンに同期 |
|
|
223
223
|
| `reap fix` | `.reap/`構造の診断と修復 |
|
|
224
224
|
| `reap help` | CLIコマンド + スラッシュコマンド + ワークフロー概要を出力(バージョン + 最新状況表示) |
|
|
225
225
|
| `reap run <cmd>` | スラッシュコマンドのスクリプトを直接実行(1行`.md`ラッパーが内部的に使用) |
|
|
@@ -251,6 +251,25 @@ autoSubagent: true # デフォルト: true
|
|
|
251
251
|
|
|
252
252
|
Subagentは完全なコンテキストを受け取り、すべてのステージを自律的に実行します。本当にブロックされた場合のみユーザーに確認を求めます。
|
|
253
253
|
|
|
254
|
+
### エラー時の自動Issue報告
|
|
255
|
+
|
|
256
|
+
`reap run`の実行中に予期しないエラーが発生した場合、`gh issue create`を通じてGitHub Issueを自動作成できます:
|
|
257
|
+
|
|
258
|
+
```yaml
|
|
259
|
+
# .reap/config.yml
|
|
260
|
+
autoIssueReport: true # デフォルト: true(gh CLIがある場合)
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### AI Migration Agent
|
|
264
|
+
|
|
265
|
+
`reap update`の実行時にプロジェクトと最新REAPバージョン間の構造的な差分(不足しているconfigフィールド、古いテンプレートなど)が検出されると、AI支援のマイグレーションプロンプトが表示されます。エージェントが差分を分析し、対話的に変更を適用するため、手動マイグレーションは不要です。
|
|
266
|
+
|
|
267
|
+
`reap init`ではすべてのconfigフィールドを明示的に宣言し、`reap update`時に不足しているフィールドは自動的に補完されます。
|
|
268
|
+
|
|
269
|
+
### CLAUDE.md連携
|
|
270
|
+
|
|
271
|
+
`reap init`と`reap update`の実行時に、`.claude/CLAUDE.md`にREAP管理セクションを追加し、Claude Codeセッションに必要なプロジェクトコンテキストを提供します。
|
|
272
|
+
|
|
254
273
|
### スラッシュコマンド [↗](https://reap.cc/docs/command-reference)
|
|
255
274
|
|
|
256
275
|
スラッシュコマンドが`.claude/commands/`にインストールされ、ワークフロー全体を駆動します:
|
|
@@ -270,6 +289,7 @@ Subagentは完全なコンテキストを受け取り、すべてのステージ
|
|
|
270
289
|
| `/reap.sync` | GenomeとEnvironmentを同時に同期 |
|
|
271
290
|
| `/reap.sync.genome` | ソースコードベースでGenomeを最新化 |
|
|
272
291
|
| `/reap.sync.environment` | 外部環境依存関係の発見と文書化 |
|
|
292
|
+
| `/reap.config` | 現在のプロジェクト設定を表示 |
|
|
273
293
|
| `/reap.report` | REAPプロジェクトにバグ/フィードバックを報告(プライバシー保護) |
|
|
274
294
|
| `/reap.help` | 24+トピックのcontextual AIヘルプ |
|
|
275
295
|
| `/reap.update` | REAPパッケージのアップグレード + コマンド/テンプレート/hook同期 |
|
|
@@ -403,7 +423,7 @@ my-project/
|
|
|
403
423
|
~/.claude/
|
|
404
424
|
└── settings.json # SessionStart hookの登録
|
|
405
425
|
|
|
406
|
-
.claude/commands/ #
|
|
426
|
+
.claude/commands/ # プロジェクトレベルのスラッシュコマンド
|
|
407
427
|
└── reap.*.md # アクティブなスラッシュコマンド(`reap run <cmd>`を呼び出し)
|
|
408
428
|
```
|
|
409
429
|
|
package/README.ko.md
CHANGED
|
@@ -218,8 +218,8 @@ Machine A:
|
|
|
218
218
|
| 명령어 | 설명 |
|
|
219
219
|
|--------|------|
|
|
220
220
|
| `reap init <name>` | 프로젝트 초기화. `.reap/` 구조 생성 |
|
|
221
|
-
| `reap status` | 현재 Generation 상태 확인
|
|
222
|
-
| `reap update` | 커맨드/템플릿/훅을 최신 버전으로
|
|
221
|
+
| `reap status` | 현재 Generation 상태 확인 |
|
|
222
|
+
| `reap update` | 커맨드/템플릿/훅을 최신 버전으로 동기화 |
|
|
223
223
|
| `reap fix` | `.reap/` 구조 진단 및 복구 |
|
|
224
224
|
| `reap help` | CLI 명령어 + 슬래시 커맨드 + 워크플로우 요약 출력 (버전 + 최신 여부 표시) |
|
|
225
225
|
| `reap run <cmd>` | 슬래시 커맨드의 스크립트를 직접 실행 (1줄 `.md` wrapper가 내부적으로 사용) |
|
|
@@ -251,6 +251,25 @@ autoSubagent: true # 기본값: true
|
|
|
251
251
|
|
|
252
252
|
Subagent는 전체 컨텍스트를 받아 모든 stage를 자율적으로 실행하며, 정말로 막혔을 때만 사용자에게 확인을 요청합니다.
|
|
253
253
|
|
|
254
|
+
### 에러 시 자동 이슈 리포트
|
|
255
|
+
|
|
256
|
+
`reap run` 실행 중 예상치 못한 에러가 발생하면, `gh issue create`를 통해 GitHub Issue를 자동으로 생성할 수 있습니다:
|
|
257
|
+
|
|
258
|
+
```yaml
|
|
259
|
+
# .reap/config.yml
|
|
260
|
+
autoIssueReport: true # 기본값: true (gh CLI가 있을 때)
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### AI Migration Agent
|
|
264
|
+
|
|
265
|
+
`reap update` 실행 시 프로젝트와 최신 REAP 버전 사이의 구조적 차이(누락된 config 필드, 오래된 템플릿 등)가 감지되면, AI 기반 마이그레이션 프롬프트를 제공합니다. 에이전트가 차이를 분석하고 대화형으로 변경을 적용하므로 수동 마이그레이션이 필요 없습니다.
|
|
266
|
+
|
|
267
|
+
`reap init`도 모든 config 필드를 명시적으로 선언하며, `reap update` 시 누락된 필드는 자동으로 채워집니다.
|
|
268
|
+
|
|
269
|
+
### CLAUDE.md 연동
|
|
270
|
+
|
|
271
|
+
`reap init`과 `reap update` 시 `.claude/CLAUDE.md`에 REAP 관리 섹션을 추가하여 Claude Code 세션에 필요한 프로젝트 컨텍스트를 제공합니다.
|
|
272
|
+
|
|
254
273
|
### Slash Commands
|
|
255
274
|
|
|
256
275
|
Slash command가 `.claude/commands/`에 설치되어 전체 워크플로우를 구동합니다:
|
|
@@ -270,6 +289,7 @@ Slash command가 `.claude/commands/`에 설치되어 전체 워크플로우를
|
|
|
270
289
|
| `/reap.sync` | Genome + Environment 동시 동기화 |
|
|
271
290
|
| `/reap.sync.genome` | 소스 코드 기반 Genome 최신화 |
|
|
272
291
|
| `/reap.sync.environment` | 외부 환경 의존성 탐색 및 문서화 |
|
|
292
|
+
| `/reap.config` | 현재 프로젝트 설정 표시 |
|
|
273
293
|
| `/reap.report` | REAP 프로젝트에 버그/피드백 보고 (개인정보 보호) |
|
|
274
294
|
| `/reap.help` | 24+ 주제의 contextual AI 도움말 |
|
|
275
295
|
| `/reap.update` | REAP 패키지 업그레이드 + 커맨드/템플릿/훅 동기화 |
|
|
@@ -403,7 +423,7 @@ my-project/
|
|
|
403
423
|
~/.claude/
|
|
404
424
|
└── settings.json # SessionStart hook 등록
|
|
405
425
|
|
|
406
|
-
.claude/commands/ # 프로젝트 레벨
|
|
426
|
+
.claude/commands/ # 프로젝트 레벨 슬래시 커맨드
|
|
407
427
|
└── reap.*.md # 활성 슬래시 커맨드 (`reap run <cmd>` 호출)
|
|
408
428
|
```
|
|
409
429
|
|
package/README.md
CHANGED
|
@@ -250,6 +250,25 @@ autoSubagent: true # default: true
|
|
|
250
250
|
|
|
251
251
|
The subagent receives the full context and runs autonomously through all stages, only surfacing when genuinely blocked.
|
|
252
252
|
|
|
253
|
+
### Auto Issue Report
|
|
254
|
+
|
|
255
|
+
When an unexpected error occurs during `reap run`, REAP can automatically create a GitHub Issue via `gh issue create`. This is controlled by:
|
|
256
|
+
|
|
257
|
+
```yaml
|
|
258
|
+
# .reap/config.yml
|
|
259
|
+
autoIssueReport: true # default: true (when gh CLI is available)
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### AI Migration Agent
|
|
263
|
+
|
|
264
|
+
When `reap update` detects structural gaps between your project and the latest REAP version (e.g., missing config fields, outdated templates), it offers an AI-assisted migration prompt. The agent analyzes the differences and applies changes interactively — no manual migration needed.
|
|
265
|
+
|
|
266
|
+
`reap init` also ensures all config fields are explicitly declared, and `reap update` backfills any missing fields automatically.
|
|
267
|
+
|
|
268
|
+
### CLAUDE.md Integration
|
|
269
|
+
|
|
270
|
+
During `reap init` and `reap update`, REAP adds a managed section to `.claude/CLAUDE.md` containing essential project context for Claude Code sessions.
|
|
271
|
+
|
|
253
272
|
### Slash Commands [↗](https://reap.cc/docs/command-reference)
|
|
254
273
|
|
|
255
274
|
Slash commands are installed in `.claude/commands/` and drive the entire workflow:
|
|
@@ -269,6 +288,7 @@ Slash commands are installed in `.claude/commands/` and drive the entire workflo
|
|
|
269
288
|
| `/reap.sync` | Synchronize both Genome and Environment |
|
|
270
289
|
| `/reap.sync.genome` | Synchronize Genome with current source code |
|
|
271
290
|
| `/reap.sync.environment` | Discover and document external environment dependencies |
|
|
291
|
+
| `/reap.config` | Display current project configuration |
|
|
272
292
|
| `/reap.report` | Report a bug or feedback to the REAP project (privacy-safe) |
|
|
273
293
|
| `/reap.help` | Contextual AI help with 24+ topics |
|
|
274
294
|
| `/reap.update` | Upgrade REAP package + sync commands/templates/hooks |
|
package/README.zh-CN.md
CHANGED
|
@@ -218,8 +218,8 @@ Machine A:
|
|
|
218
218
|
| 命令 | 说明 |
|
|
219
219
|
|------|------|
|
|
220
220
|
| `reap init <name>` | 初始化项目。创建`.reap/`结构 |
|
|
221
|
-
| `reap status` | 查看当前Generation
|
|
222
|
-
| `reap update` | 将命令/模板/hook
|
|
221
|
+
| `reap status` | 查看当前Generation状态 |
|
|
222
|
+
| `reap update` | 将命令/模板/hook同步到最新版本 |
|
|
223
223
|
| `reap fix` | 诊断和修复`.reap/`结构 |
|
|
224
224
|
| `reap help` | 输出CLI命令 + 斜杠命令 + 工作流摘要(显示版本 + 最新状态) |
|
|
225
225
|
| `reap run <cmd>` | 直接执行斜杠命令的脚本(由1行`.md` wrapper内部调用) |
|
|
@@ -251,6 +251,25 @@ autoSubagent: true # 默认值: true
|
|
|
251
251
|
|
|
252
252
|
Subagent接收完整上下文后自主执行所有阶段,仅在确实遇到阻碍时才向用户确认。
|
|
253
253
|
|
|
254
|
+
### 错误时自动Issue报告
|
|
255
|
+
|
|
256
|
+
当`reap run`执行中发生意外错误时,可通过`gh issue create`自动创建GitHub Issue:
|
|
257
|
+
|
|
258
|
+
```yaml
|
|
259
|
+
# .reap/config.yml
|
|
260
|
+
autoIssueReport: true # 默认值: true(检测到gh CLI时)
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### AI Migration Agent
|
|
264
|
+
|
|
265
|
+
`reap update`执行时,如果检测到项目与最新REAP版本之间的结构性差异(缺失的config字段、过时的模板等),会提供AI辅助的迁移提示。代理分析差异并交互式地应用变更,无需手动迁移。
|
|
266
|
+
|
|
267
|
+
`reap init`会明确声明所有config字段,`reap update`时自动补全缺失字段。
|
|
268
|
+
|
|
269
|
+
### CLAUDE.md集成
|
|
270
|
+
|
|
271
|
+
`reap init`和`reap update`执行时,会在`.claude/CLAUDE.md`中添加REAP管理段落,为Claude Code会话提供必要的项目上下文。
|
|
272
|
+
|
|
254
273
|
### 斜杠命令 [↗](https://reap.cc/docs/command-reference)
|
|
255
274
|
|
|
256
275
|
斜杠命令安装在`.claude/commands/`中,驱动整个工作流:
|
|
@@ -270,6 +289,7 @@ Subagent接收完整上下文后自主执行所有阶段,仅在确实遇到阻
|
|
|
270
289
|
| `/reap.sync` | 同时同步Genome和Environment |
|
|
271
290
|
| `/reap.sync.genome` | 基于源代码同步Genome |
|
|
272
291
|
| `/reap.sync.environment` | 发现和记录外部环境依赖 |
|
|
292
|
+
| `/reap.config` | 显示当前项目配置 |
|
|
273
293
|
| `/reap.report` | 向REAP项目报告bug/反馈(隐私保护) |
|
|
274
294
|
| `/reap.help` | 24+主题的上下文AI帮助 |
|
|
275
295
|
| `/reap.update` | 升级REAP包 + 同步命令/模板/hook |
|
|
@@ -403,7 +423,7 @@ my-project/
|
|
|
403
423
|
~/.claude/
|
|
404
424
|
└── settings.json # SessionStart hook注册
|
|
405
425
|
|
|
406
|
-
.claude/commands/ #
|
|
426
|
+
.claude/commands/ # 项目级斜杠命令
|
|
407
427
|
└── reap.*.md # 活跃斜杠命令(调用`reap run <cmd>`)
|
|
408
428
|
```
|
|
409
429
|
|
package/dist/cli.js
CHANGED
|
@@ -9020,6 +9020,26 @@ class ConfigManager {
|
|
|
9020
9020
|
static resolveAutoSubagent(value) {
|
|
9021
9021
|
return value !== false;
|
|
9022
9022
|
}
|
|
9023
|
+
static async backfill(paths) {
|
|
9024
|
+
const config = await ConfigManager.read(paths);
|
|
9025
|
+
const added = [];
|
|
9026
|
+
const defaults = {
|
|
9027
|
+
strict: false,
|
|
9028
|
+
autoUpdate: true,
|
|
9029
|
+
autoSubagent: true,
|
|
9030
|
+
autoIssueReport: false
|
|
9031
|
+
};
|
|
9032
|
+
for (const [key, defaultValue] of Object.entries(defaults)) {
|
|
9033
|
+
if (config[key] === undefined) {
|
|
9034
|
+
config[key] = defaultValue;
|
|
9035
|
+
added.push(key);
|
|
9036
|
+
}
|
|
9037
|
+
}
|
|
9038
|
+
if (added.length > 0) {
|
|
9039
|
+
await ConfigManager.write(paths, config);
|
|
9040
|
+
}
|
|
9041
|
+
return { added };
|
|
9042
|
+
}
|
|
9023
9043
|
static resolveStrict(strict) {
|
|
9024
9044
|
if (strict === undefined || strict === false) {
|
|
9025
9045
|
return { edit: false, merge: false };
|
|
@@ -10048,7 +10068,14 @@ class GenerationManager {
|
|
|
10048
10068
|
const lifeEntries = await readdir7(this.paths.life);
|
|
10049
10069
|
for (const entry of lifeEntries) {
|
|
10050
10070
|
if (/^\d{2}-[a-z]+(?:-[a-z]+)*\.md$/.test(entry)) {
|
|
10051
|
-
|
|
10071
|
+
const srcPath = join8(this.paths.life, entry);
|
|
10072
|
+
const destPath = join8(genDir, entry);
|
|
10073
|
+
let content = await readTextFile(srcPath);
|
|
10074
|
+
if (content && content.startsWith("# REAP MANAGED")) {
|
|
10075
|
+
content = content.replace(/^# REAP MANAGED[^\n]*\n/, "");
|
|
10076
|
+
}
|
|
10077
|
+
await writeTextFile(destPath, content ?? "");
|
|
10078
|
+
await unlink3(srcPath);
|
|
10052
10079
|
}
|
|
10053
10080
|
}
|
|
10054
10081
|
const backlogDir = join8(genDir, "backlog");
|
|
@@ -10271,7 +10298,7 @@ async function parseHookMeta(filePath, ext) {
|
|
|
10271
10298
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
10272
10299
|
if (fmMatch) {
|
|
10273
10300
|
try {
|
|
10274
|
-
const fm =
|
|
10301
|
+
const fm = import_yaml8.default.parse(fmMatch[1]) ?? {};
|
|
10275
10302
|
return {
|
|
10276
10303
|
condition: String(fm.condition ?? "always"),
|
|
10277
10304
|
order: Number(fm.order ?? 50)
|
|
@@ -10346,10 +10373,10 @@ async function executeMdHook(hook, event, hooksDir) {
|
|
|
10346
10373
|
content: body
|
|
10347
10374
|
};
|
|
10348
10375
|
}
|
|
10349
|
-
var
|
|
10376
|
+
var import_yaml8;
|
|
10350
10377
|
var init_hook_engine = __esm(() => {
|
|
10351
10378
|
init_fs();
|
|
10352
|
-
|
|
10379
|
+
import_yaml8 = __toESM(require_dist(), 1);
|
|
10353
10380
|
});
|
|
10354
10381
|
|
|
10355
10382
|
// src/cli/commands/run/next.ts
|
|
@@ -10571,7 +10598,7 @@ async function markBacklogConsumed(backlogDir, filename, genId) {
|
|
|
10571
10598
|
frontmatter.consumedBy = genId;
|
|
10572
10599
|
delete frontmatter.consumed;
|
|
10573
10600
|
const newContent = `---
|
|
10574
|
-
${
|
|
10601
|
+
${import_yaml9.default.stringify(frontmatter).trim()}
|
|
10575
10602
|
---
|
|
10576
10603
|
${body}`;
|
|
10577
10604
|
await writeTextFile(filePath, newContent);
|
|
@@ -10595,7 +10622,7 @@ async function revertBacklogConsumed(backlogDir, genId) {
|
|
|
10595
10622
|
frontmatter.status = "pending";
|
|
10596
10623
|
delete frontmatter.consumedBy;
|
|
10597
10624
|
const newContent = `---
|
|
10598
|
-
${
|
|
10625
|
+
${import_yaml9.default.stringify(frontmatter).trim()}
|
|
10599
10626
|
---
|
|
10600
10627
|
${body}`;
|
|
10601
10628
|
await writeTextFile(filePath, newContent);
|
|
@@ -10607,15 +10634,15 @@ function parseFrontmatter2(content) {
|
|
|
10607
10634
|
if (!match)
|
|
10608
10635
|
return { frontmatter: {}, body: content };
|
|
10609
10636
|
try {
|
|
10610
|
-
return { frontmatter:
|
|
10637
|
+
return { frontmatter: import_yaml9.default.parse(match[1]) ?? {}, body: match[2] };
|
|
10611
10638
|
} catch {
|
|
10612
10639
|
return { frontmatter: {}, body: content };
|
|
10613
10640
|
}
|
|
10614
10641
|
}
|
|
10615
|
-
var
|
|
10642
|
+
var import_yaml9;
|
|
10616
10643
|
var init_backlog = __esm(() => {
|
|
10617
10644
|
init_fs();
|
|
10618
|
-
|
|
10645
|
+
import_yaml9 = __toESM(require_dist(), 1);
|
|
10619
10646
|
});
|
|
10620
10647
|
|
|
10621
10648
|
// src/cli/commands/run/start.ts
|
|
@@ -11571,11 +11598,10 @@ function buildSubagentPrompt(paths, state, genomeSummaries, backlogSummary) {
|
|
|
11571
11598
|
lines.push(" - `completion` -> `/reap.completion`");
|
|
11572
11599
|
lines.push("3. Write the required artifact BEFORE completing the stage.");
|
|
11573
11600
|
lines.push("4. Run the stage complete phase if applicable (e.g., `reap run <stage> --phase complete`).");
|
|
11574
|
-
lines.push("5.
|
|
11575
|
-
lines.push("6.
|
|
11601
|
+
lines.push("5. If current stage is NOT `completion`: run `/reap.next` to advance, then go to step 1.");
|
|
11602
|
+
lines.push("6. If current stage IS `completion`: `/reap.completion` auto-archives after genome phase. Done.");
|
|
11576
11603
|
lines.push("");
|
|
11577
|
-
lines.push("
|
|
11578
|
-
lines.push("- Run `/reap.completion` which handles: retrospective, genome updates, backlog consume, and archive.");
|
|
11604
|
+
lines.push("Note: `/reap.next` is a transition command, NOT a lifecycle stage.");
|
|
11579
11605
|
lines.push("");
|
|
11580
11606
|
lines.push("## Project");
|
|
11581
11607
|
lines.push(`- Path: ${paths.projectRoot}`);
|
|
@@ -11950,77 +11976,226 @@ var exports_help = {};
|
|
|
11950
11976
|
__export(exports_help, {
|
|
11951
11977
|
execute: () => execute15
|
|
11952
11978
|
});
|
|
11953
|
-
|
|
11979
|
+
import { join as join24 } from "path";
|
|
11980
|
+
function detectLanguage(configContent) {
|
|
11981
|
+
const raw = configContent?.match(/language:\s*(\S+)/)?.[1] ?? null;
|
|
11982
|
+
if (raw && raw in LANGUAGE_ALIASES)
|
|
11983
|
+
return LANGUAGE_ALIASES[raw];
|
|
11984
|
+
return raw;
|
|
11985
|
+
}
|
|
11986
|
+
function isSupportedLanguage(lang) {
|
|
11987
|
+
return lang !== null && SUPPORTED_LANGUAGES.includes(lang);
|
|
11988
|
+
}
|
|
11989
|
+
function buildCommandTable(lang) {
|
|
11990
|
+
return [
|
|
11991
|
+
"| Command | Description |",
|
|
11992
|
+
"|---------|-------------|",
|
|
11993
|
+
...Object.entries(COMMAND_DESCRIPTIONS).map(([cmd, descs]) => `| \`${cmd}\` | ${descs[lang]} |`)
|
|
11994
|
+
];
|
|
11995
|
+
}
|
|
11996
|
+
function buildLines(versionDisplay, lang, stateDisplay) {
|
|
11997
|
+
return [
|
|
11998
|
+
versionDisplay,
|
|
11999
|
+
REAP_INTRO[lang],
|
|
12000
|
+
"",
|
|
12001
|
+
stateDisplay,
|
|
12002
|
+
"",
|
|
12003
|
+
...buildCommandTable(lang),
|
|
12004
|
+
"",
|
|
12005
|
+
TOPICS_LINE[lang],
|
|
12006
|
+
"Usage: REAP_HELP_TOPIC=<topic> reap run help",
|
|
12007
|
+
CONFIG_LINE[lang]
|
|
12008
|
+
];
|
|
12009
|
+
}
|
|
12010
|
+
async function execute15(paths) {
|
|
11954
12011
|
const gm = new GenerationManager(paths);
|
|
11955
12012
|
const state = await gm.current();
|
|
11956
12013
|
const configContent = await readTextFile(paths.config);
|
|
11957
|
-
const strict = configContent?.match(/strict:\s*(true|false)/)?.[1] === "true" ? "on" : "off";
|
|
11958
|
-
const autoUpdate = configContent?.match(/autoUpdate:\s*(true|false)/)?.[1] === "true" ? "on" : "off";
|
|
11959
|
-
const language = configContent?.match(/language:\s*(\w+)/)?.[1] ?? "ko";
|
|
11960
12014
|
const configVersion = configContent?.match(/version:\s*([\d.]+)/)?.[1] ?? "0.0.0";
|
|
11961
|
-
const
|
|
11962
|
-
const versionDisplay = formatVersionLine(configVersion,
|
|
12015
|
+
const autoUpdate = configContent?.match(/autoUpdate:\s*(true|false)/)?.[1] === "true";
|
|
12016
|
+
const versionDisplay = formatVersionLine(configVersion, !autoUpdate);
|
|
12017
|
+
const rawLang = detectLanguage(configContent);
|
|
12018
|
+
const supported = isSupportedLanguage(rawLang);
|
|
12019
|
+
const lang = supported ? rawLang : "en";
|
|
11963
12020
|
const topic = process.env.REAP_HELP_TOPIC;
|
|
11964
|
-
|
|
11965
|
-
|
|
11966
|
-
|
|
11967
|
-
|
|
11968
|
-
|
|
11969
|
-
|
|
11970
|
-
|
|
11971
|
-
|
|
11972
|
-
|
|
11973
|
-
|
|
11974
|
-
|
|
11975
|
-
|
|
11976
|
-
|
|
11977
|
-
|
|
11978
|
-
|
|
11979
|
-
|
|
11980
|
-
|
|
11981
|
-
|
|
11982
|
-
|
|
11983
|
-
|
|
11984
|
-
"### Basic Help (no topic)",
|
|
11985
|
-
"Show REAP overview, current state, and command table.",
|
|
11986
|
-
state?.id ? `> Current: **${state.id}** — ${state.goal} (Stage: ${state.stage})` : "> No active Generation -> `/reap.start` or `/reap.evolve`",
|
|
11987
|
-
"",
|
|
11988
|
-
"### Command Table",
|
|
11989
|
-
"| Command | Description |",
|
|
11990
|
-
"|---------|-------------|",
|
|
11991
|
-
"| `/reap.start` | 새 Generation을 시작하고 goal을 설정 |",
|
|
11992
|
-
"| `/reap.evolve` | 전체 lifecycle을 자율적으로 실행 |",
|
|
11993
|
-
"| `/reap.objective` | 목표, 요구사항, 완료 기준을 정의 |",
|
|
11994
|
-
"| `/reap.planning` | 태스크를 분해하고 구현 계획을 수립 |",
|
|
11995
|
-
"| `/reap.implementation` | 계획에 따라 코드를 구현 |",
|
|
11996
|
-
"| `/reap.validation` | 테스트 실행, 완료 기준 충족 여부를 검증 |",
|
|
11997
|
-
"| `/reap.completion` | 회고, Genome 변경 반영, Generation 마무리 |",
|
|
11998
|
-
"| `/reap.next` | 다음 stage로 전진 |",
|
|
11999
|
-
"| `/reap.back` | 이전 stage로 회귀 |",
|
|
12000
|
-
"| `/reap.status` | 프로젝트 상태 표시 |",
|
|
12001
|
-
"| `/reap.sync` | Genome/Environment 동기화 |",
|
|
12002
|
-
"| `/reap.update` | REAP 최신 버전 확인 및 업그레이드 |",
|
|
12003
|
-
"| `/reap.help` | 도움말 |",
|
|
12004
|
-
"| `/reap.push` | REAP 상태 검증 + git push |",
|
|
12005
|
-
"| `/reap.report` | 버그/이슈 리포트 |",
|
|
12006
|
-
"",
|
|
12007
|
-
`${versionDisplay} | Strict: ${strict} | Auto-Update: ${autoUpdate} | Language: ${language}`,
|
|
12008
|
-
"",
|
|
12009
|
-
"### Topic Help",
|
|
12010
|
-
"If a topic is provided, look up from these known topics:",
|
|
12011
|
-
"- workflow/lifecycle, genome, backlog, strict, agents, hooks, config, evolve, regression, minor-fix, compression, merge/collaboration, author",
|
|
12012
|
-
"- Command topics: start, objective, planning, implementation, validation, completion, next, back, sync, status, update, help, pull, push, merge.*",
|
|
12013
|
-
"",
|
|
12014
|
-
"For command-name topics: read `reap.{name}.md` from `~/.reap/commands/` or the template commands directory, then explain.",
|
|
12015
|
-
"If the topic is NOT in the list: respond 'Unknown topic'."
|
|
12016
|
-
].join(`
|
|
12021
|
+
const stateDisplay = state?.id ? `Active: **${state.id}** — ${state.goal} (Stage: ${state.stage})` : "No active Generation → `/reap.start` or `/reap.evolve`";
|
|
12022
|
+
const lines = buildLines(versionDisplay, lang, stateDisplay);
|
|
12023
|
+
if (topic) {
|
|
12024
|
+
const guidePath = join24(ReapPaths.packageHooksDir, "reap-guide.md");
|
|
12025
|
+
const reapGuide = await readTextFile(guidePath) ?? "";
|
|
12026
|
+
emitOutput({
|
|
12027
|
+
status: "prompt",
|
|
12028
|
+
command: "help",
|
|
12029
|
+
phase: "respond",
|
|
12030
|
+
completed: ["gate", "context-collect"],
|
|
12031
|
+
context: { topic, reapGuide },
|
|
12032
|
+
message: lines.join(`
|
|
12033
|
+
`),
|
|
12034
|
+
prompt: [
|
|
12035
|
+
`Topic requested: "${topic}".`,
|
|
12036
|
+
"Look up from known topics: workflow/lifecycle, genome, backlog, strict, agents, hooks, config, evolve, regression, minor-fix, compression, merge/collaboration.",
|
|
12037
|
+
"Command topics: read `reap.{name}.md` from `~/.reap/commands/` or template commands directory, then explain.",
|
|
12038
|
+
"If the topic is NOT known: respond 'Unknown topic'.",
|
|
12039
|
+
"Use the reapGuide content in context as the primary knowledge source for explaining REAP topics."
|
|
12040
|
+
].join(`
|
|
12017
12041
|
`)
|
|
12018
|
-
|
|
12042
|
+
});
|
|
12043
|
+
} else if (!supported && rawLang !== null) {
|
|
12044
|
+
emitOutput({
|
|
12045
|
+
status: "prompt",
|
|
12046
|
+
command: "help",
|
|
12047
|
+
phase: "respond",
|
|
12048
|
+
completed: ["gate", "context-collect"],
|
|
12049
|
+
message: lines.join(`
|
|
12050
|
+
`),
|
|
12051
|
+
prompt: [
|
|
12052
|
+
`The user's configured language is "${rawLang}", which is not natively supported.`,
|
|
12053
|
+
"Below is the help message in English. Translate the descriptions and intro text to the target language.",
|
|
12054
|
+
"Keep command names (e.g. /reap.start) and topic names in English.",
|
|
12055
|
+
`Target language: ${rawLang}`
|
|
12056
|
+
].join(`
|
|
12057
|
+
`)
|
|
12058
|
+
});
|
|
12059
|
+
} else {
|
|
12060
|
+
emitOutput({
|
|
12061
|
+
status: "ok",
|
|
12062
|
+
command: "help",
|
|
12063
|
+
phase: "respond",
|
|
12064
|
+
completed: ["gate", "context-collect"],
|
|
12065
|
+
message: lines.join(`
|
|
12066
|
+
`)
|
|
12067
|
+
});
|
|
12068
|
+
}
|
|
12019
12069
|
}
|
|
12070
|
+
var SUPPORTED_LANGUAGES, REAP_INTRO, COMMAND_DESCRIPTIONS, TOPICS_LINE, CONFIG_LINE, LANGUAGE_ALIASES;
|
|
12020
12071
|
var init_help = __esm(() => {
|
|
12072
|
+
init_paths();
|
|
12021
12073
|
init_generation();
|
|
12022
12074
|
init_fs();
|
|
12023
12075
|
init_version();
|
|
12076
|
+
SUPPORTED_LANGUAGES = ["en", "ko", "ja", "zh-CN"];
|
|
12077
|
+
REAP_INTRO = {
|
|
12078
|
+
en: "REAP (Recursive Evolutionary Autonomous Pipeline) — A development pipeline that evolves software generation by generation through AI+Human collaboration.",
|
|
12079
|
+
ko: "REAP (Recursive Evolutionary Autonomous Pipeline) — AI+Human 협업으로 소프트웨어를 세대 단위로 진화시키는 개발 파이프라인.",
|
|
12080
|
+
ja: "REAP (Recursive Evolutionary Autonomous Pipeline) — AI+Humanの協業でソフトウェアを世代単位で進化させる開発パイプライン。",
|
|
12081
|
+
"zh-CN": "REAP (Recursive Evolutionary Autonomous Pipeline) — 通过AI+Human协作,以世代为单位进化软件的开发管道。"
|
|
12082
|
+
};
|
|
12083
|
+
COMMAND_DESCRIPTIONS = {
|
|
12084
|
+
"/reap.start": {
|
|
12085
|
+
en: "Start a new Generation and set the goal",
|
|
12086
|
+
ko: "새 Generation을 시작하고 goal을 설정",
|
|
12087
|
+
ja: "新しいGenerationを開始し、ゴールを設定",
|
|
12088
|
+
"zh-CN": "开始新的Generation并设定目标"
|
|
12089
|
+
},
|
|
12090
|
+
"/reap.evolve": {
|
|
12091
|
+
en: "Run the entire lifecycle autonomously",
|
|
12092
|
+
ko: "전체 lifecycle을 자율적으로 실행",
|
|
12093
|
+
ja: "ライフサイクル全体を自律的に実行",
|
|
12094
|
+
"zh-CN": "自主运行整个生命周期"
|
|
12095
|
+
},
|
|
12096
|
+
"/reap.objective": {
|
|
12097
|
+
en: "Define goals, requirements, and completion criteria",
|
|
12098
|
+
ko: "목표, 요구사항, 완료 기준을 정의",
|
|
12099
|
+
ja: "目標、要件、完了基準を定義",
|
|
12100
|
+
"zh-CN": "定义目标、需求和完成标准"
|
|
12101
|
+
},
|
|
12102
|
+
"/reap.planning": {
|
|
12103
|
+
en: "Decompose tasks and create an implementation plan",
|
|
12104
|
+
ko: "태스크를 분해하고 구현 계획을 수립",
|
|
12105
|
+
ja: "タスクを分解し、実装計画を策定",
|
|
12106
|
+
"zh-CN": "分解任务并制定实施计划"
|
|
12107
|
+
},
|
|
12108
|
+
"/reap.implementation": {
|
|
12109
|
+
en: "Implement code according to the plan",
|
|
12110
|
+
ko: "계획에 따라 코드를 구현",
|
|
12111
|
+
ja: "計画に従ってコードを実装",
|
|
12112
|
+
"zh-CN": "按照计划实现代码"
|
|
12113
|
+
},
|
|
12114
|
+
"/reap.validation": {
|
|
12115
|
+
en: "Run tests and verify completion criteria are met",
|
|
12116
|
+
ko: "테스트 실행, 완료 기준 충족 여부를 검증",
|
|
12117
|
+
ja: "テストを実行し、完了基準の充足を検証",
|
|
12118
|
+
"zh-CN": "运行测试,验证是否满足完成标准"
|
|
12119
|
+
},
|
|
12120
|
+
"/reap.completion": {
|
|
12121
|
+
en: "Retrospective, apply Genome changes, finalize Generation",
|
|
12122
|
+
ko: "회고, Genome 변경 반영, Generation 마무리",
|
|
12123
|
+
ja: "振り返り、Genome変更を反映、Generationを完了",
|
|
12124
|
+
"zh-CN": "回顾,应用Genome变更,完成Generation"
|
|
12125
|
+
},
|
|
12126
|
+
"/reap.next": {
|
|
12127
|
+
en: "Advance to the next stage",
|
|
12128
|
+
ko: "다음 stage로 전진",
|
|
12129
|
+
ja: "次のステージへ進む",
|
|
12130
|
+
"zh-CN": "进入下一阶段"
|
|
12131
|
+
},
|
|
12132
|
+
"/reap.back": {
|
|
12133
|
+
en: "Return to the previous stage",
|
|
12134
|
+
ko: "이전 stage로 회귀",
|
|
12135
|
+
ja: "前のステージへ戻る",
|
|
12136
|
+
"zh-CN": "返回上一阶段"
|
|
12137
|
+
},
|
|
12138
|
+
"/reap.status": {
|
|
12139
|
+
en: "Show project status",
|
|
12140
|
+
ko: "프로젝트 상태 표시",
|
|
12141
|
+
ja: "プロジェクトの状態を表示",
|
|
12142
|
+
"zh-CN": "显示项目状态"
|
|
12143
|
+
},
|
|
12144
|
+
"/reap.config": {
|
|
12145
|
+
en: "Show current project settings",
|
|
12146
|
+
ko: "현재 프로젝트 설정 표시",
|
|
12147
|
+
ja: "現在のプロジェクト設定を表示",
|
|
12148
|
+
"zh-CN": "显示当前项目设置"
|
|
12149
|
+
},
|
|
12150
|
+
"/reap.sync": {
|
|
12151
|
+
en: "Synchronize Genome/Environment",
|
|
12152
|
+
ko: "Genome/Environment 동기화",
|
|
12153
|
+
ja: "Genome/Environmentを同期",
|
|
12154
|
+
"zh-CN": "同步Genome/Environment"
|
|
12155
|
+
},
|
|
12156
|
+
"/reap.update": {
|
|
12157
|
+
en: "Check for latest REAP version and upgrade",
|
|
12158
|
+
ko: "REAP 최신 버전 확인 및 업그레이드",
|
|
12159
|
+
ja: "REAP最新バージョンの確認とアップグレード",
|
|
12160
|
+
"zh-CN": "检查REAP最新版本并升级"
|
|
12161
|
+
},
|
|
12162
|
+
"/reap.help": {
|
|
12163
|
+
en: "Help",
|
|
12164
|
+
ko: "도움말",
|
|
12165
|
+
ja: "ヘルプ",
|
|
12166
|
+
"zh-CN": "帮助"
|
|
12167
|
+
},
|
|
12168
|
+
"/reap.push": {
|
|
12169
|
+
en: "Validate REAP state + git push",
|
|
12170
|
+
ko: "REAP 상태 검증 + git push",
|
|
12171
|
+
ja: "REAP状態検証 + git push",
|
|
12172
|
+
"zh-CN": "验证REAP状态 + git push"
|
|
12173
|
+
},
|
|
12174
|
+
"/reap.report": {
|
|
12175
|
+
en: "Bug/issue report",
|
|
12176
|
+
ko: "버그/이슈 리포트",
|
|
12177
|
+
ja: "バグ/イシューレポート",
|
|
12178
|
+
"zh-CN": "Bug/问题报告"
|
|
12179
|
+
}
|
|
12180
|
+
};
|
|
12181
|
+
TOPICS_LINE = {
|
|
12182
|
+
en: "Topics: workflow, lifecycle, genome, backlog, strict, agents, hooks, config, evolve, regression, minor-fix, compression, merge, collaboration, start, objective, planning, implementation, validation, completion, next, back, sync, status, update, help, pull, push, abort, report",
|
|
12183
|
+
ko: "Topics: workflow, lifecycle, genome, backlog, strict, agents, hooks, config, evolve, regression, minor-fix, compression, merge, collaboration, start, objective, planning, implementation, validation, completion, next, back, sync, status, update, help, pull, push, abort, report",
|
|
12184
|
+
ja: "Topics: workflow, lifecycle, genome, backlog, strict, agents, hooks, config, evolve, regression, minor-fix, compression, merge, collaboration, start, objective, planning, implementation, validation, completion, next, back, sync, status, update, help, pull, push, abort, report",
|
|
12185
|
+
"zh-CN": "Topics: workflow, lifecycle, genome, backlog, strict, agents, hooks, config, evolve, regression, minor-fix, compression, merge, collaboration, start, objective, planning, implementation, validation, completion, next, back, sync, status, update, help, pull, push, abort, report"
|
|
12186
|
+
};
|
|
12187
|
+
CONFIG_LINE = {
|
|
12188
|
+
en: "Settings: /reap.config",
|
|
12189
|
+
ko: "설정 확인: /reap.config",
|
|
12190
|
+
ja: "設定確認: /reap.config",
|
|
12191
|
+
"zh-CN": "查看设置: /reap.config"
|
|
12192
|
+
};
|
|
12193
|
+
LANGUAGE_ALIASES = {
|
|
12194
|
+
korean: "ko",
|
|
12195
|
+
english: "en",
|
|
12196
|
+
japanese: "ja",
|
|
12197
|
+
chinese: "zh-CN"
|
|
12198
|
+
};
|
|
12024
12199
|
});
|
|
12025
12200
|
|
|
12026
12201
|
// src/cli/commands/run/report.ts
|
|
@@ -12031,12 +12206,7 @@ __export(exports_report, {
|
|
|
12031
12206
|
async function execute16(paths, phase) {
|
|
12032
12207
|
const gm = new GenerationManager(paths);
|
|
12033
12208
|
const state = await gm.current();
|
|
12034
|
-
const configContent = await readTextFile(paths.config);
|
|
12035
12209
|
if (!phase || phase === "collect") {
|
|
12036
|
-
const autoIssueReport = configContent?.match(/autoIssueReport:\s*false/);
|
|
12037
|
-
if (autoIssueReport) {
|
|
12038
|
-
emitError("report", "Issue reporting is disabled. Set `autoIssueReport: true` in .reap/config.yml to enable.");
|
|
12039
|
-
}
|
|
12040
12210
|
emitOutput({
|
|
12041
12211
|
status: "prompt",
|
|
12042
12212
|
command: "report",
|
|
@@ -12088,7 +12258,6 @@ async function execute16(paths, phase) {
|
|
|
12088
12258
|
}
|
|
12089
12259
|
var init_report = __esm(() => {
|
|
12090
12260
|
init_generation();
|
|
12091
|
-
init_fs();
|
|
12092
12261
|
});
|
|
12093
12262
|
|
|
12094
12263
|
// src/core/merge.ts
|
|
@@ -12158,7 +12327,7 @@ var init_merge = __esm(() => {
|
|
|
12158
12327
|
|
|
12159
12328
|
// src/core/merge-generation.ts
|
|
12160
12329
|
import { readdir as readdir17, mkdir as mkdir8, rename as rename3 } from "fs/promises";
|
|
12161
|
-
import { join as
|
|
12330
|
+
import { join as join25 } from "path";
|
|
12162
12331
|
|
|
12163
12332
|
class MergeGenerationManager {
|
|
12164
12333
|
paths;
|
|
@@ -12169,7 +12338,7 @@ class MergeGenerationManager {
|
|
|
12169
12338
|
const content = await readTextFile(this.paths.currentYml);
|
|
12170
12339
|
if (content === null || !content.trim())
|
|
12171
12340
|
return null;
|
|
12172
|
-
const state =
|
|
12341
|
+
const state = import_yaml10.default.parse(content);
|
|
12173
12342
|
if (!state.type)
|
|
12174
12343
|
state.type = "normal";
|
|
12175
12344
|
if (!state.parents)
|
|
@@ -12202,7 +12371,7 @@ class MergeGenerationManager {
|
|
|
12202
12371
|
genomeHash,
|
|
12203
12372
|
commonAncestor: commonAncestor ?? undefined
|
|
12204
12373
|
};
|
|
12205
|
-
await writeTextFile(this.paths.currentYml,
|
|
12374
|
+
await writeTextFile(this.paths.currentYml, import_yaml10.default.stringify(state));
|
|
12206
12375
|
return state;
|
|
12207
12376
|
}
|
|
12208
12377
|
async createFromBranch(targetBranch, projectRoot) {
|
|
@@ -12246,7 +12415,7 @@ class MergeGenerationManager {
|
|
|
12246
12415
|
genomeHash,
|
|
12247
12416
|
commonAncestor: commonAncestor ?? undefined
|
|
12248
12417
|
};
|
|
12249
|
-
await writeTextFile(this.paths.currentYml,
|
|
12418
|
+
await writeTextFile(this.paths.currentYml, import_yaml10.default.stringify(state));
|
|
12250
12419
|
return { state, report };
|
|
12251
12420
|
}
|
|
12252
12421
|
async resolveLatestGenId(branch, cwd) {
|
|
@@ -12271,7 +12440,7 @@ class MergeGenerationManager {
|
|
|
12271
12440
|
const content = gitShow(ref, metaFile, cwd);
|
|
12272
12441
|
if (content) {
|
|
12273
12442
|
try {
|
|
12274
|
-
const meta =
|
|
12443
|
+
const meta = import_yaml10.default.parse(content);
|
|
12275
12444
|
if (meta?.id)
|
|
12276
12445
|
metas.push(meta);
|
|
12277
12446
|
} catch {}
|
|
@@ -12318,7 +12487,7 @@ class MergeGenerationManager {
|
|
|
12318
12487
|
if (!state.timeline)
|
|
12319
12488
|
state.timeline = [];
|
|
12320
12489
|
state.timeline.push({ stage: next, at: new Date().toISOString() });
|
|
12321
|
-
await writeTextFile(this.paths.currentYml,
|
|
12490
|
+
await writeTextFile(this.paths.currentYml, import_yaml10.default.stringify(state));
|
|
12322
12491
|
return state;
|
|
12323
12492
|
}
|
|
12324
12493
|
async complete() {
|
|
@@ -12344,19 +12513,19 @@ class MergeGenerationManager {
|
|
|
12344
12513
|
startedAt: state.startedAt,
|
|
12345
12514
|
completedAt: now
|
|
12346
12515
|
};
|
|
12347
|
-
await writeTextFile(
|
|
12516
|
+
await writeTextFile(join25(genDir, "meta.yml"), import_yaml10.default.stringify(meta));
|
|
12348
12517
|
const lifeEntries = await readdir17(this.paths.life);
|
|
12349
12518
|
for (const entry of lifeEntries) {
|
|
12350
12519
|
if (/^\d{2}-[a-z]+(?:-[a-z]+)*\.md$/.test(entry)) {
|
|
12351
|
-
await rename3(
|
|
12520
|
+
await rename3(join25(this.paths.life, entry), join25(genDir, entry));
|
|
12352
12521
|
}
|
|
12353
12522
|
}
|
|
12354
|
-
const backlogDir =
|
|
12523
|
+
const backlogDir = join25(genDir, "backlog");
|
|
12355
12524
|
await mkdir8(backlogDir, { recursive: true });
|
|
12356
12525
|
try {
|
|
12357
12526
|
const backlogEntries = await readdir17(this.paths.backlog);
|
|
12358
12527
|
for (const entry of backlogEntries) {
|
|
12359
|
-
await rename3(
|
|
12528
|
+
await rename3(join25(this.paths.backlog, entry), join25(backlogDir, entry));
|
|
12360
12529
|
}
|
|
12361
12530
|
} catch {}
|
|
12362
12531
|
await writeTextFile(this.paths.currentYml, "");
|
|
@@ -12364,7 +12533,7 @@ class MergeGenerationManager {
|
|
|
12364
12533
|
return compression;
|
|
12365
12534
|
}
|
|
12366
12535
|
async save(state) {
|
|
12367
|
-
await writeTextFile(this.paths.currentYml,
|
|
12536
|
+
await writeTextFile(this.paths.currentYml, import_yaml10.default.stringify(state));
|
|
12368
12537
|
}
|
|
12369
12538
|
}
|
|
12370
12539
|
function canFastForward(localLatestId, remoteLatestId, allMetas) {
|
|
@@ -12426,7 +12595,7 @@ function findCommonAncestor(idA, idB, metas) {
|
|
|
12426
12595
|
}
|
|
12427
12596
|
return null;
|
|
12428
12597
|
}
|
|
12429
|
-
var
|
|
12598
|
+
var import_yaml10;
|
|
12430
12599
|
var init_merge_generation = __esm(() => {
|
|
12431
12600
|
init_merge_lifecycle();
|
|
12432
12601
|
init_compression();
|
|
@@ -12436,7 +12605,7 @@ var init_merge_generation = __esm(() => {
|
|
|
12436
12605
|
init_merge();
|
|
12437
12606
|
init_lineage();
|
|
12438
12607
|
init_compression();
|
|
12439
|
-
|
|
12608
|
+
import_yaml10 = __toESM(require_dist(), 1);
|
|
12440
12609
|
});
|
|
12441
12610
|
|
|
12442
12611
|
// src/cli/commands/run/merge-start.ts
|
|
@@ -13307,11 +13476,46 @@ var init_pull = __esm(() => {
|
|
|
13307
13476
|
init_merge_generation();
|
|
13308
13477
|
});
|
|
13309
13478
|
|
|
13479
|
+
// src/cli/commands/run/config.ts
|
|
13480
|
+
var exports_config = {};
|
|
13481
|
+
__export(exports_config, {
|
|
13482
|
+
execute: () => execute27
|
|
13483
|
+
});
|
|
13484
|
+
async function execute27(paths) {
|
|
13485
|
+
const config = await ConfigManager.read(paths);
|
|
13486
|
+
const lines = [
|
|
13487
|
+
`REAP Configuration (${paths.config})`,
|
|
13488
|
+
"",
|
|
13489
|
+
` version: ${config.version}`,
|
|
13490
|
+
` project: ${config.project}`,
|
|
13491
|
+
` entryMode: ${config.entryMode}`,
|
|
13492
|
+
` strict: ${config.strict ?? false}`,
|
|
13493
|
+
` language: ${config.language ?? "(not set)"}`,
|
|
13494
|
+
` autoUpdate: ${config.autoUpdate ?? true}`,
|
|
13495
|
+
` autoSubagent: ${config.autoSubagent ?? true}`,
|
|
13496
|
+
` autoIssueReport: ${config.autoIssueReport ?? false}`,
|
|
13497
|
+
"",
|
|
13498
|
+
"Edit .reap/config.yml to change settings."
|
|
13499
|
+
].join(`
|
|
13500
|
+
`);
|
|
13501
|
+
emitOutput({
|
|
13502
|
+
status: "ok",
|
|
13503
|
+
command: "config",
|
|
13504
|
+
phase: "show",
|
|
13505
|
+
completed: ["read-config"],
|
|
13506
|
+
message: lines
|
|
13507
|
+
});
|
|
13508
|
+
}
|
|
13509
|
+
var init_config2 = __esm(() => {
|
|
13510
|
+
init_config();
|
|
13511
|
+
});
|
|
13512
|
+
|
|
13310
13513
|
// src/cli/commands/run/index.ts
|
|
13311
13514
|
var exports_run = {};
|
|
13312
13515
|
__export(exports_run, {
|
|
13313
13516
|
runCommand: () => runCommand
|
|
13314
13517
|
});
|
|
13518
|
+
import { execSync as execSync6 } from "child_process";
|
|
13315
13519
|
async function runCommand(command, phase) {
|
|
13316
13520
|
const cwd = process.cwd();
|
|
13317
13521
|
const paths = new ReapPaths(cwd);
|
|
@@ -13322,12 +13526,33 @@ async function runCommand(command, phase) {
|
|
|
13322
13526
|
if (!loader) {
|
|
13323
13527
|
emitError(command, `Unknown command: ${command}. Available: ${Object.keys(COMMANDS).join(", ")}`);
|
|
13324
13528
|
}
|
|
13325
|
-
|
|
13326
|
-
|
|
13529
|
+
try {
|
|
13530
|
+
const mod = await loader();
|
|
13531
|
+
await mod.execute(paths, phase);
|
|
13532
|
+
} catch (err) {
|
|
13533
|
+
try {
|
|
13534
|
+
const config = await ConfigManager.read(paths);
|
|
13535
|
+
if (config.autoIssueReport) {
|
|
13536
|
+
const version = "0.12.0";
|
|
13537
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
13538
|
+
const title = `[auto] reap run ${command}: ${errMsg.slice(0, 80)}`;
|
|
13539
|
+
const body = [
|
|
13540
|
+
`**REAP Version**: ${version}`,
|
|
13541
|
+
`**Command**: reap run ${command}${phase ? ` --phase ${phase}` : ""}`,
|
|
13542
|
+
`**Error**: ${errMsg}`,
|
|
13543
|
+
`**OS**: ${process.platform} ${process.arch}`,
|
|
13544
|
+
`**Node**: ${process.version}`
|
|
13545
|
+
].join("\\n");
|
|
13546
|
+
execSync6(`gh issue create --repo c-d-cc/reap --title "${title}" --label "auto-reported,bug" --body "${body}"`, { stdio: "ignore", timeout: 1e4 });
|
|
13547
|
+
}
|
|
13548
|
+
} catch {}
|
|
13549
|
+
emitError(command, err instanceof Error ? err.message : String(err));
|
|
13550
|
+
}
|
|
13327
13551
|
}
|
|
13328
13552
|
var COMMANDS;
|
|
13329
13553
|
var init_run = __esm(() => {
|
|
13330
13554
|
init_paths();
|
|
13555
|
+
init_config();
|
|
13331
13556
|
COMMANDS = {
|
|
13332
13557
|
next: () => Promise.resolve().then(() => (init_next(), exports_next)),
|
|
13333
13558
|
back: () => Promise.resolve().then(() => (init_back(), exports_back)),
|
|
@@ -13354,7 +13579,8 @@ var init_run = __esm(() => {
|
|
|
13354
13579
|
"merge-completion": () => Promise.resolve().then(() => (init_merge_completion(), exports_merge_completion)),
|
|
13355
13580
|
"merge-evolve": () => Promise.resolve().then(() => (init_merge_evolve(), exports_merge_evolve)),
|
|
13356
13581
|
merge: () => Promise.resolve().then(() => (init_merge2(), exports_merge)),
|
|
13357
|
-
pull: () => Promise.resolve().then(() => (init_pull(), exports_pull))
|
|
13582
|
+
pull: () => Promise.resolve().then(() => (init_pull(), exports_pull)),
|
|
13583
|
+
config: () => Promise.resolve().then(() => (init_config2(), exports_config))
|
|
13358
13584
|
};
|
|
13359
13585
|
});
|
|
13360
13586
|
|
|
@@ -13572,6 +13798,30 @@ class ClaudeCodeAdapter {
|
|
|
13572
13798
|
} catch {}
|
|
13573
13799
|
return removed;
|
|
13574
13800
|
}
|
|
13801
|
+
async setupClaudeMd(projectRoot) {
|
|
13802
|
+
const claudeMdPath = join2(projectRoot, ".claude", "CLAUDE.md");
|
|
13803
|
+
const marker = "# REAP Project";
|
|
13804
|
+
const reapSection = `# REAP Project
|
|
13805
|
+
This project uses REAP. Session-start hook loads project knowledge on session start.
|
|
13806
|
+
If context was compacted and REAP knowledge is lost, re-run the session-start hook.
|
|
13807
|
+
`;
|
|
13808
|
+
await mkdir(join2(projectRoot, ".claude"), { recursive: true });
|
|
13809
|
+
const existing = await readTextFile(claudeMdPath);
|
|
13810
|
+
if (existing === null) {
|
|
13811
|
+
await writeTextFile(claudeMdPath, reapSection);
|
|
13812
|
+
return { action: "created" };
|
|
13813
|
+
}
|
|
13814
|
+
if (existing.includes(marker)) {
|
|
13815
|
+
const updated = existing.replace(/# REAP Project[\s\S]*?(?=\n# |\n*$)/, reapSection.trim());
|
|
13816
|
+
if (updated === existing)
|
|
13817
|
+
return { action: "skipped" };
|
|
13818
|
+
await writeTextFile(claudeMdPath, updated);
|
|
13819
|
+
return { action: "updated" };
|
|
13820
|
+
}
|
|
13821
|
+
await writeTextFile(claudeMdPath, reapSection + `
|
|
13822
|
+
` + existing);
|
|
13823
|
+
return { action: "created" };
|
|
13824
|
+
}
|
|
13575
13825
|
getHookEntry() {
|
|
13576
13826
|
const sessionStartPath = join2(ReapPaths.packageHooksDir, "session-start.cjs");
|
|
13577
13827
|
return {
|
|
@@ -13832,7 +14082,8 @@ var COMMAND_NAMES = [
|
|
|
13832
14082
|
"reap.merge.evolve",
|
|
13833
14083
|
"reap.merge",
|
|
13834
14084
|
"reap.pull",
|
|
13835
|
-
"reap.push"
|
|
14085
|
+
"reap.push",
|
|
14086
|
+
"reap.config"
|
|
13836
14087
|
];
|
|
13837
14088
|
async function initProject(projectRoot, projectName, entryMode, preset, onProgress) {
|
|
13838
14089
|
const log = onProgress ?? (() => {});
|
|
@@ -13866,11 +14117,15 @@ async function initProject(projectRoot, projectName, entryMode, preset, onProgre
|
|
|
13866
14117
|
if (!hasGhCli) {
|
|
13867
14118
|
log("GitHub CLI(gh) not found. Install from https://cli.github.com for auto issue reporting.");
|
|
13868
14119
|
}
|
|
14120
|
+
const detectedLanguage = await AgentRegistry.readLanguage();
|
|
13869
14121
|
const config = {
|
|
13870
|
-
version: "0.
|
|
14122
|
+
version: "0.12.0",
|
|
13871
14123
|
project: projectName,
|
|
13872
14124
|
entryMode,
|
|
14125
|
+
strict: false,
|
|
14126
|
+
...detectedLanguage && { language: detectedLanguage },
|
|
13873
14127
|
autoUpdate: true,
|
|
14128
|
+
autoSubagent: true,
|
|
13874
14129
|
autoIssueReport: hasGhCli,
|
|
13875
14130
|
...preset && { preset }
|
|
13876
14131
|
};
|
|
@@ -13929,6 +14184,10 @@ async function initProject(projectRoot, projectName, entryMode, preset, onProgre
|
|
|
13929
14184
|
await adapter.installCommands(COMMAND_NAMES, sourceDir);
|
|
13930
14185
|
log(` Registering session hook for ${adapter.displayName}...`);
|
|
13931
14186
|
await adapter.registerSessionHook();
|
|
14187
|
+
if (typeof adapter.setupClaudeMd === "function") {
|
|
14188
|
+
const mdResult = await adapter.setupClaudeMd(projectRoot);
|
|
14189
|
+
log(` .claude/CLAUDE.md: ${mdResult.action}`);
|
|
14190
|
+
}
|
|
13932
14191
|
}
|
|
13933
14192
|
if (detectedAgents.length === 0) {
|
|
13934
14193
|
log(" No AI agents detected.");
|
|
@@ -14159,6 +14418,140 @@ class MigrationRunner {
|
|
|
14159
14418
|
}
|
|
14160
14419
|
}
|
|
14161
14420
|
|
|
14421
|
+
// src/core/migration-spec.ts
|
|
14422
|
+
init_fs();
|
|
14423
|
+
var import_yaml6 = __toESM(require_dist(), 1);
|
|
14424
|
+
import { existsSync as existsSync2 } from "fs";
|
|
14425
|
+
function buildMigrationSpec(paths) {
|
|
14426
|
+
const sections = [];
|
|
14427
|
+
sections.push(`## Config fields (config.yml)
|
|
14428
|
+
|
|
14429
|
+
| Field | Type | Required | Default |
|
|
14430
|
+
|-------|------|----------|---------|
|
|
14431
|
+
| version | string | yes | — |
|
|
14432
|
+
| project | string | yes | — |
|
|
14433
|
+
| entryMode | greenfield \\| migration \\| adoption | yes | — |
|
|
14434
|
+
| stack | string | no | — |
|
|
14435
|
+
| preset | string | no | — |
|
|
14436
|
+
| agents | AgentName[] | no | auto-detect |
|
|
14437
|
+
| language | string | no | — |
|
|
14438
|
+
| autoUpdate | boolean | no | true |
|
|
14439
|
+
| autoSubagent | boolean | no | true |
|
|
14440
|
+
| autoIssueReport | boolean | no | false |
|
|
14441
|
+
| strict | boolean \\| { edit?: boolean; merge?: boolean } | no | false |`);
|
|
14442
|
+
sections.push(`## Expected directory structure
|
|
14443
|
+
|
|
14444
|
+
.reap/
|
|
14445
|
+
├── config.yml
|
|
14446
|
+
├── genome/
|
|
14447
|
+
│ ├── principles.md
|
|
14448
|
+
│ ├── conventions.md
|
|
14449
|
+
│ ├── constraints.md
|
|
14450
|
+
│ ├── source-map.md
|
|
14451
|
+
│ └── domain/
|
|
14452
|
+
├── environment/
|
|
14453
|
+
│ ├── summary.md
|
|
14454
|
+
│ ├── docs/
|
|
14455
|
+
│ └── resources/
|
|
14456
|
+
├── life/
|
|
14457
|
+
│ ├── current.yml
|
|
14458
|
+
│ ├── backlog/
|
|
14459
|
+
│ ├── 01-objective.md
|
|
14460
|
+
│ ├── 02-planning.md
|
|
14461
|
+
│ ├── 03-implementation.md
|
|
14462
|
+
│ ├── 04-validation.md
|
|
14463
|
+
│ └── 05-completion.md
|
|
14464
|
+
├── lineage/
|
|
14465
|
+
│ └── gen-NNN-hash/ or gen-NNN-hash.md
|
|
14466
|
+
└── hooks/
|
|
14467
|
+
├── conditions/
|
|
14468
|
+
└── {event}.{name}.{sh|md}`);
|
|
14469
|
+
sections.push(`## Slash commands (29)
|
|
14470
|
+
|
|
14471
|
+
reap.objective, reap.planning, reap.implementation,
|
|
14472
|
+
reap.validation, reap.completion, reap.evolve,
|
|
14473
|
+
reap.start, reap.next, reap.back, reap.abort,
|
|
14474
|
+
reap.status, reap.sync, reap.sync.genome, reap.sync.environment,
|
|
14475
|
+
reap.help, reap.update, reap.report,
|
|
14476
|
+
reap.merge.start, reap.merge.detect, reap.merge.mate,
|
|
14477
|
+
reap.merge.merge, reap.merge.sync, reap.merge.validation,
|
|
14478
|
+
reap.merge.completion, reap.merge.evolve,
|
|
14479
|
+
reap.merge,
|
|
14480
|
+
reap.pull, reap.push,
|
|
14481
|
+
reap.config`);
|
|
14482
|
+
sections.push(`## Hooks format
|
|
14483
|
+
|
|
14484
|
+
File naming: {event}.{name}.{md|sh}
|
|
14485
|
+
Location: .reap/hooks/
|
|
14486
|
+
|
|
14487
|
+
Frontmatter (md hooks):
|
|
14488
|
+
---
|
|
14489
|
+
event: onLifeStarted
|
|
14490
|
+
name: my-hook
|
|
14491
|
+
description: What this hook does
|
|
14492
|
+
---
|
|
14493
|
+
|
|
14494
|
+
Condition files: .reap/hooks/conditions/{name}.yml`);
|
|
14495
|
+
sections.push(`## Project root: ${paths.projectRoot}`);
|
|
14496
|
+
return sections.join(`
|
|
14497
|
+
|
|
14498
|
+
`);
|
|
14499
|
+
}
|
|
14500
|
+
async function detectMigrationGaps(paths) {
|
|
14501
|
+
const gaps = [];
|
|
14502
|
+
const configContent = await readTextFile(paths.config);
|
|
14503
|
+
if (configContent === null) {
|
|
14504
|
+
gaps.push("config.yml missing");
|
|
14505
|
+
} else {
|
|
14506
|
+
try {
|
|
14507
|
+
const config = import_yaml6.default.parse(configContent);
|
|
14508
|
+
if (!config?.version)
|
|
14509
|
+
gaps.push("config.yml: missing required field 'version'");
|
|
14510
|
+
if (!config?.project)
|
|
14511
|
+
gaps.push("config.yml: missing required field 'project'");
|
|
14512
|
+
if (!config?.entryMode)
|
|
14513
|
+
gaps.push("config.yml: missing required field 'entryMode'");
|
|
14514
|
+
} catch {
|
|
14515
|
+
gaps.push("config.yml: invalid YAML");
|
|
14516
|
+
}
|
|
14517
|
+
}
|
|
14518
|
+
if (!existsSync2(paths.genome)) {
|
|
14519
|
+
gaps.push("genome/ directory missing");
|
|
14520
|
+
} else {
|
|
14521
|
+
const genomeFiles = [
|
|
14522
|
+
{ path: paths.principles, label: "genome/principles.md" },
|
|
14523
|
+
{ path: paths.conventions, label: "genome/conventions.md" },
|
|
14524
|
+
{ path: paths.constraints, label: "genome/constraints.md" },
|
|
14525
|
+
{ path: paths.sourceMap, label: "genome/source-map.md" }
|
|
14526
|
+
];
|
|
14527
|
+
for (const { path, label } of genomeFiles) {
|
|
14528
|
+
if (!existsSync2(path)) {
|
|
14529
|
+
gaps.push(`${label} missing`);
|
|
14530
|
+
}
|
|
14531
|
+
}
|
|
14532
|
+
}
|
|
14533
|
+
if (!existsSync2(paths.environment)) {
|
|
14534
|
+
gaps.push("environment/ directory missing");
|
|
14535
|
+
}
|
|
14536
|
+
if (!existsSync2(paths.life)) {
|
|
14537
|
+
gaps.push("life/ directory missing");
|
|
14538
|
+
} else {
|
|
14539
|
+
if (!existsSync2(paths.backlog)) {
|
|
14540
|
+
gaps.push("life/backlog/ directory missing");
|
|
14541
|
+
}
|
|
14542
|
+
}
|
|
14543
|
+
if (!existsSync2(paths.lineage)) {
|
|
14544
|
+
gaps.push("lineage/ directory missing");
|
|
14545
|
+
}
|
|
14546
|
+
if (!existsSync2(paths.hooks)) {
|
|
14547
|
+
gaps.push("hooks/ directory missing");
|
|
14548
|
+
}
|
|
14549
|
+
if (!existsSync2(paths.hookConditions)) {
|
|
14550
|
+
gaps.push("hooks/conditions/ directory missing");
|
|
14551
|
+
}
|
|
14552
|
+
return gaps;
|
|
14553
|
+
}
|
|
14554
|
+
|
|
14162
14555
|
// src/cli/commands/update.ts
|
|
14163
14556
|
function selfUpgrade() {
|
|
14164
14557
|
try {
|
|
@@ -14278,7 +14671,23 @@ async function updateProject(projectRoot, dryRun = false) {
|
|
|
14278
14671
|
result.skipped.push(`[${adapter.displayName}] session hook`);
|
|
14279
14672
|
}
|
|
14280
14673
|
}
|
|
14674
|
+
for (const adapter of adapters) {
|
|
14675
|
+
if (typeof adapter.setupClaudeMd === "function") {
|
|
14676
|
+
const mdResult = await adapter.setupClaudeMd(projectRoot);
|
|
14677
|
+
if (mdResult.action !== "skipped") {
|
|
14678
|
+
result.updated.push(`[${adapter.displayName}] .claude/CLAUDE.md (${mdResult.action})`);
|
|
14679
|
+
} else {
|
|
14680
|
+
result.skipped.push(`[${adapter.displayName}] .claude/CLAUDE.md`);
|
|
14681
|
+
}
|
|
14682
|
+
}
|
|
14683
|
+
}
|
|
14281
14684
|
if (await paths.isReapProject()) {
|
|
14685
|
+
if (!dryRun) {
|
|
14686
|
+
const backfillResult = await ConfigManager.backfill(paths);
|
|
14687
|
+
if (backfillResult.added.length > 0) {
|
|
14688
|
+
result.updated.push(`Config: added ${backfillResult.added.join(", ")}`);
|
|
14689
|
+
}
|
|
14690
|
+
}
|
|
14282
14691
|
const projectClaudeCommands = join10(paths.projectRoot, ".claude", "commands");
|
|
14283
14692
|
await mkdir6(projectClaudeCommands, { recursive: true });
|
|
14284
14693
|
const reapCmdFiles = (await readdir9(ReapPaths.userReapCommands)).filter((f) => f.startsWith("reap.") && f.endsWith(".md"));
|
|
@@ -14309,7 +14718,7 @@ async function updateProject(projectRoot, dryRun = false) {
|
|
|
14309
14718
|
result.skipped.push(`.claude/commands/ (${reapCmdFiles.length} unchanged)`);
|
|
14310
14719
|
}
|
|
14311
14720
|
await migrateLegacyFiles(paths, dryRun, result);
|
|
14312
|
-
const currentVersion = "0.
|
|
14721
|
+
const currentVersion = "0.12.0";
|
|
14313
14722
|
const migrationResult = await MigrationRunner.run(paths, currentVersion, dryRun);
|
|
14314
14723
|
for (const m of migrationResult.migrated) {
|
|
14315
14724
|
result.updated.push(`[migration] ${m}`);
|
|
@@ -14320,6 +14729,17 @@ async function updateProject(projectRoot, dryRun = false) {
|
|
|
14320
14729
|
for (const e of migrationResult.errors) {
|
|
14321
14730
|
result.removed.push(`[migration error] ${e}`);
|
|
14322
14731
|
}
|
|
14732
|
+
const gaps = await detectMigrationGaps(paths);
|
|
14733
|
+
if (gaps.length > 0) {
|
|
14734
|
+
const spec = buildMigrationSpec(paths);
|
|
14735
|
+
console.log(JSON.stringify({
|
|
14736
|
+
status: "prompt",
|
|
14737
|
+
command: "migrate",
|
|
14738
|
+
gaps,
|
|
14739
|
+
spec,
|
|
14740
|
+
prompt: "Analyze the gaps between current .reap/ structure and expected structure. Fix each gap after user confirmation."
|
|
14741
|
+
}, null, 2));
|
|
14742
|
+
}
|
|
14323
14743
|
if (migrationResult.errors.length > 0 && config?.autoIssueReport) {
|
|
14324
14744
|
try {
|
|
14325
14745
|
const { execSync: execSync3 } = await import("child_process");
|
|
@@ -14415,7 +14835,7 @@ async function getStatus(projectRoot) {
|
|
|
14415
14835
|
init_paths();
|
|
14416
14836
|
init_lifecycle();
|
|
14417
14837
|
init_fs();
|
|
14418
|
-
var
|
|
14838
|
+
var import_yaml7 = __toESM(require_dist(), 1);
|
|
14419
14839
|
import { mkdir as mkdir7, stat as stat3, copyFile } from "fs/promises";
|
|
14420
14840
|
import { join as join11 } from "path";
|
|
14421
14841
|
async function dirExists(path) {
|
|
@@ -14468,7 +14888,7 @@ async function fixProject(projectRoot) {
|
|
|
14468
14888
|
if (currentContent !== null) {
|
|
14469
14889
|
if (currentContent.trim()) {
|
|
14470
14890
|
try {
|
|
14471
|
-
const state =
|
|
14891
|
+
const state = import_yaml7.default.parse(currentContent);
|
|
14472
14892
|
if (!state.stage || !LifeCycle.isValid(state.stage)) {
|
|
14473
14893
|
issues.push(`Invalid stage "${state.stage}" in current.yml. Valid stages: ${LifeCycle.stages().join(", ")}. Manual correction required.`);
|
|
14474
14894
|
}
|
|
@@ -14495,8 +14915,8 @@ init_paths();
|
|
|
14495
14915
|
init_fs();
|
|
14496
14916
|
init_version();
|
|
14497
14917
|
init_config();
|
|
14498
|
-
import { join as
|
|
14499
|
-
program.name("reap").description("REAP — Recursive Evolutionary Autonomous Pipeline").version("0.
|
|
14918
|
+
import { join as join26 } from "path";
|
|
14919
|
+
program.name("reap").description("REAP — Recursive Evolutionary Autonomous Pipeline").version("0.12.0");
|
|
14500
14920
|
program.command("init").description("Initialize a new REAP project (Genesis)").argument("[project-name]", "Project name (defaults to current directory name)").option("-m, --mode <mode>", "Entry mode: greenfield, migration, adoption", "greenfield").option("-p, --preset <preset>", "Bootstrap with a genome preset (e.g., bun-hono-react)").action(async (projectName, options) => {
|
|
14501
14921
|
try {
|
|
14502
14922
|
const cwd = process.cwd();
|
|
@@ -14504,9 +14924,9 @@ program.command("init").description("Initialize a new REAP project (Genesis)").a
|
|
|
14504
14924
|
let mode = options.mode;
|
|
14505
14925
|
const modeExplicit = process.argv.some((a) => a === "-m" || a === "--mode");
|
|
14506
14926
|
if (!modeExplicit && mode === "greenfield") {
|
|
14507
|
-
const { existsSync:
|
|
14927
|
+
const { existsSync: existsSync3 } = __require("fs");
|
|
14508
14928
|
const signals = ["package.json", "go.mod", "Cargo.toml", "pom.xml", "pyproject.toml", "Makefile", "CMakeLists.txt"];
|
|
14509
|
-
const hasExistingProject = signals.some((f) =>
|
|
14929
|
+
const hasExistingProject = signals.some((f) => existsSync3(__require("path").join(cwd, f)));
|
|
14510
14930
|
if (hasExistingProject) {
|
|
14511
14931
|
mode = "adoption";
|
|
14512
14932
|
console.log(`Existing project detected. Automatically using adoption mode.`);
|
|
@@ -14630,10 +15050,10 @@ program.command("help").description("Show REAP commands, slash commands, and wor
|
|
|
14630
15050
|
if (l === "korean" || l === "ko")
|
|
14631
15051
|
lang = "ko";
|
|
14632
15052
|
}
|
|
14633
|
-
const helpDir =
|
|
14634
|
-
let helpText = await readTextFile(
|
|
15053
|
+
const helpDir = join26(ReapPaths.packageTemplatesDir, "help");
|
|
15054
|
+
let helpText = await readTextFile(join26(helpDir, `${lang}.txt`));
|
|
14635
15055
|
if (!helpText)
|
|
14636
|
-
helpText = await readTextFile(
|
|
15056
|
+
helpText = await readTextFile(join26(helpDir, "en.txt"));
|
|
14637
15057
|
if (!helpText) {
|
|
14638
15058
|
console.log("Help file not found. Run 'reap update' to install templates.");
|
|
14639
15059
|
return;
|
|
@@ -156,21 +156,21 @@ REAP supports multiple AI agents simultaneously through the AgentAdapter abstrac
|
|
|
156
156
|
|
|
157
157
|
## Execution Flow
|
|
158
158
|
|
|
159
|
+
**Lifecycle stages** (5 stages, in order):
|
|
159
160
|
```
|
|
160
|
-
|
|
161
|
-
2. /reap.objective → Define goal + requirements
|
|
162
|
-
3. /reap.next
|
|
163
|
-
4. /reap.planning → Task decomposition + implementation plan
|
|
164
|
-
5. /reap.next
|
|
165
|
-
6. /reap.implementation → Code implementation
|
|
166
|
-
7. /reap.next
|
|
167
|
-
8. /reap.validation → Verification
|
|
168
|
-
9. /reap.next
|
|
169
|
-
10. /reap.completion → Retrospective + genome updates
|
|
170
|
-
11. /reap.next → Archiving, generation ends
|
|
161
|
+
objective → planning → implementation → validation → completion
|
|
171
162
|
```
|
|
172
163
|
|
|
173
|
-
|
|
164
|
+
**Execution sequence**:
|
|
165
|
+
1. `/reap.start` — Create a new Generation
|
|
166
|
+
2. `/reap.objective` — Define goal + requirements → `/reap.next`
|
|
167
|
+
3. `/reap.planning` — Task decomposition + plan → `/reap.next`
|
|
168
|
+
4. `/reap.implementation` — Code implementation → `/reap.next`
|
|
169
|
+
5. `/reap.validation` — Verification → `/reap.next`
|
|
170
|
+
6. `/reap.completion` — Retrospective + genome updates + archiving (auto)
|
|
171
|
+
|
|
172
|
+
`/reap.next` is a **transition command**, not a lifecycle stage. It advances `current.yml` to the next stage.
|
|
173
|
+
`/reap.completion` auto-archives after the genome phase — no separate `/reap.next` needed at the end.
|
|
174
174
|
|
|
175
175
|
## Language
|
|
176
176
|
|
|
@@ -204,3 +204,4 @@ When `strict: true` is set in `.reap/config.yml`, the AI agent enforces code mod
|
|
|
204
204
|
4. **Genome is the authoritative source of truth.** When making any decision about architecture, conventions, constraints, or domain rules, ALWAYS consult the Genome first. If you observe code that contradicts the Genome, flag it as a potential `genome-change` backlog item. Do NOT silently ignore discrepancies.
|
|
205
205
|
5. **Keep Genome fresh.** If you notice the Genome is missing information about current code patterns, or contains outdated information, inform the human and suggest `/reap.sync`. The human may choose to defer sync — respect that choice, but always flag the staleness.
|
|
206
206
|
6. **Report malfunctions.** If you detect unexpected behavior during REAP operations (state inconsistency, command failure, corrupted files), suggest `/reap.report` to the user. This helps improve REAP for everyone.
|
|
207
|
+
- If `reap run` returns an unexpected error (not a gate failure), and the error repeats 2+ times, automatically run `/reap.report`.
|