agent-control-plane 0.1.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 (317) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +589 -0
  3. package/SKILL.md +149 -0
  4. package/assets/workflow-catalog.json +57 -0
  5. package/bin/audit-issue-routing.sh +74 -0
  6. package/bin/issue-resource-class.sh +58 -0
  7. package/bin/label-follow-up-issues.sh +114 -0
  8. package/bin/pr-risk.sh +532 -0
  9. package/bin/sync-pr-labels.sh +112 -0
  10. package/hooks/heartbeat-hooks.sh +573 -0
  11. package/hooks/issue-reconcile-hooks.sh +217 -0
  12. package/hooks/pr-reconcile-hooks.sh +225 -0
  13. package/npm/bin/agent-control-plane.js +1984 -0
  14. package/npm/public-bin/agent-control-plane +3 -0
  15. package/package.json +61 -0
  16. package/tools/bin/agent-cleanup-worktree +247 -0
  17. package/tools/bin/agent-github-update-labels +66 -0
  18. package/tools/bin/agent-init-worktree +216 -0
  19. package/tools/bin/agent-project-archive-run +52 -0
  20. package/tools/bin/agent-project-capture-worker +46 -0
  21. package/tools/bin/agent-project-catch-up-merged-prs +137 -0
  22. package/tools/bin/agent-project-cleanup-session +244 -0
  23. package/tools/bin/agent-project-detached-launch +107 -0
  24. package/tools/bin/agent-project-heartbeat-loop +2347 -0
  25. package/tools/bin/agent-project-open-issue-worktree +89 -0
  26. package/tools/bin/agent-project-open-pr-worktree +80 -0
  27. package/tools/bin/agent-project-publish-issue-pr +349 -0
  28. package/tools/bin/agent-project-reconcile-issue-session +1128 -0
  29. package/tools/bin/agent-project-reconcile-pr-session +1005 -0
  30. package/tools/bin/agent-project-retry-state +147 -0
  31. package/tools/bin/agent-project-run-claude-session +657 -0
  32. package/tools/bin/agent-project-run-codex-resilient +718 -0
  33. package/tools/bin/agent-project-run-codex-session +316 -0
  34. package/tools/bin/agent-project-run-kilo-session +27 -0
  35. package/tools/bin/agent-project-run-openclaw-session +984 -0
  36. package/tools/bin/agent-project-run-opencode-session +27 -0
  37. package/tools/bin/agent-project-sync-anchor-repo +128 -0
  38. package/tools/bin/agent-project-worker-status +143 -0
  39. package/tools/bin/audit-agent-worktrees.sh +310 -0
  40. package/tools/bin/audit-issue-routing.sh +11 -0
  41. package/tools/bin/audit-retained-layout.sh +58 -0
  42. package/tools/bin/audit-retained-overlap.sh +135 -0
  43. package/tools/bin/audit-retained-worktrees.sh +228 -0
  44. package/tools/bin/branch-verification-guard.sh +351 -0
  45. package/tools/bin/capture-worker.sh +18 -0
  46. package/tools/bin/check-skill-contracts.sh +324 -0
  47. package/tools/bin/cleanup-worktree.sh +44 -0
  48. package/tools/bin/codex-quota +31 -0
  49. package/tools/bin/create-follow-up-issue.sh +114 -0
  50. package/tools/bin/dashboard-launchd-bootstrap.sh +38 -0
  51. package/tools/bin/flow-config-lib.sh +2127 -0
  52. package/tools/bin/flow-resident-worker-lib.sh +683 -0
  53. package/tools/bin/flow-runtime-doctor.sh +97 -0
  54. package/tools/bin/flow-shell-lib.sh +266 -0
  55. package/tools/bin/heartbeat-recovery-preflight.sh +106 -0
  56. package/tools/bin/heartbeat-safe-auto.sh +551 -0
  57. package/tools/bin/install-dashboard-launchd.sh +152 -0
  58. package/tools/bin/install-project-launchd.sh +219 -0
  59. package/tools/bin/issue-publish-scope-guard.sh +242 -0
  60. package/tools/bin/issue-requires-local-workspace-install.sh +31 -0
  61. package/tools/bin/issue-resource-class.sh +12 -0
  62. package/tools/bin/kick-scheduler.sh +75 -0
  63. package/tools/bin/label-follow-up-issues.sh +14 -0
  64. package/tools/bin/new-pr-worktree.sh +50 -0
  65. package/tools/bin/new-worktree.sh +49 -0
  66. package/tools/bin/pr-risk.sh +12 -0
  67. package/tools/bin/prepare-worktree.sh +140 -0
  68. package/tools/bin/profile-activate.sh +109 -0
  69. package/tools/bin/profile-adopt.sh +219 -0
  70. package/tools/bin/profile-smoke.sh +461 -0
  71. package/tools/bin/project-init.sh +189 -0
  72. package/tools/bin/project-launchd-bootstrap.sh +54 -0
  73. package/tools/bin/project-remove.sh +155 -0
  74. package/tools/bin/project-runtime-supervisor.sh +56 -0
  75. package/tools/bin/project-runtimectl.sh +586 -0
  76. package/tools/bin/provider-cooldown-state.sh +166 -0
  77. package/tools/bin/publish-issue-worker.sh +31 -0
  78. package/tools/bin/reconcile-issue-worker.sh +34 -0
  79. package/tools/bin/reconcile-pr-worker.sh +34 -0
  80. package/tools/bin/record-verification.sh +71 -0
  81. package/tools/bin/render-architecture-infographics.sh +110 -0
  82. package/tools/bin/render-dashboard-demo-media.sh +333 -0
  83. package/tools/bin/render-dashboard-snapshot.py +16 -0
  84. package/tools/bin/render-flow-config.sh +86 -0
  85. package/tools/bin/retry-state.sh +31 -0
  86. package/tools/bin/reuse-issue-worktree.sh +75 -0
  87. package/tools/bin/run-codex-bypass.sh +3 -0
  88. package/tools/bin/run-codex-safe.sh +3 -0
  89. package/tools/bin/run-codex-task.sh +231 -0
  90. package/tools/bin/scaffold-profile.sh +374 -0
  91. package/tools/bin/serve-dashboard.sh +5 -0
  92. package/tools/bin/split-retained-slice.sh +124 -0
  93. package/tools/bin/start-issue-worker.sh +796 -0
  94. package/tools/bin/start-pr-fix-worker.sh +458 -0
  95. package/tools/bin/start-pr-merge-repair-worker.sh +8 -0
  96. package/tools/bin/start-pr-review-worker.sh +227 -0
  97. package/tools/bin/start-resident-issue-loop.sh +908 -0
  98. package/tools/bin/sync-agent-repo.sh +52 -0
  99. package/tools/bin/sync-dependency-baseline.sh +247 -0
  100. package/tools/bin/sync-pr-labels.sh +12 -0
  101. package/tools/bin/sync-recurring-issue-checklist.sh +274 -0
  102. package/tools/bin/sync-shared-agent-home.sh +214 -0
  103. package/tools/bin/sync-vscode-workspace.sh +157 -0
  104. package/tools/bin/test-smoke.sh +63 -0
  105. package/tools/bin/uninstall-project-launchd.sh +55 -0
  106. package/tools/bin/update-github-labels.sh +14 -0
  107. package/tools/bin/worker-status.sh +19 -0
  108. package/tools/bin/workflow-catalog.sh +77 -0
  109. package/tools/dashboard/app.js +286 -0
  110. package/tools/dashboard/dashboard_snapshot.py +466 -0
  111. package/tools/dashboard/index.html +41 -0
  112. package/tools/dashboard/server.py +64 -0
  113. package/tools/dashboard/styles.css +351 -0
  114. package/tools/templates/issue-prompt-template.md +109 -0
  115. package/tools/templates/pr-fix-template.md +120 -0
  116. package/tools/templates/pr-merge-repair-template.md +91 -0
  117. package/tools/templates/pr-review-template.md +62 -0
  118. package/tools/templates/scheduled-issue-prompt-template.md +62 -0
  119. package/tools/tests/test-agent-control-plane-npm-cli.sh +279 -0
  120. package/tools/tests/test-agent-github-update-labels-falls-back-to-repository-id.sh +56 -0
  121. package/tools/tests/test-agent-project-claude-session-wrapper-clears-stale-sandbox-artifacts.sh +89 -0
  122. package/tools/tests/test-agent-project-claude-session-wrapper-does-not-retry-provider-quota.sh +82 -0
  123. package/tools/tests/test-agent-project-claude-session-wrapper-retries-transient-failures.sh +90 -0
  124. package/tools/tests/test-agent-project-claude-session-wrapper-times-out.sh +73 -0
  125. package/tools/tests/test-agent-project-claude-session-wrapper.sh +103 -0
  126. package/tools/tests/test-agent-project-cleanup-session-orphan-fallback.sh +90 -0
  127. package/tools/tests/test-agent-project-cleanup-session-skip-worktree-cleanup.sh +90 -0
  128. package/tools/tests/test-agent-project-codex-live-thread-persist.sh +76 -0
  129. package/tools/tests/test-agent-project-codex-recovery.sh +731 -0
  130. package/tools/tests/test-agent-project-codex-session-wrapper-clears-stale-sandbox-artifacts.sh +105 -0
  131. package/tools/tests/test-agent-project-codex-session-wrapper.sh +97 -0
  132. package/tools/tests/test-agent-project-open-pr-worktree-config-prefix.sh +81 -0
  133. package/tools/tests/test-agent-project-openclaw-session-wrapper-clears-stale-sandbox-artifacts.sh +109 -0
  134. package/tools/tests/test-agent-project-openclaw-session-wrapper-infers-blocked-result-contract.sh +89 -0
  135. package/tools/tests/test-agent-project-openclaw-session-wrapper-recovers-literal-env-artifacts.sh +113 -0
  136. package/tools/tests/test-agent-project-openclaw-session-wrapper-recovers-version-mismatch.sh +135 -0
  137. package/tools/tests/test-agent-project-openclaw-session-wrapper-resident.sh +179 -0
  138. package/tools/tests/test-agent-project-openclaw-session-wrapper-reuses-existing-agent-after-add-race.sh +119 -0
  139. package/tools/tests/test-agent-project-openclaw-session-wrapper-terminates-rate-limit-hang.sh +91 -0
  140. package/tools/tests/test-agent-project-openclaw-session-wrapper.sh +117 -0
  141. package/tools/tests/test-agent-project-publish-issue-pr-prunes-stale-worktree-entry.sh +148 -0
  142. package/tools/tests/test-agent-project-publish-issue-pr-reads-archived-session.sh +146 -0
  143. package/tools/tests/test-agent-project-publish-issue-pr-recovers-final-head.sh +145 -0
  144. package/tools/tests/test-agent-project-publish-issue-pr-reuses-existing-worktree.sh +147 -0
  145. package/tools/tests/test-agent-project-reconcile-failure-reason.sh +456 -0
  146. package/tools/tests/test-agent-project-reconcile-issue-archived-session-fallback.sh +96 -0
  147. package/tools/tests/test-agent-project-reconcile-issue-before-blocked.sh +90 -0
  148. package/tools/tests/test-agent-project-reconcile-issue-host-verification-recovery-uses-recovered-worktree.sh +212 -0
  149. package/tools/tests/test-agent-project-reconcile-issue-host-verification-recovery.sh +207 -0
  150. package/tools/tests/test-agent-project-reconcile-issue-provider-quota-schedules-provider-cooldown.sh +101 -0
  151. package/tools/tests/test-agent-project-reconcile-issue-session-backfills-lane-metadata-from-worker-key.sh +113 -0
  152. package/tools/tests/test-agent-project-reconcile-issue-session-clears-stale-failed-summary.sh +117 -0
  153. package/tools/tests/test-agent-project-reconcile-issue-session-initializes-shared-agent-home.sh +55 -0
  154. package/tools/tests/test-agent-project-reconcile-issue-session-normalizes-runner-state.sh +125 -0
  155. package/tools/tests/test-agent-project-reconcile-issue-session-records-invalid-contract-summary.sh +118 -0
  156. package/tools/tests/test-agent-project-reconcile-issue-session-skips-duplicate-blocked-comment.sh +144 -0
  157. package/tools/tests/test-agent-project-reconcile-issue-session-standardizes-no-commits-blocker.sh +145 -0
  158. package/tools/tests/test-agent-project-reconcile-issue-session-synthesizes-blocked-comment.sh +139 -0
  159. package/tools/tests/test-agent-project-reconcile-pr-blocked-host-recovery.sh +242 -0
  160. package/tools/tests/test-agent-project-reconcile-pr-guard-blocked-no-commit.sh +142 -0
  161. package/tools/tests/test-agent-project-reconcile-pr-provider-quota-schedules-provider-cooldown.sh +106 -0
  162. package/tools/tests/test-agent-project-reconcile-pr-session-initializes-shared-agent-home.sh +66 -0
  163. package/tools/tests/test-agent-project-reconcile-pr-updated-branch-noop.sh +129 -0
  164. package/tools/tests/test-audit-agent-worktrees-active-launch-skips-git-inspection.sh +69 -0
  165. package/tools/tests/test-audit-agent-worktrees-broken-worktree.sh +43 -0
  166. package/tools/tests/test-audit-agent-worktrees-pending-launch-owner.sh +46 -0
  167. package/tools/tests/test-audit-agent-worktrees-unreconciled-owner.sh +79 -0
  168. package/tools/tests/test-audit-issue-routing-managed-branch-globs.sh +56 -0
  169. package/tools/tests/test-branch-verification-guard-generated-artifacts.sh +72 -0
  170. package/tools/tests/test-branch-verification-guard-targeted-coverage.sh +125 -0
  171. package/tools/tests/test-codex-quota-manager-failure-driven-rotation.sh +178 -0
  172. package/tools/tests/test-codex-quota-wrapper.sh +37 -0
  173. package/tools/tests/test-contribution-docs.sh +18 -0
  174. package/tools/tests/test-control-plane-dashboard-runtime-smoke.sh +343 -0
  175. package/tools/tests/test-create-follow-up-issue.sh +73 -0
  176. package/tools/tests/test-dashboard-launchd-bootstrap.sh +55 -0
  177. package/tools/tests/test-flow-export-execution-env-exports-repo-id.sh +30 -0
  178. package/tools/tests/test-flow-export-github-cli-auth-env-prefers-git-credential.sh +48 -0
  179. package/tools/tests/test-flow-github-api-repo-fallback-preserves-input.sh +85 -0
  180. package/tools/tests/test-flow-github-api-repo-prefers-explicit-repository-id.sh +60 -0
  181. package/tools/tests/test-flow-github-issue-list-falls-back-to-repository-id.sh +64 -0
  182. package/tools/tests/test-flow-github-pr-list-falls-back-to-repository-id.sh +77 -0
  183. package/tools/tests/test-flow-resident-can-reuse-does-not-leak-metadata.sh +52 -0
  184. package/tools/tests/test-flow-resident-reap-stale-controllers.sh +63 -0
  185. package/tools/tests/test-flow-resolve-codex-quota-tools.sh +104 -0
  186. package/tools/tests/test-flow-runtime-doctor-profile-selection.sh +27 -0
  187. package/tools/tests/test-heartbeat-codex-pr-linked-issue-exclusion.sh +79 -0
  188. package/tools/tests/test-heartbeat-hooks-enqueue-resident-issue-for-idle-controller.sh +115 -0
  189. package/tools/tests/test-heartbeat-hooks-enqueue-resident-issue-for-live-lane-controller.sh +117 -0
  190. package/tools/tests/test-heartbeat-hooks-start-resident-issue-loop-claude.sh +96 -0
  191. package/tools/tests/test-heartbeat-hooks-start-resident-issue-loop-codex.sh +96 -0
  192. package/tools/tests/test-heartbeat-hooks-start-resident-issue-loop.sh +96 -0
  193. package/tools/tests/test-heartbeat-loop-auth-wait-does-not-consume-capacity.sh +170 -0
  194. package/tools/tests/test-heartbeat-loop-blocked-recovery-lane.sh +201 -0
  195. package/tools/tests/test-heartbeat-loop-blocked-recovery-vs-pr-reservation.sh +201 -0
  196. package/tools/tests/test-heartbeat-loop-idle-resident-controller-does-not-block-launches.sh +160 -0
  197. package/tools/tests/test-heartbeat-loop-pr-launch-dedup.sh +133 -0
  198. package/tools/tests/test-heartbeat-loop-provider-cooldown-suppresses-launches.sh +157 -0
  199. package/tools/tests/test-heartbeat-loop-reaps-stale-resident-controller.sh +181 -0
  200. package/tools/tests/test-heartbeat-loop-waiting-provider-resident-controller-does-not-block-launches.sh +160 -0
  201. package/tools/tests/test-heartbeat-ready-issues-blocked-recovery.sh +134 -0
  202. package/tools/tests/test-heartbeat-safe-auto-dynamic-concurrency.sh +162 -0
  203. package/tools/tests/test-heartbeat-safe-auto-no-tmux-sessions.sh +136 -0
  204. package/tools/tests/test-heartbeat-safe-auto-openclaw-skips-codex-quota.sh +139 -0
  205. package/tools/tests/test-heartbeat-safe-auto-quota-health-signal.sh +119 -0
  206. package/tools/tests/test-heartbeat-safe-auto-stale-shared-loop-pid-does-not-skip.sh +140 -0
  207. package/tools/tests/test-heartbeat-safe-auto-static-capacity-without-quota-cache.sh +142 -0
  208. package/tools/tests/test-heartbeat-safe-auto-zero-healthy-pools.sh +141 -0
  209. package/tools/tests/test-heartbeat-sync-issue-labels-empty-schedule.sh +65 -0
  210. package/tools/tests/test-heartbeat-sync-open-agent-prs-terminal-clears-running.sh +179 -0
  211. package/tools/tests/test-install-dashboard-launchd.sh +78 -0
  212. package/tools/tests/test-install-project-launchd-adds-tool-paths.sh +87 -0
  213. package/tools/tests/test-install-project-launchd.sh +110 -0
  214. package/tools/tests/test-issue-local-workspace-install-policy.sh +81 -0
  215. package/tools/tests/test-issue-publish-scope-guard-docs-signal.sh +70 -0
  216. package/tools/tests/test-issue-reconcile-hooks-success-clears-blocked.sh +36 -0
  217. package/tools/tests/test-kick-scheduler-requires-explicit-profile.sh +47 -0
  218. package/tools/tests/test-label-follow-up-issues-falls-back-to-repository-id.sh +132 -0
  219. package/tools/tests/test-manual-operator-entrypoints-require-explicit-profile.sh +64 -0
  220. package/tools/tests/test-package-funding-metadata.sh +21 -0
  221. package/tools/tests/test-package-public-metadata.sh +62 -0
  222. package/tools/tests/test-placeholder-worker-adapters.sh +38 -0
  223. package/tools/tests/test-pr-reconcile-hooks-refreshes-recurring-issue-checklist.sh +110 -0
  224. package/tools/tests/test-pr-risk-cohesive-mobile-locale-scope.sh +70 -0
  225. package/tools/tests/test-pr-risk-fix-label-semantics.sh +114 -0
  226. package/tools/tests/test-pr-risk-local-first-no-checks.sh +70 -0
  227. package/tools/tests/test-prepare-worktree-simple-repo-baseline.sh +67 -0
  228. package/tools/tests/test-profile-activate.sh +33 -0
  229. package/tools/tests/test-profile-adopt-allow-missing-repo.sh +68 -0
  230. package/tools/tests/test-profile-adopt-skip-workspace-sync-missing-file.sh +61 -0
  231. package/tools/tests/test-profile-adopt-syncs-anchor-and-workspace.sh +90 -0
  232. package/tools/tests/test-profile-smoke-collision.sh +44 -0
  233. package/tools/tests/test-profile-smoke-invalid-claude-config.sh +31 -0
  234. package/tools/tests/test-profile-smoke-invalid-provider-pool.sh +68 -0
  235. package/tools/tests/test-profile-smoke-repo-slug-mismatch.sh +36 -0
  236. package/tools/tests/test-profile-smoke.sh +45 -0
  237. package/tools/tests/test-project-init-force-and-skip-sync.sh +61 -0
  238. package/tools/tests/test-project-init-repo-slug-mismatch.sh +29 -0
  239. package/tools/tests/test-project-init.sh +66 -0
  240. package/tools/tests/test-project-launchd-bootstrap.sh +66 -0
  241. package/tools/tests/test-project-remove.sh +150 -0
  242. package/tools/tests/test-project-runtime-supervisor.sh +47 -0
  243. package/tools/tests/test-project-runtimectl-launchd.sh +115 -0
  244. package/tools/tests/test-project-runtimectl-missing-profile.sh +54 -0
  245. package/tools/tests/test-project-runtimectl-start-falls-back-to-bootstrap.sh +108 -0
  246. package/tools/tests/test-project-runtimectl-status-reports-supervisor-as-heartbeat-parent.sh +95 -0
  247. package/tools/tests/test-project-runtimectl-status-supervisor-running.sh +59 -0
  248. package/tools/tests/test-project-runtimectl-stop-cancels-pending-kick.sh +85 -0
  249. package/tools/tests/test-project-runtimectl-stop-clears-running-labels.sh +78 -0
  250. package/tools/tests/test-project-runtimectl.sh +212 -0
  251. package/tools/tests/test-provider-cooldown-state-prefers-runtime-worker-context.sh +39 -0
  252. package/tools/tests/test-provider-cooldown-state.sh +59 -0
  253. package/tools/tests/test-public-repo-docs.sh +159 -0
  254. package/tools/tests/test-reconcile-pr-worker-acp-config-routing.sh +75 -0
  255. package/tools/tests/test-render-dashboard-snapshot.sh +149 -0
  256. package/tools/tests/test-render-flow-config-demo-profile.sh +36 -0
  257. package/tools/tests/test-render-flow-config-provider-pool-fallback.sh +81 -0
  258. package/tools/tests/test-render-flow-config.sh +52 -0
  259. package/tools/tests/test-run-codex-task-claude-routing.sh +125 -0
  260. package/tools/tests/test-run-codex-task-codex-resident-routing.sh +108 -0
  261. package/tools/tests/test-run-codex-task-kilo-routing.sh +98 -0
  262. package/tools/tests/test-run-codex-task-openclaw-resident-routing.sh +117 -0
  263. package/tools/tests/test-run-codex-task-openclaw-routing.sh +113 -0
  264. package/tools/tests/test-run-codex-task-opencode-routing.sh +98 -0
  265. package/tools/tests/test-run-codex-task-provider-pool-fallback-routing.sh +146 -0
  266. package/tools/tests/test-scaffold-profile.sh +108 -0
  267. package/tools/tests/test-serve-dashboard.sh +93 -0
  268. package/tools/tests/test-start-issue-worker-blocked-context.sh +129 -0
  269. package/tools/tests/test-start-issue-worker-blocks-complete-recurring-checklist.sh +189 -0
  270. package/tools/tests/test-start-issue-worker-local-install-routing.sh +157 -0
  271. package/tools/tests/test-start-issue-worker-profile-template-routing.sh +149 -0
  272. package/tools/tests/test-start-issue-worker-recurring-resident-reuse-codex.sh +212 -0
  273. package/tools/tests/test-start-issue-worker-recurring-resident-reuse.sh +219 -0
  274. package/tools/tests/test-start-issue-worker-renders-verification-snippet.sh +155 -0
  275. package/tools/tests/test-start-issue-worker-resident-reuse-falls-back-to-new-worktree.sh +199 -0
  276. package/tools/tests/test-start-pr-fix-worker-host-blocker-context.sh +275 -0
  277. package/tools/tests/test-start-resident-issue-loop-adopts-next-recurring-issue.sh +185 -0
  278. package/tools/tests/test-start-resident-issue-loop-clears-pending-while-waiting-due.sh +152 -0
  279. package/tools/tests/test-start-resident-issue-loop-consumes-queued-lease.sh +186 -0
  280. package/tools/tests/test-start-resident-issue-loop-fails-over-provider-pool.sh +212 -0
  281. package/tools/tests/test-start-resident-issue-loop-immediate-cycles.sh +148 -0
  282. package/tools/tests/test-start-resident-issue-loop-waits-for-provider.sh +194 -0
  283. package/tools/tests/test-start-resident-issue-loop-waits-for-terminal-reconcile-status.sh +198 -0
  284. package/tools/tests/test-start-resident-issue-loop-yields-to-live-lane-controller.sh +145 -0
  285. package/tools/tests/test-sync-pr-labels-fix-lane-uses-repair-queued.sh +67 -0
  286. package/tools/tests/test-sync-recurring-issue-checklist-backfills-workflow-complete-blocker.sh +70 -0
  287. package/tools/tests/test-sync-recurring-issue-checklist.sh +95 -0
  288. package/tools/tests/test-sync-shared-agent-home-local-source-root.sh +66 -0
  289. package/tools/tests/test-sync-shared-agent-home-preserves-unrelated-workflow-catalog-skill.sh +47 -0
  290. package/tools/tests/test-test-smoke.sh +86 -0
  291. package/tools/tests/test-uninstall-project-launchd.sh +37 -0
  292. package/tools/tests/test-update-github-labels-prefers-sibling-helper.sh +49 -0
  293. package/tools/tests/test-workflow-catalog.sh +43 -0
  294. package/tools/vendor/codex-quota/LICENSE +21 -0
  295. package/tools/vendor/codex-quota/README.md +459 -0
  296. package/tools/vendor/codex-quota/codex-quota.js +261 -0
  297. package/tools/vendor/codex-quota/lib/claude-accounts.js +226 -0
  298. package/tools/vendor/codex-quota/lib/claude-oauth.js +174 -0
  299. package/tools/vendor/codex-quota/lib/claude-tokens.js +471 -0
  300. package/tools/vendor/codex-quota/lib/claude-usage.js +929 -0
  301. package/tools/vendor/codex-quota/lib/codex-accounts.js +205 -0
  302. package/tools/vendor/codex-quota/lib/codex-tokens.js +326 -0
  303. package/tools/vendor/codex-quota/lib/codex-usage.js +32 -0
  304. package/tools/vendor/codex-quota/lib/color.js +72 -0
  305. package/tools/vendor/codex-quota/lib/constants.js +57 -0
  306. package/tools/vendor/codex-quota/lib/container.js +143 -0
  307. package/tools/vendor/codex-quota/lib/display.js +1111 -0
  308. package/tools/vendor/codex-quota/lib/fs.js +63 -0
  309. package/tools/vendor/codex-quota/lib/handlers.js +2060 -0
  310. package/tools/vendor/codex-quota/lib/jwt.js +33 -0
  311. package/tools/vendor/codex-quota/lib/oauth.js +486 -0
  312. package/tools/vendor/codex-quota/lib/paths.js +34 -0
  313. package/tools/vendor/codex-quota/lib/prompts.js +44 -0
  314. package/tools/vendor/codex-quota/lib/sync.js +1438 -0
  315. package/tools/vendor/codex-quota/lib/token-match.js +96 -0
  316. package/tools/vendor/codex-quota-manager/scripts/auto-switch.sh +500 -0
  317. package/tools/vendor/codex-quota-manager/scripts/batch-add.sh +123 -0
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ require("../bin/agent-control-plane.js");
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "agent-control-plane",
3
+ "version": "0.1.0",
4
+ "description": "Help a repo keep GitHub-driven coding agents running reliably without constant human babysitting",
5
+ "homepage": "https://github.com/ducminhuyen0319/agent-control-plane",
6
+ "bugs": {
7
+ "url": "https://github.com/ducminhuyen0319/agent-control-plane/issues"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/ducminhuyen0319/agent-control-plane.git"
12
+ },
13
+ "license": "MIT",
14
+ "funding": [
15
+ "https://github.com/sponsors/ducminhnguyen0319"
16
+ ],
17
+ "directories": {
18
+ "bin": "npm/public-bin"
19
+ },
20
+ "files": [
21
+ "README.md",
22
+ "SKILL.md",
23
+ "assets/workflow-catalog.json",
24
+ "bin",
25
+ "hooks",
26
+ "npm/bin",
27
+ "npm/public-bin",
28
+ "tools/bin",
29
+ "tools/dashboard/app.js",
30
+ "tools/dashboard/dashboard_snapshot.py",
31
+ "tools/dashboard/index.html",
32
+ "tools/dashboard/server.py",
33
+ "tools/dashboard/styles.css",
34
+ "tools/templates",
35
+ "tools/tests",
36
+ "tools/vendor/codex-quota/LICENSE",
37
+ "tools/vendor/codex-quota/codex-quota.js",
38
+ "tools/vendor/codex-quota/lib",
39
+ "tools/vendor/codex-quota-manager/scripts"
40
+ ],
41
+ "scripts": {
42
+ "doctor": "node ./npm/bin/agent-control-plane.js doctor",
43
+ "smoke": "node ./npm/bin/agent-control-plane.js smoke",
44
+ "test": "bash tools/tests/test-agent-control-plane-npm-cli.sh"
45
+ },
46
+ "keywords": [
47
+ "agents",
48
+ "automation",
49
+ "background-jobs",
50
+ "dashboard",
51
+ "control-plane",
52
+ "developer-tools",
53
+ "github-actions",
54
+ "github",
55
+ "npx",
56
+ "runtime"
57
+ ],
58
+ "engines": {
59
+ "node": ">=18"
60
+ }
61
+ }
@@ -0,0 +1,247 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ usage() {
5
+ cat <<'EOF'
6
+ Usage:
7
+ agent-cleanup-worktree --branch <branch-name> [--merged-base <ref>] [--path <worktree-path>] [--remote <name>] [--keep-remote] [--allow-unmerged] [--dry-run]
8
+
9
+ Safely cleans up a dedicated task branch/worktree:
10
+ - optionally prunes remote refs
11
+ - by default verifies the branch is merged into the base ref
12
+ - removes the dedicated worktree
13
+ - deletes the local branch
14
+ - deletes the remote branch if it still exists unless --keep-remote is set
15
+
16
+ Run this from a retained checkout, not from the task worktree being removed.
17
+ EOF
18
+ }
19
+
20
+ branch_name=""
21
+ merged_base=""
22
+ worktree_path=""
23
+ remote_name="origin"
24
+ keep_remote="false"
25
+ allow_unmerged="false"
26
+ dry_run="false"
27
+ branch_delete_flag="-d"
28
+
29
+ while [[ $# -gt 0 ]]; do
30
+ case "$1" in
31
+ --branch) branch_name="${2:-}"; shift 2 ;;
32
+ --merged-base) merged_base="${2:-}"; shift 2 ;;
33
+ --path) worktree_path="${2:-}"; shift 2 ;;
34
+ --remote) remote_name="${2:-}"; shift 2 ;;
35
+ --keep-remote) keep_remote="true"; shift ;;
36
+ --allow-unmerged) allow_unmerged="true"; shift ;;
37
+ --dry-run) dry_run="true"; shift ;;
38
+ --help|-h) usage; exit 0 ;;
39
+ *) echo "Unknown argument: $1" >&2; usage >&2; exit 1 ;;
40
+ esac
41
+ done
42
+
43
+ if [[ -z "$branch_name" ]]; then
44
+ echo "--branch is required" >&2
45
+ usage >&2
46
+ exit 1
47
+ fi
48
+
49
+ if [[ "$branch_name" == "main" || "$branch_name" == "master" ]]; then
50
+ echo "[agent-cleanup] Refusing to clean up protected branch: $branch_name" >&2
51
+ exit 1
52
+ fi
53
+
54
+ repo_root="$(git rev-parse --show-toplevel)"
55
+ git_common_dir="$(cd "$(git rev-parse --git-common-dir)" && pwd)"
56
+ source_root="$(dirname "$git_common_dir")"
57
+ current_branch="$(git rev-parse --abbrev-ref HEAD)"
58
+ current_worktree_root="$repo_root"
59
+ local_branch_exists="false"
60
+ remote_branch_exists="false"
61
+
62
+ if [[ -z "$merged_base" ]]; then
63
+ remote_head="$(git symbolic-ref --quiet --short refs/remotes/${remote_name}/HEAD 2>/dev/null || true)"
64
+ if [[ -n "$remote_head" ]]; then
65
+ merged_base="${remote_head#${remote_name}/}"
66
+ merged_base="${remote_name}/${merged_base}"
67
+ elif git show-ref --verify --quiet "refs/remotes/${remote_name}/main"; then
68
+ merged_base="${remote_name}/main"
69
+ elif git show-ref --verify --quiet "refs/heads/main"; then
70
+ merged_base="main"
71
+ else
72
+ merged_base="HEAD"
73
+ fi
74
+ fi
75
+
76
+ canonicalize_existing_dir() {
77
+ local target="$1"
78
+ if [[ ! -d "$target" ]]; then
79
+ return 1
80
+ fi
81
+ (
82
+ cd "$target"
83
+ pwd -P
84
+ )
85
+ }
86
+
87
+ prune_worktree_runtime_artifacts() {
88
+ local target="${1:?target worktree required}"
89
+ local candidate=""
90
+ local -a paths=(
91
+ "$target/.openclaw-artifacts"
92
+ "$target/node_modules"
93
+ "$target/apps/api/node_modules"
94
+ "$target/apps/mobile/node_modules"
95
+ "$target/apps/web/node_modules"
96
+ )
97
+
98
+ if [[ -d "$target/packages" ]]; then
99
+ while IFS= read -r candidate; do
100
+ paths+=("$candidate")
101
+ done < <(find "$target/packages" -mindepth 2 -maxdepth 2 -type d -name node_modules | sort)
102
+ fi
103
+
104
+ for candidate in "${paths[@]}"; do
105
+ [[ -e "$candidate" ]] || continue
106
+ rm -rf "$candidate"
107
+ done
108
+ }
109
+
110
+ resolve_branch_worktree_path() {
111
+ local line=""
112
+ local worktree=""
113
+ local branch=""
114
+ local ref="refs/heads/${branch_name}"
115
+ while IFS= read -r line || [[ -n "$line" ]]; do
116
+ if [[ -z "$line" ]]; then
117
+ if [[ "$branch" == "$ref" ]]; then
118
+ printf '%s\n' "$worktree"
119
+ return 0
120
+ fi
121
+ worktree=""
122
+ branch=""
123
+ continue
124
+ fi
125
+ case "$line" in
126
+ worktree\ *) worktree="${line#worktree }" ;;
127
+ branch\ *) branch="${line#branch }" ;;
128
+ esac
129
+ done < <(git worktree list --porcelain)
130
+ if [[ "$branch" == "$ref" ]]; then
131
+ printf '%s\n' "$worktree"
132
+ fi
133
+ }
134
+
135
+ if [[ "$current_branch" == "$branch_name" ]]; then
136
+ echo "[agent-cleanup] Refusing to clean up the branch currently checked out: $branch_name" >&2
137
+ exit 1
138
+ fi
139
+
140
+ if git show-ref --verify --quiet "refs/heads/${branch_name}"; then
141
+ local_branch_exists="true"
142
+ fi
143
+
144
+ resolved_branch_worktree_path=""
145
+ if [[ -z "$worktree_path" ]]; then
146
+ worktree_path="$(resolve_branch_worktree_path || true)"
147
+ resolved_branch_worktree_path="$worktree_path"
148
+ else
149
+ resolved_branch_worktree_path="$(resolve_branch_worktree_path || true)"
150
+ if [[ -z "$resolved_branch_worktree_path" ]]; then
151
+ echo "[agent-cleanup] Branch $branch_name is not associated with a dedicated worktree." >&2
152
+ echo "[agent-cleanup] Refusing to trust explicit --path '$worktree_path' without a Git-resolved branch worktree." >&2
153
+ exit 1
154
+ fi
155
+
156
+ explicit_canonical_path="$(canonicalize_existing_dir "$worktree_path" || true)"
157
+ branch_canonical_path="$(canonicalize_existing_dir "$resolved_branch_worktree_path" || true)"
158
+ if [[ -z "$explicit_canonical_path" ]]; then
159
+ echo "[agent-cleanup] Explicit --path '$worktree_path' does not exist as a directory." >&2
160
+ exit 1
161
+ fi
162
+ if [[ -z "$branch_canonical_path" ]]; then
163
+ echo "[agent-cleanup] Git resolved branch worktree '$resolved_branch_worktree_path' does not exist as a directory." >&2
164
+ exit 1
165
+ fi
166
+ if [[ "$explicit_canonical_path" != "$branch_canonical_path" ]]; then
167
+ echo "[agent-cleanup] Explicit --path '$worktree_path' does not match the worktree Git associates with branch '$branch_name' ('$resolved_branch_worktree_path')." >&2
168
+ exit 1
169
+ fi
170
+ worktree_path="$branch_canonical_path"
171
+ fi
172
+
173
+ if [[ "$dry_run" != "true" && "$remote_name" != "" ]]; then
174
+ git fetch --prune "$remote_name"
175
+ fi
176
+
177
+ if git show-ref --verify --quiet "refs/remotes/${remote_name}/${branch_name}"; then
178
+ remote_branch_exists="true"
179
+ fi
180
+
181
+ if [[ "$allow_unmerged" != "true" && "$local_branch_exists" == "true" ]]; then
182
+ if ! git merge-base --is-ancestor "$branch_name" "$merged_base"; then
183
+ echo "[agent-cleanup] Branch $branch_name is not merged into $merged_base" >&2
184
+ exit 1
185
+ fi
186
+ fi
187
+
188
+ if [[ "$allow_unmerged" == "true" ]]; then
189
+ branch_delete_flag="-D"
190
+ fi
191
+
192
+ if [[ -n "$worktree_path" && "$worktree_path" == "$current_worktree_root" ]]; then
193
+ echo "[agent-cleanup] Refusing to remove the current worktree: $worktree_path" >&2
194
+ exit 1
195
+ fi
196
+
197
+ if [[ -n "$worktree_path" ]]; then
198
+ canonical_worktree_path="$(canonicalize_existing_dir "$worktree_path" || true)"
199
+ if [[ -n "$canonical_worktree_path" && "$canonical_worktree_path" == "$source_root" ]]; then
200
+ echo "[agent-cleanup] Refusing to remove the canonical source checkout: $canonical_worktree_path" >&2
201
+ exit 1
202
+ fi
203
+ fi
204
+
205
+ if [[ "$dry_run" == "true" ]]; then
206
+ if [[ -n "$worktree_path" ]]; then
207
+ echo "git worktree remove --force '$worktree_path'"
208
+ fi
209
+ if [[ "$local_branch_exists" == "true" ]]; then
210
+ echo "git branch $branch_delete_flag '$branch_name'"
211
+ fi
212
+ if [[ "$remote_branch_exists" == "true" && "$keep_remote" != "true" ]]; then
213
+ echo "git push '$remote_name' --delete '$branch_name'"
214
+ fi
215
+ if [[ "$remote_name" != "" ]]; then
216
+ echo "git fetch --prune '$remote_name'"
217
+ fi
218
+ exit 0
219
+ fi
220
+
221
+ if [[ -n "$worktree_path" ]]; then
222
+ prune_worktree_runtime_artifacts "$worktree_path"
223
+ (
224
+ cd "$source_root"
225
+ git worktree remove --force "$worktree_path"
226
+ )
227
+ fi
228
+ if [[ "$local_branch_exists" == "true" ]]; then
229
+ git branch "$branch_delete_flag" "$branch_name"
230
+ fi
231
+ if [[ "$remote_branch_exists" == "true" && "$keep_remote" != "true" ]]; then
232
+ remote_delete_output="$(git push "$remote_name" --delete "$branch_name" 2>&1)" || remote_delete_status=$?
233
+ remote_delete_status="${remote_delete_status:-0}"
234
+ if [[ "$remote_delete_status" -ne 0 ]]; then
235
+ if rg -q "remote ref does not exist|unable to delete" <<<"$remote_delete_output"; then
236
+ :
237
+ else
238
+ printf '%s\n' "$remote_delete_output" >&2
239
+ exit "$remote_delete_status"
240
+ fi
241
+ fi
242
+ fi
243
+ if [[ "$remote_name" != "" ]]; then
244
+ git fetch --prune "$remote_name"
245
+ fi
246
+
247
+ echo "[agent-cleanup] cleanup complete for $branch_name"
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+ # shellcheck source=/dev/null
6
+ source "${SCRIPT_DIR}/flow-config-lib.sh"
7
+
8
+ usage() {
9
+ cat <<'EOF'
10
+ Usage:
11
+ agent-github-update-labels --repo-slug <owner/repo> --number <issue-or-pr-number> [--add LABEL]... [--remove LABEL]...
12
+
13
+ Merge requested label adds/removals into the current issue/PR labels and patch
14
+ the final sorted label set back to GitHub.
15
+ EOF
16
+ }
17
+
18
+ repo_slug=""
19
+ number=""
20
+ add_file="$(mktemp)"
21
+ remove_file="$(mktemp)"
22
+ trap 'rm -f "$add_file" "$remove_file"' EXIT
23
+
24
+ while [[ $# -gt 0 ]]; do
25
+ case "$1" in
26
+ --repo-slug) repo_slug="${2:-}"; shift 2 ;;
27
+ --number) number="${2:-}"; shift 2 ;;
28
+ --add)
29
+ printf '%s\n' "${2:?missing label after --add}" >>"$add_file"
30
+ shift 2
31
+ ;;
32
+ --remove)
33
+ printf '%s\n' "${2:?missing label after --remove}" >>"$remove_file"
34
+ shift 2
35
+ ;;
36
+ --help|-h) usage; exit 0 ;;
37
+ *)
38
+ echo "unknown argument: $1" >&2
39
+ usage >&2
40
+ exit 1
41
+ ;;
42
+ esac
43
+ done
44
+
45
+ if [[ -z "$repo_slug" || -z "$number" ]]; then
46
+ usage >&2
47
+ exit 1
48
+ fi
49
+
50
+ resource="issues/${number}"
51
+ current_json="$(flow_github_api_repo "${repo_slug}" "${resource}")"
52
+ add_json="$(jq -R . <"$add_file" | jq -s .)"
53
+ remove_json="$(jq -R . <"$remove_file" | jq -s .)"
54
+ payload="$(
55
+ CURRENT_JSON="$current_json" ADD_JSON="$add_json" REMOVE_JSON="$remove_json" node <<'EOF'
56
+ const current = JSON.parse(process.env.CURRENT_JSON || '{}');
57
+ const add = JSON.parse(process.env.ADD_JSON || '[]');
58
+ const remove = new Set(JSON.parse(process.env.REMOVE_JSON || '[]'));
59
+ const labels = new Set((current.labels || []).map((label) => label.name));
60
+ for (const label of remove) labels.delete(label);
61
+ for (const label of add) labels.add(label);
62
+ process.stdout.write(JSON.stringify({ labels: Array.from(labels).sort() }));
63
+ EOF
64
+ )"
65
+
66
+ printf '%s' "$payload" | flow_github_api_repo "${repo_slug}" "${resource}" --method PATCH --input - >/dev/null
@@ -0,0 +1,216 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ usage() {
5
+ cat <<'EOF'
6
+ Usage:
7
+ agent-init-worktree --branch <branch-name> --claim <task-id> [--base <ref>] [--path <worktree-path>] [--allow-unclaimed] [--no-bootstrap-deps] [--dry-run]
8
+
9
+ Creates a dedicated agent branch + worktree and writes a namespaced env file:
10
+ .agent-session.env
11
+
12
+ Options:
13
+ --branch <name> Required branch name for the task
14
+ --base <ref> Base ref for a new branch (default: remote HEAD, else origin/main, else main, else HEAD)
15
+ --path <path> Explicit worktree path
16
+ --claim <task-id> Required shared task claim, e.g. change-id:2.1
17
+ --allow-unclaimed Explicitly allow bootstrap without a claim
18
+ --no-bootstrap-deps Skip node_modules linking for the new worktree
19
+ --dry-run Print actions without creating anything
20
+ --help Show this help
21
+ EOF
22
+ }
23
+
24
+ branch_name=""
25
+ base_ref=""
26
+ worktree_path=""
27
+ claim_task_id=""
28
+ bootstrap_deps="true"
29
+ allow_unclaimed="false"
30
+ dry_run="false"
31
+
32
+ while [[ $# -gt 0 ]]; do
33
+ case "$1" in
34
+ --branch) branch_name="${2:-}"; shift 2 ;;
35
+ --base) base_ref="${2:-}"; shift 2 ;;
36
+ --path) worktree_path="${2:-}"; shift 2 ;;
37
+ --claim) claim_task_id="${2:-}"; shift 2 ;;
38
+ --allow-unclaimed) allow_unclaimed="true"; shift ;;
39
+ --no-bootstrap-deps) bootstrap_deps="false"; shift ;;
40
+ --dry-run) dry_run="true"; shift ;;
41
+ --help|-h) usage; exit 0 ;;
42
+ *) echo "Unknown argument: $1" >&2; usage >&2; exit 1 ;;
43
+ esac
44
+ done
45
+
46
+ if [[ -z "$branch_name" ]]; then
47
+ echo "--branch is required" >&2
48
+ usage >&2
49
+ exit 1
50
+ fi
51
+
52
+ if [[ "$branch_name" == "main" || "$branch_name" == "master" ]]; then
53
+ echo "[agent-init] Refusing to bootstrap protected branch: $branch_name" >&2
54
+ echo "[agent-init] Keep the retained checkout on $branch_name read-only for inspection only." >&2
55
+ echo "[agent-init] Create a dedicated task branch/worktree before doing any write work." >&2
56
+ exit 1
57
+ fi
58
+
59
+ if [[ -z "$claim_task_id" && "$allow_unclaimed" != "true" ]]; then
60
+ echo "--claim is required for agent task worktrees. Use --allow-unclaimed only for exceptional preserve/review cases." >&2
61
+ usage >&2
62
+ exit 1
63
+ fi
64
+
65
+ if [[ -z "$base_ref" ]]; then
66
+ remote_name="origin"
67
+ remote_head="$(git symbolic-ref --quiet --short "refs/remotes/${remote_name}/HEAD" 2>/dev/null || true)"
68
+ if [[ -n "$remote_head" ]]; then
69
+ base_ref="${remote_head}"
70
+ elif git show-ref --verify --quiet "refs/remotes/${remote_name}/main"; then
71
+ base_ref="${remote_name}/main"
72
+ elif git show-ref --verify --quiet "refs/heads/main"; then
73
+ base_ref="main"
74
+ else
75
+ base_ref="HEAD"
76
+ fi
77
+ fi
78
+
79
+ repo_root="$(git rev-parse --show-toplevel)"
80
+ git_common_dir="$(cd "$(git rev-parse --git-common-dir)" && pwd)"
81
+ source_root="$(dirname "$git_common_dir")"
82
+ repo_name="$(basename "$source_root")"
83
+ repo_parent="$(dirname "$source_root")"
84
+
85
+ branch_slug="$(
86
+ printf '%s' "$branch_name" |
87
+ tr '[:upper:]' '[:lower:]' |
88
+ sed 's#[^a-z0-9._/-]#-#g; s#/#-#g; s/-\{2,\}/-/g; s/^-//; s/-$//'
89
+ )"
90
+
91
+ if [[ -z "$branch_slug" ]]; then
92
+ echo "Failed to derive branch slug from: $branch_name" >&2
93
+ exit 1
94
+ fi
95
+
96
+ if [[ -z "$worktree_path" ]]; then
97
+ worktree_path="${repo_parent}/${repo_name}-${branch_slug}"
98
+ fi
99
+
100
+ namespace="$(
101
+ printf '%s' "$branch_slug" |
102
+ sed 's/[^a-z0-9]/-/g; s/-\{2,\}/-/g; s/^-//; s/-$//' |
103
+ cut -c1-24
104
+ )"
105
+
106
+ if [[ -z "$namespace" ]]; then
107
+ namespace="agent-local"
108
+ fi
109
+
110
+ run_id_raw="${AO_SESSION_ID:-${branch_slug}-$$}"
111
+ env_file="${worktree_path}/.agent-session.env"
112
+
113
+ branch_exists="false"
114
+ if git show-ref --verify --quiet "refs/heads/${branch_name}"; then
115
+ branch_exists="true"
116
+ fi
117
+
118
+ if [[ -e "$worktree_path" ]]; then
119
+ echo "Worktree path already exists: $worktree_path" >&2
120
+ exit 1
121
+ fi
122
+
123
+ cat <<EOF
124
+ [agent-init] repo=$repo_root
125
+ [agent-init] source_root=$source_root
126
+ [agent-init] branch=$branch_name
127
+ [agent-init] base_ref=$base_ref
128
+ [agent-init] worktree_path=$worktree_path
129
+ [agent-init] test_namespace=$namespace
130
+ [agent-init] branch_exists=$branch_exists
131
+ [agent-init] bootstrap_deps=$bootstrap_deps
132
+ [agent-init] claim_task_id=${claim_task_id:-<none>}
133
+ [agent-init] allow_unclaimed=$allow_unclaimed
134
+ EOF
135
+
136
+ if [[ "$dry_run" == "true" ]]; then
137
+ echo "[agent-init] dry-run only"
138
+ echo
139
+ echo "Planned commands:"
140
+ if [[ "$branch_exists" == "false" ]]; then
141
+ echo " git worktree add -b $branch_name $worktree_path $base_ref"
142
+ else
143
+ echo " git worktree add $worktree_path $branch_name"
144
+ fi
145
+ cat <<EOF
146
+
147
+ Planned env file: $env_file
148
+ export AGENT_TASK_BRANCH='$branch_name'
149
+ export AGENT_WORKTREE_PATH='$worktree_path'
150
+ export TEST_RUN_ID='$run_id_raw'
151
+ export API_TEST_RUN_ID='$run_id_raw'
152
+ export TEST_SEED_NAMESPACE='$namespace'
153
+ export E2E_SEED_NAMESPACE='$namespace'
154
+ export MOBILE_SEED_NAMESPACE='$namespace'
155
+ EOF
156
+ if [[ "$bootstrap_deps" == "true" ]]; then
157
+ echo " agent-bootstrap-worktree --source-root '$source_root' --path '$worktree_path'"
158
+ fi
159
+ if [[ -n "$claim_task_id" ]]; then
160
+ echo " agent-claim-task --task '$claim_task_id' --branch '$branch_name' --worktree '$worktree_path'"
161
+ fi
162
+ exit 0
163
+ fi
164
+
165
+ if [[ "$branch_exists" == "true" ]]; then
166
+ git worktree add "$worktree_path" "$branch_name"
167
+ else
168
+ git worktree add -b "$branch_name" "$worktree_path" "$base_ref"
169
+ fi
170
+
171
+ cat >"$env_file" <<EOF
172
+ export AGENT_TASK_BRANCH='$branch_name'
173
+ export AGENT_WORKTREE_PATH='$worktree_path'
174
+ export TEST_RUN_ID='$run_id_raw'
175
+ export API_TEST_RUN_ID='$run_id_raw'
176
+ export TEST_SEED_NAMESPACE='$namespace'
177
+ export E2E_SEED_NAMESPACE='$namespace'
178
+ export MOBILE_SEED_NAMESPACE='$namespace'
179
+ EOF
180
+
181
+ if [[ -n "$claim_task_id" ]]; then
182
+ printf "export AGENT_TASK_CLAIM='%s'\n" "$claim_task_id" >>"$env_file"
183
+ fi
184
+
185
+ if [[ "$bootstrap_deps" == "true" ]]; then
186
+ agent-bootstrap-worktree \
187
+ --source-root "$source_root" \
188
+ --path "$worktree_path"
189
+ fi
190
+
191
+ if [[ -n "$claim_task_id" ]]; then
192
+ agent-claim-task \
193
+ --task "$claim_task_id" \
194
+ --branch "$branch_name" \
195
+ --worktree "$worktree_path"
196
+ fi
197
+
198
+ if [[ -f "$HOME/.ao/bin/ao-metadata-helper.sh" ]]; then
199
+ # shellcheck source=/dev/null
200
+ source "$HOME/.ao/bin/ao-metadata-helper.sh" || true
201
+ if declare -F update_ao_metadata >/dev/null 2>&1; then
202
+ update_ao_metadata branch "$branch_name" || true
203
+ update_ao_metadata worktree "$worktree_path" || true
204
+ update_ao_metadata test_seed_namespace "$namespace" || true
205
+ fi
206
+ fi
207
+
208
+ cat <<EOF
209
+ [agent-init] created worktree: $worktree_path
210
+ [agent-init] wrote env file: $env_file
211
+ $(if [[ -n "$claim_task_id" ]]; then printf "[agent-init] claimed task: %s\n" "$claim_task_id"; fi)
212
+
213
+ Next:
214
+ cd '$worktree_path'
215
+ source .agent-session.env
216
+ EOF
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ usage() {
5
+ cat <<'EOF'
6
+ Usage:
7
+ agent-project-archive-run --runs-root <path> --history-root <path> --session <id> [--remove-file <path>]
8
+
9
+ Moves a completed run directory into the history root and optionally removes an
10
+ extra file such as a sandbox result file.
11
+ EOF
12
+ }
13
+
14
+ runs_root="${AGENT_PROJECT_RUNS_ROOT:-}"
15
+ history_root="${AGENT_PROJECT_HISTORY_ROOT:-}"
16
+ session=""
17
+ remove_file=""
18
+
19
+ while [[ $# -gt 0 ]]; do
20
+ case "$1" in
21
+ --runs-root) runs_root="${2:-}"; shift 2 ;;
22
+ --history-root) history_root="${2:-}"; shift 2 ;;
23
+ --session) session="${2:-}"; shift 2 ;;
24
+ --remove-file) remove_file="${2:-}"; shift 2 ;;
25
+ --help|-h) usage; exit 0 ;;
26
+ *) echo "Unknown argument: $1" >&2; usage >&2; exit 1 ;;
27
+ esac
28
+ done
29
+
30
+ if [[ -z "$runs_root" || -z "$history_root" || -z "$session" ]]; then
31
+ usage >&2
32
+ exit 1
33
+ fi
34
+
35
+ run_dir="${runs_root}/${session}"
36
+ archived_dir=""
37
+
38
+ mkdir -p "$history_root"
39
+
40
+ if [[ -d "$run_dir" && "$run_dir" == "${runs_root}/"* ]]; then
41
+ archived_dir="${history_root}/${session}-$(date +%Y%m%d-%H%M%S)"
42
+ mv "$run_dir" "$archived_dir"
43
+ fi
44
+
45
+ if [[ -n "$remove_file" && -f "$remove_file" ]]; then
46
+ rm -f "$remove_file"
47
+ fi
48
+
49
+ printf 'SESSION=%s\n' "$session"
50
+ printf 'RUN_DIR=%s\n' "$run_dir"
51
+ printf 'ARCHIVED_DIR=%s\n' "$archived_dir"
52
+ printf 'REMOVED_FILE=%s\n' "$remove_file"
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ usage() {
5
+ cat <<'EOF'
6
+ Usage:
7
+ agent-project-capture-worker --runs-root <path> --session <id> [--lines <n>]
8
+
9
+ Print the latest worker transcript, preferring a live tmux session and falling
10
+ back to the persisted run log.
11
+ EOF
12
+ }
13
+
14
+ runs_root="${AGENT_PROJECT_RUNS_ROOT:-}"
15
+ session=""
16
+ lines="80"
17
+
18
+ while [[ $# -gt 0 ]]; do
19
+ case "$1" in
20
+ --runs-root) runs_root="${2:-}"; shift 2 ;;
21
+ --session) session="${2:-}"; shift 2 ;;
22
+ --lines) lines="${2:-}"; shift 2 ;;
23
+ --help|-h) usage; exit 0 ;;
24
+ *) echo "Unknown argument: $1" >&2; usage >&2; exit 1 ;;
25
+ esac
26
+ done
27
+
28
+ if [[ -z "$runs_root" || -z "$session" ]]; then
29
+ usage >&2
30
+ exit 1
31
+ fi
32
+
33
+ output_file="${runs_root}/${session}/${session}.log"
34
+
35
+ if tmux has-session -t "$session" 2>/dev/null; then
36
+ tmux capture-pane -t "$session" -p | tail -n "$lines"
37
+ exit 0
38
+ fi
39
+
40
+ if [[ -f "$output_file" ]]; then
41
+ tail -n "$lines" "$output_file"
42
+ exit 0
43
+ fi
44
+
45
+ echo "no tmux session or log found for $session" >&2
46
+ exit 1