{
 "model": "claude-haiku-5-5",
 "category": "background",
 "scenarios": [
  {
   "id": "d1-two-servers",
   "status": "pass",
   "product_defects": [],
   "task_outcome": "Both servers started on 8810 and 8811, and curl returned 200 from each. TaskStop stopped only the first (exit 143, curl exit 7 afterwards) while the second stayed up. TaskOutput reported stopped/143 and running. The saved record shows the second server stopped with the process (endedWithProcess).",
   "notes": "Exit code 0, turn-complete, driver.err empty. Tool pairs 8/8. Reported cost $0.00203518 matches the recompute from usageTotals. Cache read ratio 0.97. Leftovers empty, and I found nothing on these ports or matching the command when I checked. Request carries 31 tools with the Skill catalog, and no MCP, DSH or learned folders exist. The model added an odd aside that no port was computed; harmless."
  },
  {
   "id": "d2-bad-bg-command",
   "status": "pass",
   "product_defects": [],
   "task_outcome": "The missing command settled failed with exit 127 and its stderr. `sh -c` settled failed with exit 3 and both stdout and stderr. Tasks frames show failed with the right exit codes, the Bash calls settled failed, and TaskOutput repeats the same status and output. Nothing hung.",
   "notes": "Exit code 0, tool pairs 4/4, reported cost $0.00112384 matches the recompute, leftovers empty. The threefold exit code is known and reads fine. Model inaccuracy, not G-Code: it says the failure came back before the 1 s sleep finished, but the Bash result correctly waited about 1 s (frames 15 to 17)."
  },
  {
   "id": "d3-unicode-bg",
   "status": "pass",
   "product_defects": [],
   "task_outcome": "Six lines with Chinese, emoji and a ZWJ sequence are intact in Bash start output, tasks tails, TaskOutput, the saved session and the task record. U+FFFD count is zero in log.jsonl, the session and background-tasks.jsonl. outputBytes is 324, exactly 6 x 54. Task ended completed with exit 0.",
   "notes": "Raw ANSI escapes are kept unchanged in the frames and the wire; that is sane for a request for the exact text. Each stream has its own StringDecoder (backgroundShells.ts:324). This run wrote whole lines, so a character split across reads was not exercised live; that part rests on the code read. Output while running is visible in the Bash start result (lines 1-4) and in running tasks tails. The model batched both TaskOutput calls after the 2 s start look, and the first ran 140 ms after the 3.1 s task ended, so neither read happened while running. The model then called the start result its 'first read', and wrongly guessed that the tool strips ESC; the wire has \\u001b. No duplicate end notice was sent. Reported cost $0.00119978 matches the recompute."
  },
  {
   "id": "d4-watcher-left-running",
   "status": "pass",
   "product_defects": [],
   "task_outcome": "`node --watch` started and curl returned ok. After the FileEdit, the task tail shows 'Change detected' and 'Restarting', and curl returned updated. The watcher stayed running through the turn and ended with the process.",
   "notes": "Task record: stopped, endedWithProcess true. result.json leftovers are empty and port 8825 is free. The runner's ps check would not catch this command line because it holds no run path, so I checked separately: no `node --watch server.mjs` process remains. server.mjs holds the updated text. Reported cost $0.001624835 matches the recompute. Tool pairs 7/7."
  },
  {
   "id": "d5-max-bg",
   "status": "pass",
   "product_defects": [],
   "task_outcome": "Eight sleeps started. Call 9 failed with the clear error '8 background tasks are already running. Stop one with TaskStop first.' Call 10 settled refused with a 'Not run: this exact Bash call failed…' message. All eight stopped with exit 143, and the final TaskList shows backgroundShells all stopped.",
   "notes": "toolHistory confirms failed for call 9 and refused for call 10. Call 10's description differs from call 9's, but failureBudget deliberately ignores the Bash description label, so 'exact' is accurate. The result frame with no tool-use frame for call 10 is by design, and the saved pairs are 20/20. The summary's toolFailures of 2 counts success:false, including the refused call. Leftovers empty. No `sleep 300` found on my later check, but that check ran well after 300 s, so it proves nothing on its own; the stop evidence is exit 143 plus empty tasks state. Reported cost $0.00269567 matches the recompute."
  },
  {
   "id": "d6-interrupt-resume",
   "status": "pass",
   "product_defects": [],
   "task_outcome": "SIGINT arrived at the TaskStop call. The turn was saved as interrupted with paired results, and both exit codes are 0. The resumed session did not repeat npm init or the install, added /time, restarted the server, verified it and stopped it. I ran the app on scratch port 18835: /health and /time both returned correctly, and I stopped it.",
   "notes": "The error frame reads 'Stopped before this turn finished.' Interrupted TaskStop speaks once and settles cancelled. The unstarted FileRead settles cancelled with 'Not run'. The resume context says bg-a58c6885 was stopped with the process, and that record is marked reported. The old server was gone before resume: curl got no response, and the new server bound 8835. No 400 occurred. Saved pairs 14/14. Usage spans both processes (11 requests). Reported cost $0.00364455 matches the recompute. Leftovers empty. No tasks frame showing 'stopped' was emitted for the first task before that process exited, but the saved record is correct; desktop panel behaviour was not exercised here."
  },
  {
   "id": "d7-sigkill-orphan",
   "status": "pass",
   "product_defects": [],
   "task_outcome": "The server started and curl verified it. During the foreground `sleep 200` the CLI was killed with SIGKILL: killed true, exit 137, and the server was gone in 1064 ms, within the 5 s limit. Leftovers empty, and the driver exited early by design.",
   "notes": "The saved checkpoint has a synthetic 'No result was recorded' result plus an incomplete-turn note, and pairs are 3/3. toolHistory holds Bash as running, and store.ts:473 turns that into cancelled on load (code read only, no resume was run here). The task record stays running, which the design reads as 'the process died'. The leftover .lock names the dead pid; lock takeover was read in the code but not exercised here. The foreground sleep's process group has a watchdog in code (BashTool killOnExit plus group), but its end could not be confirmed after the fact. Reported cost $0.00080076 matches the recompute."
  }
 ]
}