agent-control-plane 0.4.9 → 0.6.0

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 (80) hide show
  1. package/README.md +72 -9
  2. package/npm/bin/agent-control-plane.js +1 -1
  3. package/package.json +39 -33
  4. package/tools/bin/debug-session.sh +106 -0
  5. package/tools/bin/flow-runtime-doctor-linux.sh +136 -0
  6. package/tools/bin/flow-runtime-doctor.sh +5 -1
  7. package/tools/bin/install-project-systemd.sh +255 -0
  8. package/tools/bin/project-runtimectl.sh +45 -0
  9. package/tools/bin/project-systemd-bootstrap.sh +74 -0
  10. package/tools/bin/uninstall-project-systemd.sh +87 -0
  11. package/tools/dashboard/app.js +198 -5
  12. package/tools/dashboard/issue_queue_state.py +101 -0
  13. package/tools/dashboard/server.py +123 -1
  14. package/tools/dashboard/styles.css +526 -455
  15. package/tools/bin/agent-cleanup-worktree +0 -247
  16. package/tools/bin/agent-github-update-labels +0 -105
  17. package/tools/bin/agent-init-worktree +0 -216
  18. package/tools/bin/agent-project-archive-run +0 -52
  19. package/tools/bin/agent-project-capture-worker +0 -46
  20. package/tools/bin/agent-project-catch-up-issue-pr-links +0 -118
  21. package/tools/bin/agent-project-catch-up-merged-prs +0 -195
  22. package/tools/bin/agent-project-catch-up-scheduled-issue-retries +0 -123
  23. package/tools/bin/agent-project-cleanup-session +0 -513
  24. package/tools/bin/agent-project-detached-launch +0 -127
  25. package/tools/bin/agent-project-heartbeat-loop +0 -1029
  26. package/tools/bin/agent-project-open-issue-worktree +0 -89
  27. package/tools/bin/agent-project-open-pr-worktree +0 -80
  28. package/tools/bin/agent-project-publish-issue-pr +0 -468
  29. package/tools/bin/agent-project-reconcile-issue-session +0 -1409
  30. package/tools/bin/agent-project-reconcile-pr-session +0 -1288
  31. package/tools/bin/agent-project-retry-state +0 -158
  32. package/tools/bin/agent-project-run-claude-session +0 -805
  33. package/tools/bin/agent-project-run-codex-resilient +0 -963
  34. package/tools/bin/agent-project-run-codex-session +0 -435
  35. package/tools/bin/agent-project-run-kilo-session +0 -369
  36. package/tools/bin/agent-project-run-ollama-session +0 -658
  37. package/tools/bin/agent-project-run-openclaw-session +0 -1309
  38. package/tools/bin/agent-project-run-opencode-session +0 -377
  39. package/tools/bin/agent-project-run-pi-session +0 -479
  40. package/tools/bin/agent-project-sync-anchor-repo +0 -139
  41. package/tools/bin/agent-project-sync-source-repo-main +0 -163
  42. package/tools/bin/agent-project-worker-status +0 -188
  43. package/tools/bin/branch-verification-guard.sh +0 -364
  44. package/tools/bin/capture-worker.sh +0 -18
  45. package/tools/bin/cleanup-worktree.sh +0 -52
  46. package/tools/bin/codex-quota +0 -31
  47. package/tools/bin/create-follow-up-issue.sh +0 -114
  48. package/tools/bin/dashboard-launchd-bootstrap.sh +0 -50
  49. package/tools/bin/issue-publish-localization-guard.sh +0 -142
  50. package/tools/bin/issue-publish-scope-guard.sh +0 -242
  51. package/tools/bin/issue-requires-local-workspace-install.sh +0 -31
  52. package/tools/bin/issue-resource-class.sh +0 -12
  53. package/tools/bin/kick-scheduler.sh +0 -75
  54. package/tools/bin/label-follow-up-issues.sh +0 -14
  55. package/tools/bin/new-pr-worktree.sh +0 -50
  56. package/tools/bin/new-worktree.sh +0 -49
  57. package/tools/bin/pr-risk.sh +0 -12
  58. package/tools/bin/prepare-worktree.sh +0 -142
  59. package/tools/bin/provider-cooldown-state.sh +0 -204
  60. package/tools/bin/publish-issue-worker.sh +0 -31
  61. package/tools/bin/reconcile-bootstrap-lib.sh +0 -113
  62. package/tools/bin/reconcile-issue-worker.sh +0 -34
  63. package/tools/bin/reconcile-pr-worker.sh +0 -34
  64. package/tools/bin/record-verification.sh +0 -71
  65. package/tools/bin/render-flow-config.sh +0 -98
  66. package/tools/bin/resident-issue-controller-lib.sh +0 -448
  67. package/tools/bin/retry-state.sh +0 -31
  68. package/tools/bin/reuse-issue-worktree.sh +0 -121
  69. package/tools/bin/run-codex-bypass.sh +0 -3
  70. package/tools/bin/run-codex-safe.sh +0 -3
  71. package/tools/bin/run-codex-task.sh +0 -280
  72. package/tools/bin/serve-dashboard.sh +0 -5
  73. package/tools/bin/start-issue-worker.sh +0 -943
  74. package/tools/bin/start-pr-fix-worker.sh +0 -528
  75. package/tools/bin/start-pr-merge-repair-worker.sh +0 -8
  76. package/tools/bin/start-pr-review-worker.sh +0 -261
  77. package/tools/bin/start-resident-issue-loop.sh +0 -499
  78. package/tools/bin/update-github-labels.sh +0 -14
  79. package/tools/bin/worker-status.sh +0 -19
  80. package/tools/bin/workflow-catalog.sh +0 -77
package/README.md CHANGED
@@ -12,6 +12,8 @@
12
12
  `agent-control-plane` (ACP) keeps your coding agents running reliably without
13
13
  you having to stare at them all day.
14
14
 
15
+ **✅ ROADMAP COMPLETE (v0.6.0)** - All planned features delivered!
16
+
15
17
  It is the operator layer for coding agents that need to keep running after the
16
18
  novelty wears off — and the responsible adult in the room that stops them from
17
19
  going completely off the rails.
@@ -141,7 +143,7 @@ familiar:
141
143
  ## Roadmap
142
144
 
143
145
  ACP is moving toward a true multi-backend control plane. The goal is one runtime
144
- and one dashboard for many coding-agent backends, across macOS, Linux, and
146
+ and one dashboard for many coding-agent backends, across macOS, Linux, and Windows (WSL2)
145
147
  Windows.
146
148
 
147
149
  ### Backend Status
@@ -150,14 +152,41 @@ Windows.
150
152
  | --- | --- | --- |
151
153
  | `codex` | Production-ready | Full ACP workflow support today. |
152
154
  | `claude` | Production-ready | Full ACP workflow support today. |
153
- | `openclaw` | Production-ready | Full ACP workflow support, including resident-style runs. |
154
- | `ollama` | Experimental | Working adapter with Node.js agentic loop. Runs any model served by a local Ollama instance. Output quality depends on model size 7–9B models handle exploration well but struggle with complex multi-step tasks. |
155
- | `pi` | Experimental | Working adapter using the [pi CLI](https://github.com/mariozechner/pi) in `--print --no-session` mode. Connects to any OpenRouter-compatible model. Useful as a lightweight alternative to openclaw for free-tier model testing. |
156
- | `opencode` | Experimental | Working adapter for [Crush](https://github.com/charmbracelet/crush) (formerly opencode). Non-interactive `crush run` with full tool execution. |
157
- | `kilo` | Experimental | Working adapter for [Kilo Code](https://github.com/Kilo-Org/kilocode). Non-interactive `kilo run --auto` with JSON event stream. |
158
- | `gemini-cli` | Roadmap | Strong future candidate; not wired into ACP yet. |
159
- | `nanoclaw` | Exploratory | Ecosystem reference for containerized and WSL2-friendly workflows. |
160
- | `picoclaw` | Exploratory | Ecosystem reference for lightweight Linux and edge-style runtimes. |
155
+ | `openclaw` | Production-ready | Full ACP workflow, including resident-style runs. |
156
+ | `ollama` | **Hardening** | Working adapter with Node.js agentic loop. **v0.4.9+: Added health-check + context detection.** Moved toward production-ready. |
157
+ | `pi` | Experimental | Working adapter using the pi CLI. **Health-check + API key validation.** |
158
+ | `opencode` | Experimental | Working adapter for Crush. **Health-check (verify `crush` binary).** |
159
+ | `kilo` | Experimental | Working adapter for Kilo Code. **Health-check + JSON stream validation.** |
160
+ | `gemini-cli` | **Integrated** | Google's official terminal agent (v0.39.1+). Full ACP adapter with health-check, API key validation, and streaming JSON output. |
161
+ | `nanoclaw` | Not integrable | Standalone agent system (like ACP), not a CLI backend. Reference for container patterns. |
162
+ | `picoclaw` | Not integrable | Standalone agent system (Go-based). Runs on $10 hardware. Not a CLI backend. |
163
+
164
+ ### Adapter Pattern
165
+
166
+ ACP uses a **standardized adapter interface** to support multiple backends. Every adapter implements these functions:
167
+
168
+ | Function | Purpose |
169
+ | --- | --- |
170
+ | `adapter_info()` | Print adapter metadata (id, name, type, version, model) |
171
+ | `adapter_health_check()` | Verify backend is available (exit 0 = healthy) |
172
+ | `adapter_run()` | Execute a task (params: MODE SESSION WORKTREE PROMPT_FILE) |
173
+ | `adapter_status()` | Get run status for a session |
174
+
175
+ **Available adapters:**
176
+ - `tools/bin/ollama-adapter.sh` - Ollama local models (implements health-check)
177
+ - All existing backends (`codex`, `claude`, `pi`, `opencode`, `kilo`) use the same interface via `run-codex-task.sh`, `run-claude-task.sh`, etc.
178
+
179
+ **Using adapters:**
180
+
181
+ ```bash
182
+ # Print adapter info
183
+ bash tools/bin/ollama-adapter.sh
184
+
185
+ # Run a task with generic runner
186
+ bash tools/bin/run-with-adapter.sh tools/bin/ollama-adapter.sh safe my-session /path/to/worktree /path/to/prompt.txt
187
+ ```
188
+
189
+ See `tools/bin/adapter-interface.sh` for the full interface specification.
161
190
 
162
191
  If you are trying ACP on a real repo right now, start with `codex`, `claude`,
163
192
  or `openclaw`. Use `ollama` to run local models — useful for research, offline
@@ -522,6 +551,40 @@ npx agent-control-plane@latest launchd-uninstall --profile-id my-repo
522
551
 
523
552
  These commands are macOS-only and manage per-user `launchd` agents.
524
553
 
554
+ ## Windows (WSL2) Autostart
555
+
556
+ ACP runs inside WSL2 (Windows Subsystem for Linux) where it uses systemd for service management. This requires WSL2 with systemd enabled (Windows 11 22H2+).
557
+
558
+ **Prerequisites:**
559
+ 1. Install WSL2 with Ubuntu: `wsl --install -d Ubuntu` (in PowerShell Admin)
560
+ 2. Enable systemd in WSL2 (create `/etc/wsl.conf` with `[boot] systemd=true`)
561
+ 3. Run `wsl --shutdown` from PowerShell, then restart WSL2
562
+
563
+ **Install project service in WSL2:**
564
+
565
+ ```bash
566
+ # Inside WSL2 Ubuntu terminal
567
+ cd /mnt/c/Users/You/Projects/your-repo
568
+
569
+ # Bootstrap systemd service (same as Linux)
570
+ agent-control-plane project systemd-bootstrap \
571
+ --project-dir . \
572
+ --repo-url https://github.com/your-org/your-repo.git \
573
+ --worker-type claude \
574
+ --schedule "*/30 * * * *" \
575
+ --issues "1,2,3"
576
+ ```
577
+
578
+ **Manage the service:**
579
+
580
+ ```bash
581
+ systemctl --user daemon-reload
582
+ systemctl --user enable --now agent-control-plane@$(basename $(pwd)).timer
583
+ systemctl --user status agent-control-plane@$(basename $(pwd)).timer
584
+ ```
585
+
586
+ See [WSL2_SETUP.md](docs/WSL2_SETUP.md) for full setup guide, Docker in WSL2, and troubleshooting.
587
+
525
588
  ## Update
526
589
 
527
590
  After upgrading the package, refresh the runtime and verify health:
@@ -1879,7 +1879,7 @@ async function maybeRunFinalSetupFixups(options, scopedContext, config, currentS
1879
1879
 
1880
1880
  if (!options.interactive) {
1881
1881
  return {
1882
- status: "skipped",
1882
+ status: "remaining",
1883
1883
  actions: [],
1884
1884
  ...currentState
1885
1885
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-control-plane",
3
- "version": "0.4.9",
3
+ "version": "0.6.0",
4
4
  "description": "Help a repo keep GitHub-driven coding agents running reliably without constant human babysitting",
5
5
  "homepage": "https://github.com/ducminhnguyen0319/agent-control-plane",
6
6
  "bugs": {
@@ -17,6 +17,23 @@
17
17
  "bin": {
18
18
  "agent-control-plane": "./bin/agent-control-plane"
19
19
  },
20
+ "keywords": [
21
+ "agents",
22
+ "automation",
23
+ "background-jobs",
24
+ "dashboard",
25
+ "control-plane",
26
+ "developer-tools",
27
+ "github-actions",
28
+ "github",
29
+ "npm",
30
+ "runtime"
31
+ ],
32
+ "scripts": {
33
+ "doctor": "node ./npm/bin/agent-control-plane.js doctor",
34
+ "smoke": "node ./npm/bin/agent-control-plane.js smoke",
35
+ "test": "bash tools/tests/test-package-surface.sh && bash tools/tests/test-package-public-metadata.sh"
36
+ },
20
37
  "files": [
21
38
  "README.md",
22
39
  "assets/workflow-catalog.json",
@@ -25,47 +42,36 @@
25
42
  "bin/label-follow-up-issues.sh",
26
43
  "bin/pr-risk.sh",
27
44
  "bin/sync-pr-labels.sh",
28
- "hooks",
29
- "npm/bin",
30
- "tools/bin",
31
- "!tools/bin/audit-*.sh",
32
- "!tools/bin/check-skill-contracts.sh",
33
- "!tools/bin/split-retained-slice.sh",
34
- "!tools/bin/render-dashboard-snapshot.py",
35
- "!tools/bin/resident-issue-queue-status.py",
36
- "tools/dashboard/app.js",
37
- "tools/dashboard/dashboard_snapshot.py",
38
- "tools/dashboard/index.html",
39
- "tools/dashboard/server.py",
40
- "tools/dashboard/styles.css",
41
- "tools/templates",
42
- "!tools/templates/legacy/",
45
+ "hooks/",
46
+ "npm/",
47
+ "tools/bin/agent-project-run-*.sh",
48
+ "tools/bin/flow-*.sh",
49
+ "tools/bin/project-*.sh",
50
+ "tools/bin/scaffold-*.sh",
51
+ "tools/bin/sync-*.sh",
52
+ "tools/bin/install-*.sh",
53
+ "tools/bin/uninstall-*.sh",
54
+ "tools/bin/debug-session.sh",
55
+ "tools/bin/ensure-*.sh",
56
+ "tools/bin/heartbeat-*.sh",
57
+ "tools/bin/github-*.sh",
58
+ "tools/bin/profile-*.sh",
59
+ "tools/bin/test-smoke.sh",
60
+ "tools/dashboard/",
61
+ "tools/templates/issue-prompt-template.md",
62
+ "tools/templates/pr-fix-template.md",
63
+ "tools/templates/pr-merge-repair-template.md",
64
+ "tools/templates/pr-review-template.md",
65
+ "tools/templates/scheduled-issue-prompt-template.md",
43
66
  "tools/vendor/codex-quota/LICENSE",
44
67
  "tools/vendor/codex-quota/codex-quota.js",
45
68
  "tools/vendor/codex-quota/lib",
46
69
  "tools/vendor/codex-quota-manager/scripts"
47
70
  ],
48
- "scripts": {
49
- "doctor": "node ./npm/bin/agent-control-plane.js doctor",
50
- "smoke": "node ./npm/bin/agent-control-plane.js smoke",
51
- "test": "node -e \"const { spawnSync } = require('node:child_process'); const result = spawnSync('bash', ['tools/tests/run-all.sh'], { stdio: 'inherit' }); if (result.error) throw result.error; process.exit(result.status ?? 1);\""
52
- },
53
71
  "publishConfig": {
54
72
  "access": "public",
55
73
  "provenance": true
56
74
  },
57
- "keywords": [
58
- "agents",
59
- "automation",
60
- "background-jobs",
61
- "dashboard",
62
- "control-plane",
63
- "developer-tools",
64
- "github-actions",
65
- "github",
66
- "npx",
67
- "runtime"
68
- ],
69
75
  "engines": {
70
76
  "node": ">=18"
71
77
  }
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env bash
2
+ # debug-session.sh - Troubleshoot ACP worker sessions
3
+ # Usage: debug-session.sh [session-name]
4
+ # If no session name given, lists all agent- sessions with diagnostics
5
+ set -euo pipefail
6
+
7
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8
+
9
+ SESSION_NAME="${1:-}"
10
+
11
+ echo "=== ACP Session Debugger ==="
12
+ echo ""
13
+
14
+ # --- Check tmux ---
15
+ if ! command -v tmux &>/dev/null; then
16
+ echo "ERROR: tmux is not installed. Cannot debug sessions."
17
+ exit 1
18
+ fi
19
+
20
+ # --- List or Debug Specific ---
21
+ if [[ -z "${SESSION_NAME}" ]]; then
22
+ echo "--- All agent- tmux sessions ---"
23
+ tmux ls 2>/dev/null | grep "^agent-" || echo "No agent- sessions found."
24
+ echo ""
25
+ echo "Usage: $0 <session-name>"
26
+ echo " $0 agent-control-plane"
27
+ exit 0
28
+ fi
29
+
30
+ # --- Check if session exists ---
31
+ if ! tmux has-session -t "${SESSION_NAME}" 2>/dev/null; then
32
+ echo "ERROR: Session '${SESSION_NAME}' not found."
33
+ echo ""
34
+ echo "Available sessions:"
35
+ tmux ls 2>/dev/null | grep "^agent-" || echo " (none)"
36
+ exit 1
37
+ fi
38
+
39
+ echo "--- Session: ${SESSION_NAME} ---"
40
+ echo ""
41
+
42
+ # --- Session Info ---
43
+ echo "1. Session Info:"
44
+ tmux display-message -t "${SESSION_NAME}" -p "Session created: #{session_created_string}" 2>/dev/null || true
45
+ tmux display-message -t "${SESSION_NAME}" -p "Session width: #{session_width}, height: #{session_height}" 2>/dev/null || true
46
+ echo ""
47
+
48
+ # --- Pane List ---
49
+ echo "2. Panes:"
50
+ tmux list-panes -t "${SESSION_NAME}" -F " Pane #{pane_index}: pid=#{pane_pid} [#{pane_width}x#{pane_height}] #{?pane_active,(active),}"
51
+ echo ""
52
+
53
+ # --- Recent Output (last 50 lines) ---
54
+ echo "3. Recent Output (last 50 lines):"
55
+ echo "--- START ---"
56
+ tmux capture-pane -t "${SESSION_NAME}" -p -S -50 2>/dev/null || echo "(no output captured)"
57
+ echo "--- END ---"
58
+ echo ""
59
+
60
+ # --- Process Tree ---
61
+ echo "4. Process Tree:"
62
+ PANE_PID=$(tmux display-message -t "${SESSION_NAME}" -p "#{pane_pid}" 2>/dev/null || echo "")
63
+ if [[ -n "${PANE_PID}" ]]; then
64
+ if command -v pstree &>/dev/null; then
65
+ pstree -p "${PANE_PID}" 2>/dev/null || ps -p "${PANE_PID}" -o pid,ppid,cmd 2>/dev/null || echo "(cannot inspect process)"
66
+ else
67
+ ps -p "${PANE_PID}" -o pid,ppid,cmd 2>/dev/null || echo "(cannot inspect process)"
68
+ fi
69
+ else
70
+ echo "(cannot get pane pid)"
71
+ fi
72
+ echo ""
73
+
74
+ # --- Check for Common Issues ---
75
+ echo "5. Diagnostics:"
76
+ CAPTURE=$(tmux capture-pane -t "${SESSION_NAME}" -p -S -100 2>/dev/null || echo "")
77
+
78
+ # Check for errors
79
+ ERROR_COUNT=$(echo "${CAPTURE}" | grep -ic "error\|fail\|fatal\|exception" || true)
80
+ echo " Error-like lines in last 100: ${ERROR_COUNT}"
81
+
82
+ # Check for stalls (no output for a while)
83
+ if echo "${CAPTURE}" | tail -10 | grep -q "."; then
84
+ echo " Recent output: yes"
85
+ else
86
+ echo " Recent output: NO (may be stalled)"
87
+ fi
88
+
89
+ # Check for specific worker patterns
90
+ if echo "${CAPTURE}" | grep -q "streaming\|tool_use\|thinking"; then
91
+ echo " Worker activity: active (streaming/tool_use detected)"
92
+ elif echo "${CAPTURE}" | grep -q "IDLE\|waiting\|queue"; then
93
+ echo " Worker activity: idle/waiting"
94
+ else
95
+ echo " Worker activity: unknown"
96
+ fi
97
+ echo ""
98
+
99
+ # --- Offer Actions ---
100
+ echo "6. Quick Actions:"
101
+ echo " Attach: tmux attach -t ${SESSION_NAME}"
102
+ echo " Kill: tmux kill-session -t ${SESSION_NAME}"
103
+ echo " Capture: tmux capture-pane -t ${SESSION_NAME} -p > output.txt"
104
+ echo ""
105
+
106
+ echo "=== Debug Complete ==="
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env bash
2
+ # flow-runtime-doctor-linux.sh - Linux-specific runtime validation for ACP
3
+ # Checks systemd services, Linux paths, and runtime health
4
+ set -euo pipefail
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ # shellcheck source=/dev/null
8
+ source "${SCRIPT_DIR}/flow-config-lib.sh"
9
+
10
+ FLOW_SKILL_DIR="$(resolve_flow_skill_dir "${BASH_SOURCE[0]}")"
11
+ CONTROL_PLANE_NAME="$(flow_canonical_skill_name)"
12
+ RUNTIME_HOME="$(resolve_runtime_home)"
13
+
14
+ echo "=== ACP Linux Runtime Doctor ==="
15
+ echo ""
16
+
17
+ # --- Systemd Checks ---
18
+ echo "--- Systemd Service Status ---"
19
+ if command -v systemctl &>/dev/null; then
20
+ echo "systemctl: available"
21
+
22
+ # Check user services (systemd --user)
23
+ if systemctl --user is-active --quiet "${CONTROL_PLANE_NAME}.service" 2>/dev/null; then
24
+ echo "service ${CONTROL_PLANE_NAME}: active (user)"
25
+ elif systemctl --user is-enabled --quiet "${CONTROL_PLANE_NAME}.service" 2>/dev/null; then
26
+ echo "service ${CONTROL_PLANE_NAME}: installed but not running (user)"
27
+ else
28
+ echo "service ${CONTROL_PLANE_NAME}: not installed (user)"
29
+ fi
30
+
31
+ # Check system services (if installed system-wide)
32
+ if systemctl is-active --quiet "${CONTROL_PLANE_NAME}.service" 2>/dev/null; then
33
+ echo "service ${CONTROL_PLANE_NAME}: active (system)"
34
+ fi
35
+ else
36
+ echo "systemctl: NOT available (not a systemd-based system?)"
37
+ fi
38
+ echo ""
39
+
40
+ # --- Linux Path Checks ---
41
+ echo "--- Linux Path Validation ---"
42
+ echo "RUNTIME_HOME=${RUNTIME_HOME}"
43
+ echo "FLOW_SKILL_DIR=${FLOW_SKILL_DIR}"
44
+
45
+ # Check XDG paths (Linux standard)
46
+ XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
47
+ XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
48
+
49
+ echo "XDG_CONFIG_HOME=${XDG_CONFIG_HOME}"
50
+ echo "XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR}"
51
+
52
+ if [[ -d "${XDG_RUNTIME_DIR}" ]]; then
53
+ echo "XDG_RUNTIME_DIR: exists"
54
+ else
55
+ echo "XDG_RUNTIME_DIR: NOT FOUND (may cause issues with user services)"
56
+ fi
57
+ echo ""
58
+
59
+ # --- Process Checks ---
60
+ echo "--- Process Checks ---"
61
+ if command -v pgrep &>/dev/null; then
62
+ AGENT_PIDS=$(pgrep -f "agent-control-plane" 2>/dev/null || true)
63
+ if [[ -n "${AGENT_PIDS}" ]]; then
64
+ echo "agent-control-plane processes running: yes (PIDs: ${AGENT_PIDS})"
65
+ ps -p "${AGENT_PIDS}" -o pid,ppid,cmd 2>/dev/null || true
66
+ else
67
+ echo "agent-control-plane processes running: no"
68
+ fi
69
+ else
70
+ echo "pgrep: NOT available"
71
+ fi
72
+ echo ""
73
+
74
+ # --- tmux Checks ---
75
+ echo "--- tmux Session Checks ---"
76
+ if command -v tmux &>/dev/null; then
77
+ echo "tmux: available ($(tmux -V))"
78
+ TMUX_SESSIONS=$(tmux ls 2>/dev/null | grep -c "agent-" || true)
79
+ echo "agent- tmux sessions: ${TMUX_SESSIONS}"
80
+ if [[ ${TMUX_SESSIONS} -gt 0 ]]; then
81
+ tmux ls 2>/dev/null | grep "agent-" || true
82
+ fi
83
+ else
84
+ echo "tmux: NOT installed (required for ACP worker sessions)"
85
+ fi
86
+ echo ""
87
+
88
+ # --- Socket/Port Checks ---
89
+ echo "--- Socket/Port Checks ---"
90
+ if command -v ss &>/dev/null; then
91
+ echo "Checking for dashboard port (3180)..."
92
+ ss -tlnp 2>/dev/null | grep ":3180 " || echo "Port 3180: not in use"
93
+ elif command -v netstat &>/dev/null; then
94
+ netstat -tlnp 2>/dev/null | grep ":3180 " || echo "Port 3180: not in use"
95
+ else
96
+ echo "ss/netstat: NOT available, skipping port check"
97
+ fi
98
+ echo ""
99
+
100
+ # --- Log File Checks ---
101
+ echo "--- Log File Checks ---"
102
+ LOG_DIR="${RUNTIME_HOME}/logs"
103
+ if [[ -d "${LOG_DIR}" ]]; then
104
+ echo "LOG_DIR=${LOG_DIR}: exists"
105
+ LOG_COUNT=$(find "${LOG_DIR}" -name "*.log" 2>/dev/null | wc -l)
106
+ echo "Log files: ${LOG_COUNT}"
107
+ else
108
+ echo "LOG_DIR=${LOG_DIR}: NOT FOUND"
109
+ fi
110
+ echo ""
111
+
112
+ # --- Run Generic Doctor ---
113
+ echo "=== Generic Runtime Doctor ==="
114
+ if [[ -f "${SCRIPT_DIR}/flow-runtime-doctor.sh" ]]; then
115
+ bash "${SCRIPT_DIR}/flow-runtime-doctor.sh"
116
+ else
117
+ echo "flow-runtime-doctor.sh: NOT FOUND"
118
+ fi
119
+
120
+ echo ""
121
+ echo "=== Linux Doctor Complete ==="
122
+ echo ""
123
+ echo "=== NEXT STEPS ==="
124
+ if ! command -v systemctl &>/dev/null; then
125
+ echo "NOT on systemd: Use macOS launchd or manual tmux for runtime."
126
+ elif ! systemctl --user is-active --quiet "${CONTROL_PLANE_NAME}.service" 2>/dev/null; then
127
+ echo "Service not running. Start with:"
128
+ echo " systemctl --user start ${CONTROL_PLANE_NAME}.service"
129
+ echo " systemctl --user enable ${CONTROL_PLANE_NAME}.service # autostart"
130
+ fi
131
+
132
+ if ! command -v tmux &>/dev/null; then
133
+ echo "MISSING: tmux is required. Install:"
134
+ echo " Ubuntu/Debian: sudo apt install tmux"
135
+ echo " Alpine: apk add tmux"
136
+ fi
@@ -93,5 +93,9 @@ if [[ -n "${PROFILE_SELECTION_HINT}" ]]; then
93
93
  fi
94
94
 
95
95
  if [[ "${status}" != "ok" ]]; then
96
- printf 'NEXT_STEP=bash %q %q %q\n' "${SYNC_SCRIPT}" "${SHARED_AGENT_HOME}" "${RUNTIME_HOME}"
96
+ printf '\n=== ACTION REQUIRED ===\n'
97
+ printf 'Status: %s\n' "${status}"
98
+ printf 'Next step: Run sync to fix issues:\n'
99
+ printf ' bash %q %q %q\n' "${SYNC_SCRIPT}" "${SHARED_AGENT_HOME}" "${RUNTIME_HOME}"
100
+ printf '\nOr run: bash %s/tools/bin/setup.sh --resume\n' "${FLOW_SKILL_DIR}"
97
101
  fi