@a5c-ai/babysitter-opencode 0.1.3 → 0.1.4-staging.06f78f92

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.
package/README.md CHANGED
@@ -25,6 +25,9 @@ plugins/babysitter-opencode/
25
25
  tool-execute-after.js Post-tool-use hook
26
26
  skills/
27
27
  babysit/SKILL.md Core orchestration skill
28
+ accomplish-status/SKILL.md Run status reporting for Accomplish
29
+ accomplish-skills/
30
+ babysitter/SKILL.md Bundled skill in Accomplish format
28
31
  plugin.json Plugin manifest
29
32
  versions.json SDK version tracking
30
33
  ```
@@ -36,7 +39,7 @@ plugins/babysitter-opencode/
36
39
  Install the Babysitter SDK CLI:
37
40
 
38
41
  ```bash
39
- npm install -g @a5c-ai/babysitter
42
+ npm install -g @a5c-ai/babysitter-sdk
40
43
  ```
41
44
 
42
45
  ### Method 1: npm global install (recommended)
@@ -54,10 +57,10 @@ To install into a specific workspace:
54
57
  babysitter-opencode install --workspace /path/to/project
55
58
  ```
56
59
 
57
- ### Method 2: Babysitter plugin manager
60
+ ### Method 2: Babysitter harness install
58
61
 
59
62
  ```bash
60
- babysitter plugin:install babysitter-opencode
63
+ babysitter harness:install-plugin opencode
61
64
  ```
62
65
 
63
66
  ### Method 3: Manual copy
@@ -83,11 +86,34 @@ Or from a specific workspace:
83
86
  babysitter-opencode uninstall --workspace /path/to/project
84
87
  ```
85
88
 
89
+ ### Method 4: Accomplish AI (auto-detected)
90
+
91
+ When [Accomplish](https://github.com/accomplish-ai/accomplish) is installed,
92
+ the installer automatically detects it and copies the plugin into Accomplish's
93
+ OpenCode config directory (`<userDataPath>/opencode/plugins/babysitter/`).
94
+
95
+ ```bash
96
+ # Auto-detects Accomplish during standard install
97
+ npm install -g @a5c-ai/babysitter-opencode
98
+
99
+ # Or target Accomplish explicitly
100
+ babysitter-opencode install --accomplish
101
+
102
+ # Install to both standalone OpenCode and Accomplish
103
+ babysitter-opencode install --global --accomplish
104
+ ```
105
+
106
+ Accomplish stores OpenCode config at platform-specific locations:
107
+ - **macOS**: `~/Library/Application Support/Accomplish/opencode/`
108
+ - **Windows**: `%APPDATA%/Accomplish/opencode/`
109
+ - **Linux**: `~/.config/Accomplish/opencode/`
110
+
86
111
  ## CLI Reference
87
112
 
88
113
  ```
89
114
  babysitter-opencode install [--global] Install plugin globally
90
115
  babysitter-opencode install --workspace [path] Install into workspace
116
+ babysitter-opencode install --accomplish Install into Accomplish data dir
91
117
  babysitter-opencode uninstall [--global] Uninstall plugin globally
92
118
  babysitter-opencode uninstall --workspace [path] Uninstall from workspace
93
119
  babysitter-opencode sync Sync command surfaces
@@ -127,6 +153,24 @@ natively provide them:
127
153
  - `BABYSITTER_RUNS_DIR` -- Runs directory path
128
154
  - `OPENCODE_PLUGIN_ROOT` -- Plugin root directory
129
155
 
156
+ ### Accomplish Integration
157
+
158
+ When running inside [Accomplish](https://github.com/accomplish-ai/accomplish), OpenCode is spawned as a subprocess with
159
+ additional environment variables. The babysitter adapter detects these
160
+ automatically:
161
+
162
+ - `ACCOMPLISH_TASK_ID` -- Accomplish task identifier (primary correlation key)
163
+ - `OPENCODE_CONFIG_DIR` -- Path to Accomplish's OpenCode config directory
164
+ - `OPENCODE_CONFIG` -- Path to the generated `opencode.json`
165
+
166
+ The adapter writes `accomplishTaskId` into session state metadata for
167
+ correlation. The `accomplish-status` skill writes run status JSON to
168
+ `<OPENCODE_CONFIG_DIR>/run-status/<runId>.json` for file-based IPC.
169
+
170
+ Breakpoints are resolved conversationally: when a breakpoint is pending, the
171
+ agent uses Accomplish's `ask-user-question` MCP tool to prompt the user, then
172
+ posts the result via `babysitter task:post`.
173
+
130
174
  ### Configuration Environment Variables
131
175
 
132
176
  | Variable | Default | Description |
@@ -137,6 +181,8 @@ natively provide them:
137
181
  | `BABYSITTER_OPENCODE_MARKETPLACE_PATH` | `~/.agents/plugins/marketplace.json` | Marketplace file |
138
182
  | `BABYSITTER_SDK_CLI` | (auto-detected) | Path to SDK CLI entry |
139
183
  | `BABYSITTER_GLOBAL_STATE_DIR` | `~/.a5c` | Global state directory |
184
+ | `ACCOMPLISH_TASK_ID` | -- | Set by Accomplish when spawning OpenCode |
185
+ | `OPENCODE_CONFIG_DIR` | -- | Accomplish's OpenCode config directory |
140
186
 
141
187
  ## Verification
142
188
 
@@ -367,6 +367,76 @@ function ensureGlobalProcessLibrary(packageRoot) {
367
367
  );
368
368
  }
369
369
 
370
+ // ---------------------------------------------------------------------------
371
+ // Accomplish AI detection and paths
372
+ // ---------------------------------------------------------------------------
373
+
374
+ /**
375
+ * Returns the Accomplish user data directory for the current platform.
376
+ * If OPENCODE_CONFIG_DIR is set, returns its parent (the Accomplish data dir).
377
+ * Otherwise falls back to platform-specific defaults.
378
+ */
379
+ function getAccomplishDataDir() {
380
+ if (process.env.OPENCODE_CONFIG_DIR) {
381
+ return path.resolve(process.env.OPENCODE_CONFIG_DIR, '..');
382
+ }
383
+ const home = getUserHome();
384
+ switch (process.platform) {
385
+ case 'darwin':
386
+ return path.join(home, 'Library', 'Application Support', 'Accomplish');
387
+ case 'win32': {
388
+ const appData = process.env.APPDATA || process.env.LOCALAPPDATA;
389
+ return appData
390
+ ? path.join(appData, 'Accomplish')
391
+ : path.join(home, 'AppData', 'Roaming', 'Accomplish');
392
+ }
393
+ default:
394
+ return path.join(home, '.config', 'Accomplish');
395
+ }
396
+ }
397
+
398
+ /**
399
+ * Returns true if Accomplish AI appears to be installed or is running.
400
+ * Checks for:
401
+ * - ACCOMPLISH_TASK_ID env var (running inside Accomplish)
402
+ * - Accomplish data dir with an opencode/ subdirectory on disk
403
+ */
404
+ function isAccomplishInstalled() {
405
+ if (process.env.ACCOMPLISH_TASK_ID) return true;
406
+ try {
407
+ const dataDir = getAccomplishDataDir();
408
+ const openCodeDir = path.join(dataDir, 'opencode');
409
+ return fs.existsSync(openCodeDir);
410
+ } catch {
411
+ return false;
412
+ }
413
+ }
414
+
415
+ /**
416
+ * Returns the OpenCode home directory inside the Accomplish data dir.
417
+ */
418
+ function getAccomplishOpenCodeHome() {
419
+ return path.join(getAccomplishDataDir(), 'opencode');
420
+ }
421
+
422
+ /**
423
+ * Install the babysitter plugin into Accomplish's OpenCode directory.
424
+ * Mirrors the standard OpenCode install: copies bundle, writes index.js,
425
+ * installs skills and hooks.
426
+ */
427
+ function installAccomplishSurface(packageRoot, accomplishOpenCodeHome) {
428
+ const pluginRoot = path.join(accomplishOpenCodeHome, 'plugins', PLUGIN_NAME);
429
+
430
+ // Copy plugin bundle
431
+ copyPluginBundle(packageRoot, pluginRoot);
432
+
433
+ // Create index.js entry point
434
+ writeIndexJs(pluginRoot);
435
+
436
+ // Install skills and hooks config
437
+ installOpenCodeSurface(packageRoot, accomplishOpenCodeHome);
438
+ }
439
+
370
440
  // ---------------------------------------------------------------------------
371
441
  // OpenCode surface installation
372
442
  // ---------------------------------------------------------------------------
@@ -395,10 +465,14 @@ module.exports = {
395
465
  copyRecursive,
396
466
  ensureGlobalProcessLibrary,
397
467
  ensureMarketplaceEntry,
468
+ getAccomplishDataDir,
469
+ getAccomplishOpenCodeHome,
398
470
  getHomeMarketplacePath,
399
471
  getHomePluginRoot,
400
472
  getOpenCodeHome,
473
+ installAccomplishSurface,
401
474
  installOpenCodeSurface,
475
+ isAccomplishInstalled,
402
476
  removeManagedHooks,
403
477
  removeMarketplaceEntry,
404
478
  writeIndexJs,
package/bin/install.cjs CHANGED
@@ -14,6 +14,7 @@
14
14
  * node install.cjs # Install into cwd workspace
15
15
  * node install.cjs --workspace /path # Install into specified workspace
16
16
  * node install.cjs --global # Global install (user home)
17
+ * node install.cjs --accomplish # Install only to Accomplish AI data dir
17
18
  */
18
19
 
19
20
  const path = require('path');
@@ -21,10 +22,13 @@ const {
21
22
  copyPluginBundle,
22
23
  ensureGlobalProcessLibrary,
23
24
  ensureMarketplaceEntry,
25
+ getAccomplishOpenCodeHome,
24
26
  getHomeMarketplacePath,
25
27
  getHomePluginRoot,
26
28
  getOpenCodeHome,
29
+ installAccomplishSurface,
27
30
  installOpenCodeSurface,
31
+ isAccomplishInstalled,
28
32
  writeIndexJs,
29
33
  } = require('./install-shared.cjs');
30
34
 
@@ -32,6 +36,7 @@ const PACKAGE_ROOT = path.resolve(__dirname, '..');
32
36
 
33
37
  function parseArgs(argv) {
34
38
  let workspace = process.env.OPENCODE_WORKSPACE || process.cwd();
39
+ let accomplish = false;
35
40
  for (let i = 2; i < argv.length; i += 1) {
36
41
  const arg = argv[i];
37
42
  if (arg === '--workspace') {
@@ -43,47 +48,91 @@ function parseArgs(argv) {
43
48
  workspace = null;
44
49
  continue;
45
50
  }
51
+ if (arg === '--accomplish') {
52
+ accomplish = true;
53
+ continue;
54
+ }
46
55
  throw new Error(`unknown argument: ${arg}`);
47
56
  }
48
- return { workspace };
57
+ return { workspace, accomplish };
49
58
  }
50
59
 
51
- function main() {
52
- const { workspace } = parseArgs(process.argv);
60
+ function installStandardOpenCode(workspace) {
53
61
  const openCodeHome = getOpenCodeHome(workspace);
54
62
  const pluginRoot = getHomePluginRoot(workspace);
55
63
  const marketplacePath = getHomeMarketplacePath(workspace);
56
64
 
57
65
  console.log(`[babysitter] Installing OpenCode plugin to ${pluginRoot}`);
58
66
 
67
+ // 1. Copy plugin bundle
68
+ copyPluginBundle(PACKAGE_ROOT, pluginRoot);
69
+ console.log('[babysitter] Copied plugin bundle');
70
+
71
+ // 2. Write index.js entry point for OpenCode plugin discovery
72
+ writeIndexJs(pluginRoot);
73
+ console.log('[babysitter] Created index.js entry point');
74
+
75
+ // 3. Register in marketplace
76
+ ensureMarketplaceEntry(marketplacePath, pluginRoot);
77
+ console.log(`[babysitter] Marketplace: ${marketplacePath}`);
78
+
79
+ // 4. Install OpenCode surfaces (skills, hooks config)
80
+ installOpenCodeSurface(PACKAGE_ROOT, openCodeHome);
81
+ console.log('[babysitter] Installed hooks and skills');
82
+
83
+ // 5. Bootstrap global process library
84
+ try {
85
+ const active = ensureGlobalProcessLibrary(PACKAGE_ROOT);
86
+ console.log(`[babysitter] Process library: ${active.binding?.dir || '(default)'}`);
87
+ if (active.defaultSpec?.cloneDir) {
88
+ console.log(`[babysitter] Process library clone: ${active.defaultSpec.cloneDir}`);
89
+ }
90
+ console.log(`[babysitter] Process library state: ${active.stateFile}`);
91
+ } catch (err) {
92
+ console.warn(`[babysitter] Warning: Could not bootstrap process library: ${err.message}`);
93
+ console.warn('[babysitter] Run "babysitter process-library:clone" manually if needed.');
94
+ }
95
+ }
96
+
97
+ function installToAccomplish() {
98
+ const accomplishHome = getAccomplishOpenCodeHome();
99
+ console.log(`[babysitter] Installing plugin to Accomplish AI: ${accomplishHome}`);
100
+
101
+ installAccomplishSurface(PACKAGE_ROOT, accomplishHome);
102
+
103
+ console.log('[babysitter] Copied plugin bundle to Accomplish');
104
+ console.log('[babysitter] Created index.js entry point for Accomplish');
105
+ console.log('[babysitter] Installed hooks and skills for Accomplish');
106
+ console.log('[babysitter] Accomplish AI installation complete.');
107
+ console.log('[babysitter] Restart Accomplish to pick up the installed plugin.');
108
+ }
109
+
110
+ function main() {
111
+ const { workspace, accomplish } = parseArgs(process.argv);
112
+
59
113
  try {
60
- // 1. Copy plugin bundle
61
- copyPluginBundle(PACKAGE_ROOT, pluginRoot);
62
- console.log('[babysitter] Copied plugin bundle');
63
-
64
- // 2. Write index.js entry point for OpenCode plugin discovery
65
- writeIndexJs(pluginRoot);
66
- console.log('[babysitter] Created index.js entry point');
67
-
68
- // 3. Register in marketplace
69
- ensureMarketplaceEntry(marketplacePath, pluginRoot);
70
- console.log(`[babysitter] Marketplace: ${marketplacePath}`);
71
-
72
- // 4. Install OpenCode surfaces (skills, hooks config)
73
- installOpenCodeSurface(PACKAGE_ROOT, openCodeHome);
74
- console.log('[babysitter] Installed hooks and skills');
75
-
76
- // 5. Bootstrap global process library
77
- try {
78
- const active = ensureGlobalProcessLibrary(PACKAGE_ROOT);
79
- console.log(`[babysitter] Process library: ${active.binding?.dir || '(default)'}`);
80
- if (active.defaultSpec?.cloneDir) {
81
- console.log(`[babysitter] Process library clone: ${active.defaultSpec.cloneDir}`);
114
+ // If --accomplish is used without --global/--workspace, install only to Accomplish
115
+ if (accomplish && workspace !== null) {
116
+ installToAccomplish();
117
+ return;
118
+ }
119
+
120
+ // Standard OpenCode install
121
+ installStandardOpenCode(workspace);
122
+
123
+ // Auto-detect Accomplish and install there too (unless --accomplish was explicit)
124
+ if (!accomplish) {
125
+ try {
126
+ if (isAccomplishInstalled()) {
127
+ console.log('[babysitter] Detected Accomplish AI installation.');
128
+ installToAccomplish();
129
+ }
130
+ } catch (err) {
131
+ console.warn(`[babysitter] Warning: Accomplish AI detection failed: ${err.message}`);
82
132
  }
83
- console.log(`[babysitter] Process library state: ${active.stateFile}`);
84
- } catch (err) {
85
- console.warn(`[babysitter] Warning: Could not bootstrap process library: ${err.message}`);
86
- console.warn('[babysitter] Run "babysitter process-library:clone" manually if needed.');
133
+ } else {
134
+ // --accomplish combined with --global: install to both
135
+ installToAccomplish();
87
136
  }
88
137
 
89
138
  console.log('[babysitter] Installation complete!');
@@ -4,9 +4,9 @@ argument-hint: "[run-id] Optional run ID to diagnose. If omitted, uses the most
4
4
  allowed-tools: Read, Grep, Write, Task, Bash, Edit, Grep, Glob, WebFetch, WebSearch, Search, AskUserQuestion, TodoWrite, TodoRead, Skill, BashOutput, KillShell, MultiEdit, LS
5
5
  ---
6
6
 
7
- You are a diagnostic agent for the babysitter runtime. Your job is to perform a comprehensive health check across 10 areas and produce a structured diagnostic report. Follow each section methodically. Track results as you go and produce the final summary at the end.
7
+ You are a diagnostic agent for the babysitter runtime. Your job is to perform a comprehensive health check across 14 areas and produce a structured diagnostic report. Follow each section methodically. Track results as you go and produce the final summary at the end.
8
8
 
9
- Initialize a results tracker with these 10 checks, all starting as PENDING:
9
+ Initialize a results tracker with these 14 checks, all starting as PENDING:
10
10
  1. Run Discovery
11
11
  2. Journal Integrity
12
12
  3. State Cache Consistency
@@ -17,6 +17,10 @@ Initialize a results tracker with these 10 checks, all starting as PENDING:
17
17
  8. Disk Usage
18
18
  9. Process Validation
19
19
  10. Hook Execution Health
20
+ 11. Session-ID Provenance
21
+ 12. Ancestor Liveness
22
+ 13. Concurrent Session Detection
23
+ 14. Windows Ancestor-Walk Strategy
20
24
 
21
25
  ---
22
26
 
@@ -177,13 +181,13 @@ Mark as PASS if no issues. Mark as WARN if runaway loops or stale sessions detec
177
181
  **Goal:** Analyze babysitter log files for errors, warnings, and stop hook decisions.
178
182
 
179
183
  Read the last 50 lines of each of these log files (if they exist):
180
- - `$CLAUDE_PLUGIN_ROOT/.a5c/logs/hooks.log`
181
- - `$CLAUDE_PLUGIN_ROOT/.a5c/logs/babysitter-stop-hook.log`
182
- - `$CLAUDE_PLUGIN_ROOT/.a5c/logs/babysitter-stop-hook-stderr.log`
183
- - `$CLAUDE_PLUGIN_ROOT/.a5c/logs/babysitter-session-start-hook.log`
184
- - `$CLAUDE_PLUGIN_ROOT/.a5c/logs/babysitter-session-start-hook-stderr.log`
185
- - `$CLAUDE_PLUGIN_ROOT/.a5c/logs/babysitter.log`
186
- - `$HOME/.a5c/logs/` and relevant logs and run/session specific logs there
184
+ - `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/hooks.log`
185
+ - `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-stop-hook.log`
186
+ - `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-stop-hook-stderr.log`
187
+ - `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-session-start-hook.log`
188
+ - `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-session-start-hook-stderr.log`
189
+ - `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter.log`
190
+ - `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/` and relevant run/session specific logs there
187
191
 
188
192
 
189
193
  For each log file:
@@ -285,7 +289,7 @@ The hooks delegate to the `babysitter` CLI. Check if it is available:
285
289
  Check whether the stop hook has actually been invoked during this run's lifetime:
286
290
 
287
291
  **From log files:**
288
- - Read `$CLAUDE_PLUGIN_ROOT/.a5c/logs/babysitter-stop-hook.log` (if it exists).
292
+ - Read `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-stop-hook.log` (if it exists).
289
293
  - Count the number of "Hook script invoked" lines. This is the total invocation count.
290
294
  - Count the number of "CLI exit code=" lines and extract exit codes.
291
295
  - If the log file does not exist or has zero invocations, the stop hook has NOT been running.
@@ -297,7 +301,7 @@ Check whether the stop hook has actually been invoked during this run's lifetime
297
301
  - If no STOP_HOOK_INVOKED events exist in the journal, note that the stop hook has not recorded any decisions for this run.
298
302
 
299
303
  **From stderr:**
300
- - Read `$CLAUDE_PLUGIN_ROOT/.a5c/logs/babysitter-stop-hook-stderr.log`.
304
+ - Read `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-stop-hook-stderr.log`.
301
305
  - If it contains error output, display it and diagnose:
302
306
  - "command not found" or exit code 127 → CLI not installed (see 10c)
303
307
  - "MODULE_NOT_FOUND" or "Cannot find module" → SDK package corrupted or not built
@@ -350,9 +354,65 @@ Mark as FAIL if:
350
354
 
351
355
  ---
352
356
 
357
+ ## 11. Session-ID Provenance
358
+
359
+ **Goal:** Verify how the current babysitter session ID was resolved and flag stale or shadowed values.
360
+
361
+ - Invoke: `npx babysitter session:whoami --json`
362
+ - Parse the output and inspect the `resolvedFrom` field. Classify as follows:
363
+ - `resolvedFrom: "pid-marker"` → mark as PASS ("Session ID derives from the live Claude Code ancestor process -- authoritative").
364
+ - `resolvedFrom: "env-file"` → mark as PASS with a note ("CLAUDE_ENV_FILE was used; typically healthy").
365
+ - `resolvedFrom: "env-var"` → mark as WARN ("`BABYSITTER_SESSION_ID` is set without a corroborating PID marker. Likely stale from a prior Claude Code session -- see GitHub issue #130").
366
+ - Remediation: run `babysitter session:cleanup` and start a fresh Claude Code session, or `unset BABYSITTER_SESSION_ID` before invoking babysitter.
367
+ - `resolvedFrom: "none"` → mark as ERROR ("No session ID resolvable. Either no session-start hook fired, or the ancestor walk failed").
368
+
369
+ **Env-var shadow check:**
370
+ - Independently inspect `envVarPresent` and `envVarMatches` in the output.
371
+ - If `envVarPresent && !envVarMatches`, mark as WARN ("`BABYSITTER_SESSION_ID` in env does not match the resolved session ID; a stale value is shadowing the authoritative one. Unset the env var").
372
+
373
+ ---
374
+
375
+ ## 12. Ancestor Liveness
376
+
377
+ **Goal:** Confirm the PID marker references a live Claude Code process.
378
+
379
+ - Reuse the `session:whoami --json` output from check 11.
380
+ - Inspect the `ancestorAlive` field.
381
+ - If `ancestorAlive === false`, mark as ERROR ("The PID marker references a dead Claude Code process").
382
+ - Remediation: `babysitter session:cleanup`.
383
+ - Otherwise mark as PASS.
384
+
385
+ ---
386
+
387
+ ## 13. Concurrent Session Detection
388
+
389
+ **Goal:** Surface multiple live harness sessions that may compete for the same session ID.
390
+
391
+ - Enumerate files in `~/.a5c/` matching the pattern `current-session-*-pid-*`.
392
+ - Count markers per harness (derived from the filename).
393
+ - If more than one live marker exists for the same harness, mark as INFO ("Multiple live Claude Code / harness sessions detected; ensure each shell scopes `BABYSITTER_SESSION_ID` appropriately -- the PID marker handles this automatically").
394
+ - Otherwise mark as PASS.
395
+
396
+ ---
397
+
398
+ ## 14. Windows Ancestor-Walk Strategy
399
+
400
+ **Goal:** Verify the ancestor-walk strategy works on Windows, where `wmic` is no longer guaranteed to be present.
401
+
402
+ - Only run this check when `process.platform === 'win32'`. On other platforms, mark as PASS ("Not applicable -- non-Windows platform").
403
+ - Attempt the ancestor walk by invoking `npx babysitter session:whoami --json` (reuse output from check 11 if available).
404
+ - If resolution succeeded (any `resolvedFrom` other than `none`), mark as PASS.
405
+ - If `resolvedFrom: "none"` on Windows:
406
+ - Test `wmic` availability: `where wmic` via shell.
407
+ - If absent, document that Windows 11 24H2 removed `wmic`; the fallback PowerShell CIM path should handle this.
408
+ - If the PowerShell ancestor walk also failed, mark as ERROR with remediation: ensure PowerShell is available (`powershell -NoProfile -Command "Get-CimInstance Win32_Process -Filter ProcessId=$PID"` should work).
409
+ - If the cascade works but is slow (>5s on first probe), add an INFO note on first-probe latency.
410
+
411
+ ---
412
+
353
413
  ## Final Report
354
414
 
355
- After completing all 10 checks, produce the diagnostic report in this format:
415
+ After completing all 14 checks, produce the diagnostic report in this format:
356
416
 
357
417
  ```
358
418
  ============================================
@@ -379,6 +439,10 @@ OVERALL HEALTH: <HEALTHY | WARNING | CRITICAL>
379
439
  | 8 | Disk Usage | <status> |
380
440
  | 9 | Process Validation | <status> |
381
441
  | 10 | Hook Execution Health | <status> |
442
+ | 11 | Session-ID Provenance | <status> |
443
+ | 12 | Ancestor Liveness | <status> |
444
+ | 13 | Concurrent Session Detection | <status> |
445
+ | 14 | Windows Ancestor-Walk Strategy | <status> |
382
446
 
383
447
  --------------------------------------------
384
448
  ISSUES & RECOMMENDATIONS
@@ -392,9 +456,9 @@ OVERALL HEALTH: <HEALTHY | WARNING | CRITICAL>
392
456
  ```
393
457
 
394
458
  **Overall health determination:**
395
- - **HEALTHY**: All 10 checks are PASS.
396
- - **WARNING**: At least one check is WARN but none are FAIL.
397
- - **CRITICAL**: At least one check is FAIL.
459
+ - **HEALTHY**: All 14 checks are PASS (INFO notes are acceptable).
460
+ - **WARNING**: At least one check is WARN but none are FAIL or ERROR.
461
+ - **CRITICAL**: At least one check is FAIL or ERROR.
398
462
 
399
463
  Present the full detailed findings for each check BEFORE the summary table, so the user can see the evidence. End with the summary table and recommendations. Also, create a single HTML report file with all the findings that uses the arwes UI framework and open it for the user in the browser.
400
464
 
@@ -424,3 +488,25 @@ After diagnosing issues, prompt the user to report or fix what was found -- they
424
488
  Example prompt after diagnosis:
425
489
 
426
490
  > "Diagnosis found a stale lock -- process 12847 crashed without cleanup. This is a known edge case in the orchestration loop. Even if you don't want to fix it yourself, reporting it helps: run `/babysitter:contrib bug report: orchestration loop doesn't release lock on unhandled rejection` to open an issue."
491
+
492
+ ---
493
+
494
+ ## Self-Heal Suggestions
495
+
496
+ If any of checks 11-14 surface issues (stale env vars, dead ancestor PIDs, shadowed session IDs, or Windows ancestor-walk failures), suggest the following remediation sequence, in order. Present it as an actionable block:
497
+
498
+ ```bash
499
+ # 1. Cleanup dead markers and orphaned state files
500
+ babysitter session:cleanup --dry-run # preview
501
+ babysitter session:cleanup # apply
502
+
503
+ # 2. Unset a stale env var
504
+ unset BABYSITTER_SESSION_ID
505
+
506
+ # 3. Re-bind a run explicitly if needed
507
+ babysitter session:resume --session-id <fresh-id> --state-dir ~/.a5c --run-id <runId> --runs-dir .a5c/runs
508
+
509
+ # 4. Start a fresh Claude Code session (closes and reopens the session)
510
+ ```
511
+
512
+ Run steps 1 and 2 first; re-run `/babysitter:doctor` after each step to confirm the session-provenance checks return to PASS. Step 3 is only needed when a specific run must be re-bound to the fresh session. If the issue persists after step 4, escalate via `/debug` or `/babysitter:contrib`.
@@ -16,12 +16,13 @@
16
16
 
17
17
  const { execSync, execFileSync } = require("child_process");
18
18
  const { readFileSync, mkdirSync, appendFileSync, existsSync, writeFileSync } = require("fs");
19
+ const os = require("os");
19
20
  const path = require("path");
20
21
  const crypto = require("crypto");
21
22
 
22
23
  const PLUGIN_ROOT = process.env.OPENCODE_PLUGIN_ROOT || path.resolve(__dirname, "..");
23
24
  const STATE_DIR = process.env.BABYSITTER_STATE_DIR || path.join(process.cwd(), ".a5c");
24
- const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(PLUGIN_ROOT, ".a5c", "logs");
25
+ const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(os.homedir(), ".a5c", "logs");
25
26
  const LOG_FILE = path.join(LOG_DIR, "babysitter-session-created-hook.log");
26
27
 
27
28
  // ---------------------------------------------------------------------------
@@ -20,11 +20,12 @@
20
20
 
21
21
  const { execSync } = require("child_process");
22
22
  const { readFileSync, mkdirSync, appendFileSync } = require("fs");
23
+ const os = require("os");
23
24
  const path = require("path");
24
25
 
25
26
  const PLUGIN_ROOT = process.env.OPENCODE_PLUGIN_ROOT || path.resolve(__dirname, "..");
26
27
  const STATE_DIR = process.env.BABYSITTER_STATE_DIR || path.join(process.cwd(), ".a5c");
27
- const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(PLUGIN_ROOT, ".a5c", "logs");
28
+ const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(os.homedir(), ".a5c", "logs");
28
29
  const LOG_FILE = path.join(LOG_DIR, "babysitter-session-idle-hook.log");
29
30
 
30
31
  function ensureDir(dir) {
@@ -18,13 +18,14 @@
18
18
  "use strict";
19
19
 
20
20
  const { readFileSync, mkdirSync, appendFileSync, existsSync } = require("fs");
21
+ const os = require("os");
21
22
  const path = require("path");
22
23
  const crypto = require("crypto");
23
24
 
24
25
  const PLUGIN_ROOT = process.env.OPENCODE_PLUGIN_ROOT || path.resolve(__dirname, "..");
25
26
  const STATE_DIR = process.env.BABYSITTER_STATE_DIR || path.join(process.cwd(), ".a5c");
26
27
  const RUNS_DIR = process.env.BABYSITTER_RUNS_DIR || path.join(STATE_DIR, "runs");
27
- const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(PLUGIN_ROOT, ".a5c", "logs");
28
+ const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(os.homedir(), ".a5c", "logs");
28
29
  const LOG_FILE = path.join(LOG_DIR, "babysitter-shell-env-hook.log");
29
30
 
30
31
  function ensureDir(dir) {
@@ -20,11 +20,12 @@
20
20
 
21
21
  const { execSync } = require("child_process");
22
22
  const { readFileSync, mkdirSync, appendFileSync } = require("fs");
23
+ const os = require("os");
23
24
  const path = require("path");
24
25
 
25
26
  const PLUGIN_ROOT = process.env.OPENCODE_PLUGIN_ROOT || path.resolve(__dirname, "..");
26
27
  const STATE_DIR = process.env.BABYSITTER_STATE_DIR || path.join(process.cwd(), ".a5c");
27
- const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(PLUGIN_ROOT, ".a5c", "logs");
28
+ const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(os.homedir(), ".a5c", "logs");
28
29
  const LOG_FILE = path.join(LOG_DIR, "babysitter-tool-after-hook.log");
29
30
 
30
31
  function ensureDir(dir) {
@@ -20,11 +20,12 @@
20
20
 
21
21
  const { execSync } = require("child_process");
22
22
  const { readFileSync, mkdirSync, appendFileSync } = require("fs");
23
+ const os = require("os");
23
24
  const path = require("path");
24
25
 
25
26
  const PLUGIN_ROOT = process.env.OPENCODE_PLUGIN_ROOT || path.resolve(__dirname, "..");
26
27
  const STATE_DIR = process.env.BABYSITTER_STATE_DIR || path.join(process.cwd(), ".a5c");
27
- const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(PLUGIN_ROOT, ".a5c", "logs");
28
+ const LOG_DIR = process.env.BABYSITTER_LOG_DIR || path.join(os.homedir(), ".a5c", "logs");
28
29
  const LOG_FILE = path.join(LOG_DIR, "babysitter-tool-before-hook.log");
29
30
 
30
31
  function ensureDir(dir) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a5c-ai/babysitter-opencode",
3
- "version": "0.1.3",
3
+ "version": "0.1.4-staging.06f78f92",
4
4
  "description": "Babysitter orchestration plugin for OpenCode with SDK-managed process-library bootstrapping and in-turn iteration model",
5
5
  "scripts": {
6
6
  "test": "node test/integration.test.js",
@@ -41,6 +41,6 @@
41
41
  },
42
42
  "homepage": "https://github.com/a5c-ai/babysitter/tree/main/plugins/babysitter-opencode#readme",
43
43
  "dependencies": {
44
- "@a5c-ai/babysitter-sdk": "0.0.187"
44
+ "@a5c-ai/babysitter-sdk": "0.0.188-staging.06f78f92"
45
45
  }
46
46
  }
@@ -0,0 +1,114 @@
1
+ ---
2
+ name: accomplish-status
3
+ description: Report babysitter orchestration run status to Accomplish AI desktop app via file-based IPC
4
+ command: /accomplish-status
5
+ ---
6
+
7
+ # accomplish-status
8
+
9
+ Report babysitter run status to the [Accomplish AI](https://github.com/accomplish-ai/accomplish) desktop app via file-based IPC.
10
+
11
+ ## Overview
12
+
13
+ This skill writes run status JSON to a well-known directory. External consumers (such as a future Accomplish daemon integration or other tooling) can watch this directory for changes to track orchestration progress, pending breakpoints, and completion state.
14
+
15
+ ## Status File Location
16
+
17
+ Status files are written to:
18
+
19
+ ```
20
+ <OPENCODE_CONFIG_DIR>/run-status/<runId>.json
21
+ ```
22
+
23
+ Where `OPENCODE_CONFIG_DIR` is resolved from the `OPENCODE_CONFIG_DIR` environment variable (typically `~/.config/opencode` or platform equivalent).
24
+
25
+ ## Dependencies
26
+
27
+ ### Babysitter SDK and CLI
28
+
29
+ Read the SDK version from `versions.json` to ensure version compatibility:
30
+
31
+ ```bash
32
+ SDK_VERSION=$(node -e "try{const fs=require('fs');const probes=['./plugins/babysitter-opencode/versions.json','./node_modules/@a5c-ai/babysitter-opencode/versions.json'];for(const probe of probes){if(fs.existsSync(probe)){console.log(JSON.parse(fs.readFileSync(probe,'utf8')).sdkVersion||'latest');process.exit(0)}}console.log('latest')}catch{console.log('latest')}")
33
+ CLI="npx -y @a5c-ai/babysitter-sdk@$SDK_VERSION"
34
+ ```
35
+
36
+ ## Instructions
37
+
38
+ ### 1. Resolve the status directory
39
+
40
+ ```bash
41
+ STATUS_DIR="${OPENCODE_CONFIG_DIR:-$HOME/.config/opencode}/run-status"
42
+ mkdir -p "$STATUS_DIR"
43
+ ```
44
+
45
+ ### 2. Get run status from babysitter
46
+
47
+ ```bash
48
+ babysitter run:status .a5c/runs/<runId> --json
49
+ ```
50
+
51
+ ### 3. Write the status file
52
+
53
+ Transform the run status output into the Accomplish status format and write it to `$STATUS_DIR/<runId>.json`.
54
+
55
+ Use the `ACCOMPLISH_TASK_ID` environment variable to correlate the babysitter run with the originating Accomplish task. This variable is set automatically by Accomplish when it spawns the agent session.
56
+
57
+ ```bash
58
+ ACCOMPLISH_TASK_ID="${ACCOMPLISH_TASK_ID:-}"
59
+ ```
60
+
61
+ ### 4. Status file format
62
+
63
+ Write the following JSON structure to `$STATUS_DIR/<runId>.json`:
64
+
65
+ ```json
66
+ {
67
+ "runId": "abc123-def456",
68
+ "processId": "my-process",
69
+ "status": "running",
70
+ "currentPhase": "execute",
71
+ "phases": [
72
+ { "name": "plan", "status": "completed" },
73
+ { "name": "execute", "status": "running" },
74
+ { "name": "verify", "status": "pending" }
75
+ ],
76
+ "pendingEffects": [
77
+ {
78
+ "effectId": "eff-001",
79
+ "kind": "breakpoint",
80
+ "title": "Approve implementation plan"
81
+ }
82
+ ],
83
+ "accomplishTaskId": "accomplish-task-789",
84
+ "lastUpdatedAt": "2026-04-04T12:00:00.000Z"
85
+ }
86
+ ```
87
+
88
+ #### Field reference
89
+
90
+ | Field | Type | Description |
91
+ |-------|------|-------------|
92
+ | `runId` | string | Babysitter run identifier |
93
+ | `processId` | string | Process definition identifier |
94
+ | `status` | enum | One of: `created`, `running`, `waiting`, `completed`, `failed` |
95
+ | `currentPhase` | string | Name of the currently active phase |
96
+ | `phases` | array | Ordered list of phases with individual status (`pending`, `running`, `completed`, `failed`) |
97
+ | `pendingEffects` | array | Currently pending effects (tasks, breakpoints, sleeps) awaiting resolution |
98
+ | `accomplishTaskId` | string | Correlation ID from `ACCOMPLISH_TASK_ID` env var; links this run to the Accomplish UI task |
99
+ | `lastUpdatedAt` | string | ISO 8601 timestamp of the last status update |
100
+
101
+ ### 5. When to update
102
+
103
+ Write or update the status file:
104
+
105
+ - Immediately after `babysitter run:create` (status: `created`)
106
+ - After each `babysitter run:iterate` call (status: `running` or `waiting`)
107
+ - When breakpoints are requested (status: `waiting`, include breakpoint in `pendingEffects`)
108
+ - After `babysitter task:post` resolves an effect (status: `running`)
109
+ - On run completion (status: `completed`)
110
+ - On run failure (status: `failed`)
111
+
112
+ ### 6. Cleanup
113
+
114
+ When a run reaches a terminal state (`completed` or `failed`), the status file may be left in place for external consumers to read the final state. Stale status files can be cleaned up manually or by external tooling.
@@ -5,9 +5,9 @@ description: Diagnose babysitter run health - journal integrity, state cache, ef
5
5
 
6
6
  # doctor
7
7
 
8
- You are a diagnostic agent for the babysitter runtime. Your job is to perform a comprehensive health check across 10 areas and produce a structured diagnostic report. Follow each section methodically. Track results as you go and produce the final summary at the end.
8
+ You are a diagnostic agent for the babysitter runtime. Your job is to perform a comprehensive health check across 14 areas and produce a structured diagnostic report. Follow each section methodically. Track results as you go and produce the final summary at the end.
9
9
 
10
- Initialize a results tracker with these 10 checks, all starting as PENDING:
10
+ Initialize a results tracker with these 14 checks, all starting as PENDING:
11
11
  1. Run Discovery
12
12
  2. Journal Integrity
13
13
  3. State Cache Consistency
@@ -18,6 +18,10 @@ Initialize a results tracker with these 10 checks, all starting as PENDING:
18
18
  8. Disk Usage
19
19
  9. Process Validation
20
20
  10. Hook Execution Health
21
+ 11. Session-ID Provenance
22
+ 12. Ancestor Liveness
23
+ 13. Concurrent Session Detection
24
+ 14. Windows Ancestor-Walk Strategy
21
25
 
22
26
  ---
23
27
 
@@ -178,13 +182,13 @@ Mark as PASS if no issues. Mark as WARN if runaway loops or stale sessions detec
178
182
  **Goal:** Analyze babysitter log files for errors, warnings, and stop hook decisions.
179
183
 
180
184
  Read the last 50 lines of each of these log files (if they exist):
181
- - `$CLAUDE_PLUGIN_ROOT/.a5c/logs/hooks.log`
182
- - `$CLAUDE_PLUGIN_ROOT/.a5c/logs/babysitter-stop-hook.log`
183
- - `$CLAUDE_PLUGIN_ROOT/.a5c/logs/babysitter-stop-hook-stderr.log`
184
- - `$CLAUDE_PLUGIN_ROOT/.a5c/logs/babysitter-session-start-hook.log`
185
- - `$CLAUDE_PLUGIN_ROOT/.a5c/logs/babysitter-session-start-hook-stderr.log`
186
- - `$CLAUDE_PLUGIN_ROOT/.a5c/logs/babysitter.log`
187
- - `$HOME/.a5c/logs/` and relevant logs and run/session specific logs there
185
+ - `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/hooks.log`
186
+ - `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-stop-hook.log`
187
+ - `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-stop-hook-stderr.log`
188
+ - `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-session-start-hook.log`
189
+ - `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-session-start-hook-stderr.log`
190
+ - `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter.log`
191
+ - `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/` and relevant run/session specific logs there
188
192
 
189
193
 
190
194
  For each log file:
@@ -286,7 +290,7 @@ The hooks delegate to the `babysitter` CLI. Check if it is available:
286
290
  Check whether the stop hook has actually been invoked during this run's lifetime:
287
291
 
288
292
  **From log files:**
289
- - Read `$CLAUDE_PLUGIN_ROOT/.a5c/logs/babysitter-stop-hook.log` (if it exists).
293
+ - Read `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-stop-hook.log` (if it exists).
290
294
  - Count the number of "Hook script invoked" lines. This is the total invocation count.
291
295
  - Count the number of "CLI exit code=" lines and extract exit codes.
292
296
  - If the log file does not exist or has zero invocations, the stop hook has NOT been running.
@@ -298,7 +302,7 @@ Check whether the stop hook has actually been invoked during this run's lifetime
298
302
  - If no STOP_HOOK_INVOKED events exist in the journal, note that the stop hook has not recorded any decisions for this run.
299
303
 
300
304
  **From stderr:**
301
- - Read `$CLAUDE_PLUGIN_ROOT/.a5c/logs/babysitter-stop-hook-stderr.log`.
305
+ - Read `${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}/babysitter-stop-hook-stderr.log`.
302
306
  - If it contains error output, display it and diagnose:
303
307
  - "command not found" or exit code 127 → CLI not installed (see 10c)
304
308
  - "MODULE_NOT_FOUND" or "Cannot find module" → SDK package corrupted or not built
@@ -351,9 +355,65 @@ Mark as FAIL if:
351
355
 
352
356
  ---
353
357
 
358
+ ## 11. Session-ID Provenance
359
+
360
+ **Goal:** Verify how the current babysitter session ID was resolved and flag stale or shadowed values.
361
+
362
+ - Invoke: `npx babysitter session:whoami --json`
363
+ - Parse the output and inspect the `resolvedFrom` field. Classify as follows:
364
+ - `resolvedFrom: "pid-marker"` → mark as PASS ("Session ID derives from the live Claude Code ancestor process -- authoritative").
365
+ - `resolvedFrom: "env-file"` → mark as PASS with a note ("CLAUDE_ENV_FILE was used; typically healthy").
366
+ - `resolvedFrom: "env-var"` → mark as WARN ("`BABYSITTER_SESSION_ID` is set without a corroborating PID marker. Likely stale from a prior Claude Code session -- see GitHub issue #130").
367
+ - Remediation: run `babysitter session:cleanup` and start a fresh Claude Code session, or `unset BABYSITTER_SESSION_ID` before invoking babysitter.
368
+ - `resolvedFrom: "none"` → mark as ERROR ("No session ID resolvable. Either no session-start hook fired, or the ancestor walk failed").
369
+
370
+ **Env-var shadow check:**
371
+ - Independently inspect `envVarPresent` and `envVarMatches` in the output.
372
+ - If `envVarPresent && !envVarMatches`, mark as WARN ("`BABYSITTER_SESSION_ID` in env does not match the resolved session ID; a stale value is shadowing the authoritative one. Unset the env var").
373
+
374
+ ---
375
+
376
+ ## 12. Ancestor Liveness
377
+
378
+ **Goal:** Confirm the PID marker references a live Claude Code process.
379
+
380
+ - Reuse the `session:whoami --json` output from check 11.
381
+ - Inspect the `ancestorAlive` field.
382
+ - If `ancestorAlive === false`, mark as ERROR ("The PID marker references a dead Claude Code process").
383
+ - Remediation: `babysitter session:cleanup`.
384
+ - Otherwise mark as PASS.
385
+
386
+ ---
387
+
388
+ ## 13. Concurrent Session Detection
389
+
390
+ **Goal:** Surface multiple live harness sessions that may compete for the same session ID.
391
+
392
+ - Enumerate files in `~/.a5c/` matching the pattern `current-session-*-pid-*`.
393
+ - Count markers per harness (derived from the filename).
394
+ - If more than one live marker exists for the same harness, mark as INFO ("Multiple live Claude Code / harness sessions detected; ensure each shell scopes `BABYSITTER_SESSION_ID` appropriately -- the PID marker handles this automatically").
395
+ - Otherwise mark as PASS.
396
+
397
+ ---
398
+
399
+ ## 14. Windows Ancestor-Walk Strategy
400
+
401
+ **Goal:** Verify the ancestor-walk strategy works on Windows, where `wmic` is no longer guaranteed to be present.
402
+
403
+ - Only run this check when `process.platform === 'win32'`. On other platforms, mark as PASS ("Not applicable -- non-Windows platform").
404
+ - Attempt the ancestor walk by invoking `npx babysitter session:whoami --json` (reuse output from check 11 if available).
405
+ - If resolution succeeded (any `resolvedFrom` other than `none`), mark as PASS.
406
+ - If `resolvedFrom: "none"` on Windows:
407
+ - Test `wmic` availability: `where wmic` via shell.
408
+ - If absent, document that Windows 11 24H2 removed `wmic`; the fallback PowerShell CIM path should handle this.
409
+ - If the PowerShell ancestor walk also failed, mark as ERROR with remediation: ensure PowerShell is available (`powershell -NoProfile -Command "Get-CimInstance Win32_Process -Filter ProcessId=$PID"` should work).
410
+ - If the cascade works but is slow (>5s on first probe), add an INFO note on first-probe latency.
411
+
412
+ ---
413
+
354
414
  ## Final Report
355
415
 
356
- After completing all 10 checks, produce the diagnostic report in this format:
416
+ After completing all 14 checks, produce the diagnostic report in this format:
357
417
 
358
418
  ```
359
419
  ============================================
@@ -380,6 +440,10 @@ OVERALL HEALTH: <HEALTHY | WARNING | CRITICAL>
380
440
  | 8 | Disk Usage | <status> |
381
441
  | 9 | Process Validation | <status> |
382
442
  | 10 | Hook Execution Health | <status> |
443
+ | 11 | Session-ID Provenance | <status> |
444
+ | 12 | Ancestor Liveness | <status> |
445
+ | 13 | Concurrent Session Detection | <status> |
446
+ | 14 | Windows Ancestor-Walk Strategy | <status> |
383
447
 
384
448
  --------------------------------------------
385
449
  ISSUES & RECOMMENDATIONS
@@ -393,9 +457,9 @@ OVERALL HEALTH: <HEALTHY | WARNING | CRITICAL>
393
457
  ```
394
458
 
395
459
  **Overall health determination:**
396
- - **HEALTHY**: All 10 checks are PASS.
397
- - **WARNING**: At least one check is WARN but none are FAIL.
398
- - **CRITICAL**: At least one check is FAIL.
460
+ - **HEALTHY**: All 14 checks are PASS (INFO notes are acceptable).
461
+ - **WARNING**: At least one check is WARN but none are FAIL or ERROR.
462
+ - **CRITICAL**: At least one check is FAIL or ERROR.
399
463
 
400
464
  Present the full detailed findings for each check BEFORE the summary table, so the user can see the evidence. End with the summary table and recommendations. Also, create a single HTML report file with all the findings that uses the arwes UI framework and open it for the user in the browser.
401
465
 
@@ -425,3 +489,25 @@ After diagnosing issues, prompt the user to report or fix what was found -- they
425
489
  Example prompt after diagnosis:
426
490
 
427
491
  > "Diagnosis found a stale lock -- process 12847 crashed without cleanup. This is a known edge case in the orchestration loop. Even if you don't want to fix it yourself, reporting it helps: run `/babysitter:contrib bug report: orchestration loop doesn't release lock on unhandled rejection` to open an issue."
492
+
493
+ ---
494
+
495
+ ## Self-Heal Suggestions
496
+
497
+ If any of checks 11-14 surface issues (stale env vars, dead ancestor PIDs, shadowed session IDs, or Windows ancestor-walk failures), suggest the following remediation sequence, in order. Present it as an actionable block:
498
+
499
+ ```bash
500
+ # 1. Cleanup dead markers and orphaned state files
501
+ babysitter session:cleanup --dry-run # preview
502
+ babysitter session:cleanup # apply
503
+
504
+ # 2. Unset a stale env var
505
+ unset BABYSITTER_SESSION_ID
506
+
507
+ # 3. Re-bind a run explicitly if needed
508
+ babysitter session:resume --session-id <fresh-id> --state-dir ~/.a5c --run-id <runId> --runs-dir .a5c/runs
509
+
510
+ # 4. Start a fresh Claude Code session (closes and reopens the session)
511
+ ```
512
+
513
+ Run steps 1 and 2 first; re-run `/babysitter:doctor` after each step to confirm the session-provenance checks return to PASS. Step 3 is only needed when a specific run must be re-bound to the fresh session. If the issue persists after step 4, escalate via `/debug` or `/babysitter:contrib`.
package/versions.json CHANGED
@@ -1,4 +1,4 @@
1
1
  {
2
- "sdkVersion": "0.0.187",
2
+ "sdkVersion": "0.0.188-staging.06f78f92",
3
3
  "pluginVersion": "0.1.0"
4
4
  }