opencode-immune 1.0.9 → 1.0.11

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 +28 -3
  2. package/package.json +1 -1
package/dist/plugin.js CHANGED
@@ -699,15 +699,29 @@ function createKeywordDetectorChatMessage(_state) {
699
699
  // ═══════════════════════════════════════════════════════════════════════════════
700
700
  /**
701
701
  * chat.params: observational logging of model and agent info.
702
- * NOTE: chat.params output does NOT expose the `model` field.
703
- * Primary model routing is handled by BUILD router + alias agents.
704
- * This hook only provides observability.
702
+ * Also handles session registration and auto-resume for existing sessions
703
+ * after server restart (when session.created doesn't fire).
705
704
  */
706
705
  function createFallbackModels(state) {
707
706
  return async (input, _output) => {
708
707
  if (input.agent === ULTRAWORK_AGENT) {
708
+ const wasAlreadyManaged = isManagedUltraworkSession(state, input.sessionID);
709
709
  await addManagedUltraworkSession(state, input.sessionID);
710
710
  await writeUltraworkMarker(state);
711
+ // First contact with 0-ultrawork after plugin restart:
712
+ // if marker is active and tasks.md has incomplete work, populate recoveryContext
713
+ // so that system.transform injects recovery info into the conversation.
714
+ if (!wasAlreadyManaged && !state.recoveryContext) {
715
+ const markerActive = await isUltraworkMarkerActive(state);
716
+ if (markerActive) {
717
+ const recovery = await parseTasksFile(state.input.directory);
718
+ if (recovery && recovery.phase !== "ARCHIVE: DONE") {
719
+ state.recoveryContext = recovery;
720
+ console.log(`[opencode-immune] Auto-recovery on existing session: ` +
721
+ `task="${recovery.task}", level=${recovery.level}, phase=${recovery.phase}`);
722
+ }
723
+ }
724
+ }
711
725
  }
712
726
  else if (getManagedSession(state, input.sessionID)?.kind === "root") {
713
727
  await removeManagedUltraworkSession(state, input.sessionID, `session switched to agent \"${input.agent}\"`);
@@ -946,6 +960,17 @@ function createMultiCycleHandler(state) {
946
960
  // ═══════════════════════════════════════════════════════════════════════════════
947
961
  async function server(input) {
948
962
  const state = createState(input);
963
+ // Eagerly load recovery context at plugin init so it's available
964
+ // for the very first system.transform call (before chat.params fires).
965
+ const markerActive = await isUltraworkMarkerActive(state);
966
+ if (markerActive) {
967
+ const recovery = await parseTasksFile(state.input.directory);
968
+ if (recovery && recovery.phase !== "ARCHIVE: DONE") {
969
+ state.recoveryContext = recovery;
970
+ console.log(`[opencode-immune] Plugin init: ultrawork marker active, recovery context loaded: ` +
971
+ `task="${recovery.task}", level=${recovery.level}, phase=${recovery.phase}`);
972
+ }
973
+ }
949
974
  console.log(`[opencode-immune] Plugin initialized. Directory: ${input.directory}`);
950
975
  // Compose tool.execute.after handlers:
951
976
  // Todo Enforcer (counter) + Ralph Loop (edit error) + Comment Checker
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-immune",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "description": "OpenCode plugin: session recovery, auto-retry, multi-cycle automation, context monitoring",
5
5
  "exports": {
6
6
  "./server": "./dist/plugin.js"