@c-d-cc/reap 0.15.12 → 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.
@@ -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
- execSync("npm update -g @c-d-cc/reap >/dev/null 2>&1", { ...execOpts, stdio: "ignore" });
54
- execSync("reap update >/dev/null 2>&1", { ...execOpts, stdio: "ignore" });
55
- autoUpdateMessage = `REAP auto-updated: v${installed} v${latest}`;
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
- updateSection = `\n\n## Auto-Update\n${autoUpdateMessage}. Tell the user: "${autoUpdateMessage}"`;
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
- const updated = gl.exec('npm update -g @c-d-cc/reap');
133
- if (updated !== null) {
134
- gl.exec('reap update');
135
- autoUpdateMessage = `REAP auto-updated: v${installed} v${latest}`;
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
- updateSection = `\n\n## Auto-Update\n${autoUpdateMessage}. Tell the user: "${autoUpdateMessage}"`;
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.12",
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",
@@ -45,7 +45,9 @@
45
45
  "typescript": "^5.0.0"
46
46
  },
47
47
  "dependencies": {
48
- "commander": "^12.0.0",
49
48
  "yaml": "^2.0.0"
49
+ },
50
+ "reap": {
51
+ "autoUpdateMinVersion": "0.15.0"
50
52
  }
51
53
  }