agent-control-plane 0.1.2 → 0.1.4

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 (182) hide show
  1. package/README.md +6 -0
  2. package/npm/bin/agent-control-plane.js +149 -5
  3. package/package.json +1 -2
  4. package/tools/bin/render-architecture-infographics.sh +0 -110
  5. package/tools/bin/render-dashboard-demo-media.sh +0 -333
  6. package/tools/tests/test-agent-control-plane-npm-cli.sh +0 -280
  7. package/tools/tests/test-agent-github-update-labels-falls-back-to-repository-id.sh +0 -56
  8. package/tools/tests/test-agent-project-claude-session-wrapper-clears-stale-sandbox-artifacts.sh +0 -89
  9. package/tools/tests/test-agent-project-claude-session-wrapper-does-not-retry-provider-quota.sh +0 -82
  10. package/tools/tests/test-agent-project-claude-session-wrapper-retries-transient-failures.sh +0 -90
  11. package/tools/tests/test-agent-project-claude-session-wrapper-times-out.sh +0 -73
  12. package/tools/tests/test-agent-project-claude-session-wrapper.sh +0 -103
  13. package/tools/tests/test-agent-project-cleanup-session-orphan-fallback.sh +0 -90
  14. package/tools/tests/test-agent-project-cleanup-session-skip-worktree-cleanup.sh +0 -90
  15. package/tools/tests/test-agent-project-codex-live-thread-persist.sh +0 -76
  16. package/tools/tests/test-agent-project-codex-recovery.sh +0 -731
  17. package/tools/tests/test-agent-project-codex-session-wrapper-clears-stale-sandbox-artifacts.sh +0 -105
  18. package/tools/tests/test-agent-project-codex-session-wrapper.sh +0 -97
  19. package/tools/tests/test-agent-project-open-pr-worktree-config-prefix.sh +0 -81
  20. package/tools/tests/test-agent-project-openclaw-session-wrapper-clears-stale-sandbox-artifacts.sh +0 -109
  21. package/tools/tests/test-agent-project-openclaw-session-wrapper-infers-blocked-result-contract.sh +0 -89
  22. package/tools/tests/test-agent-project-openclaw-session-wrapper-recovers-literal-env-artifacts.sh +0 -113
  23. package/tools/tests/test-agent-project-openclaw-session-wrapper-recovers-version-mismatch.sh +0 -135
  24. package/tools/tests/test-agent-project-openclaw-session-wrapper-resident.sh +0 -179
  25. package/tools/tests/test-agent-project-openclaw-session-wrapper-reuses-existing-agent-after-add-race.sh +0 -119
  26. package/tools/tests/test-agent-project-openclaw-session-wrapper-terminates-rate-limit-hang.sh +0 -91
  27. package/tools/tests/test-agent-project-openclaw-session-wrapper.sh +0 -117
  28. package/tools/tests/test-agent-project-publish-issue-pr-prunes-stale-worktree-entry.sh +0 -148
  29. package/tools/tests/test-agent-project-publish-issue-pr-reads-archived-session.sh +0 -146
  30. package/tools/tests/test-agent-project-publish-issue-pr-recovers-final-head.sh +0 -145
  31. package/tools/tests/test-agent-project-publish-issue-pr-reuses-existing-worktree.sh +0 -147
  32. package/tools/tests/test-agent-project-reconcile-failure-reason.sh +0 -456
  33. package/tools/tests/test-agent-project-reconcile-issue-archived-session-fallback.sh +0 -96
  34. package/tools/tests/test-agent-project-reconcile-issue-before-blocked.sh +0 -90
  35. package/tools/tests/test-agent-project-reconcile-issue-host-verification-recovery-uses-recovered-worktree.sh +0 -212
  36. package/tools/tests/test-agent-project-reconcile-issue-host-verification-recovery.sh +0 -207
  37. package/tools/tests/test-agent-project-reconcile-issue-provider-quota-schedules-provider-cooldown.sh +0 -101
  38. package/tools/tests/test-agent-project-reconcile-issue-session-backfills-lane-metadata-from-worker-key.sh +0 -113
  39. package/tools/tests/test-agent-project-reconcile-issue-session-clears-stale-failed-summary.sh +0 -117
  40. package/tools/tests/test-agent-project-reconcile-issue-session-initializes-shared-agent-home.sh +0 -55
  41. package/tools/tests/test-agent-project-reconcile-issue-session-normalizes-runner-state.sh +0 -125
  42. package/tools/tests/test-agent-project-reconcile-issue-session-records-invalid-contract-summary.sh +0 -118
  43. package/tools/tests/test-agent-project-reconcile-issue-session-skips-duplicate-blocked-comment.sh +0 -144
  44. package/tools/tests/test-agent-project-reconcile-issue-session-standardizes-no-commits-blocker.sh +0 -145
  45. package/tools/tests/test-agent-project-reconcile-issue-session-synthesizes-blocked-comment.sh +0 -139
  46. package/tools/tests/test-agent-project-reconcile-pr-blocked-host-recovery.sh +0 -242
  47. package/tools/tests/test-agent-project-reconcile-pr-guard-blocked-no-commit.sh +0 -142
  48. package/tools/tests/test-agent-project-reconcile-pr-provider-quota-schedules-provider-cooldown.sh +0 -106
  49. package/tools/tests/test-agent-project-reconcile-pr-session-initializes-shared-agent-home.sh +0 -66
  50. package/tools/tests/test-agent-project-reconcile-pr-updated-branch-noop.sh +0 -129
  51. package/tools/tests/test-audit-agent-worktrees-active-launch-skips-git-inspection.sh +0 -69
  52. package/tools/tests/test-audit-agent-worktrees-broken-worktree.sh +0 -43
  53. package/tools/tests/test-audit-agent-worktrees-pending-launch-owner.sh +0 -46
  54. package/tools/tests/test-audit-agent-worktrees-unreconciled-owner.sh +0 -79
  55. package/tools/tests/test-audit-issue-routing-managed-branch-globs.sh +0 -56
  56. package/tools/tests/test-branch-verification-guard-generated-artifacts.sh +0 -72
  57. package/tools/tests/test-branch-verification-guard-targeted-coverage.sh +0 -125
  58. package/tools/tests/test-codex-quota-manager-failure-driven-rotation.sh +0 -178
  59. package/tools/tests/test-codex-quota-wrapper.sh +0 -37
  60. package/tools/tests/test-contribution-docs.sh +0 -18
  61. package/tools/tests/test-control-plane-dashboard-runtime-smoke.sh +0 -343
  62. package/tools/tests/test-create-follow-up-issue.sh +0 -73
  63. package/tools/tests/test-dashboard-launchd-bootstrap.sh +0 -55
  64. package/tools/tests/test-flow-export-execution-env-exports-repo-id.sh +0 -30
  65. package/tools/tests/test-flow-export-github-cli-auth-env-prefers-git-credential.sh +0 -48
  66. package/tools/tests/test-flow-github-api-repo-fallback-preserves-input.sh +0 -85
  67. package/tools/tests/test-flow-github-api-repo-prefers-explicit-repository-id.sh +0 -60
  68. package/tools/tests/test-flow-github-issue-list-falls-back-to-repository-id.sh +0 -64
  69. package/tools/tests/test-flow-github-pr-list-falls-back-to-repository-id.sh +0 -77
  70. package/tools/tests/test-flow-resident-can-reuse-does-not-leak-metadata.sh +0 -52
  71. package/tools/tests/test-flow-resident-reap-stale-controllers.sh +0 -63
  72. package/tools/tests/test-flow-resolve-codex-quota-tools.sh +0 -104
  73. package/tools/tests/test-flow-runtime-doctor-profile-selection.sh +0 -27
  74. package/tools/tests/test-heartbeat-codex-pr-linked-issue-exclusion.sh +0 -79
  75. package/tools/tests/test-heartbeat-hooks-enqueue-resident-issue-for-idle-controller.sh +0 -115
  76. package/tools/tests/test-heartbeat-hooks-enqueue-resident-issue-for-live-lane-controller.sh +0 -117
  77. package/tools/tests/test-heartbeat-hooks-start-resident-issue-loop-claude.sh +0 -96
  78. package/tools/tests/test-heartbeat-hooks-start-resident-issue-loop-codex.sh +0 -96
  79. package/tools/tests/test-heartbeat-hooks-start-resident-issue-loop.sh +0 -96
  80. package/tools/tests/test-heartbeat-loop-auth-wait-does-not-consume-capacity.sh +0 -170
  81. package/tools/tests/test-heartbeat-loop-blocked-recovery-lane.sh +0 -201
  82. package/tools/tests/test-heartbeat-loop-blocked-recovery-vs-pr-reservation.sh +0 -201
  83. package/tools/tests/test-heartbeat-loop-idle-resident-controller-does-not-block-launches.sh +0 -160
  84. package/tools/tests/test-heartbeat-loop-pr-launch-dedup.sh +0 -133
  85. package/tools/tests/test-heartbeat-loop-provider-cooldown-suppresses-launches.sh +0 -157
  86. package/tools/tests/test-heartbeat-loop-reaps-stale-resident-controller.sh +0 -181
  87. package/tools/tests/test-heartbeat-loop-waiting-provider-resident-controller-does-not-block-launches.sh +0 -160
  88. package/tools/tests/test-heartbeat-ready-issues-blocked-recovery.sh +0 -134
  89. package/tools/tests/test-heartbeat-safe-auto-dynamic-concurrency.sh +0 -162
  90. package/tools/tests/test-heartbeat-safe-auto-no-tmux-sessions.sh +0 -136
  91. package/tools/tests/test-heartbeat-safe-auto-openclaw-skips-codex-quota.sh +0 -139
  92. package/tools/tests/test-heartbeat-safe-auto-quota-health-signal.sh +0 -119
  93. package/tools/tests/test-heartbeat-safe-auto-stale-shared-loop-pid-does-not-skip.sh +0 -140
  94. package/tools/tests/test-heartbeat-safe-auto-static-capacity-without-quota-cache.sh +0 -142
  95. package/tools/tests/test-heartbeat-safe-auto-zero-healthy-pools.sh +0 -141
  96. package/tools/tests/test-heartbeat-sync-issue-labels-empty-schedule.sh +0 -65
  97. package/tools/tests/test-heartbeat-sync-open-agent-prs-terminal-clears-running.sh +0 -179
  98. package/tools/tests/test-install-dashboard-launchd.sh +0 -78
  99. package/tools/tests/test-install-project-launchd-adds-tool-paths.sh +0 -87
  100. package/tools/tests/test-install-project-launchd.sh +0 -110
  101. package/tools/tests/test-issue-local-workspace-install-policy.sh +0 -81
  102. package/tools/tests/test-issue-publish-scope-guard-docs-signal.sh +0 -70
  103. package/tools/tests/test-issue-reconcile-hooks-success-clears-blocked.sh +0 -36
  104. package/tools/tests/test-kick-scheduler-requires-explicit-profile.sh +0 -47
  105. package/tools/tests/test-label-follow-up-issues-falls-back-to-repository-id.sh +0 -132
  106. package/tools/tests/test-manual-operator-entrypoints-require-explicit-profile.sh +0 -64
  107. package/tools/tests/test-package-funding-metadata.sh +0 -21
  108. package/tools/tests/test-package-public-metadata.sh +0 -62
  109. package/tools/tests/test-placeholder-worker-adapters.sh +0 -38
  110. package/tools/tests/test-pr-reconcile-hooks-refreshes-recurring-issue-checklist.sh +0 -110
  111. package/tools/tests/test-pr-risk-cohesive-mobile-locale-scope.sh +0 -70
  112. package/tools/tests/test-pr-risk-fix-label-semantics.sh +0 -114
  113. package/tools/tests/test-pr-risk-local-first-no-checks.sh +0 -70
  114. package/tools/tests/test-prepare-worktree-simple-repo-baseline.sh +0 -67
  115. package/tools/tests/test-profile-activate.sh +0 -33
  116. package/tools/tests/test-profile-adopt-allow-missing-repo.sh +0 -68
  117. package/tools/tests/test-profile-adopt-skip-workspace-sync-missing-file.sh +0 -61
  118. package/tools/tests/test-profile-adopt-syncs-anchor-and-workspace.sh +0 -90
  119. package/tools/tests/test-profile-smoke-collision.sh +0 -44
  120. package/tools/tests/test-profile-smoke-invalid-claude-config.sh +0 -31
  121. package/tools/tests/test-profile-smoke-invalid-provider-pool.sh +0 -68
  122. package/tools/tests/test-profile-smoke-repo-slug-mismatch.sh +0 -36
  123. package/tools/tests/test-profile-smoke.sh +0 -45
  124. package/tools/tests/test-project-init-force-and-skip-sync.sh +0 -61
  125. package/tools/tests/test-project-init-repo-slug-mismatch.sh +0 -29
  126. package/tools/tests/test-project-init.sh +0 -66
  127. package/tools/tests/test-project-launchd-bootstrap.sh +0 -66
  128. package/tools/tests/test-project-remove.sh +0 -150
  129. package/tools/tests/test-project-runtime-supervisor.sh +0 -47
  130. package/tools/tests/test-project-runtimectl-launchd.sh +0 -115
  131. package/tools/tests/test-project-runtimectl-missing-profile.sh +0 -54
  132. package/tools/tests/test-project-runtimectl-start-falls-back-to-bootstrap.sh +0 -108
  133. package/tools/tests/test-project-runtimectl-status-reports-supervisor-as-heartbeat-parent.sh +0 -95
  134. package/tools/tests/test-project-runtimectl-status-supervisor-running.sh +0 -59
  135. package/tools/tests/test-project-runtimectl-stop-cancels-pending-kick.sh +0 -85
  136. package/tools/tests/test-project-runtimectl-stop-clears-running-labels.sh +0 -78
  137. package/tools/tests/test-project-runtimectl.sh +0 -212
  138. package/tools/tests/test-provider-cooldown-state-prefers-runtime-worker-context.sh +0 -39
  139. package/tools/tests/test-provider-cooldown-state.sh +0 -59
  140. package/tools/tests/test-public-repo-docs.sh +0 -161
  141. package/tools/tests/test-reconcile-pr-worker-acp-config-routing.sh +0 -75
  142. package/tools/tests/test-render-dashboard-snapshot.sh +0 -149
  143. package/tools/tests/test-render-flow-config-demo-profile.sh +0 -36
  144. package/tools/tests/test-render-flow-config-provider-pool-fallback.sh +0 -81
  145. package/tools/tests/test-render-flow-config.sh +0 -52
  146. package/tools/tests/test-run-codex-task-claude-routing.sh +0 -125
  147. package/tools/tests/test-run-codex-task-codex-resident-routing.sh +0 -108
  148. package/tools/tests/test-run-codex-task-kilo-routing.sh +0 -98
  149. package/tools/tests/test-run-codex-task-openclaw-resident-routing.sh +0 -117
  150. package/tools/tests/test-run-codex-task-openclaw-routing.sh +0 -113
  151. package/tools/tests/test-run-codex-task-opencode-routing.sh +0 -98
  152. package/tools/tests/test-run-codex-task-provider-pool-fallback-routing.sh +0 -146
  153. package/tools/tests/test-scaffold-profile.sh +0 -108
  154. package/tools/tests/test-serve-dashboard.sh +0 -93
  155. package/tools/tests/test-start-issue-worker-blocked-context.sh +0 -129
  156. package/tools/tests/test-start-issue-worker-blocks-complete-recurring-checklist.sh +0 -189
  157. package/tools/tests/test-start-issue-worker-local-install-routing.sh +0 -157
  158. package/tools/tests/test-start-issue-worker-profile-template-routing.sh +0 -149
  159. package/tools/tests/test-start-issue-worker-recurring-resident-reuse-codex.sh +0 -212
  160. package/tools/tests/test-start-issue-worker-recurring-resident-reuse.sh +0 -219
  161. package/tools/tests/test-start-issue-worker-renders-verification-snippet.sh +0 -155
  162. package/tools/tests/test-start-issue-worker-resident-reuse-falls-back-to-new-worktree.sh +0 -199
  163. package/tools/tests/test-start-pr-fix-worker-host-blocker-context.sh +0 -275
  164. package/tools/tests/test-start-resident-issue-loop-adopts-next-recurring-issue.sh +0 -185
  165. package/tools/tests/test-start-resident-issue-loop-clears-pending-while-waiting-due.sh +0 -152
  166. package/tools/tests/test-start-resident-issue-loop-consumes-queued-lease.sh +0 -186
  167. package/tools/tests/test-start-resident-issue-loop-fails-over-provider-pool.sh +0 -212
  168. package/tools/tests/test-start-resident-issue-loop-immediate-cycles.sh +0 -148
  169. package/tools/tests/test-start-resident-issue-loop-waits-for-provider.sh +0 -194
  170. package/tools/tests/test-start-resident-issue-loop-waits-for-terminal-reconcile-status.sh +0 -198
  171. package/tools/tests/test-start-resident-issue-loop-yields-to-live-lane-controller.sh +0 -145
  172. package/tools/tests/test-sync-pr-labels-fix-lane-uses-repair-queued.sh +0 -67
  173. package/tools/tests/test-sync-recurring-issue-checklist-backfills-workflow-complete-blocker.sh +0 -70
  174. package/tools/tests/test-sync-recurring-issue-checklist.sh +0 -95
  175. package/tools/tests/test-sync-shared-agent-home-local-source-root.sh +0 -66
  176. package/tools/tests/test-sync-shared-agent-home-preserves-unrelated-workflow-catalog-skill.sh +0 -47
  177. package/tools/tests/test-test-smoke.sh +0 -86
  178. package/tools/tests/test-uninstall-project-launchd.sh +0 -37
  179. package/tools/tests/test-update-github-labels-prefers-sibling-helper.sh +0 -49
  180. package/tools/tests/test-vendored-codex-quota-claude-oauth-only.sh +0 -38
  181. package/tools/tests/test-workflow-catalog.sh +0 -43
  182. package/tools/vendor/codex-quota/README.md +0 -451
@@ -1,343 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- FLOW_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5
- SNAPSHOT_BIN="${FLOW_ROOT}/tools/bin/render-dashboard-snapshot.py"
6
- SERVER_BIN="${FLOW_ROOT}/tools/bin/serve-dashboard.sh"
7
- RUNTIMECTL_BIN="${FLOW_ROOT}/tools/bin/project-runtimectl.sh"
8
-
9
- tmpdir="$(mktemp -d)"
10
- server_pid=""
11
- supervisor_pid=""
12
- heartbeat_pid=""
13
- shared_loop_pid=""
14
- controller_pid=""
15
- cleanup() {
16
- local pid=""
17
- for pid in "${server_pid}" "${shared_loop_pid}" "${controller_pid}" "${heartbeat_pid}" "${supervisor_pid}"; do
18
- [[ -n "${pid}" ]] || continue
19
- kill "${pid}" >/dev/null 2>&1 || true
20
- wait "${pid}" >/dev/null 2>&1 || true
21
- done
22
- rm -rf "${tmpdir}"
23
- }
24
- trap cleanup EXIT
25
-
26
- profile_registry_root="${tmpdir}/profiles"
27
- profile_dir="${profile_registry_root}/demo"
28
- runs_root="${tmpdir}/runtime/demo/runs"
29
- state_root="${tmpdir}/runtime/demo/state"
30
- recurring_run_dir="${runs_root}/demo-issue-2"
31
- scheduled_run_dir="${runs_root}/demo-issue-3"
32
- recurring_worker_key="issue-lane-recurring-general-openclaw-safe"
33
- scheduled_worker_key="issue-lane-scheduled-1800-openclaw-safe"
34
- repo_slug="example/demo-control-plane"
35
- port="18766"
36
- heartbeat_child_pid_file="${tmpdir}/heartbeat-child.pid"
37
- heartbeat_script="${tmpdir}/heartbeat-safe-auto.sh"
38
- supervisor_script="${tmpdir}/project-runtime-supervisor.sh"
39
- shared_loop_script="${tmpdir}/agent-project-heartbeat-loop"
40
-
41
- mkdir -p \
42
- "${profile_dir}" \
43
- "${recurring_run_dir}" \
44
- "${scheduled_run_dir}" \
45
- "${state_root}/heartbeat-loop.lock" \
46
- "${state_root}/resident-workers/issues/2" \
47
- "${state_root}/resident-workers/issues/${recurring_worker_key}" \
48
- "${state_root}/resident-workers/issues/${scheduled_worker_key}" \
49
- "${state_root}/resident-workers/issue-queue/pending" \
50
- "${state_root}/retries/providers" \
51
- "${state_root}/scheduled-issues"
52
-
53
- cat >"${profile_dir}/control-plane.yaml" <<EOF
54
- schema_version: "1"
55
- id: "demo"
56
- repo:
57
- slug: "${repo_slug}"
58
- root: "${tmpdir}/repo"
59
- default_branch: "main"
60
- runtime:
61
- orchestrator_agent_root: "${tmpdir}/runtime/demo"
62
- worktree_root: "${tmpdir}/worktrees"
63
- agent_repo_root: "${tmpdir}/repo"
64
- runs_root: "${runs_root}"
65
- state_root: "${state_root}"
66
- history_root: "${tmpdir}/runtime/demo/history"
67
- retained_repo_root: "${tmpdir}/repo"
68
- vscode_workspace_file: "${tmpdir}/demo.code-workspace"
69
- session_naming:
70
- issue_prefix: "demo-issue-"
71
- pr_prefix: "demo-pr-"
72
- execution:
73
- coding_worker: "openclaw"
74
- openclaw:
75
- model: "primary/model"
76
- thinking: "adaptive"
77
- timeout_seconds: 900
78
- EOF
79
-
80
- cat >"${recurring_run_dir}/run.env" <<EOF
81
- TASK_KIND=issue
82
- TASK_ID=2
83
- SESSION=demo-issue-2
84
- MODE=safe
85
- STARTED_AT=2026-03-27T11:00:00Z
86
- CODING_WORKER=openclaw
87
- WORKTREE=${tmpdir}/worktrees/issue-2
88
- BRANCH=agent/demo/issue-2
89
- RESIDENT_WORKER_KEY=${recurring_worker_key}
90
- OPENCLAW_MODEL=primary/model
91
- EOF
92
-
93
- cat >"${recurring_run_dir}/runner.env" <<'EOF'
94
- RUNNER_STATE=succeeded
95
- THREAD_ID=thread-demo-2
96
- LAST_EXIT_CODE=0
97
- LAST_FAILURE_REASON=''
98
- UPDATED_AT=2026-03-27T11:03:00Z
99
- EOF
100
-
101
- cat >"${recurring_run_dir}/result.env" <<'EOF'
102
- OUTCOME=implemented
103
- ACTION=host-publish-issue-pr
104
- EOF
105
-
106
- cat >"${scheduled_run_dir}/run.env" <<EOF
107
- TASK_KIND=issue
108
- TASK_ID=3
109
- SESSION=demo-issue-3
110
- MODE=safe
111
- STARTED_AT=2026-03-27T11:10:00Z
112
- CODING_WORKER=openclaw
113
- WORKTREE=${tmpdir}/worktrees/issue-3
114
- BRANCH=agent/demo/issue-3
115
- RESIDENT_WORKER_KEY=${scheduled_worker_key}
116
- OPENCLAW_MODEL=primary/model
117
- EOF
118
-
119
- cat >"${scheduled_run_dir}/runner.env" <<'EOF'
120
- RUNNER_STATE=succeeded
121
- THREAD_ID=thread-demo-3
122
- LAST_EXIT_CODE=0
123
- LAST_FAILURE_REASON=''
124
- UPDATED_AT=2026-03-27T11:12:00Z
125
- EOF
126
-
127
- cat >"${scheduled_run_dir}/result.env" <<'EOF'
128
- OUTCOME=reported
129
- ACTION=host-comment-scheduled-report
130
- EOF
131
-
132
- cat >"${heartbeat_script}" <<'EOF'
133
- #!/usr/bin/env bash
134
- set -euo pipefail
135
- sleep 60
136
- EOF
137
- chmod +x "${heartbeat_script}"
138
-
139
- cat >"${supervisor_script}" <<EOF
140
- #!/usr/bin/env bash
141
- set -euo pipefail
142
- bash "${heartbeat_script}" >/dev/null 2>&1 &
143
- child_pid=\$!
144
- printf '%s\n' "\${child_pid}" >"${heartbeat_child_pid_file}"
145
- wait "\${child_pid}"
146
- EOF
147
- chmod +x "${supervisor_script}"
148
-
149
- cat >"${shared_loop_script}" <<'EOF'
150
- #!/usr/bin/env bash
151
- set -euo pipefail
152
- sleep 60
153
- EOF
154
- chmod +x "${shared_loop_script}"
155
-
156
- bash "${supervisor_script}" >/dev/null 2>&1 &
157
- supervisor_pid="$!"
158
-
159
- for _ in $(seq 1 50); do
160
- if [[ -s "${heartbeat_child_pid_file}" ]]; then
161
- break
162
- fi
163
- sleep 0.1
164
- done
165
-
166
- heartbeat_pid="$(tr -d '[:space:]' <"${heartbeat_child_pid_file}")"
167
- if [[ -z "${heartbeat_pid}" ]]; then
168
- echo "failed to capture heartbeat pid" >&2
169
- exit 1
170
- fi
171
-
172
- printf '%s\n' "${heartbeat_pid}" >"${state_root}/heartbeat-loop.lock/pid"
173
- printf '%s\n' "${supervisor_pid}" >"${state_root}/runtime-supervisor.pid"
174
-
175
- bash "${shared_loop_script}" --repo-slug "${repo_slug}" >/dev/null 2>&1 &
176
- shared_loop_pid="$!"
177
- printf '%s\n' "${shared_loop_pid}" >"${state_root}/shared-heartbeat-loop.pid"
178
-
179
- sleep 60 >/dev/null 2>&1 &
180
- controller_pid="$!"
181
-
182
- cat >"${state_root}/resident-workers/issues/2/controller.env" <<EOF
183
- ISSUE_ID=2
184
- SESSION=demo-issue-2
185
- CONTROLLER_PID=${controller_pid}
186
- CONTROLLER_MODE=safe
187
- CONTROLLER_LOOP_COUNT=4
188
- CONTROLLER_STATE=waiting-provider
189
- CONTROLLER_REASON=provider-cooldown
190
- ACTIVE_RESIDENT_WORKER_KEY=${recurring_worker_key}
191
- ACTIVE_RESIDENT_LANE_KIND=recurring
192
- ACTIVE_RESIDENT_LANE_VALUE=general
193
- ACTIVE_PROVIDER_BACKEND=openclaw
194
- ACTIVE_PROVIDER_MODEL=primary/model
195
- ACTIVE_PROVIDER_KEY=openclaw-primary-model
196
- PROVIDER_SWITCH_COUNT=2
197
- PROVIDER_FAILOVER_COUNT=1
198
- PROVIDER_WAIT_COUNT=3
199
- PROVIDER_WAIT_TOTAL_SECONDS=90
200
- PROVIDER_LAST_WAIT_SECONDS=30
201
- UPDATED_AT=2026-03-27T11:13:00Z
202
- EOF
203
-
204
- cat >"${state_root}/resident-workers/issues/${recurring_worker_key}/metadata.env" <<EOF
205
- RESIDENT_WORKER_KIND=issue
206
- RESIDENT_WORKER_SCOPE=lane
207
- RESIDENT_WORKER_KEY=${recurring_worker_key}
208
- RESIDENT_LANE_KIND=recurring
209
- RESIDENT_LANE_VALUE=general
210
- ISSUE_ID=2
211
- CODING_WORKER=openclaw
212
- TASK_COUNT=5
213
- LAST_STATUS=SUCCEEDED
214
- LAST_STARTED_AT=2026-03-27T11:00:00Z
215
- LAST_FINISHED_AT=2026-03-27T11:03:00Z
216
- LAST_RUN_SESSION=demo-issue-2
217
- LAST_OUTCOME=implemented
218
- LAST_ACTION=host-publish-issue-pr
219
- LAST_FAILURE_REASON=
220
- EOF
221
-
222
- cat >"${state_root}/resident-workers/issues/${scheduled_worker_key}/metadata.env" <<EOF
223
- RESIDENT_WORKER_KIND=issue
224
- RESIDENT_WORKER_SCOPE=lane
225
- RESIDENT_WORKER_KEY=${scheduled_worker_key}
226
- RESIDENT_LANE_KIND=scheduled
227
- RESIDENT_LANE_VALUE=1800
228
- ISSUE_ID=3
229
- CODING_WORKER=openclaw
230
- TASK_COUNT=2
231
- LAST_STATUS=SUCCEEDED
232
- LAST_STARTED_AT=2026-03-27T11:10:00Z
233
- LAST_FINISHED_AT=2026-03-27T11:12:00Z
234
- LAST_RUN_SESSION=demo-issue-3
235
- LAST_OUTCOME=reported
236
- LAST_ACTION=host-comment-scheduled-report
237
- LAST_FAILURE_REASON=
238
- EOF
239
-
240
- cat >"${state_root}/scheduled-issues/3.env" <<'EOF'
241
- INTERVAL_SECONDS=1800
242
- LAST_STARTED_AT=2026-03-27T11:10:00Z
243
- NEXT_DUE_AT=2026-03-27T11:40:00Z
244
- UPDATED_AT=2026-03-27T11:12:00Z
245
- EOF
246
-
247
- cat >"${state_root}/retries/providers/openclaw-primary-model.env" <<'EOF'
248
- ATTEMPTS=2
249
- NEXT_ATTEMPT_EPOCH=4102444800
250
- NEXT_ATTEMPT_AT=2100-01-01T00:00:00Z
251
- LAST_REASON=provider-quota-limit
252
- UPDATED_AT=2026-03-27T11:13:00Z
253
- EOF
254
-
255
- cat >"${state_root}/resident-workers/issue-queue/pending/issue-6.env" <<'EOF'
256
- ISSUE_ID=6
257
- SESSION=demo-issue-6
258
- UPDATED_AT=2026-03-27T11:13:30Z
259
- EOF
260
-
261
- snapshot_file="${tmpdir}/snapshot.json"
262
- api_snapshot_file="${tmpdir}/api-snapshot.json"
263
-
264
- ACP_PROFILE_REGISTRY_ROOT="${profile_registry_root}" python3 "${SNAPSHOT_BIN}" --pretty >"${snapshot_file}"
265
-
266
- bash "${SERVER_BIN}" --host 127.0.0.1 --port "${port}" --registry-root "${profile_registry_root}" >"${tmpdir}/server.log" 2>&1 &
267
- server_pid="$!"
268
-
269
- for _ in $(seq 1 10); do
270
- if curl -fsS "http://127.0.0.1:${port}/api/snapshot.json" >/dev/null 2>&1; then
271
- break
272
- fi
273
- sleep 1
274
- done
275
-
276
- curl -fsS "http://127.0.0.1:${port}/api/snapshot.json" >"${api_snapshot_file}"
277
- html="$(curl -fsS "http://127.0.0.1:${port}/")"
278
-
279
- status_output="$(
280
- ACP_PROFILE_REGISTRY_ROOT="${profile_registry_root}" \
281
- ACP_PROJECT_RUNTIME_LAUNCHCTL_BIN="/nonexistent" \
282
- bash "${RUNTIMECTL_BIN}" status --profile-id demo
283
- )"
284
-
285
- grep -q '^RUNTIME_STATUS=running$' <<<"${status_output}"
286
- grep -q "^HEARTBEAT_PID=${heartbeat_pid}$" <<<"${status_output}"
287
- grep -q "^HEARTBEAT_PARENT_PID=${supervisor_pid}$" <<<"${status_output}"
288
- grep -q "^SHARED_LOOP_PID=${shared_loop_pid}$" <<<"${status_output}"
289
- grep -q "^SUPERVISOR_PID=${supervisor_pid}$" <<<"${status_output}"
290
- grep -q '^CONTROLLER_COUNT=1$' <<<"${status_output}"
291
-
292
- grep -q 'ACP Worker Dashboard' <<<"${html}"
293
- grep -q 'Track active runs, resident controllers, queue pressure, and provider failover in one place.' <<<"${html}"
294
-
295
- python3 - "${snapshot_file}" "${api_snapshot_file}" <<'PY'
296
- import json
297
- import sys
298
-
299
- snapshot_path, api_path = sys.argv[1], sys.argv[2]
300
- snapshot = json.load(open(snapshot_path, encoding="utf-8"))
301
- api_snapshot = json.load(open(api_path, encoding="utf-8"))
302
-
303
- assert snapshot["profile_count"] == 1
304
- assert api_snapshot["profile_count"] == 1
305
-
306
- profile = snapshot["profiles"][0]
307
- api_profile = api_snapshot["profiles"][0]
308
-
309
- assert profile["id"] == "demo"
310
- assert profile["repo_slug"] == "example/demo-control-plane"
311
- assert profile["counts"]["implemented_runs"] == 1
312
- assert profile["counts"]["reported_runs"] == 1
313
- assert profile["counts"]["blocked_runs"] == 0
314
- assert profile["counts"]["live_resident_controllers"] == 1
315
- assert profile["counts"]["resident_workers"] == 2
316
- assert profile["counts"]["queued_issues"] == 1
317
- assert profile["counts"]["provider_cooldowns"] == 1
318
- assert profile["counts"]["scheduled_issues"] == 1
319
-
320
- runs = {item["session"]: item for item in profile["runs"]}
321
- assert runs["demo-issue-2"]["result_kind"] == "implemented"
322
- assert runs["demo-issue-2"]["action"] == "host-publish-issue-pr"
323
- assert runs["demo-issue-3"]["result_kind"] == "reported"
324
- assert runs["demo-issue-3"]["action"] == "host-comment-scheduled-report"
325
-
326
- controllers = {item["issue_id"]: item for item in profile["resident_controllers"]}
327
- controller = controllers["2"]
328
- assert controller["state"] == "waiting-provider"
329
- assert controller["controller_live"] is True
330
- assert controller["provider_failover_count"] == 1
331
- assert controller["provider_wait_total_seconds"] == 90
332
-
333
- workers = {item["key"]: item for item in profile["resident_workers"]}
334
- assert workers["issue-lane-recurring-general-openclaw-safe"]["last_action"] == "host-publish-issue-pr"
335
- assert workers["issue-lane-scheduled-1800-openclaw-safe"]["last_action"] == "host-comment-scheduled-report"
336
-
337
- assert api_profile["counts"]["implemented_runs"] == 1
338
- assert api_profile["counts"]["reported_runs"] == 1
339
- assert api_profile["counts"]["live_resident_controllers"] == 1
340
- assert api_profile["counts"]["scheduled_issues"] == 1
341
- PY
342
-
343
- echo "control plane dashboard runtime smoke test passed"
@@ -1,73 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- FLOW_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5
- SCRIPT="${FLOW_ROOT}/tools/bin/create-follow-up-issue.sh"
6
-
7
- tmpdir="$(mktemp -d)"
8
- trap 'rm -rf "$tmpdir"' EXIT
9
-
10
- bin_dir="$tmpdir/bin"
11
- labels_log="$tmpdir/labels.log"
12
- body_capture="$tmpdir/body.txt"
13
- mkdir -p "$bin_dir"
14
-
15
- cat >"$bin_dir/gh" <<'EOF'
16
- #!/usr/bin/env bash
17
- set -euo pipefail
18
-
19
- if [[ "${1:-}" == "issue" && "${2:-}" == "create" ]]; then
20
- body_file=""
21
- while [[ $# -gt 0 ]]; do
22
- case "$1" in
23
- --body-file)
24
- body_file="${2:-}"
25
- shift 2
26
- ;;
27
- *)
28
- shift
29
- ;;
30
- esac
31
- done
32
- cat "$body_file" >"${TEST_BODY_CAPTURE:?}"
33
- printf 'https://github.com/example/repo/issues/912\n'
34
- exit 0
35
- fi
36
-
37
- echo "unexpected gh args: $*" >&2
38
- exit 1
39
- EOF
40
- chmod +x "$bin_dir/gh"
41
-
42
- cat >"$bin_dir/agent-github-update-labels" <<'EOF'
43
- #!/usr/bin/env bash
44
- set -euo pipefail
45
- printf '%s\n' "$*" >"${TEST_LABELS_LOG:?}"
46
- EOF
47
- chmod +x "$bin_dir/agent-github-update-labels"
48
-
49
- body_file="$tmpdir/follow-up.md"
50
- cat >"$body_file" <<'EOF'
51
- Target slice: mobile settings language cluster
52
-
53
- - Keep PR to one route family
54
- - Reuse account cluster shell
55
- EOF
56
-
57
- TEST_BODY_CAPTURE="$body_capture" \
58
- TEST_LABELS_LOG="$labels_log" \
59
- UPDATE_LABELS_BIN="$bin_dir/agent-github-update-labels" \
60
- PATH="$bin_dir:$PATH" \
61
- bash "$SCRIPT" \
62
- --parent 421 \
63
- --title "Mobile settings: split language cluster from umbrella" \
64
- --body-file "$body_file" \
65
- --label agent-e2e-heavy >"$tmpdir/out.txt"
66
-
67
- grep -q '^ISSUE_NUMBER=912$' "$tmpdir/out.txt"
68
- grep -q '^ISSUE_URL=https://github.com/example/repo/issues/912$' "$tmpdir/out.txt"
69
- grep -q '^Parent issue: #421$' "$body_capture"
70
- grep -q 'Target slice: mobile settings language cluster' "$body_capture"
71
- grep -q -- '--number 912 --add agent-e2e-heavy' "$labels_log"
72
-
73
- echo "create follow-up issue test passed"
@@ -1,55 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- FLOW_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5
- BOOTSTRAP_BIN="${FLOW_ROOT}/tools/bin/dashboard-launchd-bootstrap.sh"
6
-
7
- tmpdir="$(mktemp -d)"
8
- trap 'rm -rf "$tmpdir"' EXIT
9
-
10
- home_dir="$tmpdir/home"
11
- runtime_home="$tmpdir/runtime-home"
12
- profile_registry_root="$tmpdir/profiles"
13
- capture_dir="$tmpdir/capture"
14
- sync_script="$tmpdir/sync.sh"
15
- runtime_serve_script="$runtime_home/skills/openclaw/agent-control-plane/tools/bin/serve-dashboard.sh"
16
-
17
- mkdir -p "$home_dir" "$profile_registry_root" "$(dirname "$runtime_serve_script")" "$capture_dir"
18
-
19
- cat >"$sync_script" <<'EOF'
20
- #!/usr/bin/env bash
21
- set -euo pipefail
22
- printf 'SYNC_SOURCE=%s\n' "$1" >"${ACP_DASHBOARD_CAPTURE_DIR}/sync.log"
23
- printf 'SYNC_TARGET=%s\n' "$2" >>"${ACP_DASHBOARD_CAPTURE_DIR}/sync.log"
24
- EOF
25
- chmod +x "$sync_script"
26
-
27
- cat >"$runtime_serve_script" <<'EOF'
28
- #!/usr/bin/env bash
29
- set -euo pipefail
30
- printf 'ARGS=%s %s %s %s\n' "$1" "$2" "$3" "$4" >"${ACP_DASHBOARD_CAPTURE_DIR}/serve.log"
31
- printf 'PROFILE_REGISTRY_ROOT=%s\n' "${ACP_PROFILE_REGISTRY_ROOT:-}" >>"${ACP_DASHBOARD_CAPTURE_DIR}/serve.log"
32
- printf 'HOME=%s\n' "${HOME:-}" >>"${ACP_DASHBOARD_CAPTURE_DIR}/serve.log"
33
- printf 'PYTHONDONTWRITEBYTECODE=%s\n' "${PYTHONDONTWRITEBYTECODE:-}" >>"${ACP_DASHBOARD_CAPTURE_DIR}/serve.log"
34
- EOF
35
- chmod +x "$runtime_serve_script"
36
-
37
- ACP_DASHBOARD_HOME_DIR="$home_dir" \
38
- ACP_DASHBOARD_SOURCE_HOME="$tmpdir/source-home" \
39
- ACP_DASHBOARD_RUNTIME_HOME="$runtime_home" \
40
- ACP_DASHBOARD_PROFILE_REGISTRY_ROOT="$profile_registry_root" \
41
- ACP_DASHBOARD_HOST="127.0.0.1" \
42
- ACP_DASHBOARD_PORT="9911" \
43
- ACP_DASHBOARD_SYNC_SCRIPT="$sync_script" \
44
- ACP_DASHBOARD_RUNTIME_SERVE_SCRIPT="$runtime_serve_script" \
45
- ACP_DASHBOARD_CAPTURE_DIR="$capture_dir" \
46
- bash "$BOOTSTRAP_BIN"
47
-
48
- grep -q "^SYNC_SOURCE=$tmpdir/source-home$" "$capture_dir/sync.log"
49
- grep -q "^SYNC_TARGET=$runtime_home$" "$capture_dir/sync.log"
50
- grep -q '^ARGS=--host 127.0.0.1 --port 9911$' "$capture_dir/serve.log"
51
- grep -q "^PROFILE_REGISTRY_ROOT=$profile_registry_root$" "$capture_dir/serve.log"
52
- grep -q "^HOME=$home_dir$" "$capture_dir/serve.log"
53
- grep -q '^PYTHONDONTWRITEBYTECODE=1$' "$capture_dir/serve.log"
54
-
55
- echo "dashboard launchd bootstrap test passed"
@@ -1,30 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- FLOW_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5
- CONFIG_LIB="${FLOW_ROOT}/tools/bin/flow-config-lib.sh"
6
-
7
- tmpdir="$(mktemp -d)"
8
- trap 'rm -rf "$tmpdir"' EXIT
9
-
10
- config_file="$tmpdir/control-plane.yaml"
11
-
12
- cat >"$config_file" <<'EOF'
13
- schema_version: "1"
14
- id: "demo"
15
- repo:
16
- slug: "example/repo"
17
- id: "123"
18
- default_branch: "main"
19
- EOF
20
-
21
- output="$(
22
- bash -lc 'source "'"$CONFIG_LIB"'"; flow_export_execution_env "'"$config_file"'"; printf "ACP_REPO_ID=%s\nF_LOSNING_REPO_ID=%s\nACP_GITHUB_REPOSITORY_ID=%s\nF_LOSNING_GITHUB_REPOSITORY_ID=%s\n" "${ACP_REPO_ID:-}" "${F_LOSNING_REPO_ID:-}" "${ACP_GITHUB_REPOSITORY_ID:-}" "${F_LOSNING_GITHUB_REPOSITORY_ID:-}"'
23
- )"
24
-
25
- grep -q '^ACP_REPO_ID=123$' <<<"$output"
26
- grep -q '^F_LOSNING_REPO_ID=123$' <<<"$output"
27
- grep -q '^ACP_GITHUB_REPOSITORY_ID=123$' <<<"$output"
28
- grep -q '^F_LOSNING_GITHUB_REPOSITORY_ID=123$' <<<"$output"
29
-
30
- echo "flow export execution env exports repo id test passed"
@@ -1,48 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- FLOW_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5
- REAL_CONFIG_LIB="${FLOW_ROOT}/tools/bin/flow-config-lib.sh"
6
- REAL_SHELL_LIB="${FLOW_ROOT}/tools/bin/flow-shell-lib.sh"
7
-
8
- tmpdir="$(mktemp -d)"
9
- trap 'rm -rf "$tmpdir"' EXIT
10
-
11
- bin_dir="$tmpdir/bin"
12
- mkdir -p "$bin_dir"
13
-
14
- cp "$REAL_CONFIG_LIB" "$bin_dir/flow-config-lib.sh"
15
- cp "$REAL_SHELL_LIB" "$bin_dir/flow-shell-lib.sh"
16
-
17
- cat >"$bin_dir/git" <<'EOF'
18
- #!/usr/bin/env bash
19
- set -euo pipefail
20
- if [[ "${1:-}" == "credential" && "${2:-}" == "fill" ]]; then
21
- cat >/dev/null
22
- printf 'protocol=https\n'
23
- printf 'host=github.com\n'
24
- printf 'username=test-user\n'
25
- printf 'password=repo-specific-token\n'
26
- exit 0
27
- fi
28
- exit 1
29
- EOF
30
- chmod +x "$bin_dir/git"
31
-
32
- output="$(
33
- LIB_PATH="$bin_dir/flow-config-lib.sh" \
34
- PATH="$bin_dir:/usr/bin:/bin:/usr/sbin:/sbin" \
35
- GITHUB_PERSONAL_ACCESS_TOKEN="env-fallback-token" \
36
- bash <<'EOF'
37
- set -euo pipefail
38
- source "$LIB_PATH"
39
- unset GH_TOKEN
40
- unset GITHUB_TOKEN
41
- flow_export_github_cli_auth_env "owner/repo"
42
- printf 'GH_TOKEN=%s\n' "${GH_TOKEN:-}"
43
- EOF
44
- )"
45
-
46
- grep -q '^GH_TOKEN=repo-specific-token$' <<<"$output"
47
-
48
- echo "flow export github cli auth env prefers git credential test passed"
@@ -1,85 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- FLOW_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5
- REAL_CONFIG_LIB="${FLOW_ROOT}/tools/bin/flow-config-lib.sh"
6
- REAL_SHELL_LIB="${FLOW_ROOT}/tools/bin/flow-shell-lib.sh"
7
-
8
- tmpdir="$(mktemp -d)"
9
- trap 'rm -rf "$tmpdir"' EXIT
10
-
11
- bin_dir="$tmpdir/bin"
12
- mkdir -p "$bin_dir"
13
-
14
- cp "$REAL_CONFIG_LIB" "$bin_dir/flow-config-lib.sh"
15
- cp "$REAL_SHELL_LIB" "$bin_dir/flow-shell-lib.sh"
16
-
17
- captured_payload_file="$tmpdir/captured-payload.json"
18
- cat >"$bin_dir/gh" <<'EOF'
19
- #!/usr/bin/env bash
20
- set -euo pipefail
21
-
22
- if [[ "${1:-}" != "api" ]]; then
23
- echo "unexpected gh invocation: $*" >&2
24
- exit 1
25
- fi
26
-
27
- route="${2:-}"
28
- shift 2 || true
29
-
30
- input_file=""
31
- while [[ $# -gt 0 ]]; do
32
- case "$1" in
33
- --input)
34
- input_file="${2:-}"
35
- shift 2
36
- ;;
37
- *)
38
- shift
39
- ;;
40
- esac
41
- done
42
-
43
- case "$route" in
44
- repos/example/repo/issues/42)
45
- if [[ -n "$input_file" && -f "$input_file" ]]; then
46
- cat "$input_file" >/dev/null
47
- fi
48
- exit 1
49
- ;;
50
- repositories/123/issues/42)
51
- if [[ -z "$input_file" || ! -f "$input_file" ]]; then
52
- echo "missing preserved input file" >&2
53
- exit 97
54
- fi
55
- cp "$input_file" "${TEST_CAPTURED_PAYLOAD_FILE:?}"
56
- printf '{"number":42,"state":"open"}\n'
57
- exit 0
58
- ;;
59
- *)
60
- echo "unexpected gh api route: $route" >&2
61
- exit 1
62
- ;;
63
- esac
64
- EOF
65
-
66
- chmod +x "$bin_dir/flow-config-lib.sh" "$bin_dir/flow-shell-lib.sh" "$bin_dir/gh"
67
-
68
- output="$(
69
- LIB_PATH="$bin_dir/flow-config-lib.sh" \
70
- PATH="$bin_dir:/usr/bin:/bin:/usr/sbin:/sbin" \
71
- ACP_REPO_ID="123" \
72
- ACP_REPO_SLUG="example/repo" \
73
- TEST_CAPTURED_PAYLOAD_FILE="$captured_payload_file" \
74
- bash <<'EOF'
75
- set -euo pipefail
76
- source "$LIB_PATH"
77
- printf '{"body":"patched body"}' | flow_github_api_repo "example/repo" "issues/42" --method PATCH --input -
78
- EOF
79
- )"
80
-
81
- test "$(jq -r '.number' <<<"$output")" = "42"
82
- test "$(jq -r '.state' <<<"$output")" = "open"
83
- test "$(jq -r '.body' "$captured_payload_file")" = "patched body"
84
-
85
- echo "flow github api repo fallback preserves input test passed"