@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.
- package/README.ja.md +31 -19
- package/README.ko.md +31 -19
- package/README.md +31 -19
- package/README.zh-CN.md +31 -19
- package/dist/cli.js +35 -21
- package/dist/templates/commands/reap.back.md +12 -4
- package/dist/templates/commands/reap.completion.md +33 -0
- package/dist/templates/commands/reap.next.md +23 -7
- package/dist/templates/commands/reap.start.md +12 -4
- package/dist/templates/conditions/always.sh +3 -0
- package/dist/templates/conditions/has-code-changes.sh +13 -0
- package/dist/templates/conditions/version-bumped.sh +17 -0
- package/dist/templates/genome/constraints.md +1 -1
- package/dist/templates/genome/conventions.md +1 -1
- package/dist/templates/genome/principles.md +3 -7
- package/dist/templates/genome/source-map.md +22 -0
- package/dist/templates/hooks/reap-guide.md +27 -19
- package/dist/templates/hooks/session-init-format.md +2 -0
- package/dist/templates/hooks/session-start.cjs +250 -0
- package/dist/templates/presets/bun-hono-react/source-map.md +22 -0
- package/package.json +1 -1
- package/dist/templates/hooks/session-start.sh +0 -200
package/README.ja.md
CHANGED
|
@@ -38,6 +38,7 @@ REAPは**世代ベースの進化モデル**でこれらの問題を解決しま
|
|
|
38
38
|
- AIエージェントが毎セッション開始時に現在のコンテキストを自動認識(SessionStart Hook)
|
|
39
39
|
- 実装中に発見した設計問題はbacklogに記録、Completionで反映
|
|
40
40
|
- レトロスペクティブ(Completion)で導き出した教訓がGenomeに蓄積
|
|
41
|
+
- 世代を重ねて繰り返される手作業を自動検出し、ユーザー確認の上でHookとして生成
|
|
41
42
|
|
|
42
43
|
## インストール
|
|
43
44
|
|
|
@@ -97,7 +98,7 @@ Objective → Planning → Implementation ⟷ Validation → Completion
|
|
|
97
98
|
| **Planning** | タスク分解、実装アプローチ、依存関係 | `02-planning.md` |
|
|
98
99
|
| **Implementation** | AI+Human協力でコード実装 | `03-implementation.md` |
|
|
99
100
|
| **Validation** | テスト実行、完了条件の確認 | `04-validation.md` |
|
|
100
|
-
| **Completion** | レトロスペクティブ + Genome変更反映 + アーカイブ | `05-completion.md` |
|
|
101
|
+
| **Completion** | レトロスペクティブ + Genome変更反映 + Hook提案 + アーカイブ | `05-completion.md` |
|
|
101
102
|
|
|
102
103
|
## コアコンセプト
|
|
103
104
|
|
|
@@ -110,7 +111,8 @@ Objective → Planning → Implementation ⟷ Validation → Completion
|
|
|
110
111
|
├── principles.md # アーキテクチャ原則/決定
|
|
111
112
|
├── domain/ # ビジネスルール(モジュール別)
|
|
112
113
|
├── conventions.md # 開発ルール/コンベンション
|
|
113
|
-
|
|
114
|
+
├── constraints.md # 技術制約/選択
|
|
115
|
+
└── source-map.md # C4 Container/Componentダイアグラム(Mermaid)
|
|
114
116
|
```
|
|
115
117
|
|
|
116
118
|
**Genome不変原則**: 現在の世代ではGenomeを直接変更しません。問題を発見した場合はbacklogに記録し、Completionステージでのみ反映します。
|
|
@@ -193,6 +195,8 @@ REAPはスラッシュコマンドとセッションフックを通じてAIエ
|
|
|
193
195
|
- REAPワークフロー全体のガイド(Genome、ライフサイクル、4軸構造など)
|
|
194
196
|
- 現在のGeneration状態(どのステージにいるか、次に何をすべきか)
|
|
195
197
|
- REAPライフサイクルに従うルール
|
|
198
|
+
- Genome鮮度検出 — 最後のGenome更新以降にコード関連のコミット(`src/`、`tests/`、`package.json`、`tsconfig.json`、`scripts/`)があったかを確認(ドキュメントのみの変更は除外)
|
|
199
|
+
- Source-mapドリフト検出 — `source-map.md`に記録されたコンポーネントとプロジェクト内の実際のファイルを比較
|
|
196
200
|
|
|
197
201
|
これにより、新しいセッションを開いてもエージェントがプロジェクトコンテキストを即座に把握します。
|
|
198
202
|
|
|
@@ -220,22 +224,28 @@ Strictモードはデフォルトで無効です(`strict: false`)。
|
|
|
220
224
|
|
|
221
225
|
### REAP Hooks
|
|
222
226
|
|
|
223
|
-
|
|
227
|
+
Hookはファイルベースで`.reap/hooks/`に保存されます。各Hookは`{event}.{name}.{md|sh}`形式のファイルです:
|
|
224
228
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
- command: "echo 'Regressed'"
|
|
229
|
+
- `.md`ファイルはAIプロンプトを含みます(AIエージェントが実行)
|
|
230
|
+
- `.sh`ファイルはシェルスクリプトを含みます(直接実行)
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
.reap/hooks/
|
|
234
|
+
├── onGenerationStart.context-load.md
|
|
235
|
+
├── onGenerationComplete.version-bump.md
|
|
236
|
+
├── onGenerationComplete.readme-update.md
|
|
237
|
+
├── onStageTransition.notify.sh
|
|
238
|
+
└── onRegression.alert.sh
|
|
236
239
|
```
|
|
237
240
|
|
|
238
|
-
各
|
|
241
|
+
各Hookファイルは以下のフィールドを持つfrontmatterをサポートします:
|
|
242
|
+
|
|
243
|
+
```yaml
|
|
244
|
+
---
|
|
245
|
+
condition: has-code-changes # always | has-code-changes | version-bumped
|
|
246
|
+
order: 10 # 実行順序(小さいほど先に実行)
|
|
247
|
+
---
|
|
248
|
+
```
|
|
239
249
|
|
|
240
250
|
| イベント | トリガー |
|
|
241
251
|
|----------|----------|
|
|
@@ -244,7 +254,7 @@ hooks:
|
|
|
244
254
|
| `onGenerationComplete` | `/reap.next`で完了したGenerationをアーカイブ後 |
|
|
245
255
|
| `onRegression` | `/reap.back`で前のステージに回帰後 |
|
|
246
256
|
|
|
247
|
-
HookはAI
|
|
257
|
+
HookはAIエージェントがプロジェクトルートディレクトリで実行します。`onGenerationComplete` Hookには自動バージョンバンプ判定が含まれています — patchレベルは自動適用され、minor/majorバンプはユーザー確認が必要です。
|
|
248
258
|
|
|
249
259
|
## `reap init`後のプロジェクト構造
|
|
250
260
|
|
|
@@ -257,7 +267,9 @@ my-project/
|
|
|
257
267
|
│ ├── principles.md
|
|
258
268
|
│ ├── domain/
|
|
259
269
|
│ ├── conventions.md
|
|
260
|
-
│
|
|
270
|
+
│ ├── constraints.md
|
|
271
|
+
│ └── source-map.md
|
|
272
|
+
├── hooks/ # Lifecycle hooks (.md/.sh)
|
|
261
273
|
├── environment/ # 外部環境
|
|
262
274
|
├── life/ # 現在の世代
|
|
263
275
|
│ ├── current.yml
|
|
@@ -275,10 +287,10 @@ my-project/
|
|
|
275
287
|
|
|
276
288
|
| レベル | 入力 | 出力 | 最大行数 | トリガー |
|
|
277
289
|
|--------|------|------|----------|----------|
|
|
278
|
-
| **Level 1** | 世代フォルダ(5つの成果物) | `gen-XXX.md` | 40行 | lineage >
|
|
290
|
+
| **Level 1** | 世代フォルダ(5つの成果物) | `gen-XXX.md` | 40行 | lineage > 5,000行 + 5世代以上 |
|
|
279
291
|
| **Level 2** | Level 1ファイル5つ | `epoch-XXX.md` | 60行 | Level 1が5つ以上 |
|
|
280
292
|
|
|
281
|
-
|
|
293
|
+
圧縮は世代完了時に自動実行されます。直近3世代は常に圧縮から保護されます。圧縮されたファイルは目標(Objective)と結果(Completion)を中心に保存し、中間過程は特記事項のみを残します。
|
|
282
294
|
|
|
283
295
|
## 進化フロー(Evolution Flow)
|
|
284
296
|
|
package/README.ko.md
CHANGED
|
@@ -38,6 +38,7 @@ REAP은 **세대 기반 진화 모델**로 이 문제들을 해결합니다:
|
|
|
38
38
|
- AI 에이전트가 매 세션 시작 시 현재 맥락을 자동으로 인식 (SessionStart Hook)
|
|
39
39
|
- 구현 중 발견한 설계 문제는 backlog에 기록, Completion에서 반영
|
|
40
40
|
- 회고(Completion)에서 도출한 교훈이 Genome에 축적
|
|
41
|
+
- 세대를 거듭하며 반복되는 수작업을 자동 감지하고, 사용자 확인 후 Hook으로 생성
|
|
41
42
|
|
|
42
43
|
## 설치
|
|
43
44
|
|
|
@@ -97,7 +98,7 @@ Objective → Planning → Implementation ⟷ Validation → Completion
|
|
|
97
98
|
| **Planning** | 태스크 분해, 구현 접근법, 의존관계 | `02-planning.md` |
|
|
98
99
|
| **Implementation** | AI+Human 협업으로 코드 구현 | `03-implementation.md` |
|
|
99
100
|
| **Validation** | 테스트 실행, 완료 조건 점검 | `04-validation.md` |
|
|
100
|
-
| **Completion** | 회고 + Genome 변경 반영 + 아카이빙 | `05-completion.md` |
|
|
101
|
+
| **Completion** | 회고 + Genome 변경 반영 + Hook 제안 + 아카이빙 | `05-completion.md` |
|
|
101
102
|
|
|
102
103
|
## 핵심 개념
|
|
103
104
|
|
|
@@ -110,7 +111,8 @@ Application의 유전 정보 — 아키텍처 원칙, 비즈니스 규칙, 개
|
|
|
110
111
|
├── principles.md # 아키텍처 원칙/결정
|
|
111
112
|
├── domain/ # 비즈니스 규칙 (모듈별)
|
|
112
113
|
├── conventions.md # 개발 규칙/컨벤션
|
|
113
|
-
|
|
114
|
+
├── constraints.md # 기술 제약/선택
|
|
115
|
+
└── source-map.md # C4 Container/Component 다이어그램 (Mermaid)
|
|
114
116
|
```
|
|
115
117
|
|
|
116
118
|
**Genome 불변 원칙**: 현재 세대에서는 Genome을 직접 수정하지 않습니다. 문제를 발견하면 backlog에 기록하고, Completion 단계에서만 반영합니다.
|
|
@@ -193,6 +195,8 @@ Slash command가 `.claude/commands/`에 설치되어 전체 워크플로우를
|
|
|
193
195
|
- REAP 워크플로우 전체 가이드 (Genome, Life Cycle, 4축 구조 등)
|
|
194
196
|
- 현재 Generation 상태 (어떤 stage인지, 다음에 뭘 해야 하는지)
|
|
195
197
|
- REAP lifecycle을 따르라는 규칙
|
|
198
|
+
- Genome 최신성 감지 — 마지막 Genome 업데이트 이후 코드 관련 커밋(`src/`, `tests/`, `package.json`, `tsconfig.json`, `scripts/`)이 있었는지 확인 (문서 전용 변경은 제외)
|
|
199
|
+
- Source-map 드리프트 감지 — `source-map.md`에 기록된 컴포넌트와 프로젝트의 실제 파일을 비교
|
|
196
200
|
|
|
197
201
|
이를 통해 새 세션을 열어도 에이전트가 프로젝트 맥락을 즉시 파악합니다.
|
|
198
202
|
|
|
@@ -220,22 +224,28 @@ Strict 모드는 기본적으로 비활성화되어 있습니다 (`strict: false
|
|
|
220
224
|
|
|
221
225
|
### REAP Hooks
|
|
222
226
|
|
|
223
|
-
`.reap/
|
|
227
|
+
Hook은 파일 기반이며 `.reap/hooks/`에 저장됩니다. 각 Hook은 `{event}.{name}.{md|sh}` 형식의 파일입니다:
|
|
224
228
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
- command: "echo 'Regressed'"
|
|
229
|
+
- `.md` 파일은 AI 프롬프트를 담고 있습니다 (AI 에이전트가 실행)
|
|
230
|
+
- `.sh` 파일은 셸 스크립트를 담고 있습니다 (직접 실행)
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
.reap/hooks/
|
|
234
|
+
├── onGenerationStart.context-load.md
|
|
235
|
+
├── onGenerationComplete.version-bump.md
|
|
236
|
+
├── onGenerationComplete.readme-update.md
|
|
237
|
+
├── onStageTransition.notify.sh
|
|
238
|
+
└── onRegression.alert.sh
|
|
236
239
|
```
|
|
237
240
|
|
|
238
|
-
각
|
|
241
|
+
각 Hook 파일은 다음 필드를 가진 frontmatter를 지원합니다:
|
|
242
|
+
|
|
243
|
+
```yaml
|
|
244
|
+
---
|
|
245
|
+
condition: has-code-changes # always | has-code-changes | version-bumped
|
|
246
|
+
order: 10 # 실행 순서 (낮을수록 먼저 실행)
|
|
247
|
+
---
|
|
248
|
+
```
|
|
239
249
|
|
|
240
250
|
| 이벤트 | 트리거 |
|
|
241
251
|
|--------|--------|
|
|
@@ -244,7 +254,7 @@ hooks:
|
|
|
244
254
|
| `onGenerationComplete` | `/reap.next`로 완료된 Generation 아카이빙 후 |
|
|
245
255
|
| `onRegression` | `/reap.back`으로 이전 stage 복귀 후 |
|
|
246
256
|
|
|
247
|
-
Hook은 AI 에이전트가 프로젝트 루트 디렉토리에서 실행합니다.
|
|
257
|
+
Hook은 AI 에이전트가 프로젝트 루트 디렉토리에서 실행합니다. `onGenerationComplete` Hook에는 자동 버전 범프 판단이 포함되어 있습니다 — patch 수준은 자동으로 적용되고, minor/major 범프는 사용자 확인을 거칩니다.
|
|
248
258
|
|
|
249
259
|
## `reap init` 후 프로젝트 구조
|
|
250
260
|
|
|
@@ -257,7 +267,9 @@ my-project/
|
|
|
257
267
|
│ ├── principles.md
|
|
258
268
|
│ ├── domain/
|
|
259
269
|
│ ├── conventions.md
|
|
260
|
-
│
|
|
270
|
+
│ ├── constraints.md
|
|
271
|
+
│ └── source-map.md
|
|
272
|
+
├── hooks/ # Lifecycle hooks (.md/.sh)
|
|
261
273
|
├── environment/ # 외부 환경
|
|
262
274
|
├── life/ # 현재 세대
|
|
263
275
|
│ ├── current.yml
|
|
@@ -275,10 +287,10 @@ my-project/
|
|
|
275
287
|
|
|
276
288
|
| 레벨 | 입력 | 출력 | 최대 줄 수 | 트리거 |
|
|
277
289
|
|------|------|------|-----------|--------|
|
|
278
|
-
| **Level 1** | 세대 폴더 (5개 산출물) | `gen-XXX.md` | 40줄 | lineage >
|
|
290
|
+
| **Level 1** | 세대 폴더 (5개 산출물) | `gen-XXX.md` | 40줄 | lineage > 5,000줄 + 5세대 이상 |
|
|
279
291
|
| **Level 2** | Level 1 파일 5개 | `epoch-XXX.md` | 60줄 | Level 1이 5개 이상 |
|
|
280
292
|
|
|
281
|
-
압축은 세대 완료 시 자동 실행됩니다. 압축된 파일은 목표(Objective)와 결과(Completion)를 중심으로 보존하고, 중간 과정은 특이사항만 남깁니다.
|
|
293
|
+
압축은 세대 완료 시 자동 실행됩니다. 가장 최근 3개 세대는 항상 압축에서 보호됩니다. 압축된 파일은 목표(Objective)와 결과(Completion)를 중심으로 보존하고, 중간 과정은 특이사항만 남깁니다.
|
|
282
294
|
|
|
283
295
|
## 진화 흐름 (Evolution Flow)
|
|
284
296
|
|
package/README.md
CHANGED
|
@@ -38,6 +38,7 @@ REAP solves these with a **generation-based evolution model**:
|
|
|
38
38
|
- The AI agent automatically picks up current context at every session start (SessionStart Hook)
|
|
39
39
|
- Design issues discovered during implementation are logged in the backlog and addressed at Completion
|
|
40
40
|
- Lessons drawn from retrospectives (Completion) accumulate in the Genome
|
|
41
|
+
- Repeated manual tasks are automatically detected across generations, with user-confirmed hook creation
|
|
41
42
|
|
|
42
43
|
## Installation
|
|
43
44
|
|
|
@@ -96,7 +97,7 @@ Objective → Planning → Implementation ⟷ Validation → Completion
|
|
|
96
97
|
| **Planning** | Break down tasks, choose approach, map dependencies | `02-planning.md` |
|
|
97
98
|
| **Implementation** | Build with AI + human collaboration | `03-implementation.md` |
|
|
98
99
|
| **Validation** | Run tests, verify completion criteria | `04-validation.md` |
|
|
99
|
-
| **Completion** | Retrospective + apply Genome changes + archive | `05-completion.md` |
|
|
100
|
+
| **Completion** | Retrospective + apply Genome changes + hook suggestion + archive | `05-completion.md` |
|
|
100
101
|
|
|
101
102
|
## Core Concepts
|
|
102
103
|
|
|
@@ -109,7 +110,8 @@ The application's genetic information — a collection of architecture principle
|
|
|
109
110
|
├── principles.md # Architecture principles/decisions
|
|
110
111
|
├── domain/ # Business rules (per module)
|
|
111
112
|
├── conventions.md # Development rules/conventions
|
|
112
|
-
|
|
113
|
+
├── constraints.md # Technical constraints/choices
|
|
114
|
+
└── source-map.md # C4 Container/Component diagram (Mermaid)
|
|
113
115
|
```
|
|
114
116
|
|
|
115
117
|
**Genome Immutability Principle**: The Genome is never modified directly during the current generation. When an issue is found, it is recorded in the backlog and only applied at the Completion stage.
|
|
@@ -192,6 +194,8 @@ Runs automatically at the start of every session, injecting the following into t
|
|
|
192
194
|
- The full REAP workflow guide (Genome, Life Cycle, Four-Axis Structure, etc.)
|
|
193
195
|
- Current generation state (which stage you're in, what to do next)
|
|
194
196
|
- Rules to follow the REAP lifecycle
|
|
197
|
+
- Genome staleness detection — checks if code-related commits (`src/`, `tests/`, `package.json`, `tsconfig.json`, `scripts/`) have occurred since the last Genome update (docs-only changes are excluded)
|
|
198
|
+
- Source-map drift detection — compares documented components in `source-map.md` against actual files in the project
|
|
195
199
|
|
|
196
200
|
This ensures the agent immediately understands the project context even in a brand-new session.
|
|
197
201
|
|
|
@@ -219,22 +223,28 @@ Strict mode is disabled by default (`strict: false`).
|
|
|
219
223
|
|
|
220
224
|
### REAP Hooks
|
|
221
225
|
|
|
222
|
-
|
|
226
|
+
Hooks are file-based and stored in `.reap/hooks/`. Each hook is a file named `{event}.{name}.{md|sh}`:
|
|
223
227
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
- command: "echo 'Regressed'"
|
|
228
|
+
- `.md` files contain AI prompts (executed by the AI agent)
|
|
229
|
+
- `.sh` files contain shell scripts (executed directly)
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
.reap/hooks/
|
|
233
|
+
├── onGenerationStart.context-load.md
|
|
234
|
+
├── onGenerationComplete.version-bump.md
|
|
235
|
+
├── onGenerationComplete.readme-update.md
|
|
236
|
+
├── onStageTransition.notify.sh
|
|
237
|
+
└── onRegression.alert.sh
|
|
235
238
|
```
|
|
236
239
|
|
|
237
|
-
Each hook supports
|
|
240
|
+
Each hook file supports frontmatter with the following fields:
|
|
241
|
+
|
|
242
|
+
```yaml
|
|
243
|
+
---
|
|
244
|
+
condition: has-code-changes # always | has-code-changes | version-bumped
|
|
245
|
+
order: 10 # execution order (lower runs first)
|
|
246
|
+
---
|
|
247
|
+
```
|
|
238
248
|
|
|
239
249
|
| Event | Trigger |
|
|
240
250
|
|-------|---------|
|
|
@@ -243,7 +253,7 @@ Each hook supports `command` (shell) or `prompt` (AI agent instruction).
|
|
|
243
253
|
| `onGenerationComplete` | After `/reap.next` archives a completed generation |
|
|
244
254
|
| `onRegression` | After `/reap.back` returns to a previous stage |
|
|
245
255
|
|
|
246
|
-
Hooks are executed by the AI agent in the project root directory.
|
|
256
|
+
Hooks are executed by the AI agent in the project root directory. The `onGenerationComplete` hooks include automatic version bump judgment — patch-level bumps are applied automatically, while minor/major bumps require user confirmation.
|
|
247
257
|
|
|
248
258
|
## Project Structure After `reap init`
|
|
249
259
|
|
|
@@ -256,7 +266,9 @@ my-project/
|
|
|
256
266
|
│ ├── principles.md
|
|
257
267
|
│ ├── domain/
|
|
258
268
|
│ ├── conventions.md
|
|
259
|
-
│
|
|
269
|
+
│ ├── constraints.md
|
|
270
|
+
│ └── source-map.md
|
|
271
|
+
├── hooks/ # Lifecycle hooks (.md/.sh)
|
|
260
272
|
├── environment/ # External context
|
|
261
273
|
├── life/ # Current generation
|
|
262
274
|
│ ├── current.yml
|
|
@@ -274,10 +286,10 @@ As generations accumulate, the lineage directory grows. REAP manages this with a
|
|
|
274
286
|
|
|
275
287
|
| Level | Input | Output | Max lines | Trigger |
|
|
276
288
|
|-------|-------|--------|-----------|---------|
|
|
277
|
-
| **Level 1** | Generation folder (5 artifacts) | `gen-XXX.md` | 40 lines | lineage >
|
|
289
|
+
| **Level 1** | Generation folder (5 artifacts) | `gen-XXX.md` | 40 lines | lineage > 5,000 lines + 5+ generations |
|
|
278
290
|
| **Level 2** | 5 Level 1 files | `epoch-XXX.md` | 60 lines | 5+ Level 1 files |
|
|
279
291
|
|
|
280
|
-
Compression runs automatically when a generation completes. Compressed files preserve objectives and completion results while retaining only notable findings from intermediate stages.
|
|
292
|
+
Compression runs automatically when a generation completes. The most recent 3 generations are always protected from compression. Compressed files preserve objectives and completion results while retaining only notable findings from intermediate stages.
|
|
281
293
|
|
|
282
294
|
## Evolution Flow
|
|
283
295
|
|
package/README.zh-CN.md
CHANGED
|
@@ -38,6 +38,7 @@ REAP通过**基于世代的进化模型**解决这些问题:
|
|
|
38
38
|
- AI代理在每次会话开始时自动获取当前上下文(SessionStart Hook)
|
|
39
39
|
- 实现过程中发现的设计问题记录在backlog中,在Completion时反映
|
|
40
40
|
- 回顾(Completion)中提取的教训积累在Genome中
|
|
41
|
+
- 跨世代自动检测重复的手动操作,经用户确认后生成Hook
|
|
41
42
|
|
|
42
43
|
## 安装
|
|
43
44
|
|
|
@@ -97,7 +98,7 @@ Objective → Planning → Implementation ⟷ Validation → Completion
|
|
|
97
98
|
| **Planning** | 任务分解、实施方案、依赖关系 | `02-planning.md` |
|
|
98
99
|
| **Implementation** | AI+人类协作编写代码 | `03-implementation.md` |
|
|
99
100
|
| **Validation** | 执行测试、检查完成条件 | `04-validation.md` |
|
|
100
|
-
| **Completion** | 回顾 + 应用Genome变更 + 归档 | `05-completion.md` |
|
|
101
|
+
| **Completion** | 回顾 + 应用Genome变更 + Hook建议 + 归档 | `05-completion.md` |
|
|
101
102
|
|
|
102
103
|
## 核心概念
|
|
103
104
|
|
|
@@ -110,7 +111,8 @@ Objective → Planning → Implementation ⟷ Validation → Completion
|
|
|
110
111
|
├── principles.md # 架构原则/决策
|
|
111
112
|
├── domain/ # 业务规则(按模块)
|
|
112
113
|
├── conventions.md # 开发规则/约定
|
|
113
|
-
|
|
114
|
+
├── constraints.md # 技术约束/选择
|
|
115
|
+
└── source-map.md # C4 Container/Component图(Mermaid)
|
|
114
116
|
```
|
|
115
117
|
|
|
116
118
|
**Genome不变原则**:当前世代不直接修改Genome。发现问题时记录在backlog中,仅在Completion阶段反映。
|
|
@@ -193,6 +195,8 @@ REAP通过斜杠命令和会话钩子与AI代理集成。当前支持的代理
|
|
|
193
195
|
- REAP工作流完整指南(Genome、生命周期、四轴结构等)
|
|
194
196
|
- 当前Generation状态(在哪个阶段、下一步做什么)
|
|
195
197
|
- 遵循REAP生命周期的规则
|
|
198
|
+
- Genome新鲜度检测 — 检查上次Genome更新后是否有代码相关提交(`src/`、`tests/`、`package.json`、`tsconfig.json`、`scripts/`),纯文档变更除外
|
|
199
|
+
- Source-map漂移检测 — 将`source-map.md`中记录的组件与项目中的实际文件进行比对
|
|
196
200
|
|
|
197
201
|
这确保即使打开新会话,代理也能立即理解项目上下文。
|
|
198
202
|
|
|
@@ -220,22 +224,28 @@ Strict模式默认禁用(`strict: false`)。
|
|
|
220
224
|
|
|
221
225
|
### REAP Hooks
|
|
222
226
|
|
|
223
|
-
|
|
227
|
+
Hook基于文件,存储在`.reap/hooks/`中。每个Hook是一个以`{event}.{name}.{md|sh}`命名的文件:
|
|
224
228
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
- command: "echo 'Regressed'"
|
|
229
|
+
- `.md`文件包含AI提示词(由AI代理执行)
|
|
230
|
+
- `.sh`文件包含Shell脚本(直接执行)
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
.reap/hooks/
|
|
234
|
+
├── onGenerationStart.context-load.md
|
|
235
|
+
├── onGenerationComplete.version-bump.md
|
|
236
|
+
├── onGenerationComplete.readme-update.md
|
|
237
|
+
├── onStageTransition.notify.sh
|
|
238
|
+
└── onRegression.alert.sh
|
|
236
239
|
```
|
|
237
240
|
|
|
238
|
-
每个
|
|
241
|
+
每个Hook文件支持包含以下字段的frontmatter:
|
|
242
|
+
|
|
243
|
+
```yaml
|
|
244
|
+
---
|
|
245
|
+
condition: has-code-changes # always | has-code-changes | version-bumped
|
|
246
|
+
order: 10 # 执行顺序(数值越小越先执行)
|
|
247
|
+
---
|
|
248
|
+
```
|
|
239
249
|
|
|
240
250
|
| 事件 | 触发时机 |
|
|
241
251
|
|------|----------|
|
|
@@ -244,7 +254,7 @@ hooks:
|
|
|
244
254
|
| `onGenerationComplete` | `/reap.next`归档已完成的Generation后 |
|
|
245
255
|
| `onRegression` | `/reap.back`回到前一阶段后 |
|
|
246
256
|
|
|
247
|
-
Hook由AI
|
|
257
|
+
Hook由AI代理在项目根目录中执行。`onGenerationComplete` Hook包含自动版本号升级判断 — patch级别自动应用,minor/major级别需要用户确认。
|
|
248
258
|
|
|
249
259
|
## `reap init`后的项目结构
|
|
250
260
|
|
|
@@ -257,7 +267,9 @@ my-project/
|
|
|
257
267
|
│ ├── principles.md
|
|
258
268
|
│ ├── domain/
|
|
259
269
|
│ ├── conventions.md
|
|
260
|
-
│
|
|
270
|
+
│ ├── constraints.md
|
|
271
|
+
│ └── source-map.md
|
|
272
|
+
├── hooks/ # Lifecycle hooks (.md/.sh)
|
|
261
273
|
├── environment/ # 外部环境
|
|
262
274
|
├── life/ # 当前世代
|
|
263
275
|
│ ├── current.yml
|
|
@@ -275,10 +287,10 @@ my-project/
|
|
|
275
287
|
|
|
276
288
|
| 级别 | 输入 | 输出 | 最大行数 | 触发条件 |
|
|
277
289
|
|------|------|------|----------|----------|
|
|
278
|
-
| **Level 1** | 世代文件夹(5个产出物) | `gen-XXX.md` | 40行 | lineage >
|
|
290
|
+
| **Level 1** | 世代文件夹(5个产出物) | `gen-XXX.md` | 40行 | lineage > 5,000行 + 5个以上世代 |
|
|
279
291
|
| **Level 2** | 5个Level 1文件 | `epoch-XXX.md` | 60行 | Level 1达到5个以上 |
|
|
280
292
|
|
|
281
|
-
|
|
293
|
+
压缩在世代完成时自动执行。最近3个世代始终受到保护,不会被压缩。压缩后的文件以目标(Objective)和结果(Completion)为中心保存,中间过程仅保留特别事项。
|
|
282
294
|
|
|
283
295
|
## 进化流程(Evolution Flow)
|
|
284
296
|
|
package/dist/cli.js
CHANGED
|
@@ -8840,7 +8840,7 @@ var {
|
|
|
8840
8840
|
} = import__.default;
|
|
8841
8841
|
|
|
8842
8842
|
// src/cli/commands/init.ts
|
|
8843
|
-
import { mkdir as mkdir3 } from "fs/promises";
|
|
8843
|
+
import { mkdir as mkdir3, readdir as readdir3, chmod } from "fs/promises";
|
|
8844
8844
|
import { join as join4 } from "path";
|
|
8845
8845
|
|
|
8846
8846
|
// src/core/paths.ts
|
|
@@ -8943,7 +8943,7 @@ class ReapPaths {
|
|
|
8943
8943
|
get legacyTemplates() {
|
|
8944
8944
|
return join(this.root, "templates");
|
|
8945
8945
|
}
|
|
8946
|
-
get
|
|
8946
|
+
get hooks() {
|
|
8947
8947
|
return join(this.root, "hooks");
|
|
8948
8948
|
}
|
|
8949
8949
|
get legacyClaudeCommands() {
|
|
@@ -9178,10 +9178,10 @@ class ClaudeCodeAdapter {
|
|
|
9178
9178
|
return { action: "migrated" };
|
|
9179
9179
|
}
|
|
9180
9180
|
getHookEntry() {
|
|
9181
|
-
const sessionStartPath = join2(ReapPaths.packageHooksDir, "session-start.
|
|
9181
|
+
const sessionStartPath = join2(ReapPaths.packageHooksDir, "session-start.cjs");
|
|
9182
9182
|
return {
|
|
9183
9183
|
matcher: "",
|
|
9184
|
-
hooks: [{ type: "command", command: `
|
|
9184
|
+
hooks: [{ type: "command", command: `node "${sessionStartPath}"` }]
|
|
9185
9185
|
};
|
|
9186
9186
|
}
|
|
9187
9187
|
hasReapHook(sessionStartHooks) {
|
|
@@ -9450,7 +9450,7 @@ async function initProject(projectRoot, projectName, entryMode, preset, onProgre
|
|
|
9450
9450
|
};
|
|
9451
9451
|
await ConfigManager.write(paths, config);
|
|
9452
9452
|
log("Setting up Genome templates...");
|
|
9453
|
-
const genomeTemplates = ["principles.md", "conventions.md", "constraints.md"];
|
|
9453
|
+
const genomeTemplates = ["principles.md", "conventions.md", "constraints.md", "source-map.md"];
|
|
9454
9454
|
const genomeSourceDir = preset ? join4(ReapPaths.packageTemplatesDir, "presets", preset) : ReapPaths.packageGenomeDir;
|
|
9455
9455
|
for (const file of genomeTemplates) {
|
|
9456
9456
|
const src = join4(genomeSourceDir, file);
|
|
@@ -9468,6 +9468,19 @@ async function initProject(projectRoot, projectName, entryMode, preset, onProgre
|
|
|
9468
9468
|
const domainGuideSrc = join4(ReapPaths.packageGenomeDir, "domain/README.md");
|
|
9469
9469
|
const domainGuideDest = join4(ReapPaths.userReapTemplates, "domain-guide.md");
|
|
9470
9470
|
await writeTextFile(domainGuideDest, await readTextFileOrThrow(domainGuideSrc));
|
|
9471
|
+
log("Installing hook conditions...");
|
|
9472
|
+
const conditionsSourceDir = join4(ReapPaths.packageTemplatesDir, "conditions");
|
|
9473
|
+
const conditionsDestDir = join4(paths.hooks, "conditions");
|
|
9474
|
+
await mkdir3(conditionsDestDir, { recursive: true });
|
|
9475
|
+
const conditionFiles = await readdir3(conditionsSourceDir);
|
|
9476
|
+
for (const file of conditionFiles) {
|
|
9477
|
+
if (!file.endsWith(".sh"))
|
|
9478
|
+
continue;
|
|
9479
|
+
const src = join4(conditionsSourceDir, file);
|
|
9480
|
+
const dest = join4(conditionsDestDir, file);
|
|
9481
|
+
await writeTextFile(dest, await readTextFileOrThrow(src));
|
|
9482
|
+
await chmod(dest, 493);
|
|
9483
|
+
}
|
|
9471
9484
|
log("Detecting AI agents...");
|
|
9472
9485
|
const detectedAgents = await AgentRegistry.detectInstalled();
|
|
9473
9486
|
const sourceDir = ReapPaths.packageCommandsDir;
|
|
@@ -9484,7 +9497,7 @@ async function initProject(projectRoot, projectName, entryMode, preset, onProgre
|
|
|
9484
9497
|
}
|
|
9485
9498
|
|
|
9486
9499
|
// src/cli/commands/update.ts
|
|
9487
|
-
import { readdir as
|
|
9500
|
+
import { readdir as readdir4, unlink as unlink3, rm, mkdir as mkdir4 } from "fs/promises";
|
|
9488
9501
|
import { join as join5 } from "path";
|
|
9489
9502
|
|
|
9490
9503
|
// src/core/hooks.ts
|
|
@@ -9510,7 +9523,7 @@ async function updateProject(projectRoot, dryRun = false) {
|
|
|
9510
9523
|
const config = await ConfigManager.read(paths);
|
|
9511
9524
|
const adapters = await AgentRegistry.getActiveAdapters(config ?? undefined);
|
|
9512
9525
|
const commandsDir = ReapPaths.packageCommandsDir;
|
|
9513
|
-
const commandFiles = await
|
|
9526
|
+
const commandFiles = await readdir4(commandsDir);
|
|
9514
9527
|
for (const adapter of adapters) {
|
|
9515
9528
|
const agentCmdDir = adapter.getCommandsDir();
|
|
9516
9529
|
const label = `${adapter.displayName}`;
|
|
@@ -9579,10 +9592,9 @@ async function updateProject(projectRoot, dryRun = false) {
|
|
|
9579
9592
|
async function migrateLegacyFiles(paths, dryRun, result) {
|
|
9580
9593
|
await removeDirIfExists(paths.legacyCommands, ".reap/commands/", dryRun, result);
|
|
9581
9594
|
await removeDirIfExists(paths.legacyTemplates, ".reap/templates/", dryRun, result);
|
|
9582
|
-
await removeDirIfExists(paths.legacyHooks, ".reap/hooks/", dryRun, result);
|
|
9583
9595
|
try {
|
|
9584
9596
|
const claudeCmdDir = paths.legacyClaudeCommands;
|
|
9585
|
-
const files = await
|
|
9597
|
+
const files = await readdir4(claudeCmdDir);
|
|
9586
9598
|
for (const file of files) {
|
|
9587
9599
|
if (file.startsWith("reap.") && file.endsWith(".md")) {
|
|
9588
9600
|
if (!dryRun)
|
|
@@ -9630,7 +9642,7 @@ async function migrateLegacyFiles(paths, dryRun, result) {
|
|
|
9630
9642
|
}
|
|
9631
9643
|
async function removeDirIfExists(dirPath, label, dryRun, result) {
|
|
9632
9644
|
try {
|
|
9633
|
-
const entries = await
|
|
9645
|
+
const entries = await readdir4(dirPath);
|
|
9634
9646
|
if (entries.length > 0 || true) {
|
|
9635
9647
|
if (!dryRun)
|
|
9636
9648
|
await rm(dirPath, { recursive: true });
|
|
@@ -9641,7 +9653,7 @@ async function removeDirIfExists(dirPath, label, dryRun, result) {
|
|
|
9641
9653
|
|
|
9642
9654
|
// src/core/generation.ts
|
|
9643
9655
|
var import_yaml2 = __toESM(require_dist(), 1);
|
|
9644
|
-
import { readdir as
|
|
9656
|
+
import { readdir as readdir6, mkdir as mkdir5, rename } from "fs/promises";
|
|
9645
9657
|
import { join as join7 } from "path";
|
|
9646
9658
|
|
|
9647
9659
|
// src/types/index.ts
|
|
@@ -9696,13 +9708,14 @@ class LifeCycle {
|
|
|
9696
9708
|
}
|
|
9697
9709
|
|
|
9698
9710
|
// src/core/compression.ts
|
|
9699
|
-
import { readdir as
|
|
9711
|
+
import { readdir as readdir5, rm as rm2 } from "fs/promises";
|
|
9700
9712
|
import { join as join6 } from "path";
|
|
9701
|
-
var LINEAGE_MAX_LINES =
|
|
9713
|
+
var LINEAGE_MAX_LINES = 5000;
|
|
9702
9714
|
var MIN_GENERATIONS_FOR_COMPRESSION = 5;
|
|
9703
9715
|
var LEVEL1_MAX_LINES = 40;
|
|
9704
9716
|
var LEVEL2_MAX_LINES = 60;
|
|
9705
9717
|
var LEVEL2_BATCH_SIZE = 5;
|
|
9718
|
+
var RECENT_PROTECTED_COUNT = 3;
|
|
9706
9719
|
async function countLines(filePath) {
|
|
9707
9720
|
const content = await readTextFile(filePath);
|
|
9708
9721
|
if (content === null)
|
|
@@ -9713,7 +9726,7 @@ async function countLines(filePath) {
|
|
|
9713
9726
|
async function countDirLines(dirPath) {
|
|
9714
9727
|
let total = 0;
|
|
9715
9728
|
try {
|
|
9716
|
-
const entries = await
|
|
9729
|
+
const entries = await readdir5(dirPath, { withFileTypes: true });
|
|
9717
9730
|
for (const entry of entries) {
|
|
9718
9731
|
const fullPath = join6(dirPath, entry.name);
|
|
9719
9732
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -9728,7 +9741,7 @@ async function countDirLines(dirPath) {
|
|
|
9728
9741
|
async function scanLineage(paths) {
|
|
9729
9742
|
const entries = [];
|
|
9730
9743
|
try {
|
|
9731
|
-
const items = await
|
|
9744
|
+
const items = await readdir5(paths.lineage, { withFileTypes: true });
|
|
9732
9745
|
for (const item of items) {
|
|
9733
9746
|
const fullPath = join6(paths.lineage, item.name);
|
|
9734
9747
|
if (item.isDirectory() && item.name.startsWith("gen-")) {
|
|
@@ -9911,7 +9924,8 @@ async function compressLineageIfNeeded(paths) {
|
|
|
9911
9924
|
if (totalLines <= LINEAGE_MAX_LINES) {
|
|
9912
9925
|
return result;
|
|
9913
9926
|
}
|
|
9914
|
-
const
|
|
9927
|
+
const allDirs = entries.filter((e) => e.type === "dir").sort((a, b) => a.genNum - b.genNum);
|
|
9928
|
+
const dirs = allDirs.slice(0, Math.max(0, allDirs.length - RECENT_PROTECTED_COUNT));
|
|
9915
9929
|
for (const dir of dirs) {
|
|
9916
9930
|
const currentTotal = await countDirLines(paths.lineage);
|
|
9917
9931
|
if (currentTotal <= LINEAGE_MAX_LINES)
|
|
@@ -9998,7 +10012,7 @@ class GenerationManager {
|
|
|
9998
10012
|
const genDirName = `${state.id}-${goalSlug}`;
|
|
9999
10013
|
const genDir = this.paths.generationDir(genDirName);
|
|
10000
10014
|
await mkdir5(genDir, { recursive: true });
|
|
10001
|
-
const lifeEntries = await
|
|
10015
|
+
const lifeEntries = await readdir6(this.paths.life);
|
|
10002
10016
|
for (const entry of lifeEntries) {
|
|
10003
10017
|
if (/^\d{2}-[a-z]+(?:-[a-z]+)*\.md$/.test(entry)) {
|
|
10004
10018
|
await rename(join7(this.paths.life, entry), join7(genDir, entry));
|
|
@@ -10007,13 +10021,13 @@ class GenerationManager {
|
|
|
10007
10021
|
const backlogDir = join7(genDir, "backlog");
|
|
10008
10022
|
await mkdir5(backlogDir, { recursive: true });
|
|
10009
10023
|
try {
|
|
10010
|
-
const backlogEntries = await
|
|
10024
|
+
const backlogEntries = await readdir6(this.paths.backlog);
|
|
10011
10025
|
for (const entry of backlogEntries) {
|
|
10012
10026
|
await rename(join7(this.paths.backlog, entry), join7(backlogDir, entry));
|
|
10013
10027
|
}
|
|
10014
10028
|
} catch {}
|
|
10015
10029
|
try {
|
|
10016
|
-
const mutEntries = await
|
|
10030
|
+
const mutEntries = await readdir6(this.paths.mutations);
|
|
10017
10031
|
if (mutEntries.length > 0) {
|
|
10018
10032
|
const mutDir = join7(genDir, "mutations");
|
|
10019
10033
|
await mkdir5(mutDir, { recursive: true });
|
|
@@ -10031,7 +10045,7 @@ class GenerationManager {
|
|
|
10031
10045
|
}
|
|
10032
10046
|
async listCompleted() {
|
|
10033
10047
|
try {
|
|
10034
|
-
const entries = await
|
|
10048
|
+
const entries = await readdir6(this.paths.lineage);
|
|
10035
10049
|
return entries.filter((e) => e.startsWith("gen-")).sort();
|
|
10036
10050
|
} catch {
|
|
10037
10051
|
return [];
|
|
@@ -10133,7 +10147,7 @@ async function fixProject(projectRoot) {
|
|
|
10133
10147
|
|
|
10134
10148
|
// src/cli/index.ts
|
|
10135
10149
|
import { join as join8 } from "path";
|
|
10136
|
-
program.name("reap").description("REAP — Recursive Evolutionary Autonomous Pipeline").version("0.
|
|
10150
|
+
program.name("reap").description("REAP — Recursive Evolutionary Autonomous Pipeline").version("0.3.1");
|
|
10137
10151
|
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) => {
|
|
10138
10152
|
try {
|
|
10139
10153
|
const cwd = process.cwd();
|
|
@@ -45,10 +45,18 @@ description: "REAP Back — Return to a previous lifecycle stage"
|
|
|
45
45
|
- **Affected**: [affected subsequent artifacts]
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
### Hook Execution
|
|
49
|
-
7.
|
|
50
|
-
-
|
|
51
|
-
|
|
48
|
+
### Hook Execution (Regression)
|
|
49
|
+
7. Scan `.reap/hooks/` for files matching `onRegression.*`
|
|
50
|
+
- For each matched file (sorted by `order` from frontmatter, then alphabetically):
|
|
51
|
+
1. Read the frontmatter (`condition`, `order`)
|
|
52
|
+
2. Evaluate `condition` by running `.reap/hooks/conditions/{condition}.sh` (exit 0 = met, non-zero = skip):
|
|
53
|
+
- If `condition` is absent: treat as `always`
|
|
54
|
+
- If the condition script doesn't exist: warn and skip the hook
|
|
55
|
+
- Default conditions: `always`, `has-code-changes`, `version-bumped`
|
|
56
|
+
- Users can add custom conditions by placing scripts in `.reap/hooks/conditions/`
|
|
57
|
+
3. Execute based on file extension:
|
|
58
|
+
- `.md`: read the file content (after frontmatter) as AI prompt and follow the instructions
|
|
59
|
+
- `.sh`: run as shell script in the project root directory
|
|
52
60
|
|
|
53
61
|
## Completion
|
|
54
62
|
- "Returned to [stage] stage. Proceed with `/reap.[stage]`."
|