@c-d-cc/reap 0.7.0 → 0.7.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/dist/cli.js +439 -125
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -31,6 +31,20 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
31
31
|
return to;
|
|
32
32
|
};
|
|
33
33
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
34
|
+
var __returnValue = (v) => v;
|
|
35
|
+
function __exportSetter(name, newValue) {
|
|
36
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
37
|
+
}
|
|
38
|
+
var __export = (target, all) => {
|
|
39
|
+
for (var name in all)
|
|
40
|
+
__defProp(target, name, {
|
|
41
|
+
get: all[name],
|
|
42
|
+
enumerable: true,
|
|
43
|
+
configurable: true,
|
|
44
|
+
set: __exportSetter.bind(all, name)
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
34
48
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
35
49
|
|
|
36
50
|
// node_modules/commander/lib/error.js
|
|
@@ -8823,6 +8837,311 @@ var require_dist = __commonJS((exports) => {
|
|
|
8823
8837
|
exports.visitAsync = visit.visitAsync;
|
|
8824
8838
|
});
|
|
8825
8839
|
|
|
8840
|
+
// src/core/fs.ts
|
|
8841
|
+
var exports_fs = {};
|
|
8842
|
+
__export(exports_fs, {
|
|
8843
|
+
writeTextFile: () => writeTextFile,
|
|
8844
|
+
readTextFileOrThrow: () => readTextFileOrThrow,
|
|
8845
|
+
readTextFile: () => readTextFile,
|
|
8846
|
+
fileExists: () => fileExists
|
|
8847
|
+
});
|
|
8848
|
+
import { readFile, writeFile, access } from "fs/promises";
|
|
8849
|
+
async function readTextFile(path) {
|
|
8850
|
+
try {
|
|
8851
|
+
return await readFile(path, "utf-8");
|
|
8852
|
+
} catch {
|
|
8853
|
+
return null;
|
|
8854
|
+
}
|
|
8855
|
+
}
|
|
8856
|
+
async function readTextFileOrThrow(path) {
|
|
8857
|
+
return await readFile(path, "utf-8");
|
|
8858
|
+
}
|
|
8859
|
+
async function writeTextFile(path, content) {
|
|
8860
|
+
await writeFile(path, content, "utf-8");
|
|
8861
|
+
}
|
|
8862
|
+
async function fileExists(path) {
|
|
8863
|
+
try {
|
|
8864
|
+
await access(path);
|
|
8865
|
+
return true;
|
|
8866
|
+
} catch {
|
|
8867
|
+
return false;
|
|
8868
|
+
}
|
|
8869
|
+
}
|
|
8870
|
+
var init_fs = () => {};
|
|
8871
|
+
|
|
8872
|
+
// src/core/genome-sync.ts
|
|
8873
|
+
var exports_genome_sync = {};
|
|
8874
|
+
__export(exports_genome_sync, {
|
|
8875
|
+
syncGenomeFromProject: () => syncGenomeFromProject
|
|
8876
|
+
});
|
|
8877
|
+
import { join as join4 } from "path";
|
|
8878
|
+
import { readdir as readdir3, stat as stat2 } from "fs/promises";
|
|
8879
|
+
async function scanProject(projectRoot) {
|
|
8880
|
+
const scan = {
|
|
8881
|
+
language: "Unknown",
|
|
8882
|
+
runtime: "Unknown",
|
|
8883
|
+
framework: "None",
|
|
8884
|
+
packageManager: "Unknown",
|
|
8885
|
+
testFramework: "None",
|
|
8886
|
+
linter: "None",
|
|
8887
|
+
formatter: "None",
|
|
8888
|
+
buildTool: "None",
|
|
8889
|
+
scripts: {},
|
|
8890
|
+
dependencies: [],
|
|
8891
|
+
devDependencies: [],
|
|
8892
|
+
hasTypeScript: false,
|
|
8893
|
+
hasDocker: false,
|
|
8894
|
+
directories: [],
|
|
8895
|
+
existingDocs: []
|
|
8896
|
+
};
|
|
8897
|
+
const pkgContent = await readTextFile(join4(projectRoot, "package.json"));
|
|
8898
|
+
if (pkgContent) {
|
|
8899
|
+
try {
|
|
8900
|
+
const pkg = JSON.parse(pkgContent);
|
|
8901
|
+
scan.dependencies = Object.keys(pkg.dependencies ?? {});
|
|
8902
|
+
scan.devDependencies = Object.keys(pkg.devDependencies ?? {});
|
|
8903
|
+
scan.scripts = pkg.scripts ?? {};
|
|
8904
|
+
scan.packageManager = pkg.packageManager?.startsWith("bun") ? "Bun" : pkg.packageManager?.startsWith("pnpm") ? "pnpm" : pkg.packageManager?.startsWith("yarn") ? "Yarn" : "npm";
|
|
8905
|
+
scan.language = "JavaScript";
|
|
8906
|
+
scan.runtime = "Node.js";
|
|
8907
|
+
const allDeps = [...scan.dependencies, ...scan.devDependencies];
|
|
8908
|
+
if (allDeps.includes("next"))
|
|
8909
|
+
scan.framework = "Next.js";
|
|
8910
|
+
else if (allDeps.includes("nuxt"))
|
|
8911
|
+
scan.framework = "Nuxt";
|
|
8912
|
+
else if (allDeps.includes("react"))
|
|
8913
|
+
scan.framework = "React";
|
|
8914
|
+
else if (allDeps.includes("vue"))
|
|
8915
|
+
scan.framework = "Vue";
|
|
8916
|
+
else if (allDeps.includes("svelte") || allDeps.includes("@sveltejs/kit"))
|
|
8917
|
+
scan.framework = "Svelte/SvelteKit";
|
|
8918
|
+
else if (allDeps.includes("express"))
|
|
8919
|
+
scan.framework = "Express";
|
|
8920
|
+
else if (allDeps.includes("hono"))
|
|
8921
|
+
scan.framework = "Hono";
|
|
8922
|
+
else if (allDeps.includes("fastify"))
|
|
8923
|
+
scan.framework = "Fastify";
|
|
8924
|
+
else if (allDeps.includes("nestjs") || allDeps.includes("@nestjs/core"))
|
|
8925
|
+
scan.framework = "NestJS";
|
|
8926
|
+
else if (allDeps.includes("astro"))
|
|
8927
|
+
scan.framework = "Astro";
|
|
8928
|
+
if (allDeps.includes("vitest"))
|
|
8929
|
+
scan.testFramework = "Vitest";
|
|
8930
|
+
else if (allDeps.includes("jest"))
|
|
8931
|
+
scan.testFramework = "Jest";
|
|
8932
|
+
else if (allDeps.includes("mocha"))
|
|
8933
|
+
scan.testFramework = "Mocha";
|
|
8934
|
+
else if (scan.scripts.test?.includes("bun test"))
|
|
8935
|
+
scan.testFramework = "Bun Test";
|
|
8936
|
+
if (allDeps.includes("eslint"))
|
|
8937
|
+
scan.linter = "ESLint";
|
|
8938
|
+
else if (allDeps.includes("biome") || allDeps.includes("@biomejs/biome"))
|
|
8939
|
+
scan.linter = "Biome";
|
|
8940
|
+
if (allDeps.includes("prettier"))
|
|
8941
|
+
scan.formatter = "Prettier";
|
|
8942
|
+
else if (allDeps.includes("biome") || allDeps.includes("@biomejs/biome"))
|
|
8943
|
+
scan.formatter = "Biome";
|
|
8944
|
+
if (allDeps.includes("vite"))
|
|
8945
|
+
scan.buildTool = "Vite";
|
|
8946
|
+
else if (allDeps.includes("webpack"))
|
|
8947
|
+
scan.buildTool = "Webpack";
|
|
8948
|
+
else if (allDeps.includes("esbuild"))
|
|
8949
|
+
scan.buildTool = "esbuild";
|
|
8950
|
+
else if (allDeps.includes("rollup"))
|
|
8951
|
+
scan.buildTool = "Rollup";
|
|
8952
|
+
else if (allDeps.includes("turbo") || allDeps.includes("turbopack"))
|
|
8953
|
+
scan.buildTool = "Turbopack";
|
|
8954
|
+
} catch {}
|
|
8955
|
+
}
|
|
8956
|
+
if (await fileExists(join4(projectRoot, "go.mod"))) {
|
|
8957
|
+
scan.language = "Go";
|
|
8958
|
+
scan.runtime = "Go";
|
|
8959
|
+
scan.packageManager = "Go Modules";
|
|
8960
|
+
}
|
|
8961
|
+
if (await fileExists(join4(projectRoot, "pyproject.toml")) || await fileExists(join4(projectRoot, "requirements.txt"))) {
|
|
8962
|
+
scan.language = "Python";
|
|
8963
|
+
scan.runtime = "Python";
|
|
8964
|
+
if (await fileExists(join4(projectRoot, "pyproject.toml"))) {
|
|
8965
|
+
const pyproject = await readTextFile(join4(projectRoot, "pyproject.toml"));
|
|
8966
|
+
if (pyproject?.includes("[tool.poetry]"))
|
|
8967
|
+
scan.packageManager = "Poetry";
|
|
8968
|
+
else if (pyproject?.includes("[tool.uv]") || pyproject?.includes("[project]"))
|
|
8969
|
+
scan.packageManager = "uv/pip";
|
|
8970
|
+
if (pyproject?.includes("pytest"))
|
|
8971
|
+
scan.testFramework = "pytest";
|
|
8972
|
+
if (pyproject?.includes("django"))
|
|
8973
|
+
scan.framework = "Django";
|
|
8974
|
+
else if (pyproject?.includes("fastapi"))
|
|
8975
|
+
scan.framework = "FastAPI";
|
|
8976
|
+
else if (pyproject?.includes("flask"))
|
|
8977
|
+
scan.framework = "Flask";
|
|
8978
|
+
}
|
|
8979
|
+
}
|
|
8980
|
+
if (await fileExists(join4(projectRoot, "Cargo.toml"))) {
|
|
8981
|
+
scan.language = "Rust";
|
|
8982
|
+
scan.runtime = "Rust";
|
|
8983
|
+
scan.packageManager = "Cargo";
|
|
8984
|
+
}
|
|
8985
|
+
if (await fileExists(join4(projectRoot, "tsconfig.json"))) {
|
|
8986
|
+
scan.hasTypeScript = true;
|
|
8987
|
+
scan.language = "TypeScript";
|
|
8988
|
+
}
|
|
8989
|
+
scan.hasDocker = await fileExists(join4(projectRoot, "Dockerfile")) || await fileExists(join4(projectRoot, "docker-compose.yml"));
|
|
8990
|
+
try {
|
|
8991
|
+
const entries = await readdir3(projectRoot);
|
|
8992
|
+
for (const entry of entries) {
|
|
8993
|
+
if (entry.startsWith(".") || entry === "node_modules")
|
|
8994
|
+
continue;
|
|
8995
|
+
try {
|
|
8996
|
+
const s = await stat2(join4(projectRoot, entry));
|
|
8997
|
+
if (s.isDirectory())
|
|
8998
|
+
scan.directories.push(entry);
|
|
8999
|
+
} catch {}
|
|
9000
|
+
}
|
|
9001
|
+
} catch {}
|
|
9002
|
+
const docFiles = ["README.md", "CLAUDE.md", "AGENTS.md", "CONTRIBUTING.md", "ARCHITECTURE.md"];
|
|
9003
|
+
for (const file of docFiles) {
|
|
9004
|
+
const content = await readTextFile(join4(projectRoot, file));
|
|
9005
|
+
if (content) {
|
|
9006
|
+
scan.existingDocs.push({ file, content: content.substring(0, 2000) });
|
|
9007
|
+
}
|
|
9008
|
+
}
|
|
9009
|
+
return scan;
|
|
9010
|
+
}
|
|
9011
|
+
function generateConstraints(scan) {
|
|
9012
|
+
const lines = [
|
|
9013
|
+
"# Technical Constraints",
|
|
9014
|
+
"",
|
|
9015
|
+
"> Auto-generated by `reap init` from project scan. Refine during the first Generation's Objective stage.",
|
|
9016
|
+
"",
|
|
9017
|
+
"## Tech Stack",
|
|
9018
|
+
"",
|
|
9019
|
+
`- **Language**: ${scan.language}${scan.hasTypeScript ? " (TypeScript)" : ""}`,
|
|
9020
|
+
`- **Runtime**: ${scan.runtime}`
|
|
9021
|
+
];
|
|
9022
|
+
if (scan.framework !== "None")
|
|
9023
|
+
lines.push(`- **Framework**: ${scan.framework}`);
|
|
9024
|
+
if (scan.packageManager !== "Unknown")
|
|
9025
|
+
lines.push(`- **Package Manager**: ${scan.packageManager}`);
|
|
9026
|
+
if (scan.buildTool !== "None")
|
|
9027
|
+
lines.push(`- **Build Tool**: ${scan.buildTool}`);
|
|
9028
|
+
lines.push("", "## Constraints", "");
|
|
9029
|
+
if (scan.hasDocker)
|
|
9030
|
+
lines.push("- Docker containerized deployment");
|
|
9031
|
+
if (scan.hasTypeScript)
|
|
9032
|
+
lines.push("- TypeScript strict mode (check tsconfig.json for details)");
|
|
9033
|
+
lines.push("", "## Validation Commands", "", "| Purpose | Command | Description |", "|---------|---------|-------------|");
|
|
9034
|
+
if (scan.testFramework !== "None") {
|
|
9035
|
+
const testCmd = scan.scripts.test ?? `${scan.testFramework.toLowerCase()} test`;
|
|
9036
|
+
lines.push(`| Test | \`${testCmd}\` | Run tests |`);
|
|
9037
|
+
}
|
|
9038
|
+
if (scan.scripts.lint)
|
|
9039
|
+
lines.push(`| Lint | \`${scan.scripts.lint.includes("npm") ? "npm run lint" : scan.scripts.lint}\` | Lint check |`);
|
|
9040
|
+
else if (scan.scripts.lint)
|
|
9041
|
+
lines.push(`| Lint | \`npm run lint\` | Lint check |`);
|
|
9042
|
+
if (scan.scripts.build)
|
|
9043
|
+
lines.push(`| Build | \`npm run build\` | Build project |`);
|
|
9044
|
+
if (scan.hasTypeScript)
|
|
9045
|
+
lines.push("| Type check | `npx tsc --noEmit` | TypeScript compile check |");
|
|
9046
|
+
lines.push("", "## External Dependencies", "", "- (review and fill in during first generation)");
|
|
9047
|
+
return lines.join(`
|
|
9048
|
+
`) + `
|
|
9049
|
+
`;
|
|
9050
|
+
}
|
|
9051
|
+
function generateConventions(scan) {
|
|
9052
|
+
const lines = [
|
|
9053
|
+
"# Development Conventions",
|
|
9054
|
+
"",
|
|
9055
|
+
"> Auto-generated by `reap init` from project scan. Refine during the first Generation's Objective stage.",
|
|
9056
|
+
"",
|
|
9057
|
+
"## Code Style",
|
|
9058
|
+
""
|
|
9059
|
+
];
|
|
9060
|
+
if (scan.linter !== "None")
|
|
9061
|
+
lines.push(`- Linter: ${scan.linter}`);
|
|
9062
|
+
if (scan.formatter !== "None")
|
|
9063
|
+
lines.push(`- Formatter: ${scan.formatter}`);
|
|
9064
|
+
if (scan.hasTypeScript)
|
|
9065
|
+
lines.push("- TypeScript strict mode");
|
|
9066
|
+
lines.push("", "## Naming Conventions", "", "- (review and fill in during first generation)");
|
|
9067
|
+
lines.push("", "## Git Conventions", "", "- (review and fill in during first generation)");
|
|
9068
|
+
if (scan.testFramework !== "None") {
|
|
9069
|
+
lines.push("", "## Testing", "", `- Test framework: ${scan.testFramework}`);
|
|
9070
|
+
}
|
|
9071
|
+
lines.push("", "## Enforced Rules", "", "| Rule | Tool | Command |", "|------|------|---------|");
|
|
9072
|
+
if (scan.scripts.test)
|
|
9073
|
+
lines.push(`| Tests pass | ${scan.testFramework} | \`npm test\` |`);
|
|
9074
|
+
if (scan.scripts.lint)
|
|
9075
|
+
lines.push(`| Lint clean | ${scan.linter} | \`npm run lint\` |`);
|
|
9076
|
+
if (scan.scripts.build)
|
|
9077
|
+
lines.push("| Build succeeds | Build | `npm run build` |");
|
|
9078
|
+
if (scan.hasTypeScript)
|
|
9079
|
+
lines.push("| TypeScript compiles | tsc | `npx tsc --noEmit` |");
|
|
9080
|
+
return lines.join(`
|
|
9081
|
+
`) + `
|
|
9082
|
+
`;
|
|
9083
|
+
}
|
|
9084
|
+
function generatePrinciples(scan) {
|
|
9085
|
+
const lines = [
|
|
9086
|
+
"# Architecture Principles",
|
|
9087
|
+
"",
|
|
9088
|
+
"> Auto-generated by `reap init` from project scan. Refine during the first Generation's Objective stage.",
|
|
9089
|
+
"",
|
|
9090
|
+
"## Core Beliefs",
|
|
9091
|
+
"",
|
|
9092
|
+
"- (define your project's core architectural beliefs during the first generation)",
|
|
9093
|
+
"",
|
|
9094
|
+
"## Architecture Decisions",
|
|
9095
|
+
"",
|
|
9096
|
+
"| ID | Decision | Rationale | Date |",
|
|
9097
|
+
"|----|----------|-----------|------|"
|
|
9098
|
+
];
|
|
9099
|
+
if (scan.framework !== "None")
|
|
9100
|
+
lines.push(`| ADR-001 | ${scan.framework} | Detected from project dependencies | Auto |`);
|
|
9101
|
+
if (scan.hasTypeScript)
|
|
9102
|
+
lines.push(`| ADR-002 | TypeScript | Type safety | Auto |`);
|
|
9103
|
+
lines.push("", "## Source Map", "", "→ `genome/source-map.md`");
|
|
9104
|
+
return lines.join(`
|
|
9105
|
+
`) + `
|
|
9106
|
+
`;
|
|
9107
|
+
}
|
|
9108
|
+
function generateSourceMap(scan) {
|
|
9109
|
+
const lines = [
|
|
9110
|
+
"# Source Map",
|
|
9111
|
+
"",
|
|
9112
|
+
"> Auto-generated by `reap init` from project scan. Refine during the first Generation's Objective stage.",
|
|
9113
|
+
"",
|
|
9114
|
+
"## Project Structure",
|
|
9115
|
+
"",
|
|
9116
|
+
"```"
|
|
9117
|
+
];
|
|
9118
|
+
for (const dir of scan.directories.sort()) {
|
|
9119
|
+
lines.push(`${dir}/`);
|
|
9120
|
+
}
|
|
9121
|
+
lines.push("```");
|
|
9122
|
+
return lines.join(`
|
|
9123
|
+
`) + `
|
|
9124
|
+
`;
|
|
9125
|
+
}
|
|
9126
|
+
async function syncGenomeFromProject(projectRoot, genomePath, onProgress) {
|
|
9127
|
+
const log = onProgress ?? (() => {});
|
|
9128
|
+
log("Scanning project structure...");
|
|
9129
|
+
const scan = await scanProject(projectRoot);
|
|
9130
|
+
log(`Detected: ${scan.language}, ${scan.framework !== "None" ? scan.framework : "no framework"}, ${scan.packageManager}`);
|
|
9131
|
+
const { writeTextFile: writeTextFile2 } = await Promise.resolve().then(() => (init_fs(), exports_fs));
|
|
9132
|
+
log("Generating constraints.md...");
|
|
9133
|
+
await writeTextFile2(join4(genomePath, "constraints.md"), generateConstraints(scan));
|
|
9134
|
+
log("Generating conventions.md...");
|
|
9135
|
+
await writeTextFile2(join4(genomePath, "conventions.md"), generateConventions(scan));
|
|
9136
|
+
log("Generating principles.md...");
|
|
9137
|
+
await writeTextFile2(join4(genomePath, "principles.md"), generatePrinciples(scan));
|
|
9138
|
+
log("Generating source-map.md...");
|
|
9139
|
+
await writeTextFile2(join4(genomePath, "source-map.md"), generateSourceMap(scan));
|
|
9140
|
+
}
|
|
9141
|
+
var init_genome_sync = __esm(() => {
|
|
9142
|
+
init_fs();
|
|
9143
|
+
});
|
|
9144
|
+
|
|
8826
9145
|
// node_modules/commander/esm.mjs
|
|
8827
9146
|
var import__ = __toESM(require_commander(), 1);
|
|
8828
9147
|
var {
|
|
@@ -8840,8 +9159,8 @@ var {
|
|
|
8840
9159
|
} = import__.default;
|
|
8841
9160
|
|
|
8842
9161
|
// src/cli/commands/init.ts
|
|
8843
|
-
import { mkdir as mkdir3, readdir as
|
|
8844
|
-
import { join as
|
|
9162
|
+
import { mkdir as mkdir3, readdir as readdir4, chmod } from "fs/promises";
|
|
9163
|
+
import { join as join5 } from "path";
|
|
8845
9164
|
|
|
8846
9165
|
// src/core/paths.ts
|
|
8847
9166
|
import { join, dirname } from "path";
|
|
@@ -8966,33 +9285,9 @@ class ReapPaths {
|
|
|
8966
9285
|
}
|
|
8967
9286
|
|
|
8968
9287
|
// src/core/config.ts
|
|
9288
|
+
init_fs();
|
|
8969
9289
|
var import_yaml = __toESM(require_dist(), 1);
|
|
8970
9290
|
|
|
8971
|
-
// src/core/fs.ts
|
|
8972
|
-
import { readFile, writeFile, access } from "fs/promises";
|
|
8973
|
-
async function readTextFile(path) {
|
|
8974
|
-
try {
|
|
8975
|
-
return await readFile(path, "utf-8");
|
|
8976
|
-
} catch {
|
|
8977
|
-
return null;
|
|
8978
|
-
}
|
|
8979
|
-
}
|
|
8980
|
-
async function readTextFileOrThrow(path) {
|
|
8981
|
-
return await readFile(path, "utf-8");
|
|
8982
|
-
}
|
|
8983
|
-
async function writeTextFile(path, content) {
|
|
8984
|
-
await writeFile(path, content, "utf-8");
|
|
8985
|
-
}
|
|
8986
|
-
async function fileExists(path) {
|
|
8987
|
-
try {
|
|
8988
|
-
await access(path);
|
|
8989
|
-
return true;
|
|
8990
|
-
} catch {
|
|
8991
|
-
return false;
|
|
8992
|
-
}
|
|
8993
|
-
}
|
|
8994
|
-
|
|
8995
|
-
// src/core/config.ts
|
|
8996
9291
|
class ConfigManager {
|
|
8997
9292
|
static async read(paths) {
|
|
8998
9293
|
const content = await readTextFileOrThrow(paths.config);
|
|
@@ -9017,6 +9312,7 @@ class ConfigManager {
|
|
|
9017
9312
|
}
|
|
9018
9313
|
|
|
9019
9314
|
// src/core/agents/claude-code.ts
|
|
9315
|
+
init_fs();
|
|
9020
9316
|
import { join as join2 } from "path";
|
|
9021
9317
|
import { homedir as homedir2 } from "os";
|
|
9022
9318
|
import { mkdir, readdir, unlink } from "fs/promises";
|
|
@@ -9242,6 +9538,7 @@ Read \`~/.reap/commands/${cmd}.md\` and follow the instructions there.
|
|
|
9242
9538
|
}
|
|
9243
9539
|
|
|
9244
9540
|
// src/core/agents/opencode.ts
|
|
9541
|
+
init_fs();
|
|
9245
9542
|
import { join as join3 } from "path";
|
|
9246
9543
|
import { homedir as homedir3 } from "os";
|
|
9247
9544
|
import { mkdir as mkdir2, readdir as readdir2, unlink as unlink2 } from "fs/promises";
|
|
@@ -9441,6 +9738,7 @@ class AgentRegistry {
|
|
|
9441
9738
|
}
|
|
9442
9739
|
|
|
9443
9740
|
// src/cli/commands/init.ts
|
|
9741
|
+
init_fs();
|
|
9444
9742
|
var COMMAND_NAMES = [
|
|
9445
9743
|
"reap.objective",
|
|
9446
9744
|
"reap.planning",
|
|
@@ -9474,8 +9772,8 @@ async function initProject(projectRoot, projectName, entryMode, preset, onProgre
|
|
|
9474
9772
|
throw new Error(".reap/ already exists. This is already a REAP project.");
|
|
9475
9773
|
}
|
|
9476
9774
|
if (preset) {
|
|
9477
|
-
const presetDir =
|
|
9478
|
-
const presetExists = await fileExists(
|
|
9775
|
+
const presetDir = join5(ReapPaths.packageTemplatesDir, "presets", preset);
|
|
9776
|
+
const presetExists = await fileExists(join5(presetDir, "principles.md"));
|
|
9479
9777
|
if (!presetExists) {
|
|
9480
9778
|
throw new Error(`Unknown preset: "${preset}". Available presets: bun-hono-react`);
|
|
9481
9779
|
}
|
|
@@ -9497,54 +9795,59 @@ async function initProject(projectRoot, projectName, entryMode, preset, onProgre
|
|
|
9497
9795
|
await ConfigManager.write(paths, config);
|
|
9498
9796
|
log("Setting up Genome templates...");
|
|
9499
9797
|
const genomeTemplates = ["principles.md", "conventions.md", "constraints.md", "source-map.md"];
|
|
9500
|
-
const genomeSourceDir = preset ?
|
|
9798
|
+
const genomeSourceDir = preset ? join5(ReapPaths.packageTemplatesDir, "presets", preset) : ReapPaths.packageGenomeDir;
|
|
9501
9799
|
for (const file of genomeTemplates) {
|
|
9502
|
-
const src =
|
|
9503
|
-
const dest =
|
|
9800
|
+
const src = join5(genomeSourceDir, file);
|
|
9801
|
+
const dest = join5(paths.genome, file);
|
|
9504
9802
|
await writeTextFile(dest, await readTextFileOrThrow(src));
|
|
9505
9803
|
}
|
|
9804
|
+
if ((entryMode === "adoption" || entryMode === "migration") && !preset) {
|
|
9805
|
+
log("Scanning project for genome auto-sync...");
|
|
9806
|
+
const { syncGenomeFromProject: syncGenomeFromProject2 } = await Promise.resolve().then(() => (init_genome_sync(), exports_genome_sync));
|
|
9807
|
+
await syncGenomeFromProject2(projectRoot, paths.genome, log);
|
|
9808
|
+
}
|
|
9506
9809
|
log("Installing artifact templates...");
|
|
9507
9810
|
await mkdir3(ReapPaths.userReapTemplates, { recursive: true });
|
|
9508
9811
|
const artifactFiles = ["01-objective.md", "02-planning.md", "03-implementation.md", "04-validation.md", "05-completion.md"];
|
|
9509
9812
|
for (const file of artifactFiles) {
|
|
9510
|
-
const src =
|
|
9511
|
-
const dest =
|
|
9813
|
+
const src = join5(ReapPaths.packageArtifactsDir, file);
|
|
9814
|
+
const dest = join5(ReapPaths.userReapTemplates, file);
|
|
9512
9815
|
await writeTextFile(dest, await readTextFileOrThrow(src));
|
|
9513
9816
|
}
|
|
9514
|
-
const domainGuideSrc =
|
|
9515
|
-
const domainGuideDest =
|
|
9817
|
+
const domainGuideSrc = join5(ReapPaths.packageGenomeDir, "domain/README.md");
|
|
9818
|
+
const domainGuideDest = join5(ReapPaths.userReapTemplates, "domain-guide.md");
|
|
9516
9819
|
await writeTextFile(domainGuideDest, await readTextFileOrThrow(domainGuideSrc));
|
|
9517
|
-
const mergeTemplatesDir =
|
|
9820
|
+
const mergeTemplatesDir = join5(ReapPaths.userReapTemplates, "merge");
|
|
9518
9821
|
await mkdir3(mergeTemplatesDir, { recursive: true });
|
|
9519
9822
|
const mergeArtifactFiles = ["01-detect.md", "02-mate.md", "03-merge.md", "04-sync.md", "05-validation.md", "06-completion.md"];
|
|
9520
|
-
const mergeSourceDir =
|
|
9823
|
+
const mergeSourceDir = join5(ReapPaths.packageArtifactsDir, "merge");
|
|
9521
9824
|
for (const file of mergeArtifactFiles) {
|
|
9522
|
-
const src =
|
|
9523
|
-
const dest =
|
|
9825
|
+
const src = join5(mergeSourceDir, file);
|
|
9826
|
+
const dest = join5(mergeTemplatesDir, file);
|
|
9524
9827
|
await writeTextFile(dest, await readTextFileOrThrow(src));
|
|
9525
9828
|
}
|
|
9526
9829
|
log("Installing brainstorm server...");
|
|
9527
|
-
const brainstormSourceDir =
|
|
9528
|
-
const brainstormDestDir =
|
|
9830
|
+
const brainstormSourceDir = join5(ReapPaths.packageTemplatesDir, "brainstorm");
|
|
9831
|
+
const brainstormDestDir = join5(paths.root, "brainstorm");
|
|
9529
9832
|
await mkdir3(brainstormDestDir, { recursive: true });
|
|
9530
9833
|
const brainstormFiles = ["server.cjs", "frame.html", "start-server.sh"];
|
|
9531
9834
|
for (const file of brainstormFiles) {
|
|
9532
|
-
const src =
|
|
9533
|
-
const dest =
|
|
9835
|
+
const src = join5(brainstormSourceDir, file);
|
|
9836
|
+
const dest = join5(brainstormDestDir, file);
|
|
9534
9837
|
await writeTextFile(dest, await readTextFileOrThrow(src));
|
|
9535
9838
|
if (file.endsWith(".sh"))
|
|
9536
9839
|
await chmod(dest, 493);
|
|
9537
9840
|
}
|
|
9538
9841
|
log("Installing hook conditions...");
|
|
9539
|
-
const conditionsSourceDir =
|
|
9540
|
-
const conditionsDestDir =
|
|
9842
|
+
const conditionsSourceDir = join5(ReapPaths.packageTemplatesDir, "conditions");
|
|
9843
|
+
const conditionsDestDir = join5(paths.hooks, "conditions");
|
|
9541
9844
|
await mkdir3(conditionsDestDir, { recursive: true });
|
|
9542
|
-
const conditionFiles = await
|
|
9845
|
+
const conditionFiles = await readdir4(conditionsSourceDir);
|
|
9543
9846
|
for (const file of conditionFiles) {
|
|
9544
9847
|
if (!file.endsWith(".sh"))
|
|
9545
9848
|
continue;
|
|
9546
|
-
const src =
|
|
9547
|
-
const dest =
|
|
9849
|
+
const src = join5(conditionsSourceDir, file);
|
|
9850
|
+
const dest = join5(conditionsDestDir, file);
|
|
9548
9851
|
await writeTextFile(dest, await readTextFileOrThrow(src));
|
|
9549
9852
|
await chmod(dest, 493);
|
|
9550
9853
|
}
|
|
@@ -9564,8 +9867,8 @@ async function initProject(projectRoot, projectName, entryMode, preset, onProgre
|
|
|
9564
9867
|
}
|
|
9565
9868
|
|
|
9566
9869
|
// src/cli/commands/update.ts
|
|
9567
|
-
import { readdir as
|
|
9568
|
-
import { join as
|
|
9870
|
+
import { readdir as readdir9, unlink as unlink3, rm as rm2, mkdir as mkdir6, chmod as chmod2 } from "fs/promises";
|
|
9871
|
+
import { join as join10 } from "path";
|
|
9569
9872
|
|
|
9570
9873
|
// src/core/hooks.ts
|
|
9571
9874
|
async function migrateHooks(dryRun = false) {
|
|
@@ -9580,17 +9883,21 @@ async function migrateHooks(dryRun = false) {
|
|
|
9580
9883
|
return { results };
|
|
9581
9884
|
}
|
|
9582
9885
|
|
|
9886
|
+
// src/cli/commands/update.ts
|
|
9887
|
+
init_fs();
|
|
9888
|
+
|
|
9583
9889
|
// src/core/migration.ts
|
|
9890
|
+
init_fs();
|
|
9584
9891
|
var import_yaml5 = __toESM(require_dist(), 1);
|
|
9585
|
-
import { readdir as
|
|
9586
|
-
import { join as
|
|
9892
|
+
import { readdir as readdir8, rename as rename2 } from "fs/promises";
|
|
9893
|
+
import { join as join9 } from "path";
|
|
9587
9894
|
|
|
9588
9895
|
// src/core/generation.ts
|
|
9589
9896
|
var import_yaml4 = __toESM(require_dist(), 1);
|
|
9590
9897
|
import { createHash } from "crypto";
|
|
9591
9898
|
import { hostname } from "os";
|
|
9592
|
-
import { readdir as
|
|
9593
|
-
import { join as
|
|
9899
|
+
import { readdir as readdir7, mkdir as mkdir4, rename } from "fs/promises";
|
|
9900
|
+
import { join as join8 } from "path";
|
|
9594
9901
|
|
|
9595
9902
|
// src/types/index.ts
|
|
9596
9903
|
var LIFECYCLE_ORDER = [
|
|
@@ -9644,9 +9951,10 @@ class LifeCycle {
|
|
|
9644
9951
|
}
|
|
9645
9952
|
|
|
9646
9953
|
// src/core/compression.ts
|
|
9954
|
+
init_fs();
|
|
9647
9955
|
var import_yaml2 = __toESM(require_dist(), 1);
|
|
9648
|
-
import { readdir as
|
|
9649
|
-
import { join as
|
|
9956
|
+
import { readdir as readdir5, rm } from "fs/promises";
|
|
9957
|
+
import { join as join6 } from "path";
|
|
9650
9958
|
var LINEAGE_MAX_LINES = 5000;
|
|
9651
9959
|
var MIN_GENERATIONS_FOR_COMPRESSION = 5;
|
|
9652
9960
|
var LEVEL1_MAX_LINES = 40;
|
|
@@ -9683,9 +9991,9 @@ async function countLines(filePath) {
|
|
|
9683
9991
|
async function countDirLines(dirPath) {
|
|
9684
9992
|
let total = 0;
|
|
9685
9993
|
try {
|
|
9686
|
-
const entries = await
|
|
9994
|
+
const entries = await readdir5(dirPath, { withFileTypes: true });
|
|
9687
9995
|
for (const entry of entries) {
|
|
9688
|
-
const fullPath =
|
|
9996
|
+
const fullPath = join6(dirPath, entry.name);
|
|
9689
9997
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
9690
9998
|
total += await countLines(fullPath);
|
|
9691
9999
|
} else if (entry.isDirectory()) {
|
|
@@ -9696,7 +10004,7 @@ async function countDirLines(dirPath) {
|
|
|
9696
10004
|
return total;
|
|
9697
10005
|
}
|
|
9698
10006
|
async function readDirMeta(dirPath) {
|
|
9699
|
-
const content = await readTextFile(
|
|
10007
|
+
const content = await readTextFile(join6(dirPath, "meta.yml"));
|
|
9700
10008
|
if (content === null)
|
|
9701
10009
|
return null;
|
|
9702
10010
|
try {
|
|
@@ -9714,9 +10022,9 @@ async function readFileMeta(filePath) {
|
|
|
9714
10022
|
async function scanLineage(paths) {
|
|
9715
10023
|
const entries = [];
|
|
9716
10024
|
try {
|
|
9717
|
-
const items = await
|
|
10025
|
+
const items = await readdir5(paths.lineage, { withFileTypes: true });
|
|
9718
10026
|
for (const item of items) {
|
|
9719
|
-
const fullPath =
|
|
10027
|
+
const fullPath = join6(paths.lineage, item.name);
|
|
9720
10028
|
if (item.isDirectory() && item.name.startsWith("gen-")) {
|
|
9721
10029
|
const genNum = extractGenNum(item.name);
|
|
9722
10030
|
const lines = await countDirLines(fullPath);
|
|
@@ -9770,7 +10078,7 @@ async function findLeafNodes(paths, entries) {
|
|
|
9770
10078
|
if (entry.type === "level2")
|
|
9771
10079
|
continue;
|
|
9772
10080
|
let meta = null;
|
|
9773
|
-
const fullPath =
|
|
10081
|
+
const fullPath = join6(paths.lineage, entry.name);
|
|
9774
10082
|
if (entry.type === "dir") {
|
|
9775
10083
|
meta = await readDirMeta(fullPath);
|
|
9776
10084
|
} else {
|
|
@@ -9801,7 +10109,7 @@ async function compressLevel1(genDir, genName) {
|
|
|
9801
10109
|
}
|
|
9802
10110
|
let goal = "", completionConditions = "";
|
|
9803
10111
|
{
|
|
9804
|
-
const objective = await readTextFile(
|
|
10112
|
+
const objective = await readTextFile(join6(genDir, "01-objective.md"));
|
|
9805
10113
|
if (objective) {
|
|
9806
10114
|
const goalMatch = objective.match(/## Goal\n([\s\S]*?)(?=\n##)/);
|
|
9807
10115
|
if (goalMatch)
|
|
@@ -9813,7 +10121,7 @@ async function compressLevel1(genDir, genName) {
|
|
|
9813
10121
|
}
|
|
9814
10122
|
let lessons = "", genomeChanges = "", nextBacklog = "";
|
|
9815
10123
|
{
|
|
9816
|
-
const completion = await readTextFile(
|
|
10124
|
+
const completion = await readTextFile(join6(genDir, "05-completion.md"));
|
|
9817
10125
|
if (completion) {
|
|
9818
10126
|
const lessonsMatch = completion.match(/### Lessons Learned\n([\s\S]*?)(?=\n###)/);
|
|
9819
10127
|
if (lessonsMatch)
|
|
@@ -9828,7 +10136,7 @@ async function compressLevel1(genDir, genName) {
|
|
|
9828
10136
|
}
|
|
9829
10137
|
let summaryText = "";
|
|
9830
10138
|
{
|
|
9831
|
-
const completion = await readTextFile(
|
|
10139
|
+
const completion = await readTextFile(join6(genDir, "05-completion.md"));
|
|
9832
10140
|
if (completion) {
|
|
9833
10141
|
const summaryMatch = completion.match(/## Summary\n([\s\S]*?)(?=\n##)/);
|
|
9834
10142
|
if (summaryMatch)
|
|
@@ -9837,7 +10145,7 @@ async function compressLevel1(genDir, genName) {
|
|
|
9837
10145
|
}
|
|
9838
10146
|
let validationResult = "";
|
|
9839
10147
|
{
|
|
9840
|
-
const validation = await readTextFile(
|
|
10148
|
+
const validation = await readTextFile(join6(genDir, "04-validation.md"));
|
|
9841
10149
|
if (validation) {
|
|
9842
10150
|
const resultMatch = validation.match(/## Result: (.+)/);
|
|
9843
10151
|
if (resultMatch)
|
|
@@ -9846,7 +10154,7 @@ async function compressLevel1(genDir, genName) {
|
|
|
9846
10154
|
}
|
|
9847
10155
|
let deferred = "";
|
|
9848
10156
|
{
|
|
9849
|
-
const impl = await readTextFile(
|
|
10157
|
+
const impl = await readTextFile(join6(genDir, "03-implementation.md"));
|
|
9850
10158
|
if (impl) {
|
|
9851
10159
|
const deferredMatch = impl.match(/## Deferred Tasks\n([\s\S]*?)(?=\n##)/);
|
|
9852
10160
|
if (deferredMatch) {
|
|
@@ -9970,10 +10278,10 @@ async function compressLineageIfNeeded(paths) {
|
|
|
9970
10278
|
const currentTotal = await countDirLines(paths.lineage);
|
|
9971
10279
|
if (currentTotal <= LINEAGE_MAX_LINES)
|
|
9972
10280
|
break;
|
|
9973
|
-
const dirPath =
|
|
10281
|
+
const dirPath = join6(paths.lineage, dir.name);
|
|
9974
10282
|
const compressed = await compressLevel1(dirPath, dir.name);
|
|
9975
10283
|
const genId = dir.name.match(/^gen-\d{3}(?:-[a-f0-9]{6})?/)?.[0] ?? dir.name;
|
|
9976
|
-
const outPath =
|
|
10284
|
+
const outPath = join6(paths.lineage, `${genId}.md`);
|
|
9977
10285
|
await writeTextFile(outPath, compressed);
|
|
9978
10286
|
await rm(dirPath, { recursive: true });
|
|
9979
10287
|
result.level1.push(genId);
|
|
@@ -9987,10 +10295,10 @@ async function compressLineageIfNeeded(paths) {
|
|
|
9987
10295
|
const batch = level1s.slice(i * LEVEL2_BATCH_SIZE, (i + 1) * LEVEL2_BATCH_SIZE);
|
|
9988
10296
|
const files = batch.map((e) => ({
|
|
9989
10297
|
name: e.name,
|
|
9990
|
-
path:
|
|
10298
|
+
path: join6(paths.lineage, e.name)
|
|
9991
10299
|
}));
|
|
9992
10300
|
const compressed = await compressLevel2(files, epochNum);
|
|
9993
|
-
const outPath =
|
|
10301
|
+
const outPath = join6(paths.lineage, `epoch-${String(epochNum).padStart(3, "0")}.md`);
|
|
9994
10302
|
await writeTextFile(outPath, compressed);
|
|
9995
10303
|
for (const file of files) {
|
|
9996
10304
|
await rm(file.path);
|
|
@@ -10002,20 +10310,24 @@ async function compressLineageIfNeeded(paths) {
|
|
|
10002
10310
|
return result;
|
|
10003
10311
|
}
|
|
10004
10312
|
|
|
10313
|
+
// src/core/generation.ts
|
|
10314
|
+
init_fs();
|
|
10315
|
+
|
|
10005
10316
|
// src/core/lineage.ts
|
|
10317
|
+
init_fs();
|
|
10006
10318
|
var import_yaml3 = __toESM(require_dist(), 1);
|
|
10007
|
-
import { readdir as
|
|
10008
|
-
import { join as
|
|
10319
|
+
import { readdir as readdir6 } from "fs/promises";
|
|
10320
|
+
import { join as join7 } from "path";
|
|
10009
10321
|
async function listCompleted(paths) {
|
|
10010
10322
|
try {
|
|
10011
|
-
const entries = await
|
|
10323
|
+
const entries = await readdir6(paths.lineage);
|
|
10012
10324
|
return entries.filter((e) => e.startsWith("gen-")).sort();
|
|
10013
10325
|
} catch {
|
|
10014
10326
|
return [];
|
|
10015
10327
|
}
|
|
10016
10328
|
}
|
|
10017
10329
|
async function readMeta(paths, lineageDirName) {
|
|
10018
|
-
const metaPath =
|
|
10330
|
+
const metaPath = join7(paths.lineage, lineageDirName, "meta.yml");
|
|
10019
10331
|
const content = await readTextFile(metaPath);
|
|
10020
10332
|
if (content === null)
|
|
10021
10333
|
return null;
|
|
@@ -10024,14 +10336,14 @@ async function readMeta(paths, lineageDirName) {
|
|
|
10024
10336
|
async function listMeta(paths) {
|
|
10025
10337
|
const metas = [];
|
|
10026
10338
|
try {
|
|
10027
|
-
const entries = await
|
|
10339
|
+
const entries = await readdir6(paths.lineage, { withFileTypes: true });
|
|
10028
10340
|
for (const entry of entries) {
|
|
10029
10341
|
if (entry.isDirectory() && entry.name.startsWith("gen-")) {
|
|
10030
10342
|
const meta = await readMeta(paths, entry.name);
|
|
10031
10343
|
if (meta)
|
|
10032
10344
|
metas.push(meta);
|
|
10033
10345
|
} else if (entry.isFile() && entry.name.startsWith("gen-") && entry.name.endsWith(".md")) {
|
|
10034
|
-
const content = await readTextFile(
|
|
10346
|
+
const content = await readTextFile(join7(paths.lineage, entry.name));
|
|
10035
10347
|
if (content) {
|
|
10036
10348
|
const meta = parseFrontmatter(content);
|
|
10037
10349
|
if (meta)
|
|
@@ -10085,13 +10397,13 @@ function getMachineId() {
|
|
|
10085
10397
|
async function computeGenomeHash(genomePath) {
|
|
10086
10398
|
const hash = createHash("sha256");
|
|
10087
10399
|
try {
|
|
10088
|
-
const entries = (await
|
|
10089
|
-
const pathA =
|
|
10090
|
-
const pathB =
|
|
10400
|
+
const entries = (await readdir7(genomePath, { recursive: true, withFileTypes: true })).filter((e) => e.isFile()).sort((a, b) => {
|
|
10401
|
+
const pathA = join8(e2path(a), a.name);
|
|
10402
|
+
const pathB = join8(e2path(b), b.name);
|
|
10091
10403
|
return pathA.localeCompare(pathB);
|
|
10092
10404
|
});
|
|
10093
10405
|
for (const entry of entries) {
|
|
10094
|
-
const filePath =
|
|
10406
|
+
const filePath = join8(e2path(entry), entry.name);
|
|
10095
10407
|
const content = await readTextFile(filePath);
|
|
10096
10408
|
if (content !== null) {
|
|
10097
10409
|
hash.update(filePath.replace(genomePath, ""));
|
|
@@ -10188,28 +10500,28 @@ class GenerationManager {
|
|
|
10188
10500
|
startedAt: state.startedAt,
|
|
10189
10501
|
completedAt: now
|
|
10190
10502
|
};
|
|
10191
|
-
await writeTextFile(
|
|
10192
|
-
const lifeEntries = await
|
|
10503
|
+
await writeTextFile(join8(genDir, "meta.yml"), import_yaml4.default.stringify(meta));
|
|
10504
|
+
const lifeEntries = await readdir7(this.paths.life);
|
|
10193
10505
|
for (const entry of lifeEntries) {
|
|
10194
10506
|
if (/^\d{2}-[a-z]+(?:-[a-z]+)*\.md$/.test(entry)) {
|
|
10195
|
-
await rename(
|
|
10507
|
+
await rename(join8(this.paths.life, entry), join8(genDir, entry));
|
|
10196
10508
|
}
|
|
10197
10509
|
}
|
|
10198
|
-
const backlogDir =
|
|
10510
|
+
const backlogDir = join8(genDir, "backlog");
|
|
10199
10511
|
await mkdir4(backlogDir, { recursive: true });
|
|
10200
10512
|
try {
|
|
10201
|
-
const backlogEntries = await
|
|
10513
|
+
const backlogEntries = await readdir7(this.paths.backlog);
|
|
10202
10514
|
for (const entry of backlogEntries) {
|
|
10203
|
-
await rename(
|
|
10515
|
+
await rename(join8(this.paths.backlog, entry), join8(backlogDir, entry));
|
|
10204
10516
|
}
|
|
10205
10517
|
} catch {}
|
|
10206
10518
|
try {
|
|
10207
|
-
const mutEntries = await
|
|
10519
|
+
const mutEntries = await readdir7(this.paths.mutations);
|
|
10208
10520
|
if (mutEntries.length > 0) {
|
|
10209
|
-
const mutDir =
|
|
10521
|
+
const mutDir = join8(genDir, "mutations");
|
|
10210
10522
|
await mkdir4(mutDir, { recursive: true });
|
|
10211
10523
|
for (const entry of mutEntries) {
|
|
10212
|
-
await rename(
|
|
10524
|
+
await rename(join8(this.paths.mutations, entry), join8(mutDir, entry));
|
|
10213
10525
|
}
|
|
10214
10526
|
}
|
|
10215
10527
|
} catch {}
|
|
@@ -10245,11 +10557,11 @@ class GenerationManager {
|
|
|
10245
10557
|
// src/core/migration.ts
|
|
10246
10558
|
async function needsMigration(paths) {
|
|
10247
10559
|
try {
|
|
10248
|
-
const entries = await
|
|
10560
|
+
const entries = await readdir8(paths.lineage, { withFileTypes: true });
|
|
10249
10561
|
for (const entry of entries) {
|
|
10250
10562
|
if (!entry.isDirectory() || !entry.name.startsWith("gen-"))
|
|
10251
10563
|
continue;
|
|
10252
|
-
const metaPath =
|
|
10564
|
+
const metaPath = join9(paths.lineage, entry.name, "meta.yml");
|
|
10253
10565
|
const content = await readTextFile(metaPath);
|
|
10254
10566
|
if (content === null)
|
|
10255
10567
|
return true;
|
|
@@ -10263,18 +10575,18 @@ async function migrateLineage(paths) {
|
|
|
10263
10575
|
const result = { migrated: [], skipped: [], errors: [] };
|
|
10264
10576
|
let entries;
|
|
10265
10577
|
try {
|
|
10266
|
-
const dirEntries = await
|
|
10578
|
+
const dirEntries = await readdir8(paths.lineage, { withFileTypes: true });
|
|
10267
10579
|
entries = dirEntries.filter((e) => e.isDirectory() && e.name.startsWith("gen-")).map((e) => e.name).sort();
|
|
10268
10580
|
} catch {
|
|
10269
10581
|
return result;
|
|
10270
10582
|
}
|
|
10271
10583
|
const plan = [];
|
|
10272
10584
|
for (const dirName of entries) {
|
|
10273
|
-
const metaPath =
|
|
10585
|
+
const metaPath = join9(paths.lineage, dirName, "meta.yml");
|
|
10274
10586
|
const metaContent = await readTextFile(metaPath);
|
|
10275
10587
|
const seq = parseGenSeq(dirName);
|
|
10276
10588
|
let goal = "";
|
|
10277
|
-
const objContent = await readTextFile(
|
|
10589
|
+
const objContent = await readTextFile(join9(paths.lineage, dirName, "01-objective.md"));
|
|
10278
10590
|
if (objContent) {
|
|
10279
10591
|
const goalMatch = objContent.match(/## Goal\n+([\s\S]*?)(?=\n##)/);
|
|
10280
10592
|
if (goalMatch)
|
|
@@ -10289,7 +10601,7 @@ async function migrateLineage(paths) {
|
|
|
10289
10601
|
let prevId = null;
|
|
10290
10602
|
for (const entry of plan) {
|
|
10291
10603
|
if (entry.hasMeta) {
|
|
10292
|
-
const metaContent = await readTextFile(
|
|
10604
|
+
const metaContent = await readTextFile(join9(paths.lineage, entry.dirName, "meta.yml"));
|
|
10293
10605
|
if (metaContent) {
|
|
10294
10606
|
const meta = import_yaml5.default.parse(metaContent);
|
|
10295
10607
|
prevId = meta.id;
|
|
@@ -10310,11 +10622,11 @@ async function migrateLineage(paths) {
|
|
|
10310
10622
|
startedAt: `legacy-${entry.seq}`,
|
|
10311
10623
|
completedAt: `legacy-${entry.seq}`
|
|
10312
10624
|
};
|
|
10313
|
-
await writeTextFile(
|
|
10625
|
+
await writeTextFile(join9(paths.lineage, entry.dirName, "meta.yml"), import_yaml5.default.stringify(meta));
|
|
10314
10626
|
const oldSlug = entry.dirName.replace(/^gen-\d{3}/, "");
|
|
10315
10627
|
const newDirName = `${newId}${oldSlug}`;
|
|
10316
10628
|
if (newDirName !== entry.dirName) {
|
|
10317
|
-
await rename2(
|
|
10629
|
+
await rename2(join9(paths.lineage, entry.dirName), join9(paths.lineage, newDirName));
|
|
10318
10630
|
}
|
|
10319
10631
|
prevId = newId;
|
|
10320
10632
|
result.migrated.push(`${entry.dirName} → ${newDirName}`);
|
|
@@ -10352,13 +10664,13 @@ async function updateProject(projectRoot, dryRun = false) {
|
|
|
10352
10664
|
const config = await ConfigManager.read(paths);
|
|
10353
10665
|
const adapters = await AgentRegistry.getActiveAdapters(config ?? undefined);
|
|
10354
10666
|
const commandsDir = ReapPaths.packageCommandsDir;
|
|
10355
|
-
const commandFiles = await
|
|
10667
|
+
const commandFiles = await readdir9(commandsDir);
|
|
10356
10668
|
await mkdir6(ReapPaths.userReapCommands, { recursive: true });
|
|
10357
10669
|
for (const file of commandFiles) {
|
|
10358
10670
|
if (!file.endsWith(".md"))
|
|
10359
10671
|
continue;
|
|
10360
|
-
const src = await readTextFileOrThrow(
|
|
10361
|
-
const dest =
|
|
10672
|
+
const src = await readTextFileOrThrow(join10(commandsDir, file));
|
|
10673
|
+
const dest = join10(ReapPaths.userReapCommands, file);
|
|
10362
10674
|
const existing = await readTextFile(dest);
|
|
10363
10675
|
if (existing !== null && existing === src) {
|
|
10364
10676
|
result.skipped.push(`~/.reap/commands/${file}`);
|
|
@@ -10380,7 +10692,7 @@ description: "REAP — redirected to ~/.reap/commands/"
|
|
|
10380
10692
|
---
|
|
10381
10693
|
Read \`~/.reap/commands/${cmdName}.md\` and follow the instructions there.
|
|
10382
10694
|
`;
|
|
10383
|
-
const dest =
|
|
10695
|
+
const dest = join10(agentCmdDir, file);
|
|
10384
10696
|
const existingContent = await readTextFile(dest);
|
|
10385
10697
|
if (existingContent !== null && existingContent === redirectContent) {
|
|
10386
10698
|
result.skipped.push(`[${label}] commands/${file}`);
|
|
@@ -10400,8 +10712,8 @@ Read \`~/.reap/commands/${cmdName}.md\` and follow the instructions there.
|
|
|
10400
10712
|
await mkdir6(ReapPaths.userReapTemplates, { recursive: true });
|
|
10401
10713
|
const artifactFiles = ["01-objective.md", "02-planning.md", "03-implementation.md", "04-validation.md", "05-completion.md"];
|
|
10402
10714
|
for (const file of artifactFiles) {
|
|
10403
|
-
const src = await readTextFileOrThrow(
|
|
10404
|
-
const dest =
|
|
10715
|
+
const src = await readTextFileOrThrow(join10(ReapPaths.packageArtifactsDir, file));
|
|
10716
|
+
const dest = join10(ReapPaths.userReapTemplates, file);
|
|
10405
10717
|
const existingContent = await readTextFile(dest);
|
|
10406
10718
|
if (existingContent !== null && existingContent === src) {
|
|
10407
10719
|
result.skipped.push(`~/.reap/templates/${file}`);
|
|
@@ -10411,8 +10723,8 @@ Read \`~/.reap/commands/${cmdName}.md\` and follow the instructions there.
|
|
|
10411
10723
|
result.updated.push(`~/.reap/templates/${file}`);
|
|
10412
10724
|
}
|
|
10413
10725
|
}
|
|
10414
|
-
const domainGuideSrc = await readTextFileOrThrow(
|
|
10415
|
-
const domainGuideDest =
|
|
10726
|
+
const domainGuideSrc = await readTextFileOrThrow(join10(ReapPaths.packageGenomeDir, "domain/README.md"));
|
|
10727
|
+
const domainGuideDest = join10(ReapPaths.userReapTemplates, "domain-guide.md");
|
|
10416
10728
|
const domainExistingContent = await readTextFile(domainGuideDest);
|
|
10417
10729
|
if (domainExistingContent !== null && domainExistingContent === domainGuideSrc) {
|
|
10418
10730
|
result.skipped.push(`~/.reap/templates/domain-guide.md`);
|
|
@@ -10421,13 +10733,13 @@ Read \`~/.reap/commands/${cmdName}.md\` and follow the instructions there.
|
|
|
10421
10733
|
await writeTextFile(domainGuideDest, domainGuideSrc);
|
|
10422
10734
|
result.updated.push(`~/.reap/templates/domain-guide.md`);
|
|
10423
10735
|
}
|
|
10424
|
-
const mergeTemplatesDir =
|
|
10736
|
+
const mergeTemplatesDir = join10(ReapPaths.userReapTemplates, "merge");
|
|
10425
10737
|
await mkdir6(mergeTemplatesDir, { recursive: true });
|
|
10426
10738
|
const mergeArtifactFiles = ["01-detect.md", "02-mate.md", "03-merge.md", "04-sync.md", "05-validation.md", "06-completion.md"];
|
|
10427
|
-
const mergeSourceDir =
|
|
10739
|
+
const mergeSourceDir = join10(ReapPaths.packageArtifactsDir, "merge");
|
|
10428
10740
|
for (const file of mergeArtifactFiles) {
|
|
10429
|
-
const src = await readTextFileOrThrow(
|
|
10430
|
-
const dest =
|
|
10741
|
+
const src = await readTextFileOrThrow(join10(mergeSourceDir, file));
|
|
10742
|
+
const dest = join10(mergeTemplatesDir, file);
|
|
10431
10743
|
const existing = await readTextFile(dest);
|
|
10432
10744
|
if (existing !== null && existing === src) {
|
|
10433
10745
|
result.skipped.push(`~/.reap/templates/merge/${file}`);
|
|
@@ -10437,13 +10749,13 @@ Read \`~/.reap/commands/${cmdName}.md\` and follow the instructions there.
|
|
|
10437
10749
|
result.updated.push(`~/.reap/templates/merge/${file}`);
|
|
10438
10750
|
}
|
|
10439
10751
|
}
|
|
10440
|
-
const brainstormSourceDir =
|
|
10441
|
-
const brainstormDestDir =
|
|
10752
|
+
const brainstormSourceDir = join10(ReapPaths.packageTemplatesDir, "brainstorm");
|
|
10753
|
+
const brainstormDestDir = join10(paths.root, "brainstorm");
|
|
10442
10754
|
await mkdir6(brainstormDestDir, { recursive: true });
|
|
10443
10755
|
const brainstormFiles = ["server.cjs", "frame.html", "start-server.sh"];
|
|
10444
10756
|
for (const file of brainstormFiles) {
|
|
10445
|
-
const src = await readTextFileOrThrow(
|
|
10446
|
-
const dest =
|
|
10757
|
+
const src = await readTextFileOrThrow(join10(brainstormSourceDir, file));
|
|
10758
|
+
const dest = join10(brainstormDestDir, file);
|
|
10447
10759
|
const existing = await readTextFile(dest);
|
|
10448
10760
|
if (existing !== null && existing === src) {
|
|
10449
10761
|
result.skipped.push(`.reap/brainstorm/${file}`);
|
|
@@ -10492,11 +10804,11 @@ async function migrateLegacyFiles(paths, dryRun, result) {
|
|
|
10492
10804
|
await removeDirIfExists(paths.legacyTemplates, ".reap/templates/", dryRun, result);
|
|
10493
10805
|
try {
|
|
10494
10806
|
const claudeCmdDir = paths.legacyClaudeCommands;
|
|
10495
|
-
const files = await
|
|
10807
|
+
const files = await readdir9(claudeCmdDir);
|
|
10496
10808
|
for (const file of files) {
|
|
10497
10809
|
if (file.startsWith("reap.") && file.endsWith(".md")) {
|
|
10498
10810
|
if (!dryRun)
|
|
10499
|
-
await unlink3(
|
|
10811
|
+
await unlink3(join10(claudeCmdDir, file));
|
|
10500
10812
|
result.removed.push(`.claude/commands/${file}`);
|
|
10501
10813
|
}
|
|
10502
10814
|
}
|
|
@@ -10540,7 +10852,7 @@ async function migrateLegacyFiles(paths, dryRun, result) {
|
|
|
10540
10852
|
}
|
|
10541
10853
|
async function removeDirIfExists(dirPath, label, dryRun, result) {
|
|
10542
10854
|
try {
|
|
10543
|
-
const entries = await
|
|
10855
|
+
const entries = await readdir9(dirPath);
|
|
10544
10856
|
if (entries.length > 0 || true) {
|
|
10545
10857
|
if (!dryRun)
|
|
10546
10858
|
await rm2(dirPath, { recursive: true });
|
|
@@ -10575,10 +10887,11 @@ async function getStatus(projectRoot) {
|
|
|
10575
10887
|
|
|
10576
10888
|
// src/cli/commands/fix.ts
|
|
10577
10889
|
var import_yaml6 = __toESM(require_dist(), 1);
|
|
10578
|
-
import { mkdir as mkdir7, stat as
|
|
10890
|
+
import { mkdir as mkdir7, stat as stat3 } from "fs/promises";
|
|
10891
|
+
init_fs();
|
|
10579
10892
|
async function dirExists(path) {
|
|
10580
10893
|
try {
|
|
10581
|
-
const s = await
|
|
10894
|
+
const s = await stat3(path);
|
|
10582
10895
|
return s.isDirectory();
|
|
10583
10896
|
} catch {
|
|
10584
10897
|
return false;
|
|
@@ -10631,8 +10944,9 @@ async function fixProject(projectRoot) {
|
|
|
10631
10944
|
}
|
|
10632
10945
|
|
|
10633
10946
|
// src/cli/index.ts
|
|
10634
|
-
|
|
10635
|
-
|
|
10947
|
+
init_fs();
|
|
10948
|
+
import { join as join11 } from "path";
|
|
10949
|
+
program.name("reap").description("REAP — Recursive Evolutionary Autonomous Pipeline").version("0.7.1");
|
|
10636
10950
|
program.command("init").description("Initialize a new REAP project (Genesis)").argument("[project-name]", "Project name (defaults to current directory name)").option("-m, --mode <mode>", "Entry mode: greenfield, migration, adoption", "greenfield").option("-p, --preset <preset>", "Bootstrap with a genome preset (e.g., bun-hono-react)").action(async (projectName, options) => {
|
|
10637
10951
|
try {
|
|
10638
10952
|
const cwd = process.cwd();
|
|
@@ -10754,10 +11068,10 @@ program.command("help").description("Show REAP commands, slash commands, and wor
|
|
|
10754
11068
|
if (l === "korean" || l === "ko")
|
|
10755
11069
|
lang = "ko";
|
|
10756
11070
|
}
|
|
10757
|
-
const helpDir =
|
|
10758
|
-
let helpText = await readTextFile(
|
|
11071
|
+
const helpDir = join11(ReapPaths.packageTemplatesDir, "help");
|
|
11072
|
+
let helpText = await readTextFile(join11(helpDir, `${lang}.txt`));
|
|
10759
11073
|
if (!helpText)
|
|
10760
|
-
helpText = await readTextFile(
|
|
11074
|
+
helpText = await readTextFile(join11(helpDir, "en.txt"));
|
|
10761
11075
|
if (!helpText) {
|
|
10762
11076
|
console.log("Help file not found. Run 'reap update' to install templates.");
|
|
10763
11077
|
return;
|