@c-d-cc/reap 0.17.0 → 0.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/RELEASE_NOTICE.md +6 -0
- package/dist/cli/index.js +403 -251
- package/dist/templates/migration/v0.17.1.md +56 -0
- package/dist/templates/reap-guide.md +92 -37
- 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 join5 } from "path";
|
|
7071
7071
|
import { homedir } from "os";
|
|
7072
7072
|
async function detectV15(paths) {
|
|
7073
|
-
return fileExists(
|
|
7073
|
+
return fileExists(join5(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 = join5(homedir(), ".reap", "reap-guide.md");
|
|
7125
|
+
const guideLocal = join5(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 = join5(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'");
|
|
@@ -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 = join5(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 = join5(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`);
|
|
@@ -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(join5(paths.lineage, name));
|
|
7276
7276
|
if (!content)
|
|
7277
7277
|
continue;
|
|
7278
7278
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
@@ -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 = join5(paths.lineage, name);
|
|
7299
7299
|
let parents = [];
|
|
7300
7300
|
let itemStat;
|
|
7301
7301
|
try {
|
|
@@ -7304,7 +7304,7 @@ 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(join5(paths.lineage, name, "meta.yml"));
|
|
7308
7308
|
if (metaContent) {
|
|
7309
7309
|
try {
|
|
7310
7310
|
const meta = import_yaml3.default.parse(metaContent);
|
|
@@ -7312,7 +7312,7 @@ async function checkLineage(paths, errors, warnings) {
|
|
|
7312
7312
|
} catch {}
|
|
7313
7313
|
}
|
|
7314
7314
|
} else if (itemStat.isFile() && name.endsWith(".md")) {
|
|
7315
|
-
const content = await readTextFile(
|
|
7315
|
+
const content = await readTextFile(join5(paths.lineage, name));
|
|
7316
7316
|
if (content) {
|
|
7317
7317
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
7318
7318
|
if (fmMatch) {
|
|
@@ -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(join5(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(join5(paths.backlog, filename));
|
|
7401
7401
|
if (!content)
|
|
7402
7402
|
continue;
|
|
7403
7403
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
@@ -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(join5(home, ".claude", "skills"), /^reap\./, "~/.claude/skills/", "user-level reap skill found (should only be project-level)", errors);
|
|
7435
|
+
await checkGlobPattern(join5(home, ".claude", "commands"), /^reap\./, "~/.claude/commands/", "legacy reap command at user level (Phase 2 remnant)", warnings);
|
|
7436
|
+
await checkGlobPattern(join5(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 = join5(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(join5(commandsDir, entry), { force: true });
|
|
7460
7460
|
deleted.push(`.claude/commands/${entry}`);
|
|
7461
7461
|
}
|
|
7462
7462
|
}
|
|
7463
7463
|
} catch {}
|
|
7464
|
-
const skillsDir =
|
|
7464
|
+
const skillsDir = join5(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 = join5(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
|
+
join5(projectRoot, ".claude", "settings.json"),
|
|
7486
|
+
join5(homedir(), ".claude", "settings.json")
|
|
7487
7487
|
];
|
|
7488
7488
|
for (const settingsPath of settingsPaths) {
|
|
7489
7489
|
try {
|
|
@@ -7543,13 +7543,13 @@ __export(exports_common, {
|
|
|
7543
7543
|
buildPromptPreamble: () => buildPromptPreamble,
|
|
7544
7544
|
buildHardGateBlock: () => buildHardGateBlock
|
|
7545
7545
|
});
|
|
7546
|
-
import { join as
|
|
7547
|
-
import { fileURLToPath } from "url";
|
|
7546
|
+
import { join as join6, dirname as dirname5 } from "path";
|
|
7547
|
+
import { fileURLToPath as fileURLToPath4 } 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
|
-
const __dirname2 =
|
|
7552
|
-
return
|
|
7551
|
+
const __dirname2 = dirname5(fileURLToPath4(import.meta.url));
|
|
7552
|
+
return join6(__dirname2, "..", "templates", ...segments);
|
|
7553
7553
|
}
|
|
7554
7554
|
async function initCommon(paths, projectName) {
|
|
7555
7555
|
await cleanupLegacyProjectSkills(paths.root);
|
|
@@ -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 = join6(root, "CLAUDE.md");
|
|
7666
|
+
const dotClaudePath = join6(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 = join6(templateDir, "conditions");
|
|
7735
|
+
const conditionsDir = join6(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 = join6(conditionsDir, file);
|
|
7741
7741
|
if (!await fileExists(dest)) {
|
|
7742
|
-
await copyFile(
|
|
7742
|
+
await copyFile(join6(conditionsTemplateDir, file), dest);
|
|
7743
7743
|
await chmod(dest, 493);
|
|
7744
7744
|
}
|
|
7745
7745
|
}
|
|
@@ -7749,9 +7749,9 @@ 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 = join6(hooksDir, file);
|
|
7753
7753
|
if (!await fileExists(dest)) {
|
|
7754
|
-
await copyFile(
|
|
7754
|
+
await copyFile(join6(templateDir, file), dest);
|
|
7755
7755
|
}
|
|
7756
7756
|
}
|
|
7757
7757
|
} catch {}
|
|
@@ -7780,7 +7780,7 @@ var init_common = __esm(() => {
|
|
|
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 join13 } from "path";
|
|
7784
7784
|
import { homedir as homedir3 } from "os";
|
|
7785
7785
|
function resolvePort() {
|
|
7786
7786
|
const raw = process.env.REAP_DAEMON_PORT;
|
|
@@ -7831,7 +7831,7 @@ function resolveDaemonBin() {
|
|
|
7831
7831
|
try {
|
|
7832
7832
|
return __require.resolve("@c-d-cc/reap-daemon/dist/index.js");
|
|
7833
7833
|
} catch {
|
|
7834
|
-
return
|
|
7834
|
+
return join13(__dirname, "..", "..", "..", "daemon", "dist", "index.js");
|
|
7835
7835
|
}
|
|
7836
7836
|
}
|
|
7837
7837
|
function detectRuntime() {
|
|
@@ -7855,8 +7855,8 @@ async function findProjectId(projectRoot) {
|
|
|
7855
7855
|
}
|
|
7856
7856
|
var __dirname = "/home/runner/work/reap/reap/src/cli/commands/daemon", DAEMON_ROOT, PID_PATH, DEFAULT_PORT = 17224;
|
|
7857
7857
|
var init_client = __esm(() => {
|
|
7858
|
-
DAEMON_ROOT =
|
|
7859
|
-
PID_PATH =
|
|
7858
|
+
DAEMON_ROOT = join13(homedir3(), ".reap", "daemon");
|
|
7859
|
+
PID_PATH = join13(DAEMON_ROOT, "daemon.pid");
|
|
7860
7860
|
});
|
|
7861
7861
|
|
|
7862
7862
|
// src/cli/commands/daemon/lifecycle.ts
|
|
@@ -7898,9 +7898,9 @@ var init_lifecycle = __esm(() => {
|
|
|
7898
7898
|
});
|
|
7899
7899
|
|
|
7900
7900
|
// src/cli/index.ts
|
|
7901
|
-
import { readFileSync as
|
|
7902
|
-
import { join as
|
|
7903
|
-
import { fileURLToPath as
|
|
7901
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
7902
|
+
import { join as join31, dirname as dirname13 } from "path";
|
|
7903
|
+
import { fileURLToPath as fileURLToPath11 } from "url";
|
|
7904
7904
|
|
|
7905
7905
|
// src/libs/cli.ts
|
|
7906
7906
|
function parseOptionFlags(flags) {
|
|
@@ -8591,7 +8591,7 @@ var program = new Command;
|
|
|
8591
8591
|
|
|
8592
8592
|
// src/cli/commands/init/index.ts
|
|
8593
8593
|
import { readdir as readdir5 } from "fs/promises";
|
|
8594
|
-
import { join as
|
|
8594
|
+
import { join as join9 } from "path";
|
|
8595
8595
|
|
|
8596
8596
|
// src/core/paths.ts
|
|
8597
8597
|
import { join } from "path";
|
|
@@ -8639,8 +8639,9 @@ init_fs();
|
|
|
8639
8639
|
|
|
8640
8640
|
// src/core/dump-state-sync.ts
|
|
8641
8641
|
var import_yaml2 = __toESM(require_dist(), 1);
|
|
8642
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
|
|
8643
|
-
import { join as
|
|
8642
|
+
import { readFileSync as readFileSync3, writeFileSync, mkdirSync, existsSync as existsSync2 } from "fs";
|
|
8643
|
+
import { join as join4, dirname as dirname4 } from "path";
|
|
8644
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
8644
8645
|
|
|
8645
8646
|
// src/core/prompt.ts
|
|
8646
8647
|
init_fs();
|
|
@@ -9127,10 +9128,99 @@ function buildEvaluatorPrompt(knowledge, paths, state, opts) {
|
|
|
9127
9128
|
|
|
9128
9129
|
// src/cli/commands/load-context.ts
|
|
9129
9130
|
var import_yaml = __toESM(require_dist(), 1);
|
|
9130
|
-
import {
|
|
9131
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
9132
|
+
import { join as join3, dirname as dirname3 } from "path";
|
|
9133
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9131
9134
|
init_fs();
|
|
9135
|
+
|
|
9136
|
+
// src/core/migration.ts
|
|
9137
|
+
import { readdirSync, readFileSync, existsSync } from "fs";
|
|
9138
|
+
import { join as join2, dirname as dirname2 } from "path";
|
|
9139
|
+
import { fileURLToPath } from "url";
|
|
9140
|
+
var MIGRATION_FILENAME_RE = /^v(\d+\.\d+\.\d+)\.md$/;
|
|
9141
|
+
function parseVersionFromFilename(name) {
|
|
9142
|
+
const m = MIGRATION_FILENAME_RE.exec(name);
|
|
9143
|
+
return m ? m[1] : null;
|
|
9144
|
+
}
|
|
9145
|
+
function semverGt(a, b) {
|
|
9146
|
+
const pa = a.split(".").map((s) => Number.parseInt(s, 10) || 0);
|
|
9147
|
+
const pb = b.split(".").map((s) => Number.parseInt(s, 10) || 0);
|
|
9148
|
+
for (let i = 0;i < 3; i++) {
|
|
9149
|
+
const av = pa[i] ?? 0;
|
|
9150
|
+
const bv = pb[i] ?? 0;
|
|
9151
|
+
if (av > bv)
|
|
9152
|
+
return true;
|
|
9153
|
+
if (av < bv)
|
|
9154
|
+
return false;
|
|
9155
|
+
}
|
|
9156
|
+
return false;
|
|
9157
|
+
}
|
|
9158
|
+
function migrationTemplatesDir() {
|
|
9159
|
+
const here = dirname2(fileURLToPath(import.meta.url));
|
|
9160
|
+
return here.includes("dist") ? join2(here, "..", "templates", "migration") : join2(here, "..", "templates", "migration");
|
|
9161
|
+
}
|
|
9162
|
+
function detectPendingMigrations(config, currentVersion, templatesDir) {
|
|
9163
|
+
if (!currentVersion || currentVersion === "0.0.0")
|
|
9164
|
+
return [];
|
|
9165
|
+
const lastMigrated = config?.lastMigratedVersion ?? "0.0.0";
|
|
9166
|
+
const dir = templatesDir ?? migrationTemplatesDir();
|
|
9167
|
+
let entries;
|
|
9168
|
+
try {
|
|
9169
|
+
if (!existsSync(dir))
|
|
9170
|
+
return [];
|
|
9171
|
+
entries = readdirSync(dir);
|
|
9172
|
+
} catch {
|
|
9173
|
+
return [];
|
|
9174
|
+
}
|
|
9175
|
+
const pending = [];
|
|
9176
|
+
for (const name of entries) {
|
|
9177
|
+
const version = parseVersionFromFilename(name);
|
|
9178
|
+
if (!version)
|
|
9179
|
+
continue;
|
|
9180
|
+
if (!semverGt(version, lastMigrated))
|
|
9181
|
+
continue;
|
|
9182
|
+
if (semverGt(version, currentVersion))
|
|
9183
|
+
continue;
|
|
9184
|
+
try {
|
|
9185
|
+
const body = readFileSync(join2(dir, name), "utf-8");
|
|
9186
|
+
pending.push({ version, instructions: body });
|
|
9187
|
+
} catch {}
|
|
9188
|
+
}
|
|
9189
|
+
pending.sort((a, b) => semverGt(a.version, b.version) ? 1 : -1);
|
|
9190
|
+
return pending;
|
|
9191
|
+
}
|
|
9192
|
+
function buildPendingMigrationsSection(config, currentVersion, templatesDir) {
|
|
9193
|
+
const pending = detectPendingMigrations(config, currentVersion, templatesDir);
|
|
9194
|
+
if (pending.length === 0)
|
|
9195
|
+
return null;
|
|
9196
|
+
const lines = [];
|
|
9197
|
+
lines.push("# Pending Migrations");
|
|
9198
|
+
lines.push("");
|
|
9199
|
+
lines.push(`This project has not yet been migrated for ${pending.length} REAP version${pending.length === 1 ? "" : "s"}. ` + `Follow the instructions below to bring existing artifacts/memory in line with the current REAP version, ` + `then run \`reap update --mark-migrated\` to record completion.`);
|
|
9200
|
+
for (const m of pending) {
|
|
9201
|
+
lines.push("");
|
|
9202
|
+
lines.push(`## v${m.version}`);
|
|
9203
|
+
lines.push("");
|
|
9204
|
+
lines.push(m.instructions.trim());
|
|
9205
|
+
}
|
|
9206
|
+
return lines.join(`
|
|
9207
|
+
`);
|
|
9208
|
+
}
|
|
9209
|
+
|
|
9210
|
+
// src/cli/commands/load-context.ts
|
|
9211
|
+
function getPackageVersion() {
|
|
9212
|
+
try {
|
|
9213
|
+
const __dir = dirname3(fileURLToPath2(import.meta.url));
|
|
9214
|
+
for (const rel of [join3(__dir, "..", "..", "..", "package.json"), join3(__dir, "..", "..", "package.json"), join3(__dir, "..", "package.json")]) {
|
|
9215
|
+
try {
|
|
9216
|
+
return JSON.parse(readFileSync2(rel, "utf-8")).version;
|
|
9217
|
+
} catch {}
|
|
9218
|
+
}
|
|
9219
|
+
} catch {}
|
|
9220
|
+
return "0.0.0";
|
|
9221
|
+
}
|
|
9132
9222
|
async function buildKnowledgeContext(cwd) {
|
|
9133
|
-
const configPath =
|
|
9223
|
+
const configPath = join3(cwd, ".reap", "config.yml");
|
|
9134
9224
|
if (!await fileExists(configPath)) {
|
|
9135
9225
|
return null;
|
|
9136
9226
|
}
|
|
@@ -9183,6 +9273,11 @@ Always respond in ${config.language}. Use ${config.language} for all explanation
|
|
|
9183
9273
|
if (config?.daemon === true) {
|
|
9184
9274
|
sections.push(buildDaemonStaticSection());
|
|
9185
9275
|
}
|
|
9276
|
+
try {
|
|
9277
|
+
const migrationsSection = buildPendingMigrationsSection(config, getPackageVersion());
|
|
9278
|
+
if (migrationsSection)
|
|
9279
|
+
sections.push(migrationsSection);
|
|
9280
|
+
} catch {}
|
|
9186
9281
|
return sections.join(`
|
|
9187
9282
|
|
|
9188
9283
|
---
|
|
@@ -9216,6 +9311,17 @@ async function execute() {
|
|
|
9216
9311
|
}
|
|
9217
9312
|
|
|
9218
9313
|
// src/core/dump-state-sync.ts
|
|
9314
|
+
function getPackageVersion2() {
|
|
9315
|
+
try {
|
|
9316
|
+
const __dir = dirname4(fileURLToPath3(import.meta.url));
|
|
9317
|
+
for (const rel of [join4(__dir, "..", "..", "package.json"), join4(__dir, "..", "package.json")]) {
|
|
9318
|
+
try {
|
|
9319
|
+
return JSON.parse(readFileSync3(rel, "utf-8")).version;
|
|
9320
|
+
} catch {}
|
|
9321
|
+
}
|
|
9322
|
+
} catch {}
|
|
9323
|
+
return "0.0.0";
|
|
9324
|
+
}
|
|
9219
9325
|
var DUMP_COMMANDS = new Set([
|
|
9220
9326
|
"start",
|
|
9221
9327
|
"learning",
|
|
@@ -9237,17 +9343,17 @@ var DUMP_COMMANDS = new Set([
|
|
|
9237
9343
|
"init"
|
|
9238
9344
|
]);
|
|
9239
9345
|
function buildKnowledgeContextSync(cwd) {
|
|
9240
|
-
const configPath =
|
|
9241
|
-
if (!
|
|
9346
|
+
const configPath = join4(cwd, ".reap", "config.yml");
|
|
9347
|
+
if (!existsSync2(configPath))
|
|
9242
9348
|
return null;
|
|
9243
9349
|
const paths = createPaths(cwd);
|
|
9244
9350
|
let configContent = "";
|
|
9245
9351
|
let currentContent = "";
|
|
9246
9352
|
try {
|
|
9247
|
-
configContent =
|
|
9353
|
+
configContent = readFileSync3(paths.config, "utf-8");
|
|
9248
9354
|
} catch {}
|
|
9249
9355
|
try {
|
|
9250
|
-
currentContent =
|
|
9356
|
+
currentContent = readFileSync3(paths.current, "utf-8");
|
|
9251
9357
|
} catch {}
|
|
9252
9358
|
let config = null;
|
|
9253
9359
|
if (configContent) {
|
|
@@ -9293,6 +9399,11 @@ Always respond in ${config.language}. Use ${config.language} for all explanation
|
|
|
9293
9399
|
if (config?.daemon === true) {
|
|
9294
9400
|
sections.push(buildDaemonStaticSection());
|
|
9295
9401
|
}
|
|
9402
|
+
try {
|
|
9403
|
+
const migrationsSection = buildPendingMigrationsSection(config, getPackageVersion2());
|
|
9404
|
+
if (migrationsSection)
|
|
9405
|
+
sections.push(migrationsSection);
|
|
9406
|
+
} catch {}
|
|
9296
9407
|
return sections.join(`
|
|
9297
9408
|
|
|
9298
9409
|
---
|
|
@@ -9304,7 +9415,7 @@ function dumpStateSync(cwd) {
|
|
|
9304
9415
|
if (!ctx)
|
|
9305
9416
|
return;
|
|
9306
9417
|
const paths = createPaths(cwd);
|
|
9307
|
-
mkdirSync(
|
|
9418
|
+
mkdirSync(dirname4(paths.sessionState), { recursive: true });
|
|
9308
9419
|
writeFileSync(paths.sessionState, ctx + `
|
|
9309
9420
|
`, "utf-8");
|
|
9310
9421
|
}
|
|
@@ -9450,10 +9561,10 @@ init_common();
|
|
|
9450
9561
|
// src/core/scanner.ts
|
|
9451
9562
|
init_fs();
|
|
9452
9563
|
import { readdir as readdir3, stat as stat2 } from "fs/promises";
|
|
9453
|
-
import { join as
|
|
9564
|
+
import { join as join7, relative } from "path";
|
|
9454
9565
|
async function scanCodebase(root) {
|
|
9455
9566
|
let packageJson = null;
|
|
9456
|
-
const pkgContent = await readTextFile(
|
|
9567
|
+
const pkgContent = await readTextFile(join7(root, "package.json"));
|
|
9457
9568
|
if (pkgContent) {
|
|
9458
9569
|
try {
|
|
9459
9570
|
packageJson = JSON.parse(pkgContent);
|
|
@@ -9462,7 +9573,7 @@ async function scanCodebase(root) {
|
|
|
9462
9573
|
const deps = Object.keys(packageJson?.dependencies ?? {});
|
|
9463
9574
|
const devDeps = Object.keys(packageJson?.devDependencies ?? {});
|
|
9464
9575
|
const scripts = packageJson?.scripts ?? {};
|
|
9465
|
-
const hasTypeScript = !!await readTextFile(
|
|
9576
|
+
const hasTypeScript = !!await readTextFile(join7(root, "tsconfig.json")) || devDeps.includes("typescript");
|
|
9466
9577
|
const testFrameworks = ["jest", "vitest", "mocha", "@jest/core", "bun:test"];
|
|
9467
9578
|
const testFramework = [...deps, ...devDeps].find((d) => testFrameworks.includes(d)) ?? null;
|
|
9468
9579
|
const hasTests = !!testFramework || scripts.test !== undefined;
|
|
@@ -9470,7 +9581,7 @@ async function scanCodebase(root) {
|
|
|
9470
9581
|
const buildTool = [...deps, ...devDeps].find((d) => buildTools.includes(d)) ?? null;
|
|
9471
9582
|
const tree = await buildTree(root, root, 2);
|
|
9472
9583
|
let readmeExcerpt = null;
|
|
9473
|
-
const readme = await readTextFile(
|
|
9584
|
+
const readme = await readTextFile(join7(root, "README.md"));
|
|
9474
9585
|
if (readme) {
|
|
9475
9586
|
readmeExcerpt = readme.slice(0, 500);
|
|
9476
9587
|
}
|
|
@@ -9504,7 +9615,7 @@ async function buildTree(root, dir, depth) {
|
|
|
9504
9615
|
continue;
|
|
9505
9616
|
if (SKIP_DIRS.has(entry))
|
|
9506
9617
|
continue;
|
|
9507
|
-
const fullPath =
|
|
9618
|
+
const fullPath = join7(dir, entry);
|
|
9508
9619
|
const relPath = relative(root, fullPath);
|
|
9509
9620
|
const s = await stat2(fullPath).catch(() => null);
|
|
9510
9621
|
if (!s)
|
|
@@ -9833,9 +9944,9 @@ async function execute4(paths) {
|
|
|
9833
9944
|
init_fs();
|
|
9834
9945
|
var import_yaml6 = __toESM(require_dist(), 1);
|
|
9835
9946
|
import { readdir as readdir4, cp, rename, rm as rm2 } from "fs/promises";
|
|
9836
|
-
import { join as
|
|
9947
|
+
import { join as join8, dirname as dirname6 } from "path";
|
|
9837
9948
|
import { execSync as execSync2 } from "child_process";
|
|
9838
|
-
import { fileURLToPath as
|
|
9949
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
9839
9950
|
import { homedir as homedir2 } from "os";
|
|
9840
9951
|
|
|
9841
9952
|
// src/core/git.ts
|
|
@@ -10029,8 +10140,8 @@ function pushSubmodules(cwd) {
|
|
|
10029
10140
|
init_integrity();
|
|
10030
10141
|
init_common();
|
|
10031
10142
|
function distPath2(...segments) {
|
|
10032
|
-
const __dirname2 =
|
|
10033
|
-
return
|
|
10143
|
+
const __dirname2 = dirname6(fileURLToPath5(import.meta.url));
|
|
10144
|
+
return join8(__dirname2, "..", "templates", ...segments);
|
|
10034
10145
|
}
|
|
10035
10146
|
function isGitClean(cwd) {
|
|
10036
10147
|
if (!isGitRepo(cwd))
|
|
@@ -10106,7 +10217,7 @@ function mapHookFilename(filename) {
|
|
|
10106
10217
|
}
|
|
10107
10218
|
async function scanV15Structure(paths) {
|
|
10108
10219
|
const genomeFiles = [];
|
|
10109
|
-
const genomeDir =
|
|
10220
|
+
const genomeDir = join8(paths.reap, "v15", "genome");
|
|
10110
10221
|
const currentGenomeDir = paths.genome;
|
|
10111
10222
|
try {
|
|
10112
10223
|
const entries = await readdir4(currentGenomeDir);
|
|
@@ -10116,7 +10227,7 @@ async function scanV15Structure(paths) {
|
|
|
10116
10227
|
}
|
|
10117
10228
|
} catch {}
|
|
10118
10229
|
const domainFiles = [];
|
|
10119
|
-
const domainDir =
|
|
10230
|
+
const domainDir = join8(currentGenomeDir, "domain");
|
|
10120
10231
|
try {
|
|
10121
10232
|
const entries = await readdir4(domainDir);
|
|
10122
10233
|
for (const e of entries) {
|
|
@@ -10186,7 +10297,7 @@ async function executePreCheck(paths) {
|
|
|
10186
10297
|
if (currentContent && currentContent.trim()) {
|
|
10187
10298
|
emitError("migrate", "Active generation exists. Run '/reap.abort' first, then retry migration.");
|
|
10188
10299
|
}
|
|
10189
|
-
if (await fileExists(
|
|
10300
|
+
if (await fileExists(join8(paths.reap, "v15"))) {
|
|
10190
10301
|
emitError("migrate", "Previous migration backup (.reap/v15/) already exists. Remove it first if you want to re-migrate.");
|
|
10191
10302
|
}
|
|
10192
10303
|
const configContent = await readTextFile(paths.config);
|
|
@@ -10278,7 +10389,7 @@ async function executeMain(paths) {
|
|
|
10278
10389
|
let state = await loadMigrationState(paths);
|
|
10279
10390
|
if (!state) {
|
|
10280
10391
|
if (!await detectV15(paths)) {
|
|
10281
|
-
if (!await fileExists(
|
|
10392
|
+
if (!await fileExists(join8(paths.reap, "v15"))) {
|
|
10282
10393
|
emitError("migrate", "v0.15 structure not found. Cannot proceed.");
|
|
10283
10394
|
}
|
|
10284
10395
|
}
|
|
@@ -10286,7 +10397,7 @@ async function executeMain(paths) {
|
|
|
10286
10397
|
await saveMigrationState(paths, state);
|
|
10287
10398
|
}
|
|
10288
10399
|
const done = new Set(state.completedSteps);
|
|
10289
|
-
const v15Dir =
|
|
10400
|
+
const v15Dir = join8(paths.reap, "v15");
|
|
10290
10401
|
async function step(name, fn) {
|
|
10291
10402
|
if (done.has(name))
|
|
10292
10403
|
return;
|
|
@@ -10297,12 +10408,12 @@ async function executeMain(paths) {
|
|
|
10297
10408
|
await step("backup", async () => {
|
|
10298
10409
|
await ensureDir(v15Dir);
|
|
10299
10410
|
const backupItems = [
|
|
10300
|
-
{ src: paths.genome, dest:
|
|
10301
|
-
{ src: paths.environment, dest:
|
|
10302
|
-
{ src: paths.life, dest:
|
|
10303
|
-
{ src: paths.lineage, dest:
|
|
10304
|
-
{ src: paths.hooks, dest:
|
|
10305
|
-
{ src: paths.config, dest:
|
|
10411
|
+
{ src: paths.genome, dest: join8(v15Dir, "genome") },
|
|
10412
|
+
{ src: paths.environment, dest: join8(v15Dir, "environment") },
|
|
10413
|
+
{ src: paths.life, dest: join8(v15Dir, "life") },
|
|
10414
|
+
{ src: paths.lineage, dest: join8(v15Dir, "lineage") },
|
|
10415
|
+
{ src: paths.hooks, dest: join8(v15Dir, "hooks") },
|
|
10416
|
+
{ src: paths.config, dest: join8(v15Dir, "config.yml") }
|
|
10306
10417
|
];
|
|
10307
10418
|
for (const item of backupItems) {
|
|
10308
10419
|
if (await fileExists(item.src)) {
|
|
@@ -10312,7 +10423,7 @@ async function executeMain(paths) {
|
|
|
10312
10423
|
});
|
|
10313
10424
|
await step("create-dirs", async () => {
|
|
10314
10425
|
await ensureDir(paths.genome);
|
|
10315
|
-
await ensureDir(
|
|
10426
|
+
await ensureDir(join8(paths.environment, "domain"));
|
|
10316
10427
|
await ensureDir(paths.environmentResources);
|
|
10317
10428
|
await ensureDir(paths.environmentDocs);
|
|
10318
10429
|
await ensureDir(paths.life);
|
|
@@ -10320,7 +10431,7 @@ async function executeMain(paths) {
|
|
|
10320
10431
|
await ensureDir(paths.lineage);
|
|
10321
10432
|
await ensureDir(paths.vision);
|
|
10322
10433
|
await ensureDir(paths.visionDesign);
|
|
10323
|
-
await ensureDir(
|
|
10434
|
+
await ensureDir(join8(paths.vision, "memory"));
|
|
10324
10435
|
await ensureDir(paths.hooks);
|
|
10325
10436
|
});
|
|
10326
10437
|
let v16Config = {
|
|
@@ -10334,7 +10445,7 @@ async function executeMain(paths) {
|
|
|
10334
10445
|
autoIssueReport: true
|
|
10335
10446
|
};
|
|
10336
10447
|
await step("config-migrate", async () => {
|
|
10337
|
-
const v15ConfigContent = await readTextFile(
|
|
10448
|
+
const v15ConfigContent = await readTextFile(join8(v15Dir, "config.yml"));
|
|
10338
10449
|
let v15Config = {};
|
|
10339
10450
|
if (v15ConfigContent) {
|
|
10340
10451
|
v15Config = import_yaml6.default.parse(v15ConfigContent) ?? {};
|
|
@@ -10359,46 +10470,46 @@ async function executeMain(paths) {
|
|
|
10359
10470
|
v16Config = { ...v16Config, ...parsed };
|
|
10360
10471
|
}
|
|
10361
10472
|
}
|
|
10362
|
-
const principles = await readTextFile(
|
|
10363
|
-
const conventions = await readTextFile(
|
|
10364
|
-
const constraints = await readTextFile(
|
|
10365
|
-
const sourceMap = await readTextFile(
|
|
10473
|
+
const principles = await readTextFile(join8(v15Dir, "genome", "principles.md")) ?? "";
|
|
10474
|
+
const conventions = await readTextFile(join8(v15Dir, "genome", "conventions.md")) ?? "";
|
|
10475
|
+
const constraints = await readTextFile(join8(v15Dir, "genome", "constraints.md")) ?? "";
|
|
10476
|
+
const sourceMap = await readTextFile(join8(v15Dir, "genome", "source-map.md")) ?? "";
|
|
10366
10477
|
const evolutionTemplate = await readTextFile(distPath2("evolution.md")) ?? "";
|
|
10367
10478
|
const domainFiles = [];
|
|
10368
|
-
const v15DomainDir =
|
|
10479
|
+
const v15DomainDir = join8(v15Dir, "genome", "domain");
|
|
10369
10480
|
try {
|
|
10370
10481
|
const entries = await readdir4(v15DomainDir);
|
|
10371
10482
|
domainFiles.push(...entries.filter((e) => e.endsWith(".md")));
|
|
10372
10483
|
} catch {}
|
|
10373
10484
|
await step("environment-copy", async () => {
|
|
10374
|
-
const v15EnvSummary =
|
|
10485
|
+
const v15EnvSummary = join8(v15Dir, "environment", "summary.md");
|
|
10375
10486
|
if (await fileExists(v15EnvSummary)) {
|
|
10376
10487
|
await cp(v15EnvSummary, paths.environmentSummary);
|
|
10377
10488
|
}
|
|
10378
|
-
const v15EnvDomain =
|
|
10489
|
+
const v15EnvDomain = join8(v15Dir, "environment", "domain");
|
|
10379
10490
|
if (await fileExists(v15EnvDomain)) {
|
|
10380
10491
|
try {
|
|
10381
10492
|
const entries = await readdir4(v15EnvDomain);
|
|
10382
10493
|
for (const e of entries) {
|
|
10383
|
-
await cp(
|
|
10494
|
+
await cp(join8(v15EnvDomain, e), join8(paths.environmentDomain, e), { recursive: true });
|
|
10384
10495
|
}
|
|
10385
10496
|
} catch {}
|
|
10386
10497
|
}
|
|
10387
|
-
const v15EnvResources =
|
|
10498
|
+
const v15EnvResources = join8(v15Dir, "environment", "resources");
|
|
10388
10499
|
if (await fileExists(v15EnvResources)) {
|
|
10389
10500
|
try {
|
|
10390
10501
|
const entries = await readdir4(v15EnvResources);
|
|
10391
10502
|
for (const e of entries) {
|
|
10392
|
-
await cp(
|
|
10503
|
+
await cp(join8(v15EnvResources, e), join8(paths.environmentResources, e), { recursive: true });
|
|
10393
10504
|
}
|
|
10394
10505
|
} catch {}
|
|
10395
10506
|
}
|
|
10396
|
-
const v15EnvDocs =
|
|
10507
|
+
const v15EnvDocs = join8(v15Dir, "environment", "docs");
|
|
10397
10508
|
if (await fileExists(v15EnvDocs)) {
|
|
10398
10509
|
try {
|
|
10399
10510
|
const entries = await readdir4(v15EnvDocs);
|
|
10400
10511
|
for (const e of entries) {
|
|
10401
|
-
await cp(
|
|
10512
|
+
await cp(join8(v15EnvDocs, e), join8(paths.environmentDocs, e), { recursive: true });
|
|
10402
10513
|
}
|
|
10403
10514
|
} catch {}
|
|
10404
10515
|
}
|
|
@@ -10407,8 +10518,8 @@ async function executeMain(paths) {
|
|
|
10407
10518
|
}
|
|
10408
10519
|
if (domainFiles.length > 0) {
|
|
10409
10520
|
for (const f of domainFiles) {
|
|
10410
|
-
const src =
|
|
10411
|
-
const dest =
|
|
10521
|
+
const src = join8(v15DomainDir, f);
|
|
10522
|
+
const dest = join8(paths.environmentDomain, f);
|
|
10412
10523
|
if (await fileExists(src)) {
|
|
10413
10524
|
await cp(src, dest);
|
|
10414
10525
|
}
|
|
@@ -10416,23 +10527,23 @@ async function executeMain(paths) {
|
|
|
10416
10527
|
}
|
|
10417
10528
|
});
|
|
10418
10529
|
await step("lineage-copy", async () => {
|
|
10419
|
-
const v15Lineage =
|
|
10530
|
+
const v15Lineage = join8(v15Dir, "lineage");
|
|
10420
10531
|
if (await fileExists(v15Lineage)) {
|
|
10421
10532
|
try {
|
|
10422
10533
|
const entries = await readdir4(v15Lineage);
|
|
10423
10534
|
for (const e of entries) {
|
|
10424
|
-
await cp(
|
|
10535
|
+
await cp(join8(v15Lineage, e), join8(paths.lineage, e), { recursive: true });
|
|
10425
10536
|
}
|
|
10426
10537
|
} catch {}
|
|
10427
10538
|
}
|
|
10428
10539
|
});
|
|
10429
10540
|
await step("backlog-copy", async () => {
|
|
10430
|
-
const v15Backlog =
|
|
10541
|
+
const v15Backlog = join8(v15Dir, "life", "backlog");
|
|
10431
10542
|
if (await fileExists(v15Backlog)) {
|
|
10432
10543
|
try {
|
|
10433
10544
|
const entries = await readdir4(v15Backlog);
|
|
10434
10545
|
for (const e of entries) {
|
|
10435
|
-
await cp(
|
|
10546
|
+
await cp(join8(v15Backlog, e), join8(paths.backlog, e), { recursive: true });
|
|
10436
10547
|
}
|
|
10437
10548
|
} catch {}
|
|
10438
10549
|
}
|
|
@@ -10440,20 +10551,20 @@ async function executeMain(paths) {
|
|
|
10440
10551
|
const hooksMapped = [];
|
|
10441
10552
|
const hooksUnmapped = [];
|
|
10442
10553
|
await step("hooks-map", async () => {
|
|
10443
|
-
const v15Hooks =
|
|
10554
|
+
const v15Hooks = join8(v15Dir, "hooks");
|
|
10444
10555
|
if (await fileExists(v15Hooks)) {
|
|
10445
10556
|
try {
|
|
10446
10557
|
const entries = await readdir4(v15Hooks);
|
|
10447
10558
|
for (const e of entries) {
|
|
10448
10559
|
if (e === "conditions") {
|
|
10449
|
-
const condSrc =
|
|
10450
|
-
const condDest =
|
|
10560
|
+
const condSrc = join8(v15Hooks, "conditions");
|
|
10561
|
+
const condDest = join8(paths.hooks, "conditions");
|
|
10451
10562
|
await cp(condSrc, condDest, { recursive: true });
|
|
10452
10563
|
continue;
|
|
10453
10564
|
}
|
|
10454
10565
|
const mapping = mapHookFilename(e);
|
|
10455
10566
|
if (mapping) {
|
|
10456
|
-
await cp(
|
|
10567
|
+
await cp(join8(v15Hooks, e), join8(paths.hooks, mapping.newName));
|
|
10457
10568
|
if (mapping.newName !== e) {
|
|
10458
10569
|
hooksMapped.push(`${e} → ${mapping.newName}`);
|
|
10459
10570
|
}
|
|
@@ -10461,7 +10572,7 @@ async function executeMain(paths) {
|
|
|
10461
10572
|
hooksUnmapped.push(e);
|
|
10462
10573
|
}
|
|
10463
10574
|
} else {
|
|
10464
|
-
await cp(
|
|
10575
|
+
await cp(join8(v15Hooks, e), join8(paths.hooks, e));
|
|
10465
10576
|
}
|
|
10466
10577
|
}
|
|
10467
10578
|
} catch {}
|
|
@@ -10481,20 +10592,20 @@ async function executeMain(paths) {
|
|
|
10481
10592
|
## Goal Items
|
|
10482
10593
|
<!-- Checklist of major milestones -->
|
|
10483
10594
|
`;
|
|
10484
|
-
await writeTextFile(
|
|
10485
|
-
await writeTextFile(
|
|
10595
|
+
await writeTextFile(join8(paths.vision, "goals.md"), goalsContent);
|
|
10596
|
+
await writeTextFile(join8(paths.vision, "memory", "longterm.md"), `# Longterm Memory
|
|
10486
10597
|
`);
|
|
10487
|
-
await writeTextFile(
|
|
10598
|
+
await writeTextFile(join8(paths.vision, "memory", "midterm.md"), `# Midterm Memory
|
|
10488
10599
|
`);
|
|
10489
|
-
await writeTextFile(
|
|
10600
|
+
await writeTextFile(join8(paths.vision, "memory", "shortterm.md"), `# Shortterm Memory
|
|
10490
10601
|
`);
|
|
10491
10602
|
});
|
|
10492
10603
|
await step("reap-guide", async () => {
|
|
10493
10604
|
const guide = await readTextFile(distPath2("reap-guide.md"));
|
|
10494
10605
|
if (guide) {
|
|
10495
|
-
const reapHome =
|
|
10606
|
+
const reapHome = join8(homedir2(), ".reap");
|
|
10496
10607
|
await ensureDir(reapHome);
|
|
10497
|
-
await writeTextFile(
|
|
10608
|
+
await writeTextFile(join8(reapHome, "reap-guide.md"), guide);
|
|
10498
10609
|
}
|
|
10499
10610
|
});
|
|
10500
10611
|
await step("claude-md", async () => {
|
|
@@ -10734,12 +10845,12 @@ var PROJECT_FILES = [
|
|
|
10734
10845
|
var SOURCE_GLOBS = [".ts", ".js", ".py", ".rs", ".go", ".java", ".rb", ".php", ".swift", ".kt"];
|
|
10735
10846
|
async function detectMode(root) {
|
|
10736
10847
|
for (const file of PROJECT_FILES) {
|
|
10737
|
-
if (await fileExists(
|
|
10848
|
+
if (await fileExists(join9(root, file))) {
|
|
10738
10849
|
return "adoption";
|
|
10739
10850
|
}
|
|
10740
10851
|
}
|
|
10741
10852
|
for (const dir of SOURCE_DIRS) {
|
|
10742
|
-
if (await fileExists(
|
|
10853
|
+
if (await fileExists(join9(root, dir))) {
|
|
10743
10854
|
return "adoption";
|
|
10744
10855
|
}
|
|
10745
10856
|
}
|
|
@@ -10866,7 +10977,7 @@ function autoReport(command, error, extraLabels) {
|
|
|
10866
10977
|
|
|
10867
10978
|
// src/cli/commands/run/start.ts
|
|
10868
10979
|
var import_yaml12 = __toESM(require_dist(), 1);
|
|
10869
|
-
import { basename, join as
|
|
10980
|
+
import { basename, join as join14 } from "path";
|
|
10870
10981
|
|
|
10871
10982
|
// src/core/generation.ts
|
|
10872
10983
|
init_fs();
|
|
@@ -10984,13 +11095,13 @@ init_fs();
|
|
|
10984
11095
|
init_fs();
|
|
10985
11096
|
var import_yaml9 = __toESM(require_dist(), 1);
|
|
10986
11097
|
import { readdir as readdir8 } from "fs/promises";
|
|
10987
|
-
import { join as
|
|
11098
|
+
import { join as join10 } from "path";
|
|
10988
11099
|
import { execSync as execSync4 } from "child_process";
|
|
10989
11100
|
async function executeHooks(hooksDir, event, projectRoot) {
|
|
10990
11101
|
const hooks = await scanHooks(hooksDir, event);
|
|
10991
11102
|
if (hooks.length === 0)
|
|
10992
11103
|
return [];
|
|
10993
|
-
const conditionsDir =
|
|
11104
|
+
const conditionsDir = join10(hooksDir, "conditions");
|
|
10994
11105
|
const results = [];
|
|
10995
11106
|
for (const hook of hooks) {
|
|
10996
11107
|
const conditionMet = await evaluateCondition(conditionsDir, hook.condition, projectRoot);
|
|
@@ -11025,7 +11136,7 @@ async function scanHooks(hooksDir, event) {
|
|
|
11025
11136
|
const match = filename.match(pattern);
|
|
11026
11137
|
if (!match)
|
|
11027
11138
|
continue;
|
|
11028
|
-
const meta = await parseHookMeta(
|
|
11139
|
+
const meta = await parseHookMeta(join10(hooksDir, filename), match[2]);
|
|
11029
11140
|
hooks.push({
|
|
11030
11141
|
filename,
|
|
11031
11142
|
name: match[1],
|
|
@@ -11072,7 +11183,7 @@ async function parseHookMeta(filePath, ext) {
|
|
|
11072
11183
|
async function evaluateCondition(conditionsDir, conditionName, projectRoot) {
|
|
11073
11184
|
if (conditionName === "always")
|
|
11074
11185
|
return { met: true };
|
|
11075
|
-
const scriptPath =
|
|
11186
|
+
const scriptPath = join10(conditionsDir, `${conditionName}.sh`);
|
|
11076
11187
|
if (!await fileExists(scriptPath)) {
|
|
11077
11188
|
return { met: false, reason: `condition script not found: ${conditionName}.sh` };
|
|
11078
11189
|
}
|
|
@@ -11085,7 +11196,7 @@ async function evaluateCondition(conditionsDir, conditionName, projectRoot) {
|
|
|
11085
11196
|
}
|
|
11086
11197
|
async function executeShHook(hook, event, projectRoot, hooksDir) {
|
|
11087
11198
|
try {
|
|
11088
|
-
const stdout = execSync4(`bash "${
|
|
11199
|
+
const stdout = execSync4(`bash "${join10(hooksDir, hook.filename)}"`, {
|
|
11089
11200
|
cwd: projectRoot,
|
|
11090
11201
|
timeout: 60000,
|
|
11091
11202
|
stdio: "pipe"
|
|
@@ -11111,7 +11222,7 @@ async function executeShHook(hook, event, projectRoot, hooksDir) {
|
|
|
11111
11222
|
}
|
|
11112
11223
|
}
|
|
11113
11224
|
async function executeMdHook(hook, event, hooksDir) {
|
|
11114
|
-
const content = await readTextFile(
|
|
11225
|
+
const content = await readTextFile(join10(hooksDir, hook.filename));
|
|
11115
11226
|
const body = content?.replace(/^---\n[\s\S]*?\n---\n?/, "").trim() ?? "";
|
|
11116
11227
|
return {
|
|
11117
11228
|
name: hook.name,
|
|
@@ -11126,7 +11237,7 @@ async function executeMdHook(hook, event, hooksDir) {
|
|
|
11126
11237
|
init_fs();
|
|
11127
11238
|
var import_yaml10 = __toESM(require_dist(), 1);
|
|
11128
11239
|
import { readdir as readdir9 } from "fs/promises";
|
|
11129
|
-
import { join as
|
|
11240
|
+
import { join as join11 } from "path";
|
|
11130
11241
|
async function scanBacklog(backlogDir) {
|
|
11131
11242
|
let entries;
|
|
11132
11243
|
try {
|
|
@@ -11138,7 +11249,7 @@ async function scanBacklog(backlogDir) {
|
|
|
11138
11249
|
for (const entry of entries) {
|
|
11139
11250
|
if (!entry.endsWith(".md"))
|
|
11140
11251
|
continue;
|
|
11141
|
-
const filePath =
|
|
11252
|
+
const filePath = join11(backlogDir, entry);
|
|
11142
11253
|
const content = await readTextFile(filePath);
|
|
11143
11254
|
if (!content)
|
|
11144
11255
|
continue;
|
|
@@ -11281,7 +11392,7 @@ ${body}
|
|
|
11281
11392
|
`;
|
|
11282
11393
|
const { mkdir: mkdir3 } = await import("fs/promises");
|
|
11283
11394
|
await mkdir3(backlogDir, { recursive: true });
|
|
11284
|
-
await writeTextFile(
|
|
11395
|
+
await writeTextFile(join11(backlogDir, filename), content);
|
|
11285
11396
|
return filename;
|
|
11286
11397
|
}
|
|
11287
11398
|
async function createDeferredBacklog(backlogDir, input) {
|
|
@@ -11311,7 +11422,7 @@ ${tasksSection}
|
|
|
11311
11422
|
`;
|
|
11312
11423
|
const { mkdir: mkdir3 } = await import("fs/promises");
|
|
11313
11424
|
await mkdir3(backlogDir, { recursive: true });
|
|
11314
|
-
await writeTextFile(
|
|
11425
|
+
await writeTextFile(join11(backlogDir, filename), content);
|
|
11315
11426
|
return filename;
|
|
11316
11427
|
}
|
|
11317
11428
|
function extractUncheckedTasks(artifactContent) {
|
|
@@ -11334,7 +11445,7 @@ function countCheckedTasks(artifactContent) {
|
|
|
11334
11445
|
init_fs();
|
|
11335
11446
|
var import_yaml11 = __toESM(require_dist(), 1);
|
|
11336
11447
|
import { readdir as readdir10, stat as stat3 } from "fs/promises";
|
|
11337
|
-
import { join as
|
|
11448
|
+
import { join as join12 } from "path";
|
|
11338
11449
|
import { execSync as execSync5 } from "child_process";
|
|
11339
11450
|
function gitShow(cwd, ref, path) {
|
|
11340
11451
|
try {
|
|
@@ -11395,7 +11506,7 @@ async function getLastLineageEntry(paths) {
|
|
|
11395
11506
|
if (genEntries.length === 0)
|
|
11396
11507
|
return null;
|
|
11397
11508
|
const last = genEntries[genEntries.length - 1];
|
|
11398
|
-
const lastPath =
|
|
11509
|
+
const lastPath = join12(paths.lineage, last);
|
|
11399
11510
|
try {
|
|
11400
11511
|
const st = await stat3(lastPath);
|
|
11401
11512
|
if (!st.isDirectory())
|
|
@@ -11403,7 +11514,7 @@ async function getLastLineageEntry(paths) {
|
|
|
11403
11514
|
} catch {
|
|
11404
11515
|
return null;
|
|
11405
11516
|
}
|
|
11406
|
-
const metaContent = await readTextFile(
|
|
11517
|
+
const metaContent = await readTextFile(join12(lastPath, "meta.yml"));
|
|
11407
11518
|
if (!metaContent)
|
|
11408
11519
|
return null;
|
|
11409
11520
|
let parsed;
|
|
@@ -11546,7 +11657,7 @@ async function execute8(phase, goal, type, parents, backlog) {
|
|
|
11546
11657
|
const state = await gm.create(goal, genType);
|
|
11547
11658
|
let consumeWarning;
|
|
11548
11659
|
if (backlogFilename) {
|
|
11549
|
-
const backlogPath =
|
|
11660
|
+
const backlogPath = join14(paths.backlog, backlogFilename);
|
|
11550
11661
|
if (await fileExists(backlogPath)) {
|
|
11551
11662
|
const result = await consumeBacklog(backlogPath, state.id);
|
|
11552
11663
|
if (result.status === "warning" && result.warning) {
|
|
@@ -11594,7 +11705,7 @@ async function execute8(phase, goal, type, parents, backlog) {
|
|
|
11594
11705
|
init_fs();
|
|
11595
11706
|
var import_yaml13 = __toESM(require_dist(), 1);
|
|
11596
11707
|
import { readdir as readdir11 } from "fs/promises";
|
|
11597
|
-
import { basename as basename2, join as
|
|
11708
|
+
import { basename as basename2, join as join16 } from "path";
|
|
11598
11709
|
|
|
11599
11710
|
// src/core/lifecycle.ts
|
|
11600
11711
|
init_types();
|
|
@@ -11777,8 +11888,8 @@ async function performMergeTransition(state, gm, paths) {
|
|
|
11777
11888
|
|
|
11778
11889
|
// src/core/template.ts
|
|
11779
11890
|
init_fs();
|
|
11780
|
-
import { join as
|
|
11781
|
-
import { fileURLToPath as
|
|
11891
|
+
import { join as join15, dirname as dirname7 } from "path";
|
|
11892
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
11782
11893
|
import { copyFile as copyFile2 } from "fs/promises";
|
|
11783
11894
|
var STAGE_ARTIFACTS2 = {
|
|
11784
11895
|
learning: "01-learning.md",
|
|
@@ -11804,11 +11915,11 @@ async function copyArtifactTemplate(stage, artifactPath, isMerge) {
|
|
|
11804
11915
|
if (await fileExists(destPath))
|
|
11805
11916
|
return;
|
|
11806
11917
|
const subdir = isMerge ? "merge" : "normal";
|
|
11807
|
-
const __dirname2 =
|
|
11808
|
-
const templatePath =
|
|
11918
|
+
const __dirname2 = dirname7(fileURLToPath6(import.meta.url));
|
|
11919
|
+
const templatePath = join15(__dirname2, "..", "templates", "artifacts", subdir, filename);
|
|
11809
11920
|
if (!await fileExists(templatePath))
|
|
11810
11921
|
return;
|
|
11811
|
-
await ensureDir(
|
|
11922
|
+
await ensureDir(dirname7(destPath));
|
|
11812
11923
|
await copyFile2(templatePath, destPath);
|
|
11813
11924
|
}
|
|
11814
11925
|
|
|
@@ -11830,7 +11941,7 @@ async function execute9(paths, phase) {
|
|
|
11830
11941
|
const envSummary = await readTextFile(paths.environmentSummary);
|
|
11831
11942
|
let sourceBacklogContent = null;
|
|
11832
11943
|
if (s.sourceBacklog) {
|
|
11833
|
-
sourceBacklogContent = await readTextFile(
|
|
11944
|
+
sourceBacklogContent = await readTextFile(join16(paths.backlog, s.sourceBacklog)) ?? await readTextFile(join16(paths.life, "backlog", s.sourceBacklog));
|
|
11834
11945
|
}
|
|
11835
11946
|
const backlogItems = await scanBacklog(paths.backlog);
|
|
11836
11947
|
const pendingBacklog = backlogItems.filter((b) => b.status === "pending");
|
|
@@ -11841,8 +11952,8 @@ async function execute9(paths, phase) {
|
|
|
11841
11952
|
const genDirs = lineageEntries.filter((e) => e.startsWith("gen-")).sort();
|
|
11842
11953
|
if (genDirs.length > 0) {
|
|
11843
11954
|
const lastGen = genDirs[genDirs.length - 1];
|
|
11844
|
-
prevCompletion = await readTextFile(
|
|
11845
|
-
const metaContent = await readTextFile(
|
|
11955
|
+
prevCompletion = await readTextFile(join16(paths.lineage, lastGen, "05-completion.md"));
|
|
11956
|
+
const metaContent = await readTextFile(join16(paths.lineage, lastGen, "meta.yml"));
|
|
11846
11957
|
if (metaContent) {
|
|
11847
11958
|
const fitnessMatch = metaContent.match(/fitnessFeedback:\n\s+text:\s*([\s\S]*?)(?:\n\s+evaluatedAt:|\n[a-z])/);
|
|
11848
11959
|
if (fitnessMatch)
|
|
@@ -12378,14 +12489,14 @@ init_fs();
|
|
|
12378
12489
|
// src/core/archive.ts
|
|
12379
12490
|
init_fs();
|
|
12380
12491
|
var import_yaml17 = __toESM(require_dist(), 1);
|
|
12381
|
-
import { join as
|
|
12492
|
+
import { join as join18 } from "path";
|
|
12382
12493
|
import { readdir as readdir13, rm as rm4, unlink } from "fs/promises";
|
|
12383
12494
|
|
|
12384
12495
|
// src/core/compression.ts
|
|
12385
12496
|
init_fs();
|
|
12386
12497
|
var import_yaml16 = __toESM(require_dist(), 1);
|
|
12387
12498
|
import { readdir as readdir12, rm as rm3 } from "fs/promises";
|
|
12388
|
-
import { join as
|
|
12499
|
+
import { join as join17 } from "path";
|
|
12389
12500
|
var LEVEL1_THRESHOLD = 20;
|
|
12390
12501
|
var PROTECTED_RECENT = 20;
|
|
12391
12502
|
var LEVEL2_THRESHOLD = 100;
|
|
@@ -12402,7 +12513,7 @@ async function compressLineage(lineageDir) {
|
|
|
12402
12513
|
const { stat: stat4 } = await import("fs/promises");
|
|
12403
12514
|
const uncompressed = [];
|
|
12404
12515
|
for (const entry of genDirs) {
|
|
12405
|
-
const s = await stat4(
|
|
12516
|
+
const s = await stat4(join17(lineageDir, entry)).catch(() => null);
|
|
12406
12517
|
if (s?.isDirectory())
|
|
12407
12518
|
uncompressed.push(entry);
|
|
12408
12519
|
}
|
|
@@ -12411,15 +12522,15 @@ async function compressLineage(lineageDir) {
|
|
|
12411
12522
|
return 0;
|
|
12412
12523
|
let compressed = 0;
|
|
12413
12524
|
for (const dirName of toCompress) {
|
|
12414
|
-
const dirPath =
|
|
12415
|
-
const metaContent = await readTextFile(
|
|
12525
|
+
const dirPath = join17(lineageDir, dirName);
|
|
12526
|
+
const metaContent = await readTextFile(join17(dirPath, "meta.yml"));
|
|
12416
12527
|
let meta = { id: dirName, type: "unknown", goal: "", parents: [] };
|
|
12417
12528
|
if (metaContent) {
|
|
12418
12529
|
try {
|
|
12419
12530
|
meta = import_yaml16.default.parse(metaContent);
|
|
12420
12531
|
} catch {}
|
|
12421
12532
|
}
|
|
12422
|
-
const completion = await readTextFile(
|
|
12533
|
+
const completion = await readTextFile(join17(dirPath, "05-completion.md")) ?? "";
|
|
12423
12534
|
const summarySection = completion.match(/## Summary\n([\s\S]*?)(?=\n## |\n$)/)?.[1]?.trim() ?? "";
|
|
12424
12535
|
const compressedContent = [
|
|
12425
12536
|
"---",
|
|
@@ -12436,7 +12547,7 @@ async function compressLineage(lineageDir) {
|
|
|
12436
12547
|
""
|
|
12437
12548
|
].filter(Boolean).join(`
|
|
12438
12549
|
`);
|
|
12439
|
-
await writeTextFile(
|
|
12550
|
+
await writeTextFile(join17(lineageDir, `${dirName}.md`), compressedContent);
|
|
12440
12551
|
await rm3(dirPath, { recursive: true, force: true });
|
|
12441
12552
|
compressed++;
|
|
12442
12553
|
}
|
|
@@ -12455,7 +12566,7 @@ async function compressToEpoch(lineageDir) {
|
|
|
12455
12566
|
for (const entry of entries) {
|
|
12456
12567
|
if (!entry.startsWith("gen-") || !entry.endsWith(".md"))
|
|
12457
12568
|
continue;
|
|
12458
|
-
const s = await stat4(
|
|
12569
|
+
const s = await stat4(join17(lineageDir, entry)).catch(() => null);
|
|
12459
12570
|
if (s?.isFile())
|
|
12460
12571
|
level1Files.push(entry);
|
|
12461
12572
|
}
|
|
@@ -12464,7 +12575,7 @@ async function compressToEpoch(lineageDir) {
|
|
|
12464
12575
|
const allParents = new Set;
|
|
12465
12576
|
const fileMetas = [];
|
|
12466
12577
|
for (const file of level1Files.sort()) {
|
|
12467
|
-
const content = await readTextFile(
|
|
12578
|
+
const content = await readTextFile(join17(lineageDir, file));
|
|
12468
12579
|
if (!content)
|
|
12469
12580
|
continue;
|
|
12470
12581
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
@@ -12484,7 +12595,7 @@ async function compressToEpoch(lineageDir) {
|
|
|
12484
12595
|
const dirEntries = entries.filter((e) => e.startsWith("gen-") && !e.endsWith(".md"));
|
|
12485
12596
|
const dirParents = new Set;
|
|
12486
12597
|
for (const dir of dirEntries) {
|
|
12487
|
-
const metaContent = await readTextFile(
|
|
12598
|
+
const metaContent = await readTextFile(join17(lineageDir, dir, "meta.yml"));
|
|
12488
12599
|
if (!metaContent)
|
|
12489
12600
|
continue;
|
|
12490
12601
|
try {
|
|
@@ -12495,7 +12606,7 @@ async function compressToEpoch(lineageDir) {
|
|
|
12495
12606
|
}
|
|
12496
12607
|
const epochFiles = entries.filter((e) => e.startsWith("epoch-") && e.endsWith(".md"));
|
|
12497
12608
|
for (const ef of epochFiles) {
|
|
12498
|
-
const content = await readTextFile(
|
|
12609
|
+
const content = await readTextFile(join17(lineageDir, ef));
|
|
12499
12610
|
if (!content)
|
|
12500
12611
|
continue;
|
|
12501
12612
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
@@ -12539,9 +12650,9 @@ async function compressToEpoch(lineageDir) {
|
|
|
12539
12650
|
""
|
|
12540
12651
|
].join(`
|
|
12541
12652
|
`);
|
|
12542
|
-
await writeTextFile(
|
|
12653
|
+
await writeTextFile(join17(lineageDir, epochName), epochContent);
|
|
12543
12654
|
for (const f of compressible) {
|
|
12544
|
-
await rm3(
|
|
12655
|
+
await rm3(join17(lineageDir, f.filename), { force: true });
|
|
12545
12656
|
}
|
|
12546
12657
|
return compressible.length;
|
|
12547
12658
|
}
|
|
@@ -12549,7 +12660,7 @@ async function compressToEpoch(lineageDir) {
|
|
|
12549
12660
|
// src/core/archive.ts
|
|
12550
12661
|
function buildArchiveDir(lineageRoot, state) {
|
|
12551
12662
|
const goalSlug = state.goal.toLowerCase().replace(/[^a-z0-9가-힣]+/g, "-").slice(0, 40).replace(/-+$/, "");
|
|
12552
|
-
return
|
|
12663
|
+
return join18(lineageRoot, `${state.id}-${goalSlug}`);
|
|
12553
12664
|
}
|
|
12554
12665
|
async function writeArchive(paths, state, archiveDir, extraMeta) {
|
|
12555
12666
|
await ensureDir(archiveDir);
|
|
@@ -12557,20 +12668,20 @@ async function writeArchive(paths, state, archiveDir, extraMeta) {
|
|
|
12557
12668
|
for (const entry of lifeEntries) {
|
|
12558
12669
|
if (entry === "current.yml" || entry === "backlog")
|
|
12559
12670
|
continue;
|
|
12560
|
-
const src =
|
|
12561
|
-
const dest =
|
|
12671
|
+
const src = join18(paths.life, entry);
|
|
12672
|
+
const dest = join18(archiveDir, entry);
|
|
12562
12673
|
const { cp: cp2 } = await import("fs/promises");
|
|
12563
12674
|
await cp2(src, dest, { recursive: true });
|
|
12564
12675
|
}
|
|
12565
12676
|
const backlogItems = await scanBacklog(paths.backlog);
|
|
12566
12677
|
const consumedItems = backlogItems.filter((b) => b.status === "consumed");
|
|
12567
12678
|
if (consumedItems.length > 0) {
|
|
12568
|
-
const archiveBacklogDir =
|
|
12679
|
+
const archiveBacklogDir = join18(archiveDir, "backlog");
|
|
12569
12680
|
await ensureDir(archiveBacklogDir);
|
|
12570
12681
|
for (const item of consumedItems) {
|
|
12571
12682
|
const content = await readTextFile(item.path);
|
|
12572
12683
|
if (content) {
|
|
12573
|
-
await writeTextFile(
|
|
12684
|
+
await writeTextFile(join18(archiveBacklogDir, item.filename), content);
|
|
12574
12685
|
}
|
|
12575
12686
|
await unlink(item.path).catch(() => {});
|
|
12576
12687
|
}
|
|
@@ -12583,11 +12694,11 @@ async function writeArchive(paths, state, archiveDir, extraMeta) {
|
|
|
12583
12694
|
timeline: state.timeline,
|
|
12584
12695
|
...extraMeta
|
|
12585
12696
|
};
|
|
12586
|
-
await writeTextFile(
|
|
12697
|
+
await writeTextFile(join18(archiveDir, "meta.yml"), import_yaml17.default.stringify(meta));
|
|
12587
12698
|
for (const entry of lifeEntries) {
|
|
12588
12699
|
if (entry === "backlog")
|
|
12589
12700
|
continue;
|
|
12590
|
-
await rm4(
|
|
12701
|
+
await rm4(join18(paths.life, entry), { recursive: true, force: true });
|
|
12591
12702
|
}
|
|
12592
12703
|
await compressLineage(paths.lineage).catch(() => {});
|
|
12593
12704
|
}
|
|
@@ -13284,9 +13395,9 @@ async function execute13(paths, phase, feedback) {
|
|
|
13284
13395
|
verifyTransition("completion", s, "completion:commit");
|
|
13285
13396
|
if (feedback) {
|
|
13286
13397
|
const filenames = feedback.split(",").map((f) => f.trim()).filter(Boolean);
|
|
13287
|
-
const { join:
|
|
13398
|
+
const { join: join19 } = await import("path");
|
|
13288
13399
|
for (const filename of filenames) {
|
|
13289
|
-
await consumeBacklog(
|
|
13400
|
+
await consumeBacklog(join19(paths.backlog, filename), s.id);
|
|
13290
13401
|
}
|
|
13291
13402
|
}
|
|
13292
13403
|
const fitnessFeedback = s.fitnessFeedback;
|
|
@@ -13512,7 +13623,7 @@ async function execute16(paths) {
|
|
|
13512
13623
|
|
|
13513
13624
|
// src/cli/commands/run/abort.ts
|
|
13514
13625
|
import { readdir as readdir15, rm as rm5 } from "fs/promises";
|
|
13515
|
-
import { join as
|
|
13626
|
+
import { join as join19 } from "path";
|
|
13516
13627
|
init_fs();
|
|
13517
13628
|
function parseExtra(extra) {
|
|
13518
13629
|
if (!extra)
|
|
@@ -13588,7 +13699,7 @@ createdAt: ${new Date().toISOString()}
|
|
|
13588
13699
|
## Progress
|
|
13589
13700
|
<!-- Progress from the aborted generation can be referenced here -->
|
|
13590
13701
|
`;
|
|
13591
|
-
await writeTextFile(
|
|
13702
|
+
await writeTextFile(join19(paths.backlog, filename), content);
|
|
13592
13703
|
savedBacklogFile = filename;
|
|
13593
13704
|
}
|
|
13594
13705
|
const revertedCount = await revertBacklogConsumed(paths.backlog, id);
|
|
@@ -13596,7 +13707,7 @@ createdAt: ${new Date().toISOString()}
|
|
|
13596
13707
|
for (const entry of lifeEntries) {
|
|
13597
13708
|
if (entry === "backlog")
|
|
13598
13709
|
continue;
|
|
13599
|
-
await rm5(
|
|
13710
|
+
await rm5(join19(paths.life, entry), { recursive: true, force: true });
|
|
13600
13711
|
}
|
|
13601
13712
|
emitOutput({
|
|
13602
13713
|
status: "ok",
|
|
@@ -13617,7 +13728,7 @@ createdAt: ${new Date().toISOString()}
|
|
|
13617
13728
|
}
|
|
13618
13729
|
|
|
13619
13730
|
// src/cli/commands/run/early-close.ts
|
|
13620
|
-
import { join as
|
|
13731
|
+
import { join as join20 } from "path";
|
|
13621
13732
|
init_fs();
|
|
13622
13733
|
function parseExtra2(extra) {
|
|
13623
13734
|
if (!extra)
|
|
@@ -13756,7 +13867,7 @@ async function execute18(paths, phase, extra) {
|
|
|
13756
13867
|
message: [
|
|
13757
13868
|
`Generation ${s.id} early-closed at stage '${s.stage}' (reason: ${reason}).`,
|
|
13758
13869
|
`Archived: ${archiveDir}`,
|
|
13759
|
-
deferredBacklogFile ? `Deferred backlog: ${
|
|
13870
|
+
deferredBacklogFile ? `Deferred backlog: ${join20(paths.backlog, deferredBacklogFile)} (${deferredTaskCount} task(s))` : `Defer skipped — ${deferredTaskCount} unchecked task(s) found but not carried over.`,
|
|
13760
13871
|
commitHash ? `Commit: ${commitHash}` : "Commit your changes manually."
|
|
13761
13872
|
].join(" ")
|
|
13762
13873
|
});
|
|
@@ -14593,7 +14704,7 @@ async function makeBacklog(paths, options) {
|
|
|
14593
14704
|
}
|
|
14594
14705
|
|
|
14595
14706
|
// src/cli/commands/make/hook.ts
|
|
14596
|
-
import { join as
|
|
14707
|
+
import { join as join21 } from "path";
|
|
14597
14708
|
import { chmod as chmod2 } from "fs/promises";
|
|
14598
14709
|
init_fs();
|
|
14599
14710
|
var VALID_EVENTS = [
|
|
@@ -14631,7 +14742,7 @@ ${VALID_EVENTS.join(`
|
|
|
14631
14742
|
emitError("make", "Invalid --type. Use 'sh' or 'md'.");
|
|
14632
14743
|
}
|
|
14633
14744
|
const filename = `${event}.${name}.${type}`;
|
|
14634
|
-
const filePath =
|
|
14745
|
+
const filePath = join21(paths.hooks, filename);
|
|
14635
14746
|
await ensureDir(paths.hooks);
|
|
14636
14747
|
if (await fileExists(filePath)) {
|
|
14637
14748
|
emitError("make", `Hook already exists: ${filename}`);
|
|
@@ -14706,29 +14817,29 @@ var import_yaml23 = __toESM(require_dist(), 1);
|
|
|
14706
14817
|
// src/adapters/claude-code/install.ts
|
|
14707
14818
|
init_fs();
|
|
14708
14819
|
import { readdir as readdir16, cp as cp2, unlink as unlink2, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
14709
|
-
import { join as
|
|
14710
|
-
import { fileURLToPath as
|
|
14820
|
+
import { join as join22, dirname as dirname8 } from "path";
|
|
14821
|
+
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
14711
14822
|
import { homedir as homedir4 } from "os";
|
|
14712
|
-
var __dirname2 =
|
|
14713
|
-
var SKILLS_DIR = __dirname2.includes("dist") ?
|
|
14823
|
+
var __dirname2 = dirname8(fileURLToPath7(import.meta.url));
|
|
14824
|
+
var SKILLS_DIR = __dirname2.includes("dist") ? join22(__dirname2, "..", "adapters", "claude-code", "skills") : join22(__dirname2, "skills");
|
|
14714
14825
|
var SKILL_PATTERN = /^reap\..+\.md$/;
|
|
14715
14826
|
async function cleanupStaleSkills(targetDir) {
|
|
14716
14827
|
const files = await readdir16(targetDir);
|
|
14717
14828
|
const staleFiles = files.filter((f) => SKILL_PATTERN.test(f));
|
|
14718
14829
|
for (const file of staleFiles) {
|
|
14719
|
-
await unlink2(
|
|
14830
|
+
await unlink2(join22(targetDir, file));
|
|
14720
14831
|
}
|
|
14721
14832
|
return staleFiles;
|
|
14722
14833
|
}
|
|
14723
14834
|
async function installSlashCommandsOnly() {
|
|
14724
|
-
const targetDir =
|
|
14835
|
+
const targetDir = join22(homedir4(), ".claude", "commands");
|
|
14725
14836
|
await ensureDir(targetDir);
|
|
14726
14837
|
const cleaned = await cleanupStaleSkills(targetDir);
|
|
14727
14838
|
const files = await readdir16(SKILLS_DIR);
|
|
14728
14839
|
const mdFiles = files.filter((f) => f.endsWith(".md"));
|
|
14729
14840
|
let installed = 0;
|
|
14730
14841
|
for (const file of mdFiles) {
|
|
14731
|
-
await cp2(
|
|
14842
|
+
await cp2(join22(SKILLS_DIR, file), join22(targetDir, file));
|
|
14732
14843
|
installed++;
|
|
14733
14844
|
}
|
|
14734
14845
|
return { cleaned, installed, files: mdFiles, targetDir };
|
|
@@ -14753,17 +14864,17 @@ async function installSkills(_projectRoot) {
|
|
|
14753
14864
|
}
|
|
14754
14865
|
var AGENT_PATTERN = /^reap-.+\.md$/;
|
|
14755
14866
|
function agentsTemplateDir() {
|
|
14756
|
-
return __dirname2.includes("dist") ?
|
|
14867
|
+
return __dirname2.includes("dist") ? join22(__dirname2, "..", "templates", "agents") : join22(__dirname2, "..", "..", "templates", "agents");
|
|
14757
14868
|
}
|
|
14758
14869
|
async function installAgents(home = homedir4()) {
|
|
14759
|
-
const targetDir =
|
|
14870
|
+
const targetDir = join22(home, ".claude", "agents");
|
|
14760
14871
|
await ensureDir(targetDir);
|
|
14761
14872
|
let cleaned = [];
|
|
14762
14873
|
try {
|
|
14763
14874
|
const existing = await readdir16(targetDir);
|
|
14764
14875
|
cleaned = existing.filter((f) => AGENT_PATTERN.test(f));
|
|
14765
14876
|
for (const file of cleaned) {
|
|
14766
|
-
await unlink2(
|
|
14877
|
+
await unlink2(join22(targetDir, file));
|
|
14767
14878
|
}
|
|
14768
14879
|
} catch {}
|
|
14769
14880
|
let installed = 0;
|
|
@@ -14774,7 +14885,7 @@ async function installAgents(home = homedir4()) {
|
|
|
14774
14885
|
for (const file of sources) {
|
|
14775
14886
|
if (!file.endsWith(".md"))
|
|
14776
14887
|
continue;
|
|
14777
|
-
await cp2(
|
|
14888
|
+
await cp2(join22(templateDir, file), join22(targetDir, file));
|
|
14778
14889
|
files.push(file);
|
|
14779
14890
|
installed++;
|
|
14780
14891
|
}
|
|
@@ -14782,16 +14893,16 @@ async function installAgents(home = homedir4()) {
|
|
|
14782
14893
|
return { cleaned, installed, files, targetDir };
|
|
14783
14894
|
}
|
|
14784
14895
|
async function installReapGuide() {
|
|
14785
|
-
const reapHome =
|
|
14896
|
+
const reapHome = join22(homedir4(), ".reap");
|
|
14786
14897
|
await ensureDir(reapHome);
|
|
14787
|
-
const templateDir = __dirname2.includes("dist") ?
|
|
14788
|
-
const src =
|
|
14898
|
+
const templateDir = __dirname2.includes("dist") ? join22(__dirname2, "..", "templates") : join22(__dirname2, "..", "..", "templates");
|
|
14899
|
+
const src = join22(templateDir, "reap-guide.md");
|
|
14789
14900
|
if (await fileExists(src)) {
|
|
14790
|
-
await cp2(src,
|
|
14901
|
+
await cp2(src, join22(reapHome, "reap-guide.md"));
|
|
14791
14902
|
}
|
|
14792
14903
|
}
|
|
14793
14904
|
async function registerSessionHooks() {
|
|
14794
|
-
const settingsPath =
|
|
14905
|
+
const settingsPath = join22(homedir4(), ".claude", "settings.json");
|
|
14795
14906
|
const requiredHooks = [
|
|
14796
14907
|
{ command: "reap check-version 2>/dev/null || true", marker: "reap check-version" },
|
|
14797
14908
|
{ command: "reap load-context 2>/dev/null || true", marker: "reap load-context" }
|
|
@@ -14850,13 +14961,13 @@ var claudeCodeAdapter = {
|
|
|
14850
14961
|
// src/adapters/opencode/install.ts
|
|
14851
14962
|
init_fs();
|
|
14852
14963
|
import { cp as cp3, readFile as readFile4, writeFile as writeFile4, readdir as readdir17, unlink as unlink3 } from "fs/promises";
|
|
14853
|
-
import { join as
|
|
14854
|
-
import { fileURLToPath as
|
|
14964
|
+
import { join as join23, dirname as dirname9 } from "path";
|
|
14965
|
+
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
14855
14966
|
import { homedir as homedir5 } from "os";
|
|
14856
14967
|
import { createHash as createHash4 } from "crypto";
|
|
14857
|
-
var __dirname3 =
|
|
14968
|
+
var __dirname3 = dirname9(fileURLToPath8(import.meta.url));
|
|
14858
14969
|
function assetPath(...segments) {
|
|
14859
|
-
return __dirname3.includes("dist") ?
|
|
14970
|
+
return __dirname3.includes("dist") ? join23(__dirname3, "..", "adapters", "opencode", ...segments) : join23(__dirname3, ...segments);
|
|
14860
14971
|
}
|
|
14861
14972
|
var PLUGIN_FILENAME = "reap-plugin.ts";
|
|
14862
14973
|
var PLUGIN_SRC = assetPath("plugin", PLUGIN_FILENAME);
|
|
@@ -14914,7 +15025,7 @@ async function ensureAgentsMd(projectRoot, projectName) {
|
|
|
14914
15025
|
const inner = stripMarkers2(rawTemplate);
|
|
14915
15026
|
const wrapped = wrapWithMarkers2(inner);
|
|
14916
15027
|
const newHash = computeSectionHash2(inner);
|
|
14917
|
-
const agentsPath =
|
|
15028
|
+
const agentsPath = join23(projectRoot, "AGENTS.md");
|
|
14918
15029
|
const existing = await readTextFile(agentsPath);
|
|
14919
15030
|
if (!existing) {
|
|
14920
15031
|
await writeTextFile(agentsPath, `# ${projectName}
|
|
@@ -14961,7 +15072,7 @@ function stripMarkers2(content) {
|
|
|
14961
15072
|
return content.slice(afterStart + 1, endIdx).trimEnd();
|
|
14962
15073
|
}
|
|
14963
15074
|
async function ensureOpencodeJson(projectRoot) {
|
|
14964
|
-
const path =
|
|
15075
|
+
const path = join23(projectRoot, "opencode.json");
|
|
14965
15076
|
const existed = await fileExists(path);
|
|
14966
15077
|
let cfg = {};
|
|
14967
15078
|
if (existed) {
|
|
@@ -15000,27 +15111,27 @@ async function ensureOpencodeJson(projectRoot) {
|
|
|
15000
15111
|
return existed ? "updated" : "created";
|
|
15001
15112
|
}
|
|
15002
15113
|
async function installPluginFile(projectRoot) {
|
|
15003
|
-
const pluginsDir =
|
|
15114
|
+
const pluginsDir = join23(projectRoot, ".opencode", "plugins");
|
|
15004
15115
|
await ensureDir(pluginsDir);
|
|
15005
15116
|
if (await fileExists(PLUGIN_SRC)) {
|
|
15006
|
-
await cp3(PLUGIN_SRC,
|
|
15117
|
+
await cp3(PLUGIN_SRC, join23(pluginsDir, PLUGIN_FILENAME));
|
|
15007
15118
|
}
|
|
15008
15119
|
}
|
|
15009
15120
|
async function installReapGuide2() {
|
|
15010
|
-
const reapHome =
|
|
15121
|
+
const reapHome = join23(homedir5(), ".reap");
|
|
15011
15122
|
await ensureDir(reapHome);
|
|
15012
|
-
const templateDir = __dirname3.includes("dist") ?
|
|
15013
|
-
const src =
|
|
15123
|
+
const templateDir = __dirname3.includes("dist") ? join23(__dirname3, "..", "..", "templates") : join23(__dirname3, "..", "..", "templates");
|
|
15124
|
+
const src = join23(templateDir, "reap-guide.md");
|
|
15014
15125
|
if (await fileExists(src)) {
|
|
15015
|
-
await cp3(src,
|
|
15126
|
+
await cp3(src, join23(reapHome, "reap-guide.md"));
|
|
15016
15127
|
}
|
|
15017
15128
|
}
|
|
15018
15129
|
var SLASH_COMMAND_PATTERN = /^reap\..+\.md$/;
|
|
15019
15130
|
function claudeCodeSkillsDir() {
|
|
15020
|
-
return __dirname3.includes("dist") ?
|
|
15131
|
+
return __dirname3.includes("dist") ? join23(__dirname3, "..", "adapters", "claude-code", "skills") : join23(__dirname3, "..", "claude-code", "skills");
|
|
15021
15132
|
}
|
|
15022
15133
|
function opencodeCommandsDir(home = homedir5()) {
|
|
15023
|
-
return
|
|
15134
|
+
return join23(home, ".config", "opencode", "commands");
|
|
15024
15135
|
}
|
|
15025
15136
|
async function installSlashCommands(home = homedir5()) {
|
|
15026
15137
|
const targetDir = opencodeCommandsDir(home);
|
|
@@ -15030,7 +15141,7 @@ async function installSlashCommands(home = homedir5()) {
|
|
|
15030
15141
|
const existing = await readdir17(targetDir);
|
|
15031
15142
|
for (const file of existing) {
|
|
15032
15143
|
if (SLASH_COMMAND_PATTERN.test(file)) {
|
|
15033
|
-
await unlink3(
|
|
15144
|
+
await unlink3(join23(targetDir, file));
|
|
15034
15145
|
cleaned++;
|
|
15035
15146
|
}
|
|
15036
15147
|
}
|
|
@@ -15042,7 +15153,7 @@ async function installSlashCommands(home = homedir5()) {
|
|
|
15042
15153
|
for (const file of sources) {
|
|
15043
15154
|
if (!file.endsWith(".md"))
|
|
15044
15155
|
continue;
|
|
15045
|
-
await cp3(
|
|
15156
|
+
await cp3(join23(srcDir, file), join23(targetDir, file));
|
|
15046
15157
|
installed++;
|
|
15047
15158
|
}
|
|
15048
15159
|
} catch {}
|
|
@@ -15050,10 +15161,10 @@ async function installSlashCommands(home = homedir5()) {
|
|
|
15050
15161
|
}
|
|
15051
15162
|
var AGENT_PATTERN2 = /^reap-.+\.md$/;
|
|
15052
15163
|
function agentsTemplateDir2() {
|
|
15053
|
-
return __dirname3.includes("dist") ?
|
|
15164
|
+
return __dirname3.includes("dist") ? join23(__dirname3, "..", "templates", "agents") : join23(__dirname3, "..", "..", "templates", "agents");
|
|
15054
15165
|
}
|
|
15055
15166
|
function opencodeAgentsDir(home = homedir5()) {
|
|
15056
|
-
return
|
|
15167
|
+
return join23(home, ".config", "opencode", "agent");
|
|
15057
15168
|
}
|
|
15058
15169
|
async function installAgents2(home = homedir5()) {
|
|
15059
15170
|
const targetDir = opencodeAgentsDir(home);
|
|
@@ -15063,7 +15174,7 @@ async function installAgents2(home = homedir5()) {
|
|
|
15063
15174
|
const existing = await readdir17(targetDir);
|
|
15064
15175
|
for (const file of existing) {
|
|
15065
15176
|
if (AGENT_PATTERN2.test(file)) {
|
|
15066
|
-
await unlink3(
|
|
15177
|
+
await unlink3(join23(targetDir, file));
|
|
15067
15178
|
cleaned++;
|
|
15068
15179
|
}
|
|
15069
15180
|
}
|
|
@@ -15075,7 +15186,7 @@ async function installAgents2(home = homedir5()) {
|
|
|
15075
15186
|
for (const file of sources) {
|
|
15076
15187
|
if (!file.endsWith(".md"))
|
|
15077
15188
|
continue;
|
|
15078
|
-
await cp3(
|
|
15189
|
+
await cp3(join23(srcDir, file), join23(targetDir, file));
|
|
15079
15190
|
installed++;
|
|
15080
15191
|
}
|
|
15081
15192
|
} catch {}
|
|
@@ -15099,7 +15210,7 @@ async function installSkills2(projectRoot) {
|
|
|
15099
15210
|
],
|
|
15100
15211
|
context: {
|
|
15101
15212
|
agentClient: "opencode",
|
|
15102
|
-
pluginPath:
|
|
15213
|
+
pluginPath: join23(projectRoot, ".opencode", "plugins", PLUGIN_FILENAME),
|
|
15103
15214
|
opencodeJson: opencodeJsonAction,
|
|
15104
15215
|
slashCommands: {
|
|
15105
15216
|
cleaned: slashCommands.cleaned,
|
|
@@ -15174,8 +15285,8 @@ async function execute30() {
|
|
|
15174
15285
|
// src/cli/commands/fix.ts
|
|
15175
15286
|
var import_yaml24 = __toESM(require_dist(), 1);
|
|
15176
15287
|
import { mkdir as mkdir3, stat as stat4 } from "fs/promises";
|
|
15177
|
-
import { join as
|
|
15178
|
-
import { fileURLToPath as
|
|
15288
|
+
import { join as join24, dirname as dirname10 } from "path";
|
|
15289
|
+
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
15179
15290
|
import { homedir as homedir6 } from "os";
|
|
15180
15291
|
init_fs();
|
|
15181
15292
|
init_integrity();
|
|
@@ -15256,13 +15367,13 @@ async function fixProject(projectRoot) {
|
|
|
15256
15367
|
issues.push(`genome/${gf.name} is missing. Run 'reap init --repair' to restore.`);
|
|
15257
15368
|
}
|
|
15258
15369
|
}
|
|
15259
|
-
const guidePath =
|
|
15370
|
+
const guidePath = join24(homedir6(), ".reap", "reap-guide.md");
|
|
15260
15371
|
if (!await fileExists(guidePath)) {
|
|
15261
|
-
const __dir =
|
|
15262
|
-
const srcGuide = await readTextFile(
|
|
15372
|
+
const __dir = dirname10(fileURLToPath9(import.meta.url));
|
|
15373
|
+
const srcGuide = await readTextFile(join24(__dir, "..", "templates", "reap-guide.md"));
|
|
15263
15374
|
if (srcGuide) {
|
|
15264
15375
|
const { ensureDir: ensDir } = await Promise.resolve().then(() => (init_fs(), exports_fs));
|
|
15265
|
-
await ensDir(
|
|
15376
|
+
await ensDir(join24(homedir6(), ".reap"));
|
|
15266
15377
|
await writeTextFile(guidePath, srcGuide);
|
|
15267
15378
|
fixed.push("Restored missing ~/.reap/reap-guide.md");
|
|
15268
15379
|
} else {
|
|
@@ -15342,7 +15453,7 @@ async function execute31(check) {
|
|
|
15342
15453
|
// src/cli/commands/destroy.ts
|
|
15343
15454
|
var import_yaml25 = __toESM(require_dist(), 1);
|
|
15344
15455
|
import { rm as rm6 } from "fs/promises";
|
|
15345
|
-
import { join as
|
|
15456
|
+
import { join as join25 } from "path";
|
|
15346
15457
|
init_fs();
|
|
15347
15458
|
init_integrity();
|
|
15348
15459
|
async function getProjectName(projectRoot) {
|
|
@@ -15360,7 +15471,7 @@ async function getProjectName(projectRoot) {
|
|
|
15360
15471
|
async function destroyProject(projectRoot) {
|
|
15361
15472
|
const removed = [];
|
|
15362
15473
|
const skipped = [];
|
|
15363
|
-
const reapDir =
|
|
15474
|
+
const reapDir = join25(projectRoot, ".reap");
|
|
15364
15475
|
if (await fileExists(reapDir)) {
|
|
15365
15476
|
await rm6(reapDir, { recursive: true, force: true });
|
|
15366
15477
|
removed.push(".reap/");
|
|
@@ -15372,7 +15483,7 @@ async function destroyProject(projectRoot) {
|
|
|
15372
15483
|
return { removed, skipped };
|
|
15373
15484
|
}
|
|
15374
15485
|
async function cleanClaudeMd(projectRoot, removed, skipped) {
|
|
15375
|
-
const claudeMdPath =
|
|
15486
|
+
const claudeMdPath = join25(projectRoot, "CLAUDE.md");
|
|
15376
15487
|
const content = await readTextFile(claudeMdPath);
|
|
15377
15488
|
if (content === null) {
|
|
15378
15489
|
skipped.push("CLAUDE.md (not found)");
|
|
@@ -15397,7 +15508,7 @@ async function cleanClaudeMd(projectRoot, removed, skipped) {
|
|
|
15397
15508
|
}
|
|
15398
15509
|
}
|
|
15399
15510
|
async function cleanGitignore(projectRoot, removed, skipped) {
|
|
15400
|
-
const gitignorePath =
|
|
15511
|
+
const gitignorePath = join25(projectRoot, ".gitignore");
|
|
15401
15512
|
const content = await readTextFile(gitignorePath);
|
|
15402
15513
|
if (content === null) {
|
|
15403
15514
|
skipped.push(".gitignore (not found)");
|
|
@@ -15462,7 +15573,7 @@ async function execute32(confirm) {
|
|
|
15462
15573
|
|
|
15463
15574
|
// src/cli/commands/clean.ts
|
|
15464
15575
|
import { rm as rm7, readdir as readdir18, mkdir as mkdir4 } from "fs/promises";
|
|
15465
|
-
import { join as
|
|
15576
|
+
import { join as join26 } from "path";
|
|
15466
15577
|
init_fs();
|
|
15467
15578
|
init_integrity();
|
|
15468
15579
|
async function cleanProject(projectRoot, options) {
|
|
@@ -15501,7 +15612,7 @@ async function cleanLineage(lineageDir, mode, actions) {
|
|
|
15501
15612
|
}
|
|
15502
15613
|
if (mode === "delete") {
|
|
15503
15614
|
for (const entry of entries) {
|
|
15504
|
-
await rm7(
|
|
15615
|
+
await rm7(join26(lineageDir, entry), { recursive: true, force: true });
|
|
15505
15616
|
}
|
|
15506
15617
|
actions.push(`Lineage: deleted ${entries.length} item(s)`);
|
|
15507
15618
|
} else {
|
|
@@ -15517,9 +15628,9 @@ async function cleanLineage(lineageDir, mode, actions) {
|
|
|
15517
15628
|
].join(`
|
|
15518
15629
|
`);
|
|
15519
15630
|
for (const dir of genDirs) {
|
|
15520
|
-
await rm7(
|
|
15631
|
+
await rm7(join26(lineageDir, dir), { recursive: true, force: true });
|
|
15521
15632
|
}
|
|
15522
|
-
await writeTextFile(
|
|
15633
|
+
await writeTextFile(join26(lineageDir, `${epochId}.md`), summary);
|
|
15523
15634
|
actions.push(`Lineage: compressed ${genDirs.length} generation(s) into ${epochId}`);
|
|
15524
15635
|
}
|
|
15525
15636
|
}
|
|
@@ -15539,7 +15650,7 @@ async function cleanLife(lifeDir, actions) {
|
|
|
15539
15650
|
for (const entry of entries) {
|
|
15540
15651
|
if (entry === "backlog")
|
|
15541
15652
|
continue;
|
|
15542
|
-
await rm7(
|
|
15653
|
+
await rm7(join26(lifeDir, entry), { recursive: true, force: true });
|
|
15543
15654
|
removedCount++;
|
|
15544
15655
|
}
|
|
15545
15656
|
actions.push(`Life: cleaned ${removedCount} file(s)`);
|
|
@@ -15601,16 +15712,16 @@ async function execute33(options) {
|
|
|
15601
15712
|
init_integrity();
|
|
15602
15713
|
var import_yaml26 = __toESM(require_dist(), 1);
|
|
15603
15714
|
import { execSync as execSync7 } from "child_process";
|
|
15604
|
-
import { readFileSync as
|
|
15605
|
-
import { join as
|
|
15715
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
15716
|
+
import { join as join28 } from "path";
|
|
15606
15717
|
|
|
15607
15718
|
// src/core/notice.ts
|
|
15608
|
-
import { readFileSync as
|
|
15609
|
-
import { join as
|
|
15719
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
15720
|
+
import { join as join27, dirname as dirname11 } from "path";
|
|
15610
15721
|
function findPackageRoot() {
|
|
15611
15722
|
try {
|
|
15612
15723
|
const pkgPath = __require.resolve("@c-d-cc/reap/package.json");
|
|
15613
|
-
return
|
|
15724
|
+
return dirname11(pkgPath);
|
|
15614
15725
|
} catch {
|
|
15615
15726
|
return process.cwd();
|
|
15616
15727
|
}
|
|
@@ -15627,8 +15738,8 @@ var LANG_MAP = {
|
|
|
15627
15738
|
};
|
|
15628
15739
|
function fetchReleaseNotice(version, language) {
|
|
15629
15740
|
try {
|
|
15630
|
-
const noticePath =
|
|
15631
|
-
const content =
|
|
15741
|
+
const noticePath = join27(findPackageRoot(), "RELEASE_NOTICE.md");
|
|
15742
|
+
const content = readFileSync4(noticePath, "utf-8");
|
|
15632
15743
|
const versionTag = version.startsWith("v") ? version : `v${version}`;
|
|
15633
15744
|
const versionPattern = new RegExp(`^## ${versionTag.replace(/\./g, "\\.")}\\s*$`, "m");
|
|
15634
15745
|
const versionMatch = versionPattern.exec(content);
|
|
@@ -15779,8 +15890,8 @@ async function execute34() {
|
|
|
15779
15890
|
const result = performAutoUpdate(root);
|
|
15780
15891
|
if (result.action === "upgraded" && result.to) {
|
|
15781
15892
|
try {
|
|
15782
|
-
const configPath =
|
|
15783
|
-
const configContent =
|
|
15893
|
+
const configPath = join28(root, ".reap", "config.yml");
|
|
15894
|
+
const configContent = readFileSync5(configPath, "utf-8");
|
|
15784
15895
|
const config = import_yaml26.default.parse(configContent);
|
|
15785
15896
|
const language = config?.language ?? "english";
|
|
15786
15897
|
const notice = fetchReleaseNotice(result.to, language);
|
|
@@ -15827,17 +15938,17 @@ async function execute35() {
|
|
|
15827
15938
|
|
|
15828
15939
|
// src/cli/commands/update.ts
|
|
15829
15940
|
var import_yaml28 = __toESM(require_dist(), 1);
|
|
15830
|
-
import { readFileSync as
|
|
15831
|
-
import { join as
|
|
15832
|
-
import { fileURLToPath as
|
|
15941
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
15942
|
+
import { join as join29, dirname as dirname12 } from "path";
|
|
15943
|
+
import { fileURLToPath as fileURLToPath10 } from "url";
|
|
15833
15944
|
init_fs();
|
|
15834
15945
|
init_integrity();
|
|
15835
|
-
function
|
|
15946
|
+
function getPackageVersion3() {
|
|
15836
15947
|
try {
|
|
15837
|
-
const __dir =
|
|
15838
|
-
for (const rel of [
|
|
15948
|
+
const __dir = dirname12(fileURLToPath10(import.meta.url));
|
|
15949
|
+
for (const rel of [join29(__dir, "..", "..", "package.json"), join29(__dir, "..", "package.json")]) {
|
|
15839
15950
|
try {
|
|
15840
|
-
return JSON.parse(
|
|
15951
|
+
return JSON.parse(readFileSync6(rel, "utf-8")).version;
|
|
15841
15952
|
} catch {}
|
|
15842
15953
|
}
|
|
15843
15954
|
} catch {}
|
|
@@ -15852,7 +15963,10 @@ var VALID_CONFIG_FIELDS = new Set([
|
|
|
15852
15963
|
"agentClient",
|
|
15853
15964
|
"autoUpdate",
|
|
15854
15965
|
"autoIssueReport",
|
|
15855
|
-
"cruiseCount"
|
|
15966
|
+
"cruiseCount",
|
|
15967
|
+
"evaluator",
|
|
15968
|
+
"daemon",
|
|
15969
|
+
"lastMigratedVersion"
|
|
15856
15970
|
]);
|
|
15857
15971
|
var CONFIG_DEFAULTS = {
|
|
15858
15972
|
language: "english",
|
|
@@ -15915,6 +16029,17 @@ async function backfillConfig(paths) {
|
|
|
15915
16029
|
}
|
|
15916
16030
|
return { added, removed };
|
|
15917
16031
|
}
|
|
16032
|
+
async function markMigratedNow(paths, version) {
|
|
16033
|
+
const content = await readTextFile(paths.config) ?? "";
|
|
16034
|
+
let config = {};
|
|
16035
|
+
try {
|
|
16036
|
+
config = import_yaml28.default.parse(content) ?? {};
|
|
16037
|
+
} catch {}
|
|
16038
|
+
const previous = config.lastMigratedVersion ?? "0.0.0";
|
|
16039
|
+
config.lastMigratedVersion = version;
|
|
16040
|
+
await writeTextFile(paths.config, import_yaml28.default.stringify(config));
|
|
16041
|
+
return previous;
|
|
16042
|
+
}
|
|
15918
16043
|
async function ensureDirectories(paths) {
|
|
15919
16044
|
const created = [];
|
|
15920
16045
|
for (const dir of getRequiredDirs(paths)) {
|
|
@@ -15926,12 +16051,27 @@ async function ensureDirectories(paths) {
|
|
|
15926
16051
|
}
|
|
15927
16052
|
return created;
|
|
15928
16053
|
}
|
|
15929
|
-
async function execute36(phase, postUpgrade) {
|
|
16054
|
+
async function execute36(phase, postUpgrade, markMigrated) {
|
|
15930
16055
|
const root = process.cwd();
|
|
15931
16056
|
const paths = createPaths(root);
|
|
15932
16057
|
if (!await fileExists(paths.config) && !await detectV15(paths)) {
|
|
15933
16058
|
emitError("update", "No REAP project detected. Run 'reap init' first.");
|
|
15934
16059
|
}
|
|
16060
|
+
if (markMigrated) {
|
|
16061
|
+
await backfillConfig(paths);
|
|
16062
|
+
const version = getPackageVersion3();
|
|
16063
|
+
const previous = await markMigratedNow(paths, version);
|
|
16064
|
+
emitOutput({
|
|
16065
|
+
status: "ok",
|
|
16066
|
+
command: "update",
|
|
16067
|
+
context: {
|
|
16068
|
+
markMigrated: true,
|
|
16069
|
+
lastMigratedVersion: version,
|
|
16070
|
+
previous
|
|
16071
|
+
},
|
|
16072
|
+
message: previous === version ? `Already marked as migrated for v${version}.` : `Marked project as migrated for v${version} (was ${previous}).`
|
|
16073
|
+
});
|
|
16074
|
+
}
|
|
15935
16075
|
if (!postUpgrade) {
|
|
15936
16076
|
if (await detectV15(paths)) {
|
|
15937
16077
|
try {
|
|
@@ -15984,32 +16124,44 @@ async function execute36(phase, postUpgrade) {
|
|
|
15984
16124
|
language = cfg.language;
|
|
15985
16125
|
} catch {}
|
|
15986
16126
|
}
|
|
15987
|
-
const version =
|
|
16127
|
+
const version = getPackageVersion3();
|
|
15988
16128
|
if (version !== "0.0.0") {
|
|
15989
16129
|
const notice = fetchReleaseNotice(version, language);
|
|
15990
16130
|
if (notice)
|
|
15991
16131
|
console.error(notice);
|
|
15992
16132
|
}
|
|
15993
16133
|
} catch {}
|
|
15994
|
-
|
|
15995
|
-
|
|
15996
|
-
|
|
15997
|
-
|
|
15998
|
-
|
|
15999
|
-
|
|
16000
|
-
});
|
|
16001
|
-
} else {
|
|
16002
|
-
emitOutput({
|
|
16003
|
-
status: "ok",
|
|
16004
|
-
command: "update",
|
|
16005
|
-
context: { changes: updated },
|
|
16006
|
-
message: `Updated: ${updated.join("; ")}`
|
|
16007
|
-
});
|
|
16134
|
+
const refreshedRaw = await readTextFile(paths.config);
|
|
16135
|
+
let refreshedConfig = null;
|
|
16136
|
+
if (refreshedRaw) {
|
|
16137
|
+
try {
|
|
16138
|
+
refreshedConfig = import_yaml28.default.parse(refreshedRaw);
|
|
16139
|
+
} catch {}
|
|
16008
16140
|
}
|
|
16141
|
+
const pkgVersion = getPackageVersion3();
|
|
16142
|
+
let pendingMigrations = [];
|
|
16143
|
+
try {
|
|
16144
|
+
pendingMigrations = detectPendingMigrations(refreshedConfig, pkgVersion);
|
|
16145
|
+
} catch {
|
|
16146
|
+
pendingMigrations = [];
|
|
16147
|
+
}
|
|
16148
|
+
const baseMessage = updated.length === 0 ? "Project is up to date. Nothing to update." : `Updated: ${updated.join("; ")}`;
|
|
16149
|
+
const migrationMessage = pendingMigrations.length === 0 ? "" : ` ${pendingMigrations.length} pending migration${pendingMigrations.length === 1 ? "" : "s"} ` + `(${pendingMigrations.map((m) => "v" + m.version).join(", ")}) — see context.pendingMigrations. ` + `Run \`reap update --mark-migrated\` after applying them.`;
|
|
16150
|
+
emitOutput({
|
|
16151
|
+
status: "ok",
|
|
16152
|
+
command: "update",
|
|
16153
|
+
context: {
|
|
16154
|
+
changes: updated,
|
|
16155
|
+
pendingMigrations,
|
|
16156
|
+
packageVersion: pkgVersion,
|
|
16157
|
+
lastMigratedVersion: refreshedConfig?.lastMigratedVersion ?? "0.0.0"
|
|
16158
|
+
},
|
|
16159
|
+
message: baseMessage + migrationMessage
|
|
16160
|
+
});
|
|
16009
16161
|
}
|
|
16010
16162
|
|
|
16011
16163
|
// src/cli/commands/help.ts
|
|
16012
|
-
import { join as
|
|
16164
|
+
import { join as join30 } from "path";
|
|
16013
16165
|
init_fs();
|
|
16014
16166
|
var SUPPORTED_LANGUAGES = ["en", "ko", "ja", "zh-CN"];
|
|
16015
16167
|
var LANGUAGE_ALIASES = {
|
|
@@ -16187,7 +16339,7 @@ async function execute37(topic) {
|
|
|
16187
16339
|
const stateDisplay = buildStateDisplay(state, lang);
|
|
16188
16340
|
const lines = buildHelpLines(lang, stateDisplay);
|
|
16189
16341
|
if (topic) {
|
|
16190
|
-
const reapGuidePath =
|
|
16342
|
+
const reapGuidePath = join30(paths.reap, "reap-guide.md");
|
|
16191
16343
|
const reapGuide = await readTextFile(reapGuidePath) ?? "";
|
|
16192
16344
|
emitOutput({
|
|
16193
16345
|
status: "prompt",
|
|
@@ -16381,16 +16533,16 @@ async function execute39(opts = {}) {
|
|
|
16381
16533
|
|
|
16382
16534
|
// src/cli/index.ts
|
|
16383
16535
|
function readVersion() {
|
|
16384
|
-
const __dir =
|
|
16536
|
+
const __dir = dirname13(fileURLToPath11(import.meta.url));
|
|
16385
16537
|
let version = "0.0.0";
|
|
16386
|
-
for (const rel of [
|
|
16538
|
+
for (const rel of [join31(__dir, "..", "..", "package.json"), join31(__dir, "..", "package.json")]) {
|
|
16387
16539
|
try {
|
|
16388
|
-
version = JSON.parse(
|
|
16540
|
+
version = JSON.parse(readFileSync7(rel, "utf-8")).version;
|
|
16389
16541
|
break;
|
|
16390
16542
|
} catch {}
|
|
16391
16543
|
}
|
|
16392
16544
|
try {
|
|
16393
|
-
const hash =
|
|
16545
|
+
const hash = readFileSync7(join31(__dir, "..", ".dev-build"), "utf-8").trim();
|
|
16394
16546
|
if (hash)
|
|
16395
16547
|
version += `+dev.${hash}`;
|
|
16396
16548
|
} catch {}
|
|
@@ -16439,8 +16591,8 @@ program2.command("config").description("Show current REAP project configuration"
|
|
|
16439
16591
|
program2.command("help [topic]").description("Show REAP commands and workflow overview").action(async (topic) => {
|
|
16440
16592
|
await execute37(topic);
|
|
16441
16593
|
});
|
|
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) => {
|
|
16443
|
-
await execute36(options.phase, options.postUpgrade);
|
|
16594
|
+
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)").option("--mark-migrated", "Mark this project as migrated for the current REAP version (gen-071 migration layer)").action(async (options) => {
|
|
16595
|
+
await execute36(options.phase, options.postUpgrade, options.markMigrated);
|
|
16444
16596
|
});
|
|
16445
16597
|
program2.command("load-context").description("Output REAP project knowledge for SessionStart hook injection").action(async () => {
|
|
16446
16598
|
await execute();
|