opencode-immune 1.0.77 → 1.0.78

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.
@@ -3777,7 +3777,7 @@ import { fileURLToPath } from "url";
3777
3777
  import { createHash } from "crypto";
3778
3778
  import { tmpdir } from "os";
3779
3779
  import { execFile } from "child_process";
3780
- var PLUGIN_VERSION = "1.0.77";
3780
+ var PLUGIN_VERSION = "1.0.78";
3781
3781
  var PLUGIN_PACKAGE_NAME = "opencode-immune";
3782
3782
  var PLUGIN_DIRNAME = dirname(fileURLToPath(import.meta.url));
3783
3783
  function getServerAuthHeaders() {
@@ -3895,8 +3895,6 @@ var PROVIDER_RETRY_WATCHDOG_MS = 3e4;
3895
3895
  var RETRY_PROMPT_DELIVERY_ATTEMPTS = 3;
3896
3896
  var CHILD_FALLBACK_REQUEST_TTL_MS = 10 * 60 * 1e3;
3897
3897
  var AUTO_CYCLE_LOCK_TTL_MS = 30 * 60 * 1e3;
3898
- var PROJECT_TMP_RELATIVE_PATH = ".opencode/tmp";
3899
- var PROJECT_LOG_RELATIVE_PATH = ".opencode/state/logs";
3900
3898
  var MODEL_NAME_CAPABILITY_SCORE = {
3901
3899
  "claude-opus-4-7": 100,
3902
3900
  "gpt-5.5": 100,
@@ -3916,12 +3914,6 @@ function isManagedRootUltraworkSession(state, sessionID) {
3916
3914
  const record = getManagedSession(state, sessionID);
3917
3915
  return !!record && record.kind === "root";
3918
3916
  }
3919
- function getProjectTmpDir(state) {
3920
- return join(state.input.directory, PROJECT_TMP_RELATIVE_PATH);
3921
- }
3922
- function getProjectLogDir(state) {
3923
- return join(state.input.directory, PROJECT_LOG_RELATIVE_PATH);
3924
- }
3925
3917
  async function createManagedUltraworkSession(state, title) {
3926
3918
  const result = await state.client.session.create({
3927
3919
  directory: state.input.directory,
@@ -5798,6 +5790,18 @@ var PRE_COMMIT_MARKER = "0-ULTRAWORK: PRE_COMMIT";
5798
5790
  var CYCLE_COMPLETE_MARKER = "0-ULTRAWORK: CYCLE_COMPLETE";
5799
5791
  var NEXT_TASK_PATTERN = /Next task:\s*(.+)/;
5800
5792
  var ALL_CYCLES_COMPLETE_MARKER = "0-ULTRAWORK: ALL_CYCLES_COMPLETE";
5793
+ async function commitCycleChanges(state, reason) {
5794
+ if (state.commitPending) return;
5795
+ state.commitPending = true;
5796
+ pluginLog.info(`[opencode-immune] Multi-Cycle: ${reason}, running git commit...`);
5797
+ try {
5798
+ await runGitCommit(state.input.directory);
5799
+ } catch (err) {
5800
+ pluginLog.error(`[opencode-immune] Multi-Cycle: git commit failed (${reason}):`, err);
5801
+ } finally {
5802
+ state.commitPending = false;
5803
+ }
5804
+ }
5801
5805
  async function archiveProgress(directory) {
5802
5806
  const progressPath = join(directory, "memory-bank", "progress.md");
5803
5807
  try {
@@ -5905,17 +5909,7 @@ function createTextCompleteHandler(state) {
5905
5909
  return;
5906
5910
  }
5907
5911
  if (text.includes(PRE_COMMIT_MARKER) && !text.includes(CYCLE_COMPLETE_MARKER)) {
5908
- if (!state.commitPending) {
5909
- state.commitPending = true;
5910
- pluginLog.info("[opencode-immune] Multi-Cycle: PRE_COMMIT detected (standalone), running git commit...");
5911
- try {
5912
- await runGitCommit(state.input.directory);
5913
- } catch (err) {
5914
- pluginLog.error("[opencode-immune] Multi-Cycle: git commit failed (standalone):", err);
5915
- } finally {
5916
- state.commitPending = false;
5917
- }
5918
- }
5912
+ await commitCycleChanges(state, "PRE_COMMIT detected (standalone)");
5919
5913
  return;
5920
5914
  }
5921
5915
  if (text.includes(CYCLE_COMPLETE_MARKER)) {
@@ -5924,18 +5918,7 @@ function createTextCompleteHandler(state) {
5924
5918
  } catch (err) {
5925
5919
  pluginLog.warn("[opencode-immune] Multi-Cycle: archive progress failed:", err);
5926
5920
  }
5927
- if (!state.commitPending) {
5928
- state.commitPending = true;
5929
- pluginLog.info("[opencode-immune] Multi-Cycle: CYCLE_COMPLETE detected, running git commit first...");
5930
- try {
5931
- await runGitCommit(state.input.directory);
5932
- pluginLog.info("[opencode-immune] Multi-Cycle: git commit completed before new cycle.");
5933
- } catch (err) {
5934
- pluginLog.error("[opencode-immune] Multi-Cycle: git commit failed (continuing anyway):", err);
5935
- } finally {
5936
- state.commitPending = false;
5937
- }
5938
- }
5921
+ await commitCycleChanges(state, "CYCLE_COMPLETE detected");
5939
5922
  state.cycleCount++;
5940
5923
  if (state.cycleCount >= MAX_CYCLES) {
5941
5924
  pluginLog.info(
@@ -5982,6 +5965,7 @@ function createTextCompleteHandler(state) {
5982
5965
  `[opencode-immune] Multi-Cycle fallback: no CYCLE_COMPLETE marker detected for ${sessionID}, but tasks.md has no active task and backlog has pending items. Starting AUTO-CYCLE.`
5983
5966
  );
5984
5967
  try {
5968
+ await commitCycleChanges(state, "fallback AUTO-CYCLE before new session");
5985
5969
  await refreshAutoCycleLock(state, sessionID);
5986
5970
  await startAutoCycleInNewSession(
5987
5971
  state,
@@ -6049,25 +6033,11 @@ function createPermissionAskHandler(state) {
6049
6033
  `[opencode-immune] Permission request recovered AUTO-RESUME session ${sessionID}; tracking as managed ultrawork session.`
6050
6034
  );
6051
6035
  }
6052
- const permissionType = getPermissionType(input);
6053
- const patterns = getPermissionPatterns(input);
6054
- if (isManagedUltraworkSession(state, sessionID) && permissionType === "external_directory" && patterns.some(isExternalTmpPattern)) {
6055
- output.status = "deny";
6056
- await writeDiagnosticLog(state, "permission:auto-deny-external-tmp", {
6057
- sessionID,
6058
- status: output.status,
6059
- permission: permissionType,
6060
- patterns,
6061
- projectTmpDir: getProjectTmpDir(state),
6062
- projectLogDir: getProjectLogDir(state)
6063
- });
6064
- return;
6065
- }
6066
6036
  await writeDiagnosticLog(state, "permission:ask", {
6067
6037
  sessionID,
6068
6038
  status: output.status,
6069
- permission: permissionType,
6070
- patterns
6039
+ permission: getPermissionType(input),
6040
+ patterns: getPermissionPatterns(input)
6071
6041
  });
6072
6042
  };
6073
6043
  }
@@ -6083,22 +6053,6 @@ function getPermissionPatterns(input) {
6083
6053
  if (Array.isArray(source)) return source.filter((item) => typeof item === "string");
6084
6054
  return typeof source === "string" ? [source] : [];
6085
6055
  }
6086
- function isExternalTmpPattern(pattern) {
6087
- return pattern === "/tmp" || pattern.startsWith("/tmp/") || pattern === "/tmp/*";
6088
- }
6089
- function createShellEnvHandler(state) {
6090
- return async (_input, output) => {
6091
- const projectTmpDir = getProjectTmpDir(state);
6092
- const projectLogDir = getProjectLogDir(state);
6093
- await mkdir(projectTmpDir, { recursive: true });
6094
- await mkdir(projectLogDir, { recursive: true });
6095
- output.env.TMPDIR = projectTmpDir;
6096
- output.env.TMP = projectTmpDir;
6097
- output.env.TEMP = projectTmpDir;
6098
- output.env.OPENCODE_TMP_DIR = projectTmpDir;
6099
- output.env.OPENCODE_LOG_DIR = projectLogDir;
6100
- };
6101
- }
6102
6056
  async function server(input) {
6103
6057
  const state = createState(input);
6104
6058
  checkPluginUpdate(state).catch(() => {
@@ -6238,11 +6192,6 @@ async function server(input) {
6238
6192
  state,
6239
6193
  "permission.ask",
6240
6194
  createPermissionAskHandler(state)
6241
- ),
6242
- "shell.env": withErrorBoundary(
6243
- state,
6244
- "shell.env",
6245
- createShellEnvHandler(state)
6246
6195
  )
6247
6196
  };
6248
6197
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-immune",
3
- "version": "1.0.77",
3
+ "version": "1.0.78",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin: session recovery, auto-retry, multi-cycle automation, context monitoring",
6
6
  "exports": {