{"record":{"id":"73e3889bd47646b7","repo":"Hmbown/CodeWhale","slug":"the-background-check-requires-the-installed-macos-app","errorCode":null,"errorMessage":"The background check requires the installed macOS app.","messagePattern":"The background check requires the installed macOS app\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/app/background-check.mjs","lineNumber":11,"sourceCode":"import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport crypto from \"node:crypto\";\nimport { spawn } from \"node:child_process\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { handle, closeSession } from \"../src/app-handler.mjs\";\n\n/** Uses the same daemon backend and cancellation path as connected hosts. */\nexport async function runBackgroundCheck({ bundle, demoDirectory } = {}) {\n  if (process.platform !== \"darwin\" || !bundle) throw new Error(\"The background check requires the installed macOS app.\");\n  const executable = path.join(bundle, \"Contents\", \"Resources\", \"Practice.app\", \"Contents\", \"MacOS\", \"practice\");\n  if (!fs.existsSync(executable)) throw new Error(\"Update the Computer Use app to run the background check.\");\n  const sessionId = `setup-${crypto.randomUUID()}`;\n  const controller = new AbortController();\n  const timer = setTimeout(() => controller.abort(), 15_000);\n  const child = spawn(executable, [], { stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n  const scratch = fs.mkdtempSync(path.join(os.tmpdir(), \"cu-setup-capture-\"));\n  let ready = false, applied = null, latest = null, buffer = \"\", spawnError = null;\n  child.on(\"error\", error => { spawnError = error; });\n  child.stderr.on(\"data\", () => {});\n  child.stdout.setEncoding(\"utf8\");\n  child.stdout.on(\"data\", chunk => {\n    buffer += chunk;\n    if (buffer.length > 16_384) { controller.abort(); return; }\n    let newline;\n    while ((newline = buffer.indexOf(\"\\n\")) >= 0) {\n      const line = buffer.slice(0, newline); buffer = buffer.slice(newline + 1);\n      try { const result = JSON.parse(line); latest = result; if (result.event === \"ready\") ready = true; if (result.event === \"applied\") applied = result; } catch { /* Cocoa diagnostics are not receipts. */ }","sourceCodeStart":1,"sourceCodeEnd":29,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/app/background-check.mjs#L1-L29","documentation":"runBackgroundCheck in the computer-use plugin's background-check.mjs refuses to run unless the host is macOS and a bundle path for the installed Computer Use app was supplied. The check drives a practice app inside the installed .app bundle, so without it there is nothing to launch. This is a precondition guard at the top of the function, raised before any process is spawned.","triggerScenarios":"Calling runBackgroundCheck() when process.platform !== 'darwin', or calling it on macOS without passing { bundle } (or passing bundle: null/undefined).","commonSituations":"Running the check on Linux/CI (non-macOS), invoking it from a dev environment where the app was never installed, or a caller that forgot to resolve and pass the installed app's bundle path.","solutions":["Install the Computer Use macOS app and pass its bundle path: runBackgroundCheck({ bundle: '/Applications/Computer Use.app' }).","On non-macOS hosts, skip the background check or route it to a macOS machine; the check cannot run there.","Resolve the bundle programmatically (e.g. via mdfind or a known install path) instead of hardcoding, so updates to the install location do not break the call."],"exampleFix":"// before\nawait runBackgroundCheck(); // fails: no bundle, maybe not macOS\n\n// after\nif (process.platform !== \"darwin\") throw new Error(\"Background check needs macOS.\");\nawait runBackgroundCheck({ bundle: \"/Applications/Computer Use.app\" });","handlingStrategy":"validation","validationCode":"if (process.platform !== \"darwin\") throw new Error(\"Background check needs macOS.\");\nif (!bundle) throw new Error(\"Pass the installed Computer Use app bundle path.\");","typeGuard":"function canRunBackgroundCheck(opts) {\n  return process.platform === \"darwin\" && typeof opts?.bundle === \"string\" && opts.bundle.length > 0;\n}","tryCatchPattern":"try {\n  await runBackgroundCheck({ bundle });\n} catch (e) {\n  if (String(e.message).includes(\"requires the installed macOS app\")) {\n    throw new Error(\"Run this on macOS with the Computer Use app installed and pass { bundle }.\");\n  }\n  throw e;\n}","preventionTips":["Gate the check behind process.platform === 'darwin' in your setup code.","Resolve and pass the bundle path in one shared setup helper, never inline ad hoc.","Document the macOS + installed-app prerequisite wherever the check is invoked."],"tags":["macos","precondition","computer-use","setup"],"backgroundTag":"missing-dependency","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}