agent-control-plane 0.4.9 → 0.7.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 (87) hide show
  1. package/README.md +109 -13
  2. package/npm/bin/agent-control-plane.js +1 -1
  3. package/package.json +39 -33
  4. package/tools/bin/debug-session.sh +106 -0
  5. package/tools/bin/flow-config-lib.sh +13 -3508
  6. package/tools/bin/flow-execution-lib.sh +243 -0
  7. package/tools/bin/flow-forge-lib.sh +1770 -0
  8. package/tools/bin/flow-profile-lib.sh +335 -0
  9. package/tools/bin/flow-provider-lib.sh +981 -0
  10. package/tools/bin/flow-runtime-doctor-linux.sh +136 -0
  11. package/tools/bin/flow-runtime-doctor.sh +5 -1
  12. package/tools/bin/flow-session-lib.sh +317 -0
  13. package/tools/bin/install-project-systemd.sh +255 -0
  14. package/tools/bin/project-runtimectl.sh +45 -0
  15. package/tools/bin/project-systemd-bootstrap.sh +74 -0
  16. package/tools/bin/uninstall-project-systemd.sh +87 -0
  17. package/tools/dashboard/app.js +238 -8
  18. package/tools/dashboard/issue_queue_state.py +101 -0
  19. package/tools/dashboard/requirements.txt +3 -0
  20. package/tools/dashboard/server.py +250 -30
  21. package/tools/dashboard/styles.css +526 -455
  22. package/tools/bin/agent-cleanup-worktree +0 -247
  23. package/tools/bin/agent-github-update-labels +0 -105
  24. package/tools/bin/agent-init-worktree +0 -216
  25. package/tools/bin/agent-project-archive-run +0 -52
  26. package/tools/bin/agent-project-capture-worker +0 -46
  27. package/tools/bin/agent-project-catch-up-issue-pr-links +0 -118
  28. package/tools/bin/agent-project-catch-up-merged-prs +0 -195
  29. package/tools/bin/agent-project-catch-up-scheduled-issue-retries +0 -123
  30. package/tools/bin/agent-project-cleanup-session +0 -513
  31. package/tools/bin/agent-project-detached-launch +0 -127
  32. package/tools/bin/agent-project-heartbeat-loop +0 -1029
  33. package/tools/bin/agent-project-open-issue-worktree +0 -89
  34. package/tools/bin/agent-project-open-pr-worktree +0 -80
  35. package/tools/bin/agent-project-publish-issue-pr +0 -468
  36. package/tools/bin/agent-project-reconcile-issue-session +0 -1409
  37. package/tools/bin/agent-project-reconcile-pr-session +0 -1288
  38. package/tools/bin/agent-project-retry-state +0 -158
  39. package/tools/bin/agent-project-run-claude-session +0 -805
  40. package/tools/bin/agent-project-run-codex-resilient +0 -963
  41. package/tools/bin/agent-project-run-codex-session +0 -435
  42. package/tools/bin/agent-project-run-kilo-session +0 -369
  43. package/tools/bin/agent-project-run-ollama-session +0 -658
  44. package/tools/bin/agent-project-run-openclaw-session +0 -1309
  45. package/tools/bin/agent-project-run-opencode-session +0 -377
  46. package/tools/bin/agent-project-run-pi-session +0 -479
  47. package/tools/bin/agent-project-sync-anchor-repo +0 -139
  48. package/tools/bin/agent-project-sync-source-repo-main +0 -163
  49. package/tools/bin/agent-project-worker-status +0 -188
  50. package/tools/bin/branch-verification-guard.sh +0 -364
  51. package/tools/bin/capture-worker.sh +0 -18
  52. package/tools/bin/cleanup-worktree.sh +0 -52
  53. package/tools/bin/codex-quota +0 -31
  54. package/tools/bin/create-follow-up-issue.sh +0 -114
  55. package/tools/bin/dashboard-launchd-bootstrap.sh +0 -50
  56. package/tools/bin/issue-publish-localization-guard.sh +0 -142
  57. package/tools/bin/issue-publish-scope-guard.sh +0 -242
  58. package/tools/bin/issue-requires-local-workspace-install.sh +0 -31
  59. package/tools/bin/issue-resource-class.sh +0 -12
  60. package/tools/bin/kick-scheduler.sh +0 -75
  61. package/tools/bin/label-follow-up-issues.sh +0 -14
  62. package/tools/bin/new-pr-worktree.sh +0 -50
  63. package/tools/bin/new-worktree.sh +0 -49
  64. package/tools/bin/pr-risk.sh +0 -12
  65. package/tools/bin/prepare-worktree.sh +0 -142
  66. package/tools/bin/provider-cooldown-state.sh +0 -204
  67. package/tools/bin/publish-issue-worker.sh +0 -31
  68. package/tools/bin/reconcile-bootstrap-lib.sh +0 -113
  69. package/tools/bin/reconcile-issue-worker.sh +0 -34
  70. package/tools/bin/reconcile-pr-worker.sh +0 -34
  71. package/tools/bin/record-verification.sh +0 -71
  72. package/tools/bin/render-flow-config.sh +0 -98
  73. package/tools/bin/resident-issue-controller-lib.sh +0 -448
  74. package/tools/bin/retry-state.sh +0 -31
  75. package/tools/bin/reuse-issue-worktree.sh +0 -121
  76. package/tools/bin/run-codex-bypass.sh +0 -3
  77. package/tools/bin/run-codex-safe.sh +0 -3
  78. package/tools/bin/run-codex-task.sh +0 -280
  79. package/tools/bin/serve-dashboard.sh +0 -5
  80. package/tools/bin/start-issue-worker.sh +0 -943
  81. package/tools/bin/start-pr-fix-worker.sh +0 -528
  82. package/tools/bin/start-pr-merge-repair-worker.sh +0 -8
  83. package/tools/bin/start-pr-review-worker.sh +0 -261
  84. package/tools/bin/start-resident-issue-loop.sh +0 -499
  85. package/tools/bin/update-github-labels.sh +0 -14
  86. package/tools/bin/worker-status.sh +0 -19
  87. package/tools/bin/workflow-catalog.sh +0 -77
@@ -1,163 +0,0 @@
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
- CONFIG_YAML="${ACP_SOURCE_REPO_SYNC_CONFIG_YAML:-$(resolve_flow_config_yaml "${BASH_SOURCE[0]}")}"
9
- REPO_SLUG="$(flow_resolve_repo_slug "${CONFIG_YAML}")"
10
- SOURCE_REPO_ROOT="$(flow_resolve_source_repo_root "${CONFIG_YAML}")"
11
- DEFAULT_BRANCH="$(flow_resolve_default_branch "${CONFIG_YAML}")"
12
- STATE_ROOT="$(flow_resolve_state_root "${CONFIG_YAML}")"
13
- SYNC_STATE_FILE="${STATE_ROOT}/source-repo-main-sync.env"
14
- FORGE_PROVIDER="$(flow_forge_provider)"
15
- REMOTE_OVERRIDE="${ACP_SOURCE_SYNC_REMOTE:-${F_LOSNING_SOURCE_SYNC_REMOTE:-}}"
16
-
17
- write_state() {
18
- local status="${1:-}"
19
- local remote_name="${2:-}"
20
- local remote_sha="${3:-}"
21
- local local_sha="${4:-}"
22
- local detail="${5:-}"
23
-
24
- mkdir -p "$(dirname "${SYNC_STATE_FILE}")"
25
- {
26
- printf 'STATUS=%s\n' "${status}"
27
- printf 'UPDATED_AT=%s\n' "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
28
- printf 'SOURCE_REPO_ROOT=%s\n' "${SOURCE_REPO_ROOT}"
29
- printf 'DEFAULT_BRANCH=%s\n' "${DEFAULT_BRANCH}"
30
- printf 'REMOTE_NAME=%s\n' "${remote_name}"
31
- printf 'REMOTE_SHA=%s\n' "${remote_sha}"
32
- printf 'LOCAL_SHA=%s\n' "${local_sha}"
33
- printf 'DETAIL=%s\n' "${detail}"
34
- } >"${SYNC_STATE_FILE}"
35
- }
36
-
37
- git_ref_sha() {
38
- local repo_root="${1:?repo root required}"
39
- local ref_name="${2:?ref required}"
40
- git -C "${repo_root}" rev-parse --verify --quiet "${ref_name}" 2>/dev/null || true
41
- }
42
-
43
- git_has_remote() {
44
- local repo_root="${1:?repo root required}"
45
- local remote_name="${2:?remote required}"
46
- git -C "${repo_root}" remote get-url "${remote_name}" >/dev/null 2>&1
47
- }
48
-
49
- discover_remote_name() {
50
- local remote_name=""
51
-
52
- if [[ -n "${REMOTE_OVERRIDE}" ]] && git_has_remote "${SOURCE_REPO_ROOT}" "${REMOTE_OVERRIDE}"; then
53
- printf '%s\n' "${REMOTE_OVERRIDE}"
54
- return 0
55
- fi
56
-
57
- case "${FORGE_PROVIDER}" in
58
- gitea)
59
- if git_has_remote "${SOURCE_REPO_ROOT}" "gitea"; then
60
- printf 'gitea\n'
61
- return 0
62
- fi
63
- ;;
64
- github)
65
- if git_has_remote "${SOURCE_REPO_ROOT}" "origin"; then
66
- printf 'origin\n'
67
- return 0
68
- fi
69
- ;;
70
- esac
71
-
72
- while IFS= read -r remote_name; do
73
- [[ -n "${remote_name}" ]] || continue
74
- if [[ "$(flow_git_remote_repo_slug "${SOURCE_REPO_ROOT}" "${remote_name}" 2>/dev/null || true)" == "${REPO_SLUG}" ]]; then
75
- printf '%s\n' "${remote_name}"
76
- return 0
77
- fi
78
- done < <(git -C "${SOURCE_REPO_ROOT}" remote)
79
-
80
- return 1
81
- }
82
-
83
- if [[ -z "${SOURCE_REPO_ROOT}" ]]; then
84
- write_state "skipped" "" "" "" "source-repo-root-unset"
85
- printf 'SOURCE_REPO_SYNC_STATUS=skipped\nSOURCE_REPO_SYNC_REASON=source-repo-root-unset\n'
86
- exit 0
87
- fi
88
-
89
- if [[ ! -d "${SOURCE_REPO_ROOT}/.git" && ! -f "${SOURCE_REPO_ROOT}/.git" ]]; then
90
- write_state "skipped" "" "" "" "source-repo-not-git"
91
- printf 'SOURCE_REPO_SYNC_STATUS=skipped\nSOURCE_REPO_SYNC_REASON=source-repo-not-git\nSOURCE_REPO_ROOT=%s\n' "${SOURCE_REPO_ROOT}"
92
- exit 0
93
- fi
94
-
95
- REMOTE_NAME="$(discover_remote_name || true)"
96
- if [[ -z "${REMOTE_NAME}" ]]; then
97
- write_state "skipped" "" "" "" "remote-not-found"
98
- printf 'SOURCE_REPO_SYNC_STATUS=skipped\nSOURCE_REPO_SYNC_REASON=remote-not-found\nSOURCE_REPO_ROOT=%s\n' "${SOURCE_REPO_ROOT}"
99
- exit 0
100
- fi
101
-
102
- if ! git -C "${SOURCE_REPO_ROOT}" fetch "${REMOTE_NAME}" "+refs/heads/${DEFAULT_BRANCH}:refs/remotes/${REMOTE_NAME}/${DEFAULT_BRANCH}" --prune >/dev/null 2>&1; then
103
- write_state "failed" "${REMOTE_NAME}" "" "" "fetch-failed"
104
- printf 'SOURCE_REPO_SYNC_STATUS=failed\nSOURCE_REPO_SYNC_REASON=fetch-failed\nSOURCE_REPO_ROOT=%s\nREMOTE_NAME=%s\n' "${SOURCE_REPO_ROOT}" "${REMOTE_NAME}"
105
- exit 1
106
- fi
107
-
108
- remote_sha="$(git_ref_sha "${SOURCE_REPO_ROOT}" "refs/remotes/${REMOTE_NAME}/${DEFAULT_BRANCH}")"
109
- local_branch_sha="$(git_ref_sha "${SOURCE_REPO_ROOT}" "refs/heads/${DEFAULT_BRANCH}")"
110
- current_branch="$(git -C "${SOURCE_REPO_ROOT}" symbolic-ref --quiet --short HEAD 2>/dev/null || true)"
111
-
112
- if [[ -z "${remote_sha}" || -z "${local_branch_sha}" ]]; then
113
- write_state "failed" "${REMOTE_NAME}" "${remote_sha}" "${local_branch_sha}" "missing-branch-ref"
114
- printf 'SOURCE_REPO_SYNC_STATUS=failed\nSOURCE_REPO_SYNC_REASON=missing-branch-ref\nSOURCE_REPO_ROOT=%s\nREMOTE_NAME=%s\n' "${SOURCE_REPO_ROOT}" "${REMOTE_NAME}"
115
- exit 1
116
- fi
117
-
118
- if [[ "${remote_sha}" == "${local_branch_sha}" ]]; then
119
- write_state "unchanged" "${REMOTE_NAME}" "${remote_sha}" "${local_branch_sha}" "already-current"
120
- printf 'SOURCE_REPO_SYNC_STATUS=unchanged\nSOURCE_REPO_ROOT=%s\nREMOTE_NAME=%s\nSOURCE_REPO_SYNC_SHA=%s\n' "${SOURCE_REPO_ROOT}" "${REMOTE_NAME}" "${remote_sha}"
121
- exit 0
122
- fi
123
-
124
- if [[ "${current_branch}" == "${DEFAULT_BRANCH}" ]]; then
125
- if [[ -n "$(git -C "${SOURCE_REPO_ROOT}" status --porcelain 2>/dev/null || true)" ]]; then
126
- write_state "blocked" "${REMOTE_NAME}" "${remote_sha}" "${local_branch_sha}" "working-tree-dirty"
127
- printf 'SOURCE_REPO_SYNC_STATUS=blocked\nSOURCE_REPO_SYNC_REASON=working-tree-dirty\nSOURCE_REPO_ROOT=%s\nREMOTE_NAME=%s\nLOCAL_SHA=%s\nREMOTE_SHA=%s\n' \
128
- "${SOURCE_REPO_ROOT}" "${REMOTE_NAME}" "${local_branch_sha}" "${remote_sha}"
129
- exit 0
130
- fi
131
-
132
- if git -C "${SOURCE_REPO_ROOT}" merge-base --is-ancestor "${local_branch_sha}" "${remote_sha}" >/dev/null 2>&1; then
133
- git -C "${SOURCE_REPO_ROOT}" merge --ff-only "refs/remotes/${REMOTE_NAME}/${DEFAULT_BRANCH}" >/dev/null
134
- updated_sha="$(git_ref_sha "${SOURCE_REPO_ROOT}" "refs/heads/${DEFAULT_BRANCH}")"
135
- write_state "updated" "${REMOTE_NAME}" "${remote_sha}" "${updated_sha}" "fast-forward-checked-out-branch"
136
- printf 'SOURCE_REPO_SYNC_STATUS=updated\nSOURCE_REPO_ROOT=%s\nREMOTE_NAME=%s\nSOURCE_REPO_SYNC_SHA=%s\n' "${SOURCE_REPO_ROOT}" "${REMOTE_NAME}" "${updated_sha}"
137
- exit 0
138
- fi
139
-
140
- if git -C "${SOURCE_REPO_ROOT}" merge --no-edit "refs/remotes/${REMOTE_NAME}/${DEFAULT_BRANCH}" >/dev/null 2>&1; then
141
- updated_sha="$(git_ref_sha "${SOURCE_REPO_ROOT}" "refs/heads/${DEFAULT_BRANCH}")"
142
- write_state "updated" "${REMOTE_NAME}" "${remote_sha}" "${updated_sha}" "merge-checked-out-branch"
143
- printf 'SOURCE_REPO_SYNC_STATUS=updated\nSOURCE_REPO_ROOT=%s\nREMOTE_NAME=%s\nSOURCE_REPO_SYNC_SHA=%s\n' "${SOURCE_REPO_ROOT}" "${REMOTE_NAME}" "${updated_sha}"
144
- exit 0
145
- fi
146
-
147
- git -C "${SOURCE_REPO_ROOT}" merge --abort >/dev/null 2>&1 || true
148
- write_state "blocked" "${REMOTE_NAME}" "${remote_sha}" "${local_branch_sha}" "merge-conflict"
149
- printf 'SOURCE_REPO_SYNC_STATUS=blocked\nSOURCE_REPO_SYNC_REASON=merge-conflict\nSOURCE_REPO_ROOT=%s\nREMOTE_NAME=%s\nLOCAL_SHA=%s\nREMOTE_SHA=%s\n' \
150
- "${SOURCE_REPO_ROOT}" "${REMOTE_NAME}" "${local_branch_sha}" "${remote_sha}"
151
- exit 0
152
- fi
153
-
154
- if ! git -C "${SOURCE_REPO_ROOT}" merge-base --is-ancestor "${local_branch_sha}" "${remote_sha}" >/dev/null 2>&1; then
155
- write_state "blocked" "${REMOTE_NAME}" "${remote_sha}" "${local_branch_sha}" "local-main-diverged"
156
- printf 'SOURCE_REPO_SYNC_STATUS=blocked\nSOURCE_REPO_SYNC_REASON=local-main-diverged\nSOURCE_REPO_ROOT=%s\nREMOTE_NAME=%s\nLOCAL_SHA=%s\nREMOTE_SHA=%s\n' \
157
- "${SOURCE_REPO_ROOT}" "${REMOTE_NAME}" "${local_branch_sha}" "${remote_sha}"
158
- exit 0
159
- fi
160
-
161
- git -C "${SOURCE_REPO_ROOT}" update-ref "refs/heads/${DEFAULT_BRANCH}" "${remote_sha}" "${local_branch_sha}"
162
- write_state "updated" "${REMOTE_NAME}" "${remote_sha}" "${remote_sha}" "fast-forward-local-ref"
163
- printf 'SOURCE_REPO_SYNC_STATUS=updated\nSOURCE_REPO_ROOT=%s\nREMOTE_NAME=%s\nSOURCE_REPO_SYNC_SHA=%s\n' "${SOURCE_REPO_ROOT}" "${REMOTE_NAME}" "${remote_sha}"
@@ -1,188 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- usage() {
5
- cat <<'EOF'
6
- Usage:
7
- agent-project-worker-status --runs-root <path> --session <id> [--exit-marker <marker>]
8
-
9
- Reads a project-lane run directory and reports session status using tmux plus the
10
- worker log exit marker.
11
- EOF
12
- }
13
-
14
- runs_root="${AGENT_PROJECT_RUNS_ROOT:-}"
15
- session=""
16
- exit_marker="__\\w+_EXIT__:"
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
- --exit-marker) exit_marker="${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
- run_dir="${runs_root}/${session}"
34
- meta_file="${run_dir}/run.env"
35
- result_file="${run_dir}/result.env"
36
- runner_state_file="${run_dir}/runner.env"
37
- output_file="${run_dir}/${session}.log"
38
-
39
- status="UNKNOWN"
40
- exit_code=""
41
- result_only_completion="no"
42
- failure_reason=""
43
- runner_state=""
44
- thread_id=""
45
- last_exit_code=""
46
-
47
- failure_reason_from_output() {
48
- [[ -f "$output_file" ]] || return 1
49
-
50
- if rg -qi "You've hit your usage limit|You have reached your Codex usage limits|visit https://chatgpt.com/codex/settings/usage|Upgrade to Pro|rate limit exceeded|quota exceeded|usage cap (reached|exceeded)|usage quota (reached|exceeded)" "$output_file"; then
51
- printf 'usage-limit\n'
52
- return 0
53
- fi
54
-
55
- if rg -qi 'stale-run no-codex-output-before-stall-threshold|no-codex-output-before-stall-threshold' "$output_file"; then
56
- printf 'no-codex-output-before-stall-threshold\n'
57
- return 0
58
- fi
59
-
60
- if rg -qi 'stale-run no-codex-progress-before-stall-threshold|no-codex-progress-before-stall-threshold' "$output_file"; then
61
- printf 'no-codex-progress-before-stall-threshold\n'
62
- return 0
63
- fi
64
-
65
- # Recover Codex startup stalls when the wrapper was archived before it could
66
- # flush a terminal runner.env state. This is intentionally narrow: the log
67
- # must show a turn started, but no tool activity or turn completion.
68
- if rg -q '"type":"turn.started"' "$output_file" \
69
- && ! rg -q '"type":"item.started"|"type":"item.completed"|"type":"turn.completed"' "$output_file"; then
70
- printf 'no-codex-progress-before-stall-threshold\n'
71
- return 0
72
- fi
73
-
74
- return 1
75
- }
76
-
77
- if tmux has-session -t "$session" 2>/dev/null; then
78
- status="RUNNING"
79
- fi
80
-
81
- if [[ -f "$runner_state_file" ]]; then
82
- set -a
83
- # shellcheck source=/dev/null
84
- source "$runner_state_file"
85
- set +a
86
- runner_state="${RUNNER_STATE:-}"
87
- thread_id="${THREAD_ID:-}"
88
- last_exit_code="${LAST_EXIT_CODE:-}"
89
- if [[ -z "$failure_reason" ]]; then
90
- failure_reason="${LAST_FAILURE_REASON:-}"
91
- fi
92
- fi
93
-
94
- if [[ "$status" == "UNKNOWN" ]]; then
95
- case "$runner_state" in
96
- succeeded)
97
- status="SUCCEEDED"
98
- ;;
99
- failed)
100
- status="FAILED"
101
- if [[ -z "$exit_code" && -n "$last_exit_code" ]]; then
102
- exit_code="$last_exit_code"
103
- fi
104
- ;;
105
- esac
106
- fi
107
-
108
- if [[ "$status" == "UNKNOWN" && -f "$output_file" ]]; then
109
- exit_match="$(rg -o "${exit_marker}[0-9]+" "$output_file" | tail -n 1 || true)"
110
- if [[ -n "$exit_match" ]]; then
111
- exit_code="${exit_match##*:}"
112
- if [[ "$exit_code" == "0" ]]; then
113
- status="SUCCEEDED"
114
- else
115
- status="FAILED"
116
- fi
117
- fi
118
- fi
119
-
120
- if [[ "$status" == "UNKNOWN" && -n "$runner_state" ]]; then
121
- case "$runner_state" in
122
- running|waiting-auth-refresh|switching-account)
123
- # Tmux session is gone and runner never reached a terminal state.
124
- # This detects crashes where the worker process died before updating
125
- # runner.env or writing an exit marker.
126
- # Check BEFORE stale result.env to avoid false SUCCEEDED when a prior
127
- # cycle's result.env happens to exist.
128
- status="FAILED"
129
- failure_reason="$(failure_reason_from_output || true)"
130
- if [[ -z "$failure_reason" ]]; then
131
- failure_reason="runner-aborted-before-completion"
132
- fi
133
- if [[ -z "$exit_code" && -n "$last_exit_code" ]]; then
134
- exit_code="$last_exit_code"
135
- fi
136
- ;;
137
- esac
138
- fi
139
-
140
- if [[ "$status" == "UNKNOWN" && -f "$result_file" ]]; then
141
- # A worker that managed to persist result.env already completed its contract,
142
- # even if the tmux session disappeared before the exit marker was flushed.
143
- # Check BEFORE failure_reason_from_output so that a completed result.env
144
- # is not overridden by transient failure text in the log.
145
- status="SUCCEEDED"
146
- result_only_completion="yes"
147
- fi
148
-
149
- if [[ "$status" == "UNKNOWN" && -z "$failure_reason" ]]; then
150
- failure_reason="$(failure_reason_from_output || true)"
151
- if [[ -n "$failure_reason" ]]; then
152
- status="FAILED"
153
- fi
154
- fi
155
-
156
- if [[ "$status" == "UNKNOWN" && -f "$output_file" ]]; then
157
- if rg -qi "You've hit your usage limit|You have reached your Codex usage limits|visit https://chatgpt.com/codex/settings/usage|Upgrade to Pro|rate limit exceeded|quota exceeded|usage cap (reached|exceeded)|usage quota (reached|exceeded)" "$output_file"; then
158
- status="FAILED"
159
- failure_reason="usage-limit"
160
- fi
161
- fi
162
-
163
- printf 'SESSION=%s\n' "$session"
164
- printf 'STATUS=%s\n' "$status"
165
- if [[ -f "$meta_file" ]]; then
166
- cat "$meta_file"
167
- printf 'META_FILE=%s\n' "$meta_file"
168
- fi
169
- if [[ -f "$runner_state_file" ]]; then
170
- cat "$runner_state_file"
171
- printf 'RUNNER_STATE_FILE=%s\n' "$runner_state_file"
172
- fi
173
- if [[ -f "$result_file" ]]; then
174
- cat "$result_file"
175
- printf 'RESULT_FILE=%s\n' "$result_file"
176
- fi
177
- if [[ "$result_only_completion" == "yes" ]]; then
178
- printf 'RESULT_ONLY_COMPLETION=yes\n'
179
- fi
180
- if [[ -n "$exit_code" ]]; then
181
- printf 'EXIT_CODE=%s\n' "$exit_code"
182
- fi
183
- if [[ -n "$failure_reason" ]]; then
184
- printf 'FAILURE_REASON=%s\n' "$failure_reason"
185
- fi
186
- if [[ -n "$thread_id" ]]; then
187
- printf 'THREAD_ID=%s\n' "$thread_id"
188
- fi