@codedrifters/configulator 0.0.355 → 0.0.357
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.mts +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +977 -134
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +977 -134
- package/lib/index.mjs.map +1 -1
- package/package.json +2 -2
package/lib/index.mjs
CHANGED
|
@@ -14721,6 +14721,7 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
|
|
|
14721
14721
|
"# .claude/procedures/check-blocked.sh eligible",
|
|
14722
14722
|
"# .claude/procedures/check-blocked.sh stale",
|
|
14723
14723
|
"# .claude/procedures/check-blocked.sh orphaned",
|
|
14724
|
+
"# .claude/procedures/check-blocked.sh lease-reconcile",
|
|
14724
14725
|
"# .claude/procedures/check-blocked.sh maintenance",
|
|
14725
14726
|
"# .claude/procedures/check-blocked.sh prs",
|
|
14726
14727
|
"# .claude/procedures/check-blocked.sh scope <issue-number>",
|
|
@@ -15049,21 +15050,181 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
|
|
|
15049
15050
|
" fi",
|
|
15050
15051
|
"}",
|
|
15051
15052
|
"",
|
|
15053
|
+
"cmd_lease_reconcile() {",
|
|
15054
|
+
" # PR-lease auto-reconcile for the feedback-drain loop. Two stuck",
|
|
15055
|
+
" # states wedge a `review:fixing` PR despite the Phase B1 drain and",
|
|
15056
|
+
" # the atomic worker hand-off; this sweep clears both WITHOUT a human:",
|
|
15057
|
+
" #",
|
|
15058
|
+
" # 1. Orphaned lease \u2014 PR carries `review:fixing` but NOT",
|
|
15059
|
+
" # `review:needs-worker`, the reviewer's fix-list comment is older",
|
|
15060
|
+
" # than the stale in-progress threshold, and NO worker-report",
|
|
15061
|
+
" # comment newer than the fix-list exists. A delegation was kicked",
|
|
15062
|
+
" # off but no worker result ever landed.",
|
|
15063
|
+
" # 2. Consumed-but-uncleared wedge \u2014 PR still carries BOTH",
|
|
15064
|
+
" # `review:needs-worker` AND `review:fixing`, but the branch HEAD",
|
|
15065
|
+
" # commit is NEWER than the fix-list comment and there is NO",
|
|
15066
|
+
" # worker-report. The worker did the work and pushed, then skipped",
|
|
15067
|
+
" # the hand-off, so the marker that the lease-without-marker",
|
|
15068
|
+
" # confirm trigger keys on was never cleared.",
|
|
15069
|
+
" #",
|
|
15070
|
+
" # AUDIT TRAIL / SAFETY: neither state is silently force-released.",
|
|
15071
|
+
" # - Orphaned lease \u2192 RE-APPLY `review:needs-worker` (not a",
|
|
15072
|
+
" # `status:needs-attention` flag) so the Phase B1 consume loop",
|
|
15073
|
+
" # retries the delegation autonomously, AND post a synthetic note",
|
|
15074
|
+
" # comment recording the re-arm. Re-arming (rather than flagging",
|
|
15075
|
+
" # for a human) is the autonomy-preserving choice the issue's",
|
|
15076
|
+
" # never-silently-force-released AC calls for: the lease itself is",
|
|
15077
|
+
" # left untouched (so the loop stays idempotent), only the durable",
|
|
15078
|
+
" # work marker is restored, and the note comment is the audit",
|
|
15079
|
+
" # trail proving the re-arm was deliberate.",
|
|
15080
|
+
" # - Consumed-but-uncleared \u2192 REMOVE `review:needs-worker` (the",
|
|
15081
|
+
" # hand-off the worker skipped) and post a synthetic reconcile note",
|
|
15082
|
+
" # comment, flipping the PR into the lease-without-marker state the",
|
|
15083
|
+
" # reviewer's confirm pass keys on so it can merge. The",
|
|
15084
|
+
" # `review:fixing` lease is left for that confirm pass to release,",
|
|
15085
|
+
" # mirroring complete-feedback-handoff.sh.",
|
|
15086
|
+
" #",
|
|
15087
|
+
" # Signals (all read via gh/jq):",
|
|
15088
|
+
" # - fix-list comment: the reviewer's most recent PR comment whose",
|
|
15089
|
+
" # body contains the stable heading `## Reviewer: fix list for",
|
|
15090
|
+
" # @issue-worker`. Its createdAt is the lease's reference time.",
|
|
15091
|
+
" # - worker-report comment: the most recent PR comment whose body",
|
|
15092
|
+
" # contains the stable HTML marker",
|
|
15093
|
+
" # `<!-- issue-worker feedback hand-off \u2014 review:needs-worker",
|
|
15094
|
+
" # cleared -->` posted by complete-feedback-handoff.sh. Presence +",
|
|
15095
|
+
" # createdAt newer than the fix-list means a result landed.",
|
|
15096
|
+
" # - branch HEAD: the PR head commit committedDate, compared against",
|
|
15097
|
+
" # the fix-list createdAt to detect a push that advanced past the",
|
|
15098
|
+
" # delegation without a hand-off.",
|
|
15099
|
+
"",
|
|
15100
|
+
" local orphaned_count=0",
|
|
15101
|
+
" local consumed_uncleared_count=0",
|
|
15102
|
+
"",
|
|
15103
|
+
" # Enumerate every open PR carrying the `review:fixing` lease \u2014 both",
|
|
15104
|
+
" # stuck states require it. One API call; the per-PR comment/commit",
|
|
15105
|
+
" # reads happen only for this (typically tiny) candidate set.",
|
|
15106
|
+
" local fixing_prs",
|
|
15107
|
+
' fixing_prs=$(gh pr list --state open --label "review:fixing" \\',
|
|
15108
|
+
' --json number,labels,headRefOid --limit 50 2>/dev/null || echo "[]")',
|
|
15109
|
+
"",
|
|
15110
|
+
" local fixing_count",
|
|
15111
|
+
` fixing_count=$(echo "$fixing_prs" | jq 'length' 2>/dev/null || echo 0)`,
|
|
15112
|
+
' if [[ "${fixing_count:-0}" -eq 0 ]]; then',
|
|
15113
|
+
' echo "LEASE_RECONCILE orphaned=0 consumed_uncleared=0"',
|
|
15114
|
+
" return 0",
|
|
15115
|
+
" fi",
|
|
15116
|
+
"",
|
|
15117
|
+
" # Stale threshold timestamp (UTC), reusing the same",
|
|
15118
|
+
" # STALE_IN_PROGRESS_HOURS=72 constant the stale-issue scan applies.",
|
|
15119
|
+
" local lease_threshold",
|
|
15120
|
+
" lease_threshold=$(date -u -v-${STALE_IN_PROGRESS_HOURS}H +%Y-%m-%dT%H:%M:%S 2>/dev/null \\",
|
|
15121
|
+
' || date -u -d "${STALE_IN_PROGRESS_HOURS} hours ago" +%Y-%m-%dT%H:%M:%S 2>/dev/null)',
|
|
15122
|
+
"",
|
|
15123
|
+
" local pr_rows",
|
|
15124
|
+
` pr_rows=$(echo "$fixing_prs" | jq -r '`,
|
|
15125
|
+
" .[] |",
|
|
15126
|
+
' (.labels | map(.name) | index("review:needs-worker") != null) as $has_marker |',
|
|
15127
|
+
' "\\(.number)\\t\\($has_marker)\\t\\(.headRefOid)"',
|
|
15128
|
+
" ' 2>/dev/null)",
|
|
15129
|
+
"",
|
|
15130
|
+
" while IFS=$'\\t' read -r pr_num has_marker head_oid; do",
|
|
15131
|
+
' [[ -z "$pr_num" ]] && continue',
|
|
15132
|
+
"",
|
|
15133
|
+
" # Pull the PR comments once; derive both the fix-list reference time",
|
|
15134
|
+
" # and the newest worker-report time from the same payload.",
|
|
15135
|
+
" local comments",
|
|
15136
|
+
' comments=$(gh pr view "$pr_num" --json comments \\',
|
|
15137
|
+
` --jq '.comments' 2>/dev/null || echo "[]")`,
|
|
15138
|
+
"",
|
|
15139
|
+
" # Newest fix-list comment createdAt (empty if none found).",
|
|
15140
|
+
" local fixlist_at",
|
|
15141
|
+
` fixlist_at=$(echo "$comments" | jq -r '`,
|
|
15142
|
+
' [.[] | select(.body | contains("## Reviewer: fix list for @issue-worker"))]',
|
|
15143
|
+
` | sort_by(.createdAt) | last | .createdAt // ""' 2>/dev/null)`,
|
|
15144
|
+
"",
|
|
15145
|
+
" # Newest worker-report createdAt (empty if none found). Keyed off the",
|
|
15146
|
+
" # stable HTML marker complete-feedback-handoff.sh embeds.",
|
|
15147
|
+
" local report_at",
|
|
15148
|
+
` report_at=$(echo "$comments" | jq -r '`,
|
|
15149
|
+
' [.[] | select(.body | contains("issue-worker feedback hand-off \u2014 review:needs-worker cleared"))]',
|
|
15150
|
+
` | sort_by(.createdAt) | last | .createdAt // ""' 2>/dev/null)`,
|
|
15151
|
+
"",
|
|
15152
|
+
" # No fix-list comment at all \u2014 we cannot reason about this lease",
|
|
15153
|
+
" # (e.g. a human applied `review:fixing` by hand). Leave it alone.",
|
|
15154
|
+
' if [[ -z "$fixlist_at" ]]; then',
|
|
15155
|
+
" continue",
|
|
15156
|
+
" fi",
|
|
15157
|
+
"",
|
|
15158
|
+
" # A worker-report newer than the fix-list means a result landed; the",
|
|
15159
|
+
" # confirm pass owns it. Skip for BOTH states.",
|
|
15160
|
+
' if [[ -n "$report_at" && "$report_at" > "$fixlist_at" ]]; then',
|
|
15161
|
+
" continue",
|
|
15162
|
+
" fi",
|
|
15163
|
+
"",
|
|
15164
|
+
' if [[ "$has_marker" == "true" ]]; then',
|
|
15165
|
+
" # \u2500\u2500 Consumed-but-uncleared wedge \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
15166
|
+
" # Marker still set + no worker-report. Reconcile only when the",
|
|
15167
|
+
" # branch advanced past the fix-list (the worker pushed but skipped",
|
|
15168
|
+
" # the hand-off); otherwise this is a normal in-flight delegation.",
|
|
15169
|
+
" local head_at",
|
|
15170
|
+
' head_at=$(gh api "repos/{owner}/{repo}/commits/${head_oid}" \\',
|
|
15171
|
+
` --jq '.commit.committer.date // ""' 2>/dev/null || echo "")`,
|
|
15172
|
+
' if [[ -n "$head_at" && "$head_at" > "$fixlist_at" ]]; then',
|
|
15173
|
+
' if gh pr edit "$pr_num" --remove-label "review:needs-worker" >/dev/null 2>&1; then',
|
|
15174
|
+
' gh pr comment "$pr_num" \\',
|
|
15175
|
+
' --body "Maintenance reconcile: branch HEAD advanced past the reviewer fix-list with no worker hand-off \u2014 clearing the orphaned \\`review:needs-worker\\` marker so the reviewer confirm pass can merge. The \\`review:fixing\\` lease is left for that pass to release." >/dev/null 2>&1 || true',
|
|
15176
|
+
' echo "LEASE_CONSUMED_UNCLEARED PR #${pr_num} \u2014 cleared review:needs-worker (branch advanced past fix-list, no worker report)"',
|
|
15177
|
+
" consumed_uncleared_count=$((consumed_uncleared_count + 1))",
|
|
15178
|
+
" else",
|
|
15179
|
+
' echo "LEASE_RECONCILE_FAILED PR #${pr_num} \u2014 could not remove review:needs-worker"',
|
|
15180
|
+
" fi",
|
|
15181
|
+
" fi",
|
|
15182
|
+
" else",
|
|
15183
|
+
" # \u2500\u2500 Orphaned lease \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
15184
|
+
" # `review:fixing` without `review:needs-worker`, no worker-report",
|
|
15185
|
+
" # newer than the fix-list. Reclaim only when the fix-list comment",
|
|
15186
|
+
" # is older than the stale threshold \u2014 a recently delegated PR may",
|
|
15187
|
+
" # still be mid-consume.",
|
|
15188
|
+
' local fixlist_trimmed="${fixlist_at%%+*}"',
|
|
15189
|
+
' fixlist_trimmed="${fixlist_trimmed%%Z*}"',
|
|
15190
|
+
' if [[ "$fixlist_trimmed" < "$lease_threshold" ]]; then',
|
|
15191
|
+
' if gh pr edit "$pr_num" --add-label "review:needs-worker" >/dev/null 2>&1; then',
|
|
15192
|
+
' gh pr comment "$pr_num" \\',
|
|
15193
|
+
' --body "Maintenance reconcile: \\`review:fixing\\` lease orphaned (fix-list older than ${STALE_IN_PROGRESS_HOURS}h with no worker report) \u2014 re-applying the \\`review:needs-worker\\` marker so the feedback-drain loop retries the delegation. This is a deliberate re-arm, not a silent force-release; the \\`review:fixing\\` lease is left untouched." >/dev/null 2>&1 || true',
|
|
15194
|
+
' echo "LEASE_ORPHANED PR #${pr_num} \u2014 re-applied review:needs-worker (fix-list stale, no worker report)"',
|
|
15195
|
+
" orphaned_count=$((orphaned_count + 1))",
|
|
15196
|
+
" else",
|
|
15197
|
+
' echo "LEASE_RECONCILE_FAILED PR #${pr_num} \u2014 could not re-apply review:needs-worker"',
|
|
15198
|
+
" fi",
|
|
15199
|
+
" fi",
|
|
15200
|
+
" fi",
|
|
15201
|
+
' done <<< "$pr_rows"',
|
|
15202
|
+
"",
|
|
15203
|
+
" # Single summary line consumed by the orchestrator, matching the",
|
|
15204
|
+
" # MAINTENANCE_DONE convention.",
|
|
15205
|
+
' echo "LEASE_RECONCILE orphaned=${orphaned_count} consumed_uncleared=${consumed_uncleared_count}"',
|
|
15206
|
+
"}",
|
|
15207
|
+
"",
|
|
15052
15208
|
"cmd_maintenance() {",
|
|
15053
15209
|
" # Phase D maintenance sweep: flag stale issues with",
|
|
15054
15210
|
" # `status:needs-attention`, count orphan branches/PRs (no",
|
|
15055
|
-
" # auto-deletion),
|
|
15056
|
-
" #
|
|
15057
|
-
" #
|
|
15058
|
-
" #
|
|
15059
|
-
" #
|
|
15060
|
-
" #
|
|
15211
|
+
" # auto-deletion), auto-reconcile stuck PR leases (re-arm orphaned",
|
|
15212
|
+
" # leases / clear consumed-but-uncleared markers, see",
|
|
15213
|
+
" # cmd_lease_reconcile), and emit a MAINTENANCE_DONE summary line",
|
|
15214
|
+
" # plus a LEASE_RECONCILE summary line so the orchestrator never",
|
|
15215
|
+
" # iterates raw stale/orphan/lease output. Mirrors the discipline of",
|
|
15216
|
+
" # cmd_unblock \u2014 per-issue / per-PR informational lines (FLAGGED #N,",
|
|
15217
|
+
" # ORPHAN_BRANCH \u2026, LEASE_ORPHANED PR #N \u2026) survive for log",
|
|
15218
|
+
" # visibility but are not load-bearing for the orchestrator.",
|
|
15061
15219
|
" #",
|
|
15062
15220
|
" # SAFETY: this subcommand NEVER auto-resets stale issues to",
|
|
15063
15221
|
" # `status:ready`. It only adds `status:needs-attention`; the",
|
|
15064
15222
|
" # existing `status:in-progress` or `status:blocked` label",
|
|
15065
15223
|
" # stays in place so partial implementation work on a branch",
|
|
15066
|
-
" # remains visible to humans.",
|
|
15224
|
+
" # remains visible to humans. The PR-lease reconcile likewise never",
|
|
15225
|
+
" # silently force-releases a `review:fixing` lease \u2014 it re-arms the",
|
|
15226
|
+
" # work marker (orphaned) or clears the consumed marker (wedge) and",
|
|
15227
|
+
" # always posts an audit-trail note comment.",
|
|
15067
15228
|
"",
|
|
15068
15229
|
" local flagged_stale_count=0",
|
|
15069
15230
|
" local flagged_blocked_count=0",
|
|
@@ -15134,14 +15295,40 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
|
|
|
15134
15295
|
" esac",
|
|
15135
15296
|
' done <<< "$orphan_output"',
|
|
15136
15297
|
"",
|
|
15298
|
+
" # \u2500\u2500 PR-lease auto-reconcile (MUTATING \u2014 see cmd_lease_reconcile) \u2500\u2500",
|
|
15299
|
+
" # Run the lease sweep and surface its informational lines for log",
|
|
15300
|
+
" # visibility. cmd_lease_reconcile applies the label edits itself",
|
|
15301
|
+
" # (re-arm or clear `review:needs-worker`) and posts the audit-trail",
|
|
15302
|
+
" # note comment \u2014 mirroring how this maintenance sweep already",
|
|
15303
|
+
" # mutates issue labels directly. Its terminal LEASE_RECONCILE line is",
|
|
15304
|
+
" # captured and re-emitted alongside MAINTENANCE_DONE so the",
|
|
15305
|
+
" # orchestrator reads both summaries from one maintenance invocation.",
|
|
15306
|
+
" local lease_output",
|
|
15307
|
+
" lease_output=$(cmd_lease_reconcile)",
|
|
15308
|
+
' local lease_summary="LEASE_RECONCILE orphaned=0 consumed_uncleared=0"',
|
|
15309
|
+
"",
|
|
15310
|
+
" while IFS= read -r line; do",
|
|
15311
|
+
' [[ -z "$line" ]] && continue',
|
|
15312
|
+
' case "$line" in',
|
|
15313
|
+
" 'LEASE_RECONCILE '*)",
|
|
15314
|
+
' lease_summary="$line"',
|
|
15315
|
+
" ;;",
|
|
15316
|
+
" *)",
|
|
15317
|
+
' echo "$line"',
|
|
15318
|
+
" ;;",
|
|
15319
|
+
" esac",
|
|
15320
|
+
' done <<< "$lease_output"',
|
|
15321
|
+
"",
|
|
15137
15322
|
" # \u2500\u2500 needs-attention total \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
15138
15323
|
" local needs_attention_total",
|
|
15139
15324
|
' needs_attention_total=$(gh issue list --label "status:needs-attention" --state open \\',
|
|
15140
15325
|
" --json number --limit 100 2>/dev/null | jq 'length' 2>/dev/null || echo 0)",
|
|
15141
15326
|
" needs_attention_total=${needs_attention_total:-0}",
|
|
15142
15327
|
"",
|
|
15143
|
-
" #
|
|
15328
|
+
" # Two summary lines consumed by the orchestrator: the issue/orphan",
|
|
15329
|
+
" # MAINTENANCE_DONE line and the PR-lease LEASE_RECONCILE line.",
|
|
15144
15330
|
' echo "MAINTENANCE_DONE flagged_stale=${flagged_stale_count} flagged_blocked=${flagged_blocked_count} orphan_branches=${orphan_branches_count} orphan_prs=${orphan_prs_count} needs_attention_total=${needs_attention_total}"',
|
|
15331
|
+
' echo "$lease_summary"',
|
|
15145
15332
|
"}",
|
|
15146
15333
|
"",
|
|
15147
15334
|
"cmd_prs() {",
|
|
@@ -15289,11 +15476,12 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
|
|
|
15289
15476
|
' eligible) shift; cmd_eligible "$@" ;;',
|
|
15290
15477
|
' stale) shift; cmd_stale "$@" ;;',
|
|
15291
15478
|
' orphaned) shift; cmd_orphaned "$@" ;;',
|
|
15479
|
+
' lease-reconcile) shift; cmd_lease_reconcile "$@" ;;',
|
|
15292
15480
|
' maintenance) shift; cmd_maintenance "$@" ;;',
|
|
15293
15481
|
' prs) shift; cmd_prs "$@" ;;',
|
|
15294
15482
|
' scope) shift; cmd_scope "$@" ;;',
|
|
15295
15483
|
" help|*)",
|
|
15296
|
-
' echo "Usage: check-blocked.sh <unblock|eligible|stale|orphaned|maintenance|prs|scope>"',
|
|
15484
|
+
' echo "Usage: check-blocked.sh <unblock|eligible|stale|orphaned|lease-reconcile|maintenance|prs|scope>"',
|
|
15297
15485
|
" exit 1",
|
|
15298
15486
|
" ;;",
|
|
15299
15487
|
"esac"
|
|
@@ -15302,7 +15490,7 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
|
|
|
15302
15490
|
function buildCheckBlockedProcedure(tiers, scopeGate = resolveScopeGate(), runRatio = resolveRunRatio()) {
|
|
15303
15491
|
return {
|
|
15304
15492
|
name: "check-blocked.sh",
|
|
15305
|
-
description: "Token-efficient issue triage script with subcommands: eligible, unblock, stale, orphaned, maintenance, prs, scope. Sorts eligible issues by priority desc \u2192 funnel tier asc \u2192 issue number asc; the scope subcommand classifies a single issue against the scope-gate thresholds; the unblock subcommand applies the `status:blocked` \u2192 `status:ready` label flip itself, posts the canned unblock comment, and emits a single `TRIAGE_DONE unblocked=N still_blocked=M` summary line; the maintenance subcommand flags stale issues with `status:needs-attention` (never auto-resets to `status:ready`), counts orphan branches/PRs, and emits a
|
|
15493
|
+
description: "Token-efficient issue triage script with subcommands: eligible, unblock, stale, orphaned, lease-reconcile, maintenance, prs, scope. Sorts eligible issues by priority desc \u2192 funnel tier asc \u2192 issue number asc; the scope subcommand classifies a single issue against the scope-gate thresholds; the unblock subcommand applies the `status:blocked` \u2192 `status:ready` label flip itself, posts the canned unblock comment, and emits a single `TRIAGE_DONE unblocked=N still_blocked=M` summary line; the lease-reconcile subcommand auto-reconciles stuck `review:fixing` PR leases \u2014 re-applying `review:needs-worker` on an orphaned lease (fix-list stale, no worker report) so the Phase B1 drain retries, and removing `review:needs-worker` on a consumed-but-uncleared wedge (branch HEAD advanced past the fix-list, marker still set, no worker report) so the reviewer confirm pass can merge, always posting an audit-trail note comment and emitting a single `LEASE_RECONCILE orphaned=N consumed_uncleared=M` summary line; the maintenance subcommand flags stale issues with `status:needs-attention` (never auto-resets to `status:ready`), counts orphan branches/PRs, folds in the lease-reconcile sweep, and emits a `MAINTENANCE_DONE flagged_stale=N flagged_blocked=M orphan_branches=A orphan_prs=B needs_attention_total=T` summary line followed by the `LEASE_RECONCILE` line.",
|
|
15306
15494
|
content: buildCheckBlockedScript(tiers, scopeGate, runRatio)
|
|
15307
15495
|
};
|
|
15308
15496
|
}
|
|
@@ -15324,56 +15512,289 @@ var unblockDependentsProcedure = buildUnblockDependentsProcedure(
|
|
|
15324
15512
|
function buildPrSweepScript() {
|
|
15325
15513
|
return [
|
|
15326
15514
|
"#!/usr/bin/env bash",
|
|
15327
|
-
"# pr-sweep.sh \u2014 Token-efficient PR
|
|
15328
|
-
"#
|
|
15329
|
-
"#
|
|
15330
|
-
"#
|
|
15515
|
+
"# pr-sweep.sh \u2014 Token-efficient PR enumeration for the orchestrator's",
|
|
15516
|
+
"# PR-handling phases. Two modes:",
|
|
15517
|
+
"#",
|
|
15518
|
+
"# review (default) \u2014 Phase B PR review sweep. Emits one",
|
|
15519
|
+
"# PR_ELIGIBLE / PR_SKIP line per open PR; the",
|
|
15520
|
+
"# orchestrator dispatches `pr-reviewer` per eligible PR.",
|
|
15521
|
+
"# needs-worker \u2014 Phase B1 feedback-drain. Emits one DRAIN line per",
|
|
15522
|
+
"# open PR carrying the `review:needs-worker` marker that",
|
|
15523
|
+
"# is NOT already in-flight (no `review:fixing` lease),",
|
|
15524
|
+
"# ordered highest-priority-first so the orchestrator",
|
|
15525
|
+
"# dispatches `issue-worker` per PR to consume the",
|
|
15526
|
+
"# reviewer's fix-list.",
|
|
15331
15527
|
"#",
|
|
15332
|
-
"#
|
|
15528
|
+
"# Review-mode skip rules:",
|
|
15333
15529
|
"# - isDraft = true \u2192 reason=draft",
|
|
15334
15530
|
"# - review:human-required label \u2192 reason=human-required",
|
|
15335
15531
|
"# - review:awaiting-human label \u2192 reason=awaiting-human",
|
|
15336
15532
|
"#",
|
|
15533
|
+
"# Needs-worker-mode skip rules (PR carries review:needs-worker but is",
|
|
15534
|
+
"# not eligible to drain this cycle):",
|
|
15535
|
+
"# - review:fixing label present \u2192 reason=in-flight",
|
|
15536
|
+
"# (a delegation is already being consumed; the marker plus the",
|
|
15537
|
+
"# lease means another worker is mid-run \u2014 skip to stay idempotent)",
|
|
15538
|
+
"#",
|
|
15337
15539
|
"# Usage:",
|
|
15338
|
-
"# .claude/procedures/pr-sweep.sh",
|
|
15540
|
+
"# .claude/procedures/pr-sweep.sh [review|needs-worker]",
|
|
15339
15541
|
"",
|
|
15340
15542
|
"set -uo pipefail",
|
|
15341
15543
|
"",
|
|
15342
|
-
"
|
|
15343
|
-
' --limit 50 2>/dev/null || echo "[]")',
|
|
15544
|
+
"# \u2500\u2500 helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
15344
15545
|
"",
|
|
15345
|
-
|
|
15346
|
-
|
|
15347
|
-
|
|
15348
|
-
"
|
|
15349
|
-
"
|
|
15546
|
+
"# Resolve the linked issue's priority for a PR so the needs-worker",
|
|
15547
|
+
"# drain can order highest-priority-first. Echoes a single sort key",
|
|
15548
|
+
"# 0-5 (0 = critical \u2026 4 = trivial, 5 = no/unknown priority) so an",
|
|
15549
|
+
"# unprioritised PR always sorts last but is never dropped.",
|
|
15550
|
+
"priority_key_for_pr() {",
|
|
15551
|
+
' local pr_num="$1"',
|
|
15552
|
+
" local issue_num",
|
|
15553
|
+
' issue_num=$(gh pr view "$pr_num" --json body \\',
|
|
15554
|
+
` --jq '(.body | capture("(?:Closes|Fixes|Resolves) #(?<num>[0-9]+)") | .num) // ""' \\`,
|
|
15555
|
+
' 2>/dev/null || echo "")',
|
|
15556
|
+
' if [[ -z "$issue_num" ]]; then',
|
|
15557
|
+
' echo "5"',
|
|
15558
|
+
" return",
|
|
15559
|
+
" fi",
|
|
15560
|
+
" local labels",
|
|
15561
|
+
' labels=$(gh issue view "$issue_num" --json labels \\',
|
|
15562
|
+
` --jq '.labels[].name' 2>/dev/null || echo "")`,
|
|
15563
|
+
' case "$labels" in',
|
|
15564
|
+
' *priority:critical*) echo "0" ;;',
|
|
15565
|
+
' *priority:high*) echo "1" ;;',
|
|
15566
|
+
' *priority:medium*) echo "2" ;;',
|
|
15567
|
+
' *priority:low*) echo "3" ;;',
|
|
15568
|
+
' *priority:trivial*) echo "4" ;;',
|
|
15569
|
+
' *) echo "5" ;;',
|
|
15570
|
+
" esac",
|
|
15571
|
+
"}",
|
|
15350
15572
|
"",
|
|
15351
|
-
"#
|
|
15352
|
-
"
|
|
15353
|
-
|
|
15354
|
-
"
|
|
15355
|
-
"
|
|
15356
|
-
|
|
15357
|
-
"
|
|
15358
|
-
|
|
15359
|
-
|
|
15360
|
-
'
|
|
15361
|
-
'
|
|
15362
|
-
|
|
15363
|
-
"
|
|
15364
|
-
|
|
15365
|
-
"
|
|
15366
|
-
"
|
|
15573
|
+
"# \u2500\u2500 modes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
15574
|
+
"",
|
|
15575
|
+
"cmd_review() {",
|
|
15576
|
+
" local prs",
|
|
15577
|
+
" prs=$(gh pr list --state open --json number,isDraft,labels \\",
|
|
15578
|
+
' --limit 50 2>/dev/null || echo "[]")',
|
|
15579
|
+
"",
|
|
15580
|
+
" local count",
|
|
15581
|
+
` count=$(echo "$prs" | jq 'length')`,
|
|
15582
|
+
' if [[ "$count" -eq 0 ]]; then',
|
|
15583
|
+
' echo "NO_OPEN_PRS"',
|
|
15584
|
+
" return 0",
|
|
15585
|
+
" fi",
|
|
15586
|
+
"",
|
|
15587
|
+
" # Emit one PR_ELIGIBLE / PR_SKIP line per open PR, sorted by PR",
|
|
15588
|
+
" # number ascending so the order is deterministic across runs.",
|
|
15589
|
+
` echo "$prs" | jq -r '`,
|
|
15590
|
+
" sort_by(.number) |",
|
|
15591
|
+
" .[] |",
|
|
15592
|
+
" (.labels | map(.name)) as $labels |",
|
|
15593
|
+
" if .isDraft then",
|
|
15594
|
+
' "PR_SKIP #\\(.number) reason=draft"',
|
|
15595
|
+
' elif ($labels | index("review:human-required")) then',
|
|
15596
|
+
' "PR_SKIP #\\(.number) reason=human-required"',
|
|
15597
|
+
' elif ($labels | index("review:awaiting-human")) then',
|
|
15598
|
+
' "PR_SKIP #\\(.number) reason=awaiting-human"',
|
|
15599
|
+
" else",
|
|
15600
|
+
' "PR_ELIGIBLE #\\(.number)"',
|
|
15601
|
+
" end",
|
|
15602
|
+
" '",
|
|
15603
|
+
"}",
|
|
15604
|
+
"",
|
|
15605
|
+
"cmd_needs_worker() {",
|
|
15606
|
+
" # Phase B1 feedback-drain: enumerate open PRs carrying the durable",
|
|
15607
|
+
" # `review:needs-worker` marker that are NOT already in-flight (no",
|
|
15608
|
+
" # `review:fixing` lease), ordered highest-priority-first so the",
|
|
15609
|
+
" # orchestrator dispatches `issue-worker` per PR to consume the",
|
|
15610
|
+
" # reviewer's fix-list. A PR holding both labels is a delegation",
|
|
15611
|
+
" # mid-flight \u2014 it is skipped (reason=in-flight) so the drain stays",
|
|
15612
|
+
" # idempotent and respects the cross-session lease semantics.",
|
|
15613
|
+
" local prs",
|
|
15614
|
+
" prs=$(gh pr list --state open --label 'review:needs-worker' \\",
|
|
15615
|
+
' --json number,labels --limit 50 2>/dev/null || echo "[]")',
|
|
15616
|
+
"",
|
|
15617
|
+
" local count",
|
|
15618
|
+
` count=$(echo "$prs" | jq 'length')`,
|
|
15619
|
+
' if [[ "$count" -eq 0 ]]; then',
|
|
15620
|
+
' echo "NO_NEEDS_WORKER_PRS"',
|
|
15621
|
+
" return 0",
|
|
15622
|
+
" fi",
|
|
15623
|
+
"",
|
|
15624
|
+
" # First pass: split into skip (in-flight) and drain-candidate sets.",
|
|
15625
|
+
" # The skip lines are emitted immediately for log visibility; the",
|
|
15626
|
+
" # candidates are resolved to a priority key and sorted before",
|
|
15627
|
+
" # emission so the orchestrator drains highest-priority first.",
|
|
15628
|
+
" local candidates",
|
|
15629
|
+
` candidates=$(echo "$prs" | jq -r '`,
|
|
15630
|
+
" sort_by(.number) |",
|
|
15631
|
+
" .[] |",
|
|
15632
|
+
" (.labels | map(.name)) as $labels |",
|
|
15633
|
+
' if ($labels | index("review:fixing")) then',
|
|
15634
|
+
' "SKIP\\t\\(.number)"',
|
|
15635
|
+
" else",
|
|
15636
|
+
' "DRAIN\\t\\(.number)"',
|
|
15637
|
+
" end",
|
|
15638
|
+
" ')",
|
|
15639
|
+
"",
|
|
15640
|
+
' local drain_rows=""',
|
|
15641
|
+
' local emitted_any=""',
|
|
15642
|
+
" while IFS=$'\\t' read -r kind pr_num; do",
|
|
15643
|
+
' [[ -z "$pr_num" ]] && continue',
|
|
15644
|
+
' if [[ "$kind" == "SKIP" ]]; then',
|
|
15645
|
+
' echo "PR_SKIP #${pr_num} reason=in-flight"',
|
|
15646
|
+
' emitted_any="1"',
|
|
15647
|
+
" continue",
|
|
15648
|
+
" fi",
|
|
15649
|
+
" # DRAIN candidate \u2014 resolve the linked issue's priority so the",
|
|
15650
|
+
" # drain order is highest-priority-first, tie-broken by PR number",
|
|
15651
|
+
" # ascending (FIFO, mirroring the queue scan's number-asc tie-break).",
|
|
15652
|
+
" local pkey",
|
|
15653
|
+
' pkey=$(priority_key_for_pr "$pr_num")',
|
|
15654
|
+
' drain_rows="${drain_rows}${pkey}\\t${pr_num}\\n"',
|
|
15655
|
+
' done <<< "$candidates"',
|
|
15656
|
+
"",
|
|
15657
|
+
' if [[ -n "$drain_rows" ]]; then',
|
|
15658
|
+
" # Sort by priority key asc \u2192 PR number asc, then emit one",
|
|
15659
|
+
" # PR_DRAIN line per PR in that order.",
|
|
15660
|
+
` printf '%b' "$drain_rows" \\`,
|
|
15661
|
+
" | sort -t$'\\t' -k1,1n -k2,2n \\",
|
|
15662
|
+
" | while IFS=$'\\t' read -r _pkey pr_num; do",
|
|
15663
|
+
' [[ -z "$pr_num" ]] && continue',
|
|
15664
|
+
' echo "PR_DRAIN #${pr_num}"',
|
|
15665
|
+
" done",
|
|
15666
|
+
' emitted_any="1"',
|
|
15667
|
+
" fi",
|
|
15668
|
+
"",
|
|
15669
|
+
' if [[ -z "$emitted_any" ]]; then',
|
|
15670
|
+
' echo "NO_NEEDS_WORKER_PRS"',
|
|
15671
|
+
" fi",
|
|
15672
|
+
"}",
|
|
15673
|
+
"",
|
|
15674
|
+
"# \u2500\u2500 main \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
15675
|
+
"",
|
|
15676
|
+
'case "${1:-review}" in',
|
|
15677
|
+
' review) shift || true; cmd_review "$@" ;;',
|
|
15678
|
+
' needs-worker) shift || true; cmd_needs_worker "$@" ;;',
|
|
15679
|
+
" *)",
|
|
15680
|
+
' echo "Usage: pr-sweep.sh <review|needs-worker>" >&2',
|
|
15681
|
+
" exit 1",
|
|
15682
|
+
" ;;",
|
|
15683
|
+
"esac"
|
|
15367
15684
|
].join("\n");
|
|
15368
15685
|
}
|
|
15369
15686
|
function buildPrSweepProcedure() {
|
|
15370
15687
|
return {
|
|
15371
15688
|
name: "pr-sweep.sh",
|
|
15372
|
-
description: "Token-efficient PR
|
|
15689
|
+
description: "Token-efficient PR enumeration for the orchestrator. In `review` mode (default) it emits one `PR_ELIGIBLE #<n>` or `PR_SKIP #<n> reason=<draft|human-required|awaiting-human>` line per open PR so the orchestrator dispatches `pr-reviewer` per eligible PR. In `needs-worker` mode it lists open PRs carrying the `review:needs-worker` marker that are not already in-flight (skipping any holding the `review:fixing` lease as `reason=in-flight`), emitting `PR_DRAIN #<n>` lines ordered highest-priority-first so the orchestrator drains the feedback queue by dispatching `issue-worker` per PR; `NO_NEEDS_WORKER_PRS` when none.",
|
|
15373
15690
|
content: buildPrSweepScript()
|
|
15374
15691
|
};
|
|
15375
15692
|
}
|
|
15376
15693
|
var prSweepProcedure = buildPrSweepProcedure();
|
|
15694
|
+
function buildCompleteFeedbackHandoffScript() {
|
|
15695
|
+
return [
|
|
15696
|
+
"#!/usr/bin/env bash",
|
|
15697
|
+
"# complete-feedback-handoff.sh \u2014 Atomic feedback-mode hand-off for the",
|
|
15698
|
+
"# issue-worker (Phase 6.5). Posts the structured worker-report comment",
|
|
15699
|
+
"# AND removes the `review:needs-worker` marker in ONE invocation,",
|
|
15700
|
+
"# exiting non-zero on any failure so a successful push can never land",
|
|
15701
|
+
"# without the hand-off completing.",
|
|
15702
|
+
"#",
|
|
15703
|
+
"# The marker is cleared even when some (or all) fix-list items failed \u2014",
|
|
15704
|
+
"# a partial result is reported per-item but must not wedge the PR. The",
|
|
15705
|
+
"# `review:fixing` lease is left in place for the reviewer's confirm pass.",
|
|
15706
|
+
"#",
|
|
15707
|
+
"# Usage:",
|
|
15708
|
+
"# complete-feedback-handoff.sh <pr-number> <commit-sha> <items-json>",
|
|
15709
|
+
"#",
|
|
15710
|
+
"# <items-json> \u2014 JSON array of per-item outcomes keyed by the",
|
|
15711
|
+
"# fix-list `comment_id`:",
|
|
15712
|
+
'# [{"comment_id":"IC_abc","outcome":"applied","detail":""},',
|
|
15713
|
+
'# {"comment_id":"IC_def","outcome":"failed","detail":"reason"}]',
|
|
15714
|
+
"# `outcome` is `applied` or `failed`.",
|
|
15715
|
+
"",
|
|
15716
|
+
"set -uo pipefail",
|
|
15717
|
+
"",
|
|
15718
|
+
'pr_number="${1:-}"',
|
|
15719
|
+
'commit_sha="${2:-}"',
|
|
15720
|
+
'items_json="${3:-}"',
|
|
15721
|
+
"",
|
|
15722
|
+
'if [[ -z "$pr_number" || -z "$commit_sha" || -z "$items_json" ]]; then',
|
|
15723
|
+
' echo "Usage: complete-feedback-handoff.sh <pr-number> <commit-sha> <items-json>" >&2',
|
|
15724
|
+
" exit 2",
|
|
15725
|
+
"fi",
|
|
15726
|
+
"",
|
|
15727
|
+
"# Validate the items JSON up front \u2014 a malformed payload must fail",
|
|
15728
|
+
"# loudly before we mutate any PR state.",
|
|
15729
|
+
`if ! echo "$items_json" | jq -e 'type == "array"' >/dev/null 2>&1; then`,
|
|
15730
|
+
' echo "complete-feedback-handoff: <items-json> is not a JSON array" >&2',
|
|
15731
|
+
" exit 2",
|
|
15732
|
+
"fi",
|
|
15733
|
+
"",
|
|
15734
|
+
"# \u2500\u2500 Build the structured worker report \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
15735
|
+
"# One markdown checklist line per item (\u2713 applied / \u2717 failed), keyed by",
|
|
15736
|
+
"# comment_id so the reviewer's confirm pass reacts on the right source",
|
|
15737
|
+
"# comment. Includes the pushed commit SHA and an overall outcome",
|
|
15738
|
+
"# (`complete` when every item applied, `partial` when any failed).",
|
|
15739
|
+
`applied_count=$(echo "$items_json" | jq '[.[] | select(.outcome == "applied")] | length')`,
|
|
15740
|
+
`failed_count=$(echo "$items_json" | jq '[.[] | select(.outcome == "failed")] | length')`,
|
|
15741
|
+
"",
|
|
15742
|
+
'overall="complete"',
|
|
15743
|
+
'if [[ "$failed_count" -gt 0 ]]; then',
|
|
15744
|
+
' overall="partial"',
|
|
15745
|
+
"fi",
|
|
15746
|
+
"",
|
|
15747
|
+
`item_lines=$(echo "$items_json" | jq -r '`,
|
|
15748
|
+
" .[] |",
|
|
15749
|
+
' if .outcome == "applied" then',
|
|
15750
|
+
' "- [x] `\\(.comment_id)` \u2014 applied"',
|
|
15751
|
+
" else",
|
|
15752
|
+
' "- [ ] `\\(.comment_id)` \u2014 **failed**" + (if (.detail // "") != "" then " (\\(.detail))" else "" end)',
|
|
15753
|
+
" end",
|
|
15754
|
+
"')",
|
|
15755
|
+
"",
|
|
15756
|
+
"report=$(cat <<EOF",
|
|
15757
|
+
"## Worker report",
|
|
15758
|
+
"",
|
|
15759
|
+
"Feedback-mode fix-list applied on commit \\`${commit_sha}\\`.",
|
|
15760
|
+
"",
|
|
15761
|
+
"**Outcome:** ${overall} (${applied_count} applied, ${failed_count} failed)",
|
|
15762
|
+
"",
|
|
15763
|
+
"${item_lines}",
|
|
15764
|
+
"",
|
|
15765
|
+
"<!-- issue-worker feedback hand-off \u2014 review:needs-worker cleared -->",
|
|
15766
|
+
"EOF",
|
|
15767
|
+
")",
|
|
15768
|
+
"",
|
|
15769
|
+
"# \u2500\u2500 1. Post the worker-report comment \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
15770
|
+
"# The report is ALWAYS posted, even when every item failed \u2014 the",
|
|
15771
|
+
"# reviewer's confirm pass needs the record to react and fall through to",
|
|
15772
|
+
"# the human-required hand-off rather than silently wedging.",
|
|
15773
|
+
'if ! echo "$report" | gh pr comment "$pr_number" --body-file -; then',
|
|
15774
|
+
' echo "complete-feedback-handoff: failed to post worker-report comment on PR #${pr_number}" >&2',
|
|
15775
|
+
" exit 1",
|
|
15776
|
+
"fi",
|
|
15777
|
+
"",
|
|
15778
|
+
"# \u2500\u2500 2. Clear the durable review:needs-worker marker \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
15779
|
+
"# Removing the marker (not the `review:fixing` lease) flips the PR into",
|
|
15780
|
+
"# the lease-without-marker state the reviewer's confirm pass keys on.",
|
|
15781
|
+
"# Cleared unconditionally on a partial result so the PR never wedges.",
|
|
15782
|
+
`if ! gh pr edit "$pr_number" --remove-label 'review:needs-worker'; then`,
|
|
15783
|
+
' echo "complete-feedback-handoff: failed to remove review:needs-worker from PR #${pr_number}" >&2',
|
|
15784
|
+
" exit 1",
|
|
15785
|
+
"fi",
|
|
15786
|
+
"",
|
|
15787
|
+
'echo "HANDOFF_DONE pr=#${pr_number} outcome=${overall} applied=${applied_count} failed=${failed_count}"'
|
|
15788
|
+
].join("\n");
|
|
15789
|
+
}
|
|
15790
|
+
function buildCompleteFeedbackHandoffProcedure() {
|
|
15791
|
+
return {
|
|
15792
|
+
name: "complete-feedback-handoff.sh",
|
|
15793
|
+
description: "Atomic feedback-mode hand-off for the issue-worker (Phase 6.5). Given `<pr-number> <commit-sha> <items-json>`, it posts the structured `## Worker report` comment (per-item outcomes keyed by fix-list `comment_id`, `applied` / `failed`) AND removes the `review:needs-worker` marker in one invocation, exiting non-zero on any failure so a clean push can never land without the hand-off completing. The marker is cleared even when some or all items failed (overall outcome `partial`) so a partial result never wedges the PR; the `review:fixing` lease is left for the reviewer's confirm pass.",
|
|
15794
|
+
content: buildCompleteFeedbackHandoffScript()
|
|
15795
|
+
};
|
|
15796
|
+
}
|
|
15797
|
+
var completeFeedbackHandoffProcedure = buildCompleteFeedbackHandoffProcedure();
|
|
15377
15798
|
var orchestratorSubAgent = {
|
|
15378
15799
|
name: "orchestrator",
|
|
15379
15800
|
description: "End-to-end pipeline manager that runs one full cycle every invocation: triage \u2192 maintenance \u2192 queue scan \u2192 delegate the picked issue to the issue-worker \u2192 cleanup",
|
|
@@ -15386,9 +15807,11 @@ var orchestratorSubAgent = {
|
|
|
15386
15807
|
"You are the pipeline orchestrator for the **{{repository.owner}}/{{repository.name}}** repository.",
|
|
15387
15808
|
"Each invocation runs **one full end-to-end cycle**. The cycle pulls",
|
|
15388
15809
|
"the default branch, sweeps eligible open PRs through the `pr-reviewer`",
|
|
15389
|
-
"sub-agent,
|
|
15390
|
-
"
|
|
15391
|
-
"
|
|
15810
|
+
"sub-agent, **drains every open `review:needs-worker` PR through the",
|
|
15811
|
+
"`issue-worker`** to consume the reviewer's fix-lists, triages blocked",
|
|
15812
|
+
"issues, runs maintenance scans, picks the next ready issue, and",
|
|
15813
|
+
"**delegates implementation to the `issue-worker`** sub-agent in",
|
|
15814
|
+
"scheduled mode. The orchestrator itself never implements",
|
|
15392
15815
|
"code, creates branches, pushes commits, or merges PRs \u2014 it routes",
|
|
15393
15816
|
"work to other agents. The merge decision is still owned by the",
|
|
15394
15817
|
"`pr-reviewer` sub-agent; the orchestrator only chooses which PRs the",
|
|
@@ -15405,16 +15828,22 @@ var orchestratorSubAgent = {
|
|
|
15405
15828
|
" eligibility summary and dispatch the `pr-reviewer` sub-agent",
|
|
15406
15829
|
" in scheduled mode against each eligible open PR. Failures on",
|
|
15407
15830
|
" one PR never stop the sweep.",
|
|
15408
|
-
"3. **Phase
|
|
15831
|
+
"3. **Phase B1 \u2014 Feedback Drain.** Read the procedure-script's",
|
|
15832
|
+
" needs-worker enumeration and dispatch a top-level `issue-worker`",
|
|
15833
|
+
" per open `review:needs-worker` PR \u2014 highest-priority first \u2014 to",
|
|
15834
|
+
" consume the reviewer's fix-list. Drains **every** eligible",
|
|
15835
|
+
" marker PR in the cycle. Feedback PRs are preferred over fresh",
|
|
15836
|
+
" issues, so this phase runs before the queue scan.",
|
|
15837
|
+
"4. **Phase C \u2014 Triage / Unblock.** Flip dependents that have all",
|
|
15409
15838
|
" their dependencies closed back to `status:ready`.",
|
|
15410
|
-
"
|
|
15839
|
+
"5. **Phase D \u2014 Maintenance.** Stale-issue and orphaned-resource scan",
|
|
15411
15840
|
" plus a needs-attention summary.",
|
|
15412
|
-
"
|
|
15841
|
+
"6. **Phase E \u2014 Queue Scan.** Pick the highest-priority `PICK` line",
|
|
15413
15842
|
" and run the scope gate. If the result is `large`, flag and stop.",
|
|
15414
|
-
"
|
|
15843
|
+
"7. **Phase G \u2014 Delegate Implementation.** Hand the picked issue off",
|
|
15415
15844
|
" to the `issue-worker` sub-agent in scheduled mode. The worker",
|
|
15416
15845
|
" handles claim \u2192 branch \u2192 implement \u2192 commit \u2192 PR autonomously.",
|
|
15417
|
-
"
|
|
15846
|
+
"8. **Phase F \u2014 Cleanup.** Return to the default branch and log the",
|
|
15418
15847
|
" run summary.",
|
|
15419
15848
|
"",
|
|
15420
15849
|
"Phase letters are stable identifiers \u2014 letters skipped in the list",
|
|
@@ -15447,7 +15876,7 @@ var orchestratorSubAgent = {
|
|
|
15447
15876
|
"metadata, mirroring the discipline of Phase E's bucketed queue scan.",
|
|
15448
15877
|
"",
|
|
15449
15878
|
"```bash",
|
|
15450
|
-
".claude/procedures/pr-sweep.sh",
|
|
15879
|
+
".claude/procedures/pr-sweep.sh review",
|
|
15451
15880
|
"```",
|
|
15452
15881
|
"",
|
|
15453
15882
|
"Each line follows one of these shapes:",
|
|
@@ -15468,7 +15897,7 @@ var orchestratorSubAgent = {
|
|
|
15468
15897
|
" (the reviewer already handed off; a human is the next actor)",
|
|
15469
15898
|
"",
|
|
15470
15899
|
"If the script emits `NO_OPEN_PRS`, log the empty result and skip",
|
|
15471
|
-
"directly to Phase
|
|
15900
|
+
"directly to Phase B1.",
|
|
15472
15901
|
"",
|
|
15473
15902
|
"### Step 2 \u2014 dispatch the reviewer per eligible PR",
|
|
15474
15903
|
"",
|
|
@@ -15502,7 +15931,103 @@ var orchestratorSubAgent = {
|
|
|
15502
15931
|
"eligible.",
|
|
15503
15932
|
"",
|
|
15504
15933
|
"After every eligible PR has been processed (or zero eligible PRs",
|
|
15505
|
-
"were emitted), continue to Phase
|
|
15934
|
+
"were emitted), continue to Phase B1 regardless of outcomes.",
|
|
15935
|
+
"",
|
|
15936
|
+
"## Phase B1: Feedback Drain",
|
|
15937
|
+
"",
|
|
15938
|
+
"Phase B **produces** `review:needs-worker` markers (the reviewer's",
|
|
15939
|
+
"pull-based hand-off applies one whenever it delegates an in-scope",
|
|
15940
|
+
"fix-list); Phase B1 **consumes** them. The pr-reviewer cannot spawn",
|
|
15941
|
+
"the worker in session \u2014 it frequently runs at depth-1 \u2014 so it leaves",
|
|
15942
|
+
"a durable marker and exits. The orchestrator runs at depth-0, so it",
|
|
15943
|
+
"**can** spawn `issue-worker`; this phase actively drains the marker",
|
|
15944
|
+
"queue every cycle by dispatching one top-level worker per marked PR.",
|
|
15945
|
+
"Without it, `review:needs-worker` PRs accumulate forever \u2014 the",
|
|
15946
|
+
"marker-draining path is otherwise unreachable from the running loop,",
|
|
15947
|
+
"because Phase G always hands the worker a fresh issue number, which",
|
|
15948
|
+
"suppresses the worker's own autonomous feedback-pull discovery.",
|
|
15949
|
+
"",
|
|
15950
|
+
"**Feedback PRs are preferred over fresh issues**, so this phase runs",
|
|
15951
|
+
"before the queue scan (Phase E) and the delegation (Phase G): a",
|
|
15952
|
+
"queued fix-list is a half-finished unit of work and should land",
|
|
15953
|
+
"before any new work starts.",
|
|
15954
|
+
"",
|
|
15955
|
+
"### Step 1 \u2014 read the needs-worker enumeration",
|
|
15956
|
+
"",
|
|
15957
|
+
"Run the bundled `pr-sweep.sh` procedure in `needs-worker` mode and",
|
|
15958
|
+
"read **only** the summary lines it emits. Do **not** iterate raw",
|
|
15959
|
+
"`gh pr list` JSON yourself \u2014 the procedure is the single source of",
|
|
15960
|
+
"needs-worker metadata, mirroring Phase B's `review`-mode discipline.",
|
|
15961
|
+
"",
|
|
15962
|
+
"```bash",
|
|
15963
|
+
".claude/procedures/pr-sweep.sh needs-worker",
|
|
15964
|
+
"```",
|
|
15965
|
+
"",
|
|
15966
|
+
"Each line follows one of these shapes:",
|
|
15967
|
+
"",
|
|
15968
|
+
"```",
|
|
15969
|
+
"PR_DRAIN #<n>",
|
|
15970
|
+
"PR_SKIP #<n> reason=in-flight",
|
|
15971
|
+
"```",
|
|
15972
|
+
"",
|
|
15973
|
+
"The procedure enumerates every open PR carrying the",
|
|
15974
|
+
"`review:needs-worker` marker, ordered **highest-priority-first**",
|
|
15975
|
+
"(linked-issue `priority:*`, tie-broken by PR number ascending). It",
|
|
15976
|
+
"skips \u2014 never drains \u2014 any PR that **also** carries the",
|
|
15977
|
+
"`review:fixing` lease: that label pair means a delegation is already",
|
|
15978
|
+
"in flight (a worker is mid-run or the reviewer's confirm pass is",
|
|
15979
|
+
"pending), so re-dispatching would double-work the fix-list. This is",
|
|
15980
|
+
"what makes the phase **idempotent** \u2014 a PR already being worked, or",
|
|
15981
|
+
"one whose marker was already cleared by a finished worker, never",
|
|
15982
|
+
"appears as a `PR_DRAIN` line.",
|
|
15983
|
+
"",
|
|
15984
|
+
"If the script emits `NO_NEEDS_WORKER_PRS`, log the empty result and",
|
|
15985
|
+
"skip directly to Phase C.",
|
|
15986
|
+
"",
|
|
15987
|
+
"### Step 2 \u2014 dispatch a worker per drain PR",
|
|
15988
|
+
"",
|
|
15989
|
+
"For **each** `PR_DRAIN #<n>` line in the order the procedure emitted",
|
|
15990
|
+
"them (highest-priority first), invoke the `issue-worker` sub-agent",
|
|
15991
|
+
"**in scheduled mode** with the brief below. Loop until every",
|
|
15992
|
+
"`PR_DRAIN` line has been dispatched \u2014 do **not** stop after the",
|
|
15993
|
+
"first. Substitute `<n>` with the PR number from the line.",
|
|
15994
|
+
"",
|
|
15995
|
+
"> `scheduled mode`: `feedback mode: PR #<n>`. Pull the reviewer's",
|
|
15996
|
+
"> most-recent fix-list comment on PR #<n>, check out the PR's head",
|
|
15997
|
+
"> branch, apply each fix-list item, run the verification commands,",
|
|
15998
|
+
"> commit with a `fix(review)` message, push to the existing branch",
|
|
15999
|
+
"> (never force-push, never open a new PR), then \u2014 as the first action",
|
|
16000
|
+
"> after the push \u2014 run `complete-feedback-handoff.sh` to atomically",
|
|
16001
|
+
"> post the structured worker-report comment and clear the",
|
|
16002
|
+
"> `review:needs-worker` marker (leave `review:fixing` for the",
|
|
16003
|
+
"> reviewer's confirm pass). The unit of work is not complete until",
|
|
16004
|
+
"> that procedure returns 0. Do not",
|
|
16005
|
+
"> pause for approval. Return a one-line summary as the final line of",
|
|
16006
|
+
"> your response in the form `WORKER_DONE pr:#<n>` on success or",
|
|
16007
|
+
"> `WORKER_FAILED pr:#<n> reason:<short reason>` on failure.",
|
|
16008
|
+
"",
|
|
16009
|
+
"The `feedback mode: PR #<n>` push is the explicit-pull form documented",
|
|
16010
|
+
"in the **Invocation Mode** section of `.claude/agents/issue-worker.md`",
|
|
16011
|
+
"\u2014 it always wins, so the worker fixes exactly that PR and does not",
|
|
16012
|
+
"scan the issue queue. The orchestrator is **read-only** with respect",
|
|
16013
|
+
"to the PR and its branch: never check out the branch, apply the",
|
|
16014
|
+
"fix-list, push commits, or edit review labels yourself. Consuming the",
|
|
16015
|
+
"fix-list and clearing `review:needs-worker` is the worker's job.",
|
|
16016
|
+
"",
|
|
16017
|
+
"### Step 3 \u2014 failure semantics",
|
|
16018
|
+
"",
|
|
16019
|
+
"A single PR's worker failure (missing or malformed `WORKER_*` final",
|
|
16020
|
+
"line, sub-agent error, unresolvable rebase conflict) **never stops",
|
|
16021
|
+
"the drain**. Log the failure as",
|
|
16022
|
+
"`WORKER_FAILED pr:#<n> reason:<observed>` and continue to the next",
|
|
16023
|
+
"`PR_DRAIN` line. The next orchestrator invocation re-runs",
|
|
16024
|
+
"`pr-sweep.sh needs-worker` and re-dispatches a worker if the PR still",
|
|
16025
|
+
"carries an unconsumed marker. Do **not** retry the same PR in this",
|
|
16026
|
+
"session.",
|
|
16027
|
+
"",
|
|
16028
|
+
"After every `PR_DRAIN` PR has been processed (or",
|
|
16029
|
+
"`NO_NEEDS_WORKER_PRS` was emitted), continue to Phase C regardless",
|
|
16030
|
+
"of outcomes.",
|
|
15506
16031
|
"",
|
|
15507
16032
|
"## Phase C: Triage \u2014 Unblock",
|
|
15508
16033
|
"",
|
|
@@ -15550,31 +16075,35 @@ var orchestratorSubAgent = {
|
|
|
15550
16075
|
"## Phase D: Maintenance",
|
|
15551
16076
|
"",
|
|
15552
16077
|
"Run the bundled `check-blocked.sh maintenance` procedure and read",
|
|
15553
|
-
"**only** the
|
|
15554
|
-
"procedure folds the stale-detection,
|
|
15555
|
-
"needs-attention summary
|
|
15556
|
-
"
|
|
15557
|
-
"`status:needs-attention` label
|
|
15558
|
-
"for each stale / stale-blocked
|
|
15559
|
-
"
|
|
15560
|
-
"(`
|
|
16078
|
+
"**only** the two summary lines it emits \u2014 `MAINTENANCE_DONE` and",
|
|
16079
|
+
"`LEASE_RECONCILE`. The procedure folds the stale-detection,",
|
|
16080
|
+
"orphan-detection, needs-attention summary, and PR-lease",
|
|
16081
|
+
"auto-reconcile that earlier revisions split across D1, D2, and D3",
|
|
16082
|
+
"into a single sweep \u2014 applying the `status:needs-attention` label",
|
|
16083
|
+
"and posting the canned flag comment for each stale / stale-blocked",
|
|
16084
|
+
"issue itself, and reconciling stuck `review:fixing` PR leases",
|
|
16085
|
+
"itself, mirroring the discipline of Phase B (`pr-sweep.sh`) and",
|
|
16086
|
+
"Phase C (`check-blocked.sh unblock`).",
|
|
15561
16087
|
"",
|
|
15562
16088
|
"```bash",
|
|
15563
16089
|
".claude/procedures/check-blocked.sh maintenance",
|
|
15564
16090
|
"```",
|
|
15565
16091
|
"",
|
|
15566
|
-
"The script emits
|
|
16092
|
+
"The script emits two summary lines in this shape:",
|
|
15567
16093
|
"",
|
|
15568
16094
|
"```",
|
|
15569
16095
|
"MAINTENANCE_DONE flagged_stale=<N> flagged_blocked=<M> orphan_branches=<A> orphan_prs=<B> needs_attention_total=<T>",
|
|
16096
|
+
"LEASE_RECONCILE orphaned=<N> consumed_uncleared=<M>",
|
|
15570
16097
|
"```",
|
|
15571
16098
|
"",
|
|
15572
|
-
"Per-issue / per-orphan informational lines (`FLAGGED_STALE
|
|
15573
|
-
"`FLAGGED_BLOCKED #N`, `STALE #N \u2014 \u2026`, `STALE_BLOCKED #N \u2014 \u2026`,",
|
|
15574
|
-
"`ORPHAN_BRANCH \u2026`, `ORPHAN_PR #N \u2014 \u2026`, `FLAG_FAILED #N \u2014 \u2026
|
|
15575
|
-
"
|
|
15576
|
-
"
|
|
15577
|
-
"
|
|
16099
|
+
"Per-issue / per-orphan / per-PR informational lines (`FLAGGED_STALE",
|
|
16100
|
+
"#N`, `FLAGGED_BLOCKED #N`, `STALE #N \u2014 \u2026`, `STALE_BLOCKED #N \u2014 \u2026`,",
|
|
16101
|
+
"`ORPHAN_BRANCH \u2026`, `ORPHAN_PR #N \u2014 \u2026`, `FLAG_FAILED #N \u2014 \u2026`,",
|
|
16102
|
+
"`LEASE_ORPHANED PR #N \u2014 \u2026`, `LEASE_CONSUMED_UNCLEARED PR #N \u2014 \u2026`,",
|
|
16103
|
+
"`LEASE_RECONCILE_FAILED PR #N \u2014 \u2026`) are emitted for log visibility",
|
|
16104
|
+
"but are **not** load-bearing for the orchestrator \u2014 partial failures",
|
|
16105
|
+
"(one bad `gh` call) do not abort the sweep, they are simply omitted",
|
|
16106
|
+
"from the counters.",
|
|
15578
16107
|
"",
|
|
15579
16108
|
"**Important:** the script never auto-resets stale issues to",
|
|
15580
16109
|
"`status:ready`. It only adds `status:needs-attention`; the",
|
|
@@ -15584,9 +16113,36 @@ var orchestratorSubAgent = {
|
|
|
15584
16113
|
"but are never deleted by the orchestrator \u2014 a human reviews the",
|
|
15585
16114
|
"log lines and prunes orphans manually.",
|
|
15586
16115
|
"",
|
|
15587
|
-
"
|
|
15588
|
-
"
|
|
15589
|
-
"
|
|
16116
|
+
"**PR-lease auto-reconcile (`LEASE_RECONCILE`).** The sweep also",
|
|
16117
|
+
"unwedges PRs stuck in the feedback-drain loop, so no human is",
|
|
16118
|
+
"needed to free a stuck `review:fixing` lease. Two states are",
|
|
16119
|
+
"reconciled directly by the script (it mutates the labels itself \u2014",
|
|
16120
|
+
"the orchestrator only reads the summary line):",
|
|
16121
|
+
"",
|
|
16122
|
+
"- **Orphaned lease** \u2014 a PR carries `review:fixing` but **not**",
|
|
16123
|
+
" `review:needs-worker`, its reviewer fix-list comment is older",
|
|
16124
|
+
" than the 72h stale threshold, and no worker-report comment newer",
|
|
16125
|
+
" than the fix-list exists. The sweep **re-applies**",
|
|
16126
|
+
" `review:needs-worker` (a deliberate re-arm, not a silent",
|
|
16127
|
+
" force-release \u2014 the `review:fixing` lease is left untouched) and",
|
|
16128
|
+
" posts an audit-trail note comment, so the Phase B1 drain retries",
|
|
16129
|
+
" the delegation autonomously. Counted in `orphaned=<N>`.",
|
|
16130
|
+
"- **Consumed-but-uncleared wedge** \u2014 a PR carries **both**",
|
|
16131
|
+
" `review:needs-worker` and `review:fixing`, but the branch HEAD",
|
|
16132
|
+
" commit is newer than the fix-list comment and no worker-report",
|
|
16133
|
+
" exists (the worker pushed then skipped the hand-off). The sweep",
|
|
16134
|
+
" **removes** `review:needs-worker` and posts an audit-trail",
|
|
16135
|
+
" reconcile note, flipping the PR into the lease-without-marker",
|
|
16136
|
+
" state the reviewer confirm pass keys on so it can merge. Counted",
|
|
16137
|
+
" in `consumed_uncleared=<M>`.",
|
|
16138
|
+
"",
|
|
16139
|
+
"Every lease reconcile leaves an audit-trail note comment \u2014 a lease",
|
|
16140
|
+
"is never silently force-released. The `review:fixing` lease itself",
|
|
16141
|
+
"is always left for the reviewer confirm pass to release.",
|
|
16142
|
+
"",
|
|
16143
|
+
"Log both summary lines and continue to Phase E regardless of",
|
|
16144
|
+
"outcomes \u2014 a non-zero `flagged_*`, `orphan_*`, `orphaned`, or",
|
|
16145
|
+
"`consumed_uncleared` count is informational, not a failure.",
|
|
15590
16146
|
"",
|
|
15591
16147
|
"## Phase E: Queue Scan",
|
|
15592
16148
|
"",
|
|
@@ -15746,7 +16302,7 @@ var orchestratorSubAgent = {
|
|
|
15746
16302
|
"",
|
|
15747
16303
|
"1. **Never implement code.** You triage, scan, and delegate \u2014 you do not code.",
|
|
15748
16304
|
"2. **Never claim issues.** Do not add `status:in-progress` or create branches for issues. Phase G's `issue-worker` delegation is the only path that flips an issue's claim labels.",
|
|
15749
|
-
"3. **Always use procedure scripts.** Issue triage queries go through `.claude/procedures/check-blocked.sh`; PR-eligibility filtering goes through `.claude/procedures/pr-sweep.sh`. Never iterate raw `gh issue list` / `gh pr list` JSON in-context.",
|
|
16305
|
+
"3. **Always use procedure scripts.** Issue triage queries go through `.claude/procedures/check-blocked.sh`; PR-eligibility filtering (Phase B) goes through `.claude/procedures/pr-sweep.sh review`; the feedback-drain enumeration (Phase B1) goes through `.claude/procedures/pr-sweep.sh needs-worker`. Never iterate raw `gh issue list` / `gh pr list` JSON in-context.",
|
|
15750
16306
|
"4. **Follow CLAUDE.md conventions** for all git and gh operations.",
|
|
15751
16307
|
"5. **Priority order:** critical > high > medium > low > trivial, then **funnel tier asc** (lower tier wins ties), then FIFO by issue number.",
|
|
15752
16308
|
"6. **Never dispatch a `large` issue.** Always run the scope check",
|
|
@@ -15768,8 +16324,17 @@ var orchestratorSubAgent = {
|
|
|
15768
16324
|
" human approval and the delegation stalls.",
|
|
15769
16325
|
"9. **A failed reviewer never stops the sweep.** Phase B continues",
|
|
15770
16326
|
" to the next eligible PR after a `REVIEWER_FAILED` line and",
|
|
15771
|
-
" proceeds to Phase
|
|
15772
|
-
" abort the cycle on a single PR's reviewer failure."
|
|
16327
|
+
" proceeds to Phase B1 regardless of how many PRs failed. Do not",
|
|
16328
|
+
" abort the cycle on a single PR's reviewer failure.",
|
|
16329
|
+
"10. **Drain every `review:needs-worker` PR before fresh work.**",
|
|
16330
|
+
" Phase B1 dispatches a top-level `issue-worker` per open marker",
|
|
16331
|
+
" PR (highest-priority first) to consume the reviewer's fix-list,",
|
|
16332
|
+
" and loops until the queue is empty \u2014 feedback PRs are preferred",
|
|
16333
|
+
" over fresh issues, so Phase B1 runs before Phase E / Phase G.",
|
|
16334
|
+
" Skip any PR that also carries the `review:fixing` lease (a",
|
|
16335
|
+
" delegation already in flight) so the drain stays idempotent. A",
|
|
16336
|
+
" single worker's failure never stops the drain; the next cycle",
|
|
16337
|
+
" re-dispatches against any PR whose marker is still unconsumed."
|
|
15773
16338
|
].join("\n")
|
|
15774
16339
|
};
|
|
15775
16340
|
var issueWorkerSubAgent = {
|
|
@@ -15853,7 +16418,7 @@ var issueWorkerSubAgent = {
|
|
|
15853
16418
|
"| 4. Implement | Read issue AC, implement | Read most-recent reviewer-authored fix-list comment on the PR, parse JSON, apply each item. |",
|
|
15854
16419
|
"| 5. Verify | Unchanged | Unchanged. |",
|
|
15855
16420
|
"| 6. Commit and Push | Conventional commit, interactive pause | Commit message `fix(review): <summary> (PR #<n>)`. Pause behaviour unchanged. `git push` (no `-u`). |",
|
|
15856
|
-
"| 6.5. Complete the hand-off | n/a |
|
|
16421
|
+
"| 6.5. Complete the hand-off | n/a | **Mandatory, atomic.** As the first action after the push, run `complete-feedback-handoff.sh` to post the worker-report and **clear `review:needs-worker`** in one call (leave `review:fixing` for the reviewer's confirm pass). The unit of work is not complete until it returns 0. |",
|
|
15857
16422
|
"| 7. Open a PR | Open a new PR | **Skip.** |",
|
|
15858
16423
|
"| 8. Update Status | Set issue to `status:ready-for-review` | **Skip.** PR is still open; issue stays `status:in-progress`. |",
|
|
15859
16424
|
"| 9. Branch Cleanup | Poll for merge, delete branch | **Skip.** Return control to the pr-reviewer without polling. |",
|
|
@@ -16250,46 +16815,73 @@ var issueWorkerSubAgent = {
|
|
|
16250
16815
|
"git push -u origin <branch-name>",
|
|
16251
16816
|
"```",
|
|
16252
16817
|
"",
|
|
16253
|
-
"## Phase 6.5: Complete the Feedback Hand-off",
|
|
16818
|
+
"## Phase 6.5: Complete the Feedback Hand-off (MANDATORY, ATOMIC)",
|
|
16254
16819
|
"",
|
|
16255
16820
|
"**Normal mode:** Skip this phase entirely.",
|
|
16256
16821
|
"",
|
|
16257
|
-
"**Feedback mode
|
|
16258
|
-
"the
|
|
16259
|
-
"
|
|
16822
|
+
"**Feedback mode \u2014 the invariant.** A successful Phase 6 push is **not**",
|
|
16823
|
+
"the end of the unit of work. **If you pushed in feedback mode, the unit",
|
|
16824
|
+
"of work is NOT complete until `complete-feedback-handoff.sh` returns",
|
|
16825
|
+
"0.** The git push and the hand-off are a single atomic step: the marker",
|
|
16826
|
+
"must be cleared and the worker-report posted in the **same session** as",
|
|
16827
|
+
"the push. A clean push that leaves `review:needs-worker` set and posts",
|
|
16828
|
+
"no report double-wedges the PR \u2014 the reviewer's confirm pass never",
|
|
16829
|
+
"fires (the marker is still present) and stale-lease reclaim never fires",
|
|
16830
|
+
"(it requires the marker absent). Never stop, hand back to the caller,",
|
|
16831
|
+
"or move to any optional/secondary step until the procedure has exited 0.",
|
|
16832
|
+
"",
|
|
16833
|
+
"**This is the FIRST action after a successful push** \u2014 before any",
|
|
16834
|
+
"summary, log line, or secondary step. Call the deterministic procedure",
|
|
16835
|
+
"with the PR number, the commit SHA you pushed (or the rebased head SHA",
|
|
16836
|
+
"for a synthetic-rebase item), and the per-item outcomes JSON array:",
|
|
16837
|
+
"",
|
|
16838
|
+
"```bash",
|
|
16839
|
+
".claude/procedures/complete-feedback-handoff.sh <pr-number> <commit-sha> '<items-json>'",
|
|
16840
|
+
"```",
|
|
16260
16841
|
"",
|
|
16261
|
-
"
|
|
16262
|
-
"
|
|
16263
|
-
|
|
16264
|
-
"
|
|
16265
|
-
" item), and a per-item outcome keyed by `comment_id` \u2014 `handled`",
|
|
16266
|
-
" or `failed` (with a short reason for each failure). This is the",
|
|
16267
|
-
" same structured report you would otherwise return to the caller in",
|
|
16268
|
-
" the pushed-feedback case; post it as a PR comment so a separate",
|
|
16269
|
-
" reviewer session can consume it.",
|
|
16842
|
+
"The `<items-json>` argument is a JSON array of per-item outcomes keyed",
|
|
16843
|
+
"by the fix-list `comment_id` \u2014 one entry per item you applied in Phase",
|
|
16844
|
+
'4, each `{"comment_id": "<id>", "outcome": "applied"|"failed",',
|
|
16845
|
+
' "detail": "<short reason on failure>"}`:',
|
|
16270
16846
|
"",
|
|
16271
|
-
"
|
|
16272
|
-
"
|
|
16273
|
-
"
|
|
16847
|
+
"```json",
|
|
16848
|
+
"[",
|
|
16849
|
+
' {"comment_id": "IC_abc", "outcome": "applied", "detail": ""},',
|
|
16850
|
+
' {"comment_id": "IC_def", "outcome": "failed", "detail": "test still red"}',
|
|
16851
|
+
"]",
|
|
16852
|
+
"```",
|
|
16274
16853
|
"",
|
|
16275
|
-
"
|
|
16276
|
-
"
|
|
16277
|
-
"
|
|
16278
|
-
"
|
|
16279
|
-
"
|
|
16280
|
-
"
|
|
16854
|
+
"The procedure performs **both** halves of the hand-off in one call and",
|
|
16855
|
+
"exits non-zero on any failure:",
|
|
16856
|
+
"",
|
|
16857
|
+
"1. **Posts the structured `## Worker report` comment** \u2014 the record the",
|
|
16858
|
+
" reviewer's confirm pass reads to react on source comments and",
|
|
16859
|
+
" re-evaluate AC/CI. It renders one checklist line per `comment_id`",
|
|
16860
|
+
" (`applied` / `failed`), the pushed commit SHA, and an overall",
|
|
16861
|
+
" outcome (`complete` when every item applied, `partial` when any",
|
|
16862
|
+
" failed).",
|
|
16863
|
+
"2. **Removes the `review:needs-worker` marker** \u2014 leaving the",
|
|
16864
|
+
" `review:fixing` lease in place. Clearing the marker flips the PR",
|
|
16865
|
+
" into the lease-without-marker state the reviewer's confirm pass keys",
|
|
16866
|
+
" on.",
|
|
16867
|
+
"",
|
|
16868
|
+
"**Partial failure still clears the marker.** The worker-report is",
|
|
16869
|
+
"ALWAYS posted and the marker ALWAYS cleared even when every item",
|
|
16870
|
+
"`failed` (the procedure reports overall outcome `partial` and the",
|
|
16871
|
+
"per-item failures by `comment_id`). The reviewer's confirm pass reacts",
|
|
16872
|
+
"`thinking_face` on the failed items and falls through to the",
|
|
16873
|
+
"human-required hand-off via `review:awaiting-human`. Leaving the marker",
|
|
16874
|
+
"applied on a partial or total failure would wedge the PR, so the marker",
|
|
16875
|
+
"is cleared unconditionally \u2014 never remove it yourself out-of-band and",
|
|
16876
|
+
"never skip the procedure because items failed.",
|
|
16281
16877
|
"",
|
|
16282
|
-
"
|
|
16283
|
-
"
|
|
16284
|
-
"
|
|
16878
|
+
"If the procedure exits non-zero (e.g. the comment post or the label",
|
|
16879
|
+
"removal failed), the hand-off did **not** complete \u2014 retry it. Do not",
|
|
16880
|
+
"treat the pushed commit as a finished unit of work until the procedure",
|
|
16881
|
+
"returns 0.",
|
|
16285
16882
|
"",
|
|
16286
16883
|
"Do **not** remove `review:fixing` yourself, and do **not** re-enable",
|
|
16287
|
-
"auto-merge \u2014 both belong to the reviewer's confirm pass.
|
|
16288
|
-
"not apply any item (every item `failed`), still write the report and",
|
|
16289
|
-
"still clear `review:needs-worker`: the reviewer's confirm pass reacts",
|
|
16290
|
-
"`thinking_face` on the failed items and falls through to the",
|
|
16291
|
-
"human-required hand-off via `review:awaiting-human`. Leaving the",
|
|
16292
|
-
"marker applied on a total failure would wedge the PR.",
|
|
16884
|
+
"auto-merge \u2014 both belong to the reviewer's confirm pass.",
|
|
16293
16885
|
"",
|
|
16294
16886
|
"## Phase 7: Open a PR",
|
|
16295
16887
|
"",
|
|
@@ -16418,13 +17010,19 @@ var issueWorkerSubAgent = {
|
|
|
16418
17010
|
" highest-priority unconsumed fix-list first. A half-finished PR",
|
|
16419
17011
|
" should land before a new unit of work starts. The explicit",
|
|
16420
17012
|
" `feedback mode: PR #<n>` push always overrides both scans.",
|
|
16421
|
-
"16. **
|
|
16422
|
-
"
|
|
16423
|
-
"
|
|
16424
|
-
"
|
|
16425
|
-
"
|
|
16426
|
-
"
|
|
16427
|
-
"
|
|
17013
|
+
"16. **Complete the hand-off atomically; clear `review:needs-worker`,",
|
|
17014
|
+
" never `review:fixing`.** A successful feedback-mode push is not a",
|
|
17015
|
+
" finished unit of work until the hand-off completes. As the FIRST",
|
|
17016
|
+
" action after the push (Phase 6.5), run",
|
|
17017
|
+
" `.claude/procedures/complete-feedback-handoff.sh <pr> <commit-sha>",
|
|
17018
|
+
" '<items-json>'`, which posts the structured worker-report comment",
|
|
17019
|
+
" and removes **only** the `review:needs-worker` marker in one call,",
|
|
17020
|
+
" exiting non-zero on any failure. The unit of work is **not**",
|
|
17021
|
+
" complete until it returns 0. The `review:fixing` lease belongs to",
|
|
17022
|
+
" the reviewer's confirm pass \u2014 never remove it yourself, and never",
|
|
17023
|
+
" re-enable auto-merge. The procedure clears the marker even when",
|
|
17024
|
+
" every item failed (overall outcome `partial`), so a partial or",
|
|
17025
|
+
" crashed delegation does not wedge the PR.",
|
|
16428
17026
|
"17. **Auto-pull only in scheduled mode.** The autonomous",
|
|
16429
17027
|
" `review:needs-worker` scan is scheduled-mode only. In an",
|
|
16430
17028
|
" interactive session, never auto-pull a feedback PR \u2014 a human who",
|
|
@@ -16436,19 +17034,21 @@ var ORCHESTRATOR_CONVENTIONS_PREAMBLE = [
|
|
|
16436
17034
|
"",
|
|
16437
17035
|
"When running the orchestrator agent (`.claude/agents/orchestrator.md`):",
|
|
16438
17036
|
"",
|
|
16439
|
-
"- The orchestrator runs **one full end-to-end cycle every invocation**: startup \u2192 PR review sweep \u2192 triage / unblock \u2192 maintenance \u2192 queue scan \u2192 delegate to `issue-worker` \u2192 cleanup",
|
|
17037
|
+
"- The orchestrator runs **one full end-to-end cycle every invocation**: startup \u2192 PR review sweep \u2192 feedback drain \u2192 triage / unblock \u2192 maintenance \u2192 queue scan \u2192 delegate to `issue-worker` \u2192 cleanup",
|
|
16440
17038
|
"- The orchestrator **never** implements code, creates branches, or pushes commits \u2014 it routes work to other sub-agents. The merge decision is still owned by the `pr-reviewer` sub-agent; Phase B only chooses which open PRs the reviewer should look at and dispatches one reviewer session per eligible PR (skipping drafts and any PR carrying `review:human-required` or `review:awaiting-human`).",
|
|
16441
|
-
"-
|
|
17039
|
+
"- **Phase B produces `review:needs-worker` markers; Phase B1 consumes them.** Phase B's `pr-reviewer` dispatch leaves a durable `review:needs-worker` marker whenever it delegates a fix-list (it cannot spawn the worker in session \u2014 it may run at depth-1). Phase B1 (feedback drain) actively drains that queue every cycle: it dispatches a top-level `issue-worker` per open `review:needs-worker` PR \u2014 highest-priority first, looping until the queue is empty \u2014 to consume the reviewer's fix-list. **Feedback PRs are preferred over fresh issues**, so Phase B1 runs after the review sweep but before the queue scan (Phase E) and fresh delegation (Phase G). A PR that also carries the `review:fixing` lease is a delegation already in flight and is skipped, keeping the drain idempotent.",
|
|
17040
|
+
"- All triage queries use `.claude/procedures/check-blocked.sh` for token efficiency. PR-eligibility filtering for Phase B uses `.claude/procedures/pr-sweep.sh review`, which emits `PR_ELIGIBLE` / `PR_SKIP` lines; the Phase B1 feedback-drain enumeration uses `.claude/procedures/pr-sweep.sh needs-worker`, which emits `PR_DRAIN` / `PR_SKIP reason=in-flight` lines. The orchestrator never iterates raw `gh pr list` JSON.",
|
|
16442
17041
|
"- The queue scan reads only `priority:*` and `status:*` labels \u2014 type-routing (which typed agent handles a given `type:*` label) is the `issue-worker`'s concern, not the orchestrator's. The orchestrator's funnel-tier sort is a tie-breaker on `priority:*`, not a routing decision.",
|
|
16443
17042
|
"- Priority order: critical > high > medium > low > trivial, then **funnel tier asc** (lower tier wins ties), then FIFO by issue number. Phase E's queue scan walks each priority bucket in turn (one `gh issue list` call per bucket, **capped at 50 issues per bucket**) and short-circuits on the first bucket whose survivors clear the `Depends on:` filter, so every higher-priority issue is visible even when the global ready backlog is much larger than 50.",
|
|
16444
17043
|
"- Stale thresholds: 72h for in-progress, 168h for blocked",
|
|
16445
17044
|
"- Flagged issues get `status:needs-attention` \u2014 they are not auto-reset",
|
|
17045
|
+
"- **Phase D auto-reconciles stuck PR leases.** The maintenance sweep's `check-blocked.sh maintenance` invocation folds in a PR-lease reconcile that unwedges `review:fixing` PRs the Phase B1 drain and the worker hand-off left stuck, emitting a `LEASE_RECONCILE orphaned=<N> consumed_uncleared=<M>` line alongside `MAINTENANCE_DONE`. An **orphaned lease** (`review:fixing` without `review:needs-worker`, fix-list older than the 72h stale threshold, no worker-report newer than the fix-list) is **re-armed** \u2014 the sweep re-applies `review:needs-worker` so the Phase B1 drain retries the delegation, leaving the lease untouched. A **consumed-but-uncleared wedge** (both labels present, branch HEAD newer than the fix-list, no worker-report \u2014 the worker pushed but skipped the hand-off) is **auto-reconciled** \u2014 the sweep removes `review:needs-worker` so the reviewer confirm pass can merge. Both paths post an audit-trail note comment; a lease is never silently force-released, and the `review:fixing` lease itself is always left for the reviewer confirm pass to release.",
|
|
16446
17046
|
"",
|
|
16447
17047
|
"## Depth-0 invocation requirement",
|
|
16448
17048
|
"",
|
|
16449
|
-
'The orchestrator agent **must run as the top-level (depth-0) session** because
|
|
17049
|
+
'The orchestrator agent **must run as the top-level (depth-0) session** because Phase B (PR review sweep), Phase B1 (feedback drain), and Phase G (issue delegation) all need to spawn child sub-agents. Phase B dispatches the `pr-reviewer` sub-agent once per eligible open PR; Phase B1 dispatches the `issue-worker` sub-agent once per open `review:needs-worker` PR to consume the reviewer\'s fix-list; Phase G dispatches the `issue-worker` sub-agent against the picked issue. The Claude Code harness forbids nested sub-agent spawning \u2014 *"Subagents cannot spawn other subagents. If your workflow requires nested delegation, use Skills or chain subagents from the main conversation."* (see <https://code.claude.com/docs/en/sub-agents>). If the orchestrator itself were spawned as a depth-1 sub-agent (e.g. via `Agent(subagent_type: "orchestrator")` from another session), the `Agent` tool needed to reach `pr-reviewer` and `issue-worker` at depth-2 would not be available and Phase B, Phase B1, and Phase G would all silently abort. Phase B1 is precisely why the reviewer\'s pull-based hand-off works: the depth-1 reviewer leaves a durable `review:needs-worker` marker, and the depth-0 orchestrator \u2014 which *can* spawn the worker \u2014 drains it.',
|
|
16450
17050
|
"",
|
|
16451
|
-
'Practical implication for scheduled-task wiring: the `worker-orchestrator` scheduled task\'s `SKILL.md` instructs the **scheduled-task session itself** to read `.claude/agents/orchestrator.md` and execute its phase pipeline in-session, then use the `Agent` tool to delegate to `pr-reviewer` (Phase B) and `issue-worker` (Phase G) at depth-1. The scheduled task does **not** call `Agent(subagent_type: "orchestrator")` \u2014 that would put the orchestrator at depth-1 and break
|
|
17051
|
+
'Practical implication for scheduled-task wiring: the `worker-orchestrator` scheduled task\'s `SKILL.md` instructs the **scheduled-task session itself** to read `.claude/agents/orchestrator.md` and execute its phase pipeline in-session, then use the `Agent` tool to delegate to `pr-reviewer` (Phase B) and `issue-worker` (Phase B1 and Phase G) at depth-1. The scheduled task does **not** call `Agent(subagent_type: "orchestrator")` \u2014 that would put the orchestrator at depth-1 and break all three delegation chains.'
|
|
16452
17052
|
].join("\n");
|
|
16453
17053
|
function buildOrchestratorConventionsContent(tiers, scopeGate = resolveScopeGate(), _runRatio = resolveRunRatio(), scheduledTasks = resolveScheduledTasks(), unblockDependents = resolveUnblockDependents(), excludeBundles = []) {
|
|
16454
17054
|
return [
|
|
@@ -16501,8 +17101,10 @@ var orchestrateCommand = {
|
|
|
16501
17101
|
"# Orchestrate",
|
|
16502
17102
|
"",
|
|
16503
17103
|
"Invoke the `orchestrator` sub-agent and run **one full end-to-end",
|
|
16504
|
-
"cycle**:
|
|
16505
|
-
"
|
|
17104
|
+
"cycle**: PR review sweep \u2192 feedback drain (drain every open",
|
|
17105
|
+
"`review:needs-worker` PR through the `issue-worker`) \u2192 triage /",
|
|
17106
|
+
"unblock \u2192 maintenance \u2192 queue scan \u2192 delegate the picked issue to",
|
|
17107
|
+
"the `issue-worker` sub-agent \u2192 cleanup.",
|
|
16506
17108
|
"",
|
|
16507
17109
|
"Follow the contract in `.claude/agents/orchestrator.md`. Do **not**",
|
|
16508
17110
|
"implement code, create branches, push commits, or merge PRs \u2014 those",
|
|
@@ -16597,7 +17199,8 @@ var orchestratorBundle = {
|
|
|
16597
17199
|
procedures: [
|
|
16598
17200
|
checkBlockedProcedure,
|
|
16599
17201
|
unblockDependentsProcedure,
|
|
16600
|
-
prSweepProcedure
|
|
17202
|
+
prSweepProcedure,
|
|
17203
|
+
completeFeedbackHandoffProcedure
|
|
16601
17204
|
],
|
|
16602
17205
|
commands: [orchestrateCommand, checkBlockedCommand, scanCommand],
|
|
16603
17206
|
claudePermissions: {
|
|
@@ -18192,6 +18795,116 @@ var prReviewerSubAgent = {
|
|
|
18192
18795
|
"unchanged regardless of mode. Only the terminal action in Phase 4",
|
|
18193
18796
|
"branches on the decided mode.",
|
|
18194
18797
|
"",
|
|
18798
|
+
"## Phase 2.8: Label Reconciliation",
|
|
18799
|
+
"",
|
|
18800
|
+
"A PR can never carry **mutually-exclusive review-workflow labels**",
|
|
18801
|
+
"after a reviewer pass \u2014 this is the PR equivalent of the",
|
|
18802
|
+
'"exactly one `status:*`" discipline issues already follow.',
|
|
18803
|
+
"Successive passes that layer labels with no reconciler can drive a",
|
|
18804
|
+
"PR into an impossible state (a real PR once held",
|
|
18805
|
+
"`review:awaiting-human` + `status:needs-attention` + `review:fixing`",
|
|
18806
|
+
"+ `review:needs-worker` simultaneously). Humans cannot tell what",
|
|
18807
|
+
"state such a PR is in, and downstream phases branch on contradictory",
|
|
18808
|
+
"signals. This phase detects violations and resolves them to the",
|
|
18809
|
+
"**single correct state** implied by the mode decided in Phase 2.75",
|
|
18810
|
+
"and the current loop position, logging every correction in the",
|
|
18811
|
+
"sticky `## Reviewer notes` comment.",
|
|
18812
|
+
"",
|
|
18813
|
+
"Run this phase **early** \u2014 after Phase 2.75 fixes the review mode and",
|
|
18814
|
+
"after the **Confirm a Completed Delegation** detection step reads the",
|
|
18815
|
+
"lease state, but **before** Phase 3.5 / Phase 4 branch on review",
|
|
18816
|
+
"state to decide actions. It must operate on a clean label set so no",
|
|
18817
|
+
"later phase inherits a contradiction. It runs on **every** pass.",
|
|
18818
|
+
"",
|
|
18819
|
+
"### The review-label invariants",
|
|
18820
|
+
"",
|
|
18821
|
+
"These are the workflow labels this phase governs (see the",
|
|
18822
|
+
"`pr-review-feedback-protocol` label glossary for full meanings):",
|
|
18823
|
+
"`review:awaiting-human`, `review:needs-worker`, `review:fixing`,",
|
|
18824
|
+
"plus the additive `status:needs-attention`. (`review:human-required`",
|
|
18825
|
+
"and `review:auto-ok` are **policy inputs** read in Phase 2.75, not",
|
|
18826
|
+
"workflow-state labels \u2014 this phase never adds or removes them.)",
|
|
18827
|
+
"",
|
|
18828
|
+
"1. **`review:awaiting-human` is mutually exclusive with the",
|
|
18829
|
+
" fix-delegation labels.** A PR is **either** in the fix-delegation",
|
|
18830
|
+
" loop (`review:needs-worker` and/or `review:fixing`) **or** handed",
|
|
18831
|
+
" off to a human (`review:awaiting-human`) \u2014 **never both**. The",
|
|
18832
|
+
" combination `review:awaiting-human` + `review:needs-worker`,",
|
|
18833
|
+
" `review:awaiting-human` + `review:fixing`, or all three together",
|
|
18834
|
+
" is a **violation**.",
|
|
18835
|
+
"2. **`review:fixing` WITHOUT `review:needs-worker` is NOT a",
|
|
18836
|
+
" violation** \u2014 it is the **confirm-pending** state (the worker",
|
|
18837
|
+
" finished and cleared its marker; a confirm pass owns the PR and",
|
|
18838
|
+
" will release the lease). Do **not** strip `review:fixing` here.",
|
|
18839
|
+
"3. **`review:fixing` WITH `review:needs-worker` is NOT a violation**",
|
|
18840
|
+
" \u2014 it is a valid **in-flight delegation** (the work is durably",
|
|
18841
|
+
" queued and a top-level `issue-worker` pass will consume it). Do",
|
|
18842
|
+
" **not** treat this combination as a contradiction.",
|
|
18843
|
+
"4. **`status:needs-attention` is additive but must not coexist with",
|
|
18844
|
+
" an in-flight delegation that is making progress.** When the PR",
|
|
18845
|
+
" carries an active in-flight delegation (`review:fixing` +",
|
|
18846
|
+
" `review:needs-worker`) with a fix-list newer than the flag and no",
|
|
18847
|
+
" failed-fix pushback, `status:needs-attention` contradicts the",
|
|
18848
|
+
" live progress signal and is a **violation**. (A",
|
|
18849
|
+
" `status:needs-attention` flag that coexists with a *stalled* or",
|
|
18850
|
+
" *failed* delegation, an unresolved `thinking_face` pushback, or a",
|
|
18851
|
+
" `human-required` hand-off is **legitimate** \u2014 leave it.)",
|
|
18852
|
+
"",
|
|
18853
|
+
"### Canonical resolution table",
|
|
18854
|
+
"",
|
|
18855
|
+
"For each detected violation, resolve to the single correct state",
|
|
18856
|
+
"below. The winning label is chosen by the **mode the reviewer is",
|
|
18857
|
+
"about to act in** (Phase 2.75) and the **current loop position**",
|
|
18858
|
+
"(the lease/marker labels present), so the surviving set always",
|
|
18859
|
+
"matches the action this pass will actually take:",
|
|
18860
|
+
"",
|
|
18861
|
+
"| Violation combo | Loop position / mode | Resolution (winner) | Why |",
|
|
18862
|
+
"|-----------------|----------------------|---------------------|-----|",
|
|
18863
|
+
"| `review:awaiting-human` + (`review:needs-worker` and/or `review:fixing`) | A fix-delegation is in-flight or confirm-pending (`review:needs-worker` and/or `review:fixing` present) **and** mode is `auto-merge` | **Remove `review:awaiting-human`** | The PR is in the fix-delegation loop; the loop must run to completion (worker \u2192 confirm) before any hand-off. `review:awaiting-human` was layered by a stale pass and contradicts the live delegation. |",
|
|
18864
|
+
"| `review:awaiting-human` + (`review:needs-worker` and/or `review:fixing`) | This pass decided `human-required` (rules 2\u20135) **and** no delegation is actually in flight (no fresh fix-list / no worker activity) | **Remove `review:needs-worker` and `review:fixing`** | The reviewer is handing the PR to a human; the fix-delegation labels are stale leftovers. The hand-off wins, the delegation labels lose. Release the lease and clear the marker so the human owns a clean state. |",
|
|
18865
|
+
"| `status:needs-attention` + active in-flight delegation making progress (`review:fixing` + `review:needs-worker`, fix-list newer than the flag, no failed-fix pushback) | mode `auto-merge`, delegation live | **Remove `status:needs-attention`** | The delegation is progressing autonomously; the triage flag is contradictory. Re-flag only if the delegation later stalls or fails. |",
|
|
18866
|
+
"",
|
|
18867
|
+
"Resolution is **conservative about human intent**: when the pass is",
|
|
18868
|
+
"genuinely `human-required` the human-facing labels win and the",
|
|
18869
|
+
"fix-delegation labels are cleared; when the pass is `auto-merge` and",
|
|
18870
|
+
"a delegation is live, the delegation wins and the stray",
|
|
18871
|
+
"`review:awaiting-human` is cleared. Never resolve a violation by",
|
|
18872
|
+
"*adding* a label \u2014 only by removing the contradicting one(s) per the",
|
|
18873
|
+
"table.",
|
|
18874
|
+
"",
|
|
18875
|
+
"### Detect and apply",
|
|
18876
|
+
"",
|
|
18877
|
+
"1. List the PR's current labels:",
|
|
18878
|
+
"",
|
|
18879
|
+
" ```bash",
|
|
18880
|
+
" gh pr view <pr-number> --json labels --jq '.labels[].name'",
|
|
18881
|
+
" ```",
|
|
18882
|
+
"",
|
|
18883
|
+
"2. Evaluate the invariants above against the label set, the mode from",
|
|
18884
|
+
" Phase 2.75, and the lease/marker position. If no violation exists,",
|
|
18885
|
+
" record `Label reconciliation: consistent` and proceed \u2014 this is",
|
|
18886
|
+
" the common case and the phase is a cheap no-op.",
|
|
18887
|
+
"",
|
|
18888
|
+
"3. For each violation, remove the losing label(s) named in the",
|
|
18889
|
+
" resolution table:",
|
|
18890
|
+
"",
|
|
18891
|
+
" ```bash",
|
|
18892
|
+
" gh pr edit <pr-number> --remove-label '<losing-label>'",
|
|
18893
|
+
" ```",
|
|
18894
|
+
"",
|
|
18895
|
+
"4. **Log every correction in the sticky `## Reviewer notes` comment**",
|
|
18896
|
+
" (Phase 4.5) on a `**Label reconciliation:**` line, naming the",
|
|
18897
|
+
" detected violation combo, the labels removed, and the surviving",
|
|
18898
|
+
" self-consistent set \u2014 for example:",
|
|
18899
|
+
" `Label reconciliation: removed review:awaiting-human (contradicted in-flight review:fixing+review:needs-worker delegation); set is now {review:fixing, review:needs-worker}`.",
|
|
18900
|
+
" The correction is part of the audit trail; it must never be a",
|
|
18901
|
+
" silent label mutation.",
|
|
18902
|
+
"",
|
|
18903
|
+
"After this phase the PR holds a **self-consistent** review-label set:",
|
|
18904
|
+
"at most one of {`review:awaiting-human`} versus the fix-delegation",
|
|
18905
|
+
"pair, and no `status:needs-attention` shadowing a live delegation.",
|
|
18906
|
+
"Phase 3.5 and Phase 4 then branch on a clean state.",
|
|
18907
|
+
"",
|
|
18195
18908
|
"## Phase 3: Compare Diff to Acceptance Criteria",
|
|
18196
18909
|
"",
|
|
18197
18910
|
"Read the issue body for an **Acceptance Criteria** (or equivalent) section.",
|
|
@@ -18754,6 +19467,7 @@ var prReviewerSubAgent = {
|
|
|
18754
19467
|
"**CI status:** green | pending | red",
|
|
18755
19468
|
"**Outstanding:** <list of comments still open with their classification and author>",
|
|
18756
19469
|
"**Pushbacks:** <list of disputes with reasons>",
|
|
19470
|
+
"**Label reconciliation:** <consistent | corrections applied this pass>",
|
|
18757
19471
|
"**Last pass:** <ISO timestamp>",
|
|
18758
19472
|
"```",
|
|
18759
19473
|
"",
|
|
@@ -18773,6 +19487,11 @@ var prReviewerSubAgent = {
|
|
|
18773
19487
|
"- **Pushbacks** \u2014 every comment the reviewer reacted",
|
|
18774
19488
|
" `thinking_face` to on this or any prior pass, with the reason",
|
|
18775
19489
|
" captured in the pushback reply. Empty list when there are none.",
|
|
19490
|
+
"- **Label reconciliation** \u2014 the outcome of Phase 2.8: either",
|
|
19491
|
+
" `consistent` (no mutually-exclusive labels found) or a list of",
|
|
19492
|
+
" the corrections applied this pass (the detected violation combo,",
|
|
19493
|
+
" the label(s) removed, and the resulting self-consistent set).",
|
|
19494
|
+
" Every reconciliation correction is recorded here for auditability.",
|
|
18776
19495
|
"- **Last pass** \u2014 the ISO 8601 timestamp of this run.",
|
|
18777
19496
|
"",
|
|
18778
19497
|
"### Step 3: Create or edit in place",
|
|
@@ -19111,16 +19830,23 @@ var prReviewerSubAgent = {
|
|
|
19111
19830
|
"### Stale-lease reclaim",
|
|
19112
19831
|
"",
|
|
19113
19832
|
"A crashed worker must not wedge a PR forever. A `review:fixing` lease",
|
|
19114
|
-
"is **
|
|
19833
|
+
"is **orphaned** when it has no `review:needs-worker` companion",
|
|
19115
19834
|
"**and** no consuming worker is making progress \u2014 i.e. the lease is",
|
|
19116
19835
|
"older than the stale threshold (the same in-progress threshold the",
|
|
19117
19836
|
"maintenance sweep applies, 72h by default) with no worker-report",
|
|
19118
19837
|
"comment newer than the fix-list. The reclaim is wired into the",
|
|
19119
|
-
"maintenance sweep, not a reviewer pass: the sweep
|
|
19120
|
-
"
|
|
19121
|
-
"`review:fixing` lease and
|
|
19122
|
-
"
|
|
19123
|
-
"
|
|
19838
|
+
"maintenance sweep, not a reviewer pass: the sweep **re-applies**",
|
|
19839
|
+
"`review:needs-worker` (re-arming the durable work marker, leaving the",
|
|
19840
|
+
"`review:fixing` lease untouched) and posts an audit-trail note",
|
|
19841
|
+
"comment, so the Phase B1 feedback drain retries the delegation",
|
|
19842
|
+
"autonomously \u2014 no human is needed to free the lease. The maintenance",
|
|
19843
|
+
"sweep also auto-reconciles the **consumed-but-uncleared** wedge (both",
|
|
19844
|
+
"labels present, branch HEAD advanced past the fix-list, no",
|
|
19845
|
+
"worker-report) by removing `review:needs-worker` so the reviewer",
|
|
19846
|
+
"confirm pass can merge. A lease is never silently force-released \u2014 every",
|
|
19847
|
+
"reconcile posts an audit-trail note comment. See the **Stale-lease",
|
|
19848
|
+
"reclaim** subsection of the `pr-review-feedback-protocol` rule for the",
|
|
19849
|
+
"full lifecycle.",
|
|
19124
19850
|
"",
|
|
19125
19851
|
"## Phase 5: Branch Cleanup and Issue Closure Verification",
|
|
19126
19852
|
"",
|
|
@@ -19511,7 +20237,6 @@ function buildPrReviewBundle(policy = resolvePrReviewPolicy()) {
|
|
|
19511
20237
|
"",
|
|
19512
20238
|
"human-required:",
|
|
19513
20239
|
" paths:",
|
|
19514
|
-
' - "docs/src/content/docs/requirements/architectural-decisions/**"',
|
|
19515
20240
|
' - "docs/src/content/docs/project-context.md"',
|
|
19516
20241
|
' - ".github/workflows/**"',
|
|
19517
20242
|
' - ".github/CODEOWNERS"',
|
|
@@ -19610,6 +20335,35 @@ function buildPrReviewBundle(policy = resolvePrReviewPolicy()) {
|
|
|
19610
20335
|
"the carve-out check, so the rule only relaxes the threshold for",
|
|
19611
20336
|
"PRs whose **every** changed path is doc-only.",
|
|
19612
20337
|
"",
|
|
20338
|
+
"### ADRs auto-merge as `Proposed`",
|
|
20339
|
+
"",
|
|
20340
|
+
"Architectural Decision Records (under",
|
|
20341
|
+
"`docs/src/content/docs/requirements/architectural-decisions/**`)",
|
|
20342
|
+
"are **not** a `human-required.paths` trigger. An ADR-only PR with",
|
|
20343
|
+
"green CI and met acceptance criteria resolves to `auto-merge` and",
|
|
20344
|
+
"squash-merges with no `review:awaiting-human` and no human action.",
|
|
20345
|
+
"",
|
|
20346
|
+
"Auto-merging an ADR does **not** ratify the decision it records.",
|
|
20347
|
+
"An ADR is authored in `Proposed` status, and merging it simply",
|
|
20348
|
+
"lands the proposal in the docs tree as written \u2014 its status stays",
|
|
20349
|
+
"`Proposed`. Promotion `Proposed` \u2192 `Accepted` is a separate",
|
|
20350
|
+
"human / governance step performed out of band by a",
|
|
20351
|
+
"decision-maker; it is **not** a merge gate and nothing in the",
|
|
20352
|
+
"review loop flips an ADR to `Accepted`. Routing ADRs to",
|
|
20353
|
+
"`human-required` only piled them up at `review:awaiting-human`",
|
|
20354
|
+
"waiting for a merge decision that was never the human's job \u2014",
|
|
20355
|
+
"the human's job is the later acceptance decision, not the merge.",
|
|
20356
|
+
"",
|
|
20357
|
+
"The `requirements-writer` flow already authors ADRs in",
|
|
20358
|
+
"`Proposed` status (its Decision section reads",
|
|
20359
|
+
'"Pending human review"), so the merged-as-`Proposed` terminal',
|
|
20360
|
+
"state is supplied by the author, not enforced at the merge gate.",
|
|
20361
|
+
"Consumers that genuinely need a human to gate ADR *merges* (not",
|
|
20362
|
+
"just acceptance) cannot re-add the glob via policy config \u2014 the",
|
|
20363
|
+
"`human-required.paths` list is not consumer-configurable today;",
|
|
20364
|
+
"they would apply the `review:human-required` label per-PR or",
|
|
20365
|
+
"fork the bundle.",
|
|
20366
|
+
"",
|
|
19613
20367
|
"The `pr-reviewer` sub-agent records the decided mode, the",
|
|
19614
20368
|
"triggering reason, and the numeric **matched-rule index** (2\u20136",
|
|
19615
20369
|
"for human-required matches; `null` for rule 1 force-auto or",
|
|
@@ -19926,8 +20680,15 @@ function buildPrReviewBundle(policy = resolvePrReviewPolicy()) {
|
|
|
19926
20680
|
"#### Stale-lease reclaim",
|
|
19927
20681
|
"",
|
|
19928
20682
|
"A crashed or never-launched worker must not wedge a PR by holding",
|
|
19929
|
-
"the lease forever
|
|
19930
|
-
"
|
|
20683
|
+
"the lease forever, and a worker that pushes but skips its hand-off",
|
|
20684
|
+
"must not wedge the PR either. The **maintenance sweep** (not a",
|
|
20685
|
+
"reviewer pass) owns reconcile for **both** stuck states \u2014 its",
|
|
20686
|
+
"`check-blocked.sh maintenance` invocation runs the reconcile",
|
|
20687
|
+
"directly and emits a `LEASE_RECONCILE orphaned=<N>",
|
|
20688
|
+
"consumed_uncleared=<M>` summary line. No human is needed to free a",
|
|
20689
|
+
"stuck PR.",
|
|
20690
|
+
"",
|
|
20691
|
+
"**Orphaned lease.** A `review:fixing` lease is **orphaned** when",
|
|
19931
20692
|
"**both** hold:",
|
|
19932
20693
|
"",
|
|
19933
20694
|
"- The PR carries `review:fixing` but **not**",
|
|
@@ -19939,11 +20700,90 @@ function buildPrReviewBundle(policy = resolvePrReviewPolicy()) {
|
|
|
19939
20700
|
"",
|
|
19940
20701
|
"Together these mean a delegation was kicked off, the marker was",
|
|
19941
20702
|
"consumed-or-dropped, but no worker result ever landed \u2014 the lease",
|
|
19942
|
-
"is orphaned. The maintenance sweep
|
|
19943
|
-
"`
|
|
19944
|
-
"
|
|
19945
|
-
"
|
|
19946
|
-
"
|
|
20703
|
+
"is orphaned. The maintenance sweep **re-applies**",
|
|
20704
|
+
"`review:needs-worker` (re-arming the durable work marker so the",
|
|
20705
|
+
"Phase B1 feedback drain retries the delegation) and posts an",
|
|
20706
|
+
"audit-trail note comment. The `review:fixing` lease itself is left",
|
|
20707
|
+
"untouched, so the drain stays idempotent. This is a deliberate",
|
|
20708
|
+
"re-arm for autonomy \u2014 never a silent force-release: the note",
|
|
20709
|
+
"comment is the audit trail proving the re-arm was the sweep's",
|
|
20710
|
+
"doing.",
|
|
20711
|
+
"",
|
|
20712
|
+
"**Consumed-but-uncleared wedge.** The existing orphaned-lease",
|
|
20713
|
+
"precondition (`review:fixing` *without* `review:needs-worker`)",
|
|
20714
|
+
"structurally cannot see a worker that pushed its fix and then",
|
|
20715
|
+
"skipped the hand-off \u2014 the marker is still set. The sweep detects",
|
|
20716
|
+
"this wedge when a PR carries **both** `review:needs-worker` and",
|
|
20717
|
+
"`review:fixing`, its branch HEAD commit is **newer** than the",
|
|
20718
|
+
"fix-list comment, and there is **no** worker-report. It",
|
|
20719
|
+
"auto-reconciles by **removing** `review:needs-worker` (the",
|
|
20720
|
+
"hand-off the worker skipped) and posting an audit-trail reconcile",
|
|
20721
|
+
"note comment, flipping the PR into the lease-without-marker",
|
|
20722
|
+
"confirm-trigger state so the reviewer confirm pass takes over and",
|
|
20723
|
+
"merges. As with the orphaned-lease path, the `review:fixing` lease",
|
|
20724
|
+
"is left for that confirm pass to release.",
|
|
20725
|
+
"",
|
|
20726
|
+
"### Review-Label Invariants (Phase 2.8 reconciliation)",
|
|
20727
|
+
"",
|
|
20728
|
+
"A PR must never carry **mutually-exclusive review-workflow",
|
|
20729
|
+
"labels** after a reviewer pass \u2014 the PR equivalent of the",
|
|
20730
|
+
'"exactly one `status:*`" discipline issues already follow.',
|
|
20731
|
+
"Successive passes layering labels with no reconciler can drive a",
|
|
20732
|
+
"PR into an impossible state (a real PR once held",
|
|
20733
|
+
"`review:awaiting-human` + `status:needs-attention` +",
|
|
20734
|
+
"`review:fixing` + `review:needs-worker` at the same time). The",
|
|
20735
|
+
"reviewer's **Phase 2.8 \u2014 Label Reconciliation** step enforces",
|
|
20736
|
+
"the invariants below early in every pass, after Phase 2.75",
|
|
20737
|
+
"decides the mode and after the confirm-trigger lease detection,",
|
|
20738
|
+
"but before any phase branches on review state. Every correction",
|
|
20739
|
+
"is logged on a `**Label reconciliation:**` line in the sticky",
|
|
20740
|
+
"`## Reviewer notes` comment \u2014 labels are never mutated silently.",
|
|
20741
|
+
"",
|
|
20742
|
+
"**The invariants:**",
|
|
20743
|
+
"",
|
|
20744
|
+
"1. **`review:awaiting-human` is mutually exclusive with the",
|
|
20745
|
+
" fix-delegation labels (`review:needs-worker`,",
|
|
20746
|
+
" `review:fixing`).** A PR is **either** in the fix-delegation",
|
|
20747
|
+
" loop **or** handed to a human \u2014 never both. Any of",
|
|
20748
|
+
" `review:awaiting-human` + `review:needs-worker`,",
|
|
20749
|
+
" `review:awaiting-human` + `review:fixing`, or all three is a",
|
|
20750
|
+
" violation.",
|
|
20751
|
+
"2. **`review:fixing` WITHOUT `review:needs-worker` is the",
|
|
20752
|
+
" confirm-pending state, not a violation.** The worker finished",
|
|
20753
|
+
" and cleared its marker; a confirm pass owns the PR and will",
|
|
20754
|
+
" release the lease. The reconciler must not strip it.",
|
|
20755
|
+
"3. **`review:fixing` WITH `review:needs-worker` is a valid",
|
|
20756
|
+
" in-flight delegation, not a violation.** The work is durably",
|
|
20757
|
+
" queued for a top-level `issue-worker` pass.",
|
|
20758
|
+
"4. **`status:needs-attention` is additive but must not coexist",
|
|
20759
|
+
" with a live, progressing in-flight delegation.** When",
|
|
20760
|
+
" `review:fixing` + `review:needs-worker` are present, the",
|
|
20761
|
+
" fix-list is newer than the flag, and there is no failed-fix",
|
|
20762
|
+
" pushback, the flag contradicts the live progress signal and is",
|
|
20763
|
+
" removed. A flag coexisting with a *stalled* / *failed*",
|
|
20764
|
+
" delegation, an unresolved `thinking_face` pushback, or a",
|
|
20765
|
+
" `human-required` hand-off is legitimate and stays.",
|
|
20766
|
+
"",
|
|
20767
|
+
"(`review:human-required` and `review:auto-ok` are **policy",
|
|
20768
|
+
"inputs** read in Phase 2.75, not workflow-state labels \u2014 the",
|
|
20769
|
+
"reconciler never touches them.)",
|
|
20770
|
+
"",
|
|
20771
|
+
"**Canonical resolution.** The losing label is chosen by the",
|
|
20772
|
+
"Phase 2.75 mode plus the current loop position so the surviving",
|
|
20773
|
+
"set matches the action the pass will take:",
|
|
20774
|
+
"",
|
|
20775
|
+
"| Violation combo | Loop position / mode | Resolution (winner) |",
|
|
20776
|
+
"|-----------------|----------------------|---------------------|",
|
|
20777
|
+
"| `review:awaiting-human` + fix-delegation label(s) | delegation in-flight or confirm-pending, mode `auto-merge` | **remove `review:awaiting-human`** \u2014 the delegation loop owns the PR |",
|
|
20778
|
+
"| `review:awaiting-human` + fix-delegation label(s) | pass decided `human-required` (rules 2\u20135), no delegation actually in flight | **remove `review:needs-worker` + `review:fixing`** \u2014 the human hand-off wins; clear stale delegation labels |",
|
|
20779
|
+
"| `status:needs-attention` + live progressing delegation | mode `auto-merge`, `review:fixing` + `review:needs-worker` present | **remove `status:needs-attention`** \u2014 contradicts the live progress signal |",
|
|
20780
|
+
"",
|
|
20781
|
+
"Resolution is **conservative about human intent**: a genuine",
|
|
20782
|
+
"`human-required` pass clears the fix-delegation labels and keeps",
|
|
20783
|
+
"the human-facing label; an `auto-merge` pass with a live",
|
|
20784
|
+
"delegation keeps the delegation labels and clears the stray",
|
|
20785
|
+
"`review:awaiting-human`. The reconciler only ever **removes** a",
|
|
20786
|
+
"contradicting label \u2014 never adds one.",
|
|
19947
20787
|
"",
|
|
19948
20788
|
"### Sticky `## Reviewer notes` Comment",
|
|
19949
20789
|
"",
|
|
@@ -19967,6 +20807,9 @@ function buildPrReviewBundle(policy = resolvePrReviewPolicy()) {
|
|
|
19967
20807
|
" reviewer reaction (`eyes`, open `thinking_face`).",
|
|
19968
20808
|
"- **Pushbacks** \u2014 every unresolved `thinking_face` the reviewer",
|
|
19969
20809
|
" has left, with the reason captured in its pushback reply.",
|
|
20810
|
+
"- **Label reconciliation** \u2014 the Phase 2.8 outcome: `consistent`",
|
|
20811
|
+
" or the corrections applied this pass (violation combo, labels",
|
|
20812
|
+
" removed, resulting self-consistent set), recorded for audit.",
|
|
19970
20813
|
"- **Last pass** \u2014 the ISO 8601 timestamp of the most recent run.",
|
|
19971
20814
|
"",
|
|
19972
20815
|
"The sticky is updated on every pass \u2014 including passes that ended",
|
|
@@ -19990,7 +20833,7 @@ function buildPrReviewBundle(policy = resolvePrReviewPolicy()) {
|
|
|
19990
20833
|
"| `review:human-required` | Force human review regardless of what the policy would otherwise decide. The reviewer never enables auto-merge on a PR carrying this label. |",
|
|
19991
20834
|
"| `review:auto-ok` | Force auto-merge regardless of what the policy would otherwise decide. **Also resolves outstanding `thinking_face` pushbacks** as an explicit maintainer override; the reviewer logs the override in the sticky summary. |",
|
|
19992
20835
|
"| `review:awaiting-human` | Set by the reviewer when it completes its work on a `human-required` PR and is handing off the final merge decision. Cleared by a human (or by `review:auto-ok` flipping the PR back to `auto-merge` mode). |",
|
|
19993
|
-
"| `review:fixing` | **Cross-session** delegation lease. Acquired by the reviewer pass that posts a fix-list; held across the worker's run; released only by a later reviewer **confirm** pass (PR carries `review:fixing` but not `review:needs-worker`). A lease held without `review:needs-worker` past the stale threshold with no worker report is orphaned and is
|
|
20836
|
+
"| `review:fixing` | **Cross-session** delegation lease. Acquired by the reviewer pass that posts a fix-list; held across the worker's run; released only by a later reviewer **confirm** pass (PR carries `review:fixing` but not `review:needs-worker`). A lease held without `review:needs-worker` past the stale threshold with no worker report is orphaned and is auto-reconciled by the maintenance sweep \u2014 it re-applies `review:needs-worker` (re-arm) so the feedback drain retries, leaving the lease for the next confirm pass and posting an audit-trail note. |",
|
|
19994
20837
|
"| `review:needs-worker` | **Durable hand-off marker.** Applied by the reviewer alongside the fix-list so a top-level `issue-worker` session discovers the PR and pulls the work (the reviewer cannot spawn the worker in session \u2014 it may run at depth-1). Cleared by the worker when it finishes applying the fix-list, which is what triggers the reviewer's confirm pass. |",
|
|
19995
20838
|
"",
|
|
19996
20839
|
"### Reviewing Human-Authored PRs: the `--allow-human-author` Flag",
|
|
@@ -29812,7 +30655,7 @@ var VERSION = {
|
|
|
29812
30655
|
/**
|
|
29813
30656
|
* Version of PNPM to use in workflows at github actions.
|
|
29814
30657
|
*/
|
|
29815
|
-
PNPM_VERSION: "11.
|
|
30658
|
+
PNPM_VERSION: "11.7.0",
|
|
29816
30659
|
/**
|
|
29817
30660
|
* Version of Projen to use.
|
|
29818
30661
|
*/
|