@c-d-cc/reap 0.2.2 → 0.3.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 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
- └── constraints.md # 技術制約/選択
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
- `.reap/config.yml`にhookを定義して、ライフサイクルイベントでコマンドやAIプロンプトを実行できます:
227
+ Hookはファイルベースで`.reap/hooks/`に保存されます。各Hookは`{event}.{name}.{md|sh}`形式のファイルです:
224
228
 
225
- ```yaml
226
- hooks:
227
- onGenerationStart:
228
- - command: "echo 'Generation started'"
229
- onStageTransition:
230
- - command: "echo 'Stage changed'"
231
- onGenerationComplete:
232
- - command: "reap update"
233
- - prompt: "今回のGenerationで変更された機能があればREADMEに反映せよ。"
234
- onRegression:
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
- hookは`command`(シェルコマンド)または`prompt`(AIエージェント指示)のいずれかを使用します。
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
- └── constraints.md
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 > 10,000行 + 5世代以上 |
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.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
- └── constraints.md # 기술 제약/선택
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/config.yml`에 hook을 정의하여 lifecycle 이벤트에 명령 또는 AI 프롬프트를 실행할 수 있습니다:
227
+ Hook은 파일 기반이며 `.reap/hooks/`에 저장됩니다. Hook은 `{event}.{name}.{md|sh}` 형식의 파일입니다:
224
228
 
225
- ```yaml
226
- hooks:
227
- onGenerationStart:
228
- - command: "echo 'Generation started'"
229
- onStageTransition:
230
- - command: "echo 'Stage changed'"
231
- onGenerationComplete:
232
- - command: "reap update"
233
- - prompt: "이번 Generation 변경사항을 README에 반영하라."
234
- onRegression:
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
- hook은 `command` (shell 명령) 또는 `prompt` (AI 에이전트 지시) 중 하나를 사용합니다.
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
- └── constraints.md
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 > 10,000줄 + 5세대 이상 |
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
- └── constraints.md # Technical constraints/choices
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
- Projects can define hooks in `.reap/config.yml` to run commands or AI prompts at lifecycle events:
226
+ Hooks are file-based and stored in `.reap/hooks/`. Each hook is a file named `{event}.{name}.{md|sh}`:
223
227
 
224
- ```yaml
225
- hooks:
226
- onGenerationStart:
227
- - command: "echo 'Generation started'"
228
- onStageTransition:
229
- - command: "echo 'Stage changed'"
230
- onGenerationComplete:
231
- - command: "reap update"
232
- - prompt: "Update README if this generation changed any features."
233
- onRegression:
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 `command` (shell) or `prompt` (AI agent instruction).
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
- └── constraints.md
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 > 10,000 lines + 5+ generations |
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
- └── constraints.md # 技术约束/选择
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
- 在`.reap/config.yml`中定义hook,在生命周期事件时执行命令或AI提示:
227
+ Hook基于文件,存储在`.reap/hooks/`中。每个Hook是一个以`{event}.{name}.{md|sh}`命名的文件:
224
228
 
225
- ```yaml
226
- hooks:
227
- onGenerationStart:
228
- - command: "echo 'Generation started'"
229
- onStageTransition:
230
- - command: "echo 'Stage changed'"
231
- onGenerationComplete:
232
- - command: "reap update"
233
- - prompt: "如果本Generation有功能变更,请更新README。"
234
- onRegression:
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
- 每个hook使用`command`(shell命令)或`prompt`(AI代理指令)之一。
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
- └── constraints.md
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 > 10,000行 + 5个以上世代 |
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
- 压缩在世代完成时自动执行。压缩后的文件以目标(Objective)和结果(Completion)为中心保存,中间过程仅保留特别事项。
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 legacyHooks() {
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.sh");
9181
+ const sessionStartPath = join2(ReapPaths.packageHooksDir, "session-start.cjs");
9182
9182
  return {
9183
9183
  matcher: "",
9184
- hooks: [{ type: "command", command: `bash "${sessionStartPath}"` }]
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 readdir3, unlink as unlink3, rm, mkdir as mkdir4 } from "fs/promises";
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 readdir3(commandsDir);
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 readdir3(claudeCmdDir);
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 readdir3(dirPath);
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 readdir5, mkdir as mkdir5, rename } from "fs/promises";
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 readdir4, rm as rm2 } from "fs/promises";
9711
+ import { readdir as readdir5, rm as rm2 } from "fs/promises";
9700
9712
  import { join as join6 } from "path";
9701
- var LINEAGE_MAX_LINES = 1e4;
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 readdir4(dirPath, { withFileTypes: true });
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 readdir4(paths.lineage, { withFileTypes: true });
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 dirs = entries.filter((e) => e.type === "dir").sort((a, b) => a.genNum - b.genNum);
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 readdir5(this.paths.life);
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 readdir5(this.paths.backlog);
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 readdir5(this.paths.mutations);
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 readdir5(this.paths.lineage);
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.2.2");
10150
+ program.name("reap").description("REAP — Recursive Evolutionary Autonomous Pipeline").version("0.3.0");
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. Read `.reap/config.yml` if `hooks.onRegression` is defined, execute each hook in order:
50
- - If hook has `command`: run the shell command
51
- - If hook has `prompt`: follow the prompt instructions (AI agent executes the described task)
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]`."