agent-control-plane 0.1.1 → 0.1.3

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 (184) hide show
  1. package/README.md +6 -0
  2. package/npm/bin/agent-control-plane.js +149 -5
  3. package/package.json +2 -3
  4. package/tools/vendor/codex-quota/README.md +8 -16
  5. package/tools/vendor/codex-quota/lib/claude-accounts.js +2 -68
  6. package/tools/vendor/codex-quota/lib/claude-usage.js +76 -667
  7. package/tools/vendor/codex-quota/lib/display.js +6 -14
  8. package/tools/vendor/codex-quota/lib/handlers.js +32 -117
  9. package/tools/vendor/codex-quota/lib/sync.js +9 -14
  10. package/tools/tests/test-agent-control-plane-npm-cli.sh +0 -280
  11. package/tools/tests/test-agent-github-update-labels-falls-back-to-repository-id.sh +0 -56
  12. package/tools/tests/test-agent-project-claude-session-wrapper-clears-stale-sandbox-artifacts.sh +0 -89
  13. package/tools/tests/test-agent-project-claude-session-wrapper-does-not-retry-provider-quota.sh +0 -82
  14. package/tools/tests/test-agent-project-claude-session-wrapper-retries-transient-failures.sh +0 -90
  15. package/tools/tests/test-agent-project-claude-session-wrapper-times-out.sh +0 -73
  16. package/tools/tests/test-agent-project-claude-session-wrapper.sh +0 -103
  17. package/tools/tests/test-agent-project-cleanup-session-orphan-fallback.sh +0 -90
  18. package/tools/tests/test-agent-project-cleanup-session-skip-worktree-cleanup.sh +0 -90
  19. package/tools/tests/test-agent-project-codex-live-thread-persist.sh +0 -76
  20. package/tools/tests/test-agent-project-codex-recovery.sh +0 -731
  21. package/tools/tests/test-agent-project-codex-session-wrapper-clears-stale-sandbox-artifacts.sh +0 -105
  22. package/tools/tests/test-agent-project-codex-session-wrapper.sh +0 -97
  23. package/tools/tests/test-agent-project-open-pr-worktree-config-prefix.sh +0 -81
  24. package/tools/tests/test-agent-project-openclaw-session-wrapper-clears-stale-sandbox-artifacts.sh +0 -109
  25. package/tools/tests/test-agent-project-openclaw-session-wrapper-infers-blocked-result-contract.sh +0 -89
  26. package/tools/tests/test-agent-project-openclaw-session-wrapper-recovers-literal-env-artifacts.sh +0 -113
  27. package/tools/tests/test-agent-project-openclaw-session-wrapper-recovers-version-mismatch.sh +0 -135
  28. package/tools/tests/test-agent-project-openclaw-session-wrapper-resident.sh +0 -179
  29. package/tools/tests/test-agent-project-openclaw-session-wrapper-reuses-existing-agent-after-add-race.sh +0 -119
  30. package/tools/tests/test-agent-project-openclaw-session-wrapper-terminates-rate-limit-hang.sh +0 -91
  31. package/tools/tests/test-agent-project-openclaw-session-wrapper.sh +0 -117
  32. package/tools/tests/test-agent-project-publish-issue-pr-prunes-stale-worktree-entry.sh +0 -148
  33. package/tools/tests/test-agent-project-publish-issue-pr-reads-archived-session.sh +0 -146
  34. package/tools/tests/test-agent-project-publish-issue-pr-recovers-final-head.sh +0 -145
  35. package/tools/tests/test-agent-project-publish-issue-pr-reuses-existing-worktree.sh +0 -147
  36. package/tools/tests/test-agent-project-reconcile-failure-reason.sh +0 -456
  37. package/tools/tests/test-agent-project-reconcile-issue-archived-session-fallback.sh +0 -96
  38. package/tools/tests/test-agent-project-reconcile-issue-before-blocked.sh +0 -90
  39. package/tools/tests/test-agent-project-reconcile-issue-host-verification-recovery-uses-recovered-worktree.sh +0 -212
  40. package/tools/tests/test-agent-project-reconcile-issue-host-verification-recovery.sh +0 -207
  41. package/tools/tests/test-agent-project-reconcile-issue-provider-quota-schedules-provider-cooldown.sh +0 -101
  42. package/tools/tests/test-agent-project-reconcile-issue-session-backfills-lane-metadata-from-worker-key.sh +0 -113
  43. package/tools/tests/test-agent-project-reconcile-issue-session-clears-stale-failed-summary.sh +0 -117
  44. package/tools/tests/test-agent-project-reconcile-issue-session-initializes-shared-agent-home.sh +0 -55
  45. package/tools/tests/test-agent-project-reconcile-issue-session-normalizes-runner-state.sh +0 -125
  46. package/tools/tests/test-agent-project-reconcile-issue-session-records-invalid-contract-summary.sh +0 -118
  47. package/tools/tests/test-agent-project-reconcile-issue-session-skips-duplicate-blocked-comment.sh +0 -144
  48. package/tools/tests/test-agent-project-reconcile-issue-session-standardizes-no-commits-blocker.sh +0 -145
  49. package/tools/tests/test-agent-project-reconcile-issue-session-synthesizes-blocked-comment.sh +0 -139
  50. package/tools/tests/test-agent-project-reconcile-pr-blocked-host-recovery.sh +0 -242
  51. package/tools/tests/test-agent-project-reconcile-pr-guard-blocked-no-commit.sh +0 -142
  52. package/tools/tests/test-agent-project-reconcile-pr-provider-quota-schedules-provider-cooldown.sh +0 -106
  53. package/tools/tests/test-agent-project-reconcile-pr-session-initializes-shared-agent-home.sh +0 -66
  54. package/tools/tests/test-agent-project-reconcile-pr-updated-branch-noop.sh +0 -129
  55. package/tools/tests/test-audit-agent-worktrees-active-launch-skips-git-inspection.sh +0 -69
  56. package/tools/tests/test-audit-agent-worktrees-broken-worktree.sh +0 -43
  57. package/tools/tests/test-audit-agent-worktrees-pending-launch-owner.sh +0 -46
  58. package/tools/tests/test-audit-agent-worktrees-unreconciled-owner.sh +0 -79
  59. package/tools/tests/test-audit-issue-routing-managed-branch-globs.sh +0 -56
  60. package/tools/tests/test-branch-verification-guard-generated-artifacts.sh +0 -72
  61. package/tools/tests/test-branch-verification-guard-targeted-coverage.sh +0 -125
  62. package/tools/tests/test-codex-quota-manager-failure-driven-rotation.sh +0 -178
  63. package/tools/tests/test-codex-quota-wrapper.sh +0 -37
  64. package/tools/tests/test-contribution-docs.sh +0 -18
  65. package/tools/tests/test-control-plane-dashboard-runtime-smoke.sh +0 -343
  66. package/tools/tests/test-create-follow-up-issue.sh +0 -73
  67. package/tools/tests/test-dashboard-launchd-bootstrap.sh +0 -55
  68. package/tools/tests/test-flow-export-execution-env-exports-repo-id.sh +0 -30
  69. package/tools/tests/test-flow-export-github-cli-auth-env-prefers-git-credential.sh +0 -48
  70. package/tools/tests/test-flow-github-api-repo-fallback-preserves-input.sh +0 -85
  71. package/tools/tests/test-flow-github-api-repo-prefers-explicit-repository-id.sh +0 -60
  72. package/tools/tests/test-flow-github-issue-list-falls-back-to-repository-id.sh +0 -64
  73. package/tools/tests/test-flow-github-pr-list-falls-back-to-repository-id.sh +0 -77
  74. package/tools/tests/test-flow-resident-can-reuse-does-not-leak-metadata.sh +0 -52
  75. package/tools/tests/test-flow-resident-reap-stale-controllers.sh +0 -63
  76. package/tools/tests/test-flow-resolve-codex-quota-tools.sh +0 -104
  77. package/tools/tests/test-flow-runtime-doctor-profile-selection.sh +0 -27
  78. package/tools/tests/test-heartbeat-codex-pr-linked-issue-exclusion.sh +0 -79
  79. package/tools/tests/test-heartbeat-hooks-enqueue-resident-issue-for-idle-controller.sh +0 -115
  80. package/tools/tests/test-heartbeat-hooks-enqueue-resident-issue-for-live-lane-controller.sh +0 -117
  81. package/tools/tests/test-heartbeat-hooks-start-resident-issue-loop-claude.sh +0 -96
  82. package/tools/tests/test-heartbeat-hooks-start-resident-issue-loop-codex.sh +0 -96
  83. package/tools/tests/test-heartbeat-hooks-start-resident-issue-loop.sh +0 -96
  84. package/tools/tests/test-heartbeat-loop-auth-wait-does-not-consume-capacity.sh +0 -170
  85. package/tools/tests/test-heartbeat-loop-blocked-recovery-lane.sh +0 -201
  86. package/tools/tests/test-heartbeat-loop-blocked-recovery-vs-pr-reservation.sh +0 -201
  87. package/tools/tests/test-heartbeat-loop-idle-resident-controller-does-not-block-launches.sh +0 -160
  88. package/tools/tests/test-heartbeat-loop-pr-launch-dedup.sh +0 -133
  89. package/tools/tests/test-heartbeat-loop-provider-cooldown-suppresses-launches.sh +0 -157
  90. package/tools/tests/test-heartbeat-loop-reaps-stale-resident-controller.sh +0 -181
  91. package/tools/tests/test-heartbeat-loop-waiting-provider-resident-controller-does-not-block-launches.sh +0 -160
  92. package/tools/tests/test-heartbeat-ready-issues-blocked-recovery.sh +0 -134
  93. package/tools/tests/test-heartbeat-safe-auto-dynamic-concurrency.sh +0 -162
  94. package/tools/tests/test-heartbeat-safe-auto-no-tmux-sessions.sh +0 -136
  95. package/tools/tests/test-heartbeat-safe-auto-openclaw-skips-codex-quota.sh +0 -139
  96. package/tools/tests/test-heartbeat-safe-auto-quota-health-signal.sh +0 -119
  97. package/tools/tests/test-heartbeat-safe-auto-stale-shared-loop-pid-does-not-skip.sh +0 -140
  98. package/tools/tests/test-heartbeat-safe-auto-static-capacity-without-quota-cache.sh +0 -142
  99. package/tools/tests/test-heartbeat-safe-auto-zero-healthy-pools.sh +0 -141
  100. package/tools/tests/test-heartbeat-sync-issue-labels-empty-schedule.sh +0 -65
  101. package/tools/tests/test-heartbeat-sync-open-agent-prs-terminal-clears-running.sh +0 -179
  102. package/tools/tests/test-install-dashboard-launchd.sh +0 -78
  103. package/tools/tests/test-install-project-launchd-adds-tool-paths.sh +0 -87
  104. package/tools/tests/test-install-project-launchd.sh +0 -110
  105. package/tools/tests/test-issue-local-workspace-install-policy.sh +0 -81
  106. package/tools/tests/test-issue-publish-scope-guard-docs-signal.sh +0 -70
  107. package/tools/tests/test-issue-reconcile-hooks-success-clears-blocked.sh +0 -36
  108. package/tools/tests/test-kick-scheduler-requires-explicit-profile.sh +0 -47
  109. package/tools/tests/test-label-follow-up-issues-falls-back-to-repository-id.sh +0 -132
  110. package/tools/tests/test-manual-operator-entrypoints-require-explicit-profile.sh +0 -64
  111. package/tools/tests/test-package-funding-metadata.sh +0 -21
  112. package/tools/tests/test-package-public-metadata.sh +0 -62
  113. package/tools/tests/test-placeholder-worker-adapters.sh +0 -38
  114. package/tools/tests/test-pr-reconcile-hooks-refreshes-recurring-issue-checklist.sh +0 -110
  115. package/tools/tests/test-pr-risk-cohesive-mobile-locale-scope.sh +0 -70
  116. package/tools/tests/test-pr-risk-fix-label-semantics.sh +0 -114
  117. package/tools/tests/test-pr-risk-local-first-no-checks.sh +0 -70
  118. package/tools/tests/test-prepare-worktree-simple-repo-baseline.sh +0 -67
  119. package/tools/tests/test-profile-activate.sh +0 -33
  120. package/tools/tests/test-profile-adopt-allow-missing-repo.sh +0 -68
  121. package/tools/tests/test-profile-adopt-skip-workspace-sync-missing-file.sh +0 -61
  122. package/tools/tests/test-profile-adopt-syncs-anchor-and-workspace.sh +0 -90
  123. package/tools/tests/test-profile-smoke-collision.sh +0 -44
  124. package/tools/tests/test-profile-smoke-invalid-claude-config.sh +0 -31
  125. package/tools/tests/test-profile-smoke-invalid-provider-pool.sh +0 -68
  126. package/tools/tests/test-profile-smoke-repo-slug-mismatch.sh +0 -36
  127. package/tools/tests/test-profile-smoke.sh +0 -45
  128. package/tools/tests/test-project-init-force-and-skip-sync.sh +0 -61
  129. package/tools/tests/test-project-init-repo-slug-mismatch.sh +0 -29
  130. package/tools/tests/test-project-init.sh +0 -66
  131. package/tools/tests/test-project-launchd-bootstrap.sh +0 -66
  132. package/tools/tests/test-project-remove.sh +0 -150
  133. package/tools/tests/test-project-runtime-supervisor.sh +0 -47
  134. package/tools/tests/test-project-runtimectl-launchd.sh +0 -115
  135. package/tools/tests/test-project-runtimectl-missing-profile.sh +0 -54
  136. package/tools/tests/test-project-runtimectl-start-falls-back-to-bootstrap.sh +0 -108
  137. package/tools/tests/test-project-runtimectl-status-reports-supervisor-as-heartbeat-parent.sh +0 -95
  138. package/tools/tests/test-project-runtimectl-status-supervisor-running.sh +0 -59
  139. package/tools/tests/test-project-runtimectl-stop-cancels-pending-kick.sh +0 -85
  140. package/tools/tests/test-project-runtimectl-stop-clears-running-labels.sh +0 -78
  141. package/tools/tests/test-project-runtimectl.sh +0 -212
  142. package/tools/tests/test-provider-cooldown-state-prefers-runtime-worker-context.sh +0 -39
  143. package/tools/tests/test-provider-cooldown-state.sh +0 -59
  144. package/tools/tests/test-public-repo-docs.sh +0 -160
  145. package/tools/tests/test-reconcile-pr-worker-acp-config-routing.sh +0 -75
  146. package/tools/tests/test-render-dashboard-snapshot.sh +0 -149
  147. package/tools/tests/test-render-flow-config-demo-profile.sh +0 -36
  148. package/tools/tests/test-render-flow-config-provider-pool-fallback.sh +0 -81
  149. package/tools/tests/test-render-flow-config.sh +0 -52
  150. package/tools/tests/test-run-codex-task-claude-routing.sh +0 -125
  151. package/tools/tests/test-run-codex-task-codex-resident-routing.sh +0 -108
  152. package/tools/tests/test-run-codex-task-kilo-routing.sh +0 -98
  153. package/tools/tests/test-run-codex-task-openclaw-resident-routing.sh +0 -117
  154. package/tools/tests/test-run-codex-task-openclaw-routing.sh +0 -113
  155. package/tools/tests/test-run-codex-task-opencode-routing.sh +0 -98
  156. package/tools/tests/test-run-codex-task-provider-pool-fallback-routing.sh +0 -146
  157. package/tools/tests/test-scaffold-profile.sh +0 -108
  158. package/tools/tests/test-serve-dashboard.sh +0 -93
  159. package/tools/tests/test-start-issue-worker-blocked-context.sh +0 -129
  160. package/tools/tests/test-start-issue-worker-blocks-complete-recurring-checklist.sh +0 -189
  161. package/tools/tests/test-start-issue-worker-local-install-routing.sh +0 -157
  162. package/tools/tests/test-start-issue-worker-profile-template-routing.sh +0 -149
  163. package/tools/tests/test-start-issue-worker-recurring-resident-reuse-codex.sh +0 -212
  164. package/tools/tests/test-start-issue-worker-recurring-resident-reuse.sh +0 -219
  165. package/tools/tests/test-start-issue-worker-renders-verification-snippet.sh +0 -155
  166. package/tools/tests/test-start-issue-worker-resident-reuse-falls-back-to-new-worktree.sh +0 -199
  167. package/tools/tests/test-start-pr-fix-worker-host-blocker-context.sh +0 -275
  168. package/tools/tests/test-start-resident-issue-loop-adopts-next-recurring-issue.sh +0 -185
  169. package/tools/tests/test-start-resident-issue-loop-clears-pending-while-waiting-due.sh +0 -152
  170. package/tools/tests/test-start-resident-issue-loop-consumes-queued-lease.sh +0 -186
  171. package/tools/tests/test-start-resident-issue-loop-fails-over-provider-pool.sh +0 -212
  172. package/tools/tests/test-start-resident-issue-loop-immediate-cycles.sh +0 -148
  173. package/tools/tests/test-start-resident-issue-loop-waits-for-provider.sh +0 -194
  174. package/tools/tests/test-start-resident-issue-loop-waits-for-terminal-reconcile-status.sh +0 -198
  175. package/tools/tests/test-start-resident-issue-loop-yields-to-live-lane-controller.sh +0 -145
  176. package/tools/tests/test-sync-pr-labels-fix-lane-uses-repair-queued.sh +0 -67
  177. package/tools/tests/test-sync-recurring-issue-checklist-backfills-workflow-complete-blocker.sh +0 -70
  178. package/tools/tests/test-sync-recurring-issue-checklist.sh +0 -95
  179. package/tools/tests/test-sync-shared-agent-home-local-source-root.sh +0 -66
  180. package/tools/tests/test-sync-shared-agent-home-preserves-unrelated-workflow-catalog-skill.sh +0 -47
  181. package/tools/tests/test-test-smoke.sh +0 -86
  182. package/tools/tests/test-uninstall-project-launchd.sh +0 -37
  183. package/tools/tests/test-update-github-labels-prefers-sibling-helper.sh +0 -49
  184. package/tools/tests/test-workflow-catalog.sh +0 -43
@@ -1,145 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- FLOW_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5
-
6
- tmpdir="$(mktemp -d)"
7
- trap 'rm -rf "$tmpdir"' EXIT
8
-
9
- workspace_root="$tmpdir/workspace"
10
- bin_dir="$workspace_root/tools/bin"
11
- runs_root="$tmpdir/runs"
12
- history_root="$tmpdir/history"
13
- repo_root="$tmpdir/repo"
14
- run_dir="$runs_root/demo-issue-501"
15
- posted_comment_file="$tmpdir/posted-comment.md"
16
-
17
- mkdir -p "$bin_dir" "$run_dir" "$history_root" "$repo_root"
18
- git -C "$repo_root" init -b main >/dev/null 2>&1
19
-
20
- cp "$FLOW_ROOT/tools/bin/agent-project-reconcile-issue-session" "$bin_dir/agent-project-reconcile-issue-session"
21
- cp "$FLOW_ROOT/tools/bin/flow-config-lib.sh" "$bin_dir/flow-config-lib.sh"
22
- cp "$FLOW_ROOT/tools/bin/flow-shell-lib.sh" "$bin_dir/flow-shell-lib.sh"
23
- cp "$FLOW_ROOT/tools/bin/flow-resident-worker-lib.sh" "$bin_dir/flow-resident-worker-lib.sh"
24
-
25
- cat >"$bin_dir/agent-project-worker-status" <<'EOF'
26
- #!/usr/bin/env bash
27
- set -euo pipefail
28
- cat <<OUT
29
- STATUS=SUCCEEDED
30
- META_FILE=${TEST_RUN_DIR:?}/run.env
31
- OUT
32
- EOF
33
- chmod +x "$bin_dir/agent-project-worker-status"
34
-
35
- cat >"$bin_dir/agent-project-cleanup-session" <<'EOF'
36
- #!/usr/bin/env bash
37
- set -euo pipefail
38
- exit 0
39
- EOF
40
- chmod +x "$bin_dir/agent-project-cleanup-session"
41
-
42
- cat >"$bin_dir/agent-project-publish-issue-pr" <<'EOF'
43
- #!/usr/bin/env bash
44
- set -euo pipefail
45
- echo "branch agent/demo/issue-501-keep-open has no commits ahead of origin/main; nothing to publish" >&2
46
- exit 1
47
- EOF
48
- chmod +x "$bin_dir/agent-project-publish-issue-pr"
49
-
50
- cat >"$bin_dir/sync-recurring-issue-checklist.sh" <<'EOF'
51
- #!/usr/bin/env bash
52
- set -euo pipefail
53
- cat <<OUT
54
- CHECKLIST_SYNC_STATUS=updated
55
- CHECKLIST_TOTAL=3
56
- CHECKLIST_CHECKED=3
57
- CHECKLIST_UNCHECKED=0
58
- CHECKLIST_MATCHED_PR_NUMBERS=7,8,9
59
- OUT
60
- EOF
61
- chmod +x "$bin_dir/sync-recurring-issue-checklist.sh"
62
-
63
- cat >"$tmpdir/bin-gh" <<'EOF'
64
- #!/usr/bin/env bash
65
- set -euo pipefail
66
- posted_comment_file="${TEST_POSTED_COMMENT_FILE:?}"
67
-
68
- if [[ "${1:-}" == "api" ]]; then
69
- route="${2:-}"
70
- shift 2
71
- if [[ "${route}" == "repos/example/repo/issues/501/comments" ]]; then
72
- body=""
73
- while [[ $# -gt 0 ]]; do
74
- case "$1" in
75
- -f)
76
- if [[ "${2:-}" == body=* ]]; then
77
- body="${2#body=}"
78
- shift 2
79
- continue
80
- fi
81
- ;;
82
- esac
83
- shift
84
- done
85
- printf '%s\n' "${body}" >"${posted_comment_file}"
86
- exit 0
87
- fi
88
- fi
89
-
90
- echo "unexpected gh args: $*" >&2
91
- exit 1
92
- EOF
93
- chmod +x "$tmpdir/bin-gh"
94
-
95
- mkdir -p "$tmpdir/path-bin"
96
- mv "$tmpdir/bin-gh" "$tmpdir/path-bin/gh"
97
-
98
- cat >"$run_dir/run.env" <<'EOF'
99
- ISSUE_ID=501
100
- SESSION=demo-issue-501
101
- WORKTREE=/tmp/mock-worktree
102
- BRANCH=agent/demo/issue-501-keep-open
103
- EOF
104
-
105
- cat >"$run_dir/result.env" <<'EOF'
106
- OUTCOME=implemented
107
- ACTION=host-publish-issue-pr
108
- ISSUE_ID=501
109
- EOF
110
-
111
- cat >"$run_dir/runner.env" <<'EOF'
112
- RUNNER_STATE=succeeded
113
- ATTEMPT=1
114
- RESUME_COUNT=0
115
- LAST_EXIT_CODE=0
116
- LAST_FAILURE_REASON=
117
- UPDATED_AT=2026-03-28T20:00:00Z
118
- EOF
119
-
120
- out="$(
121
- PATH="$tmpdir/path-bin:$PATH" \
122
- AGENT_CONTROL_PLANE_ROOT="$workspace_root" \
123
- TEST_RUN_DIR="$run_dir" \
124
- TEST_POSTED_COMMENT_FILE="$posted_comment_file" \
125
- bash "$bin_dir/agent-project-reconcile-issue-session" \
126
- --session demo-issue-501 \
127
- --repo-slug example/repo \
128
- --repo-root "$repo_root" \
129
- --runs-root "$runs_root" \
130
- --history-root "$history_root"
131
- )"
132
-
133
- grep -q '^STATUS=SUCCEEDED$' <<<"$out"
134
- grep -q '^OUTCOME=blocked$' <<<"$out"
135
- grep -q '^ACTION=host-comment-blocker$' <<<"$out"
136
- grep -q '^FAILURE_REASON=no-publishable-commits$' <<<"$out"
137
-
138
- grep -q '^# Blocker: All checklist items already completed$' "$run_dir/issue-comment.md"
139
- grep -q 'refresh the issue body with new unchecked improvement items' "$run_dir/issue-comment.md"
140
- grep -q 'Recently matched PRs: #7, #8, #9' "$run_dir/issue-comment.md"
141
-
142
- test -f "$posted_comment_file"
143
- grep -q '^# Blocker: All checklist items already completed$' "$posted_comment_file"
144
-
145
- echo "issue reconcile no-commits blocker standardization test passed"
@@ -1,139 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- FLOW_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5
-
6
- tmpdir="$(mktemp -d)"
7
- trap 'rm -rf "$tmpdir"' EXIT
8
-
9
- workspace_root="$tmpdir/workspace"
10
- bin_dir="$workspace_root/tools/bin"
11
- runs_root="$tmpdir/runs"
12
- history_root="$tmpdir/history"
13
- repo_root="$tmpdir/repo"
14
- run_dir="$runs_root/demo-issue-42"
15
- posted_comment_file="$tmpdir/posted-comment.md"
16
-
17
- mkdir -p "$bin_dir" "$run_dir" "$history_root" "$repo_root"
18
- git -C "$repo_root" init -b main >/dev/null 2>&1
19
- git -C "$repo_root" config user.name "Test"
20
- git -C "$repo_root" config user.email "test@example.com"
21
- printf 'seed\n' >"$repo_root/README.md"
22
- git -C "$repo_root" add README.md
23
- git -C "$repo_root" commit -m "init" >/dev/null 2>&1
24
-
25
- cp "$FLOW_ROOT/tools/bin/agent-project-reconcile-issue-session" "$bin_dir/agent-project-reconcile-issue-session"
26
- cp "$FLOW_ROOT/tools/bin/flow-config-lib.sh" "$bin_dir/flow-config-lib.sh"
27
- cp "$FLOW_ROOT/tools/bin/flow-shell-lib.sh" "$bin_dir/flow-shell-lib.sh"
28
- cp "$FLOW_ROOT/tools/bin/flow-resident-worker-lib.sh" "$bin_dir/flow-resident-worker-lib.sh"
29
-
30
- cat >"$bin_dir/agent-project-worker-status" <<'EOF'
31
- #!/usr/bin/env bash
32
- set -euo pipefail
33
- cat <<OUT
34
- STATUS=SUCCEEDED
35
- META_FILE=${TEST_RUN_DIR:?}/run.env
36
- OUT
37
- EOF
38
- chmod +x "$bin_dir/agent-project-worker-status"
39
-
40
- cat >"$bin_dir/agent-project-cleanup-session" <<'EOF'
41
- #!/usr/bin/env bash
42
- set -euo pipefail
43
- exit 0
44
- EOF
45
- chmod +x "$bin_dir/agent-project-cleanup-session"
46
-
47
- cat >"$bin_dir/sync-recurring-issue-checklist.sh" <<'EOF'
48
- #!/usr/bin/env bash
49
- set -euo pipefail
50
- cat <<OUT
51
- CHECKLIST_SYNC_STATUS=noop
52
- CHECKLIST_TOTAL=5
53
- CHECKLIST_CHECKED=4
54
- CHECKLIST_UNCHECKED=1
55
- CHECKLIST_MATCHED_PR_NUMBERS=
56
- OUT
57
- EOF
58
- chmod +x "$bin_dir/sync-recurring-issue-checklist.sh"
59
-
60
- cat >"$tmpdir/bin-gh" <<'EOF'
61
- #!/usr/bin/env bash
62
- set -euo pipefail
63
- posted_comment_file="${TEST_POSTED_COMMENT_FILE:?}"
64
-
65
- if [[ "${1:-}" == "api" ]]; then
66
- route="${2:-}"
67
- shift 2
68
- if [[ "${route}" == "repos/example/repo/issues/42/comments" ]]; then
69
- body=""
70
- while [[ $# -gt 0 ]]; do
71
- case "$1" in
72
- -f)
73
- if [[ "${2:-}" == body=* ]]; then
74
- body="${2#body=}"
75
- shift 2
76
- continue
77
- fi
78
- ;;
79
- esac
80
- shift
81
- done
82
- printf '%s\n' "${body}" >"${posted_comment_file}"
83
- exit 0
84
- fi
85
- fi
86
-
87
- echo "unexpected gh args: $*" >&2
88
- exit 1
89
- EOF
90
- chmod +x "$tmpdir/bin-gh"
91
- mkdir -p "$tmpdir/path-bin"
92
- mv "$tmpdir/bin-gh" "$tmpdir/path-bin/gh"
93
-
94
- cat >"$run_dir/run.env" <<EOF
95
- ISSUE_ID=42
96
- SESSION=demo-issue-42
97
- WORKTREE=${repo_root}
98
- BRANCH=main
99
- EOF
100
-
101
- cat >"$run_dir/result.env" <<'EOF'
102
- OUTCOME=blocked
103
- ACTION=host-comment-blocker
104
- ISSUE_ID=42
105
- EOF
106
-
107
- cat >"$run_dir/runner.env" <<'EOF'
108
- RUNNER_STATE=succeeded
109
- ATTEMPT=1
110
- RESUME_COUNT=0
111
- LAST_EXIT_CODE=0
112
- LAST_FAILURE_REASON=
113
- UPDATED_AT=2026-03-28T20:00:00Z
114
- EOF
115
-
116
- out="$(
117
- PATH="$tmpdir/path-bin:$PATH" \
118
- AGENT_CONTROL_PLANE_ROOT="$workspace_root" \
119
- TEST_RUN_DIR="$run_dir" \
120
- TEST_POSTED_COMMENT_FILE="$posted_comment_file" \
121
- bash "$bin_dir/agent-project-reconcile-issue-session" \
122
- --session demo-issue-42 \
123
- --repo-slug example/repo \
124
- --repo-root "$repo_root" \
125
- --runs-root "$runs_root" \
126
- --history-root "$history_root"
127
- )"
128
-
129
- grep -q '^STATUS=SUCCEEDED$' <<<"$out"
130
- grep -q '^OUTCOME=blocked$' <<<"$out"
131
- grep -q '^ACTION=host-comment-blocker$' <<<"$out"
132
- grep -q '^FAILURE_REASON=issue-worker-blocked$' <<<"$out"
133
-
134
- test -f "$run_dir/issue-comment.md"
135
- grep -q '^# Blocker: Worker produced no publishable delta$' "$run_dir/issue-comment.md"
136
- test -f "$posted_comment_file"
137
- grep -q '^# Blocker: Worker produced no publishable delta$' "$posted_comment_file"
138
-
139
- echo "issue reconcile synthesizes blocked comment test passed"
@@ -1,242 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- FLOW_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5
- PR_RECONCILE_SRC="${FLOW_ROOT}/tools/bin/agent-project-reconcile-pr-session"
6
- RECORD_VERIFICATION_SRC="${FLOW_ROOT}/tools/bin/record-verification.sh"
7
- FLOW_SHELL_LIB="${FLOW_ROOT}/tools/bin/flow-shell-lib.sh"
8
- FLOW_CONFIG_LIB="${FLOW_ROOT}/tools/bin/flow-config-lib.sh"
9
-
10
- tmpdir="$(mktemp -d)"
11
- trap 'rm -rf "$tmpdir"' EXIT
12
-
13
- shared_agent_home="$tmpdir/shared-agent-home"
14
- shared_bin="$shared_agent_home/tools/bin"
15
- shared_assets="$shared_agent_home/assets"
16
- flow_tools_dir="$tmpdir/flow-tools"
17
- runs_root="$tmpdir/runs"
18
- history_root="$tmpdir/history"
19
- bin_dir="$tmpdir/bin"
20
- node_bin_dir="$(dirname "$(command -v node)")"
21
- origin_repo="$tmpdir/origin.git"
22
- repo_root="$tmpdir/repo-root"
23
- pr_worktree="$tmpdir/pr-worktree"
24
- posted_comment_file="$tmpdir/posted-comment.md"
25
-
26
- mkdir -p "$shared_bin" "$shared_assets" "$flow_tools_dir" "$runs_root/fl-pr-202" "$history_root" "$bin_dir"
27
-
28
- cp "$PR_RECONCILE_SRC" "$shared_bin/agent-project-reconcile-pr-session"
29
- cp "$RECORD_VERIFICATION_SRC" "$flow_tools_dir/record-verification.sh"
30
- cp "$FLOW_SHELL_LIB" "$shared_bin/flow-shell-lib.sh"
31
- cp "$FLOW_CONFIG_LIB" "$shared_bin/flow-config-lib.sh"
32
- printf '{}\n' >"$shared_assets/workflow-catalog.json"
33
-
34
- git init --bare "$origin_repo" >/dev/null 2>&1
35
- git clone "$origin_repo" "$repo_root" >/dev/null 2>&1
36
- mkdir -p "$repo_root/scripts"
37
- cat >"$repo_root/README.md" <<'EOF'
38
- hello
39
- EOF
40
- cat >"$repo_root/scripts/host-playwright-retry.sh" <<'EOF'
41
- #!/usr/bin/env bash
42
- set -euo pipefail
43
- echo "host verification ok"
44
- EOF
45
- chmod +x "$repo_root/scripts/host-playwright-retry.sh"
46
- git -C "$repo_root" add README.md scripts/host-playwright-retry.sh
47
- git -C "$repo_root" -c user.name=Test -c user.email=test@example.com commit -m "init" >/dev/null
48
- git -C "$repo_root" branch -M main >/dev/null 2>&1
49
- git -C "$repo_root" push origin main >/dev/null 2>&1
50
- git -C "$repo_root" checkout -b codex/pr-202-recovery >/dev/null 2>&1
51
- git -C "$repo_root" push origin codex/pr-202-recovery >/dev/null 2>&1
52
-
53
- git clone "$origin_repo" "$pr_worktree" >/dev/null 2>&1
54
- git -C "$pr_worktree" checkout codex/pr-202-recovery >/dev/null 2>&1
55
- git -C "$pr_worktree" config user.name Test
56
- git -C "$pr_worktree" config user.email test@example.com
57
- branch_head="$(git -C "$pr_worktree" rev-parse HEAD)"
58
- cat >"$pr_worktree/README.md" <<'EOF'
59
- hello recovered
60
- EOF
61
-
62
- cat >"$shared_bin/agent-project-worker-status" <<EOF
63
- #!/usr/bin/env bash
64
- set -euo pipefail
65
- printf 'SESSION=fl-pr-202\n'
66
- printf 'STATUS=SUCCEEDED\n'
67
- printf 'META_FILE=%s\n' "$runs_root/fl-pr-202/run.env"
68
- EOF
69
-
70
- cat >"$shared_bin/agent-project-cleanup-session" <<'EOF'
71
- #!/usr/bin/env bash
72
- set -euo pipefail
73
- exit 0
74
- EOF
75
-
76
- cat >"$shared_bin/branch-verification-guard.sh" <<'EOF'
77
- #!/usr/bin/env bash
78
- set -euo pipefail
79
-
80
- run_dir=""
81
- while [[ $# -gt 0 ]]; do
82
- case "$1" in
83
- --run-dir) run_dir="${2:-}"; shift 2 ;;
84
- *) shift ;;
85
- esac
86
- done
87
-
88
- if [[ -f "${run_dir}/verification.jsonl" ]] && grep -Fq 'bash scripts/host-playwright-retry.sh' "${run_dir}/verification.jsonl"; then
89
- printf 'VERIFICATION_GUARD_STATUS=ok\n'
90
- exit 0
91
- fi
92
-
93
- cat >&2 <<'MSG'
94
- Verification guard blocked branch publication.
95
-
96
- Why it was blocked:
97
- - changed test files were not covered by a targeted test command
98
- MSG
99
- exit 43
100
- EOF
101
-
102
- cat >"$bin_dir/gh" <<EOF
103
- #!/usr/bin/env bash
104
- set -euo pipefail
105
-
106
- if [[ "\${1:-}" == "pr" && "\${2:-}" == "view" ]]; then
107
- if [[ " \$* " == *" --json comments "* ]]; then
108
- printf '{"comments":[]}\n'
109
- else
110
- printf '{"state":"OPEN","baseRefName":"main"}\n'
111
- fi
112
- exit 0
113
- fi
114
-
115
- if [[ "\${1:-}" == "api" && "\${2:-}" == "repos/example/repo/issues/202/comments" ]]; then
116
- shift 2
117
- while [[ \$# -gt 0 ]]; do
118
- case "\$1" in
119
- -f)
120
- if [[ "\${2:-}" == body=* ]]; then
121
- printf '%s' "\${2#body=}" >"$posted_comment_file"
122
- fi
123
- shift 2
124
- ;;
125
- --method)
126
- shift 2
127
- ;;
128
- *)
129
- shift
130
- ;;
131
- esac
132
- done
133
- exit 0
134
- fi
135
-
136
- echo "unexpected gh invocation: \$*" >&2
137
- exit 1
138
- EOF
139
-
140
- chmod +x \
141
- "$shared_bin/agent-project-reconcile-pr-session" \
142
- "$shared_bin/flow-shell-lib.sh" \
143
- "$shared_bin/flow-config-lib.sh" \
144
- "$shared_bin/agent-project-worker-status" \
145
- "$shared_bin/agent-project-cleanup-session" \
146
- "$shared_bin/branch-verification-guard.sh" \
147
- "$flow_tools_dir/record-verification.sh" \
148
- "$bin_dir/gh"
149
-
150
- cat >"$runs_root/fl-pr-202/run.env" <<EOF
151
- PR_NUMBER=202
152
- WORKTREE=$pr_worktree
153
- PR_HEAD_REF=codex/pr-202-recovery
154
- FLOW_TOOLS_DIR=$flow_tools_dir
155
- EOF
156
-
157
- cat >"$runs_root/fl-pr-202/result.env" <<'EOF'
158
- OUTCOME=blocked
159
- ACTION=host-comment-pr-blocker
160
- EOF
161
-
162
- cat >"$runs_root/fl-pr-202/prompt.md" <<'EOF'
163
- Pre-approved local verification fallbacks:
164
- - apps/web/e2e/archive/auth/tenant-isolation-login.spec.ts | loopback retry command: `bash scripts/host-playwright-retry.sh`
165
- EOF
166
-
167
- cat >"$runs_root/fl-pr-202/pr-comment.md" <<'EOF'
168
- **Summary**
169
- - Updated tenant go-live runbook.
170
-
171
- **Verification**
172
- - ✅ `pnpm --filter @alpha/api test -- --testPathPatterns="auth.service.extended"`
173
- - ❌ `bash scripts/with-test-namespace.sh pnpm --filter @alpha/web exec playwright test e2e/archive/auth/tenant-isolation-login.spec.ts --project=chromium` (Next dev failed: `listen EPERM 0.0.0.0:3000`)
174
-
175
- **Blocker**
176
- - Required Playwright coverage could not run because the web server failed to bind to local ports.
177
- EOF
178
-
179
- cat >"$runs_root/fl-pr-202/fl-pr-202.log" <<'EOF'
180
- Error: listen EPERM: operation not permitted 127.0.0.1:3001
181
- EOF
182
-
183
- cat >"$runs_root/fl-pr-202/verification.jsonl" <<'EOF'
184
- {"timestamp":"2026-03-17T14:22:19.125Z","status":"pass","command":"pnpm --filter @alpha/api test -- --testPathPatterns=\"auth.service.extended\""}
185
- EOF
186
-
187
- pr_retry_reason_file="$tmpdir/pr-retry-reason.txt"
188
- pr_retry_cleared_file="$tmpdir/pr-retry-cleared.txt"
189
- pr_updated_file="$tmpdir/pr-updated.txt"
190
- pr_hook="$tmpdir/pr-hook.sh"
191
-
192
- cat >"$pr_hook" <<EOF
193
- #!/usr/bin/env bash
194
- set -euo pipefail
195
- pr_schedule_retry() {
196
- printf '%s\n' "\$1" >"$pr_retry_reason_file"
197
- }
198
- pr_clear_retry() {
199
- : >"$pr_retry_cleared_file"
200
- }
201
- pr_after_updated_branch() {
202
- : >"$pr_updated_file"
203
- }
204
- pr_after_reconciled() { :; }
205
- EOF
206
-
207
- chmod +x "$pr_hook"
208
-
209
- pr_out="$(
210
- PATH="$bin_dir:$node_bin_dir:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin" \
211
- bash "$shared_bin/agent-project-reconcile-pr-session" \
212
- --session fl-pr-202 \
213
- --repo-slug example/repo \
214
- --repo-root "$repo_root" \
215
- --runs-root "$runs_root" \
216
- --history-root "$history_root" \
217
- --hook-file "$pr_hook"
218
- )"
219
-
220
- test -f "$pr_retry_cleared_file"
221
- test -f "$pr_updated_file"
222
- test -f "$runs_root/fl-pr-202/reconciled.ok"
223
- grep -q '^STATUS=SUCCEEDED$' <<<"$pr_out"
224
- grep -q '^OUTCOME=updated-branch$' <<<"$pr_out"
225
- grep -q '^ACTION=host-push-pr-branch$' <<<"$pr_out"
226
- grep -q '^RESULT_CONTRACT_NOTE=host-recovered-sandbox-bind-failure$' <<<"$pr_out"
227
-
228
- grep -Fq 'bash scripts/host-playwright-retry.sh' "$runs_root/fl-pr-202/verification.jsonl"
229
- grep -Fq 'host-recovery-after-sandbox-bind-failure' "$runs_root/fl-pr-202/verification.jsonl"
230
- grep -Fq '**Host Recovery**' "$runs_root/fl-pr-202/pr-comment.md"
231
- if grep -Fq '**Blocker**' "$runs_root/fl-pr-202/pr-comment.md"; then
232
- echo "blocker section should be removed after host recovery" >&2
233
- exit 1
234
- fi
235
- grep -Fq 'bash scripts/host-playwright-retry.sh' "$posted_comment_file"
236
- grep -q '^OUTCOME=updated-branch$' "$runs_root/fl-pr-202/result.env"
237
-
238
- remote_head="$(git --git-dir="$origin_repo" rev-parse refs/heads/codex/pr-202-recovery)"
239
- test "$remote_head" != "$branch_head"
240
- test "$(git --git-dir="$origin_repo" show "${remote_head}:README.md")" = "hello recovered"
241
-
242
- echo "agent-project reconcile PR blocked host recovery test passed"
@@ -1,142 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- FLOW_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5
- PR_RECONCILE_SRC="${FLOW_ROOT}/tools/bin/agent-project-reconcile-pr-session"
6
- FLOW_SHELL_LIB="${FLOW_ROOT}/tools/bin/flow-shell-lib.sh"
7
- FLOW_CONFIG_LIB="${FLOW_ROOT}/tools/bin/flow-config-lib.sh"
8
-
9
- tmpdir="$(mktemp -d)"
10
- trap 'rm -rf "$tmpdir"' EXIT
11
-
12
- shared_agent_home="$tmpdir/shared-agent-home"
13
- shared_bin="$shared_agent_home/tools/bin"
14
- runs_root="$tmpdir/runs"
15
- history_root="$tmpdir/history"
16
- bin_dir="$tmpdir/bin"
17
- origin_repo="$tmpdir/origin.git"
18
- repo_root="$tmpdir/repo-root"
19
- pr_worktree="$tmpdir/pr-worktree"
20
-
21
- mkdir -p "$shared_bin" "$runs_root/fl-pr-201" "$history_root" "$bin_dir"
22
-
23
- cp "$PR_RECONCILE_SRC" "$shared_bin/agent-project-reconcile-pr-session"
24
- cp "$FLOW_SHELL_LIB" "$shared_bin/flow-shell-lib.sh"
25
- cp "$FLOW_CONFIG_LIB" "$shared_bin/flow-config-lib.sh"
26
-
27
- git init --bare "$origin_repo" >/dev/null 2>&1
28
- git clone "$origin_repo" "$repo_root" >/dev/null 2>&1
29
- printf 'hello\n' >"$repo_root/README.md"
30
- git -C "$repo_root" add README.md
31
- git -C "$repo_root" -c user.name=Test -c user.email=test@example.com commit -m "init" >/dev/null
32
- git -C "$repo_root" branch -M main >/dev/null 2>&1
33
- git -C "$repo_root" push origin main >/dev/null 2>&1
34
- git -C "$repo_root" checkout -b codex/pr-201-guard >/dev/null 2>&1
35
- git -C "$repo_root" push origin codex/pr-201-guard >/dev/null 2>&1
36
- branch_head="$(git -C "$repo_root" rev-parse HEAD)"
37
-
38
- git clone "$origin_repo" "$pr_worktree" >/dev/null 2>&1
39
- git -C "$pr_worktree" checkout codex/pr-201-guard >/dev/null 2>&1
40
- printf 'hello guard\n' >"$pr_worktree/README.md"
41
-
42
- cat >"$shared_bin/agent-project-worker-status" <<EOF
43
- #!/usr/bin/env bash
44
- set -euo pipefail
45
- printf 'SESSION=fl-pr-201\n'
46
- printf 'STATUS=SUCCEEDED\n'
47
- printf 'META_FILE=%s\n' "$runs_root/fl-pr-201/run.env"
48
- EOF
49
-
50
- cat >"$shared_bin/agent-project-cleanup-session" <<'EOF'
51
- #!/usr/bin/env bash
52
- set -euo pipefail
53
- exit 0
54
- EOF
55
-
56
- cat >"$shared_bin/branch-verification-guard.sh" <<'EOF'
57
- #!/usr/bin/env bash
58
- set -euo pipefail
59
- cat >&2 <<'MSG'
60
- Verification guard blocked branch publication.
61
-
62
- Why it was blocked:
63
- - changed test files were not covered by a targeted test command
64
- MSG
65
- exit 43
66
- EOF
67
-
68
- cat >"$bin_dir/gh" <<'EOF'
69
- #!/usr/bin/env bash
70
- set -euo pipefail
71
-
72
- if [[ "${1:-}" == "pr" && "${2:-}" == "view" ]]; then
73
- printf '{"state":"OPEN","baseRefName":"main"}\n'
74
- exit 0
75
- fi
76
-
77
- echo "unexpected gh invocation: $*" >&2
78
- exit 1
79
- EOF
80
-
81
- chmod +x \
82
- "$shared_bin/agent-project-reconcile-pr-session" \
83
- "$shared_bin/flow-shell-lib.sh" \
84
- "$shared_bin/flow-config-lib.sh" \
85
- "$shared_bin/agent-project-worker-status" \
86
- "$shared_bin/agent-project-cleanup-session" \
87
- "$shared_bin/branch-verification-guard.sh" \
88
- "$bin_dir/gh"
89
-
90
- cat >"$runs_root/fl-pr-201/run.env" <<EOF
91
- PR_NUMBER=201
92
- WORKTREE=$pr_worktree
93
- PR_HEAD_REF=codex/pr-201-guard
94
- EOF
95
-
96
- cat >"$runs_root/fl-pr-201/result.env" <<'EOF'
97
- OUTCOME=updated-branch
98
- ACTION=host-push-pr-branch
99
- EOF
100
-
101
- pr_reason_file="$tmpdir/pr-retry-reason.txt"
102
- pr_blocked_file="$tmpdir/pr-blocked.txt"
103
- pr_hook="$tmpdir/pr-hook.sh"
104
-
105
- cat >"$pr_hook" <<EOF
106
- #!/usr/bin/env bash
107
- set -euo pipefail
108
- pr_schedule_retry() {
109
- printf '%s\n' "\$1" >"$pr_reason_file"
110
- }
111
- pr_after_blocked() {
112
- : >"$pr_blocked_file"
113
- }
114
- pr_after_reconciled() { :; }
115
- EOF
116
-
117
- chmod +x "$pr_hook"
118
-
119
- pr_out="$(
120
- PATH="$bin_dir:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin" \
121
- bash "$shared_bin/agent-project-reconcile-pr-session" \
122
- --session fl-pr-201 \
123
- --repo-slug example/repo \
124
- --repo-root "$repo_root" \
125
- --runs-root "$runs_root" \
126
- --history-root "$history_root" \
127
- --hook-file "$pr_hook"
128
- )"
129
-
130
- test "$(cat "$pr_reason_file")" = "verification-guard-blocked"
131
- test -f "$pr_blocked_file"
132
- test -f "$runs_root/fl-pr-201/reconciled.ok"
133
- grep -q '^STATUS=SUCCEEDED$' <<<"$pr_out"
134
- grep -q '^OUTCOME=blocked$' <<<"$pr_out"
135
- grep -q '^ACTION=host-verification-guard-blocked$' <<<"$pr_out"
136
- grep -q '^FAILURE_REASON=verification-guard-blocked$' <<<"$pr_out"
137
-
138
- test "$(git -C "$pr_worktree" rev-parse HEAD)" = "$branch_head"
139
- grep -q '^ M README.md$' <<<"$(git -C "$pr_worktree" status --short)"
140
- grep -q 'Verification guard blocked branch publication.' "$runs_root/fl-pr-201/host-blocker.md"
141
-
142
- echo "agent-project reconcile PR guard-blocked no-commit test passed"