opencode-immune 1.0.31 → 1.0.33

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.
Files changed (2) hide show
  1. package/dist/plugin.js +66 -87
  2. package/package.json +1 -1
package/dist/plugin.js CHANGED
@@ -1284,92 +1284,72 @@ const PRE_COMMIT_MARKER = "0-ULTRAWORK: PRE_COMMIT";
1284
1284
  const CYCLE_COMPLETE_MARKER = "0-ULTRAWORK: CYCLE_COMPLETE";
1285
1285
  const NEXT_TASK_PATTERN = /Next task:\s*(.+)/;
1286
1286
  const ALL_CYCLES_COMPLETE_MARKER = "0-ULTRAWORK: ALL_CYCLES_COMPLETE";
1287
- // Default commit prompt — used when user's /commit command file is not found
1288
- const DEFAULT_COMMIT_PROMPT = `Review the staged changes using \`git diff --cached\` and create a commit.
1289
-
1290
- If there are no staged changes, check \`git status\` for unstaged changes and stage the relevant files first.
1291
-
1292
- The commit message MUST follow this structure:
1293
- 1. First line: short description (<50 chars) prefixed with feat:/fix:/refactor:
1294
- 2. Second line: empty
1295
- 3. Body: concise bullet points describing significant changes
1296
-
1297
- Create the commit using \`git commit -m\` with the properly formatted message.`;
1298
1287
  /**
1299
- * Load the /commit command prompt from user's global config.
1300
- * Falls back to DEFAULT_COMMIT_PROMPT if file doesn't exist.
1288
+ * Archive memory-bank/progress.md before a new cycle starts.
1289
+ * Moves to memory-bank/archive/progress-YYYY-MM-DD-{timestamp}.md.
1290
+ * Skips silently if progress.md doesn't exist or is trivially empty.
1301
1291
  */
1302
- async function loadCommitPrompt() {
1292
+ async function archiveProgress(directory) {
1293
+ const progressPath = (0, path_1.join)(directory, "memory-bank", "progress.md");
1303
1294
  try {
1304
- const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
1305
- const commandPath = (0, path_1.join)(home, ".config", "opencode", "commands", "commit.md");
1306
- const content = await (0, promises_1.readFile)(commandPath, "utf-8");
1307
- // Strip YAML frontmatter (--- ... ---)
1308
- const stripped = content.replace(/^---[\s\S]*?---\s*/, "").trim();
1309
- return stripped || DEFAULT_COMMIT_PROMPT;
1310
- }
1311
- catch {
1312
- return DEFAULT_COMMIT_PROMPT;
1313
- }
1314
- }
1315
- /**
1316
- * Execute a commit by sending the /commit prompt to the current session.
1317
- * The agent will analyze the diff and create a proper commit message.
1318
- * Returns true if the prompt was sent successfully.
1319
- */
1320
- async function runSmartCommit(state, sessionID) {
1321
- try {
1322
- const commitPrompt = await loadCommitPrompt();
1323
- console.log(`[opencode-immune] Smart commit: sending commit prompt to session ${sessionID}...`);
1324
- // Send commit prompt to the SAME session (ultrawork already finished, session is free)
1325
- await state.input.client.session.prompt({
1326
- body: {
1327
- parts: [
1328
- {
1329
- type: "text",
1330
- text: commitPrompt,
1331
- },
1332
- ],
1333
- },
1334
- path: { id: sessionID },
1335
- });
1336
- console.log("[opencode-immune] Smart commit: completed.");
1337
- return true;
1295
+ const content = await (0, promises_1.readFile)(progressPath, "utf-8");
1296
+ // Skip if empty or trivially empty
1297
+ if (!content.trim() || content.trim() === "# Progress") {
1298
+ console.log("[opencode-immune] Archive progress: nothing to archive (empty).");
1299
+ return;
1300
+ }
1301
+ const archiveDir = (0, path_1.join)(directory, "memory-bank", "archive");
1302
+ await (0, promises_1.mkdir)(archiveDir, { recursive: true });
1303
+ const now = new Date();
1304
+ const dateStr = now.toISOString().slice(0, 10); // YYYY-MM-DD
1305
+ const ts = Math.floor(now.getTime() / 1000);
1306
+ const archiveName = `progress-${dateStr}-${ts}.md`;
1307
+ const archivePath = (0, path_1.join)(archiveDir, archiveName);
1308
+ await (0, promises_1.rename)(progressPath, archivePath);
1309
+ console.log(`[opencode-immune] Archive progress: moved to ${archiveName}`);
1338
1310
  }
1339
1311
  catch (err) {
1340
- console.error("[opencode-immune] Smart commit failed:", err);
1341
- return false;
1312
+ // File doesn't exist or move failed — not critical
1313
+ const msg = err instanceof Error ? err.message : String(err);
1314
+ if (!msg.includes("ENOENT")) {
1315
+ console.warn("[opencode-immune] Archive progress failed:", msg);
1316
+ }
1342
1317
  }
1343
1318
  }
1344
1319
  /**
1345
- * Helper: run git commit in the project directory (fallback).
1346
- * Uses execFile for safety (no shell injection).
1347
- * Returns true if commit succeeded, false otherwise.
1320
+ * Helper: run git add + diff-stat + commit with descriptive message.
1321
+ * Builds commit body from `git diff --cached --stat` so the commit
1322
+ * is not an opaque "auto-commit" but shows what changed.
1323
+ * Returns true if commit succeeded (or nothing to commit), false on error.
1348
1324
  */
1349
- function runGitCommit(directory, message) {
1325
+ function runGitCommit(directory) {
1350
1326
  return new Promise((resolve) => {
1351
- // Stage all changes first
1327
+ // Stage all changes
1352
1328
  (0, child_process_1.execFile)("git", ["add", "-A"], { cwd: directory }, (addErr) => {
1353
1329
  if (addErr) {
1354
1330
  console.error("[opencode-immune] git add failed:", addErr.message);
1355
1331
  resolve(false);
1356
1332
  return;
1357
1333
  }
1358
- // Then commit
1359
- (0, child_process_1.execFile)("git", ["commit", "-m", message], { cwd: directory }, (commitErr, stdout, stderr) => {
1360
- if (commitErr) {
1361
- // "nothing to commit" is not a real error
1362
- if (stderr?.includes("nothing to commit") || stdout?.includes("nothing to commit")) {
1363
- console.log("[opencode-immune] git commit: nothing to commit (clean tree).");
1364
- resolve(true);
1334
+ // Get diff stat for commit body
1335
+ (0, child_process_1.execFile)("git", ["diff", "--cached", "--stat"], { cwd: directory }, (_diffErr, diffOut) => {
1336
+ const stat = (diffOut ?? "").trim();
1337
+ const body = stat ? `\n\n${stat}` : "";
1338
+ const message = `chore: ultrawork cycle auto-commit${body}`;
1339
+ (0, child_process_1.execFile)("git", ["commit", "-m", message], { cwd: directory }, (commitErr, stdout, stderr) => {
1340
+ if (commitErr) {
1341
+ if (stderr?.includes("nothing to commit") || stdout?.includes("nothing to commit")) {
1342
+ console.log("[opencode-immune] git commit: nothing to commit (clean tree).");
1343
+ resolve(true);
1344
+ return;
1345
+ }
1346
+ console.error("[opencode-immune] git commit failed:", commitErr.message, stderr);
1347
+ resolve(false);
1365
1348
  return;
1366
1349
  }
1367
- console.error("[opencode-immune] git commit failed:", commitErr.message, stderr);
1368
- resolve(false);
1369
- return;
1370
- }
1371
- console.log("[opencode-immune] git commit succeeded:", stdout?.trim());
1372
- resolve(true);
1350
+ console.log("[opencode-immune] git commit succeeded:", stdout?.trim());
1351
+ resolve(true);
1352
+ });
1373
1353
  });
1374
1354
  });
1375
1355
  });
@@ -1398,18 +1378,14 @@ function createTextCompleteHandler(state) {
1398
1378
  }
1399
1379
  // ── PRE_COMMIT only (without CYCLE_COMPLETE in same part): run commit ──
1400
1380
  if (text.includes(PRE_COMMIT_MARKER) && !text.includes(CYCLE_COMPLETE_MARKER)) {
1401
- if (!state.commitPending && sessionID) {
1381
+ if (!state.commitPending) {
1402
1382
  state.commitPending = true;
1403
- console.log("[opencode-immune] Multi-Cycle: PRE_COMMIT detected (standalone), running smart commit...");
1383
+ console.log("[opencode-immune] Multi-Cycle: PRE_COMMIT detected (standalone), running git commit...");
1404
1384
  try {
1405
- const ok = await runSmartCommit(state, sessionID);
1406
- if (!ok) {
1407
- console.log("[opencode-immune] Multi-Cycle: smart commit failed, falling back to git commit...");
1408
- await runGitCommit(state.input.directory, "chore: ultrawork cycle auto-commit");
1409
- }
1385
+ await runGitCommit(state.input.directory);
1410
1386
  }
1411
1387
  catch (err) {
1412
- console.error("[opencode-immune] Multi-Cycle: commit failed (standalone):", err);
1388
+ console.error("[opencode-immune] Multi-Cycle: git commit failed (standalone):", err);
1413
1389
  }
1414
1390
  finally {
1415
1391
  state.commitPending = false;
@@ -1417,22 +1393,25 @@ function createTextCompleteHandler(state) {
1417
1393
  }
1418
1394
  return;
1419
1395
  }
1420
- // ── CYCLE_COMPLETE: self-contained sequence: commit → new session ──
1396
+ // ── CYCLE_COMPLETE: self-contained sequence: archive progress → commit → new session ──
1421
1397
  if (text.includes(CYCLE_COMPLETE_MARKER)) {
1422
- // Step 1: Always commit first in the current session
1423
- if (!state.commitPending && sessionID) {
1398
+ // Step 0: Archive progress.md before new cycle
1399
+ try {
1400
+ await archiveProgress(state.input.directory);
1401
+ }
1402
+ catch (err) {
1403
+ console.warn("[opencode-immune] Multi-Cycle: archive progress failed:", err);
1404
+ }
1405
+ // Step 1: Always commit first
1406
+ if (!state.commitPending) {
1424
1407
  state.commitPending = true;
1425
- console.log("[opencode-immune] Multi-Cycle: CYCLE_COMPLETE detected, running smart commit first...");
1408
+ console.log("[opencode-immune] Multi-Cycle: CYCLE_COMPLETE detected, running git commit first...");
1426
1409
  try {
1427
- const ok = await runSmartCommit(state, sessionID);
1428
- if (!ok) {
1429
- console.log("[opencode-immune] Multi-Cycle: smart commit failed, falling back to git commit...");
1430
- await runGitCommit(state.input.directory, "chore: ultrawork cycle auto-commit");
1431
- }
1432
- console.log("[opencode-immune] Multi-Cycle: commit completed before new cycle.");
1410
+ await runGitCommit(state.input.directory);
1411
+ console.log("[opencode-immune] Multi-Cycle: git commit completed before new cycle.");
1433
1412
  }
1434
1413
  catch (err) {
1435
- console.error("[opencode-immune] Multi-Cycle: commit failed (continuing anyway):", err);
1414
+ console.error("[opencode-immune] Multi-Cycle: git commit failed (continuing anyway):", err);
1436
1415
  }
1437
1416
  finally {
1438
1417
  state.commitPending = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-immune",
3
- "version": "1.0.31",
3
+ "version": "1.0.33",
4
4
  "description": "OpenCode plugin: session recovery, auto-retry, multi-cycle automation, context monitoring",
5
5
  "exports": {
6
6
  "./server": "./dist/plugin.js"