{"record":{"id":"17367d2de26d9cac","repo":"stablyai/orca","slug":"need-2-terminals-got-opentargets-length-no","errorCode":null,"errorMessage":"Need ≥2 terminals; got ${openTargets.length}. ${notes.join('; ')}","messagePattern":"Need ≥2 terminals; got (.+?)\\. (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"config/scripts/live-remote-realistic-freeze-repro.mjs","lineNumber":229,"sourceCode":"    )\n    phases.push({ phase: 'seed-flood', created: created.length })\n  }\n\n  // Prefer created floods for open pass; fill with existing live terminals.\n  let live = []\n  try {\n    live = listLiveTerminalHandles()\n    notes.push(`live terminals listed=${live.length}`)\n  } catch (error) {\n    notes.push(`terminal list failed: ${String(error).slice(0, 200)}`)\n  }\n\n  const openTargets = [...created.map((c) => c.handle), ...live.map((t) => t.handle)].filter(\n    (v, i, a) => typeof v === 'string' && a.indexOf(v) === i\n  )\n\n  if (openTargets.length < 2) {\n    throw new Error(`Need ≥2 terminals; got ${openTargets.length}. ${notes.join('; ')}`)\n  }\n\n  const openList = openTargets.slice(0, Math.min(openCount, openTargets.length))\n\n  // --- Phase: park — leave one session focused, rest accumulate flood while \"away\" ---\n  try {\n    const parkHandle = openList[0]\n    const parked = await orcaJsonAsync(['terminal', 'switch', '--terminal', parkHandle], {\n      timeoutMs: 60_000\n    })\n    notes.push(`park switch ms=${parked.elapsedMs.toFixed(0)} handle=${parkHandle}`)\n  } catch (error) {\n    notes.push(`park switch failed: ${String(error).slice(0, 200)}`)\n  }\n\n  console.log(`[realistic-freeze] idle ${idleMs}ms while remotes stream (user away / asleep)`)\n  const idleStarted = performance.now()\n  await sleep(idleMs)","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/live-remote-realistic-freeze-repro.mjs#L211-L247","documentation":"Realistic-freeze repro requires at least two distinct terminal handles for its open/switch exercise. It unions created terminal handles with live ones, dedupes, then asserts length >= 2. Below that, the open/park/switch phases cannot meaningfully run.","triggerScenarios":"createCount is 0 or all creates failed and the live list returned < 2 handles; or the live-list call itself failed (caught and pushed to notes) leaving only the created set.","commonSituations":"Idle remote with a single terminal, terminal creation failing under load, a live-list field-name mismatch filtering all handles out, or running the open phase before any terminals exist.","solutions":["Set createCount >= 2 (or pre-open terminals) so the union yields at least two handles.","Inspect the notes joined into the message — it records 'terminal list failed' and list counts that show whether list or create is the loss.","Verify listLiveTerminalHandles reads the correct handle field for the remote orca version."],"exampleFix":"// before\nif (openTargets.length < 2) {\n  throw new Error(`Need >=2 terminals; got ${openTargets.length}. ${notes.join('; ')}`)\n}\n\n// after\nif (openTargets.length < 2) {\n  throw new Error(`Need >=2 terminals; got ${openTargets.length}. created=${created.length} live=${live.length}. ${notes.join('; ')}`)\n}","handlingStrategy":"validation","validationCode":"if (createCount + live.length < 2) {\n  throw new Error(`Need >=2 terminals; create=${createCount} live=${live.length}`)\n}","typeGuard":"const hasMinHandles = (arr, n = 2) => Array.isArray(arr) && arr.filter(h => typeof h === 'string').length >= n","tryCatchPattern":null,"preventionTips":["Compute the union size before the open phase.","Push created/live counts into notes for diagnosability.","Confirm the live-list field name matches the remote orca version."],"tags":["terminal","validation","freeze-repro"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}