@c-d-cc/reap 0.15.13 → 0.15.14
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
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Release Notices
|
|
2
2
|
|
|
3
|
+
## v0.15.14
|
|
4
|
+
### en
|
|
5
|
+
Auto-update guard for breaking changes. New Release Notes docs page with v0.16 pre-announcement.
|
|
6
|
+
### ko
|
|
7
|
+
Breaking change 대비 자동 업데이트 차단 기능 추가. v0.16 사전 고지가 포함된 릴리스 노트 페이지 신규.
|
|
8
|
+
|
|
3
9
|
## v0.15.13
|
|
4
10
|
### en
|
|
5
11
|
Replaced `commander.js` with built-in CLI library. Runtime dependencies: 2 → 1.
|
package/dist/cli.js
CHANGED
|
@@ -8391,7 +8391,7 @@ function checkLatestVersion() {
|
|
|
8391
8391
|
}
|
|
8392
8392
|
}
|
|
8393
8393
|
function getCurrentVersion() {
|
|
8394
|
-
return "0.15.
|
|
8394
|
+
return "0.15.14";
|
|
8395
8395
|
}
|
|
8396
8396
|
function formatVersionLine(current, skipCheck) {
|
|
8397
8397
|
if (skipCheck) {
|
|
@@ -10604,7 +10604,7 @@ async function execute17(paths) {
|
|
|
10604
10604
|
const gm = new GenerationManager(paths);
|
|
10605
10605
|
const state = await gm.current();
|
|
10606
10606
|
const configContent = await readTextFile(paths.config);
|
|
10607
|
-
const installedVersion = "0.15.
|
|
10607
|
+
const installedVersion = "0.15.14";
|
|
10608
10608
|
const autoUpdate = configContent?.match(/autoUpdate:\s*(true|false)/)?.[1] === "true";
|
|
10609
10609
|
const versionDisplay = formatVersionLine(installedVersion, !autoUpdate);
|
|
10610
10610
|
const rawLang = detectLanguage(configContent);
|
|
@@ -12332,7 +12332,7 @@ async function execute30(paths) {
|
|
|
12332
12332
|
const lines = [
|
|
12333
12333
|
`REAP Configuration (${paths.config})`,
|
|
12334
12334
|
"",
|
|
12335
|
-
` version: ${"0.15.
|
|
12335
|
+
` version: ${"0.15.14"} (package)`,
|
|
12336
12336
|
` project: ${config.project}`,
|
|
12337
12337
|
` entryMode: ${config.entryMode}`,
|
|
12338
12338
|
` strict: ${config.strict ?? false}`,
|
|
@@ -12638,7 +12638,7 @@ async function runCommand(command, phase, argv = []) {
|
|
|
12638
12638
|
try {
|
|
12639
12639
|
const config = await ConfigManager.read(paths);
|
|
12640
12640
|
if (config.autoIssueReport) {
|
|
12641
|
-
const version = "0.15.
|
|
12641
|
+
const version = "0.15.14";
|
|
12642
12642
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
12643
12643
|
const title = `[auto] reap run ${command}: ${errMsg.slice(0, 80)}`;
|
|
12644
12644
|
const body = [
|
|
@@ -14959,12 +14959,54 @@ function selfUpgrade() {
|
|
|
14959
14959
|
if (installed === latest) {
|
|
14960
14960
|
return { upgraded: false };
|
|
14961
14961
|
}
|
|
14962
|
+
const minVersion = queryAutoUpdateMinVersion();
|
|
14963
|
+
if (minVersion && !semverGte(installed, minVersion)) {
|
|
14964
|
+
return {
|
|
14965
|
+
upgraded: false,
|
|
14966
|
+
blocked: true,
|
|
14967
|
+
from: installed,
|
|
14968
|
+
to: latest,
|
|
14969
|
+
reason: `Breaking change: v${installed} -> v${latest}. Run '/reap.update' to upgrade manually. See https://reap.cc/docs/release-notes`
|
|
14970
|
+
};
|
|
14971
|
+
}
|
|
14962
14972
|
execSync3("npm update -g @c-d-cc/reap", { encoding: "utf-8", timeout: 60000, stdio: "pipe" });
|
|
14963
14973
|
return { upgraded: true, from: installed, to: latest };
|
|
14964
14974
|
} catch {
|
|
14965
14975
|
return { upgraded: false };
|
|
14966
14976
|
}
|
|
14967
14977
|
}
|
|
14978
|
+
function semverGte(a, b) {
|
|
14979
|
+
const pa = a.split(".").map(Number);
|
|
14980
|
+
const pb = b.split(".").map(Number);
|
|
14981
|
+
for (let i = 0;i < 3; i++) {
|
|
14982
|
+
if ((pa[i] ?? 0) > (pb[i] ?? 0))
|
|
14983
|
+
return true;
|
|
14984
|
+
if ((pa[i] ?? 0) < (pb[i] ?? 0))
|
|
14985
|
+
return false;
|
|
14986
|
+
}
|
|
14987
|
+
return true;
|
|
14988
|
+
}
|
|
14989
|
+
function forceUpgrade(to) {
|
|
14990
|
+
try {
|
|
14991
|
+
const installed = execSync3("reap --version", { encoding: "utf-8", timeout: 5000 }).trim();
|
|
14992
|
+
execSync3(`npm install -g @c-d-cc/reap@${to}`, { encoding: "utf-8", timeout: 60000, stdio: "pipe" });
|
|
14993
|
+
return { upgraded: true, from: installed, to };
|
|
14994
|
+
} catch {
|
|
14995
|
+
return { upgraded: false };
|
|
14996
|
+
}
|
|
14997
|
+
}
|
|
14998
|
+
function queryAutoUpdateMinVersion() {
|
|
14999
|
+
try {
|
|
15000
|
+
const result = execSync3("npm view @c-d-cc/reap reap.autoUpdateMinVersion", {
|
|
15001
|
+
encoding: "utf-8",
|
|
15002
|
+
timeout: 1e4,
|
|
15003
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
15004
|
+
});
|
|
15005
|
+
return result.trim() || null;
|
|
15006
|
+
} catch {
|
|
15007
|
+
return null;
|
|
15008
|
+
}
|
|
15009
|
+
}
|
|
14968
15010
|
async function updateProject(projectRoot, dryRun = false) {
|
|
14969
15011
|
const paths = new ReapPaths(projectRoot);
|
|
14970
15012
|
const result = { updated: [], skipped: [], removed: [] };
|
|
@@ -15259,7 +15301,7 @@ async function getStatus(projectRoot) {
|
|
|
15259
15301
|
const totalCompleted = await mgr.countAllCompleted();
|
|
15260
15302
|
const integrityResult = await checkIntegrity(paths);
|
|
15261
15303
|
return {
|
|
15262
|
-
version: "0.15.
|
|
15304
|
+
version: "0.15.14",
|
|
15263
15305
|
project: config.project,
|
|
15264
15306
|
entryMode: config.entryMode,
|
|
15265
15307
|
lastSyncedGeneration: config.lastSyncedGeneration,
|
|
@@ -15582,7 +15624,7 @@ init_fs();
|
|
|
15582
15624
|
init_version();
|
|
15583
15625
|
init_config();
|
|
15584
15626
|
import { join as join34 } from "path";
|
|
15585
|
-
program.name("reap").description("REAP — Recursive Evolutionary Autonomous Pipeline").version("0.15.
|
|
15627
|
+
program.name("reap").description("REAP — Recursive Evolutionary Autonomous Pipeline").version("0.15.14");
|
|
15586
15628
|
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) => {
|
|
15587
15629
|
try {
|
|
15588
15630
|
const cwd = process.cwd();
|
|
@@ -15639,7 +15681,7 @@ program.command("status").description("Show current project and Generation statu
|
|
|
15639
15681
|
const paths = new ReapPaths(cwd);
|
|
15640
15682
|
const config = await ConfigManager.read(paths);
|
|
15641
15683
|
const skipCheck = config.autoUpdate === false;
|
|
15642
|
-
const installedVersion = "0.15.
|
|
15684
|
+
const installedVersion = "0.15.14";
|
|
15643
15685
|
const versionLine = formatVersionLine(installedVersion, skipCheck);
|
|
15644
15686
|
console.log(`${versionLine} | Project: ${status.project} (${status.entryMode})`);
|
|
15645
15687
|
console.log(`Completed Generations: ${status.totalGenerations}`);
|
|
@@ -15711,8 +15753,29 @@ program.command("fix").description("Diagnose and repair .reap/ directory structu
|
|
|
15711
15753
|
});
|
|
15712
15754
|
program.command("update").description("Upgrade REAP package and sync slash commands, templates, and hooks").option("--dry-run", "Show changes without applying them").action(async (options) => {
|
|
15713
15755
|
try {
|
|
15714
|
-
|
|
15715
|
-
if (upgrade.
|
|
15756
|
+
let upgrade = !options.dryRun ? selfUpgrade() : { upgraded: false };
|
|
15757
|
+
if (upgrade.blocked) {
|
|
15758
|
+
console.log(`
|
|
15759
|
+
⚠ Breaking change detected: v${upgrade.from} → v${upgrade.to}`);
|
|
15760
|
+
console.log(` This update contains breaking changes that may require manual migration.`);
|
|
15761
|
+
console.log(` See release notes: https://reap.cc/docs/release-notes
|
|
15762
|
+
`);
|
|
15763
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
15764
|
+
const answer = await new Promise((resolve) => {
|
|
15765
|
+
rl.question(" Proceed with update? (y/N) ", resolve);
|
|
15766
|
+
});
|
|
15767
|
+
rl.close();
|
|
15768
|
+
if (answer.toLowerCase() === "y" || answer.toLowerCase() === "yes") {
|
|
15769
|
+
upgrade = forceUpgrade(upgrade.to);
|
|
15770
|
+
if (upgrade.upgraded) {
|
|
15771
|
+
console.log(`Upgraded: v${upgrade.from} → v${upgrade.to}`);
|
|
15772
|
+
} else {
|
|
15773
|
+
console.log("Upgrade failed. Try manually: npm install -g @c-d-cc/reap@latest");
|
|
15774
|
+
}
|
|
15775
|
+
} else {
|
|
15776
|
+
console.log("Update skipped.");
|
|
15777
|
+
}
|
|
15778
|
+
} else if (upgrade.upgraded) {
|
|
15716
15779
|
console.log(`Upgraded: v${upgrade.from} → v${upgrade.to}`);
|
|
15717
15780
|
}
|
|
15718
15781
|
const result = await updateProject(process.cwd(), options.dryRun ?? false);
|
|
@@ -5,6 +5,17 @@ const { execSync } = require("child_process");
|
|
|
5
5
|
const fs = require("fs");
|
|
6
6
|
const path = require("path");
|
|
7
7
|
|
|
8
|
+
// Inline semver comparison (no external deps): returns true if a >= b
|
|
9
|
+
function semverGte(a, b) {
|
|
10
|
+
const pa = a.split(".").map(Number);
|
|
11
|
+
const pb = b.split(".").map(Number);
|
|
12
|
+
for (let i = 0; i < 3; i++) {
|
|
13
|
+
if ((pa[i] || 0) > (pb[i] || 0)) return true;
|
|
14
|
+
if ((pa[i] || 0) < (pb[i] || 0)) return false;
|
|
15
|
+
}
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
|
|
8
19
|
module.exports = async (ctx) => {
|
|
9
20
|
return {
|
|
10
21
|
"session.start": async ({ trigger }) => {
|
|
@@ -50,9 +61,15 @@ module.exports = async (ctx) => {
|
|
|
50
61
|
const installed = gl.exec("reap --version 2>/dev/null", execOpts);
|
|
51
62
|
const latest = gl.exec("npm view @c-d-cc/reap version 2>/dev/null", execOpts);
|
|
52
63
|
if (installed && latest && installed !== latest) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
64
|
+
// Auto-update guard: check autoUpdateMinVersion
|
|
65
|
+
const minVersion = gl.exec("npm view @c-d-cc/reap reap.autoUpdateMinVersion 2>/dev/null", execOpts);
|
|
66
|
+
if (minVersion && !semverGte(installed, minVersion)) {
|
|
67
|
+
autoUpdateMessage = `[BREAKING] Auto-update blocked: v${installed} -> v${latest} contains breaking changes. Inform the user about this breaking change and ask if they want to update via '/reap.update'. Release notes: https://reap.cc/docs/release-notes`;
|
|
68
|
+
} else {
|
|
69
|
+
execSync("npm update -g @c-d-cc/reap >/dev/null 2>&1", { ...execOpts, stdio: "ignore" });
|
|
70
|
+
execSync("reap update >/dev/null 2>&1", { ...execOpts, stdio: "ignore" });
|
|
71
|
+
autoUpdateMessage = `REAP auto-updated: v${installed} → v${latest}`;
|
|
72
|
+
}
|
|
56
73
|
}
|
|
57
74
|
} catch { /* update check failed, skip */ }
|
|
58
75
|
}
|
|
@@ -109,7 +126,11 @@ module.exports = async (ctx) => {
|
|
|
109
126
|
// Build auto-update section
|
|
110
127
|
let updateSection = "";
|
|
111
128
|
if (autoUpdateMessage) {
|
|
112
|
-
|
|
129
|
+
if (autoUpdateMessage.startsWith("[BREAKING]")) {
|
|
130
|
+
updateSection = `\n\n## Auto-Update (Breaking Change Detected)\n${autoUpdateMessage}\n\nIMPORTANT: On your first response, explain to the user that a new REAP version is available but contains breaking changes. Show them the release notes link and ask for explicit confirmation before they run the manual update command. Do NOT silently skip this.`;
|
|
131
|
+
} else {
|
|
132
|
+
updateSection = `\n\n## Auto-Update\n${autoUpdateMessage}. Tell the user: "${autoUpdateMessage}"`;
|
|
133
|
+
}
|
|
113
134
|
}
|
|
114
135
|
|
|
115
136
|
const context = `<REAP_WORKFLOW>\n${reapGuide}\n\n---\n\n## Genome (Project Knowledge)\n${genomeContent}\n\n---\n\n## Current State\n${generationContext}${staleSection}${strictSection}${updateSection}${langSection}\n\n## Rules\n1. ALL development work MUST follow the REAP lifecycle.\n2. Before writing any code, check if a Generation is active and what stage it is in.\n3. If a Generation is active, use \`${nextCmd}\` to proceed with the current stage.\n4. If no Generation is active, use \`/reap.start\` to start a new one.\n5. Do NOT implement features outside of the REAP lifecycle unless explicitly asked.\n6. Genome is the authoritative knowledge source.\n</REAP_WORKFLOW>`;
|
|
@@ -117,6 +117,17 @@ if (gl.dirExists(userReapCommands)) {
|
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
// Inline semver comparison (no external deps): returns true if a >= b
|
|
121
|
+
function semverGte(a, b) {
|
|
122
|
+
const pa = a.split('.').map(Number);
|
|
123
|
+
const pb = b.split('.').map(Number);
|
|
124
|
+
for (let i = 0; i < 3; i++) {
|
|
125
|
+
if ((pa[i] || 0) > (pb[i] || 0)) return true;
|
|
126
|
+
if ((pa[i] || 0) < (pb[i] || 0)) return false;
|
|
127
|
+
}
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
|
|
120
131
|
// Step 1: Version check + Auto-update
|
|
121
132
|
log('Checking for updates...');
|
|
122
133
|
let autoUpdateMessage = '';
|
|
@@ -129,10 +140,17 @@ if (installed && installed.includes('+dev')) {
|
|
|
129
140
|
} else if (installed && latest && installed !== latest) {
|
|
130
141
|
const autoUpdate = configContent ? /^autoUpdate:\s*true/m.test(configContent) : false;
|
|
131
142
|
if (autoUpdate) {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
143
|
+
// Auto-update guard: check autoUpdateMinVersion before upgrading
|
|
144
|
+
const minVersion = gl.exec('npm view @c-d-cc/reap reap.autoUpdateMinVersion');
|
|
145
|
+
if (minVersion && !semverGte(installed, minVersion)) {
|
|
146
|
+
// Breaking change detected — block auto-update
|
|
147
|
+
autoUpdateMessage = `[BREAKING] Auto-update blocked: v${installed} → v${latest} contains breaking changes. Inform the user about this breaking change and ask if they want to update via '/reap.update'. Release notes: https://reap.cc/docs/release-notes`;
|
|
148
|
+
} else {
|
|
149
|
+
const updated = gl.exec('npm update -g @c-d-cc/reap');
|
|
150
|
+
if (updated !== null) {
|
|
151
|
+
gl.exec('reap update');
|
|
152
|
+
autoUpdateMessage = `REAP auto-updated: v${installed} → v${latest}`;
|
|
153
|
+
}
|
|
136
154
|
}
|
|
137
155
|
} else {
|
|
138
156
|
updateAvailableMessage = `update available: v${installed} → v${latest}`;
|
|
@@ -178,7 +196,11 @@ if (genomeStaleWarning) {
|
|
|
178
196
|
// Build auto-update section
|
|
179
197
|
let updateSection = '';
|
|
180
198
|
if (autoUpdateMessage) {
|
|
181
|
-
|
|
199
|
+
if (autoUpdateMessage.startsWith('[BREAKING]')) {
|
|
200
|
+
updateSection = `\n\n## Auto-Update (Breaking Change Detected)\n${autoUpdateMessage}\n\nIMPORTANT: On your first response, explain to the user that a new REAP version is available but contains breaking changes. Show them the release notes link and ask for explicit confirmation before they run the manual update command. Do NOT silently skip this.`;
|
|
201
|
+
} else {
|
|
202
|
+
updateSection = `\n\n## Auto-Update\n${autoUpdateMessage}. Tell the user: "${autoUpdateMessage}"`;
|
|
203
|
+
}
|
|
182
204
|
}
|
|
183
205
|
|
|
184
206
|
// Build session init display
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c-d-cc/reap",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.14",
|
|
4
4
|
"description": "Recursive Evolutionary Autonomous Pipeline — AI and humans evolve software across generations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -46,5 +46,8 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"yaml": "^2.0.0"
|
|
49
|
+
},
|
|
50
|
+
"reap": {
|
|
51
|
+
"autoUpdateMinVersion": "0.15.0"
|
|
49
52
|
}
|
|
50
53
|
}
|