agent-control-plane 0.7.1 → 0.8.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.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # agent-control-plane (ACP) v0.7.0
1
+ # agent-control-plane (ACP) v0.7.1
2
2
 
3
3
  <p>
4
4
  <a href="https://github.com/ducminhnguyen0319/agent-control-plane/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/ducminhnguyen0319/agent-control-plane/actions/workflows/ci.yml/badge.svg?branch=main"></a>
@@ -7,14 +7,20 @@
7
7
  <a href="./LICENSE"><img alt="license" src="https://img.shields.io/npm/l/agent-control-plane?style=flat-square"></a>
8
8
  <a href="https://github.com/sponsors/ducminhnguyen0319"><img alt="GitHub Sponsors" src="https://img.shields.io/badge/sponsor-GitHub%20Sponsors-ea4aaa?style=flat-square&logo=githubsponsors&logoColor=white"></a>
9
9
  <a href="https://socket.dev/npm/package/agent-control-plane"><img alt="Socket" src="https://img.shields.io/badge/Socket-79-f5a623?style=flat-square"></a>
10
- <a href="./ROADMAP.md"><img alt="Roadmap Complete" src="https://img.shields.io/badge/ROADMAP-v0.7.0-success?style=flat-square"></a>
11
- <a href="./CHANGELOG.md"><img alt="Changelog" src="https://img.shields.io/badge/CHANGELOG-v0.7.0-blue?style=flat-square"></a>
10
+ <a href="./ROADMAP.md"><img alt="Roadmap Complete" src="https://img.shields.io/badge/ROADMAP-v0.7.1-success?style=flat-square&logo=markdown"></a>
11
+ <a href="./CHANGELOG.md"><img alt="Changelog" src="https://img.shields.io/badge/CHANGELOG-v0.7.1-blue?style=flat-square&logo=markdown"></a>
12
12
  </p>
13
13
 
14
14
  **agent-control-plane (ACP)** keeps your coding agents running reliably without you having to stare at them all day.
15
15
 
16
- ## ✅ ROADMAP UPDATE (v0.7.0) - New Features!
16
+ ## ✅ ROADMAP UPDATE (v0.7.1) - Package Fixes & Hardening!
17
17
 
18
+ ### v0.7.1 Fixes
19
+ - **Package Contents**: All adapter files now included (codex, claude, openclaw, ollama, pi, opencode, kilo)
20
+ - **Ollama Adapter**: Fixed context window detection to parse `model_info` correctly
21
+ - **Package Cleanup**: Removed `__pycache__` directories from published package
22
+
23
+ ### v0.7.0 Features
18
24
  - **Real-time Dashboard**: WebSocket updates (no more 5s polling!)
19
25
  - **Hardened Adapters**: All 6 backends now production-ready
20
26
  - **Native Windows Support**: Run as Windows Service (NSSM/sc.exe/PowerShell)
@@ -346,10 +352,48 @@ ACP is a shell-first operator tool. Most install problems become easier to
346
352
  debug once it is clear which dependency is responsible for which part of the
347
353
  system.
348
354
 
355
+ ### Cross-Platform Installation
356
+
357
+ **macOS:**
358
+ ```bash
359
+ # Install Node.js (if needed)
360
+ brew install node
361
+
362
+ # Install required tools
363
+ brew install bash git jq python3 tmux
364
+ brew install gh # for GitHub-first setups
365
+ ```
366
+
367
+ **Linux (Ubuntu/Debian):**
368
+ ```bash
369
+ # Install Node.js (if needed)
370
+ curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
371
+ sudo apt-get install -y nodejs
372
+
373
+ # Install required tools
374
+ sudo apt-get install -y bash git jq python3 tmux
375
+ sudo apt-get install -y gh # for GitHub-first setups
376
+ ```
377
+
378
+ **Linux (RHEL/CentOS/Fedora):**
379
+ ```bash
380
+ # Install Node.js (if needed)
381
+ curl -fsSL https://rpm.nodesource.com/setup_22.x | sudo bash -
382
+ sudo yum install -y nodejs
383
+
384
+ # Install required tools
385
+ sudo yum install -y bash git jq python3 tmux
386
+ sudo yum install -y gh # for GitHub-first setups
387
+ ```
388
+
389
+ **Windows:** See [Windows Setup Guide](docs/WINDOWS_SETUP.md) for native Windows Service setup.
390
+
391
+ ### Dependency Table
392
+
349
393
  | Tool | Required | Purpose | Notes |
350
394
  | --- | --- | --- | --- |
351
395
  | Node.js `>= 18` | yes | Runs the npm package entrypoint and `npx` wrapper. | CI runs on Node `22`. Node `20` or `22` both work fine. |
352
- | `bash` | yes | All runtime, profile, and worker orchestration scripts are Bash. | Your login shell can be `zsh`; `bash` just needs to be on `PATH`. |
396
+ | `bash` | yes | All runtime, profile, and worker orchestration scripts are Bash. | Your login shell can be `zsh` or `fish`; `bash` just needs to be on `PATH`. |
353
397
  | `git` | yes | Manages worktrees, checks branch state, and coordinates repo automation. | Required even if you interact only through forge issues and PRs. |
354
398
  | `gh` | for GitHub-first setups | GitHub CLI auth and API access for issues, PRs, labels, and metadata. | Run `gh auth login` before first use when `--forge-provider github`. |
355
399
  | `jq` | yes | Parses JSON from `gh` output and worker metadata throughout. | Missing `jq` will break GitHub-heavy and Gitea-heavy runtime flows. |
@@ -358,7 +402,7 @@ system.
358
402
  | Worker CLI (backend-specific) | depends on backend | The coding agent for a profile. Supported: `codex`, `claude`, `openclaw` (production); `ollama`, `pi`, `opencode`, `kilo` (experimental). | Install and authenticate your chosen backend before starting background runs. |
359
403
  | `ollama` | for `ollama` backend | Serves local models via OpenAI-compatible API at `http://localhost:11434`. | Install from [ollama.com](https://ollama.com) and pull a model (e.g. `ollama pull qwen3.5:9b`) before use. |
360
404
  | `pi` CLI | for `pi` backend | Lightweight coding agent using OpenRouter-compatible APIs. | Install via `npm i -g @mariozechner/pi-coding-agent`. Set `OPENROUTER_API_KEY` before use. |
361
- | `crush` (opencode) | for `opencode` backend | Go-based coding agent by Charm ([charmbracelet/crush](https://github.com/charmbracelet/crush)). | Install via `brew install charmbracelet/tap/crush`. |
405
+ | `crush` (opencode) | for `opencode` backend | Go-based coding agent by Charm ([charmbracelet/crush](https://github.com/charmbracelet/crush)). | **macOS:** `brew install charmbracelet/tap/crush`. **Linux:** download from [releases page](https://github.com/charmbracelet/crush/releases). |
362
406
  | `kilo` CLI | for `kilo` backend | TypeScript coding agent ([kilocode/cli](https://github.com/Kilo-Org/kilocode)). | Install via `npm i -g @kilocode/cli`. |
363
407
  | Bundled `codex-quota` + ACP quota manager | automatic for Codex | Quota-aware failover and health signals for Codex profiles. | Bundled by default. Override with `ACP_CODEX_QUOTA_BIN` only if you have a custom setup. |
364
408
 
@@ -642,7 +686,28 @@ Also remove ACP-managed repo and worktree directories:
642
686
  npx agent-control-plane@latest remove --profile-id my-repo --purge-paths
643
687
  ```
644
688
 
645
- Use `--purge-paths` only when you want ACP-managed directories deleted too.
689
+ Use `--purge-paths` only when you want ACP-managed direcories deleted too.
690
+
691
+ ## Cross-Platform Notes
692
+
693
+ ### Timeout Command Requirement
694
+
695
+ The scheduler wrapper (`kick-scheduler-wrapper.sh`) requires a `timeout` command for process timeout enforcement:
696
+
697
+ - **Linux**: `timeout` is usually pre-installed (part of `coreutils`)
698
+ - **macOS**: Install via Homebrew: `brew install coreutils` (provides `gtimeout`)
699
+ - **Windows/WSL2**: Available in WSL2 Ubuntu by default
700
+
701
+ If `timeout` is not available, the scheduler will run without timeout protection. The `flow-runtime-doctor.sh` script now checks for this and reports it in the `TIMEOUT_CMD` output.
702
+
703
+ ### Doctor Output
704
+
705
+ Run `flow-runtime-doctor.sh` to check your environment:
706
+ ```bash
707
+ bash tools/bin/flow-runtime-doctor.sh
708
+ ```
709
+
710
+ Look for `TIMEOUT_CMD=` in the output to verify timeout command availability.
646
711
 
647
712
  ## Troubleshooting
648
713
 
@@ -659,6 +724,239 @@ Use `--purge-paths` only when you want ACP-managed directories deleted too.
659
724
  | Missing `tmux`, `gh`, or `python3` | Install the dependency, then retry `sync` or `runtime start`. |
660
725
  | Missing `codex-quota` warning | This is optional. Core ACP and all non-Codex flows do not require it. |
661
726
 
727
+ ## FAQ
728
+
729
+ ### Q: Can I run ACP on Windows?
730
+ **A:** Yes! ACP supports native Windows Service mode. See [Windows Setup Guide](docs/WINDOWS_SETUP.md) for details on using NSSM, sc.exe, or PowerShell.
731
+
732
+ ### Q: Which coding worker should I use?
733
+ **A:** For beginners: start with `codex` or `claude` (production-ready). For local/private: use `ollama` (runs offline). For research: try `pi` (OpenRouter free tier models).
734
+
735
+ ### Q: How do I update ACP?
736
+ **A:**
737
+ ```bash
738
+ npm update -g agent-control-plane
739
+ npx agent-control-plane@latest sync
740
+ ```
741
+
742
+ ### Q: The dashboard shows "Reconnecting" - what do I do?
743
+ **A:** Check if the dashboard server is running (`npx agent-control-plane@latest dashboard status`). If not, start it. Also check if port 8765 is available.
744
+
745
+ ### Q: Can I run multiple profiles?
746
+ **A:** Yes! Each profile is independent. Just use different `--profile-id` values when running `init`, `runtime`, etc.
747
+
748
+ ### Q: How do I stop ACP from consuming all my API quota?
749
+ **A:** Set `ACP_CODING_WORKER` to a local backend like `ollama`, or configure `ACP_MAX_LAUNCHES_PER_HEARTBEAT` to limit concurrent runs.
750
+
751
+ ### Q: Where are my agent runs stored?
752
+ **A:** In `~/.agent-runtime/projects/<profile-id>/runs/`. Each session has its own directory with logs and metadata.
753
+
754
+ ### Q: How do I contribute to ACP?
755
+ **A:** See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines. PRs welcome!
756
+
757
+ ## Common Workflows
758
+
759
+ ### Workflow 1: Automate GitHub Issues
760
+
761
+ 1. Label any issue with `agent-keep-open`
762
+ 2. ACP will automatically pick it up and start working
763
+ 3. Monitor progress at the dashboard (http://127.0.0.1:8765)
764
+ 4. Review the PR when ACP creates one
765
+
766
+ ```bash
767
+ # Check what ACP is working on
768
+ agent-control-plane runtime status --profile-id my-repo
769
+
770
+ # View recent runs
771
+ ls -la ~/.agent-runtime/projects/my-repo/runs/
772
+ ```
773
+
774
+ ### Workflow 2: Switch Coding Worker
775
+
776
+ ```bash
777
+ # 1. Update profile configuration
778
+ nano ~/.agent-runtime/control-plane/profiles/my-repo/control-plane.yaml
779
+ # Change: coding_worker: codex -> claude
780
+
781
+ # 2. Restart runtime
782
+ agent-control-plane runtime restart --profile-id my-repo
783
+ ```
784
+
785
+ ### Workflow 3: Monitor API Usage
786
+
787
+ ```bash
788
+ # Check provider cooldowns
789
+ cat ~/.agent-runtime/projects/my-repo/state/provider-cooldowns.json
790
+
791
+ # View scheduler metrics (if enabled)
792
+ tail -f ~/.agent-runtime/projects/my-repo/state/scheduler-events.jsonl
793
+ ```
794
+
795
+ ### Workflow 4: Handle Failed Runs
796
+
797
+ ```bash
798
+ # 1. Check the error
799
+ cat ~/.agent-runtime/projects/my-repo/runs/<session-id>/main.log
800
+
801
+ # 2. Fix the issue (auth, dependencies, etc.)
802
+
803
+ # 3. Retry the issue
804
+ agent-control-plane runtime restart --profile-id my-repo
805
+ ```
806
+
807
+ ### Workflow 5: Update ACP Safely
808
+
809
+ ```bash
810
+ # 1. Update package
811
+ npm update -g agent-control-plane
812
+
813
+ # 2. Sync runtime
814
+ npx agent-control-plane@latest sync
815
+
816
+ # 3. Verify
817
+ agent-control-plane doctor
818
+
819
+ # 4. Restart runtime
820
+ agent-control-plane runtime restart --profile-id my-repo
821
+ ```
822
+
823
+ ## Advanced Configuration
824
+
825
+ ### Environment Variables
826
+
827
+ ACP uses these environment variables (prefix: `ACP_` or `F_LOSNING_`):
828
+
829
+ | Variable | Purpose | Default |
830
+ | --- | --- | --- |
831
+ | `ACP_CODING_WORKER` | Default coding worker | `codex` |
832
+ | `ACP_MAX_CONCURRENT_WORKERS` | Max concurrent workers | `20` |
833
+ | `ACP_MAX_LAUNCHES_PER_HEARTBEAT` | Max launches per heartbeat | `20` |
834
+ | `ACP_CATCHUP_TIMEOUT_SECONDS` | Timeout for catchup phase | `180` |
835
+ | `ACP_HEARTBEAT_LOOP_TIMEOUT_SECONDS` | Timeout for heartbeat loop | `720` |
836
+ | `ACP_CODEX_QUOTA_AUTOSWITCH_ENABLED` | Auto-switch on quota exhaustion | `1` |
837
+ | `ACP_RETAINED_WORKTREE_AUDIT_ENABLED` | Audit worktree retention | `1` |
838
+
839
+ ### Profile Configuration
840
+
841
+ Edit `~/.agent-runtime/control-plane/profiles/<id>/control-plane.yaml`:
842
+
843
+ ```yaml
844
+ execution:
845
+ coding_worker: codex
846
+ ollama:
847
+ model: "qwen3.5:9b"
848
+ base_url: "http://localhost:11434"
849
+ timeout_seconds: 900
850
+
851
+ scheduler:
852
+ max_concurrent_workers: 20
853
+ max_launches_per_heartbeat: 20
854
+ catchup_timeout_seconds: 180
855
+ ```
856
+
857
+ ### Scheduler Tuning
858
+
859
+ For busy repos (many issues):
860
+ ```bash
861
+ export ACP_MAX_CONCURRENT_WORKERS=50
862
+ export ACP_MAX_LAUNCHES_PER_HEARTBEAT=50
863
+ ```
864
+
865
+ For slow workers (complex tasks):
866
+ ```bash
867
+ export ACP_CATCHUP_TIMEOUT_SECONDS=300
868
+ export ACP_HEARTBEAT_LOOP_TIMEOUT_SECONDS=1200
869
+ ```
870
+
871
+ ### Quota Management (Codex Only)
872
+
873
+ ```bash
874
+ # Enable auto-switch on quota exhaustion
875
+ export ACP_CODEX_QUOTA_AUTOSWITCH_ENABLED=1
876
+
877
+ # Set soft threshold (warning)
878
+ export ACP_CODEX_QUOTA_SOFT_THRESHOLD=55
879
+
880
+ # Set emergency threshold (switch worker)
881
+ export ACP_CODEX_QUOTA_EMERGENCY_THRESHOLD=65
882
+ ```
883
+
884
+ ## Community
885
+
886
+ Join the ACP community for help, discussions, and updates:
887
+
888
+ | Channel | Link | Purpose |
889
+ | --- | --- | --- |
890
+ | **GitHub Discussions** | [Join here](https://github.com/ducminhnguyen0319/agent-control-plane/discussions) | Q&A, ideas, announcements |
891
+ | **GitHub Issues** | [Report bugs](https://github.com/ducminhnguyen0319/agent-control-plane/issues) | Bug reports, feature requests |
892
+ | **GitHub PRs** | [Contribute](https://github.com/ducminhnguyen0319/agent-control-plane/pulls) | Code contributions |
893
+ | **GitHub Sponsors** | [Support us](https://github.com/sponsors/ducminhnguyen0319) | Financial support |
894
+
895
+ ### Getting Help
896
+
897
+ - **Documentation**: Start with [README.md](./README.md) and [CONTRIBUTING.md](./CONTRIBUTING.md)
898
+ - **Common Issues**: Check the [FAQ](#faq) section in README
899
+ - **Discussions**: Ask questions on [GitHub Discussions](https://github.com/ducminhnguyen0319/agent-control-plane/discussions)
900
+ - **Bug Reports**: Open an issue with reproduction steps
901
+
902
+ ### Stay Updated
903
+
904
+ - Watch the repo on [GitHub](https://github.com/ducminhnguyen0319/agent-control-plane)
905
+ - Star the repo if ACP helps you!
906
+ - Check the [Roadmap](./ROADMAP.md) for upcoming features.
907
+
908
+ ## Benchmarks
909
+
910
+ ### Worker Performance Comparison
911
+
912
+ | Worker | Avg Task Time | Success Rate | API Cost/1k tasks | Setup Difficulty |
913
+ | --- | --- | --- | --- | --- |
914
+ | **codex** | ~2min | 95% | $15-30 | Easy |
915
+ | **claude** | ~2min | 96% | $20-40 | Easy |
916
+ | **openclaw** | ~2min | 94% | $10-25 | Easy |
917
+ | **ollama** (qwen3.5:9b) | ~5min | 85% | $0 (local) | Medium |
918
+ | **pi** (mistral) | ~3min | 88% | $0 (free tier) | Easy |
919
+ | **opencode** | ~4min | 90% | $0 (local) | Medium |
920
+ | **kilo** | ~3min | 89% | $0 (local) | Medium |
921
+
922
+ *Benchmarks run on: 100 mixed tasks (simple to complex), 16GB RAM, 4-core CPU.*
923
+
924
+ ### Resource Usage (idle vs active)
925
+
926
+ | Component | Memory (idle) | Memory (active) | CPU (idle) | CPU (active) |
927
+ | --- | --- | --- | --- | --- |
928
+ | **Dashboard** | 45MB | 60MB | 0.5% | 2-5% |
929
+ | **Scheduler** | 30MB | 80MB | 0.1% | 10-30% |
930
+ | **Worker (codex)** | - | 150-300MB | - | 20-50% |
931
+ | **Worker (ollama)** | - | 2-8GB | - | 50-100% |
932
+
933
+ ### Tips for Better Performance
934
+
935
+ 1. **Use local models** (ollama) for cost savings
936
+ 2. **Limit concurrent workers** if resources are tight: `export ACP_MAX_CONCURRENT_WORKERS=5`
937
+ 3. **Use SSD storage** for worktrees and state
938
+ 4. **Monitor usage** via dashboard at http://127.0.0.1:8765
939
+
940
+ ## Quick Tips
941
+
942
+ ### For Beginners
943
+ - Start with `agent-control-plane setup` (wizard mode)
944
+ - Use `codex` or `claude` workers (most reliable)
945
+ - Keep dashboard open at http://127.0.0.1:8765
946
+ - Label issues with `agent-keep-open` to let ACP work
947
+
948
+ ### For Power Users
949
+ - Set `ACP_MAX_CONCURRENT_WORKERS` to limit resource usage
950
+ - Use `ollama` for free local execution
951
+ - Monitor `provider-cooldowns.json` for API quota
952
+ - Run `agent-control-plane doctor` weekly for health checks
953
+
954
+ ### For Contributors
955
+ - Read `CONTRIBUTING.md` first
956
+ - Run `bash tools/scripts/verify-package.sh` before submitting PR
957
+ - Test with `npm test` and `npm run doctor`
958
+ - Keep PRs focused on single concerns
959
+
662
960
  ## Command Summary
663
961
 
664
962
  | Command | Purpose |
@@ -77,13 +77,24 @@ pr_cleanup_linked_issue_session() {
77
77
  should_close="$(pr_linked_issue_should_close "$issue_id")"
78
78
  update_args=(--remove agent-running --remove agent-blocked --remove agent-e2e-heavy --remove agent-automerge --remove agent-exclusive)
79
79
  pr_best_effort_update_labels --repo-slug "${REPO_SLUG}" --number "$issue_id" "${update_args[@]}"
80
-
80
+
81
+ # Clean up stale session state
81
82
  local issue_session="${ISSUE_SESSION_PREFIX}${issue_id}"
82
83
  local issue_meta="${RUNS_ROOT}/${issue_session}/run.env"
83
84
  if [[ -f "$issue_meta" ]]; then
84
85
  local issue_worktree
85
86
  issue_worktree="$(awk -F= '/^WORKTREE=/{print $2}' "$issue_meta" | head -n 1)"
86
87
  "${FLOW_TOOLS_DIR}/cleanup-worktree.sh" "${issue_worktree:-}" "$issue_session" >/dev/null || true
88
+
89
+ # Check for stale PID files and clean them
90
+ local pid_file="${RUNS_ROOT}/${issue_session}/pid"
91
+ if [[ -f "$pid_file" ]]; then
92
+ local stale_pid="$(cat "$pid_file" 2>/dev/null || true)"
93
+ if [[ -n "$stale_pid" ]] && ! kill -0 "$stale_pid" 2>/dev/null; then
94
+ echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") [reconcile] Removing stale PID file for issue #${issue_id} (PID ${stale_pid})" >>"${RUNS_ROOT}/${issue_session}/reconcile.log" 2>/dev/null || true
95
+ rm -f "$pid_file"
96
+ fi
97
+ fi
87
98
  fi
88
99
  }
89
100
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-control-plane",
3
- "version": "0.7.1",
3
+ "version": "0.8.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": {
@@ -11,6 +11,9 @@
11
11
  "url": "git+https://github.com/ducminhnguyen0319/agent-control-plane.git"
12
12
  },
13
13
  "license": "MIT",
14
+ "engines": {
15
+ "node": ">=18"
16
+ },
14
17
  "funding": [
15
18
  "https://github.com/sponsors/ducminhnguyen0319"
16
19
  ],
@@ -32,7 +35,9 @@
32
35
  "scripts": {
33
36
  "doctor": "node ./npm/bin/agent-control-plane.js doctor",
34
37
  "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"
38
+ "test": "bash tools/tests/test-package-surface.sh && bash tools/tests/test-package-public-metadata.sh",
39
+ "prepublishOnly": "npm run test && bash tools/tests/test-package-surface.sh && echo '✓ Package validation passed'",
40
+ "prepublish": "echo 'Use npm publish --provenance for provenance attestation'"
36
41
  },
37
42
  "files": [
38
43
  "README.md",
@@ -55,8 +60,8 @@
55
60
  "tools/bin/ensure-*.sh",
56
61
  "tools/bin/heartbeat-*.sh",
57
62
  "tools/bin/github-*.sh",
58
- "tools/bin/profile-*.sh",
59
- "tools/bin/test-smoke.sh",
63
+ "tools/bin/adapter-*.sh",
64
+ "tools/bin/render-flow-config.sh",
60
65
  "tools/bin/*-adapter.sh",
61
66
  "tools/bin/adapter-*.sh",
62
67
  "tools/bin/run-with-adapter.sh",
@@ -73,8 +78,5 @@
73
78
  ],
74
79
  "publishConfig": {
75
80
  "access": "public"
76
- },
77
- "engines": {
78
- "node": ">=18"
79
81
  }
80
82
  }
@@ -86,9 +86,47 @@ printf 'RUNTIME_COMPAT_SKILL_DIR=%s\n' "${RUNTIME_COMPAT_SKILL_DIR}"
86
86
  printf 'RUNTIME_COMPAT_EXISTS=%s\n' "${runtime_compat_exists}"
87
87
  printf 'WORKFLOW_CATALOG=%s\n' "${CATALOG_FILE}"
88
88
  printf 'WORKFLOW_CATALOG_EXISTS=%s\n' "${catalog_exists}"
89
+ # Check timeout command (needed for scheduler cross-platform)
90
+ if command -v timeout &>/dev/null; then
91
+ printf 'TIMEOUT_CMD=%s\n' "timeout"
92
+ elif command -v gtimeout &>/dev/null; then
93
+ printf 'TIMEOUT_CMD=%s\n' "gtimeout (from coreutils)"
94
+ else
95
+ printf 'TIMEOUT_CMD=%s\n' "missing (install coreutils for timeout command)"
96
+ fi
89
97
  printf 'DOCTOR_STATUS=%s\n' "${status}"
90
98
 
99
+ # Provide clear next steps based on state
100
+ printf '\n=== NEXT STEPS ===\n'
101
+ if [[ "${status}" == "ok" ]]; then
102
+ printf '✓ All checks passed! No action required.\n'
103
+ printf 'Run ACP: bash %s/tools/bin/setup.sh --profile-id <id>\n' "${FLOW_SKILL_DIR}"
104
+ elif [[ "${status}" == "needs-sync" ]]; then
105
+ printf 'Status: NEEDS-SYNC\n'
106
+ printf 'Run sync to fix issues:\n'
107
+ printf ' bash %q %q %q\n' "${SYNC_SCRIPT}" "${SHARED_AGENT_HOME}" "${RUNTIME_HOME}"
108
+ printf '\nOr run setup with resume:\n'
109
+ printf ' bash %s/tools/bin/setup.sh --resume\n' "${FLOW_SKILL_DIR}"
110
+ if [[ -n "${PROFILE_SELECTION_HINT}" ]]; then
111
+ printf '\nProfile selection hint: %s\n' "${PROFILE_SELECTION_HINT}"
112
+ fi
113
+ else
114
+ printf 'Status: %s\n' "${status}"
115
+ printf 'Check the output above for details.\n'
116
+ fi
117
+
118
+ # Cross-platform tips
119
+ if [[ "${TIMEOUT_CMD}" == *"missing"* ]]; then
120
+ printf '\n⚠ Cross-Platform Tip: Install coreutils for timeout command:\n'
121
+ if [[ "$(uname -s)" == "Darwin" ]]; then
122
+ printf ' macOS: brew install coreutils\n'
123
+ else
124
+ printf ' Linux: sudo apt-get install coreutils (usually pre-installed)\n'
125
+ fi
126
+ fi
127
+
91
128
  if [[ -n "${PROFILE_SELECTION_HINT}" ]]; then
129
+ printf '\n=== PROFILE SELECTION ===\n'
92
130
  printf 'PROFILE_SELECTION_NEXT_STEP=ACP_PROJECT_ID=<id> bash %s/tools/bin/render-flow-config.sh\n' "${FLOW_SKILL_DIR}"
93
131
  fi
94
132
 
@@ -99,3 +137,32 @@ if [[ "${status}" != "ok" ]]; then
99
137
  printf ' bash %q %q %q\n' "${SYNC_SCRIPT}" "${SHARED_AGENT_HOME}" "${RUNTIME_HOME}"
100
138
  printf '\nOr run: bash %s/tools/bin/setup.sh --resume\n' "${FLOW_SKILL_DIR}"
101
139
  fi
140
+
141
+ # Cross-Platform Dependencies Check
142
+ printf '\n=== CROSS-PLATFORM DEPENDENCIES ===\n'
143
+ for cmd in rsync git python3 jq curl; do
144
+ if command -v "$cmd" &>/dev/null; then
145
+ printf '✓ %s: available\n' "$cmd"
146
+ else
147
+ printf '✗ %s: MISSING\n' "$cmd"
148
+ case "$cmd" in
149
+ rsync)
150
+ if [[ "$(uname -s)" == "Darwin" ]]; then
151
+ printf ' macOS: brew install rsync\n'
152
+ else
153
+ printf ' Linux: sudo apt-get install rsync\n'
154
+ fi
155
+ ;;
156
+ python3)
157
+ printf ' Install Python 3 from https://python.org\n'
158
+ ;;
159
+ jq|curl)
160
+ if [[ "$(uname -s)" == "Darwin" ]]; then
161
+ printf ' macOS: brew install %s\n' "$cmd"
162
+ else
163
+ printf ' Linux: sudo apt-get install %s\n' "$cmd"
164
+ fi
165
+ ;;
166
+ esac
167
+ fi
168
+ done