@c-d-cc/reap 0.15.3 → 0.15.5
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/dist/cli.js +568 -374
- package/dist/templates/artifacts/01-objective.md +1 -1
- package/dist/templates/artifacts/02-planning.md +1 -1
- package/dist/templates/artifacts/03-implementation.md +1 -1
- package/dist/templates/artifacts/04-validation.md +1 -1
- package/dist/templates/artifacts/05-completion.md +1 -1
- package/dist/templates/artifacts/merge/01-detect.md +1 -1
- package/dist/templates/artifacts/merge/02-mate.md +1 -1
- package/dist/templates/artifacts/merge/03-merge.md +1 -1
- package/dist/templates/artifacts/merge/04-sync.md +1 -1
- package/dist/templates/artifacts/merge/05-validation.md +1 -1
- package/dist/templates/artifacts/merge/06-completion.md +1 -1
- package/package.json +1 -1
- package/scripts/postinstall.cjs +1 -1
package/dist/cli.js
CHANGED
|
@@ -1943,9 +1943,6 @@ class ReapPaths {
|
|
|
1943
1943
|
get backlog() {
|
|
1944
1944
|
return join(this.life, "backlog");
|
|
1945
1945
|
}
|
|
1946
|
-
get mutations() {
|
|
1947
|
-
return join(this.life, "mutations");
|
|
1948
|
-
}
|
|
1949
1946
|
artifact(name) {
|
|
1950
1947
|
return join(this.life, name);
|
|
1951
1948
|
}
|
|
@@ -9873,7 +9870,7 @@ async function compressLineageIfNeeded(paths, projectRoot) {
|
|
|
9873
9870
|
}
|
|
9874
9871
|
return result;
|
|
9875
9872
|
}
|
|
9876
|
-
var import_yaml2, LINEAGE_MAX_LINES =
|
|
9873
|
+
var import_yaml2, LINEAGE_MAX_LINES = 1e4, MIN_GENERATIONS_FOR_COMPRESSION = 5, LEVEL1_MAX_LINES = 40, LEVEL1_PROTECTED_COUNT = 20, LEVEL2_MIN_LEVEL1_COUNT = 100, LEVEL2_PROTECTED_COUNT = 9;
|
|
9877
9874
|
var init_compression = __esm(() => {
|
|
9878
9875
|
init_fs();
|
|
9879
9876
|
init_git();
|
|
@@ -9992,7 +9989,7 @@ var init_lineage = __esm(() => {
|
|
|
9992
9989
|
// src/core/generation.ts
|
|
9993
9990
|
import { createHash, randomBytes } from "crypto";
|
|
9994
9991
|
import { hostname } from "os";
|
|
9995
|
-
import { readdir as readdir9, mkdir as mkdir6,
|
|
9992
|
+
import { readdir as readdir9, mkdir as mkdir6, unlink as unlink4 } from "fs/promises";
|
|
9996
9993
|
import { join as join10 } from "path";
|
|
9997
9994
|
function generateToken(genId, stage, phase) {
|
|
9998
9995
|
const nonce = randomBytes(16).toString("hex");
|
|
@@ -10167,22 +10164,12 @@ class GenerationManager {
|
|
|
10167
10164
|
if (!content)
|
|
10168
10165
|
continue;
|
|
10169
10166
|
const isConsumed = /status:\s*consumed/i.test(content) || /consumed:\s*true/i.test(content);
|
|
10170
|
-
await writeTextFile(join10(backlogDir, entry), content);
|
|
10171
10167
|
if (isConsumed) {
|
|
10168
|
+
await writeTextFile(join10(backlogDir, entry), content);
|
|
10172
10169
|
await unlink4(join10(this.paths.backlog, entry));
|
|
10173
10170
|
}
|
|
10174
10171
|
}
|
|
10175
10172
|
} catch {}
|
|
10176
|
-
try {
|
|
10177
|
-
const mutEntries = await readdir9(this.paths.mutations);
|
|
10178
|
-
if (mutEntries.length > 0) {
|
|
10179
|
-
const mutDir = join10(genDir, "mutations");
|
|
10180
|
-
await mkdir6(mutDir, { recursive: true });
|
|
10181
|
-
for (const entry of mutEntries) {
|
|
10182
|
-
await rename(join10(this.paths.mutations, entry), join10(mutDir, entry));
|
|
10183
|
-
}
|
|
10184
|
-
}
|
|
10185
|
-
} catch {}
|
|
10186
10173
|
await writeTextFile(this.paths.currentYml, "");
|
|
10187
10174
|
const compression = await compressLineageIfNeeded(this.paths, this.paths.projectRoot);
|
|
10188
10175
|
return compression;
|
|
@@ -10214,7 +10201,7 @@ class GenerationManager {
|
|
|
10214
10201
|
return `gen-${String(seq).padStart(3, "0")}`;
|
|
10215
10202
|
}
|
|
10216
10203
|
}
|
|
10217
|
-
var import_yaml4, CURRENT_YML_HEADER = `# REAP MANAGED — Do not modify directly. Use reap run
|
|
10204
|
+
var import_yaml4, CURRENT_YML_HEADER = `# REAP MANAGED — Do not modify directly. Use 'reap run <stage> --phase <phase>' to update.
|
|
10218
10205
|
`;
|
|
10219
10206
|
var init_generation = __esm(() => {
|
|
10220
10207
|
init_lifecycle();
|
|
@@ -10238,6 +10225,9 @@ function checkLatestVersion() {
|
|
|
10238
10225
|
return null;
|
|
10239
10226
|
}
|
|
10240
10227
|
}
|
|
10228
|
+
function getCurrentVersion() {
|
|
10229
|
+
return "0.15.5";
|
|
10230
|
+
}
|
|
10241
10231
|
function formatVersionLine(current, skipCheck) {
|
|
10242
10232
|
if (skipCheck) {
|
|
10243
10233
|
return `REAP v${current}`;
|
|
@@ -10271,12 +10261,196 @@ function emitError(command, message, details) {
|
|
|
10271
10261
|
process.exit(1);
|
|
10272
10262
|
}
|
|
10273
10263
|
|
|
10264
|
+
// src/core/backlog.ts
|
|
10265
|
+
import { readdir as readdir14, mkdir as mkdir10 } from "fs/promises";
|
|
10266
|
+
import { join as join18 } from "path";
|
|
10267
|
+
async function scanBacklog(backlogDir) {
|
|
10268
|
+
let entries;
|
|
10269
|
+
try {
|
|
10270
|
+
entries = await readdir14(backlogDir);
|
|
10271
|
+
} catch {
|
|
10272
|
+
return [];
|
|
10273
|
+
}
|
|
10274
|
+
const items = [];
|
|
10275
|
+
for (const filename of entries) {
|
|
10276
|
+
if (!filename.endsWith(".md"))
|
|
10277
|
+
continue;
|
|
10278
|
+
const content = await readTextFile(join18(backlogDir, filename));
|
|
10279
|
+
if (!content)
|
|
10280
|
+
continue;
|
|
10281
|
+
const { frontmatter, body } = parseFrontmatter2(content);
|
|
10282
|
+
const title = body.match(/^#\s+(.+)/m)?.[1] ?? (frontmatter.title != null ? String(frontmatter.title) : filename.replace(/\.md$/, ""));
|
|
10283
|
+
items.push({
|
|
10284
|
+
filename,
|
|
10285
|
+
type: String(frontmatter.type ?? "task"),
|
|
10286
|
+
status: String(frontmatter.status ?? "pending"),
|
|
10287
|
+
consumedBy: frontmatter.consumedBy != null ? String(frontmatter.consumedBy) : undefined,
|
|
10288
|
+
target: frontmatter.target != null ? String(frontmatter.target) : undefined,
|
|
10289
|
+
title,
|
|
10290
|
+
body
|
|
10291
|
+
});
|
|
10292
|
+
}
|
|
10293
|
+
return items;
|
|
10294
|
+
}
|
|
10295
|
+
async function markBacklogConsumed(backlogDir, filename, genId) {
|
|
10296
|
+
const filePath = join18(backlogDir, filename);
|
|
10297
|
+
const content = await readTextFile(filePath);
|
|
10298
|
+
if (!content)
|
|
10299
|
+
return;
|
|
10300
|
+
const { frontmatter, body } = parseFrontmatter2(content);
|
|
10301
|
+
frontmatter.status = "consumed";
|
|
10302
|
+
frontmatter.consumedBy = genId;
|
|
10303
|
+
delete frontmatter.consumed;
|
|
10304
|
+
const newContent = `---
|
|
10305
|
+
${import_yaml8.default.stringify(frontmatter).trim()}
|
|
10306
|
+
---
|
|
10307
|
+
${body}`;
|
|
10308
|
+
await writeTextFile(filePath, newContent);
|
|
10309
|
+
}
|
|
10310
|
+
async function revertBacklogConsumed(backlogDir, genId) {
|
|
10311
|
+
let entries;
|
|
10312
|
+
try {
|
|
10313
|
+
entries = await readdir14(backlogDir);
|
|
10314
|
+
} catch {
|
|
10315
|
+
return;
|
|
10316
|
+
}
|
|
10317
|
+
for (const filename of entries) {
|
|
10318
|
+
if (!filename.endsWith(".md"))
|
|
10319
|
+
continue;
|
|
10320
|
+
const filePath = join18(backlogDir, filename);
|
|
10321
|
+
const content = await readTextFile(filePath);
|
|
10322
|
+
if (!content)
|
|
10323
|
+
continue;
|
|
10324
|
+
const { frontmatter, body } = parseFrontmatter2(content);
|
|
10325
|
+
if (frontmatter.status === "consumed" && frontmatter.consumedBy === genId) {
|
|
10326
|
+
frontmatter.status = "pending";
|
|
10327
|
+
delete frontmatter.consumedBy;
|
|
10328
|
+
const newContent = `---
|
|
10329
|
+
${import_yaml8.default.stringify(frontmatter).trim()}
|
|
10330
|
+
---
|
|
10331
|
+
${body}`;
|
|
10332
|
+
await writeTextFile(filePath, newContent);
|
|
10333
|
+
}
|
|
10334
|
+
}
|
|
10335
|
+
}
|
|
10336
|
+
function parseFrontmatter2(content) {
|
|
10337
|
+
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
10338
|
+
if (!match)
|
|
10339
|
+
return { frontmatter: {}, body: content };
|
|
10340
|
+
try {
|
|
10341
|
+
return { frontmatter: import_yaml8.default.parse(match[1]) ?? {}, body: match[2] };
|
|
10342
|
+
} catch {
|
|
10343
|
+
return { frontmatter: {}, body: content };
|
|
10344
|
+
}
|
|
10345
|
+
}
|
|
10346
|
+
function toKebabCase(title) {
|
|
10347
|
+
return title.toLowerCase().replace(/[^a-z0-9가-힣\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
10348
|
+
}
|
|
10349
|
+
async function createBacklog(backlogDir, opts) {
|
|
10350
|
+
if (!VALID_BACKLOG_TYPES2.includes(opts.type)) {
|
|
10351
|
+
throw new Error(`Invalid backlog type: "${opts.type}". Allowed: ${VALID_BACKLOG_TYPES2.join(", ")}`);
|
|
10352
|
+
}
|
|
10353
|
+
const priority = opts.priority ?? "medium";
|
|
10354
|
+
const filename = `${toKebabCase(opts.title)}.md`;
|
|
10355
|
+
const frontmatter = {
|
|
10356
|
+
type: opts.type,
|
|
10357
|
+
status: "pending",
|
|
10358
|
+
priority
|
|
10359
|
+
};
|
|
10360
|
+
const bodyContent = opts.body ? `
|
|
10361
|
+
# ${opts.title}
|
|
10362
|
+
|
|
10363
|
+
${opts.body}
|
|
10364
|
+
` : `
|
|
10365
|
+
# ${opts.title}
|
|
10366
|
+
`;
|
|
10367
|
+
const content = `---
|
|
10368
|
+
${import_yaml8.default.stringify(frontmatter).trim()}
|
|
10369
|
+
---
|
|
10370
|
+
${bodyContent}`;
|
|
10371
|
+
await mkdir10(backlogDir, { recursive: true });
|
|
10372
|
+
await writeTextFile(join18(backlogDir, filename), content);
|
|
10373
|
+
return filename;
|
|
10374
|
+
}
|
|
10375
|
+
var import_yaml8, VALID_BACKLOG_TYPES2;
|
|
10376
|
+
var init_backlog = __esm(() => {
|
|
10377
|
+
init_fs();
|
|
10378
|
+
import_yaml8 = __toESM(require_dist(), 1);
|
|
10379
|
+
VALID_BACKLOG_TYPES2 = ["genome-change", "environment-change", "task"];
|
|
10380
|
+
});
|
|
10381
|
+
|
|
10382
|
+
// src/cli/commands/make/backlog.ts
|
|
10383
|
+
var exports_backlog = {};
|
|
10384
|
+
__export(exports_backlog, {
|
|
10385
|
+
execute: () => execute
|
|
10386
|
+
});
|
|
10387
|
+
function parseFlags(argv) {
|
|
10388
|
+
const flags = {};
|
|
10389
|
+
for (let i = 0;i < argv.length; i++) {
|
|
10390
|
+
const arg = argv[i];
|
|
10391
|
+
if (arg.startsWith("--") && i + 1 < argv.length) {
|
|
10392
|
+
flags[arg.slice(2)] = argv[++i];
|
|
10393
|
+
}
|
|
10394
|
+
}
|
|
10395
|
+
return flags;
|
|
10396
|
+
}
|
|
10397
|
+
async function execute(paths, argv) {
|
|
10398
|
+
const flags = parseFlags(argv);
|
|
10399
|
+
if (!flags.type) {
|
|
10400
|
+
emitError("make", `--type is required. Allowed: ${VALID_BACKLOG_TYPES2.join(", ")}`);
|
|
10401
|
+
}
|
|
10402
|
+
if (!flags.title) {
|
|
10403
|
+
emitError("make", "--title is required.");
|
|
10404
|
+
}
|
|
10405
|
+
const filename = await createBacklog(paths.backlog, {
|
|
10406
|
+
type: flags.type,
|
|
10407
|
+
title: flags.title,
|
|
10408
|
+
body: flags.body,
|
|
10409
|
+
priority: flags.priority
|
|
10410
|
+
});
|
|
10411
|
+
emitOutput({
|
|
10412
|
+
status: "ok",
|
|
10413
|
+
command: "make",
|
|
10414
|
+
phase: "done",
|
|
10415
|
+
completed: ["backlog-create"],
|
|
10416
|
+
message: `Backlog created: ${filename}. Edit the file directly to add detailed content (headers, lists, code blocks, etc.).`,
|
|
10417
|
+
context: { filename, type: flags.type, title: flags.title, path: `${paths.backlog}/${filename}` }
|
|
10418
|
+
});
|
|
10419
|
+
}
|
|
10420
|
+
var init_backlog2 = __esm(() => {
|
|
10421
|
+
init_backlog();
|
|
10422
|
+
});
|
|
10423
|
+
|
|
10424
|
+
// src/cli/commands/make/index.ts
|
|
10425
|
+
var exports_make = {};
|
|
10426
|
+
__export(exports_make, {
|
|
10427
|
+
execute: () => execute2
|
|
10428
|
+
});
|
|
10429
|
+
async function execute2(paths, _phase, argv = []) {
|
|
10430
|
+
const target = argv[0];
|
|
10431
|
+
if (!target) {
|
|
10432
|
+
emitError("make", `Target required. Available: ${Object.keys(TARGETS).join(", ")}`);
|
|
10433
|
+
}
|
|
10434
|
+
const loader = TARGETS[target];
|
|
10435
|
+
if (!loader) {
|
|
10436
|
+
emitError("make", `Unknown target: "${target}". Available: ${Object.keys(TARGETS).join(", ")}`);
|
|
10437
|
+
}
|
|
10438
|
+
const mod = await loader();
|
|
10439
|
+
await mod.execute(paths, argv.slice(1));
|
|
10440
|
+
}
|
|
10441
|
+
var TARGETS;
|
|
10442
|
+
var init_make = __esm(() => {
|
|
10443
|
+
TARGETS = {
|
|
10444
|
+
backlog: () => Promise.resolve().then(() => (init_backlog2(), exports_backlog))
|
|
10445
|
+
};
|
|
10446
|
+
});
|
|
10447
|
+
|
|
10274
10448
|
// src/cli/commands/run/next.ts
|
|
10275
10449
|
var exports_next = {};
|
|
10276
10450
|
__export(exports_next, {
|
|
10277
|
-
execute: () =>
|
|
10451
|
+
execute: () => execute3
|
|
10278
10452
|
});
|
|
10279
|
-
async function
|
|
10453
|
+
async function execute3(paths, _phase) {
|
|
10280
10454
|
const gm = new GenerationManager(paths);
|
|
10281
10455
|
const state = await gm.current();
|
|
10282
10456
|
if (!state) {
|
|
@@ -10352,14 +10526,14 @@ var init_merge_lifecycle = __esm(() => {
|
|
|
10352
10526
|
});
|
|
10353
10527
|
|
|
10354
10528
|
// src/core/hook-engine.ts
|
|
10355
|
-
import { readdir as
|
|
10356
|
-
import { join as
|
|
10529
|
+
import { readdir as readdir15 } from "fs/promises";
|
|
10530
|
+
import { join as join19 } from "path";
|
|
10357
10531
|
import { execSync as execSync5 } from "child_process";
|
|
10358
10532
|
async function executeHooks(hooksDir, event, projectRoot) {
|
|
10359
10533
|
const hooks = await scanHooks(hooksDir, event);
|
|
10360
10534
|
if (hooks.length === 0)
|
|
10361
10535
|
return [];
|
|
10362
|
-
const conditionsDir =
|
|
10536
|
+
const conditionsDir = join19(hooksDir, "conditions");
|
|
10363
10537
|
const results = [];
|
|
10364
10538
|
for (const hook of hooks) {
|
|
10365
10539
|
const conditionMet = await evaluateCondition(conditionsDir, hook.condition, projectRoot);
|
|
@@ -10384,7 +10558,7 @@ async function executeHooks(hooksDir, event, projectRoot) {
|
|
|
10384
10558
|
async function scanHooks(hooksDir, event) {
|
|
10385
10559
|
let entries;
|
|
10386
10560
|
try {
|
|
10387
|
-
entries = await
|
|
10561
|
+
entries = await readdir15(hooksDir);
|
|
10388
10562
|
} catch {
|
|
10389
10563
|
return [];
|
|
10390
10564
|
}
|
|
@@ -10394,7 +10568,7 @@ async function scanHooks(hooksDir, event) {
|
|
|
10394
10568
|
const match = filename.match(pattern);
|
|
10395
10569
|
if (!match)
|
|
10396
10570
|
continue;
|
|
10397
|
-
const meta = await parseHookMeta(
|
|
10571
|
+
const meta = await parseHookMeta(join19(hooksDir, filename), match[2]);
|
|
10398
10572
|
hooks.push({
|
|
10399
10573
|
filename,
|
|
10400
10574
|
name: match[1],
|
|
@@ -10415,7 +10589,7 @@ async function parseHookMeta(filePath, ext) {
|
|
|
10415
10589
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
10416
10590
|
if (fmMatch) {
|
|
10417
10591
|
try {
|
|
10418
|
-
const fm =
|
|
10592
|
+
const fm = import_yaml9.default.parse(fmMatch[1]) ?? {};
|
|
10419
10593
|
return {
|
|
10420
10594
|
condition: String(fm.condition ?? "always"),
|
|
10421
10595
|
order: Number(fm.order ?? 50)
|
|
@@ -10441,7 +10615,7 @@ async function parseHookMeta(filePath, ext) {
|
|
|
10441
10615
|
async function evaluateCondition(conditionsDir, conditionName, projectRoot) {
|
|
10442
10616
|
if (conditionName === "always")
|
|
10443
10617
|
return { met: true };
|
|
10444
|
-
const scriptPath =
|
|
10618
|
+
const scriptPath = join19(conditionsDir, `${conditionName}.sh`);
|
|
10445
10619
|
if (!await fileExists(scriptPath)) {
|
|
10446
10620
|
return { met: false, reason: `condition script not found: ${conditionName}.sh` };
|
|
10447
10621
|
}
|
|
@@ -10454,7 +10628,7 @@ async function evaluateCondition(conditionsDir, conditionName, projectRoot) {
|
|
|
10454
10628
|
}
|
|
10455
10629
|
async function executeShHook(hook, event, projectRoot, hooksDir) {
|
|
10456
10630
|
try {
|
|
10457
|
-
const stdout = execSync5(`bash "${
|
|
10631
|
+
const stdout = execSync5(`bash "${join19(hooksDir, hook.filename)}"`, {
|
|
10458
10632
|
cwd: projectRoot,
|
|
10459
10633
|
timeout: 60000,
|
|
10460
10634
|
stdio: "pipe"
|
|
@@ -10480,7 +10654,7 @@ async function executeShHook(hook, event, projectRoot, hooksDir) {
|
|
|
10480
10654
|
}
|
|
10481
10655
|
}
|
|
10482
10656
|
async function executeMdHook(hook, event, hooksDir) {
|
|
10483
|
-
const content = await readTextFile(
|
|
10657
|
+
const content = await readTextFile(join19(hooksDir, hook.filename));
|
|
10484
10658
|
const body = content?.replace(/^---\n[\s\S]*?\n---\n?/, "").trim() ?? "";
|
|
10485
10659
|
return {
|
|
10486
10660
|
name: hook.name,
|
|
@@ -10490,16 +10664,111 @@ async function executeMdHook(hook, event, hooksDir) {
|
|
|
10490
10664
|
content: body
|
|
10491
10665
|
};
|
|
10492
10666
|
}
|
|
10493
|
-
var
|
|
10667
|
+
var import_yaml9;
|
|
10494
10668
|
var init_hook_engine = __esm(() => {
|
|
10495
10669
|
init_fs();
|
|
10496
|
-
|
|
10670
|
+
import_yaml9 = __toESM(require_dist(), 1);
|
|
10671
|
+
});
|
|
10672
|
+
|
|
10673
|
+
// src/core/stage-transition.ts
|
|
10674
|
+
import { join as join20 } from "path";
|
|
10675
|
+
function verifyNonce(command, state, stage, phase) {
|
|
10676
|
+
if (!state.lastNonce) {
|
|
10677
|
+
return;
|
|
10678
|
+
}
|
|
10679
|
+
if (!state.expectedHash) {
|
|
10680
|
+
emitError(command, "Nonce transition error: lastNonce exists but expectedHash is missing. State may be corrupted.");
|
|
10681
|
+
}
|
|
10682
|
+
if (!verifyToken(state.lastNonce, state.id, stage, state.expectedHash, phase)) {
|
|
10683
|
+
emitError(command, `Nonce verification failed for ${stage}:${phase}. Re-run the previous phase to get a valid token.`);
|
|
10684
|
+
}
|
|
10685
|
+
state.lastNonce = undefined;
|
|
10686
|
+
state.expectedHash = undefined;
|
|
10687
|
+
state.phase = undefined;
|
|
10688
|
+
}
|
|
10689
|
+
function setNonce(state, stage, phase) {
|
|
10690
|
+
const { nonce, hash } = generateToken(state.id, stage, phase);
|
|
10691
|
+
state.lastNonce = nonce;
|
|
10692
|
+
state.expectedHash = hash;
|
|
10693
|
+
state.phase = phase;
|
|
10694
|
+
}
|
|
10695
|
+
async function performTransition(paths, state, saveFn) {
|
|
10696
|
+
const isMerge = state.type === "merge";
|
|
10697
|
+
let nextStage;
|
|
10698
|
+
if (isMerge) {
|
|
10699
|
+
nextStage = MergeLifeCycle.next(state.stage);
|
|
10700
|
+
} else {
|
|
10701
|
+
nextStage = LifeCycle.next(state.stage);
|
|
10702
|
+
}
|
|
10703
|
+
if (!nextStage) {
|
|
10704
|
+
throw new Error(`Cannot advance from '${state.stage}' — already at the last stage.`);
|
|
10705
|
+
}
|
|
10706
|
+
state.stage = nextStage;
|
|
10707
|
+
if (!state.timeline)
|
|
10708
|
+
state.timeline = [];
|
|
10709
|
+
state.timeline.push({ stage: nextStage, at: new Date().toISOString() });
|
|
10710
|
+
await saveFn(state);
|
|
10711
|
+
const artifactFile = isMerge ? MERGE_ARTIFACT[nextStage] : NORMAL_ARTIFACT[nextStage];
|
|
10712
|
+
if (artifactFile) {
|
|
10713
|
+
const templateDir = join20(__require("os").homedir(), ".reap", "templates");
|
|
10714
|
+
const templatePath = join20(templateDir, artifactFile);
|
|
10715
|
+
const destPath = paths.artifact(artifactFile);
|
|
10716
|
+
if (await fileExists(templatePath) && !await fileExists(destPath)) {
|
|
10717
|
+
const templateContent = await readTextFile(templatePath);
|
|
10718
|
+
if (templateContent) {
|
|
10719
|
+
await writeTextFile(destPath, templateContent);
|
|
10720
|
+
}
|
|
10721
|
+
}
|
|
10722
|
+
}
|
|
10723
|
+
const stageKey = isMerge && (nextStage === "validation" || nextStage === "completion") ? `${nextStage}:merge` : nextStage;
|
|
10724
|
+
const stageHookEvent = STAGE_HOOK[stageKey];
|
|
10725
|
+
const stageHookResults = stageHookEvent ? await executeHooks(paths.hooks, stageHookEvent, paths.projectRoot) : [];
|
|
10726
|
+
const transitionEvent = isMerge ? "onMergeTransited" : "onLifeTransited";
|
|
10727
|
+
const transitionHookResults = await executeHooks(paths.hooks, transitionEvent, paths.projectRoot);
|
|
10728
|
+
return {
|
|
10729
|
+
nextStage,
|
|
10730
|
+
artifactFile,
|
|
10731
|
+
stageHookResults,
|
|
10732
|
+
transitionHookResults
|
|
10733
|
+
};
|
|
10734
|
+
}
|
|
10735
|
+
var NORMAL_ARTIFACT, MERGE_ARTIFACT, STAGE_HOOK;
|
|
10736
|
+
var init_stage_transition = __esm(() => {
|
|
10737
|
+
init_lifecycle();
|
|
10738
|
+
init_merge_lifecycle();
|
|
10739
|
+
init_generation();
|
|
10740
|
+
init_fs();
|
|
10741
|
+
init_hook_engine();
|
|
10742
|
+
NORMAL_ARTIFACT = {
|
|
10743
|
+
planning: "02-planning.md",
|
|
10744
|
+
implementation: "03-implementation.md",
|
|
10745
|
+
validation: "04-validation.md",
|
|
10746
|
+
completion: "05-completion.md"
|
|
10747
|
+
};
|
|
10748
|
+
MERGE_ARTIFACT = {
|
|
10749
|
+
mate: "02-mate.md",
|
|
10750
|
+
merge: "03-merge.md",
|
|
10751
|
+
sync: "04-sync.md",
|
|
10752
|
+
validation: "05-validation.md",
|
|
10753
|
+
completion: "06-completion.md"
|
|
10754
|
+
};
|
|
10755
|
+
STAGE_HOOK = {
|
|
10756
|
+
planning: "onLifeObjected",
|
|
10757
|
+
implementation: "onLifePlanned",
|
|
10758
|
+
validation: "onLifeImplemented",
|
|
10759
|
+
completion: "onLifeValidated",
|
|
10760
|
+
mate: "onMergeDetected",
|
|
10761
|
+
merge: "onMergeMated",
|
|
10762
|
+
sync: "onMergeMerged",
|
|
10763
|
+
"validation:merge": "onMergeSynced",
|
|
10764
|
+
"completion:merge": "onMergeValidated"
|
|
10765
|
+
};
|
|
10497
10766
|
});
|
|
10498
10767
|
|
|
10499
10768
|
// src/cli/commands/run/back.ts
|
|
10500
10769
|
var exports_back = {};
|
|
10501
10770
|
__export(exports_back, {
|
|
10502
|
-
execute: () =>
|
|
10771
|
+
execute: () => execute4
|
|
10503
10772
|
});
|
|
10504
10773
|
function getFlag(args, name) {
|
|
10505
10774
|
const idx = args.indexOf(`--${name}`);
|
|
@@ -10518,7 +10787,7 @@ function getPositionals(args, valueFlags) {
|
|
|
10518
10787
|
}
|
|
10519
10788
|
return result;
|
|
10520
10789
|
}
|
|
10521
|
-
async function
|
|
10790
|
+
async function execute4(paths, phase, argv = []) {
|
|
10522
10791
|
const gm = new GenerationManager(paths);
|
|
10523
10792
|
const state = await gm.current();
|
|
10524
10793
|
if (!state) {
|
|
@@ -10563,6 +10832,7 @@ async function execute2(paths, phase, argv = []) {
|
|
|
10563
10832
|
const reason = getFlag(argv, "reason") ?? "No reason provided";
|
|
10564
10833
|
const refs = (getFlag(argv, "refs") ?? "").split(",").filter(Boolean);
|
|
10565
10834
|
state.stage = target;
|
|
10835
|
+
setNonce(state, target, "entry");
|
|
10566
10836
|
state.timeline.push({
|
|
10567
10837
|
stage: target,
|
|
10568
10838
|
at: new Date().toISOString(),
|
|
@@ -10596,216 +10866,34 @@ var init_back = __esm(() => {
|
|
|
10596
10866
|
init_lifecycle();
|
|
10597
10867
|
init_merge_lifecycle();
|
|
10598
10868
|
init_hook_engine();
|
|
10869
|
+
init_stage_transition();
|
|
10599
10870
|
});
|
|
10600
10871
|
|
|
10601
|
-
// src/
|
|
10602
|
-
|
|
10603
|
-
|
|
10604
|
-
|
|
10605
|
-
|
|
10606
|
-
|
|
10607
|
-
|
|
10608
|
-
|
|
10609
|
-
}
|
|
10610
|
-
|
|
10611
|
-
|
|
10872
|
+
// src/cli/commands/run/start.ts
|
|
10873
|
+
var exports_start = {};
|
|
10874
|
+
__export(exports_start, {
|
|
10875
|
+
execute: () => execute5
|
|
10876
|
+
});
|
|
10877
|
+
import { join as join21 } from "path";
|
|
10878
|
+
import { readdir as readdir16 } from "fs/promises";
|
|
10879
|
+
function getFlag2(args, name) {
|
|
10880
|
+
const idx = args.indexOf(`--${name}`);
|
|
10881
|
+
return idx !== -1 && args[idx + 1] ? args[idx + 1] : undefined;
|
|
10882
|
+
}
|
|
10883
|
+
function getPositionals2(args, valueFlags) {
|
|
10884
|
+
const result = [];
|
|
10885
|
+
for (let i = 0;i < args.length; i++) {
|
|
10886
|
+
if (args[i].startsWith("--")) {
|
|
10887
|
+
const flagName = args[i].slice(2);
|
|
10888
|
+
if (valueFlags.includes(flagName) && i + 1 < args.length)
|
|
10889
|
+
i++;
|
|
10890
|
+
continue;
|
|
10891
|
+
}
|
|
10892
|
+
result.push(args[i]);
|
|
10612
10893
|
}
|
|
10613
|
-
|
|
10614
|
-
state.expectedHash = undefined;
|
|
10615
|
-
state.phase = undefined;
|
|
10894
|
+
return result;
|
|
10616
10895
|
}
|
|
10617
|
-
function
|
|
10618
|
-
const { nonce, hash } = generateToken(state.id, stage, phase);
|
|
10619
|
-
state.lastNonce = nonce;
|
|
10620
|
-
state.expectedHash = hash;
|
|
10621
|
-
state.phase = phase;
|
|
10622
|
-
}
|
|
10623
|
-
async function performTransition(paths, state, saveFn) {
|
|
10624
|
-
const isMerge = state.type === "merge";
|
|
10625
|
-
let nextStage;
|
|
10626
|
-
if (isMerge) {
|
|
10627
|
-
nextStage = MergeLifeCycle.next(state.stage);
|
|
10628
|
-
} else {
|
|
10629
|
-
nextStage = LifeCycle.next(state.stage);
|
|
10630
|
-
}
|
|
10631
|
-
if (!nextStage) {
|
|
10632
|
-
throw new Error(`Cannot advance from '${state.stage}' — already at the last stage.`);
|
|
10633
|
-
}
|
|
10634
|
-
state.stage = nextStage;
|
|
10635
|
-
if (!state.timeline)
|
|
10636
|
-
state.timeline = [];
|
|
10637
|
-
state.timeline.push({ stage: nextStage, at: new Date().toISOString() });
|
|
10638
|
-
await saveFn(state);
|
|
10639
|
-
const artifactFile = isMerge ? MERGE_ARTIFACT[nextStage] : NORMAL_ARTIFACT[nextStage];
|
|
10640
|
-
if (artifactFile) {
|
|
10641
|
-
const templateDir = join18(__require("os").homedir(), ".reap", "templates");
|
|
10642
|
-
const templatePath = join18(templateDir, artifactFile);
|
|
10643
|
-
const destPath = paths.artifact(artifactFile);
|
|
10644
|
-
if (await fileExists(templatePath) && !await fileExists(destPath)) {
|
|
10645
|
-
const templateContent = await readTextFile(templatePath);
|
|
10646
|
-
if (templateContent) {
|
|
10647
|
-
await writeTextFile(destPath, templateContent);
|
|
10648
|
-
}
|
|
10649
|
-
}
|
|
10650
|
-
}
|
|
10651
|
-
const stageKey = isMerge && (nextStage === "validation" || nextStage === "completion") ? `${nextStage}:merge` : nextStage;
|
|
10652
|
-
const stageHookEvent = STAGE_HOOK[stageKey];
|
|
10653
|
-
const stageHookResults = stageHookEvent ? await executeHooks(paths.hooks, stageHookEvent, paths.projectRoot) : [];
|
|
10654
|
-
const transitionEvent = isMerge ? "onMergeTransited" : "onLifeTransited";
|
|
10655
|
-
const transitionHookResults = await executeHooks(paths.hooks, transitionEvent, paths.projectRoot);
|
|
10656
|
-
return {
|
|
10657
|
-
nextStage,
|
|
10658
|
-
artifactFile,
|
|
10659
|
-
stageHookResults,
|
|
10660
|
-
transitionHookResults
|
|
10661
|
-
};
|
|
10662
|
-
}
|
|
10663
|
-
var NORMAL_ARTIFACT, MERGE_ARTIFACT, STAGE_HOOK;
|
|
10664
|
-
var init_stage_transition = __esm(() => {
|
|
10665
|
-
init_lifecycle();
|
|
10666
|
-
init_merge_lifecycle();
|
|
10667
|
-
init_generation();
|
|
10668
|
-
init_fs();
|
|
10669
|
-
init_hook_engine();
|
|
10670
|
-
NORMAL_ARTIFACT = {
|
|
10671
|
-
planning: "02-planning.md",
|
|
10672
|
-
implementation: "03-implementation.md",
|
|
10673
|
-
validation: "04-validation.md",
|
|
10674
|
-
completion: "05-completion.md"
|
|
10675
|
-
};
|
|
10676
|
-
MERGE_ARTIFACT = {
|
|
10677
|
-
mate: "02-mate.md",
|
|
10678
|
-
merge: "03-merge.md",
|
|
10679
|
-
sync: "04-sync.md",
|
|
10680
|
-
validation: "05-validation.md",
|
|
10681
|
-
completion: "06-completion.md"
|
|
10682
|
-
};
|
|
10683
|
-
STAGE_HOOK = {
|
|
10684
|
-
planning: "onLifeObjected",
|
|
10685
|
-
implementation: "onLifePlanned",
|
|
10686
|
-
validation: "onLifeImplemented",
|
|
10687
|
-
completion: "onLifeValidated",
|
|
10688
|
-
mate: "onMergeDetected",
|
|
10689
|
-
merge: "onMergeMated",
|
|
10690
|
-
sync: "onMergeMerged",
|
|
10691
|
-
"validation:merge": "onMergeSynced",
|
|
10692
|
-
"completion:merge": "onMergeValidated"
|
|
10693
|
-
};
|
|
10694
|
-
});
|
|
10695
|
-
|
|
10696
|
-
// src/core/backlog.ts
|
|
10697
|
-
import { readdir as readdir15 } from "fs/promises";
|
|
10698
|
-
import { join as join19 } from "path";
|
|
10699
|
-
async function scanBacklog(backlogDir) {
|
|
10700
|
-
let entries;
|
|
10701
|
-
try {
|
|
10702
|
-
entries = await readdir15(backlogDir);
|
|
10703
|
-
} catch {
|
|
10704
|
-
return [];
|
|
10705
|
-
}
|
|
10706
|
-
const items = [];
|
|
10707
|
-
for (const filename of entries) {
|
|
10708
|
-
if (!filename.endsWith(".md"))
|
|
10709
|
-
continue;
|
|
10710
|
-
const content = await readTextFile(join19(backlogDir, filename));
|
|
10711
|
-
if (!content)
|
|
10712
|
-
continue;
|
|
10713
|
-
const { frontmatter, body } = parseFrontmatter2(content);
|
|
10714
|
-
const title = body.match(/^#\s+(.+)/m)?.[1] ?? (frontmatter.title != null ? String(frontmatter.title) : filename.replace(/\.md$/, ""));
|
|
10715
|
-
items.push({
|
|
10716
|
-
filename,
|
|
10717
|
-
type: String(frontmatter.type ?? "task"),
|
|
10718
|
-
status: String(frontmatter.status ?? "pending"),
|
|
10719
|
-
consumedBy: frontmatter.consumedBy != null ? String(frontmatter.consumedBy) : undefined,
|
|
10720
|
-
target: frontmatter.target != null ? String(frontmatter.target) : undefined,
|
|
10721
|
-
title,
|
|
10722
|
-
body
|
|
10723
|
-
});
|
|
10724
|
-
}
|
|
10725
|
-
return items;
|
|
10726
|
-
}
|
|
10727
|
-
async function markBacklogConsumed(backlogDir, filename, genId) {
|
|
10728
|
-
const filePath = join19(backlogDir, filename);
|
|
10729
|
-
const content = await readTextFile(filePath);
|
|
10730
|
-
if (!content)
|
|
10731
|
-
return;
|
|
10732
|
-
const { frontmatter, body } = parseFrontmatter2(content);
|
|
10733
|
-
frontmatter.status = "consumed";
|
|
10734
|
-
frontmatter.consumedBy = genId;
|
|
10735
|
-
delete frontmatter.consumed;
|
|
10736
|
-
const newContent = `---
|
|
10737
|
-
${import_yaml9.default.stringify(frontmatter).trim()}
|
|
10738
|
-
---
|
|
10739
|
-
${body}`;
|
|
10740
|
-
await writeTextFile(filePath, newContent);
|
|
10741
|
-
}
|
|
10742
|
-
async function revertBacklogConsumed(backlogDir, genId) {
|
|
10743
|
-
let entries;
|
|
10744
|
-
try {
|
|
10745
|
-
entries = await readdir15(backlogDir);
|
|
10746
|
-
} catch {
|
|
10747
|
-
return;
|
|
10748
|
-
}
|
|
10749
|
-
for (const filename of entries) {
|
|
10750
|
-
if (!filename.endsWith(".md"))
|
|
10751
|
-
continue;
|
|
10752
|
-
const filePath = join19(backlogDir, filename);
|
|
10753
|
-
const content = await readTextFile(filePath);
|
|
10754
|
-
if (!content)
|
|
10755
|
-
continue;
|
|
10756
|
-
const { frontmatter, body } = parseFrontmatter2(content);
|
|
10757
|
-
if (frontmatter.status === "consumed" && frontmatter.consumedBy === genId) {
|
|
10758
|
-
frontmatter.status = "pending";
|
|
10759
|
-
delete frontmatter.consumedBy;
|
|
10760
|
-
const newContent = `---
|
|
10761
|
-
${import_yaml9.default.stringify(frontmatter).trim()}
|
|
10762
|
-
---
|
|
10763
|
-
${body}`;
|
|
10764
|
-
await writeTextFile(filePath, newContent);
|
|
10765
|
-
}
|
|
10766
|
-
}
|
|
10767
|
-
}
|
|
10768
|
-
function parseFrontmatter2(content) {
|
|
10769
|
-
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
10770
|
-
if (!match)
|
|
10771
|
-
return { frontmatter: {}, body: content };
|
|
10772
|
-
try {
|
|
10773
|
-
return { frontmatter: import_yaml9.default.parse(match[1]) ?? {}, body: match[2] };
|
|
10774
|
-
} catch {
|
|
10775
|
-
return { frontmatter: {}, body: content };
|
|
10776
|
-
}
|
|
10777
|
-
}
|
|
10778
|
-
var import_yaml9;
|
|
10779
|
-
var init_backlog = __esm(() => {
|
|
10780
|
-
init_fs();
|
|
10781
|
-
import_yaml9 = __toESM(require_dist(), 1);
|
|
10782
|
-
});
|
|
10783
|
-
|
|
10784
|
-
// src/cli/commands/run/start.ts
|
|
10785
|
-
var exports_start = {};
|
|
10786
|
-
__export(exports_start, {
|
|
10787
|
-
execute: () => execute3
|
|
10788
|
-
});
|
|
10789
|
-
import { join as join20 } from "path";
|
|
10790
|
-
import { readdir as readdir16 } from "fs/promises";
|
|
10791
|
-
function getFlag2(args, name) {
|
|
10792
|
-
const idx = args.indexOf(`--${name}`);
|
|
10793
|
-
return idx !== -1 && args[idx + 1] ? args[idx + 1] : undefined;
|
|
10794
|
-
}
|
|
10795
|
-
function getPositionals2(args, valueFlags) {
|
|
10796
|
-
const result = [];
|
|
10797
|
-
for (let i = 0;i < args.length; i++) {
|
|
10798
|
-
if (args[i].startsWith("--")) {
|
|
10799
|
-
const flagName = args[i].slice(2);
|
|
10800
|
-
if (valueFlags.includes(flagName) && i + 1 < args.length)
|
|
10801
|
-
i++;
|
|
10802
|
-
continue;
|
|
10803
|
-
}
|
|
10804
|
-
result.push(args[i]);
|
|
10805
|
-
}
|
|
10806
|
-
return result;
|
|
10807
|
-
}
|
|
10808
|
-
async function execute3(paths, phase, argv = []) {
|
|
10896
|
+
async function execute5(paths, phase, argv = []) {
|
|
10809
10897
|
const positionals = getPositionals2(argv, ["backlog"]);
|
|
10810
10898
|
const goal = positionals.join(" ") || undefined;
|
|
10811
10899
|
const backlogFile = getFlag2(argv, "backlog");
|
|
@@ -10845,8 +10933,8 @@ async function execute3(paths, phase, argv = []) {
|
|
|
10845
10933
|
if (backlogFile) {
|
|
10846
10934
|
await markBacklogConsumed(paths.backlog, backlogFile, state.id);
|
|
10847
10935
|
}
|
|
10848
|
-
const templateDir =
|
|
10849
|
-
const templatePath =
|
|
10936
|
+
const templateDir = join21(__require("os").homedir(), ".reap", "templates");
|
|
10937
|
+
const templatePath = join21(templateDir, "01-objective.md");
|
|
10850
10938
|
const destPath = paths.artifact("01-objective.md");
|
|
10851
10939
|
if (await fileExists(templatePath)) {
|
|
10852
10940
|
let template = await readTextFile(templatePath);
|
|
@@ -10909,9 +10997,9 @@ var init_commit = () => {};
|
|
|
10909
10997
|
// src/cli/commands/run/completion.ts
|
|
10910
10998
|
var exports_completion = {};
|
|
10911
10999
|
__export(exports_completion, {
|
|
10912
|
-
execute: () =>
|
|
11000
|
+
execute: () => execute6
|
|
10913
11001
|
});
|
|
10914
|
-
import { join as
|
|
11002
|
+
import { join as join22 } from "path";
|
|
10915
11003
|
import { execSync as execSync7 } from "child_process";
|
|
10916
11004
|
function detectGenomeImpact(projectRoot) {
|
|
10917
11005
|
const impact = {
|
|
@@ -10961,7 +11049,9 @@ function buildGenomeImpactPrompt(impact) {
|
|
|
10961
11049
|
"",
|
|
10962
11050
|
"",
|
|
10963
11051
|
"## Genome/Environment Impact Detection",
|
|
10964
|
-
"다음 변경이 감지되었습니다. genome-change 또는 environment-change backlog 작성이 필요한지
|
|
11052
|
+
"다음 변경이 감지되었습니다. genome-change 또는 environment-change backlog 작성이 필요한지 검토하라.",
|
|
11053
|
+
"backlog 생성 시 반드시 `reap make backlog --type <type> --title <title> --body <body>` 명령을 사용하라. Write로 직접 파일을 생성하지 마라.",
|
|
11054
|
+
"생성된 backlog 파일에 상세 내용을 추가해야 하면, 생성 후 해당 파일을 편집하라.",
|
|
10965
11055
|
"",
|
|
10966
11056
|
...lines
|
|
10967
11057
|
].join(`
|
|
@@ -10983,7 +11073,7 @@ ${h.content}`);
|
|
|
10983
11073
|
].join(`
|
|
10984
11074
|
`);
|
|
10985
11075
|
}
|
|
10986
|
-
async function
|
|
11076
|
+
async function execute6(paths, phase) {
|
|
10987
11077
|
const gm = new GenerationManager(paths);
|
|
10988
11078
|
const state = await gm.current();
|
|
10989
11079
|
if (!state) {
|
|
@@ -11004,8 +11094,8 @@ async function execute4(paths, phase) {
|
|
|
11004
11094
|
const implContent = await readTextFile(paths.artifact("03-implementation.md"));
|
|
11005
11095
|
const destPath = paths.artifact("05-completion.md");
|
|
11006
11096
|
if (!await fileExists(destPath)) {
|
|
11007
|
-
const templateDir =
|
|
11008
|
-
const templatePath =
|
|
11097
|
+
const templateDir = join22(__require("os").homedir(), ".reap", "templates");
|
|
11098
|
+
const templatePath = join22(templateDir, "05-completion.md");
|
|
11009
11099
|
if (await fileExists(templatePath)) {
|
|
11010
11100
|
const { writeTextFile: writeTextFile2 } = await Promise.resolve().then(() => (init_fs(), exports_fs));
|
|
11011
11101
|
const template = await readTextFile(templatePath);
|
|
@@ -11094,9 +11184,9 @@ var init_completion = __esm(() => {
|
|
|
11094
11184
|
// src/cli/commands/run/abort.ts
|
|
11095
11185
|
var exports_abort = {};
|
|
11096
11186
|
__export(exports_abort, {
|
|
11097
|
-
execute: () =>
|
|
11187
|
+
execute: () => execute7
|
|
11098
11188
|
});
|
|
11099
|
-
import { join as
|
|
11189
|
+
import { join as join23 } from "path";
|
|
11100
11190
|
import { readdir as readdir17, unlink as unlink6 } from "fs/promises";
|
|
11101
11191
|
function getFlag3(args, name) {
|
|
11102
11192
|
const idx = args.indexOf(`--${name}`);
|
|
@@ -11105,7 +11195,7 @@ function getFlag3(args, name) {
|
|
|
11105
11195
|
function hasFlag(args, name) {
|
|
11106
11196
|
return args.includes(`--${name}`);
|
|
11107
11197
|
}
|
|
11108
|
-
async function
|
|
11198
|
+
async function execute7(paths, phase, argv = []) {
|
|
11109
11199
|
const gm = new GenerationManager(paths);
|
|
11110
11200
|
const state = await gm.current();
|
|
11111
11201
|
if (!state || !state.id) {
|
|
@@ -11172,7 +11262,7 @@ async function execute5(paths, phase, argv = []) {
|
|
|
11172
11262
|
sourceAction === "stash" ? "git stash pop으로 코드 복구" : sourceAction === "hold" ? "코드 변경이 working tree에 유지됨" : sourceAction === "rollback" ? "코드 변경이 revert됨. objective부터 재시작 필요" : "소스 코드 변경 없음"
|
|
11173
11263
|
].filter((line) => line !== null).join(`
|
|
11174
11264
|
`);
|
|
11175
|
-
await writeTextFile(
|
|
11265
|
+
await writeTextFile(join23(paths.backlog, `aborted-${state.id}.md`), backlogContent);
|
|
11176
11266
|
backlogSaved = true;
|
|
11177
11267
|
}
|
|
11178
11268
|
await revertBacklogConsumed(paths.backlog, state.id);
|
|
@@ -11180,7 +11270,7 @@ async function execute5(paths, phase, argv = []) {
|
|
|
11180
11270
|
const lifeEntries = await readdir17(paths.life);
|
|
11181
11271
|
for (const entry of lifeEntries) {
|
|
11182
11272
|
if (/^\d{2}-[a-z]+(?:-[a-z]+)*\.md$/.test(entry)) {
|
|
11183
|
-
await unlink6(
|
|
11273
|
+
await unlink6(join23(paths.life, entry));
|
|
11184
11274
|
}
|
|
11185
11275
|
}
|
|
11186
11276
|
} catch {}
|
|
@@ -11209,9 +11299,9 @@ var init_abort = __esm(() => {
|
|
|
11209
11299
|
// src/cli/commands/run/push.ts
|
|
11210
11300
|
var exports_push = {};
|
|
11211
11301
|
__export(exports_push, {
|
|
11212
|
-
execute: () =>
|
|
11302
|
+
execute: () => execute8
|
|
11213
11303
|
});
|
|
11214
|
-
async function
|
|
11304
|
+
async function execute8(paths, phase) {
|
|
11215
11305
|
const gm = new GenerationManager(paths);
|
|
11216
11306
|
const state = await gm.current();
|
|
11217
11307
|
if (!phase || phase === "check") {
|
|
@@ -11237,11 +11327,11 @@ var init_push = __esm(() => {
|
|
|
11237
11327
|
// src/cli/commands/run/objective.ts
|
|
11238
11328
|
var exports_objective = {};
|
|
11239
11329
|
__export(exports_objective, {
|
|
11240
|
-
execute: () =>
|
|
11330
|
+
execute: () => execute9
|
|
11241
11331
|
});
|
|
11242
|
-
import { join as
|
|
11332
|
+
import { join as join24 } from "path";
|
|
11243
11333
|
import { readdir as readdir18 } from "fs/promises";
|
|
11244
|
-
async function
|
|
11334
|
+
async function execute9(paths, phase) {
|
|
11245
11335
|
const gm = new GenerationManager(paths);
|
|
11246
11336
|
const state = await gm.current();
|
|
11247
11337
|
if (!state) {
|
|
@@ -11263,9 +11353,9 @@ async function execute7(paths, phase) {
|
|
|
11263
11353
|
const genDirs = lineageEntries.filter((e) => e.startsWith("gen-")).sort();
|
|
11264
11354
|
if (genDirs.length > 0) {
|
|
11265
11355
|
const lastGen = genDirs[genDirs.length - 1];
|
|
11266
|
-
prevCompletion = await readTextFile(
|
|
11356
|
+
prevCompletion = await readTextFile(join24(paths.lineage, lastGen, "05-completion.md"));
|
|
11267
11357
|
if (!prevCompletion) {
|
|
11268
|
-
const compressed = await readTextFile(
|
|
11358
|
+
const compressed = await readTextFile(join24(paths.lineage, `${lastGen}.md`));
|
|
11269
11359
|
if (compressed)
|
|
11270
11360
|
prevCompletion = compressed.slice(0, 2000);
|
|
11271
11361
|
}
|
|
@@ -11282,8 +11372,8 @@ async function execute7(paths, phase) {
|
|
|
11282
11372
|
lineageCount = entries.filter((e) => e.startsWith("gen-")).length;
|
|
11283
11373
|
} catch {}
|
|
11284
11374
|
if (!isReentry) {
|
|
11285
|
-
const templateDir =
|
|
11286
|
-
const templatePath =
|
|
11375
|
+
const templateDir = join24(__require("os").homedir(), ".reap", "templates");
|
|
11376
|
+
const templatePath = join24(templateDir, "01-objective.md");
|
|
11287
11377
|
if (await fileExists(templatePath)) {
|
|
11288
11378
|
let template = await readTextFile(templatePath);
|
|
11289
11379
|
if (template) {
|
|
@@ -11397,10 +11487,10 @@ var init_objective = __esm(() => {
|
|
|
11397
11487
|
// src/cli/commands/run/planning.ts
|
|
11398
11488
|
var exports_planning = {};
|
|
11399
11489
|
__export(exports_planning, {
|
|
11400
|
-
execute: () =>
|
|
11490
|
+
execute: () => execute10
|
|
11401
11491
|
});
|
|
11402
|
-
import { join as
|
|
11403
|
-
async function
|
|
11492
|
+
import { join as join25 } from "path";
|
|
11493
|
+
async function execute10(paths, phase) {
|
|
11404
11494
|
const gm = new GenerationManager(paths);
|
|
11405
11495
|
const state = await gm.current();
|
|
11406
11496
|
if (!state) {
|
|
@@ -11425,8 +11515,8 @@ async function execute8(paths, phase) {
|
|
|
11425
11515
|
const principlesContent = await readTextFile(paths.principles);
|
|
11426
11516
|
const implContent = await readTextFile(paths.artifact("03-implementation.md"));
|
|
11427
11517
|
if (!isReentry) {
|
|
11428
|
-
const templateDir =
|
|
11429
|
-
const templatePath =
|
|
11518
|
+
const templateDir = join25(__require("os").homedir(), ".reap", "templates");
|
|
11519
|
+
const templatePath = join25(templateDir, "02-planning.md");
|
|
11430
11520
|
if (await fileExists(templatePath)) {
|
|
11431
11521
|
const template = await readTextFile(templatePath);
|
|
11432
11522
|
if (template)
|
|
@@ -11532,10 +11622,10 @@ var init_planning = __esm(() => {
|
|
|
11532
11622
|
// src/cli/commands/run/implementation.ts
|
|
11533
11623
|
var exports_implementation = {};
|
|
11534
11624
|
__export(exports_implementation, {
|
|
11535
|
-
execute: () =>
|
|
11625
|
+
execute: () => execute11
|
|
11536
11626
|
});
|
|
11537
|
-
import { join as
|
|
11538
|
-
async function
|
|
11627
|
+
import { join as join26 } from "path";
|
|
11628
|
+
async function execute11(paths, phase) {
|
|
11539
11629
|
const gm = new GenerationManager(paths);
|
|
11540
11630
|
const state = await gm.current();
|
|
11541
11631
|
if (!state) {
|
|
@@ -11558,8 +11648,8 @@ async function execute9(paths, phase) {
|
|
|
11558
11648
|
const conventionsContent = await readTextFile(paths.conventions);
|
|
11559
11649
|
const constraintsContent = await readTextFile(paths.constraints);
|
|
11560
11650
|
if (!isReentry) {
|
|
11561
|
-
const templateDir =
|
|
11562
|
-
const templatePath =
|
|
11651
|
+
const templateDir = join26(__require("os").homedir(), ".reap", "templates");
|
|
11652
|
+
const templatePath = join26(templateDir, "03-implementation.md");
|
|
11563
11653
|
if (await fileExists(templatePath)) {
|
|
11564
11654
|
const template = await readTextFile(templatePath);
|
|
11565
11655
|
if (template)
|
|
@@ -11664,10 +11754,10 @@ var init_implementation = __esm(() => {
|
|
|
11664
11754
|
// src/cli/commands/run/validation.ts
|
|
11665
11755
|
var exports_validation = {};
|
|
11666
11756
|
__export(exports_validation, {
|
|
11667
|
-
execute: () =>
|
|
11757
|
+
execute: () => execute12
|
|
11668
11758
|
});
|
|
11669
|
-
import { join as
|
|
11670
|
-
async function
|
|
11759
|
+
import { join as join27 } from "path";
|
|
11760
|
+
async function execute12(paths, phase) {
|
|
11671
11761
|
const gm = new GenerationManager(paths);
|
|
11672
11762
|
const state = await gm.current();
|
|
11673
11763
|
if (!state) {
|
|
@@ -11691,8 +11781,8 @@ async function execute10(paths, phase) {
|
|
|
11691
11781
|
const implContent = await readTextFile(implArtifact);
|
|
11692
11782
|
const objectiveContent = await readTextFile(paths.artifact("01-objective.md"));
|
|
11693
11783
|
if (!isReentry) {
|
|
11694
|
-
const templateDir =
|
|
11695
|
-
const templatePath =
|
|
11784
|
+
const templateDir = join27(__require("os").homedir(), ".reap", "templates");
|
|
11785
|
+
const templatePath = join27(templateDir, "04-validation.md");
|
|
11696
11786
|
if (await fileExists(templatePath)) {
|
|
11697
11787
|
const template = await readTextFile(templatePath);
|
|
11698
11788
|
if (template)
|
|
@@ -11807,9 +11897,9 @@ var init_validation = __esm(() => {
|
|
|
11807
11897
|
// src/cli/commands/run/evolve.ts
|
|
11808
11898
|
var exports_evolve = {};
|
|
11809
11899
|
__export(exports_evolve, {
|
|
11810
|
-
execute: () =>
|
|
11900
|
+
execute: () => execute13
|
|
11811
11901
|
});
|
|
11812
|
-
function buildSubagentPrompt(paths, state, genomeSummaries, backlogSummary) {
|
|
11902
|
+
function buildSubagentPrompt(paths, state, genomeSummaries, backlogSummary, backlogFilenames = []) {
|
|
11813
11903
|
const lines = [];
|
|
11814
11904
|
lines.push("# REAP Subagent Instructions");
|
|
11815
11905
|
lines.push("");
|
|
@@ -11847,6 +11937,15 @@ function buildSubagentPrompt(paths, state, genomeSummaries, backlogSummary) {
|
|
|
11847
11937
|
lines.push("## Backlog");
|
|
11848
11938
|
lines.push(backlogSummary || "(empty)");
|
|
11849
11939
|
lines.push("");
|
|
11940
|
+
if (backlogFilenames.length > 0) {
|
|
11941
|
+
lines.push("## CRITICAL: Read the backlog file");
|
|
11942
|
+
lines.push("BEFORE starting objective, read the backlog file directly:");
|
|
11943
|
+
for (const fn of backlogFilenames) {
|
|
11944
|
+
lines.push(`\`.reap/life/backlog/${fn}\``);
|
|
11945
|
+
}
|
|
11946
|
+
lines.push("This file contains ALL implementation points. Do NOT skip any of them.");
|
|
11947
|
+
lines.push("");
|
|
11948
|
+
}
|
|
11850
11949
|
lines.push("## Lifecycle Execution");
|
|
11851
11950
|
lines.push("");
|
|
11852
11951
|
if (!state || !state.id) {
|
|
@@ -11884,6 +11983,11 @@ function buildSubagentPrompt(paths, state, genomeSummaries, backlogSummary) {
|
|
|
11884
11983
|
lines.push("- Use conventional commit format: `feat|fix|chore(scope): description`");
|
|
11885
11984
|
lines.push("- Include the generation ID in the commit message.");
|
|
11886
11985
|
lines.push("");
|
|
11986
|
+
lines.push("## Backlog Creation Rules");
|
|
11987
|
+
lines.push("- backlog 생성 시 반드시 `reap make backlog --type <type> --title <title> --body <body>` 명령을 사용하라.");
|
|
11988
|
+
lines.push("- Write 도구로 backlog 파일을 직접 생성하지 마라 (frontmatter 형식 오류 방지).");
|
|
11989
|
+
lines.push("- 생성된 backlog 파일에 상세 내용을 추가해야 하면, 생성 후 해당 파일을 편집하라.");
|
|
11990
|
+
lines.push("");
|
|
11887
11991
|
lines.push("## Submodule Commit Rules");
|
|
11888
11992
|
lines.push("- 커밋 전 반드시 `git -C tests status -s` 로 tests submodule의 dirty 상태를 확인하라.");
|
|
11889
11993
|
lines.push("- dirty 파일이 있으면:");
|
|
@@ -11919,7 +12023,7 @@ function truncate(text, maxLen) {
|
|
|
11919
12023
|
return "(not found)";
|
|
11920
12024
|
return text.length <= maxLen ? text : text.slice(0, maxLen) + "...";
|
|
11921
12025
|
}
|
|
11922
|
-
async function
|
|
12026
|
+
async function execute13(paths, phase) {
|
|
11923
12027
|
const gm = new GenerationManager(paths);
|
|
11924
12028
|
const state = await gm.current();
|
|
11925
12029
|
if (!phase || phase === "start") {
|
|
@@ -11943,7 +12047,8 @@ async function execute11(paths, phase) {
|
|
|
11943
12047
|
const pendingItems = backlogItems.filter((b) => b.status === "pending");
|
|
11944
12048
|
const backlogSummary = pendingItems.length > 0 ? pendingItems.map((b) => `- [${b.type}] ${b.title}`).join(`
|
|
11945
12049
|
`) : "(no pending items)";
|
|
11946
|
-
const
|
|
12050
|
+
const backlogFilenames = pendingItems.map((b) => b.filename);
|
|
12051
|
+
const subagentPrompt = buildSubagentPrompt(paths, state, genomeSummaries, backlogSummary, backlogFilenames);
|
|
11947
12052
|
emitOutput({
|
|
11948
12053
|
status: "prompt",
|
|
11949
12054
|
command: "evolve",
|
|
@@ -12060,9 +12165,9 @@ var init_evolve = __esm(() => {
|
|
|
12060
12165
|
// src/cli/commands/run/sync.ts
|
|
12061
12166
|
var exports_sync = {};
|
|
12062
12167
|
__export(exports_sync, {
|
|
12063
|
-
execute: () =>
|
|
12168
|
+
execute: () => execute14
|
|
12064
12169
|
});
|
|
12065
|
-
async function
|
|
12170
|
+
async function execute14(paths, phase) {
|
|
12066
12171
|
emitOutput({
|
|
12067
12172
|
status: "prompt",
|
|
12068
12173
|
command: "sync",
|
|
@@ -12087,11 +12192,11 @@ var init_sync = () => {};
|
|
|
12087
12192
|
// src/cli/commands/run/sync-genome.ts
|
|
12088
12193
|
var exports_sync_genome = {};
|
|
12089
12194
|
__export(exports_sync_genome, {
|
|
12090
|
-
execute: () =>
|
|
12195
|
+
execute: () => execute15
|
|
12091
12196
|
});
|
|
12092
12197
|
import { readdir as readdir19 } from "fs/promises";
|
|
12093
|
-
import { join as
|
|
12094
|
-
async function
|
|
12198
|
+
import { join as join28 } from "path";
|
|
12199
|
+
async function execute15(paths, phase) {
|
|
12095
12200
|
const gm = new GenerationManager(paths);
|
|
12096
12201
|
const state = await gm.current();
|
|
12097
12202
|
const hasActiveGen = !!(state && state.id);
|
|
@@ -12105,7 +12210,7 @@ async function execute13(paths, phase) {
|
|
|
12105
12210
|
const entries = await readdir19(paths.domain);
|
|
12106
12211
|
for (const entry of entries) {
|
|
12107
12212
|
if (entry.endsWith(".md")) {
|
|
12108
|
-
const content = await readTextFile(
|
|
12213
|
+
const content = await readTextFile(join28(paths.domain, entry));
|
|
12109
12214
|
if (content)
|
|
12110
12215
|
domainFiles[entry] = content.slice(0, 1000);
|
|
12111
12216
|
}
|
|
@@ -12190,11 +12295,11 @@ var init_sync_genome = __esm(() => {
|
|
|
12190
12295
|
// src/cli/commands/run/sync-environment.ts
|
|
12191
12296
|
var exports_sync_environment = {};
|
|
12192
12297
|
__export(exports_sync_environment, {
|
|
12193
|
-
execute: () =>
|
|
12298
|
+
execute: () => execute16
|
|
12194
12299
|
});
|
|
12195
12300
|
import { readdir as readdir20 } from "fs/promises";
|
|
12196
|
-
import { join as
|
|
12197
|
-
async function
|
|
12301
|
+
import { join as join29 } from "path";
|
|
12302
|
+
async function execute16(paths, phase) {
|
|
12198
12303
|
const gm = new GenerationManager(paths);
|
|
12199
12304
|
const state = await gm.current();
|
|
12200
12305
|
const hasActiveGen = !!(state && state.id);
|
|
@@ -12205,7 +12310,7 @@ async function execute14(paths, phase) {
|
|
|
12205
12310
|
const docsEntries = await readdir20(paths.environmentDocs);
|
|
12206
12311
|
for (const entry of docsEntries) {
|
|
12207
12312
|
if (entry.endsWith(".md")) {
|
|
12208
|
-
const content = await readTextFile(
|
|
12313
|
+
const content = await readTextFile(join29(paths.environmentDocs, entry));
|
|
12209
12314
|
if (content)
|
|
12210
12315
|
envDocs[entry] = content.slice(0, 1000);
|
|
12211
12316
|
}
|
|
@@ -12213,7 +12318,7 @@ async function execute14(paths, phase) {
|
|
|
12213
12318
|
} catch {}
|
|
12214
12319
|
let linksContent = null;
|
|
12215
12320
|
try {
|
|
12216
|
-
linksContent = await readTextFile(
|
|
12321
|
+
linksContent = await readTextFile(join29(paths.environmentResources, "links.md"));
|
|
12217
12322
|
} catch {}
|
|
12218
12323
|
emitOutput({
|
|
12219
12324
|
status: "prompt",
|
|
@@ -12283,9 +12388,9 @@ var init_sync_environment = __esm(() => {
|
|
|
12283
12388
|
// src/cli/commands/run/help.ts
|
|
12284
12389
|
var exports_help = {};
|
|
12285
12390
|
__export(exports_help, {
|
|
12286
|
-
execute: () =>
|
|
12391
|
+
execute: () => execute17
|
|
12287
12392
|
});
|
|
12288
|
-
import { join as
|
|
12393
|
+
import { join as join30 } from "path";
|
|
12289
12394
|
function detectLanguage(configContent) {
|
|
12290
12395
|
const raw = configContent?.match(/language:\s*(\S+)/)?.[1] ?? null;
|
|
12291
12396
|
if (raw && raw in LANGUAGE_ALIASES)
|
|
@@ -12316,11 +12421,11 @@ function buildLines(versionDisplay, lang, stateDisplay) {
|
|
|
12316
12421
|
CONFIG_LINE[lang]
|
|
12317
12422
|
];
|
|
12318
12423
|
}
|
|
12319
|
-
async function
|
|
12424
|
+
async function execute17(paths) {
|
|
12320
12425
|
const gm = new GenerationManager(paths);
|
|
12321
12426
|
const state = await gm.current();
|
|
12322
12427
|
const configContent = await readTextFile(paths.config);
|
|
12323
|
-
const installedVersion = "0.15.
|
|
12428
|
+
const installedVersion = "0.15.5";
|
|
12324
12429
|
const autoUpdate = configContent?.match(/autoUpdate:\s*(true|false)/)?.[1] === "true";
|
|
12325
12430
|
const versionDisplay = formatVersionLine(installedVersion, !autoUpdate);
|
|
12326
12431
|
const rawLang = detectLanguage(configContent);
|
|
@@ -12331,7 +12436,7 @@ async function execute15(paths) {
|
|
|
12331
12436
|
const stateDisplay = state?.id ? `Active: **${state.id}** — ${state.goal} (Stage: ${state.stage})` : "No active Generation → `/reap.start` or `/reap.evolve`";
|
|
12332
12437
|
const lines = buildLines(versionDisplay, lang, stateDisplay);
|
|
12333
12438
|
if (topic) {
|
|
12334
|
-
const guidePath =
|
|
12439
|
+
const guidePath = join30(ReapPaths.packageHooksDir, "reap-guide.md");
|
|
12335
12440
|
const reapGuide = await readTextFile(guidePath) ?? "";
|
|
12336
12441
|
emitOutput({
|
|
12337
12442
|
status: "prompt",
|
|
@@ -12511,9 +12616,9 @@ var init_help = __esm(() => {
|
|
|
12511
12616
|
// src/cli/commands/run/report.ts
|
|
12512
12617
|
var exports_report = {};
|
|
12513
12618
|
__export(exports_report, {
|
|
12514
|
-
execute: () =>
|
|
12619
|
+
execute: () => execute18
|
|
12515
12620
|
});
|
|
12516
|
-
async function
|
|
12621
|
+
async function execute18(paths, phase) {
|
|
12517
12622
|
const gm = new GenerationManager(paths);
|
|
12518
12623
|
const state = await gm.current();
|
|
12519
12624
|
if (!phase || phase === "collect") {
|
|
@@ -12636,8 +12741,8 @@ var init_merge = __esm(() => {
|
|
|
12636
12741
|
});
|
|
12637
12742
|
|
|
12638
12743
|
// src/core/merge-generation.ts
|
|
12639
|
-
import { readdir as readdir21, mkdir as
|
|
12640
|
-
import { join as
|
|
12744
|
+
import { readdir as readdir21, mkdir as mkdir11, unlink as unlink7 } from "fs/promises";
|
|
12745
|
+
import { join as join31 } from "path";
|
|
12641
12746
|
|
|
12642
12747
|
class MergeGenerationManager {
|
|
12643
12748
|
paths;
|
|
@@ -12813,7 +12918,7 @@ class MergeGenerationManager {
|
|
|
12813
12918
|
const goalSlug = state.goal.toLowerCase().replace(/[^a-z0-9가-힣]+/g, "-").replace(/^-|-$/g, "").slice(0, 30);
|
|
12814
12919
|
const genDirName = `${state.id}-${goalSlug}`;
|
|
12815
12920
|
const genDir = this.paths.generationDir(genDirName);
|
|
12816
|
-
await
|
|
12921
|
+
await mkdir11(genDir, { recursive: true });
|
|
12817
12922
|
const meta = {
|
|
12818
12923
|
id: state.id,
|
|
12819
12924
|
type: "merge",
|
|
@@ -12823,12 +12928,12 @@ class MergeGenerationManager {
|
|
|
12823
12928
|
startedAt: state.startedAt,
|
|
12824
12929
|
completedAt: now
|
|
12825
12930
|
};
|
|
12826
|
-
await writeTextFile(
|
|
12931
|
+
await writeTextFile(join31(genDir, "meta.yml"), import_yaml10.default.stringify(meta));
|
|
12827
12932
|
const lifeEntries = await readdir21(this.paths.life);
|
|
12828
12933
|
for (const entry of lifeEntries) {
|
|
12829
12934
|
if (/^\d{2}-[a-z]+(?:-[a-z]+)*\.md$/.test(entry)) {
|
|
12830
|
-
const srcPath =
|
|
12831
|
-
const destPath =
|
|
12935
|
+
const srcPath = join31(this.paths.life, entry);
|
|
12936
|
+
const destPath = join31(genDir, entry);
|
|
12832
12937
|
let content = await readTextFile(srcPath);
|
|
12833
12938
|
if (content && content.startsWith("# REAP MANAGED")) {
|
|
12834
12939
|
content = content.replace(/^# REAP MANAGED[^\n]*\n/, "");
|
|
@@ -12837,18 +12942,18 @@ class MergeGenerationManager {
|
|
|
12837
12942
|
await unlink7(srcPath);
|
|
12838
12943
|
}
|
|
12839
12944
|
}
|
|
12840
|
-
const backlogDir =
|
|
12841
|
-
await
|
|
12945
|
+
const backlogDir = join31(genDir, "backlog");
|
|
12946
|
+
await mkdir11(backlogDir, { recursive: true });
|
|
12842
12947
|
try {
|
|
12843
12948
|
const backlogEntries = await readdir21(this.paths.backlog);
|
|
12844
12949
|
for (const entry of backlogEntries) {
|
|
12845
|
-
const content = await readTextFile(
|
|
12950
|
+
const content = await readTextFile(join31(this.paths.backlog, entry));
|
|
12846
12951
|
if (!content)
|
|
12847
12952
|
continue;
|
|
12848
12953
|
const isConsumed = /status:\s*consumed/i.test(content) || /consumed:\s*true/i.test(content);
|
|
12849
|
-
await writeTextFile(
|
|
12954
|
+
await writeTextFile(join31(backlogDir, entry), content);
|
|
12850
12955
|
if (isConsumed) {
|
|
12851
|
-
await unlink7(
|
|
12956
|
+
await unlink7(join31(this.paths.backlog, entry));
|
|
12852
12957
|
}
|
|
12853
12958
|
}
|
|
12854
12959
|
} catch {}
|
|
@@ -12935,9 +13040,9 @@ var init_merge_generation = __esm(() => {
|
|
|
12935
13040
|
// src/cli/commands/run/merge-start.ts
|
|
12936
13041
|
var exports_merge_start = {};
|
|
12937
13042
|
__export(exports_merge_start, {
|
|
12938
|
-
execute: () =>
|
|
13043
|
+
execute: () => execute19
|
|
12939
13044
|
});
|
|
12940
|
-
async function
|
|
13045
|
+
async function execute19(paths, phase, argv = []) {
|
|
12941
13046
|
const positionals = argv.filter((a) => !a.startsWith("--"));
|
|
12942
13047
|
const targetBranchArg = positionals[0];
|
|
12943
13048
|
const gm = new GenerationManager(paths);
|
|
@@ -13026,9 +13131,9 @@ var init_merge_start = __esm(() => {
|
|
|
13026
13131
|
// src/cli/commands/run/merge-detect.ts
|
|
13027
13132
|
var exports_merge_detect = {};
|
|
13028
13133
|
__export(exports_merge_detect, {
|
|
13029
|
-
execute: () =>
|
|
13134
|
+
execute: () => execute20
|
|
13030
13135
|
});
|
|
13031
|
-
async function
|
|
13136
|
+
async function execute20(paths, phase) {
|
|
13032
13137
|
const mgm = new MergeGenerationManager(paths);
|
|
13033
13138
|
const state = await mgm.current();
|
|
13034
13139
|
if (!state) {
|
|
@@ -13109,9 +13214,9 @@ var init_merge_detect = __esm(() => {
|
|
|
13109
13214
|
// src/cli/commands/run/merge-mate.ts
|
|
13110
13215
|
var exports_merge_mate = {};
|
|
13111
13216
|
__export(exports_merge_mate, {
|
|
13112
|
-
execute: () =>
|
|
13217
|
+
execute: () => execute21
|
|
13113
13218
|
});
|
|
13114
|
-
async function
|
|
13219
|
+
async function execute21(paths, phase) {
|
|
13115
13220
|
const mgm = new MergeGenerationManager(paths);
|
|
13116
13221
|
const state = await mgm.current();
|
|
13117
13222
|
if (!state) {
|
|
@@ -13209,9 +13314,9 @@ var init_merge_mate = __esm(() => {
|
|
|
13209
13314
|
// src/cli/commands/run/merge-merge.ts
|
|
13210
13315
|
var exports_merge_merge = {};
|
|
13211
13316
|
__export(exports_merge_merge, {
|
|
13212
|
-
execute: () =>
|
|
13317
|
+
execute: () => execute22
|
|
13213
13318
|
});
|
|
13214
|
-
async function
|
|
13319
|
+
async function execute22(paths, phase) {
|
|
13215
13320
|
const mgm = new MergeGenerationManager(paths);
|
|
13216
13321
|
const state = await mgm.current();
|
|
13217
13322
|
if (!state) {
|
|
@@ -13306,9 +13411,9 @@ var init_merge_merge = __esm(() => {
|
|
|
13306
13411
|
// src/cli/commands/run/merge-sync.ts
|
|
13307
13412
|
var exports_merge_sync = {};
|
|
13308
13413
|
__export(exports_merge_sync, {
|
|
13309
|
-
execute: () =>
|
|
13414
|
+
execute: () => execute23
|
|
13310
13415
|
});
|
|
13311
|
-
async function
|
|
13416
|
+
async function execute23(paths, phase) {
|
|
13312
13417
|
const mgm = new MergeGenerationManager(paths);
|
|
13313
13418
|
const state = await mgm.current();
|
|
13314
13419
|
if (!state) {
|
|
@@ -13414,9 +13519,9 @@ var init_merge_sync = __esm(() => {
|
|
|
13414
13519
|
// src/cli/commands/run/merge-validation.ts
|
|
13415
13520
|
var exports_merge_validation = {};
|
|
13416
13521
|
__export(exports_merge_validation, {
|
|
13417
|
-
execute: () =>
|
|
13522
|
+
execute: () => execute24
|
|
13418
13523
|
});
|
|
13419
|
-
async function
|
|
13524
|
+
async function execute24(paths, phase) {
|
|
13420
13525
|
const mgm = new MergeGenerationManager(paths);
|
|
13421
13526
|
const state = await mgm.current();
|
|
13422
13527
|
if (!state) {
|
|
@@ -13511,9 +13616,9 @@ var init_merge_validation = __esm(() => {
|
|
|
13511
13616
|
// src/cli/commands/run/merge-completion.ts
|
|
13512
13617
|
var exports_merge_completion = {};
|
|
13513
13618
|
__export(exports_merge_completion, {
|
|
13514
|
-
execute: () =>
|
|
13619
|
+
execute: () => execute25
|
|
13515
13620
|
});
|
|
13516
|
-
async function
|
|
13621
|
+
async function execute25(paths, phase) {
|
|
13517
13622
|
const mgm = new MergeGenerationManager(paths);
|
|
13518
13623
|
const state = await mgm.current();
|
|
13519
13624
|
if (!state) {
|
|
@@ -13602,9 +13707,9 @@ var init_merge_completion = __esm(() => {
|
|
|
13602
13707
|
// src/cli/commands/run/merge-evolve.ts
|
|
13603
13708
|
var exports_merge_evolve = {};
|
|
13604
13709
|
__export(exports_merge_evolve, {
|
|
13605
|
-
execute: () =>
|
|
13710
|
+
execute: () => execute26
|
|
13606
13711
|
});
|
|
13607
|
-
async function
|
|
13712
|
+
async function execute26(paths, phase) {
|
|
13608
13713
|
const mgm = new MergeGenerationManager(paths);
|
|
13609
13714
|
const state = await mgm.current();
|
|
13610
13715
|
if (!state) {
|
|
@@ -13688,9 +13793,9 @@ var init_merge_evolve = __esm(() => {
|
|
|
13688
13793
|
// src/cli/commands/run/merge.ts
|
|
13689
13794
|
var exports_merge = {};
|
|
13690
13795
|
__export(exports_merge, {
|
|
13691
|
-
execute: () =>
|
|
13796
|
+
execute: () => execute27
|
|
13692
13797
|
});
|
|
13693
|
-
async function
|
|
13798
|
+
async function execute27(paths, phase, argv = []) {
|
|
13694
13799
|
const positionals = argv.filter((a) => !a.startsWith("--"));
|
|
13695
13800
|
const targetBranchArg = positionals[0];
|
|
13696
13801
|
const gm = new GenerationManager(paths);
|
|
@@ -13777,9 +13882,9 @@ var init_merge2 = __esm(() => {
|
|
|
13777
13882
|
// src/cli/commands/run/evolve-recovery.ts
|
|
13778
13883
|
var exports_evolve_recovery = {};
|
|
13779
13884
|
__export(exports_evolve_recovery, {
|
|
13780
|
-
execute: () =>
|
|
13885
|
+
execute: () => execute28
|
|
13781
13886
|
});
|
|
13782
|
-
import { join as
|
|
13887
|
+
import { join as join32 } from "path";
|
|
13783
13888
|
import { readdir as readdir22 } from "fs/promises";
|
|
13784
13889
|
function getFlag4(args, name) {
|
|
13785
13890
|
const idx = args.indexOf(`--${name}`);
|
|
@@ -13802,12 +13907,12 @@ async function loadLineageArtifacts(paths, genId) {
|
|
|
13802
13907
|
const completed = await listCompleted(paths);
|
|
13803
13908
|
const genDir = completed.find((d) => d.startsWith(genId));
|
|
13804
13909
|
if (genDir) {
|
|
13805
|
-
const dirPath =
|
|
13910
|
+
const dirPath = join32(paths.lineage, genDir);
|
|
13806
13911
|
const [objective, planning, implementation, completion] = await Promise.all([
|
|
13807
|
-
readTextFile(
|
|
13808
|
-
readTextFile(
|
|
13809
|
-
readTextFile(
|
|
13810
|
-
readTextFile(
|
|
13912
|
+
readTextFile(join32(dirPath, "01-objective.md")),
|
|
13913
|
+
readTextFile(join32(dirPath, "02-planning.md")),
|
|
13914
|
+
readTextFile(join32(dirPath, "03-implementation.md")),
|
|
13915
|
+
readTextFile(join32(dirPath, "05-completion.md"))
|
|
13811
13916
|
]);
|
|
13812
13917
|
return {
|
|
13813
13918
|
objective: objective ?? "(not found)",
|
|
@@ -13820,7 +13925,7 @@ async function loadLineageArtifacts(paths, genId) {
|
|
|
13820
13925
|
const entries = await readdir22(paths.lineage);
|
|
13821
13926
|
const compressedFile = entries.find((e) => e.startsWith(genId) && e.endsWith(".md"));
|
|
13822
13927
|
if (compressedFile) {
|
|
13823
|
-
const content = await readTextFile(
|
|
13928
|
+
const content = await readTextFile(join32(paths.lineage, compressedFile));
|
|
13824
13929
|
if (content) {
|
|
13825
13930
|
return {
|
|
13826
13931
|
objective: content,
|
|
@@ -13833,7 +13938,7 @@ async function loadLineageArtifacts(paths, genId) {
|
|
|
13833
13938
|
} catch {}
|
|
13834
13939
|
return null;
|
|
13835
13940
|
}
|
|
13836
|
-
async function
|
|
13941
|
+
async function execute28(paths, phase, argv = []) {
|
|
13837
13942
|
const positionals = getPositionals3(argv, ["reason"]);
|
|
13838
13943
|
const targetGenIds = positionals;
|
|
13839
13944
|
const reason = getFlag4(argv, "reason");
|
|
@@ -13939,9 +14044,9 @@ var init_evolve_recovery = __esm(() => {
|
|
|
13939
14044
|
// src/cli/commands/run/pull.ts
|
|
13940
14045
|
var exports_pull = {};
|
|
13941
14046
|
__export(exports_pull, {
|
|
13942
|
-
execute: () =>
|
|
14047
|
+
execute: () => execute29
|
|
13943
14048
|
});
|
|
13944
|
-
async function
|
|
14049
|
+
async function execute29(paths, phase, argv = []) {
|
|
13945
14050
|
const positionals = argv.filter((a) => !a.startsWith("--"));
|
|
13946
14051
|
const targetBranchArg = positionals[0];
|
|
13947
14052
|
const gm = new GenerationManager(paths);
|
|
@@ -14062,9 +14167,9 @@ var init_pull = __esm(() => {
|
|
|
14062
14167
|
// src/cli/commands/run/config.ts
|
|
14063
14168
|
var exports_config = {};
|
|
14064
14169
|
__export(exports_config, {
|
|
14065
|
-
execute: () =>
|
|
14170
|
+
execute: () => execute30
|
|
14066
14171
|
});
|
|
14067
|
-
async function
|
|
14172
|
+
async function execute30(paths) {
|
|
14068
14173
|
const config = await ConfigManager.read(paths);
|
|
14069
14174
|
const lines = [
|
|
14070
14175
|
`REAP Configuration (${paths.config})`,
|
|
@@ -14096,9 +14201,9 @@ var init_config2 = __esm(() => {
|
|
|
14096
14201
|
// src/cli/commands/run/update-genome.ts
|
|
14097
14202
|
var exports_update_genome = {};
|
|
14098
14203
|
__export(exports_update_genome, {
|
|
14099
|
-
execute: () =>
|
|
14204
|
+
execute: () => execute31
|
|
14100
14205
|
});
|
|
14101
|
-
async function
|
|
14206
|
+
async function execute31(paths, phase) {
|
|
14102
14207
|
const gm = new GenerationManager(paths);
|
|
14103
14208
|
const current = await gm.current();
|
|
14104
14209
|
if (current !== null) {
|
|
@@ -14190,22 +14295,22 @@ var init_update_genome = __esm(() => {
|
|
|
14190
14295
|
// src/cli/commands/run/refresh-knowledge.ts
|
|
14191
14296
|
var exports_refresh_knowledge = {};
|
|
14192
14297
|
__export(exports_refresh_knowledge, {
|
|
14193
|
-
execute: () =>
|
|
14298
|
+
execute: () => execute32
|
|
14194
14299
|
});
|
|
14195
|
-
import { join as
|
|
14300
|
+
import { join as join33 } from "path";
|
|
14196
14301
|
import { readdir as readdir23 } from "fs/promises";
|
|
14197
14302
|
async function loadGenome(genomeDir) {
|
|
14198
14303
|
let content = "";
|
|
14199
14304
|
let l1Lines = 0;
|
|
14200
14305
|
let smLimit = null;
|
|
14201
|
-
const smContent = await readTextFile(
|
|
14306
|
+
const smContent = await readTextFile(join33(genomeDir, "source-map.md"));
|
|
14202
14307
|
if (smContent) {
|
|
14203
14308
|
const limitMatch = smContent.match(/줄 수 한도:\s*~?(\d+)줄/);
|
|
14204
14309
|
if (limitMatch)
|
|
14205
14310
|
smLimit = parseInt(limitMatch[1], 10);
|
|
14206
14311
|
}
|
|
14207
14312
|
for (const file of L1_FILES) {
|
|
14208
|
-
const fileContent = await readTextFile(
|
|
14313
|
+
const fileContent = await readTextFile(join33(genomeDir, file));
|
|
14209
14314
|
if (!fileContent)
|
|
14210
14315
|
continue;
|
|
14211
14316
|
const lines = fileContent.split(`
|
|
@@ -14227,14 +14332,14 @@ ${fileContent.split(`
|
|
|
14227
14332
|
`;
|
|
14228
14333
|
}
|
|
14229
14334
|
}
|
|
14230
|
-
const domainDir =
|
|
14335
|
+
const domainDir = join33(genomeDir, "domain");
|
|
14231
14336
|
if (await fileExists(domainDir)) {
|
|
14232
14337
|
let l2Lines = 0;
|
|
14233
14338
|
let l2Overflow = false;
|
|
14234
14339
|
try {
|
|
14235
14340
|
const domainFiles = (await readdir23(domainDir)).filter((f) => f.endsWith(".md")).sort();
|
|
14236
14341
|
for (const file of domainFiles) {
|
|
14237
|
-
const fileContent = await readTextFile(
|
|
14342
|
+
const fileContent = await readTextFile(join33(domainDir, file));
|
|
14238
14343
|
if (!fileContent)
|
|
14239
14344
|
continue;
|
|
14240
14345
|
const lines = fileContent.split(`
|
|
@@ -14284,8 +14389,8 @@ function buildStrictSection(strict, genStage) {
|
|
|
14284
14389
|
}
|
|
14285
14390
|
return sections;
|
|
14286
14391
|
}
|
|
14287
|
-
async function
|
|
14288
|
-
const guidePath =
|
|
14392
|
+
async function execute32(paths) {
|
|
14393
|
+
const guidePath = join33(ReapPaths.packageHooksDir, "reap-guide.md");
|
|
14289
14394
|
const reapGuide = await readTextFile(guidePath) || "";
|
|
14290
14395
|
const { content: genomeContent } = await loadGenome(paths.genome);
|
|
14291
14396
|
const envSummary = await readTextFile(paths.environmentSummary) || "";
|
|
@@ -14375,7 +14480,7 @@ async function runCommand(command, phase, argv = []) {
|
|
|
14375
14480
|
try {
|
|
14376
14481
|
const config = await ConfigManager.read(paths);
|
|
14377
14482
|
if (config.autoIssueReport) {
|
|
14378
|
-
const version = "0.15.
|
|
14483
|
+
const version = "0.15.5";
|
|
14379
14484
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
14380
14485
|
const title = `[auto] reap run ${command}: ${errMsg.slice(0, 80)}`;
|
|
14381
14486
|
const body = [
|
|
@@ -14772,7 +14877,7 @@ class CodexAdapter {
|
|
|
14772
14877
|
return join3(homedir3(), ".codex");
|
|
14773
14878
|
}
|
|
14774
14879
|
get commandsDir() {
|
|
14775
|
-
return join3(this.userDir, "
|
|
14880
|
+
return join3(this.userDir, "prompts");
|
|
14776
14881
|
}
|
|
14777
14882
|
get hooksJsonPath() {
|
|
14778
14883
|
return join3(this.userDir, "hooks.json");
|
|
@@ -15257,7 +15362,7 @@ async function initProject(projectRoot, projectName, entryMode, preset, onProgre
|
|
|
15257
15362
|
}
|
|
15258
15363
|
const detectedLanguage = await AgentRegistry.readLanguage();
|
|
15259
15364
|
const config = {
|
|
15260
|
-
version: "0.15.
|
|
15365
|
+
version: "0.15.5",
|
|
15261
15366
|
project: projectName,
|
|
15262
15367
|
entryMode,
|
|
15263
15368
|
strict: false,
|
|
@@ -15385,7 +15490,7 @@ init_config();
|
|
|
15385
15490
|
init_fs();
|
|
15386
15491
|
init_generation();
|
|
15387
15492
|
var import_yaml5 = __toESM(require_dist(), 1);
|
|
15388
|
-
import { readdir as readdir10, rename
|
|
15493
|
+
import { readdir as readdir10, rename } from "fs/promises";
|
|
15389
15494
|
import { join as join11 } from "path";
|
|
15390
15495
|
import { execSync as execSync2 } from "child_process";
|
|
15391
15496
|
function estimateGenDates(lineagePath, dirName, fallbackDate) {
|
|
@@ -15474,7 +15579,7 @@ async function migrateLineage(paths) {
|
|
|
15474
15579
|
const oldSlug = entry.dirName.replace(/^gen-\d{3}/, "");
|
|
15475
15580
|
const newDirName = `${newId}${oldSlug}`;
|
|
15476
15581
|
if (newDirName !== entry.dirName) {
|
|
15477
|
-
await
|
|
15582
|
+
await rename(join11(paths.lineage, entry.dirName), join11(paths.lineage, newDirName));
|
|
15478
15583
|
}
|
|
15479
15584
|
prevId = newId;
|
|
15480
15585
|
result.migrated.push(`${entry.dirName} → ${newDirName}`);
|
|
@@ -15866,7 +15971,7 @@ async function checkGenome(paths, errors, warnings) {
|
|
|
15866
15971
|
continue;
|
|
15867
15972
|
const lines = content.split(`
|
|
15868
15973
|
`).length;
|
|
15869
|
-
if (lines > GENOME_LINE_WARNING_THRESHOLD) {
|
|
15974
|
+
if (gf.name !== "source-map.md" && lines > GENOME_LINE_WARNING_THRESHOLD) {
|
|
15870
15975
|
warnings.push(`genome/${gf.name}: ${lines} lines (exceeds ~${GENOME_LINE_WARNING_THRESHOLD} line guideline)`);
|
|
15871
15976
|
}
|
|
15872
15977
|
const stripped = content.split(`
|
|
@@ -16208,7 +16313,7 @@ async function updateProject(projectRoot, dryRun = false) {
|
|
|
16208
16313
|
}
|
|
16209
16314
|
} catch {}
|
|
16210
16315
|
await migrateLegacyFiles(paths, dryRun, result);
|
|
16211
|
-
const currentVersion = "0.15.
|
|
16316
|
+
const currentVersion = "0.15.5";
|
|
16212
16317
|
const migrationResult = await MigrationRunner.run(paths, currentVersion, dryRun);
|
|
16213
16318
|
for (const m of migrationResult.migrated) {
|
|
16214
16319
|
result.updated.push(`[migration] ${m}`);
|
|
@@ -16293,6 +16398,72 @@ async function removeDirIfExists(dirPath, label, dryRun, result) {
|
|
|
16293
16398
|
} catch {}
|
|
16294
16399
|
}
|
|
16295
16400
|
|
|
16401
|
+
// src/core/notice.ts
|
|
16402
|
+
import { readFileSync } from "fs";
|
|
16403
|
+
import { join as join14 } from "path";
|
|
16404
|
+
var __dirname = "/home/runner/work/reap/reap/src/core";
|
|
16405
|
+
function extractLanguageSection(body, language) {
|
|
16406
|
+
const lang = language.toLowerCase();
|
|
16407
|
+
const pattern = new RegExp(`^## ${lang}\\s*$`, "im");
|
|
16408
|
+
const match = pattern.exec(body);
|
|
16409
|
+
if (!match)
|
|
16410
|
+
return null;
|
|
16411
|
+
const start = match.index + match[0].length;
|
|
16412
|
+
const rest = body.slice(start);
|
|
16413
|
+
const nextHeader = rest.search(/^## /m);
|
|
16414
|
+
const section = nextHeader === -1 ? rest : rest.slice(0, nextHeader);
|
|
16415
|
+
return section.trim() || null;
|
|
16416
|
+
}
|
|
16417
|
+
function findNoticeUrl(version) {
|
|
16418
|
+
try {
|
|
16419
|
+
const noticePath = join14(__dirname, "../../UPDATE_NOTICE.md");
|
|
16420
|
+
const content = readFileSync(noticePath, "utf-8");
|
|
16421
|
+
const versionTag = version.startsWith("v") ? version : `v${version}`;
|
|
16422
|
+
const pattern = new RegExp(`^- ${versionTag.replace(/\./g, "\\.")}:\\s*(.+)$`, "m");
|
|
16423
|
+
const match = pattern.exec(content);
|
|
16424
|
+
return match?.[1]?.trim() ?? null;
|
|
16425
|
+
} catch {
|
|
16426
|
+
return null;
|
|
16427
|
+
}
|
|
16428
|
+
}
|
|
16429
|
+
async function fetchDiscussionBody(url) {
|
|
16430
|
+
try {
|
|
16431
|
+
const match = url.match(/discussions\/(\d+)/);
|
|
16432
|
+
if (!match)
|
|
16433
|
+
return null;
|
|
16434
|
+
const res = await fetch(`https://api.github.com/repos/c-d-cc/reap/discussions/${match[1]}`, {
|
|
16435
|
+
headers: { Accept: "application/vnd.github+json" },
|
|
16436
|
+
signal: AbortSignal.timeout(5000)
|
|
16437
|
+
});
|
|
16438
|
+
if (!res.ok)
|
|
16439
|
+
return null;
|
|
16440
|
+
const data = await res.json();
|
|
16441
|
+
return data.body?.trim() ?? null;
|
|
16442
|
+
} catch {
|
|
16443
|
+
return null;
|
|
16444
|
+
}
|
|
16445
|
+
}
|
|
16446
|
+
async function fetchReleaseNotice(version, language) {
|
|
16447
|
+
const url = findNoticeUrl(version);
|
|
16448
|
+
if (!url)
|
|
16449
|
+
return null;
|
|
16450
|
+
const body = await fetchDiscussionBody(url);
|
|
16451
|
+
if (!body)
|
|
16452
|
+
return null;
|
|
16453
|
+
const versionTag = version.startsWith("v") ? version : `v${version}`;
|
|
16454
|
+
const section = extractLanguageSection(body, language);
|
|
16455
|
+
const content = section ?? body;
|
|
16456
|
+
if (!content)
|
|
16457
|
+
return null;
|
|
16458
|
+
return `
|
|
16459
|
+
--- Release Notes (${versionTag}) ---
|
|
16460
|
+
${content}
|
|
16461
|
+
`;
|
|
16462
|
+
}
|
|
16463
|
+
|
|
16464
|
+
// src/cli/index.ts
|
|
16465
|
+
init_version();
|
|
16466
|
+
|
|
16296
16467
|
// src/cli/commands/status.ts
|
|
16297
16468
|
init_paths();
|
|
16298
16469
|
init_generation();
|
|
@@ -16330,7 +16501,7 @@ init_lifecycle();
|
|
|
16330
16501
|
init_fs();
|
|
16331
16502
|
var import_yaml7 = __toESM(require_dist(), 1);
|
|
16332
16503
|
import { mkdir as mkdir8, stat as stat4, copyFile } from "fs/promises";
|
|
16333
|
-
import { join as
|
|
16504
|
+
import { join as join15 } from "path";
|
|
16334
16505
|
async function checkProject(projectRoot) {
|
|
16335
16506
|
const paths = new ReapPaths(projectRoot);
|
|
16336
16507
|
const [structureResult, userLevelResult] = await Promise.all([
|
|
@@ -16376,7 +16547,7 @@ async function fixProject(projectRoot) {
|
|
|
16376
16547
|
];
|
|
16377
16548
|
for (const gf of genomeFiles) {
|
|
16378
16549
|
if (!await fileExists(gf.path)) {
|
|
16379
|
-
const templateSrc =
|
|
16550
|
+
const templateSrc = join15(ReapPaths.packageGenomeDir, gf.name);
|
|
16380
16551
|
if (await fileExists(templateSrc)) {
|
|
16381
16552
|
await copyFile(templateSrc, gf.path);
|
|
16382
16553
|
fixed.push(`Restored missing genome/${gf.name} from template`);
|
|
@@ -16418,7 +16589,7 @@ init_fs();
|
|
|
16418
16589
|
init_paths();
|
|
16419
16590
|
init_config();
|
|
16420
16591
|
import { rm as rm4 } from "fs/promises";
|
|
16421
|
-
import { join as
|
|
16592
|
+
import { join as join16 } from "path";
|
|
16422
16593
|
async function getProjectName(projectRoot) {
|
|
16423
16594
|
try {
|
|
16424
16595
|
const paths = new ReapPaths(projectRoot);
|
|
@@ -16431,7 +16602,7 @@ async function getProjectName(projectRoot) {
|
|
|
16431
16602
|
async function destroyProject(projectRoot) {
|
|
16432
16603
|
const removed = [];
|
|
16433
16604
|
const skipped = [];
|
|
16434
|
-
const reapDir =
|
|
16605
|
+
const reapDir = join16(projectRoot, ".reap");
|
|
16435
16606
|
if (await fileExists(reapDir)) {
|
|
16436
16607
|
await rm4(reapDir, { recursive: true, force: true });
|
|
16437
16608
|
removed.push(".reap/");
|
|
@@ -16450,7 +16621,7 @@ async function destroyProject(projectRoot) {
|
|
|
16450
16621
|
return { removed, skipped };
|
|
16451
16622
|
}
|
|
16452
16623
|
async function cleanGitignore(projectRoot, removed, skipped) {
|
|
16453
|
-
const gitignorePath =
|
|
16624
|
+
const gitignorePath = join16(projectRoot, ".gitignore");
|
|
16454
16625
|
const content = await readTextFile(gitignorePath);
|
|
16455
16626
|
if (content === null) {
|
|
16456
16627
|
skipped.push(".gitignore (not found)");
|
|
@@ -16487,7 +16658,7 @@ init_paths();
|
|
|
16487
16658
|
init_fs();
|
|
16488
16659
|
init_generation();
|
|
16489
16660
|
import { rm as rm5, readdir as readdir13, mkdir as mkdir9 } from "fs/promises";
|
|
16490
|
-
import { join as
|
|
16661
|
+
import { join as join17 } from "path";
|
|
16491
16662
|
async function hasActiveGeneration(projectRoot) {
|
|
16492
16663
|
const paths = new ReapPaths(projectRoot);
|
|
16493
16664
|
try {
|
|
@@ -16573,9 +16744,9 @@ async function compressLineage(paths, actions) {
|
|
|
16573
16744
|
].join(`
|
|
16574
16745
|
`);
|
|
16575
16746
|
for (const dir of genDirs) {
|
|
16576
|
-
await rm5(
|
|
16747
|
+
await rm5(join17(lineageDir, dir), { recursive: true, force: true });
|
|
16577
16748
|
}
|
|
16578
|
-
await writeTextFile(
|
|
16749
|
+
await writeTextFile(join17(lineageDir, `${epochId}.md`), summary);
|
|
16579
16750
|
actions.push(`Lineage: ${genDirs.length}개 세대를 ${epochId}로 압축`);
|
|
16580
16751
|
}
|
|
16581
16752
|
async function cleanLife(paths, actions) {
|
|
@@ -16595,7 +16766,7 @@ async function cleanLife(paths, actions) {
|
|
|
16595
16766
|
for (const entry of entries) {
|
|
16596
16767
|
if (entry === "backlog")
|
|
16597
16768
|
continue;
|
|
16598
|
-
const entryPath =
|
|
16769
|
+
const entryPath = join17(lifeDir, entry);
|
|
16599
16770
|
await rm5(entryPath, { recursive: true, force: true });
|
|
16600
16771
|
removedCount++;
|
|
16601
16772
|
}
|
|
@@ -16604,14 +16775,14 @@ async function cleanLife(paths, actions) {
|
|
|
16604
16775
|
async function resetGenomeToTemplate(paths, actions) {
|
|
16605
16776
|
const genomeFiles = ["principles.md", "conventions.md", "constraints.md", "source-map.md"];
|
|
16606
16777
|
for (const file of genomeFiles) {
|
|
16607
|
-
const templatePath =
|
|
16608
|
-
const destPath =
|
|
16778
|
+
const templatePath = join17(ReapPaths.packageGenomeDir, file);
|
|
16779
|
+
const destPath = join17(paths.genome, file);
|
|
16609
16780
|
try {
|
|
16610
16781
|
const templateContent = await readTextFileOrThrow(templatePath);
|
|
16611
16782
|
await writeTextFile(destPath, templateContent);
|
|
16612
16783
|
} catch {}
|
|
16613
16784
|
}
|
|
16614
|
-
const envSummaryTemplate =
|
|
16785
|
+
const envSummaryTemplate = join17(ReapPaths.packageTemplatesDir, "environment", "summary.md");
|
|
16615
16786
|
if (await fileExists(envSummaryTemplate)) {
|
|
16616
16787
|
try {
|
|
16617
16788
|
const content = await readTextFileOrThrow(envSummaryTemplate);
|
|
@@ -16627,8 +16798,8 @@ init_paths();
|
|
|
16627
16798
|
init_fs();
|
|
16628
16799
|
init_version();
|
|
16629
16800
|
init_config();
|
|
16630
|
-
import { join as
|
|
16631
|
-
program.name("reap").description("REAP — Recursive Evolutionary Autonomous Pipeline").version("0.15.
|
|
16801
|
+
import { join as join34 } from "path";
|
|
16802
|
+
program.name("reap").description("REAP — Recursive Evolutionary Autonomous Pipeline").version("0.15.5");
|
|
16632
16803
|
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) => {
|
|
16633
16804
|
try {
|
|
16634
16805
|
const cwd = process.cwd();
|
|
@@ -16685,7 +16856,7 @@ program.command("status").description("Show current project and Generation statu
|
|
|
16685
16856
|
const paths = new ReapPaths(cwd);
|
|
16686
16857
|
const config = await ConfigManager.read(paths);
|
|
16687
16858
|
const skipCheck = config.autoUpdate === false;
|
|
16688
|
-
const installedVersion = "0.15.
|
|
16859
|
+
const installedVersion = "0.15.5";
|
|
16689
16860
|
const versionLine = formatVersionLine(installedVersion, skipCheck);
|
|
16690
16861
|
console.log(`${versionLine} | Project: ${status.project} (${status.entryMode})`);
|
|
16691
16862
|
console.log(`Completed Generations: ${status.totalGenerations}`);
|
|
@@ -16797,6 +16968,13 @@ Integrity: ${parts.join(", ")} (run 'reap fix --check' for details)`);
|
|
|
16797
16968
|
Integrity: ✓ OK`);
|
|
16798
16969
|
}
|
|
16799
16970
|
} catch {}
|
|
16971
|
+
try {
|
|
16972
|
+
const version = getCurrentVersion();
|
|
16973
|
+
const lang = await AgentRegistry.readLanguage() ?? "en";
|
|
16974
|
+
const notice = await fetchReleaseNotice(version, lang);
|
|
16975
|
+
if (notice)
|
|
16976
|
+
console.log(notice);
|
|
16977
|
+
} catch {}
|
|
16800
16978
|
} catch (e) {
|
|
16801
16979
|
console.error(`Error: ${e.message}`);
|
|
16802
16980
|
process.exit(1);
|
|
@@ -16810,10 +16988,10 @@ program.command("help").description("Show REAP commands, slash commands, and wor
|
|
|
16810
16988
|
if (l === "korean" || l === "ko")
|
|
16811
16989
|
lang = "ko";
|
|
16812
16990
|
}
|
|
16813
|
-
const helpDir =
|
|
16814
|
-
let helpText = await readTextFile(
|
|
16991
|
+
const helpDir = join34(ReapPaths.packageTemplatesDir, "help");
|
|
16992
|
+
let helpText = await readTextFile(join34(helpDir, `${lang}.txt`));
|
|
16815
16993
|
if (!helpText)
|
|
16816
|
-
helpText = await readTextFile(
|
|
16994
|
+
helpText = await readTextFile(join34(helpDir, "en.txt"));
|
|
16817
16995
|
if (!helpText) {
|
|
16818
16996
|
console.log("Help file not found. Run 'reap update' to install templates.");
|
|
16819
16997
|
return;
|
|
@@ -16917,6 +17095,22 @@ Clean complete. Run /reap.start to begin a new generation.`);
|
|
|
16917
17095
|
process.exit(1);
|
|
16918
17096
|
}
|
|
16919
17097
|
});
|
|
17098
|
+
program.command("make <target>").description("Create REAP resources (e.g., backlog items)").allowUnknownOption().action(async (target, _options, cmd) => {
|
|
17099
|
+
try {
|
|
17100
|
+
const cwd = process.cwd();
|
|
17101
|
+
const paths = new ReapPaths(cwd);
|
|
17102
|
+
if (!await paths.isReapProject()) {
|
|
17103
|
+
console.error("Error: Not a REAP project. Run 'reap init' first.");
|
|
17104
|
+
process.exit(1);
|
|
17105
|
+
}
|
|
17106
|
+
const passArgs = [target, ...cmd.args.slice(1)];
|
|
17107
|
+
const { execute: execute33 } = await Promise.resolve().then(() => (init_make(), exports_make));
|
|
17108
|
+
await execute33(paths, undefined, passArgs);
|
|
17109
|
+
} catch (e) {
|
|
17110
|
+
console.error(`Error: ${e.message}`);
|
|
17111
|
+
process.exit(1);
|
|
17112
|
+
}
|
|
17113
|
+
});
|
|
16920
17114
|
program.command("run <command>").description("Run a REAP command script (internal, used by slash commands)").option("--phase <phase>", "Start from a specific phase").allowUnknownOption().action(async (command, options, cmd) => {
|
|
16921
17115
|
const rawArgs = cmd.args.slice(1);
|
|
16922
17116
|
const passArgs = [];
|