@c-d-cc/reap 0.16.5 → 0.17.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.de.md +48 -0
- package/README.ja.md +48 -0
- package/README.ko.md +50 -0
- package/README.md +56 -0
- package/README.zh-CN.md +50 -0
- package/RELEASE_NOTICE.md +12 -0
- package/dist/cli/index.js +960 -507
- package/dist/templates/agents/reap-evaluate.md +21 -0
- package/dist/templates/agents/reap-evolve.md +49 -0
- package/dist/templates/reap-guide.md +82 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -7067,10 +7067,10 @@ var init_types = __esm(() => {
|
|
|
7067
7067
|
|
|
7068
7068
|
// src/core/integrity.ts
|
|
7069
7069
|
import { readdir, stat, rm, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
7070
|
-
import { join as
|
|
7070
|
+
import { join as join4 } from "path";
|
|
7071
7071
|
import { homedir } from "os";
|
|
7072
7072
|
async function detectV15(paths) {
|
|
7073
|
-
return fileExists(
|
|
7073
|
+
return fileExists(join4(paths.genome, "principles.md"));
|
|
7074
7074
|
}
|
|
7075
7075
|
async function checkIntegrity(paths) {
|
|
7076
7076
|
const errors = [];
|
|
@@ -7121,8 +7121,8 @@ async function checkDirectoryStructure(paths, errors) {
|
|
|
7121
7121
|
}
|
|
7122
7122
|
}
|
|
7123
7123
|
async function checkRequiredFiles(paths, errors, warnings) {
|
|
7124
|
-
const guideGlobal =
|
|
7125
|
-
const guideLocal =
|
|
7124
|
+
const guideGlobal = join4(homedir(), ".reap", "reap-guide.md");
|
|
7125
|
+
const guideLocal = join4(paths.reap, "reap-guide.md");
|
|
7126
7126
|
if (!await fileExists(guideGlobal) && !await fileExists(guideLocal)) {
|
|
7127
7127
|
errors.push("reap-guide.md missing — run 'npm install -g @c-d-cc/reap' to reinstall");
|
|
7128
7128
|
}
|
|
@@ -7139,7 +7139,7 @@ async function checkRequiredFiles(paths, errors, warnings) {
|
|
|
7139
7139
|
if (!await fileExists(paths.visionGoals)) {
|
|
7140
7140
|
warnings.push("vision/goals.md missing");
|
|
7141
7141
|
}
|
|
7142
|
-
const claudeMdPath =
|
|
7142
|
+
const claudeMdPath = join4(paths.root, "CLAUDE.md");
|
|
7143
7143
|
const claudeMd = await readTextFile(claudeMdPath);
|
|
7144
7144
|
if (!claudeMd) {
|
|
7145
7145
|
warnings.push("CLAUDE.md missing — run 'reap init --repair'");
|
|
@@ -7155,7 +7155,7 @@ async function checkConfig(paths, errors, warnings) {
|
|
|
7155
7155
|
}
|
|
7156
7156
|
let config;
|
|
7157
7157
|
try {
|
|
7158
|
-
config =
|
|
7158
|
+
config = import_yaml3.default.parse(content) ?? {};
|
|
7159
7159
|
} catch {
|
|
7160
7160
|
errors.push("config.yml is not valid YAML");
|
|
7161
7161
|
return;
|
|
@@ -7199,7 +7199,7 @@ async function checkCurrentYml(paths, errors, _warnings) {
|
|
|
7199
7199
|
}
|
|
7200
7200
|
let state;
|
|
7201
7201
|
try {
|
|
7202
|
-
state =
|
|
7202
|
+
state = import_yaml3.default.parse(content) ?? {};
|
|
7203
7203
|
} catch {
|
|
7204
7204
|
errors.push("current.yml is not valid YAML");
|
|
7205
7205
|
return null;
|
|
@@ -7247,7 +7247,7 @@ async function checkLineage(paths, errors, warnings) {
|
|
|
7247
7247
|
for (const name of items) {
|
|
7248
7248
|
if (!name.startsWith("gen-"))
|
|
7249
7249
|
continue;
|
|
7250
|
-
const itemPath =
|
|
7250
|
+
const itemPath = join4(paths.lineage, name);
|
|
7251
7251
|
let itemStat;
|
|
7252
7252
|
try {
|
|
7253
7253
|
itemStat = await stat(itemPath);
|
|
@@ -7255,7 +7255,7 @@ async function checkLineage(paths, errors, warnings) {
|
|
|
7255
7255
|
continue;
|
|
7256
7256
|
}
|
|
7257
7257
|
if (itemStat.isDirectory()) {
|
|
7258
|
-
const metaPath =
|
|
7258
|
+
const metaPath = join4(paths.lineage, name, "meta.yml");
|
|
7259
7259
|
const metaContent = await readTextFile(metaPath);
|
|
7260
7260
|
if (metaContent === null) {
|
|
7261
7261
|
errors.push(`lineage/${name}: missing meta.yml`);
|
|
@@ -7263,7 +7263,7 @@ async function checkLineage(paths, errors, warnings) {
|
|
|
7263
7263
|
}
|
|
7264
7264
|
let meta;
|
|
7265
7265
|
try {
|
|
7266
|
-
meta =
|
|
7266
|
+
meta = import_yaml3.default.parse(metaContent) ?? {};
|
|
7267
7267
|
} catch {
|
|
7268
7268
|
errors.push(`lineage/${name}/meta.yml: invalid YAML`);
|
|
7269
7269
|
continue;
|
|
@@ -7272,7 +7272,7 @@ async function checkLineage(paths, errors, warnings) {
|
|
|
7272
7272
|
if (meta.id)
|
|
7273
7273
|
allMetaIds.add(meta.id);
|
|
7274
7274
|
} else if (itemStat.isFile() && name.endsWith(".md")) {
|
|
7275
|
-
const content = await readTextFile(
|
|
7275
|
+
const content = await readTextFile(join4(paths.lineage, name));
|
|
7276
7276
|
if (!content)
|
|
7277
7277
|
continue;
|
|
7278
7278
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
@@ -7282,7 +7282,7 @@ async function checkLineage(paths, errors, warnings) {
|
|
|
7282
7282
|
}
|
|
7283
7283
|
let meta;
|
|
7284
7284
|
try {
|
|
7285
|
-
meta =
|
|
7285
|
+
meta = import_yaml3.default.parse(fmMatch[1]) ?? {};
|
|
7286
7286
|
} catch {
|
|
7287
7287
|
errors.push(`lineage/${name}: invalid frontmatter YAML`);
|
|
7288
7288
|
continue;
|
|
@@ -7295,7 +7295,7 @@ async function checkLineage(paths, errors, warnings) {
|
|
|
7295
7295
|
for (const name of items) {
|
|
7296
7296
|
if (!name.startsWith("gen-"))
|
|
7297
7297
|
continue;
|
|
7298
|
-
const itemPath =
|
|
7298
|
+
const itemPath = join4(paths.lineage, name);
|
|
7299
7299
|
let parents = [];
|
|
7300
7300
|
let itemStat;
|
|
7301
7301
|
try {
|
|
@@ -7304,20 +7304,20 @@ async function checkLineage(paths, errors, warnings) {
|
|
|
7304
7304
|
continue;
|
|
7305
7305
|
}
|
|
7306
7306
|
if (itemStat.isDirectory()) {
|
|
7307
|
-
const metaContent = await readTextFile(
|
|
7307
|
+
const metaContent = await readTextFile(join4(paths.lineage, name, "meta.yml"));
|
|
7308
7308
|
if (metaContent) {
|
|
7309
7309
|
try {
|
|
7310
|
-
const meta =
|
|
7310
|
+
const meta = import_yaml3.default.parse(metaContent);
|
|
7311
7311
|
parents = meta?.parents ?? [];
|
|
7312
7312
|
} catch {}
|
|
7313
7313
|
}
|
|
7314
7314
|
} else if (itemStat.isFile() && name.endsWith(".md")) {
|
|
7315
|
-
const content = await readTextFile(
|
|
7315
|
+
const content = await readTextFile(join4(paths.lineage, name));
|
|
7316
7316
|
if (content) {
|
|
7317
7317
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
7318
7318
|
if (fmMatch) {
|
|
7319
7319
|
try {
|
|
7320
|
-
const meta =
|
|
7320
|
+
const meta = import_yaml3.default.parse(fmMatch[1]);
|
|
7321
7321
|
parents = meta?.parents ?? [];
|
|
7322
7322
|
} catch {}
|
|
7323
7323
|
}
|
|
@@ -7325,7 +7325,7 @@ async function checkLineage(paths, errors, warnings) {
|
|
|
7325
7325
|
}
|
|
7326
7326
|
for (const parent of parents) {
|
|
7327
7327
|
if (parent && !allMetaIds.has(parent)) {
|
|
7328
|
-
const epochContent = await readTextFile(
|
|
7328
|
+
const epochContent = await readTextFile(join4(paths.lineage, "epoch.md"));
|
|
7329
7329
|
let inEpoch = false;
|
|
7330
7330
|
if (epochContent) {
|
|
7331
7331
|
inEpoch = epochContent.includes(parent);
|
|
@@ -7397,7 +7397,7 @@ async function checkBacklog(paths, errors, _warnings) {
|
|
|
7397
7397
|
for (const filename of entries) {
|
|
7398
7398
|
if (!filename.endsWith(".md"))
|
|
7399
7399
|
continue;
|
|
7400
|
-
const content = await readTextFile(
|
|
7400
|
+
const content = await readTextFile(join4(paths.backlog, filename));
|
|
7401
7401
|
if (!content)
|
|
7402
7402
|
continue;
|
|
7403
7403
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
@@ -7407,7 +7407,7 @@ async function checkBacklog(paths, errors, _warnings) {
|
|
|
7407
7407
|
}
|
|
7408
7408
|
let fm;
|
|
7409
7409
|
try {
|
|
7410
|
-
fm =
|
|
7410
|
+
fm = import_yaml3.default.parse(fmMatch[1]) ?? {};
|
|
7411
7411
|
} catch {
|
|
7412
7412
|
errors.push(`backlog/${filename}: invalid frontmatter YAML`);
|
|
7413
7413
|
continue;
|
|
@@ -7431,9 +7431,9 @@ async function checkUserLevelArtifacts(projectRoot) {
|
|
|
7431
7431
|
const errors = [];
|
|
7432
7432
|
const warnings = [];
|
|
7433
7433
|
const home = homedir();
|
|
7434
|
-
await checkGlobPattern(
|
|
7435
|
-
await checkGlobPattern(
|
|
7436
|
-
await checkGlobPattern(
|
|
7434
|
+
await checkGlobPattern(join4(home, ".claude", "skills"), /^reap\./, "~/.claude/skills/", "user-level reap skill found (should only be project-level)", errors);
|
|
7435
|
+
await checkGlobPattern(join4(home, ".claude", "commands"), /^reap\./, "~/.claude/commands/", "legacy reap command at user level (Phase 2 remnant)", warnings);
|
|
7436
|
+
await checkGlobPattern(join4(projectRoot, ".claude", "commands"), /^reap\./, ".claude/commands/", "legacy project-level reap command (should be migrated to skills/)", warnings);
|
|
7437
7437
|
return { errors, warnings };
|
|
7438
7438
|
}
|
|
7439
7439
|
async function checkGlobPattern(dir, pattern, displayDir, message, target) {
|
|
@@ -7451,22 +7451,22 @@ async function checkGlobPattern(dir, pattern, displayDir, message, target) {
|
|
|
7451
7451
|
}
|
|
7452
7452
|
async function cleanupLegacyProjectSkills(projectRoot) {
|
|
7453
7453
|
const deleted = [];
|
|
7454
|
-
const commandsDir =
|
|
7454
|
+
const commandsDir = join4(projectRoot, ".claude", "commands");
|
|
7455
7455
|
try {
|
|
7456
7456
|
const entries = await readdir(commandsDir);
|
|
7457
7457
|
for (const entry of entries) {
|
|
7458
7458
|
if (LEGACY_COMMAND_PATTERN.test(entry)) {
|
|
7459
|
-
await rm(
|
|
7459
|
+
await rm(join4(commandsDir, entry), { force: true });
|
|
7460
7460
|
deleted.push(`.claude/commands/${entry}`);
|
|
7461
7461
|
}
|
|
7462
7462
|
}
|
|
7463
7463
|
} catch {}
|
|
7464
|
-
const skillsDir =
|
|
7464
|
+
const skillsDir = join4(projectRoot, ".claude", "skills");
|
|
7465
7465
|
try {
|
|
7466
7466
|
const entries = await readdir(skillsDir);
|
|
7467
7467
|
for (const entry of entries) {
|
|
7468
7468
|
if (LEGACY_SKILL_PATTERN.test(entry)) {
|
|
7469
|
-
const entryPath =
|
|
7469
|
+
const entryPath = join4(skillsDir, entry);
|
|
7470
7470
|
try {
|
|
7471
7471
|
const s = await stat(entryPath);
|
|
7472
7472
|
if (s.isDirectory()) {
|
|
@@ -7482,8 +7482,8 @@ async function cleanupLegacyProjectSkills(projectRoot) {
|
|
|
7482
7482
|
async function cleanupLegacyHooks(projectRoot) {
|
|
7483
7483
|
const modified = [];
|
|
7484
7484
|
const settingsPaths = [
|
|
7485
|
-
|
|
7486
|
-
|
|
7485
|
+
join4(projectRoot, ".claude", "settings.json"),
|
|
7486
|
+
join4(homedir(), ".claude", "settings.json")
|
|
7487
7487
|
];
|
|
7488
7488
|
for (const settingsPath of settingsPaths) {
|
|
7489
7489
|
try {
|
|
@@ -7518,11 +7518,11 @@ async function cleanupLegacyHooks(projectRoot) {
|
|
|
7518
7518
|
}
|
|
7519
7519
|
return modified;
|
|
7520
7520
|
}
|
|
7521
|
-
var
|
|
7521
|
+
var import_yaml3, VALID_BACKLOG_TYPES, VALID_BACKLOG_STATUSES, VALID_GENERATION_TYPES, GENOME_LINE_WARNING_THRESHOLD = 100, LEGACY_COMMAND_PATTERN, LEGACY_SKILL_PATTERN;
|
|
7522
7522
|
var init_integrity = __esm(() => {
|
|
7523
7523
|
init_fs();
|
|
7524
7524
|
init_types();
|
|
7525
|
-
|
|
7525
|
+
import_yaml3 = __toESM(require_dist(), 1);
|
|
7526
7526
|
VALID_BACKLOG_TYPES = ["genome-change", "environment-change", "task"];
|
|
7527
7527
|
VALID_BACKLOG_STATUSES = ["pending", "consumed"];
|
|
7528
7528
|
VALID_GENERATION_TYPES = ["embryo", "normal", "merge"];
|
|
@@ -7543,13 +7543,13 @@ __export(exports_common, {
|
|
|
7543
7543
|
buildPromptPreamble: () => buildPromptPreamble,
|
|
7544
7544
|
buildHardGateBlock: () => buildHardGateBlock
|
|
7545
7545
|
});
|
|
7546
|
-
import { join as
|
|
7546
|
+
import { join as join5, dirname as dirname3 } from "path";
|
|
7547
7547
|
import { fileURLToPath } from "url";
|
|
7548
7548
|
import { createHash } from "crypto";
|
|
7549
7549
|
import { readdir as readdir2, copyFile, chmod } from "fs/promises";
|
|
7550
7550
|
function distPath(...segments) {
|
|
7551
7551
|
const __dirname2 = dirname3(fileURLToPath(import.meta.url));
|
|
7552
|
-
return
|
|
7552
|
+
return join5(__dirname2, "..", "templates", ...segments);
|
|
7553
7553
|
}
|
|
7554
7554
|
async function initCommon(paths, projectName) {
|
|
7555
7555
|
await cleanupLegacyProjectSkills(paths.root);
|
|
@@ -7576,7 +7576,7 @@ async function initCommon(paths, projectName) {
|
|
|
7576
7576
|
autoUpdate: true,
|
|
7577
7577
|
autoIssueReport: true
|
|
7578
7578
|
};
|
|
7579
|
-
await writeTextFile(paths.config,
|
|
7579
|
+
await writeTextFile(paths.config, import_yaml4.default.stringify(config));
|
|
7580
7580
|
const evolution = await readTextFile(distPath("evolution.md"));
|
|
7581
7581
|
await writeTextFile(paths.evolution, evolution ?? `# Evolution
|
|
7582
7582
|
`);
|
|
@@ -7662,8 +7662,8 @@ async function ensureClaudeMd(root, projectName) {
|
|
|
7662
7662
|
const templateContent = stripMarkers(rawTemplate);
|
|
7663
7663
|
const wrappedSection = wrapWithMarkers(templateContent);
|
|
7664
7664
|
const newHash = computeSectionHash(templateContent);
|
|
7665
|
-
const rootPath =
|
|
7666
|
-
const dotClaudePath =
|
|
7665
|
+
const rootPath = join5(root, "CLAUDE.md");
|
|
7666
|
+
const dotClaudePath = join5(root, ".claude", "CLAUDE.md");
|
|
7667
7667
|
const rootContent = await readTextFile(rootPath);
|
|
7668
7668
|
const dotClaudeContent = await readTextFile(dotClaudePath);
|
|
7669
7669
|
const result = await updateClaudeMdFile(rootPath, rootContent, newHash, wrappedSection);
|
|
@@ -7731,15 +7731,15 @@ async function updateClaudeMdFile(filePath, content, newHash, wrappedSection) {
|
|
|
7731
7731
|
}
|
|
7732
7732
|
async function installHookTemplates(hooksDir) {
|
|
7733
7733
|
const templateDir = distPath("hooks");
|
|
7734
|
-
const conditionsTemplateDir =
|
|
7735
|
-
const conditionsDir =
|
|
7734
|
+
const conditionsTemplateDir = join5(templateDir, "conditions");
|
|
7735
|
+
const conditionsDir = join5(hooksDir, "conditions");
|
|
7736
7736
|
await ensureDir(conditionsDir);
|
|
7737
7737
|
try {
|
|
7738
7738
|
const conditionFiles = await readdir2(conditionsTemplateDir);
|
|
7739
7739
|
for (const file of conditionFiles) {
|
|
7740
|
-
const dest =
|
|
7740
|
+
const dest = join5(conditionsDir, file);
|
|
7741
7741
|
if (!await fileExists(dest)) {
|
|
7742
|
-
await copyFile(
|
|
7742
|
+
await copyFile(join5(conditionsTemplateDir, file), dest);
|
|
7743
7743
|
await chmod(dest, 493);
|
|
7744
7744
|
}
|
|
7745
7745
|
}
|
|
@@ -7749,14 +7749,14 @@ async function installHookTemplates(hooksDir) {
|
|
|
7749
7749
|
for (const file of hookFiles) {
|
|
7750
7750
|
if (!file.endsWith(".example"))
|
|
7751
7751
|
continue;
|
|
7752
|
-
const dest =
|
|
7752
|
+
const dest = join5(hooksDir, file);
|
|
7753
7753
|
if (!await fileExists(dest)) {
|
|
7754
|
-
await copyFile(
|
|
7754
|
+
await copyFile(join5(templateDir, file), dest);
|
|
7755
7755
|
}
|
|
7756
7756
|
}
|
|
7757
7757
|
} catch {}
|
|
7758
7758
|
}
|
|
7759
|
-
var
|
|
7759
|
+
var import_yaml4, DEFAULT_INVARIANTS = `# Invariants
|
|
7760
7760
|
|
|
7761
7761
|
> Absolute constraints. Human-only modification.
|
|
7762
7762
|
|
|
@@ -7774,17 +7774,27 @@ var import_yaml3, DEFAULT_INVARIANTS = `# Invariants
|
|
|
7774
7774
|
var init_common = __esm(() => {
|
|
7775
7775
|
init_fs();
|
|
7776
7776
|
init_integrity();
|
|
7777
|
-
|
|
7777
|
+
import_yaml4 = __toESM(require_dist(), 1);
|
|
7778
7778
|
REAP_START_RE = /<!-- reap:start ([a-f0-9]+) -->/;
|
|
7779
7779
|
});
|
|
7780
7780
|
|
|
7781
7781
|
// src/cli/commands/daemon/client.ts
|
|
7782
7782
|
import { spawn, execSync as execSync6 } from "child_process";
|
|
7783
|
-
import { join as
|
|
7783
|
+
import { join as join12 } from "path";
|
|
7784
7784
|
import { homedir as homedir3 } from "os";
|
|
7785
|
+
function resolvePort() {
|
|
7786
|
+
const raw = process.env.REAP_DAEMON_PORT;
|
|
7787
|
+
if (!raw)
|
|
7788
|
+
return DEFAULT_PORT;
|
|
7789
|
+
const n = Number(raw);
|
|
7790
|
+
return Number.isFinite(n) && n > 0 ? n : DEFAULT_PORT;
|
|
7791
|
+
}
|
|
7792
|
+
function getBaseUrl() {
|
|
7793
|
+
return `http://127.0.0.1:${resolvePort()}`;
|
|
7794
|
+
}
|
|
7785
7795
|
async function daemonRequest(method, path, body) {
|
|
7786
7796
|
await ensureDaemon();
|
|
7787
|
-
const res = await fetch(`${
|
|
7797
|
+
const res = await fetch(`${getBaseUrl()}${path}`, {
|
|
7788
7798
|
method,
|
|
7789
7799
|
headers: body ? { "Content-Type": "application/json" } : undefined,
|
|
7790
7800
|
body: body ? JSON.stringify(body) : undefined
|
|
@@ -7811,7 +7821,7 @@ async function ensureDaemon() {
|
|
|
7811
7821
|
}
|
|
7812
7822
|
async function isDaemonRunning() {
|
|
7813
7823
|
try {
|
|
7814
|
-
const res = await fetch(`${
|
|
7824
|
+
const res = await fetch(`${getBaseUrl()}/health`, { signal: AbortSignal.timeout(500) });
|
|
7815
7825
|
return res.ok;
|
|
7816
7826
|
} catch {
|
|
7817
7827
|
return false;
|
|
@@ -7821,7 +7831,7 @@ function resolveDaemonBin() {
|
|
|
7821
7831
|
try {
|
|
7822
7832
|
return __require.resolve("@c-d-cc/reap-daemon/dist/index.js");
|
|
7823
7833
|
} catch {
|
|
7824
|
-
return
|
|
7834
|
+
return join12(__dirname, "..", "..", "..", "daemon", "dist", "index.js");
|
|
7825
7835
|
}
|
|
7826
7836
|
}
|
|
7827
7837
|
function detectRuntime() {
|
|
@@ -7843,11 +7853,10 @@ async function findProjectId(projectRoot) {
|
|
|
7843
7853
|
return null;
|
|
7844
7854
|
}
|
|
7845
7855
|
}
|
|
7846
|
-
var __dirname = "/home/runner/work/reap/reap/src/cli/commands/daemon", DAEMON_ROOT, PID_PATH, DEFAULT_PORT = 17224
|
|
7856
|
+
var __dirname = "/home/runner/work/reap/reap/src/cli/commands/daemon", DAEMON_ROOT, PID_PATH, DEFAULT_PORT = 17224;
|
|
7847
7857
|
var init_client = __esm(() => {
|
|
7848
|
-
DAEMON_ROOT =
|
|
7849
|
-
PID_PATH =
|
|
7850
|
-
BASE_URL = `http://127.0.0.1:${DEFAULT_PORT}`;
|
|
7858
|
+
DAEMON_ROOT = join12(homedir3(), ".reap", "daemon");
|
|
7859
|
+
PID_PATH = join12(DAEMON_ROOT, "daemon.pid");
|
|
7851
7860
|
});
|
|
7852
7861
|
|
|
7853
7862
|
// src/cli/commands/daemon/lifecycle.ts
|
|
@@ -7860,12 +7869,15 @@ async function triggerIndexing(projectRoot) {
|
|
|
7860
7869
|
try {
|
|
7861
7870
|
const result = await daemonRequest("GET", "/projects");
|
|
7862
7871
|
if (result.status !== "ok" || !result.data)
|
|
7863
|
-
return;
|
|
7872
|
+
return false;
|
|
7864
7873
|
const project = result.data.find((p) => p.path === projectRoot);
|
|
7865
7874
|
if (!project)
|
|
7866
|
-
return;
|
|
7867
|
-
await daemonRequest("POST", `/projects/${project.id}/index`);
|
|
7868
|
-
|
|
7875
|
+
return false;
|
|
7876
|
+
const indexResult = await daemonRequest("POST", `/projects/${project.id}/index`);
|
|
7877
|
+
return indexResult.status === "ok";
|
|
7878
|
+
} catch {
|
|
7879
|
+
return false;
|
|
7880
|
+
}
|
|
7869
7881
|
}
|
|
7870
7882
|
async function ensureRegistered(projectRoot, name) {
|
|
7871
7883
|
try {
|
|
@@ -7873,10 +7885,13 @@ async function ensureRegistered(projectRoot, name) {
|
|
|
7873
7885
|
if (result.status === "ok" && result.data) {
|
|
7874
7886
|
const existing = result.data.find((p) => p.path === projectRoot);
|
|
7875
7887
|
if (existing)
|
|
7876
|
-
return;
|
|
7888
|
+
return true;
|
|
7877
7889
|
}
|
|
7878
|
-
await daemonRequest("POST", "/projects/register", { path: projectRoot, name });
|
|
7879
|
-
|
|
7890
|
+
const regResult = await daemonRequest("POST", "/projects/register", { path: projectRoot, name });
|
|
7891
|
+
return regResult.status === "ok";
|
|
7892
|
+
} catch {
|
|
7893
|
+
return false;
|
|
7894
|
+
}
|
|
7880
7895
|
}
|
|
7881
7896
|
var init_lifecycle = __esm(() => {
|
|
7882
7897
|
init_client();
|
|
@@ -8576,7 +8591,7 @@ var program = new Command;
|
|
|
8576
8591
|
|
|
8577
8592
|
// src/cli/commands/init/index.ts
|
|
8578
8593
|
import { readdir as readdir5 } from "fs/promises";
|
|
8579
|
-
import { join as
|
|
8594
|
+
import { join as join8 } from "path";
|
|
8580
8595
|
|
|
8581
8596
|
// src/core/paths.ts
|
|
8582
8597
|
import { join } from "path";
|
|
@@ -8623,9 +8638,9 @@ function createPaths(root) {
|
|
|
8623
8638
|
init_fs();
|
|
8624
8639
|
|
|
8625
8640
|
// src/core/dump-state-sync.ts
|
|
8626
|
-
var
|
|
8641
|
+
var import_yaml2 = __toESM(require_dist(), 1);
|
|
8627
8642
|
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
|
|
8628
|
-
import { join as
|
|
8643
|
+
import { join as join3, dirname as dirname2 } from "path";
|
|
8629
8644
|
|
|
8630
8645
|
// src/core/prompt.ts
|
|
8631
8646
|
init_fs();
|
|
@@ -8979,12 +8994,227 @@ function buildBasePrompt(knowledge, paths, state, cruiseCount, clarityResult, co
|
|
|
8979
8994
|
lines.push("");
|
|
8980
8995
|
}
|
|
8981
8996
|
}
|
|
8997
|
+
if (config?.daemon === true) {
|
|
8998
|
+
lines.push("## Code Intelligence (Daemon)");
|
|
8999
|
+
lines.push("");
|
|
9000
|
+
lines.push("REAP daemon is enabled. Prefer daemon queries over full-text search when possible.");
|
|
9001
|
+
lines.push("");
|
|
9002
|
+
lines.push("- Health: `curl -sf http://127.0.0.1:17224/health` — if it fails, daemon is down; skip silently.");
|
|
9003
|
+
lines.push("- Project ID lookup: `curl -s http://127.0.0.1:17224/projects | jq '.data[] | select(.path==\"<cwd>\")'`.");
|
|
9004
|
+
lines.push("- Symbol search: `GET /projects/{id}/symbols?q=<query>` — find function/class/type definitions.");
|
|
9005
|
+
lines.push("- Callers: `GET /projects/{id}/symbols/{symbolId}/callers` — who calls this symbol?");
|
|
9006
|
+
lines.push("- Impact: `GET /projects/{id}/impact?file=<path>` — blast radius of changes to a file.");
|
|
9007
|
+
lines.push("- Staleness: `GET /projects/{id}/status` includes `lastIndexedCommit`. Compare against `git rev-parse HEAD`; if different, the index is stale.");
|
|
9008
|
+
lines.push("");
|
|
9009
|
+
lines.push("See `~/.reap/reap-guide.md` § Code Intelligence (Daemon) for the full protocol.");
|
|
9010
|
+
lines.push("");
|
|
9011
|
+
}
|
|
9012
|
+
lines.push("## Project");
|
|
9013
|
+
lines.push(`Path: ${paths.root}`);
|
|
9014
|
+
return lines.join(`
|
|
9015
|
+
`);
|
|
9016
|
+
}
|
|
9017
|
+
function buildEvaluatorPrompt(knowledge, paths, state, opts) {
|
|
9018
|
+
const lines = [];
|
|
9019
|
+
const isMerge = state?.type === "merge";
|
|
9020
|
+
lines.push(`## Evaluator Invocation — ${opts.stage} stage`);
|
|
9021
|
+
lines.push("");
|
|
9022
|
+
if (opts.stage === "validation") {
|
|
9023
|
+
lines.push("You are being invoked during the **validation** stage of a REAP generation. " + "The builder (reap-evolve) has completed implementation and run validation checks. " + "Your role is independent verification: confirm the build is sound, tests pass, " + "completion criteria from 02-planning.md are met, and the code changes follow " + "genome conventions. Surface any concern the builder may have missed.");
|
|
9024
|
+
} else {
|
|
9025
|
+
lines.push("You are being invoked during the **fitness** phase of completion. " + "Assess the generation against the 6 fitness dimensions in your agent definition " + "(goal achievement, code quality, regression safety, artifact quality, vision alignment, " + "cross-generation coherence). Cross-reference with vision goals and recent lineage.");
|
|
9026
|
+
}
|
|
9027
|
+
lines.push("");
|
|
9028
|
+
lines.push("## Current Generation");
|
|
9029
|
+
if (state) {
|
|
9030
|
+
lines.push(`- ID: ${state.id}`);
|
|
9031
|
+
lines.push(`- Type: ${state.type}`);
|
|
9032
|
+
lines.push(`- Goal: ${state.goal}`);
|
|
9033
|
+
lines.push(`- Stage: ${state.stage}`);
|
|
9034
|
+
if (isMerge) {
|
|
9035
|
+
lines.push(`- Parents: ${state.parents.join(", ")}`);
|
|
9036
|
+
if (state.commonAncestor)
|
|
9037
|
+
lines.push(`- Common Ancestor: ${state.commonAncestor}`);
|
|
9038
|
+
}
|
|
9039
|
+
} else {
|
|
9040
|
+
lines.push("- (no active generation — abort and report to the user)");
|
|
9041
|
+
}
|
|
9042
|
+
lines.push("");
|
|
9043
|
+
lines.push("## Artifacts to Read");
|
|
9044
|
+
lines.push("");
|
|
9045
|
+
if (isMerge) {
|
|
9046
|
+
lines.push(`- ${paths.artifact("01-detect.md")}`);
|
|
9047
|
+
lines.push(`- ${paths.artifact("02-mate.md")}`);
|
|
9048
|
+
lines.push(`- ${paths.artifact("03-merge.md")}`);
|
|
9049
|
+
lines.push(`- ${paths.artifact("04-reconcile.md")}`);
|
|
9050
|
+
lines.push(`- ${paths.artifact("05-validation.md")}`);
|
|
9051
|
+
} else {
|
|
9052
|
+
lines.push(`- ${paths.artifact("01-learning.md")}`);
|
|
9053
|
+
lines.push(`- ${paths.artifact("02-planning.md")}`);
|
|
9054
|
+
lines.push(`- ${paths.artifact("03-implementation.md")}`);
|
|
9055
|
+
lines.push(`- ${paths.artifact("04-validation.md")}`);
|
|
9056
|
+
}
|
|
9057
|
+
lines.push("");
|
|
9058
|
+
if (knowledge.visionGoals) {
|
|
9059
|
+
lines.push("## Vision Goals (current)");
|
|
9060
|
+
lines.push(knowledge.visionGoals);
|
|
9061
|
+
lines.push("");
|
|
9062
|
+
}
|
|
9063
|
+
if (knowledge.memoryShortterm || knowledge.memoryMidterm) {
|
|
9064
|
+
lines.push("## Memory");
|
|
9065
|
+
if (knowledge.memoryShortterm) {
|
|
9066
|
+
lines.push("### Shortterm (1-2 sessions)");
|
|
9067
|
+
lines.push(knowledge.memoryShortterm);
|
|
9068
|
+
lines.push("");
|
|
9069
|
+
}
|
|
9070
|
+
if (knowledge.memoryMidterm) {
|
|
9071
|
+
lines.push("### Midterm (multi-generation)");
|
|
9072
|
+
lines.push(knowledge.memoryMidterm);
|
|
9073
|
+
lines.push("");
|
|
9074
|
+
}
|
|
9075
|
+
}
|
|
9076
|
+
lines.push("## Verification Tasks");
|
|
9077
|
+
lines.push("");
|
|
9078
|
+
if (opts.stage === "validation") {
|
|
9079
|
+
lines.push("1. Run `npm run typecheck` (or the project's typecheck command) and record the result.");
|
|
9080
|
+
lines.push("2. Run `npm run build` (or the project's build command) and record the result.");
|
|
9081
|
+
lines.push("3. Run the full test suite (unit/e2e/scenario as defined by the project) and record each.");
|
|
9082
|
+
lines.push("4. Read 02-planning.md and verify each completion criterion against the implementation + validation artifacts.");
|
|
9083
|
+
lines.push("5. Read `git diff` against the parent commit and check for genome convention compliance.");
|
|
9084
|
+
lines.push('6. Check 04-validation.md for sycophancy red flags ("it will probably pass", "it passed before").');
|
|
9085
|
+
lines.push("");
|
|
9086
|
+
} else {
|
|
9087
|
+
lines.push("1. Read all completed artifacts and validate goal achievement.");
|
|
9088
|
+
lines.push("2. Cross-reference the implementation against genome conventions (application.md, evolution.md).");
|
|
9089
|
+
lines.push("3. Run the test suite and confirm no regression.");
|
|
9090
|
+
lines.push("4. Compare this generation's contribution against vision/goals.md and recent lineage.");
|
|
9091
|
+
lines.push("5. Assess each of the 6 fitness dimensions qualitatively (no scores).");
|
|
9092
|
+
lines.push("");
|
|
9093
|
+
}
|
|
9094
|
+
lines.push("## Output Format");
|
|
9095
|
+
lines.push("");
|
|
9096
|
+
lines.push("Apply the escalation matrix from your agent definition:");
|
|
9097
|
+
lines.push("");
|
|
9098
|
+
lines.push("| Confidence | Impact | Action |");
|
|
9099
|
+
lines.push("| --- | --- | --- |");
|
|
9100
|
+
lines.push("| High | Low | Direct judgment |");
|
|
9101
|
+
lines.push("| High | High | Escalate with judgment |");
|
|
9102
|
+
lines.push("| Low | Any | Escalate without judgment (facts only) |");
|
|
9103
|
+
lines.push("");
|
|
9104
|
+
lines.push("Structure your reply as:");
|
|
9105
|
+
lines.push("- **Summary** (1-2 sentences)");
|
|
9106
|
+
lines.push("- **Verification results** (typecheck / build / tests / criteria)");
|
|
9107
|
+
lines.push("- **Concerns** (if any — call out the severity)");
|
|
9108
|
+
lines.push("- **Recommendation** (per the matrix)");
|
|
9109
|
+
lines.push("");
|
|
9110
|
+
lines.push("## HARD-GATE — Evaluator Constraints");
|
|
9111
|
+
lines.push("");
|
|
9112
|
+
lines.push("- You MUST NOT write, edit, or create any source files. Use Read/Grep/Glob/Bash only.");
|
|
9113
|
+
lines.push("- You MUST NOT run git commands that modify state (`git commit`, `git push`, `git checkout`, `git reset`).");
|
|
9114
|
+
lines.push("- You MUST NOT run `reap run` commands — the lifecycle is the builder's responsibility.");
|
|
9115
|
+
lines.push("- You MUST NOT produce numerical scores, ratings, or percentages (Goodhart's Law).");
|
|
9116
|
+
lines.push("- Your verdict is an **advisor recommendation**, not a binding judgment. The builder owns the lifecycle verdict; the human owns final fitness.");
|
|
9117
|
+
lines.push("");
|
|
9118
|
+
lines.push("## If You Cannot Proceed");
|
|
9119
|
+
lines.push("");
|
|
9120
|
+
lines.push("If you cannot complete verification (missing tools, broken state, ambiguous artifacts), " + "report the obstacle in your reply with enough context for the human to act. Do not block " + "the builder's lifecycle — the builder will continue validation if you cannot.");
|
|
9121
|
+
lines.push("");
|
|
8982
9122
|
lines.push("## Project");
|
|
8983
9123
|
lines.push(`Path: ${paths.root}`);
|
|
8984
9124
|
return lines.join(`
|
|
8985
9125
|
`);
|
|
8986
9126
|
}
|
|
8987
9127
|
|
|
9128
|
+
// src/cli/commands/load-context.ts
|
|
9129
|
+
var import_yaml = __toESM(require_dist(), 1);
|
|
9130
|
+
import { join as join2 } from "path";
|
|
9131
|
+
init_fs();
|
|
9132
|
+
async function buildKnowledgeContext(cwd) {
|
|
9133
|
+
const configPath = join2(cwd, ".reap", "config.yml");
|
|
9134
|
+
if (!await fileExists(configPath)) {
|
|
9135
|
+
return null;
|
|
9136
|
+
}
|
|
9137
|
+
const paths = createPaths(cwd);
|
|
9138
|
+
const [configContent, currentContent] = await Promise.all([
|
|
9139
|
+
readTextFile(paths.config),
|
|
9140
|
+
readTextFile(paths.current)
|
|
9141
|
+
]);
|
|
9142
|
+
let config = null;
|
|
9143
|
+
if (configContent) {
|
|
9144
|
+
try {
|
|
9145
|
+
config = import_yaml.default.parse(configContent);
|
|
9146
|
+
} catch {}
|
|
9147
|
+
}
|
|
9148
|
+
let state = null;
|
|
9149
|
+
if (currentContent) {
|
|
9150
|
+
try {
|
|
9151
|
+
state = import_yaml.default.parse(currentContent);
|
|
9152
|
+
} catch {}
|
|
9153
|
+
}
|
|
9154
|
+
const sections = [];
|
|
9155
|
+
sections.push("# Current State");
|
|
9156
|
+
if (state) {
|
|
9157
|
+
const stateLines = [];
|
|
9158
|
+
stateLines.push(`- Generation: ${state.id}`);
|
|
9159
|
+
stateLines.push(`- Type: ${state.type}`);
|
|
9160
|
+
stateLines.push(`- Goal: ${state.goal}`);
|
|
9161
|
+
stateLines.push(`- Stage: ${state.stage}`);
|
|
9162
|
+
if (state.phase)
|
|
9163
|
+
stateLines.push(`- Phase: ${state.phase}`);
|
|
9164
|
+
if (state.type === "merge" && state.parents?.length) {
|
|
9165
|
+
stateLines.push(`- Parents: ${state.parents.join(", ")}`);
|
|
9166
|
+
}
|
|
9167
|
+
sections.push(stateLines.join(`
|
|
9168
|
+
`));
|
|
9169
|
+
} else {
|
|
9170
|
+
sections.push("No active generation.");
|
|
9171
|
+
}
|
|
9172
|
+
if (config) {
|
|
9173
|
+
const strictStage = state ? state.stage : "none";
|
|
9174
|
+
const strictSection = buildStrictSection(config.strictEdit ?? false, config.strictMerge ?? false, strictStage, state?.type);
|
|
9175
|
+
if (strictSection) {
|
|
9176
|
+
sections.push(strictSection.trimStart());
|
|
9177
|
+
}
|
|
9178
|
+
}
|
|
9179
|
+
if (config?.language) {
|
|
9180
|
+
sections.push(`# Language
|
|
9181
|
+
Always respond in ${config.language}. Use ${config.language} for all explanations, comments, and communications. Technical terms and code identifiers remain in their original form.`);
|
|
9182
|
+
}
|
|
9183
|
+
if (config?.daemon === true) {
|
|
9184
|
+
sections.push(buildDaemonStaticSection());
|
|
9185
|
+
}
|
|
9186
|
+
return sections.join(`
|
|
9187
|
+
|
|
9188
|
+
---
|
|
9189
|
+
|
|
9190
|
+
`);
|
|
9191
|
+
}
|
|
9192
|
+
function buildDaemonStaticSection() {
|
|
9193
|
+
return [
|
|
9194
|
+
"# Code Intelligence (Daemon)",
|
|
9195
|
+
"",
|
|
9196
|
+
"- Enabled: true",
|
|
9197
|
+
"- Base URL: http://127.0.0.1:17224",
|
|
9198
|
+
"- See `~/.reap/reap-guide.md` § Code Intelligence (Daemon) for query examples and protocol."
|
|
9199
|
+
].join(`
|
|
9200
|
+
`);
|
|
9201
|
+
}
|
|
9202
|
+
async function execute() {
|
|
9203
|
+
const context = await buildKnowledgeContext(process.cwd());
|
|
9204
|
+
if (!context) {
|
|
9205
|
+
process.exit(0);
|
|
9206
|
+
}
|
|
9207
|
+
const output = {
|
|
9208
|
+
hookSpecificOutput: {
|
|
9209
|
+
hookEventName: "SessionStart",
|
|
9210
|
+
additionalContext: context
|
|
9211
|
+
}
|
|
9212
|
+
};
|
|
9213
|
+
process.stdout.write(JSON.stringify(output) + `
|
|
9214
|
+
`);
|
|
9215
|
+
process.exit(0);
|
|
9216
|
+
}
|
|
9217
|
+
|
|
8988
9218
|
// src/core/dump-state-sync.ts
|
|
8989
9219
|
var DUMP_COMMANDS = new Set([
|
|
8990
9220
|
"start",
|
|
@@ -9007,7 +9237,7 @@ var DUMP_COMMANDS = new Set([
|
|
|
9007
9237
|
"init"
|
|
9008
9238
|
]);
|
|
9009
9239
|
function buildKnowledgeContextSync(cwd) {
|
|
9010
|
-
const configPath =
|
|
9240
|
+
const configPath = join3(cwd, ".reap", "config.yml");
|
|
9011
9241
|
if (!existsSync(configPath))
|
|
9012
9242
|
return null;
|
|
9013
9243
|
const paths = createPaths(cwd);
|
|
@@ -9022,13 +9252,13 @@ function buildKnowledgeContextSync(cwd) {
|
|
|
9022
9252
|
let config = null;
|
|
9023
9253
|
if (configContent) {
|
|
9024
9254
|
try {
|
|
9025
|
-
config =
|
|
9255
|
+
config = import_yaml2.default.parse(configContent);
|
|
9026
9256
|
} catch {}
|
|
9027
9257
|
}
|
|
9028
9258
|
let state = null;
|
|
9029
9259
|
if (currentContent) {
|
|
9030
9260
|
try {
|
|
9031
|
-
state =
|
|
9261
|
+
state = import_yaml2.default.parse(currentContent);
|
|
9032
9262
|
} catch {}
|
|
9033
9263
|
}
|
|
9034
9264
|
const sections = [];
|
|
@@ -9060,6 +9290,9 @@ function buildKnowledgeContextSync(cwd) {
|
|
|
9060
9290
|
sections.push(`# Language
|
|
9061
9291
|
Always respond in ${config.language}. Use ${config.language} for all explanations, comments, and communications. Technical terms and code identifiers remain in their original form.`);
|
|
9062
9292
|
}
|
|
9293
|
+
if (config?.daemon === true) {
|
|
9294
|
+
sections.push(buildDaemonStaticSection());
|
|
9295
|
+
}
|
|
9063
9296
|
return sections.join(`
|
|
9064
9297
|
|
|
9065
9298
|
---
|
|
@@ -9187,7 +9420,7 @@ ${claudeMdSection}
|
|
|
9187
9420
|
6. If confirmed: \`reap run start --type embryo --goal "<goal>"\`
|
|
9188
9421
|
`;
|
|
9189
9422
|
}
|
|
9190
|
-
async function
|
|
9423
|
+
async function execute2(paths, projectName) {
|
|
9191
9424
|
const config = await initCommon(paths, projectName);
|
|
9192
9425
|
await writeTextFile(paths.application, DEFAULT_APPLICATION);
|
|
9193
9426
|
await writeTextFile(paths.environmentSummary, `# ${config.project} Environment
|
|
@@ -9217,10 +9450,10 @@ init_common();
|
|
|
9217
9450
|
// src/core/scanner.ts
|
|
9218
9451
|
init_fs();
|
|
9219
9452
|
import { readdir as readdir3, stat as stat2 } from "fs/promises";
|
|
9220
|
-
import { join as
|
|
9453
|
+
import { join as join6, relative } from "path";
|
|
9221
9454
|
async function scanCodebase(root) {
|
|
9222
9455
|
let packageJson = null;
|
|
9223
|
-
const pkgContent = await readTextFile(
|
|
9456
|
+
const pkgContent = await readTextFile(join6(root, "package.json"));
|
|
9224
9457
|
if (pkgContent) {
|
|
9225
9458
|
try {
|
|
9226
9459
|
packageJson = JSON.parse(pkgContent);
|
|
@@ -9229,7 +9462,7 @@ async function scanCodebase(root) {
|
|
|
9229
9462
|
const deps = Object.keys(packageJson?.dependencies ?? {});
|
|
9230
9463
|
const devDeps = Object.keys(packageJson?.devDependencies ?? {});
|
|
9231
9464
|
const scripts = packageJson?.scripts ?? {};
|
|
9232
|
-
const hasTypeScript = !!await readTextFile(
|
|
9465
|
+
const hasTypeScript = !!await readTextFile(join6(root, "tsconfig.json")) || devDeps.includes("typescript");
|
|
9233
9466
|
const testFrameworks = ["jest", "vitest", "mocha", "@jest/core", "bun:test"];
|
|
9234
9467
|
const testFramework = [...deps, ...devDeps].find((d) => testFrameworks.includes(d)) ?? null;
|
|
9235
9468
|
const hasTests = !!testFramework || scripts.test !== undefined;
|
|
@@ -9237,7 +9470,7 @@ async function scanCodebase(root) {
|
|
|
9237
9470
|
const buildTool = [...deps, ...devDeps].find((d) => buildTools.includes(d)) ?? null;
|
|
9238
9471
|
const tree = await buildTree(root, root, 2);
|
|
9239
9472
|
let readmeExcerpt = null;
|
|
9240
|
-
const readme = await readTextFile(
|
|
9473
|
+
const readme = await readTextFile(join6(root, "README.md"));
|
|
9241
9474
|
if (readme) {
|
|
9242
9475
|
readmeExcerpt = readme.slice(0, 500);
|
|
9243
9476
|
}
|
|
@@ -9271,7 +9504,7 @@ async function buildTree(root, dir, depth) {
|
|
|
9271
9504
|
continue;
|
|
9272
9505
|
if (SKIP_DIRS.has(entry))
|
|
9273
9506
|
continue;
|
|
9274
|
-
const fullPath =
|
|
9507
|
+
const fullPath = join6(dir, entry);
|
|
9275
9508
|
const relPath = relative(root, fullPath);
|
|
9276
9509
|
const s = await stat2(fullPath).catch(() => null);
|
|
9277
9510
|
if (!s)
|
|
@@ -9493,7 +9726,7 @@ ${claudeMdSection}
|
|
|
9493
9726
|
7. If confirmed: \`reap run start --type embryo --goal "<goal>"\`
|
|
9494
9727
|
`;
|
|
9495
9728
|
}
|
|
9496
|
-
async function
|
|
9729
|
+
async function execute3(paths, projectName) {
|
|
9497
9730
|
const scan = await scanCodebase(paths.root);
|
|
9498
9731
|
const name = projectName ?? scan.projectName;
|
|
9499
9732
|
const config = await initCommon(paths, name);
|
|
@@ -9565,14 +9798,14 @@ async function execute2(paths, projectName) {
|
|
|
9565
9798
|
|
|
9566
9799
|
// src/cli/commands/init/repair.ts
|
|
9567
9800
|
init_fs();
|
|
9568
|
-
var
|
|
9801
|
+
var import_yaml5 = __toESM(require_dist(), 1);
|
|
9569
9802
|
init_common();
|
|
9570
|
-
async function
|
|
9803
|
+
async function execute4(paths) {
|
|
9571
9804
|
const configContent = await readTextFile(paths.config);
|
|
9572
9805
|
if (!configContent) {
|
|
9573
9806
|
emitError("init", ".reap/config.yml not found. This is not a reap project. Run 'reap init' first.");
|
|
9574
9807
|
}
|
|
9575
|
-
const config =
|
|
9808
|
+
const config = import_yaml5.default.parse(configContent);
|
|
9576
9809
|
const projectName = config.project ?? "my-project";
|
|
9577
9810
|
const claudeMdAction = await ensureClaudeMd(paths.root, projectName);
|
|
9578
9811
|
const repaired = [];
|
|
@@ -9598,9 +9831,9 @@ async function execute3(paths) {
|
|
|
9598
9831
|
|
|
9599
9832
|
// src/cli/commands/migrate.ts
|
|
9600
9833
|
init_fs();
|
|
9601
|
-
var
|
|
9834
|
+
var import_yaml6 = __toESM(require_dist(), 1);
|
|
9602
9835
|
import { readdir as readdir4, cp, rename, rm as rm2 } from "fs/promises";
|
|
9603
|
-
import { join as
|
|
9836
|
+
import { join as join7, dirname as dirname4 } from "path";
|
|
9604
9837
|
import { execSync as execSync2 } from "child_process";
|
|
9605
9838
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9606
9839
|
import { homedir as homedir2 } from "os";
|
|
@@ -9797,7 +10030,7 @@ init_integrity();
|
|
|
9797
10030
|
init_common();
|
|
9798
10031
|
function distPath2(...segments) {
|
|
9799
10032
|
const __dirname2 = dirname4(fileURLToPath2(import.meta.url));
|
|
9800
|
-
return
|
|
10033
|
+
return join7(__dirname2, "..", "templates", ...segments);
|
|
9801
10034
|
}
|
|
9802
10035
|
function isGitClean(cwd) {
|
|
9803
10036
|
if (!isGitRepo(cwd))
|
|
@@ -9818,14 +10051,14 @@ async function loadMigrationState(paths) {
|
|
|
9818
10051
|
if (!content)
|
|
9819
10052
|
return null;
|
|
9820
10053
|
try {
|
|
9821
|
-
return
|
|
10054
|
+
return import_yaml6.default.parse(content);
|
|
9822
10055
|
} catch {
|
|
9823
10056
|
return null;
|
|
9824
10057
|
}
|
|
9825
10058
|
}
|
|
9826
10059
|
async function saveMigrationState(paths, state) {
|
|
9827
10060
|
state.updatedAt = new Date().toISOString();
|
|
9828
|
-
await writeTextFile(paths.migrationState,
|
|
10061
|
+
await writeTextFile(paths.migrationState, import_yaml6.default.stringify(state));
|
|
9829
10062
|
}
|
|
9830
10063
|
async function clearMigrationState(paths) {
|
|
9831
10064
|
if (await fileExists(paths.migrationState)) {
|
|
@@ -9873,7 +10106,7 @@ function mapHookFilename(filename) {
|
|
|
9873
10106
|
}
|
|
9874
10107
|
async function scanV15Structure(paths) {
|
|
9875
10108
|
const genomeFiles = [];
|
|
9876
|
-
const genomeDir =
|
|
10109
|
+
const genomeDir = join7(paths.reap, "v15", "genome");
|
|
9877
10110
|
const currentGenomeDir = paths.genome;
|
|
9878
10111
|
try {
|
|
9879
10112
|
const entries = await readdir4(currentGenomeDir);
|
|
@@ -9883,7 +10116,7 @@ async function scanV15Structure(paths) {
|
|
|
9883
10116
|
}
|
|
9884
10117
|
} catch {}
|
|
9885
10118
|
const domainFiles = [];
|
|
9886
|
-
const domainDir =
|
|
10119
|
+
const domainDir = join7(currentGenomeDir, "domain");
|
|
9887
10120
|
try {
|
|
9888
10121
|
const entries = await readdir4(domainDir);
|
|
9889
10122
|
for (const e of entries) {
|
|
@@ -9953,14 +10186,14 @@ async function executePreCheck(paths) {
|
|
|
9953
10186
|
if (currentContent && currentContent.trim()) {
|
|
9954
10187
|
emitError("migrate", "Active generation exists. Run '/reap.abort' first, then retry migration.");
|
|
9955
10188
|
}
|
|
9956
|
-
if (await fileExists(
|
|
10189
|
+
if (await fileExists(join7(paths.reap, "v15"))) {
|
|
9957
10190
|
emitError("migrate", "Previous migration backup (.reap/v15/) already exists. Remove it first if you want to re-migrate.");
|
|
9958
10191
|
}
|
|
9959
10192
|
const configContent = await readTextFile(paths.config);
|
|
9960
10193
|
let config = {};
|
|
9961
10194
|
if (configContent) {
|
|
9962
10195
|
try {
|
|
9963
|
-
config =
|
|
10196
|
+
config = import_yaml6.default.parse(configContent) ?? {};
|
|
9964
10197
|
} catch {
|
|
9965
10198
|
emitError("migrate", "config.yml is not valid YAML.");
|
|
9966
10199
|
}
|
|
@@ -10045,7 +10278,7 @@ async function executeMain(paths) {
|
|
|
10045
10278
|
let state = await loadMigrationState(paths);
|
|
10046
10279
|
if (!state) {
|
|
10047
10280
|
if (!await detectV15(paths)) {
|
|
10048
|
-
if (!await fileExists(
|
|
10281
|
+
if (!await fileExists(join7(paths.reap, "v15"))) {
|
|
10049
10282
|
emitError("migrate", "v0.15 structure not found. Cannot proceed.");
|
|
10050
10283
|
}
|
|
10051
10284
|
}
|
|
@@ -10053,7 +10286,7 @@ async function executeMain(paths) {
|
|
|
10053
10286
|
await saveMigrationState(paths, state);
|
|
10054
10287
|
}
|
|
10055
10288
|
const done = new Set(state.completedSteps);
|
|
10056
|
-
const v15Dir =
|
|
10289
|
+
const v15Dir = join7(paths.reap, "v15");
|
|
10057
10290
|
async function step(name, fn) {
|
|
10058
10291
|
if (done.has(name))
|
|
10059
10292
|
return;
|
|
@@ -10064,12 +10297,12 @@ async function executeMain(paths) {
|
|
|
10064
10297
|
await step("backup", async () => {
|
|
10065
10298
|
await ensureDir(v15Dir);
|
|
10066
10299
|
const backupItems = [
|
|
10067
|
-
{ src: paths.genome, dest:
|
|
10068
|
-
{ src: paths.environment, dest:
|
|
10069
|
-
{ src: paths.life, dest:
|
|
10070
|
-
{ src: paths.lineage, dest:
|
|
10071
|
-
{ src: paths.hooks, dest:
|
|
10072
|
-
{ src: paths.config, dest:
|
|
10300
|
+
{ src: paths.genome, dest: join7(v15Dir, "genome") },
|
|
10301
|
+
{ src: paths.environment, dest: join7(v15Dir, "environment") },
|
|
10302
|
+
{ src: paths.life, dest: join7(v15Dir, "life") },
|
|
10303
|
+
{ src: paths.lineage, dest: join7(v15Dir, "lineage") },
|
|
10304
|
+
{ src: paths.hooks, dest: join7(v15Dir, "hooks") },
|
|
10305
|
+
{ src: paths.config, dest: join7(v15Dir, "config.yml") }
|
|
10073
10306
|
];
|
|
10074
10307
|
for (const item of backupItems) {
|
|
10075
10308
|
if (await fileExists(item.src)) {
|
|
@@ -10079,7 +10312,7 @@ async function executeMain(paths) {
|
|
|
10079
10312
|
});
|
|
10080
10313
|
await step("create-dirs", async () => {
|
|
10081
10314
|
await ensureDir(paths.genome);
|
|
10082
|
-
await ensureDir(
|
|
10315
|
+
await ensureDir(join7(paths.environment, "domain"));
|
|
10083
10316
|
await ensureDir(paths.environmentResources);
|
|
10084
10317
|
await ensureDir(paths.environmentDocs);
|
|
10085
10318
|
await ensureDir(paths.life);
|
|
@@ -10087,7 +10320,7 @@ async function executeMain(paths) {
|
|
|
10087
10320
|
await ensureDir(paths.lineage);
|
|
10088
10321
|
await ensureDir(paths.vision);
|
|
10089
10322
|
await ensureDir(paths.visionDesign);
|
|
10090
|
-
await ensureDir(
|
|
10323
|
+
await ensureDir(join7(paths.vision, "memory"));
|
|
10091
10324
|
await ensureDir(paths.hooks);
|
|
10092
10325
|
});
|
|
10093
10326
|
let v16Config = {
|
|
@@ -10101,10 +10334,10 @@ async function executeMain(paths) {
|
|
|
10101
10334
|
autoIssueReport: true
|
|
10102
10335
|
};
|
|
10103
10336
|
await step("config-migrate", async () => {
|
|
10104
|
-
const v15ConfigContent = await readTextFile(
|
|
10337
|
+
const v15ConfigContent = await readTextFile(join7(v15Dir, "config.yml"));
|
|
10105
10338
|
let v15Config = {};
|
|
10106
10339
|
if (v15ConfigContent) {
|
|
10107
|
-
v15Config =
|
|
10340
|
+
v15Config = import_yaml6.default.parse(v15ConfigContent) ?? {};
|
|
10108
10341
|
}
|
|
10109
10342
|
const wasStrict = v15Config.strict ?? false;
|
|
10110
10343
|
v16Config = {
|
|
@@ -10117,55 +10350,55 @@ async function executeMain(paths) {
|
|
|
10117
10350
|
autoUpdate: v15Config.autoUpdate ?? true,
|
|
10118
10351
|
autoIssueReport: v15Config.autoIssueReport ?? true
|
|
10119
10352
|
};
|
|
10120
|
-
await writeTextFile(paths.config,
|
|
10353
|
+
await writeTextFile(paths.config, import_yaml6.default.stringify(v16Config));
|
|
10121
10354
|
});
|
|
10122
10355
|
if (done.has("config-migrate")) {
|
|
10123
10356
|
const existingConfig = await readTextFile(paths.config);
|
|
10124
10357
|
if (existingConfig) {
|
|
10125
|
-
const parsed =
|
|
10358
|
+
const parsed = import_yaml6.default.parse(existingConfig) ?? {};
|
|
10126
10359
|
v16Config = { ...v16Config, ...parsed };
|
|
10127
10360
|
}
|
|
10128
10361
|
}
|
|
10129
|
-
const principles = await readTextFile(
|
|
10130
|
-
const conventions = await readTextFile(
|
|
10131
|
-
const constraints = await readTextFile(
|
|
10132
|
-
const sourceMap = await readTextFile(
|
|
10362
|
+
const principles = await readTextFile(join7(v15Dir, "genome", "principles.md")) ?? "";
|
|
10363
|
+
const conventions = await readTextFile(join7(v15Dir, "genome", "conventions.md")) ?? "";
|
|
10364
|
+
const constraints = await readTextFile(join7(v15Dir, "genome", "constraints.md")) ?? "";
|
|
10365
|
+
const sourceMap = await readTextFile(join7(v15Dir, "genome", "source-map.md")) ?? "";
|
|
10133
10366
|
const evolutionTemplate = await readTextFile(distPath2("evolution.md")) ?? "";
|
|
10134
10367
|
const domainFiles = [];
|
|
10135
|
-
const v15DomainDir =
|
|
10368
|
+
const v15DomainDir = join7(v15Dir, "genome", "domain");
|
|
10136
10369
|
try {
|
|
10137
10370
|
const entries = await readdir4(v15DomainDir);
|
|
10138
10371
|
domainFiles.push(...entries.filter((e) => e.endsWith(".md")));
|
|
10139
10372
|
} catch {}
|
|
10140
10373
|
await step("environment-copy", async () => {
|
|
10141
|
-
const v15EnvSummary =
|
|
10374
|
+
const v15EnvSummary = join7(v15Dir, "environment", "summary.md");
|
|
10142
10375
|
if (await fileExists(v15EnvSummary)) {
|
|
10143
10376
|
await cp(v15EnvSummary, paths.environmentSummary);
|
|
10144
10377
|
}
|
|
10145
|
-
const v15EnvDomain =
|
|
10378
|
+
const v15EnvDomain = join7(v15Dir, "environment", "domain");
|
|
10146
10379
|
if (await fileExists(v15EnvDomain)) {
|
|
10147
10380
|
try {
|
|
10148
10381
|
const entries = await readdir4(v15EnvDomain);
|
|
10149
10382
|
for (const e of entries) {
|
|
10150
|
-
await cp(
|
|
10383
|
+
await cp(join7(v15EnvDomain, e), join7(paths.environmentDomain, e), { recursive: true });
|
|
10151
10384
|
}
|
|
10152
10385
|
} catch {}
|
|
10153
10386
|
}
|
|
10154
|
-
const v15EnvResources =
|
|
10387
|
+
const v15EnvResources = join7(v15Dir, "environment", "resources");
|
|
10155
10388
|
if (await fileExists(v15EnvResources)) {
|
|
10156
10389
|
try {
|
|
10157
10390
|
const entries = await readdir4(v15EnvResources);
|
|
10158
10391
|
for (const e of entries) {
|
|
10159
|
-
await cp(
|
|
10392
|
+
await cp(join7(v15EnvResources, e), join7(paths.environmentResources, e), { recursive: true });
|
|
10160
10393
|
}
|
|
10161
10394
|
} catch {}
|
|
10162
10395
|
}
|
|
10163
|
-
const v15EnvDocs =
|
|
10396
|
+
const v15EnvDocs = join7(v15Dir, "environment", "docs");
|
|
10164
10397
|
if (await fileExists(v15EnvDocs)) {
|
|
10165
10398
|
try {
|
|
10166
10399
|
const entries = await readdir4(v15EnvDocs);
|
|
10167
10400
|
for (const e of entries) {
|
|
10168
|
-
await cp(
|
|
10401
|
+
await cp(join7(v15EnvDocs, e), join7(paths.environmentDocs, e), { recursive: true });
|
|
10169
10402
|
}
|
|
10170
10403
|
} catch {}
|
|
10171
10404
|
}
|
|
@@ -10174,8 +10407,8 @@ async function executeMain(paths) {
|
|
|
10174
10407
|
}
|
|
10175
10408
|
if (domainFiles.length > 0) {
|
|
10176
10409
|
for (const f of domainFiles) {
|
|
10177
|
-
const src =
|
|
10178
|
-
const dest =
|
|
10410
|
+
const src = join7(v15DomainDir, f);
|
|
10411
|
+
const dest = join7(paths.environmentDomain, f);
|
|
10179
10412
|
if (await fileExists(src)) {
|
|
10180
10413
|
await cp(src, dest);
|
|
10181
10414
|
}
|
|
@@ -10183,23 +10416,23 @@ async function executeMain(paths) {
|
|
|
10183
10416
|
}
|
|
10184
10417
|
});
|
|
10185
10418
|
await step("lineage-copy", async () => {
|
|
10186
|
-
const v15Lineage =
|
|
10419
|
+
const v15Lineage = join7(v15Dir, "lineage");
|
|
10187
10420
|
if (await fileExists(v15Lineage)) {
|
|
10188
10421
|
try {
|
|
10189
10422
|
const entries = await readdir4(v15Lineage);
|
|
10190
10423
|
for (const e of entries) {
|
|
10191
|
-
await cp(
|
|
10424
|
+
await cp(join7(v15Lineage, e), join7(paths.lineage, e), { recursive: true });
|
|
10192
10425
|
}
|
|
10193
10426
|
} catch {}
|
|
10194
10427
|
}
|
|
10195
10428
|
});
|
|
10196
10429
|
await step("backlog-copy", async () => {
|
|
10197
|
-
const v15Backlog =
|
|
10430
|
+
const v15Backlog = join7(v15Dir, "life", "backlog");
|
|
10198
10431
|
if (await fileExists(v15Backlog)) {
|
|
10199
10432
|
try {
|
|
10200
10433
|
const entries = await readdir4(v15Backlog);
|
|
10201
10434
|
for (const e of entries) {
|
|
10202
|
-
await cp(
|
|
10435
|
+
await cp(join7(v15Backlog, e), join7(paths.backlog, e), { recursive: true });
|
|
10203
10436
|
}
|
|
10204
10437
|
} catch {}
|
|
10205
10438
|
}
|
|
@@ -10207,20 +10440,20 @@ async function executeMain(paths) {
|
|
|
10207
10440
|
const hooksMapped = [];
|
|
10208
10441
|
const hooksUnmapped = [];
|
|
10209
10442
|
await step("hooks-map", async () => {
|
|
10210
|
-
const v15Hooks =
|
|
10443
|
+
const v15Hooks = join7(v15Dir, "hooks");
|
|
10211
10444
|
if (await fileExists(v15Hooks)) {
|
|
10212
10445
|
try {
|
|
10213
10446
|
const entries = await readdir4(v15Hooks);
|
|
10214
10447
|
for (const e of entries) {
|
|
10215
10448
|
if (e === "conditions") {
|
|
10216
|
-
const condSrc =
|
|
10217
|
-
const condDest =
|
|
10449
|
+
const condSrc = join7(v15Hooks, "conditions");
|
|
10450
|
+
const condDest = join7(paths.hooks, "conditions");
|
|
10218
10451
|
await cp(condSrc, condDest, { recursive: true });
|
|
10219
10452
|
continue;
|
|
10220
10453
|
}
|
|
10221
10454
|
const mapping = mapHookFilename(e);
|
|
10222
10455
|
if (mapping) {
|
|
10223
|
-
await cp(
|
|
10456
|
+
await cp(join7(v15Hooks, e), join7(paths.hooks, mapping.newName));
|
|
10224
10457
|
if (mapping.newName !== e) {
|
|
10225
10458
|
hooksMapped.push(`${e} → ${mapping.newName}`);
|
|
10226
10459
|
}
|
|
@@ -10228,7 +10461,7 @@ async function executeMain(paths) {
|
|
|
10228
10461
|
hooksUnmapped.push(e);
|
|
10229
10462
|
}
|
|
10230
10463
|
} else {
|
|
10231
|
-
await cp(
|
|
10464
|
+
await cp(join7(v15Hooks, e), join7(paths.hooks, e));
|
|
10232
10465
|
}
|
|
10233
10466
|
}
|
|
10234
10467
|
} catch {}
|
|
@@ -10248,20 +10481,20 @@ async function executeMain(paths) {
|
|
|
10248
10481
|
## Goal Items
|
|
10249
10482
|
<!-- Checklist of major milestones -->
|
|
10250
10483
|
`;
|
|
10251
|
-
await writeTextFile(
|
|
10252
|
-
await writeTextFile(
|
|
10484
|
+
await writeTextFile(join7(paths.vision, "goals.md"), goalsContent);
|
|
10485
|
+
await writeTextFile(join7(paths.vision, "memory", "longterm.md"), `# Longterm Memory
|
|
10253
10486
|
`);
|
|
10254
|
-
await writeTextFile(
|
|
10487
|
+
await writeTextFile(join7(paths.vision, "memory", "midterm.md"), `# Midterm Memory
|
|
10255
10488
|
`);
|
|
10256
|
-
await writeTextFile(
|
|
10489
|
+
await writeTextFile(join7(paths.vision, "memory", "shortterm.md"), `# Shortterm Memory
|
|
10257
10490
|
`);
|
|
10258
10491
|
});
|
|
10259
10492
|
await step("reap-guide", async () => {
|
|
10260
10493
|
const guide = await readTextFile(distPath2("reap-guide.md"));
|
|
10261
10494
|
if (guide) {
|
|
10262
|
-
const reapHome =
|
|
10495
|
+
const reapHome = join7(homedir2(), ".reap");
|
|
10263
10496
|
await ensureDir(reapHome);
|
|
10264
|
-
await writeTextFile(
|
|
10497
|
+
await writeTextFile(join7(reapHome, "reap-guide.md"), guide);
|
|
10265
10498
|
}
|
|
10266
10499
|
});
|
|
10267
10500
|
await step("claude-md", async () => {
|
|
@@ -10457,7 +10690,7 @@ async function executeComplete(paths) {
|
|
|
10457
10690
|
message: `Migration complete. Backup preserved at .reap/v15/. Run 'reap status' to verify.`
|
|
10458
10691
|
});
|
|
10459
10692
|
}
|
|
10460
|
-
async function
|
|
10693
|
+
async function execute5(paths, phase) {
|
|
10461
10694
|
switch (phase) {
|
|
10462
10695
|
case undefined:
|
|
10463
10696
|
case "confirm":
|
|
@@ -10501,12 +10734,12 @@ var PROJECT_FILES = [
|
|
|
10501
10734
|
var SOURCE_GLOBS = [".ts", ".js", ".py", ".rs", ".go", ".java", ".rb", ".php", ".swift", ".kt"];
|
|
10502
10735
|
async function detectMode(root) {
|
|
10503
10736
|
for (const file of PROJECT_FILES) {
|
|
10504
|
-
if (await fileExists(
|
|
10737
|
+
if (await fileExists(join8(root, file))) {
|
|
10505
10738
|
return "adoption";
|
|
10506
10739
|
}
|
|
10507
10740
|
}
|
|
10508
10741
|
for (const dir of SOURCE_DIRS) {
|
|
10509
|
-
if (await fileExists(
|
|
10742
|
+
if (await fileExists(join8(root, dir))) {
|
|
10510
10743
|
return "adoption";
|
|
10511
10744
|
}
|
|
10512
10745
|
}
|
|
@@ -10526,18 +10759,18 @@ async function detectMode(root) {
|
|
|
10526
10759
|
}
|
|
10527
10760
|
return "greenfield";
|
|
10528
10761
|
}
|
|
10529
|
-
async function
|
|
10762
|
+
async function execute6(projectName, mode, repair, migrate, phase) {
|
|
10530
10763
|
const root = process.cwd();
|
|
10531
10764
|
const paths = createPaths(root);
|
|
10532
10765
|
if (migrate) {
|
|
10533
|
-
await
|
|
10766
|
+
await execute5(paths, phase);
|
|
10534
10767
|
return;
|
|
10535
10768
|
}
|
|
10536
10769
|
if (repair) {
|
|
10537
10770
|
if (!await fileExists(paths.config)) {
|
|
10538
10771
|
emitError("init", ".reap/ not found. This is not a reap project. Run 'reap init' first.");
|
|
10539
10772
|
}
|
|
10540
|
-
await
|
|
10773
|
+
await execute4(paths);
|
|
10541
10774
|
return;
|
|
10542
10775
|
}
|
|
10543
10776
|
if (await fileExists(paths.config)) {
|
|
@@ -10545,18 +10778,18 @@ async function execute5(projectName, mode, repair, migrate, phase) {
|
|
|
10545
10778
|
}
|
|
10546
10779
|
const resolvedMode = mode ?? await detectMode(root);
|
|
10547
10780
|
if (resolvedMode === "adoption") {
|
|
10548
|
-
await
|
|
10781
|
+
await execute3(paths, projectName);
|
|
10549
10782
|
} else {
|
|
10550
|
-
await
|
|
10783
|
+
await execute2(paths, projectName ?? "my-project");
|
|
10551
10784
|
}
|
|
10552
10785
|
}
|
|
10553
10786
|
|
|
10554
10787
|
// src/cli/commands/status.ts
|
|
10555
|
-
var
|
|
10788
|
+
var import_yaml7 = __toESM(require_dist(), 1);
|
|
10556
10789
|
import { readdir as readdir6 } from "fs/promises";
|
|
10557
10790
|
init_fs();
|
|
10558
10791
|
init_integrity();
|
|
10559
|
-
async function
|
|
10792
|
+
async function execute7() {
|
|
10560
10793
|
const root = process.cwd();
|
|
10561
10794
|
const paths = createPaths(root);
|
|
10562
10795
|
if (!await fileExists(paths.config)) {
|
|
@@ -10566,11 +10799,11 @@ async function execute6() {
|
|
|
10566
10799
|
emitError("status", "This project uses REAP v0.15 structure. Run '/reap.update' to upgrade to v0.16.");
|
|
10567
10800
|
}
|
|
10568
10801
|
const configContent = await readTextFile(paths.config);
|
|
10569
|
-
const config = configContent ?
|
|
10802
|
+
const config = configContent ? import_yaml7.default.parse(configContent) : null;
|
|
10570
10803
|
let generation = null;
|
|
10571
10804
|
const currentContent = await readTextFile(paths.current);
|
|
10572
10805
|
if (currentContent) {
|
|
10573
|
-
generation =
|
|
10806
|
+
generation = import_yaml7.default.parse(currentContent);
|
|
10574
10807
|
}
|
|
10575
10808
|
let completedGenerations = 0;
|
|
10576
10809
|
try {
|
|
@@ -10604,7 +10837,7 @@ async function execute6() {
|
|
|
10604
10837
|
}
|
|
10605
10838
|
|
|
10606
10839
|
// src/cli/commands/run/index.ts
|
|
10607
|
-
var
|
|
10840
|
+
var import_yaml22 = __toESM(require_dist(), 1);
|
|
10608
10841
|
init_fs();
|
|
10609
10842
|
init_integrity();
|
|
10610
10843
|
|
|
@@ -10632,11 +10865,12 @@ function autoReport(command, error, extraLabels) {
|
|
|
10632
10865
|
}
|
|
10633
10866
|
|
|
10634
10867
|
// src/cli/commands/run/start.ts
|
|
10635
|
-
|
|
10868
|
+
var import_yaml12 = __toESM(require_dist(), 1);
|
|
10869
|
+
import { basename, join as join13 } from "path";
|
|
10636
10870
|
|
|
10637
10871
|
// src/core/generation.ts
|
|
10638
10872
|
init_fs();
|
|
10639
|
-
var
|
|
10873
|
+
var import_yaml8 = __toESM(require_dist(), 1);
|
|
10640
10874
|
import { createHash as createHash3 } from "crypto";
|
|
10641
10875
|
import { hostname } from "os";
|
|
10642
10876
|
import { readdir as readdir7 } from "fs/promises";
|
|
@@ -10664,12 +10898,12 @@ class GenerationManager {
|
|
|
10664
10898
|
const content = await readTextFile(this.paths.current);
|
|
10665
10899
|
if (!content)
|
|
10666
10900
|
return null;
|
|
10667
|
-
return
|
|
10901
|
+
return import_yaml8.default.parse(content);
|
|
10668
10902
|
}
|
|
10669
10903
|
async save(state) {
|
|
10670
10904
|
const header = `# REAP MANAGED — Do not modify directly.
|
|
10671
10905
|
`;
|
|
10672
|
-
await writeTextFile(this.paths.current, header +
|
|
10906
|
+
await writeTextFile(this.paths.current, header + import_yaml8.default.stringify(state));
|
|
10673
10907
|
}
|
|
10674
10908
|
async create(goal, type = "embryo") {
|
|
10675
10909
|
await ensureDir(this.paths.life);
|
|
@@ -10748,15 +10982,15 @@ init_fs();
|
|
|
10748
10982
|
|
|
10749
10983
|
// src/core/hooks.ts
|
|
10750
10984
|
init_fs();
|
|
10751
|
-
var
|
|
10985
|
+
var import_yaml9 = __toESM(require_dist(), 1);
|
|
10752
10986
|
import { readdir as readdir8 } from "fs/promises";
|
|
10753
|
-
import { join as
|
|
10987
|
+
import { join as join9 } from "path";
|
|
10754
10988
|
import { execSync as execSync4 } from "child_process";
|
|
10755
10989
|
async function executeHooks(hooksDir, event, projectRoot) {
|
|
10756
10990
|
const hooks = await scanHooks(hooksDir, event);
|
|
10757
10991
|
if (hooks.length === 0)
|
|
10758
10992
|
return [];
|
|
10759
|
-
const conditionsDir =
|
|
10993
|
+
const conditionsDir = join9(hooksDir, "conditions");
|
|
10760
10994
|
const results = [];
|
|
10761
10995
|
for (const hook of hooks) {
|
|
10762
10996
|
const conditionMet = await evaluateCondition(conditionsDir, hook.condition, projectRoot);
|
|
@@ -10791,7 +11025,7 @@ async function scanHooks(hooksDir, event) {
|
|
|
10791
11025
|
const match = filename.match(pattern);
|
|
10792
11026
|
if (!match)
|
|
10793
11027
|
continue;
|
|
10794
|
-
const meta = await parseHookMeta(
|
|
11028
|
+
const meta = await parseHookMeta(join9(hooksDir, filename), match[2]);
|
|
10795
11029
|
hooks.push({
|
|
10796
11030
|
filename,
|
|
10797
11031
|
name: match[1],
|
|
@@ -10812,7 +11046,7 @@ async function parseHookMeta(filePath, ext) {
|
|
|
10812
11046
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
10813
11047
|
if (fmMatch) {
|
|
10814
11048
|
try {
|
|
10815
|
-
const fm =
|
|
11049
|
+
const fm = import_yaml9.default.parse(fmMatch[1]) ?? {};
|
|
10816
11050
|
return {
|
|
10817
11051
|
condition: String(fm.condition ?? "always"),
|
|
10818
11052
|
order: Number(fm.order ?? 50)
|
|
@@ -10838,7 +11072,7 @@ async function parseHookMeta(filePath, ext) {
|
|
|
10838
11072
|
async function evaluateCondition(conditionsDir, conditionName, projectRoot) {
|
|
10839
11073
|
if (conditionName === "always")
|
|
10840
11074
|
return { met: true };
|
|
10841
|
-
const scriptPath =
|
|
11075
|
+
const scriptPath = join9(conditionsDir, `${conditionName}.sh`);
|
|
10842
11076
|
if (!await fileExists(scriptPath)) {
|
|
10843
11077
|
return { met: false, reason: `condition script not found: ${conditionName}.sh` };
|
|
10844
11078
|
}
|
|
@@ -10851,7 +11085,7 @@ async function evaluateCondition(conditionsDir, conditionName, projectRoot) {
|
|
|
10851
11085
|
}
|
|
10852
11086
|
async function executeShHook(hook, event, projectRoot, hooksDir) {
|
|
10853
11087
|
try {
|
|
10854
|
-
const stdout = execSync4(`bash "${
|
|
11088
|
+
const stdout = execSync4(`bash "${join9(hooksDir, hook.filename)}"`, {
|
|
10855
11089
|
cwd: projectRoot,
|
|
10856
11090
|
timeout: 60000,
|
|
10857
11091
|
stdio: "pipe"
|
|
@@ -10877,7 +11111,7 @@ async function executeShHook(hook, event, projectRoot, hooksDir) {
|
|
|
10877
11111
|
}
|
|
10878
11112
|
}
|
|
10879
11113
|
async function executeMdHook(hook, event, hooksDir) {
|
|
10880
|
-
const content = await readTextFile(
|
|
11114
|
+
const content = await readTextFile(join9(hooksDir, hook.filename));
|
|
10881
11115
|
const body = content?.replace(/^---\n[\s\S]*?\n---\n?/, "").trim() ?? "";
|
|
10882
11116
|
return {
|
|
10883
11117
|
name: hook.name,
|
|
@@ -10890,9 +11124,9 @@ async function executeMdHook(hook, event, hooksDir) {
|
|
|
10890
11124
|
|
|
10891
11125
|
// src/core/backlog.ts
|
|
10892
11126
|
init_fs();
|
|
10893
|
-
var
|
|
11127
|
+
var import_yaml10 = __toESM(require_dist(), 1);
|
|
10894
11128
|
import { readdir as readdir9 } from "fs/promises";
|
|
10895
|
-
import { join as
|
|
11129
|
+
import { join as join10 } from "path";
|
|
10896
11130
|
async function scanBacklog(backlogDir) {
|
|
10897
11131
|
let entries;
|
|
10898
11132
|
try {
|
|
@@ -10904,7 +11138,7 @@ async function scanBacklog(backlogDir) {
|
|
|
10904
11138
|
for (const entry of entries) {
|
|
10905
11139
|
if (!entry.endsWith(".md"))
|
|
10906
11140
|
continue;
|
|
10907
|
-
const filePath =
|
|
11141
|
+
const filePath = join10(backlogDir, entry);
|
|
10908
11142
|
const content = await readTextFile(filePath);
|
|
10909
11143
|
if (!content)
|
|
10910
11144
|
continue;
|
|
@@ -10935,7 +11169,7 @@ async function consumeBacklog(filePath, genId) {
|
|
|
10935
11169
|
const fmRaw = fmMatch[1];
|
|
10936
11170
|
let parsed = {};
|
|
10937
11171
|
try {
|
|
10938
|
-
parsed =
|
|
11172
|
+
parsed = import_yaml10.default.parse(fmRaw) ?? {};
|
|
10939
11173
|
} catch {
|
|
10940
11174
|
return { status: "warning", warning: `${filePath}: malformed YAML frontmatter — backlog not marked` };
|
|
10941
11175
|
}
|
|
@@ -11047,7 +11281,7 @@ ${body}
|
|
|
11047
11281
|
`;
|
|
11048
11282
|
const { mkdir: mkdir3 } = await import("fs/promises");
|
|
11049
11283
|
await mkdir3(backlogDir, { recursive: true });
|
|
11050
|
-
await writeTextFile(
|
|
11284
|
+
await writeTextFile(join10(backlogDir, filename), content);
|
|
11051
11285
|
return filename;
|
|
11052
11286
|
}
|
|
11053
11287
|
async function createDeferredBacklog(backlogDir, input) {
|
|
@@ -11077,7 +11311,7 @@ ${tasksSection}
|
|
|
11077
11311
|
`;
|
|
11078
11312
|
const { mkdir: mkdir3 } = await import("fs/promises");
|
|
11079
11313
|
await mkdir3(backlogDir, { recursive: true });
|
|
11080
|
-
await writeTextFile(
|
|
11314
|
+
await writeTextFile(join10(backlogDir, filename), content);
|
|
11081
11315
|
return filename;
|
|
11082
11316
|
}
|
|
11083
11317
|
function extractUncheckedTasks(artifactContent) {
|
|
@@ -11098,9 +11332,9 @@ function countCheckedTasks(artifactContent) {
|
|
|
11098
11332
|
|
|
11099
11333
|
// src/core/lineage.ts
|
|
11100
11334
|
init_fs();
|
|
11101
|
-
var
|
|
11335
|
+
var import_yaml11 = __toESM(require_dist(), 1);
|
|
11102
11336
|
import { readdir as readdir10, stat as stat3 } from "fs/promises";
|
|
11103
|
-
import { join as
|
|
11337
|
+
import { join as join11 } from "path";
|
|
11104
11338
|
import { execSync as execSync5 } from "child_process";
|
|
11105
11339
|
function gitShow(cwd, ref, path) {
|
|
11106
11340
|
try {
|
|
@@ -11161,7 +11395,7 @@ async function getLastLineageEntry(paths) {
|
|
|
11161
11395
|
if (genEntries.length === 0)
|
|
11162
11396
|
return null;
|
|
11163
11397
|
const last = genEntries[genEntries.length - 1];
|
|
11164
|
-
const lastPath =
|
|
11398
|
+
const lastPath = join11(paths.lineage, last);
|
|
11165
11399
|
try {
|
|
11166
11400
|
const st = await stat3(lastPath);
|
|
11167
11401
|
if (!st.isDirectory())
|
|
@@ -11169,12 +11403,12 @@ async function getLastLineageEntry(paths) {
|
|
|
11169
11403
|
} catch {
|
|
11170
11404
|
return null;
|
|
11171
11405
|
}
|
|
11172
|
-
const metaContent = await readTextFile(
|
|
11406
|
+
const metaContent = await readTextFile(join11(lastPath, "meta.yml"));
|
|
11173
11407
|
if (!metaContent)
|
|
11174
11408
|
return null;
|
|
11175
11409
|
let parsed;
|
|
11176
11410
|
try {
|
|
11177
|
-
parsed =
|
|
11411
|
+
parsed = import_yaml11.default.parse(metaContent) ?? {};
|
|
11178
11412
|
} catch {
|
|
11179
11413
|
return null;
|
|
11180
11414
|
}
|
|
@@ -11198,7 +11432,7 @@ async function getLastLineageEntry(paths) {
|
|
|
11198
11432
|
}
|
|
11199
11433
|
|
|
11200
11434
|
// src/cli/commands/run/start.ts
|
|
11201
|
-
async function
|
|
11435
|
+
async function execute8(phase, goal, type, parents, backlog) {
|
|
11202
11436
|
const paths = createPaths(process.cwd());
|
|
11203
11437
|
if (!await fileExists(paths.config)) {
|
|
11204
11438
|
emitError("start", "Not a reap project. Run 'reap init' first.");
|
|
@@ -11282,7 +11516,6 @@ async function execute7(phase, goal, type, parents, backlog) {
|
|
|
11282
11516
|
`),
|
|
11283
11517
|
nextCommand: `reap run start --phase create --goal "${goal}" --backlog <filename>`
|
|
11284
11518
|
});
|
|
11285
|
-
return;
|
|
11286
11519
|
}
|
|
11287
11520
|
}
|
|
11288
11521
|
if (type === "merge") {
|
|
@@ -11313,7 +11546,7 @@ async function execute7(phase, goal, type, parents, backlog) {
|
|
|
11313
11546
|
const state = await gm.create(goal, genType);
|
|
11314
11547
|
let consumeWarning;
|
|
11315
11548
|
if (backlogFilename) {
|
|
11316
|
-
const backlogPath =
|
|
11549
|
+
const backlogPath = join13(paths.backlog, backlogFilename);
|
|
11317
11550
|
if (await fileExists(backlogPath)) {
|
|
11318
11551
|
const result = await consumeBacklog(backlogPath, state.id);
|
|
11319
11552
|
if (result.status === "warning" && result.warning) {
|
|
@@ -11326,8 +11559,13 @@ async function execute7(phase, goal, type, parents, backlog) {
|
|
|
11326
11559
|
}
|
|
11327
11560
|
}
|
|
11328
11561
|
await executeHooks(paths.hooks, "onLifeStarted", paths.root).catch(() => {});
|
|
11329
|
-
const
|
|
11330
|
-
|
|
11562
|
+
const configContent = await readTextFile(paths.config);
|
|
11563
|
+
const config = configContent ? import_yaml12.default.parse(configContent) : null;
|
|
11564
|
+
if (config?.daemon === true) {
|
|
11565
|
+
const { ensureRegistered: ensureRegistered2, triggerIndexing: triggerIndexing2 } = await Promise.resolve().then(() => (init_lifecycle(), exports_lifecycle));
|
|
11566
|
+
await ensureRegistered2(paths.root, basename(paths.root));
|
|
11567
|
+
await triggerIndexing2(paths.root);
|
|
11568
|
+
}
|
|
11331
11569
|
const messageLines = [`Generation ${state.id} created. Run: reap run learning`];
|
|
11332
11570
|
if (consumeWarning) {
|
|
11333
11571
|
messageLines.unshift(`[backlog warning] ${consumeWarning}`);
|
|
@@ -11354,8 +11592,9 @@ async function execute7(phase, goal, type, parents, backlog) {
|
|
|
11354
11592
|
|
|
11355
11593
|
// src/cli/commands/run/learning.ts
|
|
11356
11594
|
init_fs();
|
|
11595
|
+
var import_yaml13 = __toESM(require_dist(), 1);
|
|
11357
11596
|
import { readdir as readdir11 } from "fs/promises";
|
|
11358
|
-
import { join as
|
|
11597
|
+
import { basename as basename2, join as join15 } from "path";
|
|
11359
11598
|
|
|
11360
11599
|
// src/core/lifecycle.ts
|
|
11361
11600
|
init_types();
|
|
@@ -11538,7 +11777,7 @@ async function performMergeTransition(state, gm, paths) {
|
|
|
11538
11777
|
|
|
11539
11778
|
// src/core/template.ts
|
|
11540
11779
|
init_fs();
|
|
11541
|
-
import { join as
|
|
11780
|
+
import { join as join14, dirname as dirname5 } from "path";
|
|
11542
11781
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
11543
11782
|
import { copyFile as copyFile2 } from "fs/promises";
|
|
11544
11783
|
var STAGE_ARTIFACTS2 = {
|
|
@@ -11566,7 +11805,7 @@ async function copyArtifactTemplate(stage, artifactPath, isMerge) {
|
|
|
11566
11805
|
return;
|
|
11567
11806
|
const subdir = isMerge ? "merge" : "normal";
|
|
11568
11807
|
const __dirname2 = dirname5(fileURLToPath3(import.meta.url));
|
|
11569
|
-
const templatePath =
|
|
11808
|
+
const templatePath = join14(__dirname2, "..", "templates", "artifacts", subdir, filename);
|
|
11570
11809
|
if (!await fileExists(templatePath))
|
|
11571
11810
|
return;
|
|
11572
11811
|
await ensureDir(dirname5(destPath));
|
|
@@ -11574,7 +11813,7 @@ async function copyArtifactTemplate(stage, artifactPath, isMerge) {
|
|
|
11574
11813
|
}
|
|
11575
11814
|
|
|
11576
11815
|
// src/cli/commands/run/learning.ts
|
|
11577
|
-
async function
|
|
11816
|
+
async function execute9(paths, phase) {
|
|
11578
11817
|
const gm = new GenerationManager(paths);
|
|
11579
11818
|
const state = await gm.current();
|
|
11580
11819
|
if (!state)
|
|
@@ -11591,7 +11830,7 @@ async function execute8(paths, phase) {
|
|
|
11591
11830
|
const envSummary = await readTextFile(paths.environmentSummary);
|
|
11592
11831
|
let sourceBacklogContent = null;
|
|
11593
11832
|
if (s.sourceBacklog) {
|
|
11594
|
-
sourceBacklogContent = await readTextFile(
|
|
11833
|
+
sourceBacklogContent = await readTextFile(join15(paths.backlog, s.sourceBacklog)) ?? await readTextFile(join15(paths.life, "backlog", s.sourceBacklog));
|
|
11595
11834
|
}
|
|
11596
11835
|
const backlogItems = await scanBacklog(paths.backlog);
|
|
11597
11836
|
const pendingBacklog = backlogItems.filter((b) => b.status === "pending");
|
|
@@ -11602,8 +11841,8 @@ async function execute8(paths, phase) {
|
|
|
11602
11841
|
const genDirs = lineageEntries.filter((e) => e.startsWith("gen-")).sort();
|
|
11603
11842
|
if (genDirs.length > 0) {
|
|
11604
11843
|
const lastGen = genDirs[genDirs.length - 1];
|
|
11605
|
-
prevCompletion = await readTextFile(
|
|
11606
|
-
const metaContent = await readTextFile(
|
|
11844
|
+
prevCompletion = await readTextFile(join15(paths.lineage, lastGen, "05-completion.md"));
|
|
11845
|
+
const metaContent = await readTextFile(join15(paths.lineage, lastGen, "meta.yml"));
|
|
11607
11846
|
if (metaContent) {
|
|
11608
11847
|
const fitnessMatch = metaContent.match(/fitnessFeedback:\n\s+text:\s*([\s\S]*?)(?:\n\s+evaluatedAt:|\n[a-z])/);
|
|
11609
11848
|
if (fitnessMatch)
|
|
@@ -11613,6 +11852,16 @@ async function execute8(paths, phase) {
|
|
|
11613
11852
|
} catch {}
|
|
11614
11853
|
setTransitionNonces(s, "learning:entry");
|
|
11615
11854
|
await gm.save(s);
|
|
11855
|
+
const configContent = await readTextFile(paths.config);
|
|
11856
|
+
const config = configContent ? import_yaml13.default.parse(configContent) : null;
|
|
11857
|
+
const daemonEnabled = config?.daemon === true;
|
|
11858
|
+
let daemonReady;
|
|
11859
|
+
if (daemonEnabled) {
|
|
11860
|
+
const { ensureRegistered: ensureRegistered2, triggerIndexing: triggerIndexing2 } = await Promise.resolve().then(() => (init_lifecycle(), exports_lifecycle));
|
|
11861
|
+
const registered = await ensureRegistered2(paths.root, basename2(paths.root));
|
|
11862
|
+
const indexed = await triggerIndexing2(paths.root);
|
|
11863
|
+
daemonReady = registered && indexed;
|
|
11864
|
+
}
|
|
11616
11865
|
emitOutput({
|
|
11617
11866
|
status: "prompt",
|
|
11618
11867
|
command: "learning",
|
|
@@ -11630,7 +11879,9 @@ async function execute8(paths, phase) {
|
|
|
11630
11879
|
previousFitness: prevFitness,
|
|
11631
11880
|
artifactPath: paths.artifact("01-learning.md"),
|
|
11632
11881
|
sourceBacklog: s.sourceBacklog ? { filename: s.sourceBacklog, content: sourceBacklogContent?.slice(0, 2000) } : null,
|
|
11633
|
-
pendingBacklog: pendingBacklog.map((b) => ({ type: b.type, title: b.title, filename: b.filename }))
|
|
11882
|
+
pendingBacklog: pendingBacklog.map((b) => ({ type: b.type, title: b.title, filename: b.filename })),
|
|
11883
|
+
daemonEnabled,
|
|
11884
|
+
...daemonEnabled ? { daemonReady } : {}
|
|
11634
11885
|
},
|
|
11635
11886
|
prompt: [
|
|
11636
11887
|
"## Learning Stage — Explore and Build Context",
|
|
@@ -11688,7 +11939,7 @@ ${pendingBacklog.map((b) => `- [${b.type}] ${b.title} (\`${b.filename}\`)`).join
|
|
|
11688
11939
|
|
|
11689
11940
|
// src/cli/commands/run/planning.ts
|
|
11690
11941
|
init_fs();
|
|
11691
|
-
async function
|
|
11942
|
+
async function execute10(paths, phase) {
|
|
11692
11943
|
const gm = new GenerationManager(paths);
|
|
11693
11944
|
const state = await gm.current();
|
|
11694
11945
|
if (!state)
|
|
@@ -11779,8 +12030,9 @@ async function execute9(paths, phase) {
|
|
|
11779
12030
|
}
|
|
11780
12031
|
|
|
11781
12032
|
// src/cli/commands/run/implementation.ts
|
|
12033
|
+
var import_yaml14 = __toESM(require_dist(), 1);
|
|
11782
12034
|
init_fs();
|
|
11783
|
-
async function
|
|
12035
|
+
async function execute11(paths, phase) {
|
|
11784
12036
|
const gm = new GenerationManager(paths);
|
|
11785
12037
|
const state = await gm.current();
|
|
11786
12038
|
if (!state)
|
|
@@ -11853,6 +12105,12 @@ async function execute10(paths, phase) {
|
|
|
11853
12105
|
prepareStageEntry(s, "validation:entry");
|
|
11854
12106
|
await gm.save(s);
|
|
11855
12107
|
const next = await performTransition(s, gm, paths);
|
|
12108
|
+
const configContent = await readTextFile(paths.config);
|
|
12109
|
+
const config = configContent ? import_yaml14.default.parse(configContent) : null;
|
|
12110
|
+
if (config?.daemon === true) {
|
|
12111
|
+
const { triggerIndexing: triggerIndexing2 } = await Promise.resolve().then(() => (init_lifecycle(), exports_lifecycle));
|
|
12112
|
+
await triggerIndexing2(paths.root);
|
|
12113
|
+
}
|
|
11856
12114
|
emitOutput({
|
|
11857
12115
|
status: "ok",
|
|
11858
12116
|
command: "implementation",
|
|
@@ -11865,6 +12123,10 @@ async function execute10(paths, phase) {
|
|
|
11865
12123
|
}
|
|
11866
12124
|
}
|
|
11867
12125
|
|
|
12126
|
+
// src/cli/commands/run/validation.ts
|
|
12127
|
+
var import_yaml15 = __toESM(require_dist(), 1);
|
|
12128
|
+
init_fs();
|
|
12129
|
+
|
|
11868
12130
|
// src/core/artifact-check.ts
|
|
11869
12131
|
init_fs();
|
|
11870
12132
|
var PRE_VALIDATION_NORMAL = {
|
|
@@ -11899,7 +12161,7 @@ function isUnfilled(content) {
|
|
|
11899
12161
|
}
|
|
11900
12162
|
|
|
11901
12163
|
// src/cli/commands/run/validation.ts
|
|
11902
|
-
async function
|
|
12164
|
+
async function execute12(paths, phase, extra) {
|
|
11903
12165
|
const gm = new GenerationManager(paths);
|
|
11904
12166
|
const state = await gm.current();
|
|
11905
12167
|
if (!state)
|
|
@@ -11908,6 +12170,64 @@ async function execute11(paths, phase) {
|
|
|
11908
12170
|
emitError("validation", `Current stage is '${state.stage}', not 'validation'.`);
|
|
11909
12171
|
const isMerge = state.type === "merge";
|
|
11910
12172
|
const s = state;
|
|
12173
|
+
if (phase === "report-evaluator") {
|
|
12174
|
+
let severity;
|
|
12175
|
+
let summary;
|
|
12176
|
+
if (extra) {
|
|
12177
|
+
try {
|
|
12178
|
+
const parsed = JSON.parse(extra);
|
|
12179
|
+
severity = parsed.severity;
|
|
12180
|
+
summary = parsed.summary;
|
|
12181
|
+
} catch {
|
|
12182
|
+
emitError("validation", "report-evaluator: failed to parse options. Expected --severity and --summary.");
|
|
12183
|
+
}
|
|
12184
|
+
}
|
|
12185
|
+
if (!severity) {
|
|
12186
|
+
emitError("validation", "report-evaluator requires --severity <high|low|none>.");
|
|
12187
|
+
}
|
|
12188
|
+
const sev = severity.toLowerCase();
|
|
12189
|
+
if (sev === "none") {
|
|
12190
|
+
emitOutput({
|
|
12191
|
+
status: "ok",
|
|
12192
|
+
command: "validation",
|
|
12193
|
+
phase: "report-evaluator",
|
|
12194
|
+
completed: ["gate", "noop"],
|
|
12195
|
+
context: { id: s.id, severity: "none" },
|
|
12196
|
+
message: "Evaluator reported no concern — state unchanged."
|
|
12197
|
+
});
|
|
12198
|
+
return;
|
|
12199
|
+
}
|
|
12200
|
+
if (sev !== "high" && sev !== "low") {
|
|
12201
|
+
emitError("validation", `report-evaluator: invalid severity '${severity}'. Use high, low, or none.`);
|
|
12202
|
+
}
|
|
12203
|
+
if (!summary || summary.trim().length === 0) {
|
|
12204
|
+
emitError("validation", 'report-evaluator requires --summary "<one-line description>".');
|
|
12205
|
+
}
|
|
12206
|
+
const concern = {
|
|
12207
|
+
stage: "validation",
|
|
12208
|
+
severity: sev,
|
|
12209
|
+
summary: summary.trim(),
|
|
12210
|
+
recordedAt: new Date().toISOString()
|
|
12211
|
+
};
|
|
12212
|
+
if (!s.evaluatorConcerns)
|
|
12213
|
+
s.evaluatorConcerns = [];
|
|
12214
|
+
s.evaluatorConcerns.push(concern);
|
|
12215
|
+
await gm.save(s);
|
|
12216
|
+
emitOutput({
|
|
12217
|
+
status: "ok",
|
|
12218
|
+
command: "validation",
|
|
12219
|
+
phase: "report-evaluator",
|
|
12220
|
+
completed: ["gate", "concern-recorded"],
|
|
12221
|
+
context: {
|
|
12222
|
+
id: s.id,
|
|
12223
|
+
severity: concern.severity,
|
|
12224
|
+
summary: concern.summary,
|
|
12225
|
+
total: s.evaluatorConcerns.length
|
|
12226
|
+
},
|
|
12227
|
+
message: `Evaluator concern recorded (severity=${concern.severity}). Total: ${s.evaluatorConcerns.length}.`
|
|
12228
|
+
});
|
|
12229
|
+
return;
|
|
12230
|
+
}
|
|
11911
12231
|
if (!phase || phase === "work") {
|
|
11912
12232
|
verifyTransition("validation", s, "validation:entry");
|
|
11913
12233
|
await copyArtifactTemplate("validation", paths.artifact, isMerge);
|
|
@@ -11944,48 +12264,92 @@ async function execute11(paths, phase) {
|
|
|
11944
12264
|
});
|
|
11945
12265
|
return;
|
|
11946
12266
|
}
|
|
12267
|
+
const basePromptLines = [
|
|
12268
|
+
"## Validation Stage",
|
|
12269
|
+
"",
|
|
12270
|
+
"### HARD-GATE:",
|
|
12271
|
+
"- Do NOT declare 'pass' without running the validation commands.",
|
|
12272
|
+
"- Do NOT reuse results from a previous run — execute them FRESH.",
|
|
12273
|
+
"- 'It will probably pass' is NOT validation.",
|
|
12274
|
+
"",
|
|
12275
|
+
"### Steps:",
|
|
12276
|
+
"1. **TypeCheck**: Run `npm run typecheck` (or project's typecheck command). Record result.",
|
|
12277
|
+
"2. **Build**: Run `npm run build` (or project's build command). Record result.",
|
|
12278
|
+
"3. **Tests**: Run ALL test commands the project has (e.g., e2e scripts). Record each result.",
|
|
12279
|
+
"4. **Completion Criteria**: Verify EACH criterion from 02-planning.md one by one.",
|
|
12280
|
+
"5. **Minor Fix** (trivial issues only, under 5 minutes): Fix and re-run the failed command.",
|
|
12281
|
+
"6. **Verdict**: Determine pass / partial / fail.",
|
|
12282
|
+
"",
|
|
12283
|
+
"### Red Flags (sycophancy prevention):",
|
|
12284
|
+
"- 'It will probably pass' → Run it.",
|
|
12285
|
+
"- 'It passed before' → Run it again.",
|
|
12286
|
+
"- 'It\\'s trivial, no need to test' → Test it anyway.",
|
|
12287
|
+
"",
|
|
12288
|
+
"### Verdict Criteria:",
|
|
12289
|
+
"- **pass**: All checks pass, all completion criteria met.",
|
|
12290
|
+
"- **partial**: Minor issues remain but core functionality works. Document what's incomplete.",
|
|
12291
|
+
"- **fail**: Critical failures. Must regress to implementation.",
|
|
12292
|
+
"",
|
|
12293
|
+
`### Artifact: Write \`.reap/life/${isMerge ? "05" : "04"}-validation.md\` progressively (after each command).`,
|
|
12294
|
+
"",
|
|
12295
|
+
"If pass/partial: reap run validation --phase complete",
|
|
12296
|
+
"If fail: reap run back to regress"
|
|
12297
|
+
];
|
|
12298
|
+
const configContent = await readTextFile(paths.config);
|
|
12299
|
+
const config = configContent ? import_yaml15.default.parse(configContent) : null;
|
|
12300
|
+
const evaluatorEnabled = config?.evaluator === true;
|
|
12301
|
+
const context = {
|
|
12302
|
+
id: s.id,
|
|
12303
|
+
goal: s.goal,
|
|
12304
|
+
type: s.type,
|
|
12305
|
+
artifactPath: paths.artifact(isMerge ? "05-validation.md" : "04-validation.md"),
|
|
12306
|
+
evaluator: { enabled: evaluatorEnabled }
|
|
12307
|
+
};
|
|
12308
|
+
const promptLines = [...basePromptLines];
|
|
12309
|
+
if (evaluatorEnabled) {
|
|
12310
|
+
const knowledge = await loadReapKnowledge(paths);
|
|
12311
|
+
const evaluatorPrompt = buildEvaluatorPrompt(knowledge, paths, s, { stage: "validation" });
|
|
12312
|
+
context.evaluator.prompt = evaluatorPrompt;
|
|
12313
|
+
promptLines.push("");
|
|
12314
|
+
promptLines.push("### Evaluator Subagent Invocation (opt-in via `evaluator: true`)");
|
|
12315
|
+
promptLines.push("");
|
|
12316
|
+
promptLines.push("Before declaring your verdict, launch an independent reviewer using the Agent tool:");
|
|
12317
|
+
promptLines.push("");
|
|
12318
|
+
promptLines.push("- subagent_type: `reap-evaluate`");
|
|
12319
|
+
promptLines.push("- description: independent validation review");
|
|
12320
|
+
promptLines.push("- prompt: the `evaluator.prompt` value from the context above");
|
|
12321
|
+
promptLines.push("");
|
|
12322
|
+
promptLines.push("**Advisor model** — the evaluator's assessment is a recommendation, not a verdict:");
|
|
12323
|
+
promptLines.push("- You (the builder) decide the final pass/partial/fail verdict.");
|
|
12324
|
+
promptLines.push("- Surface every evaluator concern to the user in your validation report, even if you disagree.");
|
|
12325
|
+
promptLines.push("- If the evaluator escalates a high-impact concern, lean toward `partial` and document the concern in 04-validation.md.");
|
|
12326
|
+
promptLines.push("");
|
|
12327
|
+
promptLines.push("**Persist the verdict for the fitness phase (gen-067)**:");
|
|
12328
|
+
promptLines.push("");
|
|
12329
|
+
promptLines.push("After receiving the evaluator's reply, record the outcome on the generation state so the");
|
|
12330
|
+
promptLines.push("subsequent fitness phase can act on it (cruise mode auto-abort, evaluator concern surfacing):");
|
|
12331
|
+
promptLines.push("");
|
|
12332
|
+
promptLines.push("- High-impact escalation:");
|
|
12333
|
+
promptLines.push(' `reap run validation --phase report-evaluator --severity high --summary "<one-line description>"`');
|
|
12334
|
+
promptLines.push("- Low-impact concern (informational):");
|
|
12335
|
+
promptLines.push(' `reap run validation --phase report-evaluator --severity low --summary "<one-line description>"`');
|
|
12336
|
+
promptLines.push("- Clean review (no concern):");
|
|
12337
|
+
promptLines.push(' `reap run validation --phase report-evaluator --severity none --summary ""`');
|
|
12338
|
+
promptLines.push("");
|
|
12339
|
+
promptLines.push("This call does NOT advance the lifecycle — it only appends to `state.evaluatorConcerns`.");
|
|
12340
|
+
promptLines.push("");
|
|
12341
|
+
promptLines.push("**Fallback** — if the evaluator subagent fails (tool unavailable, model error, malformed reply):");
|
|
12342
|
+
promptLines.push("- Tell the user the evaluator could not run and why.");
|
|
12343
|
+
promptLines.push("- Continue normal validation. The evaluator is opt-in advice, not a gate.");
|
|
12344
|
+
promptLines.push("- Skip the `report-evaluator` CLI call (no concern was generated).");
|
|
12345
|
+
}
|
|
11947
12346
|
emitOutput({
|
|
11948
12347
|
status: "prompt",
|
|
11949
12348
|
command: "validation",
|
|
11950
12349
|
phase: "work",
|
|
11951
12350
|
completed: ["gate", "artifact-check"],
|
|
11952
|
-
context
|
|
11953
|
-
|
|
11954
|
-
goal: s.goal,
|
|
11955
|
-
type: s.type,
|
|
11956
|
-
artifactPath: paths.artifact(isMerge ? "05-validation.md" : "04-validation.md")
|
|
11957
|
-
},
|
|
11958
|
-
prompt: [
|
|
11959
|
-
"## Validation Stage",
|
|
11960
|
-
"",
|
|
11961
|
-
"### HARD-GATE:",
|
|
11962
|
-
"- Do NOT declare 'pass' without running the validation commands.",
|
|
11963
|
-
"- Do NOT reuse results from a previous run — execute them FRESH.",
|
|
11964
|
-
"- 'It will probably pass' is NOT validation.",
|
|
11965
|
-
"",
|
|
11966
|
-
"### Steps:",
|
|
11967
|
-
"1. **TypeCheck**: Run `npm run typecheck` (or project's typecheck command). Record result.",
|
|
11968
|
-
"2. **Build**: Run `npm run build` (or project's build command). Record result.",
|
|
11969
|
-
"3. **Tests**: Run ALL test commands the project has (e.g., e2e scripts). Record each result.",
|
|
11970
|
-
"4. **Completion Criteria**: Verify EACH criterion from 02-planning.md one by one.",
|
|
11971
|
-
"5. **Minor Fix** (trivial issues only, under 5 minutes): Fix and re-run the failed command.",
|
|
11972
|
-
"6. **Verdict**: Determine pass / partial / fail.",
|
|
11973
|
-
"",
|
|
11974
|
-
"### Red Flags (sycophancy prevention):",
|
|
11975
|
-
"- 'It will probably pass' → Run it.",
|
|
11976
|
-
"- 'It passed before' → Run it again.",
|
|
11977
|
-
"- 'It\\'s trivial, no need to test' → Test it anyway.",
|
|
11978
|
-
"",
|
|
11979
|
-
"### Verdict Criteria:",
|
|
11980
|
-
"- **pass**: All checks pass, all completion criteria met.",
|
|
11981
|
-
"- **partial**: Minor issues remain but core functionality works. Document what's incomplete.",
|
|
11982
|
-
"- **fail**: Critical failures. Must regress to implementation.",
|
|
11983
|
-
"",
|
|
11984
|
-
`### Artifact: Write \`.reap/life/${isMerge ? "05" : "04"}-validation.md\` progressively (after each command).`,
|
|
11985
|
-
"",
|
|
11986
|
-
"If pass/partial: reap run validation --phase complete",
|
|
11987
|
-
"If fail: reap run back to regress"
|
|
11988
|
-
].join(`
|
|
12351
|
+
context,
|
|
12352
|
+
prompt: promptLines.join(`
|
|
11989
12353
|
`),
|
|
11990
12354
|
nextCommand: "reap run validation --phase complete"
|
|
11991
12355
|
});
|
|
@@ -12013,15 +12377,15 @@ init_fs();
|
|
|
12013
12377
|
|
|
12014
12378
|
// src/core/archive.ts
|
|
12015
12379
|
init_fs();
|
|
12016
|
-
var
|
|
12017
|
-
import { join as
|
|
12380
|
+
var import_yaml17 = __toESM(require_dist(), 1);
|
|
12381
|
+
import { join as join17 } from "path";
|
|
12018
12382
|
import { readdir as readdir13, rm as rm4, unlink } from "fs/promises";
|
|
12019
12383
|
|
|
12020
12384
|
// src/core/compression.ts
|
|
12021
12385
|
init_fs();
|
|
12022
|
-
var
|
|
12386
|
+
var import_yaml16 = __toESM(require_dist(), 1);
|
|
12023
12387
|
import { readdir as readdir12, rm as rm3 } from "fs/promises";
|
|
12024
|
-
import { join as
|
|
12388
|
+
import { join as join16 } from "path";
|
|
12025
12389
|
var LEVEL1_THRESHOLD = 20;
|
|
12026
12390
|
var PROTECTED_RECENT = 20;
|
|
12027
12391
|
var LEVEL2_THRESHOLD = 100;
|
|
@@ -12038,7 +12402,7 @@ async function compressLineage(lineageDir) {
|
|
|
12038
12402
|
const { stat: stat4 } = await import("fs/promises");
|
|
12039
12403
|
const uncompressed = [];
|
|
12040
12404
|
for (const entry of genDirs) {
|
|
12041
|
-
const s = await stat4(
|
|
12405
|
+
const s = await stat4(join16(lineageDir, entry)).catch(() => null);
|
|
12042
12406
|
if (s?.isDirectory())
|
|
12043
12407
|
uncompressed.push(entry);
|
|
12044
12408
|
}
|
|
@@ -12047,15 +12411,15 @@ async function compressLineage(lineageDir) {
|
|
|
12047
12411
|
return 0;
|
|
12048
12412
|
let compressed = 0;
|
|
12049
12413
|
for (const dirName of toCompress) {
|
|
12050
|
-
const dirPath =
|
|
12051
|
-
const metaContent = await readTextFile(
|
|
12414
|
+
const dirPath = join16(lineageDir, dirName);
|
|
12415
|
+
const metaContent = await readTextFile(join16(dirPath, "meta.yml"));
|
|
12052
12416
|
let meta = { id: dirName, type: "unknown", goal: "", parents: [] };
|
|
12053
12417
|
if (metaContent) {
|
|
12054
12418
|
try {
|
|
12055
|
-
meta =
|
|
12419
|
+
meta = import_yaml16.default.parse(metaContent);
|
|
12056
12420
|
} catch {}
|
|
12057
12421
|
}
|
|
12058
|
-
const completion = await readTextFile(
|
|
12422
|
+
const completion = await readTextFile(join16(dirPath, "05-completion.md")) ?? "";
|
|
12059
12423
|
const summarySection = completion.match(/## Summary\n([\s\S]*?)(?=\n## |\n$)/)?.[1]?.trim() ?? "";
|
|
12060
12424
|
const compressedContent = [
|
|
12061
12425
|
"---",
|
|
@@ -12072,7 +12436,7 @@ async function compressLineage(lineageDir) {
|
|
|
12072
12436
|
""
|
|
12073
12437
|
].filter(Boolean).join(`
|
|
12074
12438
|
`);
|
|
12075
|
-
await writeTextFile(
|
|
12439
|
+
await writeTextFile(join16(lineageDir, `${dirName}.md`), compressedContent);
|
|
12076
12440
|
await rm3(dirPath, { recursive: true, force: true });
|
|
12077
12441
|
compressed++;
|
|
12078
12442
|
}
|
|
@@ -12091,7 +12455,7 @@ async function compressToEpoch(lineageDir) {
|
|
|
12091
12455
|
for (const entry of entries) {
|
|
12092
12456
|
if (!entry.startsWith("gen-") || !entry.endsWith(".md"))
|
|
12093
12457
|
continue;
|
|
12094
|
-
const s = await stat4(
|
|
12458
|
+
const s = await stat4(join16(lineageDir, entry)).catch(() => null);
|
|
12095
12459
|
if (s?.isFile())
|
|
12096
12460
|
level1Files.push(entry);
|
|
12097
12461
|
}
|
|
@@ -12100,14 +12464,14 @@ async function compressToEpoch(lineageDir) {
|
|
|
12100
12464
|
const allParents = new Set;
|
|
12101
12465
|
const fileMetas = [];
|
|
12102
12466
|
for (const file of level1Files.sort()) {
|
|
12103
|
-
const content = await readTextFile(
|
|
12467
|
+
const content = await readTextFile(join16(lineageDir, file));
|
|
12104
12468
|
if (!content)
|
|
12105
12469
|
continue;
|
|
12106
12470
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
12107
12471
|
let meta = { id: file.replace(".md", ""), type: "unknown", goal: "", parents: [] };
|
|
12108
12472
|
if (fmMatch) {
|
|
12109
12473
|
try {
|
|
12110
|
-
const parsed =
|
|
12474
|
+
const parsed = import_yaml16.default.parse(fmMatch[1]);
|
|
12111
12475
|
meta = { ...meta, ...parsed };
|
|
12112
12476
|
} catch {}
|
|
12113
12477
|
}
|
|
@@ -12120,24 +12484,24 @@ async function compressToEpoch(lineageDir) {
|
|
|
12120
12484
|
const dirEntries = entries.filter((e) => e.startsWith("gen-") && !e.endsWith(".md"));
|
|
12121
12485
|
const dirParents = new Set;
|
|
12122
12486
|
for (const dir of dirEntries) {
|
|
12123
|
-
const metaContent = await readTextFile(
|
|
12487
|
+
const metaContent = await readTextFile(join16(lineageDir, dir, "meta.yml"));
|
|
12124
12488
|
if (!metaContent)
|
|
12125
12489
|
continue;
|
|
12126
12490
|
try {
|
|
12127
|
-
const m =
|
|
12491
|
+
const m = import_yaml16.default.parse(metaContent);
|
|
12128
12492
|
if (m.parents)
|
|
12129
12493
|
m.parents.forEach((p) => dirParents.add(p));
|
|
12130
12494
|
} catch {}
|
|
12131
12495
|
}
|
|
12132
12496
|
const epochFiles = entries.filter((e) => e.startsWith("epoch-") && e.endsWith(".md"));
|
|
12133
12497
|
for (const ef of epochFiles) {
|
|
12134
|
-
const content = await readTextFile(
|
|
12498
|
+
const content = await readTextFile(join16(lineageDir, ef));
|
|
12135
12499
|
if (!content)
|
|
12136
12500
|
continue;
|
|
12137
12501
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
12138
12502
|
if (fmMatch) {
|
|
12139
12503
|
try {
|
|
12140
|
-
const parsed =
|
|
12504
|
+
const parsed = import_yaml16.default.parse(fmMatch[1]);
|
|
12141
12505
|
const lastId = parsed.lastGeneration;
|
|
12142
12506
|
if (lastId)
|
|
12143
12507
|
dirParents.add(lastId);
|
|
@@ -12175,9 +12539,9 @@ async function compressToEpoch(lineageDir) {
|
|
|
12175
12539
|
""
|
|
12176
12540
|
].join(`
|
|
12177
12541
|
`);
|
|
12178
|
-
await writeTextFile(
|
|
12542
|
+
await writeTextFile(join16(lineageDir, epochName), epochContent);
|
|
12179
12543
|
for (const f of compressible) {
|
|
12180
|
-
await rm3(
|
|
12544
|
+
await rm3(join16(lineageDir, f.filename), { force: true });
|
|
12181
12545
|
}
|
|
12182
12546
|
return compressible.length;
|
|
12183
12547
|
}
|
|
@@ -12185,7 +12549,7 @@ async function compressToEpoch(lineageDir) {
|
|
|
12185
12549
|
// src/core/archive.ts
|
|
12186
12550
|
function buildArchiveDir(lineageRoot, state) {
|
|
12187
12551
|
const goalSlug = state.goal.toLowerCase().replace(/[^a-z0-9가-힣]+/g, "-").slice(0, 40).replace(/-+$/, "");
|
|
12188
|
-
return
|
|
12552
|
+
return join17(lineageRoot, `${state.id}-${goalSlug}`);
|
|
12189
12553
|
}
|
|
12190
12554
|
async function writeArchive(paths, state, archiveDir, extraMeta) {
|
|
12191
12555
|
await ensureDir(archiveDir);
|
|
@@ -12193,20 +12557,20 @@ async function writeArchive(paths, state, archiveDir, extraMeta) {
|
|
|
12193
12557
|
for (const entry of lifeEntries) {
|
|
12194
12558
|
if (entry === "current.yml" || entry === "backlog")
|
|
12195
12559
|
continue;
|
|
12196
|
-
const src =
|
|
12197
|
-
const dest =
|
|
12560
|
+
const src = join17(paths.life, entry);
|
|
12561
|
+
const dest = join17(archiveDir, entry);
|
|
12198
12562
|
const { cp: cp2 } = await import("fs/promises");
|
|
12199
12563
|
await cp2(src, dest, { recursive: true });
|
|
12200
12564
|
}
|
|
12201
12565
|
const backlogItems = await scanBacklog(paths.backlog);
|
|
12202
12566
|
const consumedItems = backlogItems.filter((b) => b.status === "consumed");
|
|
12203
12567
|
if (consumedItems.length > 0) {
|
|
12204
|
-
const archiveBacklogDir =
|
|
12568
|
+
const archiveBacklogDir = join17(archiveDir, "backlog");
|
|
12205
12569
|
await ensureDir(archiveBacklogDir);
|
|
12206
12570
|
for (const item of consumedItems) {
|
|
12207
12571
|
const content = await readTextFile(item.path);
|
|
12208
12572
|
if (content) {
|
|
12209
|
-
await writeTextFile(
|
|
12573
|
+
await writeTextFile(join17(archiveBacklogDir, item.filename), content);
|
|
12210
12574
|
}
|
|
12211
12575
|
await unlink(item.path).catch(() => {});
|
|
12212
12576
|
}
|
|
@@ -12219,11 +12583,11 @@ async function writeArchive(paths, state, archiveDir, extraMeta) {
|
|
|
12219
12583
|
timeline: state.timeline,
|
|
12220
12584
|
...extraMeta
|
|
12221
12585
|
};
|
|
12222
|
-
await writeTextFile(
|
|
12586
|
+
await writeTextFile(join17(archiveDir, "meta.yml"), import_yaml17.default.stringify(meta));
|
|
12223
12587
|
for (const entry of lifeEntries) {
|
|
12224
12588
|
if (entry === "backlog")
|
|
12225
12589
|
continue;
|
|
12226
|
-
await rm4(
|
|
12590
|
+
await rm4(join17(paths.life, entry), { recursive: true, force: true });
|
|
12227
12591
|
}
|
|
12228
12592
|
await compressLineage(paths.lineage).catch(() => {});
|
|
12229
12593
|
}
|
|
@@ -12544,7 +12908,7 @@ function tokenize(text) {
|
|
|
12544
12908
|
|
|
12545
12909
|
// src/core/cruise.ts
|
|
12546
12910
|
init_fs();
|
|
12547
|
-
var
|
|
12911
|
+
var import_yaml18 = __toESM(require_dist(), 1);
|
|
12548
12912
|
function parseCruiseCount(config) {
|
|
12549
12913
|
if (!config.cruiseCount)
|
|
12550
12914
|
return null;
|
|
@@ -12557,31 +12921,39 @@ async function advanceCruise(configPath) {
|
|
|
12557
12921
|
const content = await readTextFile(configPath);
|
|
12558
12922
|
if (!content)
|
|
12559
12923
|
return false;
|
|
12560
|
-
const config =
|
|
12924
|
+
const config = import_yaml18.default.parse(content);
|
|
12561
12925
|
const cruise = parseCruiseCount(config);
|
|
12562
12926
|
if (!cruise)
|
|
12563
12927
|
return false;
|
|
12564
12928
|
if (cruise.current >= cruise.total) {
|
|
12565
12929
|
delete config.cruiseCount;
|
|
12566
|
-
await writeTextFile(configPath,
|
|
12930
|
+
await writeTextFile(configPath, import_yaml18.default.stringify(config));
|
|
12567
12931
|
return false;
|
|
12568
12932
|
}
|
|
12569
12933
|
config.cruiseCount = `${cruise.current + 1}/${cruise.total}`;
|
|
12570
|
-
await writeTextFile(configPath,
|
|
12934
|
+
await writeTextFile(configPath, import_yaml18.default.stringify(config));
|
|
12571
12935
|
return true;
|
|
12572
12936
|
}
|
|
12937
|
+
async function clearCruise(configPath) {
|
|
12938
|
+
const content = await readTextFile(configPath);
|
|
12939
|
+
if (!content)
|
|
12940
|
+
return;
|
|
12941
|
+
const config = import_yaml18.default.parse(content);
|
|
12942
|
+
delete config.cruiseCount;
|
|
12943
|
+
await writeTextFile(configPath, import_yaml18.default.stringify(config));
|
|
12944
|
+
}
|
|
12573
12945
|
async function setCruise(configPath, total) {
|
|
12574
12946
|
const content = await readTextFile(configPath);
|
|
12575
12947
|
if (!content)
|
|
12576
12948
|
return;
|
|
12577
|
-
const config =
|
|
12949
|
+
const config = import_yaml18.default.parse(content);
|
|
12578
12950
|
config.cruiseCount = `1/${total}`;
|
|
12579
|
-
await writeTextFile(configPath,
|
|
12951
|
+
await writeTextFile(configPath, import_yaml18.default.stringify(config));
|
|
12580
12952
|
}
|
|
12581
12953
|
|
|
12582
12954
|
// src/cli/commands/run/completion.ts
|
|
12583
|
-
var
|
|
12584
|
-
async function
|
|
12955
|
+
var import_yaml19 = __toESM(require_dist(), 1);
|
|
12956
|
+
async function execute13(paths, phase, feedback) {
|
|
12585
12957
|
const gm = new GenerationManager(paths);
|
|
12586
12958
|
const state = await gm.current();
|
|
12587
12959
|
if (!state)
|
|
@@ -12669,52 +13041,144 @@ async function execute12(paths, phase, feedback) {
|
|
|
12669
13041
|
} else {
|
|
12670
13042
|
verifyTransition("completion", s, "completion:fitness");
|
|
12671
13043
|
const configContent = await readTextFile(paths.config);
|
|
12672
|
-
const config = configContent ?
|
|
13044
|
+
const config = configContent ? import_yaml19.default.parse(configContent) : null;
|
|
12673
13045
|
const cruise = config ? parseCruiseCount(config) : null;
|
|
13046
|
+
const evaluatorEnabled = config?.evaluator === true;
|
|
12674
13047
|
setTransitionNonces(s, "completion:fitness");
|
|
12675
13048
|
await gm.save(s);
|
|
13049
|
+
const highConcerns = (s.evaluatorConcerns ?? []).filter((c) => c.severity === "high");
|
|
13050
|
+
let fitnessEvaluatorPrompt;
|
|
13051
|
+
if (evaluatorEnabled) {
|
|
13052
|
+
const knowledge = await loadReapKnowledge(paths);
|
|
13053
|
+
fitnessEvaluatorPrompt = buildEvaluatorPrompt(knowledge, paths, s, { stage: "fitness" });
|
|
13054
|
+
}
|
|
13055
|
+
const evaluatorSection = [];
|
|
13056
|
+
if (evaluatorEnabled) {
|
|
13057
|
+
evaluatorSection.push("");
|
|
13058
|
+
evaluatorSection.push("### Evaluator Subagent Invocation (opt-in via `evaluator: true`)");
|
|
13059
|
+
evaluatorSection.push("");
|
|
13060
|
+
evaluatorSection.push("Before composing the final fitness feedback, launch the independent reviewer using the Agent tool:");
|
|
13061
|
+
evaluatorSection.push("");
|
|
13062
|
+
evaluatorSection.push("- subagent_type: `reap-evaluate`");
|
|
13063
|
+
evaluatorSection.push("- description: independent fitness assessment");
|
|
13064
|
+
evaluatorSection.push("- prompt: the `evaluator.prompt` value from the context above");
|
|
13065
|
+
evaluatorSection.push("");
|
|
13066
|
+
evaluatorSection.push("The evaluator scores the generation along the 6 fitness dimensions (qualitative — no numeric scores).");
|
|
13067
|
+
evaluatorSection.push("Surface every concern to the user in your fitness summary; the human owns the final feedback.");
|
|
13068
|
+
evaluatorSection.push("");
|
|
13069
|
+
evaluatorSection.push("**Fallback** — if the evaluator subagent fails, document the failure and continue. Fitness phase is not gated on the evaluator.");
|
|
13070
|
+
}
|
|
13071
|
+
const priorConcernsSection = [];
|
|
13072
|
+
if ((s.evaluatorConcerns ?? []).length > 0) {
|
|
13073
|
+
priorConcernsSection.push("");
|
|
13074
|
+
priorConcernsSection.push("### Prior Evaluator Concerns (carried from earlier stages)");
|
|
13075
|
+
priorConcernsSection.push("");
|
|
13076
|
+
for (const c of s.evaluatorConcerns) {
|
|
13077
|
+
priorConcernsSection.push(`- [${c.severity}] (${c.stage}) ${c.summary}`);
|
|
13078
|
+
}
|
|
13079
|
+
priorConcernsSection.push("");
|
|
13080
|
+
priorConcernsSection.push("Surface each of the above to the user with your fitness summary.");
|
|
13081
|
+
}
|
|
13082
|
+
if (cruise && highConcerns.length > 0) {
|
|
13083
|
+
await clearCruise(paths.config);
|
|
13084
|
+
const fallbackPrompt = [
|
|
13085
|
+
"## Cruise Aborted by Evaluator Concern",
|
|
13086
|
+
"",
|
|
13087
|
+
"Cruise mode has been **disengaged** because the evaluator raised a high-impact concern:",
|
|
13088
|
+
""
|
|
13089
|
+
];
|
|
13090
|
+
for (const c of highConcerns) {
|
|
13091
|
+
fallbackPrompt.push(`- [${c.severity}] (${c.stage}) ${c.summary}`);
|
|
13092
|
+
}
|
|
13093
|
+
fallbackPrompt.push("");
|
|
13094
|
+
fallbackPrompt.push("The remaining cruise generations will NOT auto-start. This fitness phase now follows the supervised flow:");
|
|
13095
|
+
fallbackPrompt.push("");
|
|
13096
|
+
fallbackPrompt.push("1. Present the concern(s) above to the human together with a summary of this generation.");
|
|
13097
|
+
fallbackPrompt.push("2. Wait for the human's decision (continue, override, abort generation, etc.).");
|
|
13098
|
+
fallbackPrompt.push('3. Submit: `reap run completion --phase fitness --feedback "<human feedback>"`');
|
|
13099
|
+
fallbackPrompt.push("");
|
|
13100
|
+
fallbackPrompt.push("Cruise can be resumed manually with `reap cruise <N>` once the concern is resolved.");
|
|
13101
|
+
fallbackPrompt.push(...evaluatorSection);
|
|
13102
|
+
emitOutput({
|
|
13103
|
+
status: "prompt",
|
|
13104
|
+
command: "completion",
|
|
13105
|
+
phase: "fitness",
|
|
13106
|
+
completed: ["gate", "reflect", "cruise-aborted"],
|
|
13107
|
+
context: {
|
|
13108
|
+
id: s.id,
|
|
13109
|
+
goal: s.goal,
|
|
13110
|
+
cruiseMode: false,
|
|
13111
|
+
cruiseAborted: true,
|
|
13112
|
+
previousCruiseCount: config.cruiseCount,
|
|
13113
|
+
evaluatorConcerns: s.evaluatorConcerns,
|
|
13114
|
+
evaluator: evaluatorEnabled ? { enabled: true, prompt: fitnessEvaluatorPrompt } : { enabled: false }
|
|
13115
|
+
},
|
|
13116
|
+
prompt: fallbackPrompt.join(`
|
|
13117
|
+
`),
|
|
13118
|
+
nextCommand: "reap run completion --phase fitness"
|
|
13119
|
+
});
|
|
13120
|
+
}
|
|
12676
13121
|
if (cruise) {
|
|
13122
|
+
const cruisePrompt = [
|
|
13123
|
+
"## Completion — Fitness Phase (Cruise Mode)",
|
|
13124
|
+
"",
|
|
13125
|
+
`Cruise: ${config.cruiseCount}`,
|
|
13126
|
+
"",
|
|
13127
|
+
"### Self-Assessment (not self-fitness, but metacognition):",
|
|
13128
|
+
"1. Did this generation proceed as expected?",
|
|
13129
|
+
"2. Are there uncertain areas or risks?",
|
|
13130
|
+
"3. Are there items that need human confirmation?",
|
|
13131
|
+
"",
|
|
13132
|
+
'High confidence → auto-proceed: reap run completion --phase fitness --feedback "self-assessment: OK"',
|
|
13133
|
+
"Uncertain/risky → stop cruise and request human feedback"
|
|
13134
|
+
];
|
|
13135
|
+
cruisePrompt.push(...priorConcernsSection);
|
|
13136
|
+
cruisePrompt.push(...evaluatorSection);
|
|
12677
13137
|
emitOutput({
|
|
12678
13138
|
status: "prompt",
|
|
12679
13139
|
command: "completion",
|
|
12680
13140
|
phase: "fitness",
|
|
12681
13141
|
completed: ["gate", "reflect"],
|
|
12682
|
-
context: {
|
|
12683
|
-
|
|
12684
|
-
|
|
12685
|
-
|
|
12686
|
-
|
|
12687
|
-
|
|
12688
|
-
|
|
12689
|
-
|
|
12690
|
-
|
|
12691
|
-
"3. Are there items that need human confirmation?",
|
|
12692
|
-
"",
|
|
12693
|
-
'High confidence → auto-proceed: reap run completion --phase fitness --feedback "self-assessment: OK"',
|
|
12694
|
-
"Uncertain/risky → stop cruise and request human feedback"
|
|
12695
|
-
].join(`
|
|
13142
|
+
context: {
|
|
13143
|
+
id: s.id,
|
|
13144
|
+
goal: s.goal,
|
|
13145
|
+
cruiseMode: true,
|
|
13146
|
+
cruiseCount: config.cruiseCount,
|
|
13147
|
+
evaluatorConcerns: s.evaluatorConcerns ?? [],
|
|
13148
|
+
evaluator: evaluatorEnabled ? { enabled: true, prompt: fitnessEvaluatorPrompt } : { enabled: false }
|
|
13149
|
+
},
|
|
13150
|
+
prompt: cruisePrompt.join(`
|
|
12696
13151
|
`),
|
|
12697
13152
|
nextCommand: "reap run completion --phase fitness"
|
|
12698
13153
|
});
|
|
12699
13154
|
} else {
|
|
13155
|
+
const supervisedPrompt = [
|
|
13156
|
+
"## Completion — Fitness Phase",
|
|
13157
|
+
"",
|
|
13158
|
+
"Collect feedback from the human.",
|
|
13159
|
+
"",
|
|
13160
|
+
"Present to the human:",
|
|
13161
|
+
"1. Summary of what was done in this generation",
|
|
13162
|
+
"2. What went well / areas for improvement",
|
|
13163
|
+
"3. Suggested next direction",
|
|
13164
|
+
"",
|
|
13165
|
+
'Submit: reap run completion --phase fitness --feedback "human feedback here"'
|
|
13166
|
+
];
|
|
13167
|
+
supervisedPrompt.push(...priorConcernsSection);
|
|
13168
|
+
supervisedPrompt.push(...evaluatorSection);
|
|
12700
13169
|
emitOutput({
|
|
12701
13170
|
status: "prompt",
|
|
12702
13171
|
command: "completion",
|
|
12703
13172
|
phase: "fitness",
|
|
12704
13173
|
completed: ["gate", "reflect"],
|
|
12705
|
-
context: {
|
|
12706
|
-
|
|
12707
|
-
|
|
12708
|
-
|
|
12709
|
-
|
|
12710
|
-
|
|
12711
|
-
|
|
12712
|
-
|
|
12713
|
-
"2. What went well / areas for improvement",
|
|
12714
|
-
"3. Suggested next direction",
|
|
12715
|
-
"",
|
|
12716
|
-
'Submit: reap run completion --phase fitness --feedback "human feedback here"'
|
|
12717
|
-
].join(`
|
|
13174
|
+
context: {
|
|
13175
|
+
id: s.id,
|
|
13176
|
+
goal: s.goal,
|
|
13177
|
+
cruiseMode: false,
|
|
13178
|
+
evaluatorConcerns: s.evaluatorConcerns ?? [],
|
|
13179
|
+
evaluator: evaluatorEnabled ? { enabled: true, prompt: fitnessEvaluatorPrompt } : { enabled: false }
|
|
13180
|
+
},
|
|
13181
|
+
prompt: supervisedPrompt.join(`
|
|
12718
13182
|
`),
|
|
12719
13183
|
nextCommand: "reap run completion --phase fitness"
|
|
12720
13184
|
});
|
|
@@ -12726,7 +13190,7 @@ async function execute12(paths, phase, feedback) {
|
|
|
12726
13190
|
const fitnessFeedback = s.fitnessFeedback;
|
|
12727
13191
|
const visionGoals = await readTextFile(paths.visionGoals);
|
|
12728
13192
|
const configContent = await readTextFile(paths.config);
|
|
12729
|
-
const config = configContent ?
|
|
13193
|
+
const config = configContent ? import_yaml19.default.parse(configContent) : null;
|
|
12730
13194
|
const maturity = detectMaturity(s.type, config?.cruiseCount);
|
|
12731
13195
|
const generationCount = await gm.countLineage();
|
|
12732
13196
|
setTransitionNonces(s, "completion:adapt");
|
|
@@ -12820,9 +13284,9 @@ async function execute12(paths, phase, feedback) {
|
|
|
12820
13284
|
verifyTransition("completion", s, "completion:commit");
|
|
12821
13285
|
if (feedback) {
|
|
12822
13286
|
const filenames = feedback.split(",").map((f) => f.trim()).filter(Boolean);
|
|
12823
|
-
const { join:
|
|
13287
|
+
const { join: join18 } = await import("path");
|
|
12824
13288
|
for (const filename of filenames) {
|
|
12825
|
-
await consumeBacklog(
|
|
13289
|
+
await consumeBacklog(join18(paths.backlog, filename), s.id);
|
|
12826
13290
|
}
|
|
12827
13291
|
}
|
|
12828
13292
|
const fitnessFeedback = s.fitnessFeedback;
|
|
@@ -12838,8 +13302,12 @@ async function execute12(paths, phase, feedback) {
|
|
|
12838
13302
|
const commitHash = gitCommitAll(paths.root, commitMsg);
|
|
12839
13303
|
const completionEvent = isMerge ? "onMergeCompleted" : "onLifeCompleted";
|
|
12840
13304
|
await executeHooks(paths.hooks, completionEvent, paths.root).catch(() => {});
|
|
12841
|
-
const
|
|
12842
|
-
|
|
13305
|
+
const completionConfigContent = await readTextFile(paths.config);
|
|
13306
|
+
const completionConfig = completionConfigContent ? import_yaml19.default.parse(completionConfigContent) : null;
|
|
13307
|
+
if (completionConfig?.daemon === true) {
|
|
13308
|
+
const { triggerIndexing: triggerIndexing2 } = await Promise.resolve().then(() => (init_lifecycle(), exports_lifecycle));
|
|
13309
|
+
await triggerIndexing2(paths.root);
|
|
13310
|
+
}
|
|
12843
13311
|
const cruiseStillActive = await advanceCruise(paths.config).catch(() => false);
|
|
12844
13312
|
emitOutput({
|
|
12845
13313
|
status: "ok",
|
|
@@ -12859,7 +13327,7 @@ async function execute12(paths, phase, feedback) {
|
|
|
12859
13327
|
}
|
|
12860
13328
|
|
|
12861
13329
|
// src/cli/commands/run/evolve.ts
|
|
12862
|
-
var
|
|
13330
|
+
var import_yaml20 = __toESM(require_dist(), 1);
|
|
12863
13331
|
import { readdir as readdir14 } from "fs/promises";
|
|
12864
13332
|
init_fs();
|
|
12865
13333
|
async function collectClarityInput(paths, generationType) {
|
|
@@ -12892,11 +13360,11 @@ async function collectClarityInput(paths, generationType) {
|
|
|
12892
13360
|
hasMemory
|
|
12893
13361
|
};
|
|
12894
13362
|
}
|
|
12895
|
-
async function
|
|
13363
|
+
async function execute14(paths, _phase) {
|
|
12896
13364
|
const gm = new GenerationManager(paths);
|
|
12897
13365
|
const state = await gm.current();
|
|
12898
13366
|
const configContent = await readTextFile(paths.config);
|
|
12899
|
-
const config = configContent ?
|
|
13367
|
+
const config = configContent ? import_yaml20.default.parse(configContent) : null;
|
|
12900
13368
|
const autoSubagent = config?.autoSubagent ?? true;
|
|
12901
13369
|
const cruise = config ? parseCruiseCount(config) : null;
|
|
12902
13370
|
const generationType = state?.type ?? "normal";
|
|
@@ -12975,7 +13443,7 @@ async function execute13(paths, _phase) {
|
|
|
12975
13443
|
}
|
|
12976
13444
|
|
|
12977
13445
|
// src/cli/commands/run/back.ts
|
|
12978
|
-
async function
|
|
13446
|
+
async function execute15(paths, _phase, reason) {
|
|
12979
13447
|
const gm = new GenerationManager(paths);
|
|
12980
13448
|
const state = await gm.current();
|
|
12981
13449
|
if (!state)
|
|
@@ -13022,7 +13490,7 @@ async function execute14(paths, _phase, reason) {
|
|
|
13022
13490
|
}
|
|
13023
13491
|
|
|
13024
13492
|
// src/cli/commands/run/next.ts
|
|
13025
|
-
async function
|
|
13493
|
+
async function execute16(paths) {
|
|
13026
13494
|
const gm = new GenerationManager(paths);
|
|
13027
13495
|
const state = await gm.current();
|
|
13028
13496
|
if (!state)
|
|
@@ -13044,7 +13512,7 @@ async function execute15(paths) {
|
|
|
13044
13512
|
|
|
13045
13513
|
// src/cli/commands/run/abort.ts
|
|
13046
13514
|
import { readdir as readdir15, rm as rm5 } from "fs/promises";
|
|
13047
|
-
import { join as
|
|
13515
|
+
import { join as join18 } from "path";
|
|
13048
13516
|
init_fs();
|
|
13049
13517
|
function parseExtra(extra) {
|
|
13050
13518
|
if (!extra)
|
|
@@ -13055,7 +13523,7 @@ function parseExtra(extra) {
|
|
|
13055
13523
|
return {};
|
|
13056
13524
|
}
|
|
13057
13525
|
}
|
|
13058
|
-
async function
|
|
13526
|
+
async function execute17(paths, phase, extra) {
|
|
13059
13527
|
const gm = new GenerationManager(paths);
|
|
13060
13528
|
const state = await gm.current();
|
|
13061
13529
|
if (!state)
|
|
@@ -13120,7 +13588,7 @@ createdAt: ${new Date().toISOString()}
|
|
|
13120
13588
|
## Progress
|
|
13121
13589
|
<!-- Progress from the aborted generation can be referenced here -->
|
|
13122
13590
|
`;
|
|
13123
|
-
await writeTextFile(
|
|
13591
|
+
await writeTextFile(join18(paths.backlog, filename), content);
|
|
13124
13592
|
savedBacklogFile = filename;
|
|
13125
13593
|
}
|
|
13126
13594
|
const revertedCount = await revertBacklogConsumed(paths.backlog, id);
|
|
@@ -13128,7 +13596,7 @@ createdAt: ${new Date().toISOString()}
|
|
|
13128
13596
|
for (const entry of lifeEntries) {
|
|
13129
13597
|
if (entry === "backlog")
|
|
13130
13598
|
continue;
|
|
13131
|
-
await rm5(
|
|
13599
|
+
await rm5(join18(paths.life, entry), { recursive: true, force: true });
|
|
13132
13600
|
}
|
|
13133
13601
|
emitOutput({
|
|
13134
13602
|
status: "ok",
|
|
@@ -13149,7 +13617,7 @@ createdAt: ${new Date().toISOString()}
|
|
|
13149
13617
|
}
|
|
13150
13618
|
|
|
13151
13619
|
// src/cli/commands/run/early-close.ts
|
|
13152
|
-
import { join as
|
|
13620
|
+
import { join as join19 } from "path";
|
|
13153
13621
|
init_fs();
|
|
13154
13622
|
function parseExtra2(extra) {
|
|
13155
13623
|
if (!extra)
|
|
@@ -13162,7 +13630,7 @@ function parseExtra2(extra) {
|
|
|
13162
13630
|
}
|
|
13163
13631
|
var ALLOWED_STAGES = new Set(["implementation", "validation"]);
|
|
13164
13632
|
var ALLOWED_SOURCE_ACTIONS = new Set(["hold", "stash", "none"]);
|
|
13165
|
-
async function
|
|
13633
|
+
async function execute18(paths, phase, extra) {
|
|
13166
13634
|
const gm = new GenerationManager(paths);
|
|
13167
13635
|
const state = await gm.current();
|
|
13168
13636
|
if (!state)
|
|
@@ -13288,7 +13756,7 @@ async function execute17(paths, phase, extra) {
|
|
|
13288
13756
|
message: [
|
|
13289
13757
|
`Generation ${s.id} early-closed at stage '${s.stage}' (reason: ${reason}).`,
|
|
13290
13758
|
`Archived: ${archiveDir}`,
|
|
13291
|
-
deferredBacklogFile ? `Deferred backlog: ${
|
|
13759
|
+
deferredBacklogFile ? `Deferred backlog: ${join19(paths.backlog, deferredBacklogFile)} (${deferredTaskCount} task(s))` : `Defer skipped — ${deferredTaskCount} unchecked task(s) found but not carried over.`,
|
|
13292
13760
|
commitHash ? `Commit: ${commitHash}` : "Commit your changes manually."
|
|
13293
13761
|
].join(" ")
|
|
13294
13762
|
});
|
|
@@ -13297,7 +13765,7 @@ async function execute17(paths, phase, extra) {
|
|
|
13297
13765
|
}
|
|
13298
13766
|
|
|
13299
13767
|
// src/cli/commands/run/detect.ts
|
|
13300
|
-
async function
|
|
13768
|
+
async function execute19(paths, phase) {
|
|
13301
13769
|
const gm = new GenerationManager(paths);
|
|
13302
13770
|
const state = await gm.current();
|
|
13303
13771
|
if (!state)
|
|
@@ -13383,7 +13851,7 @@ async function execute18(paths, phase) {
|
|
|
13383
13851
|
|
|
13384
13852
|
// src/cli/commands/run/mate.ts
|
|
13385
13853
|
init_fs();
|
|
13386
|
-
async function
|
|
13854
|
+
async function execute20(paths, phase) {
|
|
13387
13855
|
const gm = new GenerationManager(paths);
|
|
13388
13856
|
const state = await gm.current();
|
|
13389
13857
|
if (!state)
|
|
@@ -13481,7 +13949,7 @@ async function execute19(paths, phase) {
|
|
|
13481
13949
|
|
|
13482
13950
|
// src/cli/commands/run/merge.ts
|
|
13483
13951
|
init_fs();
|
|
13484
|
-
async function
|
|
13952
|
+
async function execute21(paths, phase) {
|
|
13485
13953
|
const gm = new GenerationManager(paths);
|
|
13486
13954
|
const state = await gm.current();
|
|
13487
13955
|
if (!state)
|
|
@@ -13554,7 +14022,7 @@ async function execute20(paths, phase) {
|
|
|
13554
14022
|
|
|
13555
14023
|
// src/cli/commands/run/reconcile.ts
|
|
13556
14024
|
init_fs();
|
|
13557
|
-
async function
|
|
14025
|
+
async function execute22(paths, phase) {
|
|
13558
14026
|
const gm = new GenerationManager(paths);
|
|
13559
14027
|
const state = await gm.current();
|
|
13560
14028
|
if (!state)
|
|
@@ -13638,7 +14106,7 @@ async function execute21(paths, phase) {
|
|
|
13638
14106
|
}
|
|
13639
14107
|
|
|
13640
14108
|
// src/cli/commands/run/push.ts
|
|
13641
|
-
async function
|
|
14109
|
+
async function execute23(paths) {
|
|
13642
14110
|
const gm = new GenerationManager(paths);
|
|
13643
14111
|
const state = await gm.current();
|
|
13644
14112
|
if (state) {
|
|
@@ -13672,7 +14140,7 @@ async function execute22(paths) {
|
|
|
13672
14140
|
}
|
|
13673
14141
|
|
|
13674
14142
|
// src/cli/commands/run/pull.ts
|
|
13675
|
-
async function
|
|
14143
|
+
async function execute24(paths, phase) {
|
|
13676
14144
|
if (!isGitRepo(paths.root)) {
|
|
13677
14145
|
emitError("pull", "Not a git repository.");
|
|
13678
14146
|
}
|
|
@@ -13825,7 +14293,7 @@ Consider using /reap.merge to start a merge lifecycle if needed.` : "No unmerged
|
|
|
13825
14293
|
}
|
|
13826
14294
|
|
|
13827
14295
|
// src/cli/commands/run/knowledge.ts
|
|
13828
|
-
async function
|
|
14296
|
+
async function execute25(paths, _phase, extra) {
|
|
13829
14297
|
const subcommand = extra ?? "";
|
|
13830
14298
|
if (subcommand === "reload") {
|
|
13831
14299
|
emitOutput({
|
|
@@ -13972,19 +14440,19 @@ async function execute24(paths, _phase, extra) {
|
|
|
13972
14440
|
|
|
13973
14441
|
// src/cli/commands/run/report.ts
|
|
13974
14442
|
init_fs();
|
|
13975
|
-
var
|
|
13976
|
-
async function
|
|
14443
|
+
var import_yaml21 = __toESM(require_dist(), 1);
|
|
14444
|
+
async function execute26(paths, _phase) {
|
|
13977
14445
|
let state = null;
|
|
13978
14446
|
try {
|
|
13979
14447
|
const raw = await readTextFile(paths.current);
|
|
13980
14448
|
if (raw)
|
|
13981
|
-
state =
|
|
14449
|
+
state = import_yaml21.default.parse(raw);
|
|
13982
14450
|
} catch {}
|
|
13983
14451
|
let projectName = "unknown";
|
|
13984
14452
|
try {
|
|
13985
14453
|
const raw = await readTextFile(paths.config);
|
|
13986
14454
|
if (raw) {
|
|
13987
|
-
const config =
|
|
14455
|
+
const config = import_yaml21.default.parse(raw);
|
|
13988
14456
|
projectName = config.project ?? "unknown";
|
|
13989
14457
|
}
|
|
13990
14458
|
} catch {}
|
|
@@ -14039,28 +14507,28 @@ async function execute25(paths, _phase) {
|
|
|
14039
14507
|
|
|
14040
14508
|
// src/cli/commands/run/index.ts
|
|
14041
14509
|
var STAGE_HANDLERS = {
|
|
14042
|
-
learning:
|
|
14043
|
-
planning:
|
|
14044
|
-
implementation:
|
|
14045
|
-
validation:
|
|
14046
|
-
completion:
|
|
14047
|
-
evolve:
|
|
14048
|
-
back:
|
|
14049
|
-
next:
|
|
14050
|
-
abort:
|
|
14051
|
-
"early-close":
|
|
14052
|
-
detect:
|
|
14053
|
-
mate:
|
|
14054
|
-
merge:
|
|
14055
|
-
reconcile:
|
|
14056
|
-
push:
|
|
14057
|
-
pull:
|
|
14058
|
-
knowledge:
|
|
14059
|
-
report:
|
|
14510
|
+
learning: execute9,
|
|
14511
|
+
planning: execute10,
|
|
14512
|
+
implementation: execute11,
|
|
14513
|
+
validation: execute12,
|
|
14514
|
+
completion: execute13,
|
|
14515
|
+
evolve: execute14,
|
|
14516
|
+
back: execute15,
|
|
14517
|
+
next: execute16,
|
|
14518
|
+
abort: execute17,
|
|
14519
|
+
"early-close": execute18,
|
|
14520
|
+
detect: execute19,
|
|
14521
|
+
mate: execute20,
|
|
14522
|
+
merge: execute21,
|
|
14523
|
+
reconcile: execute22,
|
|
14524
|
+
push: execute23,
|
|
14525
|
+
pull: execute24,
|
|
14526
|
+
knowledge: execute25,
|
|
14527
|
+
report: execute26
|
|
14060
14528
|
};
|
|
14061
|
-
async function
|
|
14529
|
+
async function execute27(stage, options) {
|
|
14062
14530
|
if (stage === "start") {
|
|
14063
|
-
await
|
|
14531
|
+
await execute8(options.phase, options.goal, options.type, options.parents, options.backlog);
|
|
14064
14532
|
return;
|
|
14065
14533
|
}
|
|
14066
14534
|
const paths = createPaths(process.cwd());
|
|
@@ -14081,13 +14549,16 @@ async function execute26(stage, options) {
|
|
|
14081
14549
|
if (stage === "early-close") {
|
|
14082
14550
|
extra = JSON.stringify({ reason: options.reason, sourceAction: options.sourceAction, deferTasks: options.deferTasks });
|
|
14083
14551
|
}
|
|
14552
|
+
if (stage === "validation" && options.phase === "report-evaluator") {
|
|
14553
|
+
extra = JSON.stringify({ severity: options.severity, summary: options.summary });
|
|
14554
|
+
}
|
|
14084
14555
|
try {
|
|
14085
14556
|
await handler(paths, options.phase, extra);
|
|
14086
14557
|
} catch (err) {
|
|
14087
14558
|
try {
|
|
14088
14559
|
const configContent = await readTextFile(paths.config);
|
|
14089
14560
|
if (configContent) {
|
|
14090
|
-
const config =
|
|
14561
|
+
const config = import_yaml22.default.parse(configContent);
|
|
14091
14562
|
if (config.autoIssueReport !== false) {
|
|
14092
14563
|
const cmd = `reap run ${stage}${options.phase ? ` --phase ${options.phase}` : ""}`;
|
|
14093
14564
|
autoReport(cmd, err);
|
|
@@ -14122,7 +14593,7 @@ async function makeBacklog(paths, options) {
|
|
|
14122
14593
|
}
|
|
14123
14594
|
|
|
14124
14595
|
// src/cli/commands/make/hook.ts
|
|
14125
|
-
import { join as
|
|
14596
|
+
import { join as join20 } from "path";
|
|
14126
14597
|
import { chmod as chmod2 } from "fs/promises";
|
|
14127
14598
|
init_fs();
|
|
14128
14599
|
var VALID_EVENTS = [
|
|
@@ -14160,7 +14631,7 @@ ${VALID_EVENTS.join(`
|
|
|
14160
14631
|
emitError("make", "Invalid --type. Use 'sh' or 'md'.");
|
|
14161
14632
|
}
|
|
14162
14633
|
const filename = `${event}.${name}.${type}`;
|
|
14163
|
-
const filePath =
|
|
14634
|
+
const filePath = join20(paths.hooks, filename);
|
|
14164
14635
|
await ensureDir(paths.hooks);
|
|
14165
14636
|
if (await fileExists(filePath)) {
|
|
14166
14637
|
emitError("make", `Hook already exists: ${filename}`);
|
|
@@ -14195,7 +14666,7 @@ order: ${order}
|
|
|
14195
14666
|
|
|
14196
14667
|
// src/cli/commands/make/index.ts
|
|
14197
14668
|
var RESOURCES = ["backlog", "hook"];
|
|
14198
|
-
async function
|
|
14669
|
+
async function execute28(resource, options) {
|
|
14199
14670
|
const paths = createPaths(process.cwd());
|
|
14200
14671
|
if (await detectV15(paths)) {
|
|
14201
14672
|
emitError("make", "This project uses REAP v0.15 structure. Run '/reap.update' to upgrade to v0.16.");
|
|
@@ -14211,7 +14682,7 @@ async function execute27(resource, options) {
|
|
|
14211
14682
|
|
|
14212
14683
|
// src/cli/commands/cruise.ts
|
|
14213
14684
|
init_integrity();
|
|
14214
|
-
async function
|
|
14685
|
+
async function execute29(count) {
|
|
14215
14686
|
const n = parseInt(count);
|
|
14216
14687
|
if (isNaN(n) || n < 1) {
|
|
14217
14688
|
emitError("cruise", "Count must be a positive integer.");
|
|
@@ -14230,34 +14701,34 @@ async function execute28(count) {
|
|
|
14230
14701
|
}
|
|
14231
14702
|
|
|
14232
14703
|
// src/cli/commands/install-skills.ts
|
|
14233
|
-
var
|
|
14704
|
+
var import_yaml23 = __toESM(require_dist(), 1);
|
|
14234
14705
|
|
|
14235
14706
|
// src/adapters/claude-code/install.ts
|
|
14236
14707
|
init_fs();
|
|
14237
14708
|
import { readdir as readdir16, cp as cp2, unlink as unlink2, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
14238
|
-
import { join as
|
|
14709
|
+
import { join as join21, dirname as dirname6 } from "path";
|
|
14239
14710
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
14240
14711
|
import { homedir as homedir4 } from "os";
|
|
14241
14712
|
var __dirname2 = dirname6(fileURLToPath4(import.meta.url));
|
|
14242
|
-
var SKILLS_DIR = __dirname2.includes("dist") ?
|
|
14713
|
+
var SKILLS_DIR = __dirname2.includes("dist") ? join21(__dirname2, "..", "adapters", "claude-code", "skills") : join21(__dirname2, "skills");
|
|
14243
14714
|
var SKILL_PATTERN = /^reap\..+\.md$/;
|
|
14244
14715
|
async function cleanupStaleSkills(targetDir) {
|
|
14245
14716
|
const files = await readdir16(targetDir);
|
|
14246
14717
|
const staleFiles = files.filter((f) => SKILL_PATTERN.test(f));
|
|
14247
14718
|
for (const file of staleFiles) {
|
|
14248
|
-
await unlink2(
|
|
14719
|
+
await unlink2(join21(targetDir, file));
|
|
14249
14720
|
}
|
|
14250
14721
|
return staleFiles;
|
|
14251
14722
|
}
|
|
14252
14723
|
async function installSlashCommandsOnly() {
|
|
14253
|
-
const targetDir =
|
|
14724
|
+
const targetDir = join21(homedir4(), ".claude", "commands");
|
|
14254
14725
|
await ensureDir(targetDir);
|
|
14255
14726
|
const cleaned = await cleanupStaleSkills(targetDir);
|
|
14256
14727
|
const files = await readdir16(SKILLS_DIR);
|
|
14257
14728
|
const mdFiles = files.filter((f) => f.endsWith(".md"));
|
|
14258
14729
|
let installed = 0;
|
|
14259
14730
|
for (const file of mdFiles) {
|
|
14260
|
-
await cp2(
|
|
14731
|
+
await cp2(join21(SKILLS_DIR, file), join21(targetDir, file));
|
|
14261
14732
|
installed++;
|
|
14262
14733
|
}
|
|
14263
14734
|
return { cleaned, installed, files: mdFiles, targetDir };
|
|
@@ -14280,30 +14751,47 @@ async function installSkills(_projectRoot) {
|
|
|
14280
14751
|
message: `Cleaned ${cleaned.length} stale skills, installed ${installed} skill files to ${targetDir}`
|
|
14281
14752
|
});
|
|
14282
14753
|
}
|
|
14283
|
-
|
|
14284
|
-
|
|
14285
|
-
|
|
14286
|
-
|
|
14754
|
+
var AGENT_PATTERN = /^reap-.+\.md$/;
|
|
14755
|
+
function agentsTemplateDir() {
|
|
14756
|
+
return __dirname2.includes("dist") ? join21(__dirname2, "..", "templates", "agents") : join21(__dirname2, "..", "..", "templates", "agents");
|
|
14757
|
+
}
|
|
14758
|
+
async function installAgents(home = homedir4()) {
|
|
14759
|
+
const targetDir = join21(home, ".claude", "agents");
|
|
14760
|
+
await ensureDir(targetDir);
|
|
14761
|
+
let cleaned = [];
|
|
14287
14762
|
try {
|
|
14288
|
-
const
|
|
14289
|
-
|
|
14290
|
-
|
|
14291
|
-
|
|
14292
|
-
|
|
14763
|
+
const existing = await readdir16(targetDir);
|
|
14764
|
+
cleaned = existing.filter((f) => AGENT_PATTERN.test(f));
|
|
14765
|
+
for (const file of cleaned) {
|
|
14766
|
+
await unlink2(join21(targetDir, file));
|
|
14767
|
+
}
|
|
14768
|
+
} catch {}
|
|
14769
|
+
let installed = 0;
|
|
14770
|
+
const files = [];
|
|
14771
|
+
const templateDir = agentsTemplateDir();
|
|
14772
|
+
try {
|
|
14773
|
+
const sources = await readdir16(templateDir);
|
|
14774
|
+
for (const file of sources) {
|
|
14775
|
+
if (!file.endsWith(".md"))
|
|
14776
|
+
continue;
|
|
14777
|
+
await cp2(join21(templateDir, file), join21(targetDir, file));
|
|
14778
|
+
files.push(file);
|
|
14779
|
+
installed++;
|
|
14293
14780
|
}
|
|
14294
14781
|
} catch {}
|
|
14782
|
+
return { cleaned, installed, files, targetDir };
|
|
14295
14783
|
}
|
|
14296
14784
|
async function installReapGuide() {
|
|
14297
|
-
const reapHome =
|
|
14785
|
+
const reapHome = join21(homedir4(), ".reap");
|
|
14298
14786
|
await ensureDir(reapHome);
|
|
14299
|
-
const templateDir = __dirname2.includes("dist") ?
|
|
14300
|
-
const src =
|
|
14787
|
+
const templateDir = __dirname2.includes("dist") ? join21(__dirname2, "..", "templates") : join21(__dirname2, "..", "..", "templates");
|
|
14788
|
+
const src = join21(templateDir, "reap-guide.md");
|
|
14301
14789
|
if (await fileExists(src)) {
|
|
14302
|
-
await cp2(src,
|
|
14790
|
+
await cp2(src, join21(reapHome, "reap-guide.md"));
|
|
14303
14791
|
}
|
|
14304
14792
|
}
|
|
14305
14793
|
async function registerSessionHooks() {
|
|
14306
|
-
const settingsPath =
|
|
14794
|
+
const settingsPath = join21(homedir4(), ".claude", "settings.json");
|
|
14307
14795
|
const requiredHooks = [
|
|
14308
14796
|
{ command: "reap check-version 2>/dev/null || true", marker: "reap check-version" },
|
|
14309
14797
|
{ command: "reap load-context 2>/dev/null || true", marker: "reap load-context" }
|
|
@@ -14354,6 +14842,7 @@ var claudeCodeAdapter = {
|
|
|
14354
14842
|
},
|
|
14355
14843
|
async registerSessionIntegration(_projectRoot) {
|
|
14356
14844
|
await installSlashCommandsOnly();
|
|
14845
|
+
await installAgents();
|
|
14357
14846
|
await registerSessionHooks();
|
|
14358
14847
|
}
|
|
14359
14848
|
};
|
|
@@ -14361,13 +14850,13 @@ var claudeCodeAdapter = {
|
|
|
14361
14850
|
// src/adapters/opencode/install.ts
|
|
14362
14851
|
init_fs();
|
|
14363
14852
|
import { cp as cp3, readFile as readFile4, writeFile as writeFile4, readdir as readdir17, unlink as unlink3 } from "fs/promises";
|
|
14364
|
-
import { join as
|
|
14853
|
+
import { join as join22, dirname as dirname7 } from "path";
|
|
14365
14854
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
14366
14855
|
import { homedir as homedir5 } from "os";
|
|
14367
14856
|
import { createHash as createHash4 } from "crypto";
|
|
14368
14857
|
var __dirname3 = dirname7(fileURLToPath5(import.meta.url));
|
|
14369
14858
|
function assetPath(...segments) {
|
|
14370
|
-
return __dirname3.includes("dist") ?
|
|
14859
|
+
return __dirname3.includes("dist") ? join22(__dirname3, "..", "adapters", "opencode", ...segments) : join22(__dirname3, ...segments);
|
|
14371
14860
|
}
|
|
14372
14861
|
var PLUGIN_FILENAME = "reap-plugin.ts";
|
|
14373
14862
|
var PLUGIN_SRC = assetPath("plugin", PLUGIN_FILENAME);
|
|
@@ -14425,7 +14914,7 @@ async function ensureAgentsMd(projectRoot, projectName) {
|
|
|
14425
14914
|
const inner = stripMarkers2(rawTemplate);
|
|
14426
14915
|
const wrapped = wrapWithMarkers2(inner);
|
|
14427
14916
|
const newHash = computeSectionHash2(inner);
|
|
14428
|
-
const agentsPath =
|
|
14917
|
+
const agentsPath = join22(projectRoot, "AGENTS.md");
|
|
14429
14918
|
const existing = await readTextFile(agentsPath);
|
|
14430
14919
|
if (!existing) {
|
|
14431
14920
|
await writeTextFile(agentsPath, `# ${projectName}
|
|
@@ -14472,7 +14961,7 @@ function stripMarkers2(content) {
|
|
|
14472
14961
|
return content.slice(afterStart + 1, endIdx).trimEnd();
|
|
14473
14962
|
}
|
|
14474
14963
|
async function ensureOpencodeJson(projectRoot) {
|
|
14475
|
-
const path =
|
|
14964
|
+
const path = join22(projectRoot, "opencode.json");
|
|
14476
14965
|
const existed = await fileExists(path);
|
|
14477
14966
|
let cfg = {};
|
|
14478
14967
|
if (existed) {
|
|
@@ -14511,27 +15000,27 @@ async function ensureOpencodeJson(projectRoot) {
|
|
|
14511
15000
|
return existed ? "updated" : "created";
|
|
14512
15001
|
}
|
|
14513
15002
|
async function installPluginFile(projectRoot) {
|
|
14514
|
-
const pluginsDir =
|
|
15003
|
+
const pluginsDir = join22(projectRoot, ".opencode", "plugins");
|
|
14515
15004
|
await ensureDir(pluginsDir);
|
|
14516
15005
|
if (await fileExists(PLUGIN_SRC)) {
|
|
14517
|
-
await cp3(PLUGIN_SRC,
|
|
15006
|
+
await cp3(PLUGIN_SRC, join22(pluginsDir, PLUGIN_FILENAME));
|
|
14518
15007
|
}
|
|
14519
15008
|
}
|
|
14520
15009
|
async function installReapGuide2() {
|
|
14521
|
-
const reapHome =
|
|
15010
|
+
const reapHome = join22(homedir5(), ".reap");
|
|
14522
15011
|
await ensureDir(reapHome);
|
|
14523
|
-
const templateDir = __dirname3.includes("dist") ?
|
|
14524
|
-
const src =
|
|
15012
|
+
const templateDir = __dirname3.includes("dist") ? join22(__dirname3, "..", "..", "templates") : join22(__dirname3, "..", "..", "templates");
|
|
15013
|
+
const src = join22(templateDir, "reap-guide.md");
|
|
14525
15014
|
if (await fileExists(src)) {
|
|
14526
|
-
await cp3(src,
|
|
15015
|
+
await cp3(src, join22(reapHome, "reap-guide.md"));
|
|
14527
15016
|
}
|
|
14528
15017
|
}
|
|
14529
15018
|
var SLASH_COMMAND_PATTERN = /^reap\..+\.md$/;
|
|
14530
15019
|
function claudeCodeSkillsDir() {
|
|
14531
|
-
return __dirname3.includes("dist") ?
|
|
15020
|
+
return __dirname3.includes("dist") ? join22(__dirname3, "..", "adapters", "claude-code", "skills") : join22(__dirname3, "..", "claude-code", "skills");
|
|
14532
15021
|
}
|
|
14533
15022
|
function opencodeCommandsDir(home = homedir5()) {
|
|
14534
|
-
return
|
|
15023
|
+
return join22(home, ".config", "opencode", "commands");
|
|
14535
15024
|
}
|
|
14536
15025
|
async function installSlashCommands(home = homedir5()) {
|
|
14537
15026
|
const targetDir = opencodeCommandsDir(home);
|
|
@@ -14541,7 +15030,7 @@ async function installSlashCommands(home = homedir5()) {
|
|
|
14541
15030
|
const existing = await readdir17(targetDir);
|
|
14542
15031
|
for (const file of existing) {
|
|
14543
15032
|
if (SLASH_COMMAND_PATTERN.test(file)) {
|
|
14544
|
-
await unlink3(
|
|
15033
|
+
await unlink3(join22(targetDir, file));
|
|
14545
15034
|
cleaned++;
|
|
14546
15035
|
}
|
|
14547
15036
|
}
|
|
@@ -14553,7 +15042,40 @@ async function installSlashCommands(home = homedir5()) {
|
|
|
14553
15042
|
for (const file of sources) {
|
|
14554
15043
|
if (!file.endsWith(".md"))
|
|
14555
15044
|
continue;
|
|
14556
|
-
await cp3(
|
|
15045
|
+
await cp3(join22(srcDir, file), join22(targetDir, file));
|
|
15046
|
+
installed++;
|
|
15047
|
+
}
|
|
15048
|
+
} catch {}
|
|
15049
|
+
return { cleaned, installed, targetDir };
|
|
15050
|
+
}
|
|
15051
|
+
var AGENT_PATTERN2 = /^reap-.+\.md$/;
|
|
15052
|
+
function agentsTemplateDir2() {
|
|
15053
|
+
return __dirname3.includes("dist") ? join22(__dirname3, "..", "templates", "agents") : join22(__dirname3, "..", "..", "templates", "agents");
|
|
15054
|
+
}
|
|
15055
|
+
function opencodeAgentsDir(home = homedir5()) {
|
|
15056
|
+
return join22(home, ".config", "opencode", "agent");
|
|
15057
|
+
}
|
|
15058
|
+
async function installAgents2(home = homedir5()) {
|
|
15059
|
+
const targetDir = opencodeAgentsDir(home);
|
|
15060
|
+
await ensureDir(targetDir);
|
|
15061
|
+
let cleaned = 0;
|
|
15062
|
+
try {
|
|
15063
|
+
const existing = await readdir17(targetDir);
|
|
15064
|
+
for (const file of existing) {
|
|
15065
|
+
if (AGENT_PATTERN2.test(file)) {
|
|
15066
|
+
await unlink3(join22(targetDir, file));
|
|
15067
|
+
cleaned++;
|
|
15068
|
+
}
|
|
15069
|
+
}
|
|
15070
|
+
} catch {}
|
|
15071
|
+
let installed = 0;
|
|
15072
|
+
const srcDir = agentsTemplateDir2();
|
|
15073
|
+
try {
|
|
15074
|
+
const sources = await readdir17(srcDir);
|
|
15075
|
+
for (const file of sources) {
|
|
15076
|
+
if (!file.endsWith(".md"))
|
|
15077
|
+
continue;
|
|
15078
|
+
await cp3(join22(srcDir, file), join22(targetDir, file));
|
|
14557
15079
|
installed++;
|
|
14558
15080
|
}
|
|
14559
15081
|
} catch {}
|
|
@@ -14564,6 +15086,7 @@ async function installSkills2(projectRoot) {
|
|
|
14564
15086
|
const opencodeJsonAction = await ensureOpencodeJson(projectRoot);
|
|
14565
15087
|
await installReapGuide2();
|
|
14566
15088
|
const slashCommands = await installSlashCommands();
|
|
15089
|
+
const agents = await installAgents2();
|
|
14567
15090
|
emitOutput({
|
|
14568
15091
|
status: "ok",
|
|
14569
15092
|
command: "install-skills",
|
|
@@ -14571,25 +15094,32 @@ async function installSkills2(projectRoot) {
|
|
|
14571
15094
|
"install-plugin",
|
|
14572
15095
|
"ensure-opencode-json",
|
|
14573
15096
|
"install-reap-guide",
|
|
14574
|
-
"install-slash-commands"
|
|
15097
|
+
"install-slash-commands",
|
|
15098
|
+
"install-agents"
|
|
14575
15099
|
],
|
|
14576
15100
|
context: {
|
|
14577
15101
|
agentClient: "opencode",
|
|
14578
|
-
pluginPath:
|
|
15102
|
+
pluginPath: join22(projectRoot, ".opencode", "plugins", PLUGIN_FILENAME),
|
|
14579
15103
|
opencodeJson: opencodeJsonAction,
|
|
14580
15104
|
slashCommands: {
|
|
14581
15105
|
cleaned: slashCommands.cleaned,
|
|
14582
15106
|
installed: slashCommands.installed,
|
|
14583
15107
|
targetDir: slashCommands.targetDir
|
|
15108
|
+
},
|
|
15109
|
+
agents: {
|
|
15110
|
+
cleaned: agents.cleaned,
|
|
15111
|
+
installed: agents.installed,
|
|
15112
|
+
targetDir: agents.targetDir
|
|
14584
15113
|
}
|
|
14585
15114
|
},
|
|
14586
|
-
message: `OpenCode integration installed (opencode.json: ${opencodeJsonAction}, ` + `slash commands: ${slashCommands.installed} installed, ` + `${slashCommands.cleaned} cleaned).`
|
|
15115
|
+
message: `OpenCode integration installed (opencode.json: ${opencodeJsonAction}, ` + `slash commands: ${slashCommands.installed} installed, ` + `${slashCommands.cleaned} cleaned; ` + `agents: ${agents.installed} installed, ${agents.cleaned} cleaned).`
|
|
14587
15116
|
});
|
|
14588
15117
|
}
|
|
14589
15118
|
async function registerSessionIntegration(projectRoot) {
|
|
14590
15119
|
await installPluginFile(projectRoot);
|
|
14591
15120
|
await ensureOpencodeJson(projectRoot);
|
|
14592
15121
|
await installSlashCommands();
|
|
15122
|
+
await installAgents2();
|
|
14593
15123
|
}
|
|
14594
15124
|
|
|
14595
15125
|
// src/adapters/opencode/index.ts
|
|
@@ -14624,7 +15154,7 @@ function getAdapter(agentClient) {
|
|
|
14624
15154
|
|
|
14625
15155
|
// src/cli/commands/install-skills.ts
|
|
14626
15156
|
init_fs();
|
|
14627
|
-
async function
|
|
15157
|
+
async function execute30() {
|
|
14628
15158
|
const cwd = process.cwd();
|
|
14629
15159
|
const paths = createPaths(cwd);
|
|
14630
15160
|
let agentClient;
|
|
@@ -14632,7 +15162,7 @@ async function execute29() {
|
|
|
14632
15162
|
const raw = await readTextFile(paths.config);
|
|
14633
15163
|
if (raw) {
|
|
14634
15164
|
try {
|
|
14635
|
-
const cfg =
|
|
15165
|
+
const cfg = import_yaml23.default.parse(raw);
|
|
14636
15166
|
agentClient = cfg.agentClient;
|
|
14637
15167
|
} catch {}
|
|
14638
15168
|
}
|
|
@@ -14642,9 +15172,9 @@ async function execute29() {
|
|
|
14642
15172
|
}
|
|
14643
15173
|
|
|
14644
15174
|
// src/cli/commands/fix.ts
|
|
14645
|
-
var
|
|
15175
|
+
var import_yaml24 = __toESM(require_dist(), 1);
|
|
14646
15176
|
import { mkdir as mkdir3, stat as stat4 } from "fs/promises";
|
|
14647
|
-
import { join as
|
|
15177
|
+
import { join as join23, dirname as dirname8 } from "path";
|
|
14648
15178
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
14649
15179
|
import { homedir as homedir6 } from "os";
|
|
14650
15180
|
init_fs();
|
|
@@ -14694,7 +15224,7 @@ async function fixProject(projectRoot) {
|
|
|
14694
15224
|
if (currentContent !== null) {
|
|
14695
15225
|
if (currentContent.trim()) {
|
|
14696
15226
|
try {
|
|
14697
|
-
const state =
|
|
15227
|
+
const state = import_yaml24.default.parse(currentContent);
|
|
14698
15228
|
const allStages = [
|
|
14699
15229
|
...LIFECYCLE_STAGES,
|
|
14700
15230
|
...MERGE_STAGES
|
|
@@ -14726,13 +15256,13 @@ async function fixProject(projectRoot) {
|
|
|
14726
15256
|
issues.push(`genome/${gf.name} is missing. Run 'reap init --repair' to restore.`);
|
|
14727
15257
|
}
|
|
14728
15258
|
}
|
|
14729
|
-
const guidePath =
|
|
15259
|
+
const guidePath = join23(homedir6(), ".reap", "reap-guide.md");
|
|
14730
15260
|
if (!await fileExists(guidePath)) {
|
|
14731
15261
|
const __dir = dirname8(fileURLToPath6(import.meta.url));
|
|
14732
|
-
const srcGuide = await readTextFile(
|
|
15262
|
+
const srcGuide = await readTextFile(join23(__dir, "..", "templates", "reap-guide.md"));
|
|
14733
15263
|
if (srcGuide) {
|
|
14734
15264
|
const { ensureDir: ensDir } = await Promise.resolve().then(() => (init_fs(), exports_fs));
|
|
14735
|
-
await ensDir(
|
|
15265
|
+
await ensDir(join23(homedir6(), ".reap"));
|
|
14736
15266
|
await writeTextFile(guidePath, srcGuide);
|
|
14737
15267
|
fixed.push("Restored missing ~/.reap/reap-guide.md");
|
|
14738
15268
|
} else {
|
|
@@ -14761,7 +15291,7 @@ async function fixProject(projectRoot) {
|
|
|
14761
15291
|
{
|
|
14762
15292
|
const { ensureClaudeMd: ensureClaudeMd2 } = await Promise.resolve().then(() => (init_common(), exports_common));
|
|
14763
15293
|
const configContent = await readTextFile(paths.config);
|
|
14764
|
-
const projectName = configContent ?
|
|
15294
|
+
const projectName = configContent ? import_yaml24.default.parse(configContent)?.project ?? "my-project" : "my-project";
|
|
14765
15295
|
const action = await ensureClaudeMd2(paths.root, projectName);
|
|
14766
15296
|
if (action !== "skipped") {
|
|
14767
15297
|
fixed.push(`CLAUDE.md ${action} with REAP section`);
|
|
@@ -14769,7 +15299,7 @@ async function fixProject(projectRoot) {
|
|
|
14769
15299
|
}
|
|
14770
15300
|
return { issues, fixed };
|
|
14771
15301
|
}
|
|
14772
|
-
async function
|
|
15302
|
+
async function execute31(check) {
|
|
14773
15303
|
const root = process.cwd();
|
|
14774
15304
|
const paths = createPaths(root);
|
|
14775
15305
|
if (await detectV15(paths)) {
|
|
@@ -14810,9 +15340,9 @@ async function execute30(check) {
|
|
|
14810
15340
|
}
|
|
14811
15341
|
|
|
14812
15342
|
// src/cli/commands/destroy.ts
|
|
14813
|
-
var
|
|
15343
|
+
var import_yaml25 = __toESM(require_dist(), 1);
|
|
14814
15344
|
import { rm as rm6 } from "fs/promises";
|
|
14815
|
-
import { join as
|
|
15345
|
+
import { join as join24 } from "path";
|
|
14816
15346
|
init_fs();
|
|
14817
15347
|
init_integrity();
|
|
14818
15348
|
async function getProjectName(projectRoot) {
|
|
@@ -14821,7 +15351,7 @@ async function getProjectName(projectRoot) {
|
|
|
14821
15351
|
const content = await readTextFile(paths.config);
|
|
14822
15352
|
if (!content)
|
|
14823
15353
|
return null;
|
|
14824
|
-
const config =
|
|
15354
|
+
const config = import_yaml25.default.parse(content);
|
|
14825
15355
|
return config.project ?? null;
|
|
14826
15356
|
} catch {
|
|
14827
15357
|
return null;
|
|
@@ -14830,7 +15360,7 @@ async function getProjectName(projectRoot) {
|
|
|
14830
15360
|
async function destroyProject(projectRoot) {
|
|
14831
15361
|
const removed = [];
|
|
14832
15362
|
const skipped = [];
|
|
14833
|
-
const reapDir =
|
|
15363
|
+
const reapDir = join24(projectRoot, ".reap");
|
|
14834
15364
|
if (await fileExists(reapDir)) {
|
|
14835
15365
|
await rm6(reapDir, { recursive: true, force: true });
|
|
14836
15366
|
removed.push(".reap/");
|
|
@@ -14842,7 +15372,7 @@ async function destroyProject(projectRoot) {
|
|
|
14842
15372
|
return { removed, skipped };
|
|
14843
15373
|
}
|
|
14844
15374
|
async function cleanClaudeMd(projectRoot, removed, skipped) {
|
|
14845
|
-
const claudeMdPath =
|
|
15375
|
+
const claudeMdPath = join24(projectRoot, "CLAUDE.md");
|
|
14846
15376
|
const content = await readTextFile(claudeMdPath);
|
|
14847
15377
|
if (content === null) {
|
|
14848
15378
|
skipped.push("CLAUDE.md (not found)");
|
|
@@ -14867,7 +15397,7 @@ async function cleanClaudeMd(projectRoot, removed, skipped) {
|
|
|
14867
15397
|
}
|
|
14868
15398
|
}
|
|
14869
15399
|
async function cleanGitignore(projectRoot, removed, skipped) {
|
|
14870
|
-
const gitignorePath =
|
|
15400
|
+
const gitignorePath = join24(projectRoot, ".gitignore");
|
|
14871
15401
|
const content = await readTextFile(gitignorePath);
|
|
14872
15402
|
if (content === null) {
|
|
14873
15403
|
skipped.push(".gitignore (not found)");
|
|
@@ -14898,7 +15428,7 @@ async function cleanGitignore(projectRoot, removed, skipped) {
|
|
|
14898
15428
|
await writeTextFile(gitignorePath, cleaned);
|
|
14899
15429
|
removed.push(".gitignore (REAP entries removed)");
|
|
14900
15430
|
}
|
|
14901
|
-
async function
|
|
15431
|
+
async function execute32(confirm) {
|
|
14902
15432
|
const root = process.cwd();
|
|
14903
15433
|
const paths = createPaths(root);
|
|
14904
15434
|
if (await detectV15(paths)) {
|
|
@@ -14932,7 +15462,7 @@ async function execute31(confirm) {
|
|
|
14932
15462
|
|
|
14933
15463
|
// src/cli/commands/clean.ts
|
|
14934
15464
|
import { rm as rm7, readdir as readdir18, mkdir as mkdir4 } from "fs/promises";
|
|
14935
|
-
import { join as
|
|
15465
|
+
import { join as join25 } from "path";
|
|
14936
15466
|
init_fs();
|
|
14937
15467
|
init_integrity();
|
|
14938
15468
|
async function cleanProject(projectRoot, options) {
|
|
@@ -14971,7 +15501,7 @@ async function cleanLineage(lineageDir, mode, actions) {
|
|
|
14971
15501
|
}
|
|
14972
15502
|
if (mode === "delete") {
|
|
14973
15503
|
for (const entry of entries) {
|
|
14974
|
-
await rm7(
|
|
15504
|
+
await rm7(join25(lineageDir, entry), { recursive: true, force: true });
|
|
14975
15505
|
}
|
|
14976
15506
|
actions.push(`Lineage: deleted ${entries.length} item(s)`);
|
|
14977
15507
|
} else {
|
|
@@ -14987,9 +15517,9 @@ async function cleanLineage(lineageDir, mode, actions) {
|
|
|
14987
15517
|
].join(`
|
|
14988
15518
|
`);
|
|
14989
15519
|
for (const dir of genDirs) {
|
|
14990
|
-
await rm7(
|
|
15520
|
+
await rm7(join25(lineageDir, dir), { recursive: true, force: true });
|
|
14991
15521
|
}
|
|
14992
|
-
await writeTextFile(
|
|
15522
|
+
await writeTextFile(join25(lineageDir, `${epochId}.md`), summary);
|
|
14993
15523
|
actions.push(`Lineage: compressed ${genDirs.length} generation(s) into ${epochId}`);
|
|
14994
15524
|
}
|
|
14995
15525
|
}
|
|
@@ -15009,7 +15539,7 @@ async function cleanLife(lifeDir, actions) {
|
|
|
15009
15539
|
for (const entry of entries) {
|
|
15010
15540
|
if (entry === "backlog")
|
|
15011
15541
|
continue;
|
|
15012
|
-
await rm7(
|
|
15542
|
+
await rm7(join25(lifeDir, entry), { recursive: true, force: true });
|
|
15013
15543
|
removedCount++;
|
|
15014
15544
|
}
|
|
15015
15545
|
actions.push(`Life: cleaned ${removedCount} file(s)`);
|
|
@@ -15023,7 +15553,7 @@ async function cleanDir(dirPath, label, actions) {
|
|
|
15023
15553
|
await mkdir4(dirPath, { recursive: true });
|
|
15024
15554
|
actions.push(`${label}: reset`);
|
|
15025
15555
|
}
|
|
15026
|
-
async function
|
|
15556
|
+
async function execute33(options) {
|
|
15027
15557
|
const root = process.cwd();
|
|
15028
15558
|
const hasOptions = options.lineage || options.life || options.backlog || options.hooks;
|
|
15029
15559
|
if (!hasOptions) {
|
|
@@ -15069,14 +15599,14 @@ async function execute32(options) {
|
|
|
15069
15599
|
|
|
15070
15600
|
// src/cli/commands/check-version.ts
|
|
15071
15601
|
init_integrity();
|
|
15072
|
-
var
|
|
15602
|
+
var import_yaml26 = __toESM(require_dist(), 1);
|
|
15073
15603
|
import { execSync as execSync7 } from "child_process";
|
|
15074
15604
|
import { readFileSync as readFileSync3 } from "fs";
|
|
15075
|
-
import { join as
|
|
15605
|
+
import { join as join27 } from "path";
|
|
15076
15606
|
|
|
15077
15607
|
// src/core/notice.ts
|
|
15078
15608
|
import { readFileSync as readFileSync2 } from "fs";
|
|
15079
|
-
import { join as
|
|
15609
|
+
import { join as join26, dirname as dirname9 } from "path";
|
|
15080
15610
|
function findPackageRoot() {
|
|
15081
15611
|
try {
|
|
15082
15612
|
const pkgPath = __require.resolve("@c-d-cc/reap/package.json");
|
|
@@ -15097,7 +15627,7 @@ var LANG_MAP = {
|
|
|
15097
15627
|
};
|
|
15098
15628
|
function fetchReleaseNotice(version, language) {
|
|
15099
15629
|
try {
|
|
15100
|
-
const noticePath =
|
|
15630
|
+
const noticePath = join26(findPackageRoot(), "RELEASE_NOTICE.md");
|
|
15101
15631
|
const content = readFileSync2(noticePath, "utf-8");
|
|
15102
15632
|
const versionTag = version.startsWith("v") ? version : `v${version}`;
|
|
15103
15633
|
const versionPattern = new RegExp(`^## ${versionTag.replace(/\./g, "\\.")}\\s*$`, "m");
|
|
@@ -15242,16 +15772,16 @@ function performAutoUpdate(root) {
|
|
|
15242
15772
|
return { action: "skipped", reason: "error" };
|
|
15243
15773
|
}
|
|
15244
15774
|
}
|
|
15245
|
-
async function
|
|
15775
|
+
async function execute34() {
|
|
15246
15776
|
const root = process.cwd();
|
|
15247
15777
|
await cleanupLegacyHooks(root);
|
|
15248
15778
|
await cleanupLegacyProjectSkills(root);
|
|
15249
15779
|
const result = performAutoUpdate(root);
|
|
15250
15780
|
if (result.action === "upgraded" && result.to) {
|
|
15251
15781
|
try {
|
|
15252
|
-
const configPath =
|
|
15782
|
+
const configPath = join27(root, ".reap", "config.yml");
|
|
15253
15783
|
const configContent = readFileSync3(configPath, "utf-8");
|
|
15254
|
-
const config =
|
|
15784
|
+
const config = import_yaml26.default.parse(configContent);
|
|
15255
15785
|
const language = config?.language ?? "english";
|
|
15256
15786
|
const notice = fetchReleaseNotice(result.to, language);
|
|
15257
15787
|
if (notice)
|
|
@@ -15261,10 +15791,10 @@ async function execute33() {
|
|
|
15261
15791
|
}
|
|
15262
15792
|
|
|
15263
15793
|
// src/cli/commands/config.ts
|
|
15264
|
-
var
|
|
15794
|
+
var import_yaml27 = __toESM(require_dist(), 1);
|
|
15265
15795
|
init_fs();
|
|
15266
15796
|
init_integrity();
|
|
15267
|
-
async function
|
|
15797
|
+
async function execute35() {
|
|
15268
15798
|
const root = process.cwd();
|
|
15269
15799
|
const paths = createPaths(root);
|
|
15270
15800
|
if (!await fileExists(paths.config)) {
|
|
@@ -15277,7 +15807,7 @@ async function execute34() {
|
|
|
15277
15807
|
if (!configContent) {
|
|
15278
15808
|
emitError("config", "Config file is empty.");
|
|
15279
15809
|
}
|
|
15280
|
-
const config =
|
|
15810
|
+
const config = import_yaml27.default.parse(configContent);
|
|
15281
15811
|
emitOutput({
|
|
15282
15812
|
status: "ok",
|
|
15283
15813
|
command: "config",
|
|
@@ -15296,16 +15826,16 @@ async function execute34() {
|
|
|
15296
15826
|
}
|
|
15297
15827
|
|
|
15298
15828
|
// src/cli/commands/update.ts
|
|
15299
|
-
var
|
|
15829
|
+
var import_yaml28 = __toESM(require_dist(), 1);
|
|
15300
15830
|
import { readFileSync as readFileSync4 } from "fs";
|
|
15301
|
-
import { join as
|
|
15831
|
+
import { join as join28, dirname as dirname10 } from "path";
|
|
15302
15832
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
15303
15833
|
init_fs();
|
|
15304
15834
|
init_integrity();
|
|
15305
15835
|
function getPackageVersion() {
|
|
15306
15836
|
try {
|
|
15307
15837
|
const __dir = dirname10(fileURLToPath7(import.meta.url));
|
|
15308
|
-
for (const rel of [
|
|
15838
|
+
for (const rel of [join28(__dir, "..", "..", "package.json"), join28(__dir, "..", "package.json")]) {
|
|
15309
15839
|
try {
|
|
15310
15840
|
return JSON.parse(readFileSync4(rel, "utf-8")).version;
|
|
15311
15841
|
} catch {}
|
|
@@ -15355,7 +15885,7 @@ async function backfillConfig(paths) {
|
|
|
15355
15885
|
return { added: [], removed: [] };
|
|
15356
15886
|
let config;
|
|
15357
15887
|
try {
|
|
15358
|
-
config =
|
|
15888
|
+
config = import_yaml28.default.parse(content) ?? {};
|
|
15359
15889
|
} catch {
|
|
15360
15890
|
return { added: [], removed: [] };
|
|
15361
15891
|
}
|
|
@@ -15381,7 +15911,7 @@ async function backfillConfig(paths) {
|
|
|
15381
15911
|
}
|
|
15382
15912
|
}
|
|
15383
15913
|
if (added.length > 0 || removed.length > 0) {
|
|
15384
|
-
await writeTextFile(paths.config,
|
|
15914
|
+
await writeTextFile(paths.config, import_yaml28.default.stringify(config));
|
|
15385
15915
|
}
|
|
15386
15916
|
return { added, removed };
|
|
15387
15917
|
}
|
|
@@ -15396,7 +15926,7 @@ async function ensureDirectories(paths) {
|
|
|
15396
15926
|
}
|
|
15397
15927
|
return created;
|
|
15398
15928
|
}
|
|
15399
|
-
async function
|
|
15929
|
+
async function execute36(phase, postUpgrade) {
|
|
15400
15930
|
const root = process.cwd();
|
|
15401
15931
|
const paths = createPaths(root);
|
|
15402
15932
|
if (!await fileExists(paths.config) && !await detectV15(paths)) {
|
|
@@ -15405,7 +15935,7 @@ async function execute35(phase, postUpgrade) {
|
|
|
15405
15935
|
if (!postUpgrade) {
|
|
15406
15936
|
if (await detectV15(paths)) {
|
|
15407
15937
|
try {
|
|
15408
|
-
await
|
|
15938
|
+
await execute5(paths, phase);
|
|
15409
15939
|
} catch (err) {
|
|
15410
15940
|
try {
|
|
15411
15941
|
autoReport("reap update (migration)", err, ["migration"]);
|
|
@@ -15432,7 +15962,7 @@ async function execute35(phase, postUpgrade) {
|
|
|
15432
15962
|
let agentClient;
|
|
15433
15963
|
if (configContent) {
|
|
15434
15964
|
try {
|
|
15435
|
-
const config =
|
|
15965
|
+
const config = import_yaml28.default.parse(configContent);
|
|
15436
15966
|
projectName = config.project ?? "my-project";
|
|
15437
15967
|
agentClient = config.agentClient;
|
|
15438
15968
|
} catch {}
|
|
@@ -15449,7 +15979,7 @@ async function execute35(phase, postUpgrade) {
|
|
|
15449
15979
|
const raw = configContent ?? "";
|
|
15450
15980
|
if (raw) {
|
|
15451
15981
|
try {
|
|
15452
|
-
const cfg =
|
|
15982
|
+
const cfg = import_yaml28.default.parse(raw);
|
|
15453
15983
|
if (cfg?.language)
|
|
15454
15984
|
language = cfg.language;
|
|
15455
15985
|
} catch {}
|
|
@@ -15479,7 +16009,7 @@ async function execute35(phase, postUpgrade) {
|
|
|
15479
16009
|
}
|
|
15480
16010
|
|
|
15481
16011
|
// src/cli/commands/help.ts
|
|
15482
|
-
import { join as
|
|
16012
|
+
import { join as join29 } from "path";
|
|
15483
16013
|
init_fs();
|
|
15484
16014
|
var SUPPORTED_LANGUAGES = ["en", "ko", "ja", "zh-CN"];
|
|
15485
16015
|
var LANGUAGE_ALIASES = {
|
|
@@ -15646,7 +16176,7 @@ function buildHelpLines(lang, stateDisplay) {
|
|
|
15646
16176
|
CONFIG_LINE[lang]
|
|
15647
16177
|
];
|
|
15648
16178
|
}
|
|
15649
|
-
async function
|
|
16179
|
+
async function execute37(topic) {
|
|
15650
16180
|
const paths = createPaths(process.cwd());
|
|
15651
16181
|
const configContent = await readTextFile(paths.config);
|
|
15652
16182
|
const rawLang = detectLanguage(configContent);
|
|
@@ -15657,7 +16187,7 @@ async function execute36(topic) {
|
|
|
15657
16187
|
const stateDisplay = buildStateDisplay(state, lang);
|
|
15658
16188
|
const lines = buildHelpLines(lang, stateDisplay);
|
|
15659
16189
|
if (topic) {
|
|
15660
|
-
const reapGuidePath =
|
|
16190
|
+
const reapGuidePath = join29(paths.reap, "reap-guide.md");
|
|
15661
16191
|
const reapGuide = await readTextFile(reapGuidePath) ?? "";
|
|
15662
16192
|
emitOutput({
|
|
15663
16193
|
status: "prompt",
|
|
@@ -15702,7 +16232,7 @@ async function execute36(topic) {
|
|
|
15702
16232
|
// src/cli/commands/daemon/index.ts
|
|
15703
16233
|
init_client();
|
|
15704
16234
|
init_fs();
|
|
15705
|
-
async function
|
|
16235
|
+
async function execute38(subcommand, options) {
|
|
15706
16236
|
switch (subcommand) {
|
|
15707
16237
|
case "status":
|
|
15708
16238
|
return statusCmd();
|
|
@@ -15815,83 +16345,6 @@ ${lines.join(`
|
|
|
15815
16345
|
});
|
|
15816
16346
|
}
|
|
15817
16347
|
|
|
15818
|
-
// src/cli/commands/load-context.ts
|
|
15819
|
-
var import_yaml24 = __toESM(require_dist(), 1);
|
|
15820
|
-
import { join as join29 } from "path";
|
|
15821
|
-
init_fs();
|
|
15822
|
-
async function buildKnowledgeContext(cwd) {
|
|
15823
|
-
const configPath = join29(cwd, ".reap", "config.yml");
|
|
15824
|
-
if (!await fileExists(configPath)) {
|
|
15825
|
-
return null;
|
|
15826
|
-
}
|
|
15827
|
-
const paths = createPaths(cwd);
|
|
15828
|
-
const [configContent, currentContent] = await Promise.all([
|
|
15829
|
-
readTextFile(paths.config),
|
|
15830
|
-
readTextFile(paths.current)
|
|
15831
|
-
]);
|
|
15832
|
-
let config = null;
|
|
15833
|
-
if (configContent) {
|
|
15834
|
-
try {
|
|
15835
|
-
config = import_yaml24.default.parse(configContent);
|
|
15836
|
-
} catch {}
|
|
15837
|
-
}
|
|
15838
|
-
let state = null;
|
|
15839
|
-
if (currentContent) {
|
|
15840
|
-
try {
|
|
15841
|
-
state = import_yaml24.default.parse(currentContent);
|
|
15842
|
-
} catch {}
|
|
15843
|
-
}
|
|
15844
|
-
const sections = [];
|
|
15845
|
-
sections.push("# Current State");
|
|
15846
|
-
if (state) {
|
|
15847
|
-
const stateLines = [];
|
|
15848
|
-
stateLines.push(`- Generation: ${state.id}`);
|
|
15849
|
-
stateLines.push(`- Type: ${state.type}`);
|
|
15850
|
-
stateLines.push(`- Goal: ${state.goal}`);
|
|
15851
|
-
stateLines.push(`- Stage: ${state.stage}`);
|
|
15852
|
-
if (state.phase)
|
|
15853
|
-
stateLines.push(`- Phase: ${state.phase}`);
|
|
15854
|
-
if (state.type === "merge" && state.parents?.length) {
|
|
15855
|
-
stateLines.push(`- Parents: ${state.parents.join(", ")}`);
|
|
15856
|
-
}
|
|
15857
|
-
sections.push(stateLines.join(`
|
|
15858
|
-
`));
|
|
15859
|
-
} else {
|
|
15860
|
-
sections.push("No active generation.");
|
|
15861
|
-
}
|
|
15862
|
-
if (config) {
|
|
15863
|
-
const strictStage = state ? state.stage : "none";
|
|
15864
|
-
const strictSection = buildStrictSection(config.strictEdit ?? false, config.strictMerge ?? false, strictStage, state?.type);
|
|
15865
|
-
if (strictSection) {
|
|
15866
|
-
sections.push(strictSection.trimStart());
|
|
15867
|
-
}
|
|
15868
|
-
}
|
|
15869
|
-
if (config?.language) {
|
|
15870
|
-
sections.push(`# Language
|
|
15871
|
-
Always respond in ${config.language}. Use ${config.language} for all explanations, comments, and communications. Technical terms and code identifiers remain in their original form.`);
|
|
15872
|
-
}
|
|
15873
|
-
return sections.join(`
|
|
15874
|
-
|
|
15875
|
-
---
|
|
15876
|
-
|
|
15877
|
-
`);
|
|
15878
|
-
}
|
|
15879
|
-
async function execute38() {
|
|
15880
|
-
const context = await buildKnowledgeContext(process.cwd());
|
|
15881
|
-
if (!context) {
|
|
15882
|
-
process.exit(0);
|
|
15883
|
-
}
|
|
15884
|
-
const output = {
|
|
15885
|
-
hookSpecificOutput: {
|
|
15886
|
-
hookEventName: "SessionStart",
|
|
15887
|
-
additionalContext: context
|
|
15888
|
-
}
|
|
15889
|
-
};
|
|
15890
|
-
process.stdout.write(JSON.stringify(output) + `
|
|
15891
|
-
`);
|
|
15892
|
-
process.exit(0);
|
|
15893
|
-
}
|
|
15894
|
-
|
|
15895
16348
|
// src/cli/commands/dump-state.ts
|
|
15896
16349
|
init_fs();
|
|
15897
16350
|
async function execute39(opts = {}) {
|
|
@@ -15946,31 +16399,31 @@ function readVersion() {
|
|
|
15946
16399
|
var program2 = new Command;
|
|
15947
16400
|
program2.name("reap").description("Recursive Evolutionary Autonomous Pipeline — Self-Evolving").version(readVersion());
|
|
15948
16401
|
program2.command("init [project-name]").description("Initialize a new reap project").option("--mode <mode>", "Override auto-detected mode (greenfield or adoption)").option("--repair", "Repair an existing project — supplement missing files (e.g., CLAUDE.md)").option("--migrate", "Migrate from v0.15 to v0.16 structure").option("--phase <phase>", "Migration phase (confirm, execute, vision, complete)").action(async (projectName, options) => {
|
|
15949
|
-
await
|
|
16402
|
+
await execute6(projectName, options.mode, options.repair, options.migrate, options.phase);
|
|
15950
16403
|
});
|
|
15951
16404
|
program2.command("status").description("Show current project status").action(async () => {
|
|
15952
|
-
await
|
|
16405
|
+
await execute7();
|
|
15953
16406
|
});
|
|
15954
|
-
program2.command("run <stage>").description("Run a lifecycle stage (start, learning, planning, ...)").option("--phase <phase>", "Stage phase (work, complete, reflect, fitness, adapt, commit)").option("--goal <goal>", "Goal for start command").option("--type <type>", "Generation type (embryo, normal, merge)").option("--parents <parents>", "Parent generation IDs for merge (comma-separated)").option("--feedback <feedback>", "Fitness feedback text").option("--reason <reason>", "Reason for back regression or abort").option("--backlog <backlog>", "Backlog filename to consume for this generation (use --no-backlog to explicitly declare no relevant backlog)").option("--no-backlog", "Explicitly declare no backlog item is relevant to this generation (suppresses pending-backlog prompt). Negates --backlog.").option("--source-action <sourceAction>", "Source action for abort/early-close (rollback, stash, hold, none — rollback only for abort)").option("--save-backlog", "Save progress to backlog on abort").option("--defer-tasks <value>", "For early-close: auto-defer unchecked tasks to new backlog (true|false, default true)").action(async (stage, options) => {
|
|
15955
|
-
await
|
|
16407
|
+
program2.command("run <stage>").description("Run a lifecycle stage (start, learning, planning, ...)").option("--phase <phase>", "Stage phase (work, complete, reflect, fitness, adapt, commit)").option("--goal <goal>", "Goal for start command").option("--type <type>", "Generation type (embryo, normal, merge)").option("--parents <parents>", "Parent generation IDs for merge (comma-separated)").option("--feedback <feedback>", "Fitness feedback text").option("--reason <reason>", "Reason for back regression or abort").option("--backlog <backlog>", "Backlog filename to consume for this generation (use --no-backlog to explicitly declare no relevant backlog)").option("--no-backlog", "Explicitly declare no backlog item is relevant to this generation (suppresses pending-backlog prompt). Negates --backlog.").option("--source-action <sourceAction>", "Source action for abort/early-close (rollback, stash, hold, none — rollback only for abort)").option("--save-backlog", "Save progress to backlog on abort").option("--defer-tasks <value>", "For early-close: auto-defer unchecked tasks to new backlog (true|false, default true)").option("--severity <severity>", "For validation --phase report-evaluator: evaluator concern severity (high|low|none — none is a no-op)").option("--summary <summary>", "For validation --phase report-evaluator: one-line evaluator concern summary").action(async (stage, options) => {
|
|
16408
|
+
await execute27(stage, options);
|
|
15956
16409
|
});
|
|
15957
16410
|
program2.command("make <resource>").description("Create a resource from template (backlog, hook)").option("--type <type>", "Resource type (backlog: genome-change/environment-change/task, hook: sh/md)").option("--title <title>", "Resource title").option("--body <body>", "Optional description body").option("--priority <priority>", "Priority (high, medium, low)").option("--event <event>", "Hook event (e.g. onLifeCompleted)").option("--name <name>", "Hook name").option("--condition <condition>", "Hook condition (default: always)").option("--order <order>", "Hook execution order (default: 50)").action(async (resource, options) => {
|
|
15958
|
-
await
|
|
16411
|
+
await execute28(resource, options);
|
|
15959
16412
|
});
|
|
15960
16413
|
program2.command("cruise <count>").description("Enable cruise mode for N generations").action(async (count) => {
|
|
15961
|
-
await
|
|
16414
|
+
await execute29(count);
|
|
15962
16415
|
});
|
|
15963
16416
|
program2.command("install-skills").description("Install Claude Code skill files to .claude/commands/").action(async () => {
|
|
15964
|
-
await
|
|
16417
|
+
await execute30();
|
|
15965
16418
|
});
|
|
15966
16419
|
program2.command("fix").description("Diagnose and repair .reap/ directory structure").option("--check", "Check only — report issues without fixing").action(async (options) => {
|
|
15967
|
-
await
|
|
16420
|
+
await execute31(options.check);
|
|
15968
16421
|
});
|
|
15969
16422
|
program2.command("destroy").description("Completely remove REAP from this project").option("--confirm", "Confirm destruction without prompt").action(async (options) => {
|
|
15970
|
-
await
|
|
16423
|
+
await execute32(options.confirm);
|
|
15971
16424
|
});
|
|
15972
16425
|
program2.command("clean").description("Selectively reset REAP project state").option("--lineage <mode>", "Lineage action (compress or delete)").option("--life", "Clear current generation and artifacts").option("--backlog", "Delete all backlog items").option("--hooks <mode>", "Hooks action (reset)").action(async (options) => {
|
|
15973
|
-
await
|
|
16426
|
+
await execute33({
|
|
15974
16427
|
lineage: options.lineage,
|
|
15975
16428
|
life: options.life,
|
|
15976
16429
|
backlog: options.backlog,
|
|
@@ -15978,24 +16431,24 @@ program2.command("clean").description("Selectively reset REAP project state").op
|
|
|
15978
16431
|
});
|
|
15979
16432
|
});
|
|
15980
16433
|
program2.command("check-version").description("Check for v0.15 project and show migration message").action(async () => {
|
|
15981
|
-
await
|
|
16434
|
+
await execute34();
|
|
15982
16435
|
});
|
|
15983
16436
|
program2.command("config").description("Show current REAP project configuration").action(async () => {
|
|
15984
|
-
await
|
|
16437
|
+
await execute35();
|
|
15985
16438
|
});
|
|
15986
16439
|
program2.command("help [topic]").description("Show REAP commands and workflow overview").action(async (topic) => {
|
|
15987
|
-
await
|
|
16440
|
+
await execute37(topic);
|
|
15988
16441
|
});
|
|
15989
16442
|
program2.command("update").description("Update project structure to match current REAP version").option("--phase <phase>", "Migration phase for v0.15 projects (confirm, execute, vision, complete)").option("--post-upgrade", "Run project sync only (called by previous binary after self-upgrade)").action(async (options) => {
|
|
15990
|
-
await
|
|
16443
|
+
await execute36(options.phase, options.postUpgrade);
|
|
15991
16444
|
});
|
|
15992
16445
|
program2.command("load-context").description("Output REAP project knowledge for SessionStart hook injection").action(async () => {
|
|
15993
|
-
await
|
|
16446
|
+
await execute();
|
|
15994
16447
|
});
|
|
15995
16448
|
program2.command("dump-state").description("Dump dynamic REAP context to .reap/.session-state.md (for OpenCode and external tools)").option("--stdout", "Write to stdout instead of the file").option("--silent", "Exit 0 silently on any error / non-REAP project").action(async (options) => {
|
|
15996
16449
|
await execute39({ stdout: options.stdout, silent: options.silent });
|
|
15997
16450
|
});
|
|
15998
16451
|
program2.command("daemon <subcommand>").description("Manage the REAP daemon (status, stop, index, query)").option("--query <query>", "Search query for daemon query subcommand").action(async (subcommand, options) => {
|
|
15999
|
-
await
|
|
16452
|
+
await execute38(subcommand, options);
|
|
16000
16453
|
});
|
|
16001
16454
|
program2.parse();
|