@codedrifters/configulator 0.0.356 → 0.0.358
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 +2 -2
- package/lib/index.d.ts +2 -2
- package/lib/index.js +978 -135
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +978 -135
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -15058,6 +15058,7 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
|
|
|
15058
15058
|
"# .claude/procedures/check-blocked.sh eligible",
|
|
15059
15059
|
"# .claude/procedures/check-blocked.sh stale",
|
|
15060
15060
|
"# .claude/procedures/check-blocked.sh orphaned",
|
|
15061
|
+
"# .claude/procedures/check-blocked.sh lease-reconcile",
|
|
15061
15062
|
"# .claude/procedures/check-blocked.sh maintenance",
|
|
15062
15063
|
"# .claude/procedures/check-blocked.sh prs",
|
|
15063
15064
|
"# .claude/procedures/check-blocked.sh scope <issue-number>",
|
|
@@ -15386,21 +15387,181 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
|
|
|
15386
15387
|
" fi",
|
|
15387
15388
|
"}",
|
|
15388
15389
|
"",
|
|
15390
|
+
"cmd_lease_reconcile() {",
|
|
15391
|
+
" # PR-lease auto-reconcile for the feedback-drain loop. Two stuck",
|
|
15392
|
+
" # states wedge a `review:fixing` PR despite the Phase B1 drain and",
|
|
15393
|
+
" # the atomic worker hand-off; this sweep clears both WITHOUT a human:",
|
|
15394
|
+
" #",
|
|
15395
|
+
" # 1. Orphaned lease \u2014 PR carries `review:fixing` but NOT",
|
|
15396
|
+
" # `review:needs-worker`, the reviewer's fix-list comment is older",
|
|
15397
|
+
" # than the stale in-progress threshold, and NO worker-report",
|
|
15398
|
+
" # comment newer than the fix-list exists. A delegation was kicked",
|
|
15399
|
+
" # off but no worker result ever landed.",
|
|
15400
|
+
" # 2. Consumed-but-uncleared wedge \u2014 PR still carries BOTH",
|
|
15401
|
+
" # `review:needs-worker` AND `review:fixing`, but the branch HEAD",
|
|
15402
|
+
" # commit is NEWER than the fix-list comment and there is NO",
|
|
15403
|
+
" # worker-report. The worker did the work and pushed, then skipped",
|
|
15404
|
+
" # the hand-off, so the marker that the lease-without-marker",
|
|
15405
|
+
" # confirm trigger keys on was never cleared.",
|
|
15406
|
+
" #",
|
|
15407
|
+
" # AUDIT TRAIL / SAFETY: neither state is silently force-released.",
|
|
15408
|
+
" # - Orphaned lease \u2192 RE-APPLY `review:needs-worker` (not a",
|
|
15409
|
+
" # `status:needs-attention` flag) so the Phase B1 consume loop",
|
|
15410
|
+
" # retries the delegation autonomously, AND post a synthetic note",
|
|
15411
|
+
" # comment recording the re-arm. Re-arming (rather than flagging",
|
|
15412
|
+
" # for a human) is the autonomy-preserving choice the issue's",
|
|
15413
|
+
" # never-silently-force-released AC calls for: the lease itself is",
|
|
15414
|
+
" # left untouched (so the loop stays idempotent), only the durable",
|
|
15415
|
+
" # work marker is restored, and the note comment is the audit",
|
|
15416
|
+
" # trail proving the re-arm was deliberate.",
|
|
15417
|
+
" # - Consumed-but-uncleared \u2192 REMOVE `review:needs-worker` (the",
|
|
15418
|
+
" # hand-off the worker skipped) and post a synthetic reconcile note",
|
|
15419
|
+
" # comment, flipping the PR into the lease-without-marker state the",
|
|
15420
|
+
" # reviewer's confirm pass keys on so it can merge. The",
|
|
15421
|
+
" # `review:fixing` lease is left for that confirm pass to release,",
|
|
15422
|
+
" # mirroring complete-feedback-handoff.sh.",
|
|
15423
|
+
" #",
|
|
15424
|
+
" # Signals (all read via gh/jq):",
|
|
15425
|
+
" # - fix-list comment: the reviewer's most recent PR comment whose",
|
|
15426
|
+
" # body contains the stable heading `## Reviewer: fix list for",
|
|
15427
|
+
" # @issue-worker`. Its createdAt is the lease's reference time.",
|
|
15428
|
+
" # - worker-report comment: the most recent PR comment whose body",
|
|
15429
|
+
" # contains the stable HTML marker",
|
|
15430
|
+
" # `<!-- issue-worker feedback hand-off \u2014 review:needs-worker",
|
|
15431
|
+
" # cleared -->` posted by complete-feedback-handoff.sh. Presence +",
|
|
15432
|
+
" # createdAt newer than the fix-list means a result landed.",
|
|
15433
|
+
" # - branch HEAD: the PR head commit committedDate, compared against",
|
|
15434
|
+
" # the fix-list createdAt to detect a push that advanced past the",
|
|
15435
|
+
" # delegation without a hand-off.",
|
|
15436
|
+
"",
|
|
15437
|
+
" local orphaned_count=0",
|
|
15438
|
+
" local consumed_uncleared_count=0",
|
|
15439
|
+
"",
|
|
15440
|
+
" # Enumerate every open PR carrying the `review:fixing` lease \u2014 both",
|
|
15441
|
+
" # stuck states require it. One API call; the per-PR comment/commit",
|
|
15442
|
+
" # reads happen only for this (typically tiny) candidate set.",
|
|
15443
|
+
" local fixing_prs",
|
|
15444
|
+
' fixing_prs=$(gh pr list --state open --label "review:fixing" \\',
|
|
15445
|
+
' --json number,labels,headRefOid --limit 50 2>/dev/null || echo "[]")',
|
|
15446
|
+
"",
|
|
15447
|
+
" local fixing_count",
|
|
15448
|
+
` fixing_count=$(echo "$fixing_prs" | jq 'length' 2>/dev/null || echo 0)`,
|
|
15449
|
+
' if [[ "${fixing_count:-0}" -eq 0 ]]; then',
|
|
15450
|
+
' echo "LEASE_RECONCILE orphaned=0 consumed_uncleared=0"',
|
|
15451
|
+
" return 0",
|
|
15452
|
+
" fi",
|
|
15453
|
+
"",
|
|
15454
|
+
" # Stale threshold timestamp (UTC), reusing the same",
|
|
15455
|
+
" # STALE_IN_PROGRESS_HOURS=72 constant the stale-issue scan applies.",
|
|
15456
|
+
" local lease_threshold",
|
|
15457
|
+
" lease_threshold=$(date -u -v-${STALE_IN_PROGRESS_HOURS}H +%Y-%m-%dT%H:%M:%S 2>/dev/null \\",
|
|
15458
|
+
' || date -u -d "${STALE_IN_PROGRESS_HOURS} hours ago" +%Y-%m-%dT%H:%M:%S 2>/dev/null)',
|
|
15459
|
+
"",
|
|
15460
|
+
" local pr_rows",
|
|
15461
|
+
` pr_rows=$(echo "$fixing_prs" | jq -r '`,
|
|
15462
|
+
" .[] |",
|
|
15463
|
+
' (.labels | map(.name) | index("review:needs-worker") != null) as $has_marker |',
|
|
15464
|
+
' "\\(.number)\\t\\($has_marker)\\t\\(.headRefOid)"',
|
|
15465
|
+
" ' 2>/dev/null)",
|
|
15466
|
+
"",
|
|
15467
|
+
" while IFS=$'\\t' read -r pr_num has_marker head_oid; do",
|
|
15468
|
+
' [[ -z "$pr_num" ]] && continue',
|
|
15469
|
+
"",
|
|
15470
|
+
" # Pull the PR comments once; derive both the fix-list reference time",
|
|
15471
|
+
" # and the newest worker-report time from the same payload.",
|
|
15472
|
+
" local comments",
|
|
15473
|
+
' comments=$(gh pr view "$pr_num" --json comments \\',
|
|
15474
|
+
` --jq '.comments' 2>/dev/null || echo "[]")`,
|
|
15475
|
+
"",
|
|
15476
|
+
" # Newest fix-list comment createdAt (empty if none found).",
|
|
15477
|
+
" local fixlist_at",
|
|
15478
|
+
` fixlist_at=$(echo "$comments" | jq -r '`,
|
|
15479
|
+
' [.[] | select(.body | contains("## Reviewer: fix list for @issue-worker"))]',
|
|
15480
|
+
` | sort_by(.createdAt) | last | .createdAt // ""' 2>/dev/null)`,
|
|
15481
|
+
"",
|
|
15482
|
+
" # Newest worker-report createdAt (empty if none found). Keyed off the",
|
|
15483
|
+
" # stable HTML marker complete-feedback-handoff.sh embeds.",
|
|
15484
|
+
" local report_at",
|
|
15485
|
+
` report_at=$(echo "$comments" | jq -r '`,
|
|
15486
|
+
' [.[] | select(.body | contains("issue-worker feedback hand-off \u2014 review:needs-worker cleared"))]',
|
|
15487
|
+
` | sort_by(.createdAt) | last | .createdAt // ""' 2>/dev/null)`,
|
|
15488
|
+
"",
|
|
15489
|
+
" # No fix-list comment at all \u2014 we cannot reason about this lease",
|
|
15490
|
+
" # (e.g. a human applied `review:fixing` by hand). Leave it alone.",
|
|
15491
|
+
' if [[ -z "$fixlist_at" ]]; then',
|
|
15492
|
+
" continue",
|
|
15493
|
+
" fi",
|
|
15494
|
+
"",
|
|
15495
|
+
" # A worker-report newer than the fix-list means a result landed; the",
|
|
15496
|
+
" # confirm pass owns it. Skip for BOTH states.",
|
|
15497
|
+
' if [[ -n "$report_at" && "$report_at" > "$fixlist_at" ]]; then',
|
|
15498
|
+
" continue",
|
|
15499
|
+
" fi",
|
|
15500
|
+
"",
|
|
15501
|
+
' if [[ "$has_marker" == "true" ]]; then',
|
|
15502
|
+
" # \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",
|
|
15503
|
+
" # Marker still set + no worker-report. Reconcile only when the",
|
|
15504
|
+
" # branch advanced past the fix-list (the worker pushed but skipped",
|
|
15505
|
+
" # the hand-off); otherwise this is a normal in-flight delegation.",
|
|
15506
|
+
" local head_at",
|
|
15507
|
+
' head_at=$(gh api "repos/{owner}/{repo}/commits/${head_oid}" \\',
|
|
15508
|
+
` --jq '.commit.committer.date // ""' 2>/dev/null || echo "")`,
|
|
15509
|
+
' if [[ -n "$head_at" && "$head_at" > "$fixlist_at" ]]; then',
|
|
15510
|
+
' if gh pr edit "$pr_num" --remove-label "review:needs-worker" >/dev/null 2>&1; then',
|
|
15511
|
+
' gh pr comment "$pr_num" \\',
|
|
15512
|
+
' --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',
|
|
15513
|
+
' echo "LEASE_CONSUMED_UNCLEARED PR #${pr_num} \u2014 cleared review:needs-worker (branch advanced past fix-list, no worker report)"',
|
|
15514
|
+
" consumed_uncleared_count=$((consumed_uncleared_count + 1))",
|
|
15515
|
+
" else",
|
|
15516
|
+
' echo "LEASE_RECONCILE_FAILED PR #${pr_num} \u2014 could not remove review:needs-worker"',
|
|
15517
|
+
" fi",
|
|
15518
|
+
" fi",
|
|
15519
|
+
" else",
|
|
15520
|
+
" # \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",
|
|
15521
|
+
" # `review:fixing` without `review:needs-worker`, no worker-report",
|
|
15522
|
+
" # newer than the fix-list. Reclaim only when the fix-list comment",
|
|
15523
|
+
" # is older than the stale threshold \u2014 a recently delegated PR may",
|
|
15524
|
+
" # still be mid-consume.",
|
|
15525
|
+
' local fixlist_trimmed="${fixlist_at%%+*}"',
|
|
15526
|
+
' fixlist_trimmed="${fixlist_trimmed%%Z*}"',
|
|
15527
|
+
' if [[ "$fixlist_trimmed" < "$lease_threshold" ]]; then',
|
|
15528
|
+
' if gh pr edit "$pr_num" --add-label "review:needs-worker" >/dev/null 2>&1; then',
|
|
15529
|
+
' gh pr comment "$pr_num" \\',
|
|
15530
|
+
' --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',
|
|
15531
|
+
' echo "LEASE_ORPHANED PR #${pr_num} \u2014 re-applied review:needs-worker (fix-list stale, no worker report)"',
|
|
15532
|
+
" orphaned_count=$((orphaned_count + 1))",
|
|
15533
|
+
" else",
|
|
15534
|
+
' echo "LEASE_RECONCILE_FAILED PR #${pr_num} \u2014 could not re-apply review:needs-worker"',
|
|
15535
|
+
" fi",
|
|
15536
|
+
" fi",
|
|
15537
|
+
" fi",
|
|
15538
|
+
' done <<< "$pr_rows"',
|
|
15539
|
+
"",
|
|
15540
|
+
" # Single summary line consumed by the orchestrator, matching the",
|
|
15541
|
+
" # MAINTENANCE_DONE convention.",
|
|
15542
|
+
' echo "LEASE_RECONCILE orphaned=${orphaned_count} consumed_uncleared=${consumed_uncleared_count}"',
|
|
15543
|
+
"}",
|
|
15544
|
+
"",
|
|
15389
15545
|
"cmd_maintenance() {",
|
|
15390
15546
|
" # Phase D maintenance sweep: flag stale issues with",
|
|
15391
15547
|
" # `status:needs-attention`, count orphan branches/PRs (no",
|
|
15392
|
-
" # auto-deletion),
|
|
15393
|
-
" #
|
|
15394
|
-
" #
|
|
15395
|
-
" #
|
|
15396
|
-
" #
|
|
15397
|
-
" #
|
|
15548
|
+
" # auto-deletion), auto-reconcile stuck PR leases (re-arm orphaned",
|
|
15549
|
+
" # leases / clear consumed-but-uncleared markers, see",
|
|
15550
|
+
" # cmd_lease_reconcile), and emit a MAINTENANCE_DONE summary line",
|
|
15551
|
+
" # plus a LEASE_RECONCILE summary line so the orchestrator never",
|
|
15552
|
+
" # iterates raw stale/orphan/lease output. Mirrors the discipline of",
|
|
15553
|
+
" # cmd_unblock \u2014 per-issue / per-PR informational lines (FLAGGED #N,",
|
|
15554
|
+
" # ORPHAN_BRANCH \u2026, LEASE_ORPHANED PR #N \u2026) survive for log",
|
|
15555
|
+
" # visibility but are not load-bearing for the orchestrator.",
|
|
15398
15556
|
" #",
|
|
15399
15557
|
" # SAFETY: this subcommand NEVER auto-resets stale issues to",
|
|
15400
15558
|
" # `status:ready`. It only adds `status:needs-attention`; the",
|
|
15401
15559
|
" # existing `status:in-progress` or `status:blocked` label",
|
|
15402
15560
|
" # stays in place so partial implementation work on a branch",
|
|
15403
|
-
" # remains visible to humans.",
|
|
15561
|
+
" # remains visible to humans. The PR-lease reconcile likewise never",
|
|
15562
|
+
" # silently force-releases a `review:fixing` lease \u2014 it re-arms the",
|
|
15563
|
+
" # work marker (orphaned) or clears the consumed marker (wedge) and",
|
|
15564
|
+
" # always posts an audit-trail note comment.",
|
|
15404
15565
|
"",
|
|
15405
15566
|
" local flagged_stale_count=0",
|
|
15406
15567
|
" local flagged_blocked_count=0",
|
|
@@ -15471,14 +15632,40 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
|
|
|
15471
15632
|
" esac",
|
|
15472
15633
|
' done <<< "$orphan_output"',
|
|
15473
15634
|
"",
|
|
15635
|
+
" # \u2500\u2500 PR-lease auto-reconcile (MUTATING \u2014 see cmd_lease_reconcile) \u2500\u2500",
|
|
15636
|
+
" # Run the lease sweep and surface its informational lines for log",
|
|
15637
|
+
" # visibility. cmd_lease_reconcile applies the label edits itself",
|
|
15638
|
+
" # (re-arm or clear `review:needs-worker`) and posts the audit-trail",
|
|
15639
|
+
" # note comment \u2014 mirroring how this maintenance sweep already",
|
|
15640
|
+
" # mutates issue labels directly. Its terminal LEASE_RECONCILE line is",
|
|
15641
|
+
" # captured and re-emitted alongside MAINTENANCE_DONE so the",
|
|
15642
|
+
" # orchestrator reads both summaries from one maintenance invocation.",
|
|
15643
|
+
" local lease_output",
|
|
15644
|
+
" lease_output=$(cmd_lease_reconcile)",
|
|
15645
|
+
' local lease_summary="LEASE_RECONCILE orphaned=0 consumed_uncleared=0"',
|
|
15646
|
+
"",
|
|
15647
|
+
" while IFS= read -r line; do",
|
|
15648
|
+
' [[ -z "$line" ]] && continue',
|
|
15649
|
+
' case "$line" in',
|
|
15650
|
+
" 'LEASE_RECONCILE '*)",
|
|
15651
|
+
' lease_summary="$line"',
|
|
15652
|
+
" ;;",
|
|
15653
|
+
" *)",
|
|
15654
|
+
' echo "$line"',
|
|
15655
|
+
" ;;",
|
|
15656
|
+
" esac",
|
|
15657
|
+
' done <<< "$lease_output"',
|
|
15658
|
+
"",
|
|
15474
15659
|
" # \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",
|
|
15475
15660
|
" local needs_attention_total",
|
|
15476
15661
|
' needs_attention_total=$(gh issue list --label "status:needs-attention" --state open \\',
|
|
15477
15662
|
" --json number --limit 100 2>/dev/null | jq 'length' 2>/dev/null || echo 0)",
|
|
15478
15663
|
" needs_attention_total=${needs_attention_total:-0}",
|
|
15479
15664
|
"",
|
|
15480
|
-
" #
|
|
15665
|
+
" # Two summary lines consumed by the orchestrator: the issue/orphan",
|
|
15666
|
+
" # MAINTENANCE_DONE line and the PR-lease LEASE_RECONCILE line.",
|
|
15481
15667
|
' 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}"',
|
|
15668
|
+
' echo "$lease_summary"',
|
|
15482
15669
|
"}",
|
|
15483
15670
|
"",
|
|
15484
15671
|
"cmd_prs() {",
|
|
@@ -15626,11 +15813,12 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
|
|
|
15626
15813
|
' eligible) shift; cmd_eligible "$@" ;;',
|
|
15627
15814
|
' stale) shift; cmd_stale "$@" ;;',
|
|
15628
15815
|
' orphaned) shift; cmd_orphaned "$@" ;;',
|
|
15816
|
+
' lease-reconcile) shift; cmd_lease_reconcile "$@" ;;',
|
|
15629
15817
|
' maintenance) shift; cmd_maintenance "$@" ;;',
|
|
15630
15818
|
' prs) shift; cmd_prs "$@" ;;',
|
|
15631
15819
|
' scope) shift; cmd_scope "$@" ;;',
|
|
15632
15820
|
" help|*)",
|
|
15633
|
-
' echo "Usage: check-blocked.sh <unblock|eligible|stale|orphaned|maintenance|prs|scope>"',
|
|
15821
|
+
' echo "Usage: check-blocked.sh <unblock|eligible|stale|orphaned|lease-reconcile|maintenance|prs|scope>"',
|
|
15634
15822
|
" exit 1",
|
|
15635
15823
|
" ;;",
|
|
15636
15824
|
"esac"
|
|
@@ -15639,7 +15827,7 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
|
|
|
15639
15827
|
function buildCheckBlockedProcedure(tiers, scopeGate = resolveScopeGate(), runRatio = resolveRunRatio()) {
|
|
15640
15828
|
return {
|
|
15641
15829
|
name: "check-blocked.sh",
|
|
15642
|
-
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
|
|
15830
|
+
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.",
|
|
15643
15831
|
content: buildCheckBlockedScript(tiers, scopeGate, runRatio)
|
|
15644
15832
|
};
|
|
15645
15833
|
}
|
|
@@ -15661,56 +15849,289 @@ var unblockDependentsProcedure = buildUnblockDependentsProcedure(
|
|
|
15661
15849
|
function buildPrSweepScript() {
|
|
15662
15850
|
return [
|
|
15663
15851
|
"#!/usr/bin/env bash",
|
|
15664
|
-
"# pr-sweep.sh \u2014 Token-efficient PR
|
|
15665
|
-
"#
|
|
15666
|
-
"#
|
|
15667
|
-
"#
|
|
15852
|
+
"# pr-sweep.sh \u2014 Token-efficient PR enumeration for the orchestrator's",
|
|
15853
|
+
"# PR-handling phases. Two modes:",
|
|
15854
|
+
"#",
|
|
15855
|
+
"# review (default) \u2014 Phase B PR review sweep. Emits one",
|
|
15856
|
+
"# PR_ELIGIBLE / PR_SKIP line per open PR; the",
|
|
15857
|
+
"# orchestrator dispatches `pr-reviewer` per eligible PR.",
|
|
15858
|
+
"# needs-worker \u2014 Phase B1 feedback-drain. Emits one DRAIN line per",
|
|
15859
|
+
"# open PR carrying the `review:needs-worker` marker that",
|
|
15860
|
+
"# is NOT already in-flight (no `review:fixing` lease),",
|
|
15861
|
+
"# ordered highest-priority-first so the orchestrator",
|
|
15862
|
+
"# dispatches `issue-worker` per PR to consume the",
|
|
15863
|
+
"# reviewer's fix-list.",
|
|
15668
15864
|
"#",
|
|
15669
|
-
"#
|
|
15865
|
+
"# Review-mode skip rules:",
|
|
15670
15866
|
"# - isDraft = true \u2192 reason=draft",
|
|
15671
15867
|
"# - review:human-required label \u2192 reason=human-required",
|
|
15672
15868
|
"# - review:awaiting-human label \u2192 reason=awaiting-human",
|
|
15673
15869
|
"#",
|
|
15870
|
+
"# Needs-worker-mode skip rules (PR carries review:needs-worker but is",
|
|
15871
|
+
"# not eligible to drain this cycle):",
|
|
15872
|
+
"# - review:fixing label present \u2192 reason=in-flight",
|
|
15873
|
+
"# (a delegation is already being consumed; the marker plus the",
|
|
15874
|
+
"# lease means another worker is mid-run \u2014 skip to stay idempotent)",
|
|
15875
|
+
"#",
|
|
15674
15876
|
"# Usage:",
|
|
15675
|
-
"# .claude/procedures/pr-sweep.sh",
|
|
15877
|
+
"# .claude/procedures/pr-sweep.sh [review|needs-worker]",
|
|
15676
15878
|
"",
|
|
15677
15879
|
"set -uo pipefail",
|
|
15678
15880
|
"",
|
|
15679
|
-
"
|
|
15680
|
-
' --limit 50 2>/dev/null || echo "[]")',
|
|
15881
|
+
"# \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",
|
|
15681
15882
|
"",
|
|
15682
|
-
|
|
15683
|
-
|
|
15684
|
-
|
|
15685
|
-
"
|
|
15686
|
-
"
|
|
15883
|
+
"# Resolve the linked issue's priority for a PR so the needs-worker",
|
|
15884
|
+
"# drain can order highest-priority-first. Echoes a single sort key",
|
|
15885
|
+
"# 0-5 (0 = critical \u2026 4 = trivial, 5 = no/unknown priority) so an",
|
|
15886
|
+
"# unprioritised PR always sorts last but is never dropped.",
|
|
15887
|
+
"priority_key_for_pr() {",
|
|
15888
|
+
' local pr_num="$1"',
|
|
15889
|
+
" local issue_num",
|
|
15890
|
+
' issue_num=$(gh pr view "$pr_num" --json body \\',
|
|
15891
|
+
` --jq '(.body | capture("(?:Closes|Fixes|Resolves) #(?<num>[0-9]+)") | .num) // ""' \\`,
|
|
15892
|
+
' 2>/dev/null || echo "")',
|
|
15893
|
+
' if [[ -z "$issue_num" ]]; then',
|
|
15894
|
+
' echo "5"',
|
|
15895
|
+
" return",
|
|
15896
|
+
" fi",
|
|
15897
|
+
" local labels",
|
|
15898
|
+
' labels=$(gh issue view "$issue_num" --json labels \\',
|
|
15899
|
+
` --jq '.labels[].name' 2>/dev/null || echo "")`,
|
|
15900
|
+
' case "$labels" in',
|
|
15901
|
+
' *priority:critical*) echo "0" ;;',
|
|
15902
|
+
' *priority:high*) echo "1" ;;',
|
|
15903
|
+
' *priority:medium*) echo "2" ;;',
|
|
15904
|
+
' *priority:low*) echo "3" ;;',
|
|
15905
|
+
' *priority:trivial*) echo "4" ;;',
|
|
15906
|
+
' *) echo "5" ;;',
|
|
15907
|
+
" esac",
|
|
15908
|
+
"}",
|
|
15687
15909
|
"",
|
|
15688
|
-
"#
|
|
15689
|
-
"
|
|
15690
|
-
|
|
15691
|
-
"
|
|
15692
|
-
"
|
|
15693
|
-
|
|
15694
|
-
"
|
|
15695
|
-
|
|
15696
|
-
|
|
15697
|
-
'
|
|
15698
|
-
'
|
|
15699
|
-
|
|
15700
|
-
"
|
|
15701
|
-
|
|
15702
|
-
"
|
|
15703
|
-
"
|
|
15910
|
+
"# \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",
|
|
15911
|
+
"",
|
|
15912
|
+
"cmd_review() {",
|
|
15913
|
+
" local prs",
|
|
15914
|
+
" prs=$(gh pr list --state open --json number,isDraft,labels \\",
|
|
15915
|
+
' --limit 50 2>/dev/null || echo "[]")',
|
|
15916
|
+
"",
|
|
15917
|
+
" local count",
|
|
15918
|
+
` count=$(echo "$prs" | jq 'length')`,
|
|
15919
|
+
' if [[ "$count" -eq 0 ]]; then',
|
|
15920
|
+
' echo "NO_OPEN_PRS"',
|
|
15921
|
+
" return 0",
|
|
15922
|
+
" fi",
|
|
15923
|
+
"",
|
|
15924
|
+
" # Emit one PR_ELIGIBLE / PR_SKIP line per open PR, sorted by PR",
|
|
15925
|
+
" # number ascending so the order is deterministic across runs.",
|
|
15926
|
+
` echo "$prs" | jq -r '`,
|
|
15927
|
+
" sort_by(.number) |",
|
|
15928
|
+
" .[] |",
|
|
15929
|
+
" (.labels | map(.name)) as $labels |",
|
|
15930
|
+
" if .isDraft then",
|
|
15931
|
+
' "PR_SKIP #\\(.number) reason=draft"',
|
|
15932
|
+
' elif ($labels | index("review:human-required")) then',
|
|
15933
|
+
' "PR_SKIP #\\(.number) reason=human-required"',
|
|
15934
|
+
' elif ($labels | index("review:awaiting-human")) then',
|
|
15935
|
+
' "PR_SKIP #\\(.number) reason=awaiting-human"',
|
|
15936
|
+
" else",
|
|
15937
|
+
' "PR_ELIGIBLE #\\(.number)"',
|
|
15938
|
+
" end",
|
|
15939
|
+
" '",
|
|
15940
|
+
"}",
|
|
15941
|
+
"",
|
|
15942
|
+
"cmd_needs_worker() {",
|
|
15943
|
+
" # Phase B1 feedback-drain: enumerate open PRs carrying the durable",
|
|
15944
|
+
" # `review:needs-worker` marker that are NOT already in-flight (no",
|
|
15945
|
+
" # `review:fixing` lease), ordered highest-priority-first so the",
|
|
15946
|
+
" # orchestrator dispatches `issue-worker` per PR to consume the",
|
|
15947
|
+
" # reviewer's fix-list. A PR holding both labels is a delegation",
|
|
15948
|
+
" # mid-flight \u2014 it is skipped (reason=in-flight) so the drain stays",
|
|
15949
|
+
" # idempotent and respects the cross-session lease semantics.",
|
|
15950
|
+
" local prs",
|
|
15951
|
+
" prs=$(gh pr list --state open --label 'review:needs-worker' \\",
|
|
15952
|
+
' --json number,labels --limit 50 2>/dev/null || echo "[]")',
|
|
15953
|
+
"",
|
|
15954
|
+
" local count",
|
|
15955
|
+
` count=$(echo "$prs" | jq 'length')`,
|
|
15956
|
+
' if [[ "$count" -eq 0 ]]; then',
|
|
15957
|
+
' echo "NO_NEEDS_WORKER_PRS"',
|
|
15958
|
+
" return 0",
|
|
15959
|
+
" fi",
|
|
15960
|
+
"",
|
|
15961
|
+
" # First pass: split into skip (in-flight) and drain-candidate sets.",
|
|
15962
|
+
" # The skip lines are emitted immediately for log visibility; the",
|
|
15963
|
+
" # candidates are resolved to a priority key and sorted before",
|
|
15964
|
+
" # emission so the orchestrator drains highest-priority first.",
|
|
15965
|
+
" local candidates",
|
|
15966
|
+
` candidates=$(echo "$prs" | jq -r '`,
|
|
15967
|
+
" sort_by(.number) |",
|
|
15968
|
+
" .[] |",
|
|
15969
|
+
" (.labels | map(.name)) as $labels |",
|
|
15970
|
+
' if ($labels | index("review:fixing")) then',
|
|
15971
|
+
' "SKIP\\t\\(.number)"',
|
|
15972
|
+
" else",
|
|
15973
|
+
' "DRAIN\\t\\(.number)"',
|
|
15974
|
+
" end",
|
|
15975
|
+
" ')",
|
|
15976
|
+
"",
|
|
15977
|
+
' local drain_rows=""',
|
|
15978
|
+
' local emitted_any=""',
|
|
15979
|
+
" while IFS=$'\\t' read -r kind pr_num; do",
|
|
15980
|
+
' [[ -z "$pr_num" ]] && continue',
|
|
15981
|
+
' if [[ "$kind" == "SKIP" ]]; then',
|
|
15982
|
+
' echo "PR_SKIP #${pr_num} reason=in-flight"',
|
|
15983
|
+
' emitted_any="1"',
|
|
15984
|
+
" continue",
|
|
15985
|
+
" fi",
|
|
15986
|
+
" # DRAIN candidate \u2014 resolve the linked issue's priority so the",
|
|
15987
|
+
" # drain order is highest-priority-first, tie-broken by PR number",
|
|
15988
|
+
" # ascending (FIFO, mirroring the queue scan's number-asc tie-break).",
|
|
15989
|
+
" local pkey",
|
|
15990
|
+
' pkey=$(priority_key_for_pr "$pr_num")',
|
|
15991
|
+
' drain_rows="${drain_rows}${pkey}\\t${pr_num}\\n"',
|
|
15992
|
+
' done <<< "$candidates"',
|
|
15993
|
+
"",
|
|
15994
|
+
' if [[ -n "$drain_rows" ]]; then',
|
|
15995
|
+
" # Sort by priority key asc \u2192 PR number asc, then emit one",
|
|
15996
|
+
" # PR_DRAIN line per PR in that order.",
|
|
15997
|
+
` printf '%b' "$drain_rows" \\`,
|
|
15998
|
+
" | sort -t$'\\t' -k1,1n -k2,2n \\",
|
|
15999
|
+
" | while IFS=$'\\t' read -r _pkey pr_num; do",
|
|
16000
|
+
' [[ -z "$pr_num" ]] && continue',
|
|
16001
|
+
' echo "PR_DRAIN #${pr_num}"',
|
|
16002
|
+
" done",
|
|
16003
|
+
' emitted_any="1"',
|
|
16004
|
+
" fi",
|
|
16005
|
+
"",
|
|
16006
|
+
' if [[ -z "$emitted_any" ]]; then',
|
|
16007
|
+
' echo "NO_NEEDS_WORKER_PRS"',
|
|
16008
|
+
" fi",
|
|
16009
|
+
"}",
|
|
16010
|
+
"",
|
|
16011
|
+
"# \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",
|
|
16012
|
+
"",
|
|
16013
|
+
'case "${1:-review}" in',
|
|
16014
|
+
' review) shift || true; cmd_review "$@" ;;',
|
|
16015
|
+
' needs-worker) shift || true; cmd_needs_worker "$@" ;;',
|
|
16016
|
+
" *)",
|
|
16017
|
+
' echo "Usage: pr-sweep.sh <review|needs-worker>" >&2',
|
|
16018
|
+
" exit 1",
|
|
16019
|
+
" ;;",
|
|
16020
|
+
"esac"
|
|
15704
16021
|
].join("\n");
|
|
15705
16022
|
}
|
|
15706
16023
|
function buildPrSweepProcedure() {
|
|
15707
16024
|
return {
|
|
15708
16025
|
name: "pr-sweep.sh",
|
|
15709
|
-
description: "Token-efficient PR
|
|
16026
|
+
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.",
|
|
15710
16027
|
content: buildPrSweepScript()
|
|
15711
16028
|
};
|
|
15712
16029
|
}
|
|
15713
16030
|
var prSweepProcedure = buildPrSweepProcedure();
|
|
16031
|
+
function buildCompleteFeedbackHandoffScript() {
|
|
16032
|
+
return [
|
|
16033
|
+
"#!/usr/bin/env bash",
|
|
16034
|
+
"# complete-feedback-handoff.sh \u2014 Atomic feedback-mode hand-off for the",
|
|
16035
|
+
"# issue-worker (Phase 6.5). Posts the structured worker-report comment",
|
|
16036
|
+
"# AND removes the `review:needs-worker` marker in ONE invocation,",
|
|
16037
|
+
"# exiting non-zero on any failure so a successful push can never land",
|
|
16038
|
+
"# without the hand-off completing.",
|
|
16039
|
+
"#",
|
|
16040
|
+
"# The marker is cleared even when some (or all) fix-list items failed \u2014",
|
|
16041
|
+
"# a partial result is reported per-item but must not wedge the PR. The",
|
|
16042
|
+
"# `review:fixing` lease is left in place for the reviewer's confirm pass.",
|
|
16043
|
+
"#",
|
|
16044
|
+
"# Usage:",
|
|
16045
|
+
"# complete-feedback-handoff.sh <pr-number> <commit-sha> <items-json>",
|
|
16046
|
+
"#",
|
|
16047
|
+
"# <items-json> \u2014 JSON array of per-item outcomes keyed by the",
|
|
16048
|
+
"# fix-list `comment_id`:",
|
|
16049
|
+
'# [{"comment_id":"IC_abc","outcome":"applied","detail":""},',
|
|
16050
|
+
'# {"comment_id":"IC_def","outcome":"failed","detail":"reason"}]',
|
|
16051
|
+
"# `outcome` is `applied` or `failed`.",
|
|
16052
|
+
"",
|
|
16053
|
+
"set -uo pipefail",
|
|
16054
|
+
"",
|
|
16055
|
+
'pr_number="${1:-}"',
|
|
16056
|
+
'commit_sha="${2:-}"',
|
|
16057
|
+
'items_json="${3:-}"',
|
|
16058
|
+
"",
|
|
16059
|
+
'if [[ -z "$pr_number" || -z "$commit_sha" || -z "$items_json" ]]; then',
|
|
16060
|
+
' echo "Usage: complete-feedback-handoff.sh <pr-number> <commit-sha> <items-json>" >&2',
|
|
16061
|
+
" exit 2",
|
|
16062
|
+
"fi",
|
|
16063
|
+
"",
|
|
16064
|
+
"# Validate the items JSON up front \u2014 a malformed payload must fail",
|
|
16065
|
+
"# loudly before we mutate any PR state.",
|
|
16066
|
+
`if ! echo "$items_json" | jq -e 'type == "array"' >/dev/null 2>&1; then`,
|
|
16067
|
+
' echo "complete-feedback-handoff: <items-json> is not a JSON array" >&2',
|
|
16068
|
+
" exit 2",
|
|
16069
|
+
"fi",
|
|
16070
|
+
"",
|
|
16071
|
+
"# \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",
|
|
16072
|
+
"# One markdown checklist line per item (\u2713 applied / \u2717 failed), keyed by",
|
|
16073
|
+
"# comment_id so the reviewer's confirm pass reacts on the right source",
|
|
16074
|
+
"# comment. Includes the pushed commit SHA and an overall outcome",
|
|
16075
|
+
"# (`complete` when every item applied, `partial` when any failed).",
|
|
16076
|
+
`applied_count=$(echo "$items_json" | jq '[.[] | select(.outcome == "applied")] | length')`,
|
|
16077
|
+
`failed_count=$(echo "$items_json" | jq '[.[] | select(.outcome == "failed")] | length')`,
|
|
16078
|
+
"",
|
|
16079
|
+
'overall="complete"',
|
|
16080
|
+
'if [[ "$failed_count" -gt 0 ]]; then',
|
|
16081
|
+
' overall="partial"',
|
|
16082
|
+
"fi",
|
|
16083
|
+
"",
|
|
16084
|
+
`item_lines=$(echo "$items_json" | jq -r '`,
|
|
16085
|
+
" .[] |",
|
|
16086
|
+
' if .outcome == "applied" then',
|
|
16087
|
+
' "- [x] `\\(.comment_id)` \u2014 applied"',
|
|
16088
|
+
" else",
|
|
16089
|
+
' "- [ ] `\\(.comment_id)` \u2014 **failed**" + (if (.detail // "") != "" then " (\\(.detail))" else "" end)',
|
|
16090
|
+
" end",
|
|
16091
|
+
"')",
|
|
16092
|
+
"",
|
|
16093
|
+
"report=$(cat <<EOF",
|
|
16094
|
+
"## Worker report",
|
|
16095
|
+
"",
|
|
16096
|
+
"Feedback-mode fix-list applied on commit \\`${commit_sha}\\`.",
|
|
16097
|
+
"",
|
|
16098
|
+
"**Outcome:** ${overall} (${applied_count} applied, ${failed_count} failed)",
|
|
16099
|
+
"",
|
|
16100
|
+
"${item_lines}",
|
|
16101
|
+
"",
|
|
16102
|
+
"<!-- issue-worker feedback hand-off \u2014 review:needs-worker cleared -->",
|
|
16103
|
+
"EOF",
|
|
16104
|
+
")",
|
|
16105
|
+
"",
|
|
16106
|
+
"# \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",
|
|
16107
|
+
"# The report is ALWAYS posted, even when every item failed \u2014 the",
|
|
16108
|
+
"# reviewer's confirm pass needs the record to react and fall through to",
|
|
16109
|
+
"# the human-required hand-off rather than silently wedging.",
|
|
16110
|
+
'if ! echo "$report" | gh pr comment "$pr_number" --body-file -; then',
|
|
16111
|
+
' echo "complete-feedback-handoff: failed to post worker-report comment on PR #${pr_number}" >&2',
|
|
16112
|
+
" exit 1",
|
|
16113
|
+
"fi",
|
|
16114
|
+
"",
|
|
16115
|
+
"# \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",
|
|
16116
|
+
"# Removing the marker (not the `review:fixing` lease) flips the PR into",
|
|
16117
|
+
"# the lease-without-marker state the reviewer's confirm pass keys on.",
|
|
16118
|
+
"# Cleared unconditionally on a partial result so the PR never wedges.",
|
|
16119
|
+
`if ! gh pr edit "$pr_number" --remove-label 'review:needs-worker'; then`,
|
|
16120
|
+
' echo "complete-feedback-handoff: failed to remove review:needs-worker from PR #${pr_number}" >&2',
|
|
16121
|
+
" exit 1",
|
|
16122
|
+
"fi",
|
|
16123
|
+
"",
|
|
16124
|
+
'echo "HANDOFF_DONE pr=#${pr_number} outcome=${overall} applied=${applied_count} failed=${failed_count}"'
|
|
16125
|
+
].join("\n");
|
|
16126
|
+
}
|
|
16127
|
+
function buildCompleteFeedbackHandoffProcedure() {
|
|
16128
|
+
return {
|
|
16129
|
+
name: "complete-feedback-handoff.sh",
|
|
16130
|
+
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.",
|
|
16131
|
+
content: buildCompleteFeedbackHandoffScript()
|
|
16132
|
+
};
|
|
16133
|
+
}
|
|
16134
|
+
var completeFeedbackHandoffProcedure = buildCompleteFeedbackHandoffProcedure();
|
|
15714
16135
|
var orchestratorSubAgent = {
|
|
15715
16136
|
name: "orchestrator",
|
|
15716
16137
|
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",
|
|
@@ -15723,9 +16144,11 @@ var orchestratorSubAgent = {
|
|
|
15723
16144
|
"You are the pipeline orchestrator for the **{{repository.owner}}/{{repository.name}}** repository.",
|
|
15724
16145
|
"Each invocation runs **one full end-to-end cycle**. The cycle pulls",
|
|
15725
16146
|
"the default branch, sweeps eligible open PRs through the `pr-reviewer`",
|
|
15726
|
-
"sub-agent,
|
|
15727
|
-
"
|
|
15728
|
-
"
|
|
16147
|
+
"sub-agent, **drains every open `review:needs-worker` PR through the",
|
|
16148
|
+
"`issue-worker`** to consume the reviewer's fix-lists, triages blocked",
|
|
16149
|
+
"issues, runs maintenance scans, picks the next ready issue, and",
|
|
16150
|
+
"**delegates implementation to the `issue-worker`** sub-agent in",
|
|
16151
|
+
"scheduled mode. The orchestrator itself never implements",
|
|
15729
16152
|
"code, creates branches, pushes commits, or merges PRs \u2014 it routes",
|
|
15730
16153
|
"work to other agents. The merge decision is still owned by the",
|
|
15731
16154
|
"`pr-reviewer` sub-agent; the orchestrator only chooses which PRs the",
|
|
@@ -15742,16 +16165,22 @@ var orchestratorSubAgent = {
|
|
|
15742
16165
|
" eligibility summary and dispatch the `pr-reviewer` sub-agent",
|
|
15743
16166
|
" in scheduled mode against each eligible open PR. Failures on",
|
|
15744
16167
|
" one PR never stop the sweep.",
|
|
15745
|
-
"3. **Phase
|
|
16168
|
+
"3. **Phase B1 \u2014 Feedback Drain.** Read the procedure-script's",
|
|
16169
|
+
" needs-worker enumeration and dispatch a top-level `issue-worker`",
|
|
16170
|
+
" per open `review:needs-worker` PR \u2014 highest-priority first \u2014 to",
|
|
16171
|
+
" consume the reviewer's fix-list. Drains **every** eligible",
|
|
16172
|
+
" marker PR in the cycle. Feedback PRs are preferred over fresh",
|
|
16173
|
+
" issues, so this phase runs before the queue scan.",
|
|
16174
|
+
"4. **Phase C \u2014 Triage / Unblock.** Flip dependents that have all",
|
|
15746
16175
|
" their dependencies closed back to `status:ready`.",
|
|
15747
|
-
"
|
|
16176
|
+
"5. **Phase D \u2014 Maintenance.** Stale-issue and orphaned-resource scan",
|
|
15748
16177
|
" plus a needs-attention summary.",
|
|
15749
|
-
"
|
|
16178
|
+
"6. **Phase E \u2014 Queue Scan.** Pick the highest-priority `PICK` line",
|
|
15750
16179
|
" and run the scope gate. If the result is `large`, flag and stop.",
|
|
15751
|
-
"
|
|
16180
|
+
"7. **Phase G \u2014 Delegate Implementation.** Hand the picked issue off",
|
|
15752
16181
|
" to the `issue-worker` sub-agent in scheduled mode. The worker",
|
|
15753
16182
|
" handles claim \u2192 branch \u2192 implement \u2192 commit \u2192 PR autonomously.",
|
|
15754
|
-
"
|
|
16183
|
+
"8. **Phase F \u2014 Cleanup.** Return to the default branch and log the",
|
|
15755
16184
|
" run summary.",
|
|
15756
16185
|
"",
|
|
15757
16186
|
"Phase letters are stable identifiers \u2014 letters skipped in the list",
|
|
@@ -15784,7 +16213,7 @@ var orchestratorSubAgent = {
|
|
|
15784
16213
|
"metadata, mirroring the discipline of Phase E's bucketed queue scan.",
|
|
15785
16214
|
"",
|
|
15786
16215
|
"```bash",
|
|
15787
|
-
".claude/procedures/pr-sweep.sh",
|
|
16216
|
+
".claude/procedures/pr-sweep.sh review",
|
|
15788
16217
|
"```",
|
|
15789
16218
|
"",
|
|
15790
16219
|
"Each line follows one of these shapes:",
|
|
@@ -15805,7 +16234,7 @@ var orchestratorSubAgent = {
|
|
|
15805
16234
|
" (the reviewer already handed off; a human is the next actor)",
|
|
15806
16235
|
"",
|
|
15807
16236
|
"If the script emits `NO_OPEN_PRS`, log the empty result and skip",
|
|
15808
|
-
"directly to Phase
|
|
16237
|
+
"directly to Phase B1.",
|
|
15809
16238
|
"",
|
|
15810
16239
|
"### Step 2 \u2014 dispatch the reviewer per eligible PR",
|
|
15811
16240
|
"",
|
|
@@ -15839,7 +16268,103 @@ var orchestratorSubAgent = {
|
|
|
15839
16268
|
"eligible.",
|
|
15840
16269
|
"",
|
|
15841
16270
|
"After every eligible PR has been processed (or zero eligible PRs",
|
|
15842
|
-
"were emitted), continue to Phase
|
|
16271
|
+
"were emitted), continue to Phase B1 regardless of outcomes.",
|
|
16272
|
+
"",
|
|
16273
|
+
"## Phase B1: Feedback Drain",
|
|
16274
|
+
"",
|
|
16275
|
+
"Phase B **produces** `review:needs-worker` markers (the reviewer's",
|
|
16276
|
+
"pull-based hand-off applies one whenever it delegates an in-scope",
|
|
16277
|
+
"fix-list); Phase B1 **consumes** them. The pr-reviewer cannot spawn",
|
|
16278
|
+
"the worker in session \u2014 it frequently runs at depth-1 \u2014 so it leaves",
|
|
16279
|
+
"a durable marker and exits. The orchestrator runs at depth-0, so it",
|
|
16280
|
+
"**can** spawn `issue-worker`; this phase actively drains the marker",
|
|
16281
|
+
"queue every cycle by dispatching one top-level worker per marked PR.",
|
|
16282
|
+
"Without it, `review:needs-worker` PRs accumulate forever \u2014 the",
|
|
16283
|
+
"marker-draining path is otherwise unreachable from the running loop,",
|
|
16284
|
+
"because Phase G always hands the worker a fresh issue number, which",
|
|
16285
|
+
"suppresses the worker's own autonomous feedback-pull discovery.",
|
|
16286
|
+
"",
|
|
16287
|
+
"**Feedback PRs are preferred over fresh issues**, so this phase runs",
|
|
16288
|
+
"before the queue scan (Phase E) and the delegation (Phase G): a",
|
|
16289
|
+
"queued fix-list is a half-finished unit of work and should land",
|
|
16290
|
+
"before any new work starts.",
|
|
16291
|
+
"",
|
|
16292
|
+
"### Step 1 \u2014 read the needs-worker enumeration",
|
|
16293
|
+
"",
|
|
16294
|
+
"Run the bundled `pr-sweep.sh` procedure in `needs-worker` mode and",
|
|
16295
|
+
"read **only** the summary lines it emits. Do **not** iterate raw",
|
|
16296
|
+
"`gh pr list` JSON yourself \u2014 the procedure is the single source of",
|
|
16297
|
+
"needs-worker metadata, mirroring Phase B's `review`-mode discipline.",
|
|
16298
|
+
"",
|
|
16299
|
+
"```bash",
|
|
16300
|
+
".claude/procedures/pr-sweep.sh needs-worker",
|
|
16301
|
+
"```",
|
|
16302
|
+
"",
|
|
16303
|
+
"Each line follows one of these shapes:",
|
|
16304
|
+
"",
|
|
16305
|
+
"```",
|
|
16306
|
+
"PR_DRAIN #<n>",
|
|
16307
|
+
"PR_SKIP #<n> reason=in-flight",
|
|
16308
|
+
"```",
|
|
16309
|
+
"",
|
|
16310
|
+
"The procedure enumerates every open PR carrying the",
|
|
16311
|
+
"`review:needs-worker` marker, ordered **highest-priority-first**",
|
|
16312
|
+
"(linked-issue `priority:*`, tie-broken by PR number ascending). It",
|
|
16313
|
+
"skips \u2014 never drains \u2014 any PR that **also** carries the",
|
|
16314
|
+
"`review:fixing` lease: that label pair means a delegation is already",
|
|
16315
|
+
"in flight (a worker is mid-run or the reviewer's confirm pass is",
|
|
16316
|
+
"pending), so re-dispatching would double-work the fix-list. This is",
|
|
16317
|
+
"what makes the phase **idempotent** \u2014 a PR already being worked, or",
|
|
16318
|
+
"one whose marker was already cleared by a finished worker, never",
|
|
16319
|
+
"appears as a `PR_DRAIN` line.",
|
|
16320
|
+
"",
|
|
16321
|
+
"If the script emits `NO_NEEDS_WORKER_PRS`, log the empty result and",
|
|
16322
|
+
"skip directly to Phase C.",
|
|
16323
|
+
"",
|
|
16324
|
+
"### Step 2 \u2014 dispatch a worker per drain PR",
|
|
16325
|
+
"",
|
|
16326
|
+
"For **each** `PR_DRAIN #<n>` line in the order the procedure emitted",
|
|
16327
|
+
"them (highest-priority first), invoke the `issue-worker` sub-agent",
|
|
16328
|
+
"**in scheduled mode** with the brief below. Loop until every",
|
|
16329
|
+
"`PR_DRAIN` line has been dispatched \u2014 do **not** stop after the",
|
|
16330
|
+
"first. Substitute `<n>` with the PR number from the line.",
|
|
16331
|
+
"",
|
|
16332
|
+
"> `scheduled mode`: `feedback mode: PR #<n>`. Pull the reviewer's",
|
|
16333
|
+
"> most-recent fix-list comment on PR #<n>, check out the PR's head",
|
|
16334
|
+
"> branch, apply each fix-list item, run the verification commands,",
|
|
16335
|
+
"> commit with a `fix(review)` message, push to the existing branch",
|
|
16336
|
+
"> (never force-push, never open a new PR), then \u2014 as the first action",
|
|
16337
|
+
"> after the push \u2014 run `complete-feedback-handoff.sh` to atomically",
|
|
16338
|
+
"> post the structured worker-report comment and clear the",
|
|
16339
|
+
"> `review:needs-worker` marker (leave `review:fixing` for the",
|
|
16340
|
+
"> reviewer's confirm pass). The unit of work is not complete until",
|
|
16341
|
+
"> that procedure returns 0. Do not",
|
|
16342
|
+
"> pause for approval. Return a one-line summary as the final line of",
|
|
16343
|
+
"> your response in the form `WORKER_DONE pr:#<n>` on success or",
|
|
16344
|
+
"> `WORKER_FAILED pr:#<n> reason:<short reason>` on failure.",
|
|
16345
|
+
"",
|
|
16346
|
+
"The `feedback mode: PR #<n>` push is the explicit-pull form documented",
|
|
16347
|
+
"in the **Invocation Mode** section of `.claude/agents/issue-worker.md`",
|
|
16348
|
+
"\u2014 it always wins, so the worker fixes exactly that PR and does not",
|
|
16349
|
+
"scan the issue queue. The orchestrator is **read-only** with respect",
|
|
16350
|
+
"to the PR and its branch: never check out the branch, apply the",
|
|
16351
|
+
"fix-list, push commits, or edit review labels yourself. Consuming the",
|
|
16352
|
+
"fix-list and clearing `review:needs-worker` is the worker's job.",
|
|
16353
|
+
"",
|
|
16354
|
+
"### Step 3 \u2014 failure semantics",
|
|
16355
|
+
"",
|
|
16356
|
+
"A single PR's worker failure (missing or malformed `WORKER_*` final",
|
|
16357
|
+
"line, sub-agent error, unresolvable rebase conflict) **never stops",
|
|
16358
|
+
"the drain**. Log the failure as",
|
|
16359
|
+
"`WORKER_FAILED pr:#<n> reason:<observed>` and continue to the next",
|
|
16360
|
+
"`PR_DRAIN` line. The next orchestrator invocation re-runs",
|
|
16361
|
+
"`pr-sweep.sh needs-worker` and re-dispatches a worker if the PR still",
|
|
16362
|
+
"carries an unconsumed marker. Do **not** retry the same PR in this",
|
|
16363
|
+
"session.",
|
|
16364
|
+
"",
|
|
16365
|
+
"After every `PR_DRAIN` PR has been processed (or",
|
|
16366
|
+
"`NO_NEEDS_WORKER_PRS` was emitted), continue to Phase C regardless",
|
|
16367
|
+
"of outcomes.",
|
|
15843
16368
|
"",
|
|
15844
16369
|
"## Phase C: Triage \u2014 Unblock",
|
|
15845
16370
|
"",
|
|
@@ -15887,31 +16412,35 @@ var orchestratorSubAgent = {
|
|
|
15887
16412
|
"## Phase D: Maintenance",
|
|
15888
16413
|
"",
|
|
15889
16414
|
"Run the bundled `check-blocked.sh maintenance` procedure and read",
|
|
15890
|
-
"**only** the
|
|
15891
|
-
"procedure folds the stale-detection,
|
|
15892
|
-
"needs-attention summary
|
|
15893
|
-
"
|
|
15894
|
-
"`status:needs-attention` label
|
|
15895
|
-
"for each stale / stale-blocked
|
|
15896
|
-
"
|
|
15897
|
-
"(`
|
|
16415
|
+
"**only** the two summary lines it emits \u2014 `MAINTENANCE_DONE` and",
|
|
16416
|
+
"`LEASE_RECONCILE`. The procedure folds the stale-detection,",
|
|
16417
|
+
"orphan-detection, needs-attention summary, and PR-lease",
|
|
16418
|
+
"auto-reconcile that earlier revisions split across D1, D2, and D3",
|
|
16419
|
+
"into a single sweep \u2014 applying the `status:needs-attention` label",
|
|
16420
|
+
"and posting the canned flag comment for each stale / stale-blocked",
|
|
16421
|
+
"issue itself, and reconciling stuck `review:fixing` PR leases",
|
|
16422
|
+
"itself, mirroring the discipline of Phase B (`pr-sweep.sh`) and",
|
|
16423
|
+
"Phase C (`check-blocked.sh unblock`).",
|
|
15898
16424
|
"",
|
|
15899
16425
|
"```bash",
|
|
15900
16426
|
".claude/procedures/check-blocked.sh maintenance",
|
|
15901
16427
|
"```",
|
|
15902
16428
|
"",
|
|
15903
|
-
"The script emits
|
|
16429
|
+
"The script emits two summary lines in this shape:",
|
|
15904
16430
|
"",
|
|
15905
16431
|
"```",
|
|
15906
16432
|
"MAINTENANCE_DONE flagged_stale=<N> flagged_blocked=<M> orphan_branches=<A> orphan_prs=<B> needs_attention_total=<T>",
|
|
16433
|
+
"LEASE_RECONCILE orphaned=<N> consumed_uncleared=<M>",
|
|
15907
16434
|
"```",
|
|
15908
16435
|
"",
|
|
15909
|
-
"Per-issue / per-orphan informational lines (`FLAGGED_STALE
|
|
15910
|
-
"`FLAGGED_BLOCKED #N`, `STALE #N \u2014 \u2026`, `STALE_BLOCKED #N \u2014 \u2026`,",
|
|
15911
|
-
"`ORPHAN_BRANCH \u2026`, `ORPHAN_PR #N \u2014 \u2026`, `FLAG_FAILED #N \u2014 \u2026
|
|
15912
|
-
"
|
|
15913
|
-
"
|
|
15914
|
-
"
|
|
16436
|
+
"Per-issue / per-orphan / per-PR informational lines (`FLAGGED_STALE",
|
|
16437
|
+
"#N`, `FLAGGED_BLOCKED #N`, `STALE #N \u2014 \u2026`, `STALE_BLOCKED #N \u2014 \u2026`,",
|
|
16438
|
+
"`ORPHAN_BRANCH \u2026`, `ORPHAN_PR #N \u2014 \u2026`, `FLAG_FAILED #N \u2014 \u2026`,",
|
|
16439
|
+
"`LEASE_ORPHANED PR #N \u2014 \u2026`, `LEASE_CONSUMED_UNCLEARED PR #N \u2014 \u2026`,",
|
|
16440
|
+
"`LEASE_RECONCILE_FAILED PR #N \u2014 \u2026`) are emitted for log visibility",
|
|
16441
|
+
"but are **not** load-bearing for the orchestrator \u2014 partial failures",
|
|
16442
|
+
"(one bad `gh` call) do not abort the sweep, they are simply omitted",
|
|
16443
|
+
"from the counters.",
|
|
15915
16444
|
"",
|
|
15916
16445
|
"**Important:** the script never auto-resets stale issues to",
|
|
15917
16446
|
"`status:ready`. It only adds `status:needs-attention`; the",
|
|
@@ -15921,9 +16450,36 @@ var orchestratorSubAgent = {
|
|
|
15921
16450
|
"but are never deleted by the orchestrator \u2014 a human reviews the",
|
|
15922
16451
|
"log lines and prunes orphans manually.",
|
|
15923
16452
|
"",
|
|
15924
|
-
"
|
|
15925
|
-
"
|
|
15926
|
-
"
|
|
16453
|
+
"**PR-lease auto-reconcile (`LEASE_RECONCILE`).** The sweep also",
|
|
16454
|
+
"unwedges PRs stuck in the feedback-drain loop, so no human is",
|
|
16455
|
+
"needed to free a stuck `review:fixing` lease. Two states are",
|
|
16456
|
+
"reconciled directly by the script (it mutates the labels itself \u2014",
|
|
16457
|
+
"the orchestrator only reads the summary line):",
|
|
16458
|
+
"",
|
|
16459
|
+
"- **Orphaned lease** \u2014 a PR carries `review:fixing` but **not**",
|
|
16460
|
+
" `review:needs-worker`, its reviewer fix-list comment is older",
|
|
16461
|
+
" than the 72h stale threshold, and no worker-report comment newer",
|
|
16462
|
+
" than the fix-list exists. The sweep **re-applies**",
|
|
16463
|
+
" `review:needs-worker` (a deliberate re-arm, not a silent",
|
|
16464
|
+
" force-release \u2014 the `review:fixing` lease is left untouched) and",
|
|
16465
|
+
" posts an audit-trail note comment, so the Phase B1 drain retries",
|
|
16466
|
+
" the delegation autonomously. Counted in `orphaned=<N>`.",
|
|
16467
|
+
"- **Consumed-but-uncleared wedge** \u2014 a PR carries **both**",
|
|
16468
|
+
" `review:needs-worker` and `review:fixing`, but the branch HEAD",
|
|
16469
|
+
" commit is newer than the fix-list comment and no worker-report",
|
|
16470
|
+
" exists (the worker pushed then skipped the hand-off). The sweep",
|
|
16471
|
+
" **removes** `review:needs-worker` and posts an audit-trail",
|
|
16472
|
+
" reconcile note, flipping the PR into the lease-without-marker",
|
|
16473
|
+
" state the reviewer confirm pass keys on so it can merge. Counted",
|
|
16474
|
+
" in `consumed_uncleared=<M>`.",
|
|
16475
|
+
"",
|
|
16476
|
+
"Every lease reconcile leaves an audit-trail note comment \u2014 a lease",
|
|
16477
|
+
"is never silently force-released. The `review:fixing` lease itself",
|
|
16478
|
+
"is always left for the reviewer confirm pass to release.",
|
|
16479
|
+
"",
|
|
16480
|
+
"Log both summary lines and continue to Phase E regardless of",
|
|
16481
|
+
"outcomes \u2014 a non-zero `flagged_*`, `orphan_*`, `orphaned`, or",
|
|
16482
|
+
"`consumed_uncleared` count is informational, not a failure.",
|
|
15927
16483
|
"",
|
|
15928
16484
|
"## Phase E: Queue Scan",
|
|
15929
16485
|
"",
|
|
@@ -16083,7 +16639,7 @@ var orchestratorSubAgent = {
|
|
|
16083
16639
|
"",
|
|
16084
16640
|
"1. **Never implement code.** You triage, scan, and delegate \u2014 you do not code.",
|
|
16085
16641
|
"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.",
|
|
16086
|
-
"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.",
|
|
16642
|
+
"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.",
|
|
16087
16643
|
"4. **Follow CLAUDE.md conventions** for all git and gh operations.",
|
|
16088
16644
|
"5. **Priority order:** critical > high > medium > low > trivial, then **funnel tier asc** (lower tier wins ties), then FIFO by issue number.",
|
|
16089
16645
|
"6. **Never dispatch a `large` issue.** Always run the scope check",
|
|
@@ -16105,8 +16661,17 @@ var orchestratorSubAgent = {
|
|
|
16105
16661
|
" human approval and the delegation stalls.",
|
|
16106
16662
|
"9. **A failed reviewer never stops the sweep.** Phase B continues",
|
|
16107
16663
|
" to the next eligible PR after a `REVIEWER_FAILED` line and",
|
|
16108
|
-
" proceeds to Phase
|
|
16109
|
-
" abort the cycle on a single PR's reviewer failure."
|
|
16664
|
+
" proceeds to Phase B1 regardless of how many PRs failed. Do not",
|
|
16665
|
+
" abort the cycle on a single PR's reviewer failure.",
|
|
16666
|
+
"10. **Drain every `review:needs-worker` PR before fresh work.**",
|
|
16667
|
+
" Phase B1 dispatches a top-level `issue-worker` per open marker",
|
|
16668
|
+
" PR (highest-priority first) to consume the reviewer's fix-list,",
|
|
16669
|
+
" and loops until the queue is empty \u2014 feedback PRs are preferred",
|
|
16670
|
+
" over fresh issues, so Phase B1 runs before Phase E / Phase G.",
|
|
16671
|
+
" Skip any PR that also carries the `review:fixing` lease (a",
|
|
16672
|
+
" delegation already in flight) so the drain stays idempotent. A",
|
|
16673
|
+
" single worker's failure never stops the drain; the next cycle",
|
|
16674
|
+
" re-dispatches against any PR whose marker is still unconsumed."
|
|
16110
16675
|
].join("\n")
|
|
16111
16676
|
};
|
|
16112
16677
|
var issueWorkerSubAgent = {
|
|
@@ -16190,7 +16755,7 @@ var issueWorkerSubAgent = {
|
|
|
16190
16755
|
"| 4. Implement | Read issue AC, implement | Read most-recent reviewer-authored fix-list comment on the PR, parse JSON, apply each item. |",
|
|
16191
16756
|
"| 5. Verify | Unchanged | Unchanged. |",
|
|
16192
16757
|
"| 6. Commit and Push | Conventional commit, interactive pause | Commit message `fix(review): <summary> (PR #<n>)`. Pause behaviour unchanged. `git push` (no `-u`). |",
|
|
16193
|
-
"| 6.5. Complete the hand-off | n/a |
|
|
16758
|
+
"| 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. |",
|
|
16194
16759
|
"| 7. Open a PR | Open a new PR | **Skip.** |",
|
|
16195
16760
|
"| 8. Update Status | Set issue to `status:ready-for-review` | **Skip.** PR is still open; issue stays `status:in-progress`. |",
|
|
16196
16761
|
"| 9. Branch Cleanup | Poll for merge, delete branch | **Skip.** Return control to the pr-reviewer without polling. |",
|
|
@@ -16587,46 +17152,73 @@ var issueWorkerSubAgent = {
|
|
|
16587
17152
|
"git push -u origin <branch-name>",
|
|
16588
17153
|
"```",
|
|
16589
17154
|
"",
|
|
16590
|
-
"## Phase 6.5: Complete the Feedback Hand-off",
|
|
17155
|
+
"## Phase 6.5: Complete the Feedback Hand-off (MANDATORY, ATOMIC)",
|
|
16591
17156
|
"",
|
|
16592
17157
|
"**Normal mode:** Skip this phase entirely.",
|
|
16593
17158
|
"",
|
|
16594
|
-
"**Feedback mode
|
|
16595
|
-
"the
|
|
16596
|
-
"
|
|
17159
|
+
"**Feedback mode \u2014 the invariant.** A successful Phase 6 push is **not**",
|
|
17160
|
+
"the end of the unit of work. **If you pushed in feedback mode, the unit",
|
|
17161
|
+
"of work is NOT complete until `complete-feedback-handoff.sh` returns",
|
|
17162
|
+
"0.** The git push and the hand-off are a single atomic step: the marker",
|
|
17163
|
+
"must be cleared and the worker-report posted in the **same session** as",
|
|
17164
|
+
"the push. A clean push that leaves `review:needs-worker` set and posts",
|
|
17165
|
+
"no report double-wedges the PR \u2014 the reviewer's confirm pass never",
|
|
17166
|
+
"fires (the marker is still present) and stale-lease reclaim never fires",
|
|
17167
|
+
"(it requires the marker absent). Never stop, hand back to the caller,",
|
|
17168
|
+
"or move to any optional/secondary step until the procedure has exited 0.",
|
|
17169
|
+
"",
|
|
17170
|
+
"**This is the FIRST action after a successful push** \u2014 before any",
|
|
17171
|
+
"summary, log line, or secondary step. Call the deterministic procedure",
|
|
17172
|
+
"with the PR number, the commit SHA you pushed (or the rebased head SHA",
|
|
17173
|
+
"for a synthetic-rebase item), and the per-item outcomes JSON array:",
|
|
17174
|
+
"",
|
|
17175
|
+
"```bash",
|
|
17176
|
+
".claude/procedures/complete-feedback-handoff.sh <pr-number> <commit-sha> '<items-json>'",
|
|
17177
|
+
"```",
|
|
16597
17178
|
"",
|
|
16598
|
-
"
|
|
16599
|
-
"
|
|
16600
|
-
|
|
16601
|
-
"
|
|
16602
|
-
" item), and a per-item outcome keyed by `comment_id` \u2014 `handled`",
|
|
16603
|
-
" or `failed` (with a short reason for each failure). This is the",
|
|
16604
|
-
" same structured report you would otherwise return to the caller in",
|
|
16605
|
-
" the pushed-feedback case; post it as a PR comment so a separate",
|
|
16606
|
-
" reviewer session can consume it.",
|
|
17179
|
+
"The `<items-json>` argument is a JSON array of per-item outcomes keyed",
|
|
17180
|
+
"by the fix-list `comment_id` \u2014 one entry per item you applied in Phase",
|
|
17181
|
+
'4, each `{"comment_id": "<id>", "outcome": "applied"|"failed",',
|
|
17182
|
+
' "detail": "<short reason on failure>"}`:',
|
|
16607
17183
|
"",
|
|
16608
|
-
"
|
|
16609
|
-
"
|
|
16610
|
-
"
|
|
17184
|
+
"```json",
|
|
17185
|
+
"[",
|
|
17186
|
+
' {"comment_id": "IC_abc", "outcome": "applied", "detail": ""},',
|
|
17187
|
+
' {"comment_id": "IC_def", "outcome": "failed", "detail": "test still red"}',
|
|
17188
|
+
"]",
|
|
17189
|
+
"```",
|
|
16611
17190
|
"",
|
|
16612
|
-
"
|
|
16613
|
-
"
|
|
16614
|
-
"
|
|
16615
|
-
"
|
|
16616
|
-
"
|
|
16617
|
-
"
|
|
17191
|
+
"The procedure performs **both** halves of the hand-off in one call and",
|
|
17192
|
+
"exits non-zero on any failure:",
|
|
17193
|
+
"",
|
|
17194
|
+
"1. **Posts the structured `## Worker report` comment** \u2014 the record the",
|
|
17195
|
+
" reviewer's confirm pass reads to react on source comments and",
|
|
17196
|
+
" re-evaluate AC/CI. It renders one checklist line per `comment_id`",
|
|
17197
|
+
" (`applied` / `failed`), the pushed commit SHA, and an overall",
|
|
17198
|
+
" outcome (`complete` when every item applied, `partial` when any",
|
|
17199
|
+
" failed).",
|
|
17200
|
+
"2. **Removes the `review:needs-worker` marker** \u2014 leaving the",
|
|
17201
|
+
" `review:fixing` lease in place. Clearing the marker flips the PR",
|
|
17202
|
+
" into the lease-without-marker state the reviewer's confirm pass keys",
|
|
17203
|
+
" on.",
|
|
17204
|
+
"",
|
|
17205
|
+
"**Partial failure still clears the marker.** The worker-report is",
|
|
17206
|
+
"ALWAYS posted and the marker ALWAYS cleared even when every item",
|
|
17207
|
+
"`failed` (the procedure reports overall outcome `partial` and the",
|
|
17208
|
+
"per-item failures by `comment_id`). The reviewer's confirm pass reacts",
|
|
17209
|
+
"`thinking_face` on the failed items and falls through to the",
|
|
17210
|
+
"human-required hand-off via `review:awaiting-human`. Leaving the marker",
|
|
17211
|
+
"applied on a partial or total failure would wedge the PR, so the marker",
|
|
17212
|
+
"is cleared unconditionally \u2014 never remove it yourself out-of-band and",
|
|
17213
|
+
"never skip the procedure because items failed.",
|
|
16618
17214
|
"",
|
|
16619
|
-
"
|
|
16620
|
-
"
|
|
16621
|
-
"
|
|
17215
|
+
"If the procedure exits non-zero (e.g. the comment post or the label",
|
|
17216
|
+
"removal failed), the hand-off did **not** complete \u2014 retry it. Do not",
|
|
17217
|
+
"treat the pushed commit as a finished unit of work until the procedure",
|
|
17218
|
+
"returns 0.",
|
|
16622
17219
|
"",
|
|
16623
17220
|
"Do **not** remove `review:fixing` yourself, and do **not** re-enable",
|
|
16624
|
-
"auto-merge \u2014 both belong to the reviewer's confirm pass.
|
|
16625
|
-
"not apply any item (every item `failed`), still write the report and",
|
|
16626
|
-
"still clear `review:needs-worker`: the reviewer's confirm pass reacts",
|
|
16627
|
-
"`thinking_face` on the failed items and falls through to the",
|
|
16628
|
-
"human-required hand-off via `review:awaiting-human`. Leaving the",
|
|
16629
|
-
"marker applied on a total failure would wedge the PR.",
|
|
17221
|
+
"auto-merge \u2014 both belong to the reviewer's confirm pass.",
|
|
16630
17222
|
"",
|
|
16631
17223
|
"## Phase 7: Open a PR",
|
|
16632
17224
|
"",
|
|
@@ -16755,13 +17347,19 @@ var issueWorkerSubAgent = {
|
|
|
16755
17347
|
" highest-priority unconsumed fix-list first. A half-finished PR",
|
|
16756
17348
|
" should land before a new unit of work starts. The explicit",
|
|
16757
17349
|
" `feedback mode: PR #<n>` push always overrides both scans.",
|
|
16758
|
-
"16. **
|
|
16759
|
-
"
|
|
16760
|
-
"
|
|
16761
|
-
"
|
|
16762
|
-
"
|
|
16763
|
-
"
|
|
16764
|
-
"
|
|
17350
|
+
"16. **Complete the hand-off atomically; clear `review:needs-worker`,",
|
|
17351
|
+
" never `review:fixing`.** A successful feedback-mode push is not a",
|
|
17352
|
+
" finished unit of work until the hand-off completes. As the FIRST",
|
|
17353
|
+
" action after the push (Phase 6.5), run",
|
|
17354
|
+
" `.claude/procedures/complete-feedback-handoff.sh <pr> <commit-sha>",
|
|
17355
|
+
" '<items-json>'`, which posts the structured worker-report comment",
|
|
17356
|
+
" and removes **only** the `review:needs-worker` marker in one call,",
|
|
17357
|
+
" exiting non-zero on any failure. The unit of work is **not**",
|
|
17358
|
+
" complete until it returns 0. The `review:fixing` lease belongs to",
|
|
17359
|
+
" the reviewer's confirm pass \u2014 never remove it yourself, and never",
|
|
17360
|
+
" re-enable auto-merge. The procedure clears the marker even when",
|
|
17361
|
+
" every item failed (overall outcome `partial`), so a partial or",
|
|
17362
|
+
" crashed delegation does not wedge the PR.",
|
|
16765
17363
|
"17. **Auto-pull only in scheduled mode.** The autonomous",
|
|
16766
17364
|
" `review:needs-worker` scan is scheduled-mode only. In an",
|
|
16767
17365
|
" interactive session, never auto-pull a feedback PR \u2014 a human who",
|
|
@@ -16773,19 +17371,21 @@ var ORCHESTRATOR_CONVENTIONS_PREAMBLE = [
|
|
|
16773
17371
|
"",
|
|
16774
17372
|
"When running the orchestrator agent (`.claude/agents/orchestrator.md`):",
|
|
16775
17373
|
"",
|
|
16776
|
-
"- 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",
|
|
17374
|
+
"- 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",
|
|
16777
17375
|
"- 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`).",
|
|
16778
|
-
"-
|
|
17376
|
+
"- **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.",
|
|
17377
|
+
"- 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.",
|
|
16779
17378
|
"- 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.",
|
|
16780
17379
|
"- 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.",
|
|
16781
17380
|
"- Stale thresholds: 72h for in-progress, 168h for blocked",
|
|
16782
17381
|
"- Flagged issues get `status:needs-attention` \u2014 they are not auto-reset",
|
|
17382
|
+
"- **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.",
|
|
16783
17383
|
"",
|
|
16784
17384
|
"## Depth-0 invocation requirement",
|
|
16785
17385
|
"",
|
|
16786
|
-
'The orchestrator agent **must run as the top-level (depth-0) session** because
|
|
17386
|
+
'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.',
|
|
16787
17387
|
"",
|
|
16788
|
-
'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
|
|
17388
|
+
'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.'
|
|
16789
17389
|
].join("\n");
|
|
16790
17390
|
function buildOrchestratorConventionsContent(tiers, scopeGate = resolveScopeGate(), _runRatio = resolveRunRatio(), scheduledTasks = resolveScheduledTasks(), unblockDependents = resolveUnblockDependents(), excludeBundles = []) {
|
|
16791
17391
|
return [
|
|
@@ -16838,8 +17438,10 @@ var orchestrateCommand = {
|
|
|
16838
17438
|
"# Orchestrate",
|
|
16839
17439
|
"",
|
|
16840
17440
|
"Invoke the `orchestrator` sub-agent and run **one full end-to-end",
|
|
16841
|
-
"cycle**:
|
|
16842
|
-
"
|
|
17441
|
+
"cycle**: PR review sweep \u2192 feedback drain (drain every open",
|
|
17442
|
+
"`review:needs-worker` PR through the `issue-worker`) \u2192 triage /",
|
|
17443
|
+
"unblock \u2192 maintenance \u2192 queue scan \u2192 delegate the picked issue to",
|
|
17444
|
+
"the `issue-worker` sub-agent \u2192 cleanup.",
|
|
16843
17445
|
"",
|
|
16844
17446
|
"Follow the contract in `.claude/agents/orchestrator.md`. Do **not**",
|
|
16845
17447
|
"implement code, create branches, push commits, or merge PRs \u2014 those",
|
|
@@ -16934,7 +17536,8 @@ var orchestratorBundle = {
|
|
|
16934
17536
|
procedures: [
|
|
16935
17537
|
checkBlockedProcedure,
|
|
16936
17538
|
unblockDependentsProcedure,
|
|
16937
|
-
prSweepProcedure
|
|
17539
|
+
prSweepProcedure,
|
|
17540
|
+
completeFeedbackHandoffProcedure
|
|
16938
17541
|
],
|
|
16939
17542
|
commands: [orchestrateCommand, checkBlockedCommand, scanCommand],
|
|
16940
17543
|
claudePermissions: {
|
|
@@ -18529,6 +19132,116 @@ var prReviewerSubAgent = {
|
|
|
18529
19132
|
"unchanged regardless of mode. Only the terminal action in Phase 4",
|
|
18530
19133
|
"branches on the decided mode.",
|
|
18531
19134
|
"",
|
|
19135
|
+
"## Phase 2.8: Label Reconciliation",
|
|
19136
|
+
"",
|
|
19137
|
+
"A PR can never carry **mutually-exclusive review-workflow labels**",
|
|
19138
|
+
"after a reviewer pass \u2014 this is the PR equivalent of the",
|
|
19139
|
+
'"exactly one `status:*`" discipline issues already follow.',
|
|
19140
|
+
"Successive passes that layer labels with no reconciler can drive a",
|
|
19141
|
+
"PR into an impossible state (a real PR once held",
|
|
19142
|
+
"`review:awaiting-human` + `status:needs-attention` + `review:fixing`",
|
|
19143
|
+
"+ `review:needs-worker` simultaneously). Humans cannot tell what",
|
|
19144
|
+
"state such a PR is in, and downstream phases branch on contradictory",
|
|
19145
|
+
"signals. This phase detects violations and resolves them to the",
|
|
19146
|
+
"**single correct state** implied by the mode decided in Phase 2.75",
|
|
19147
|
+
"and the current loop position, logging every correction in the",
|
|
19148
|
+
"sticky `## Reviewer notes` comment.",
|
|
19149
|
+
"",
|
|
19150
|
+
"Run this phase **early** \u2014 after Phase 2.75 fixes the review mode and",
|
|
19151
|
+
"after the **Confirm a Completed Delegation** detection step reads the",
|
|
19152
|
+
"lease state, but **before** Phase 3.5 / Phase 4 branch on review",
|
|
19153
|
+
"state to decide actions. It must operate on a clean label set so no",
|
|
19154
|
+
"later phase inherits a contradiction. It runs on **every** pass.",
|
|
19155
|
+
"",
|
|
19156
|
+
"### The review-label invariants",
|
|
19157
|
+
"",
|
|
19158
|
+
"These are the workflow labels this phase governs (see the",
|
|
19159
|
+
"`pr-review-feedback-protocol` label glossary for full meanings):",
|
|
19160
|
+
"`review:awaiting-human`, `review:needs-worker`, `review:fixing`,",
|
|
19161
|
+
"plus the additive `status:needs-attention`. (`review:human-required`",
|
|
19162
|
+
"and `review:auto-ok` are **policy inputs** read in Phase 2.75, not",
|
|
19163
|
+
"workflow-state labels \u2014 this phase never adds or removes them.)",
|
|
19164
|
+
"",
|
|
19165
|
+
"1. **`review:awaiting-human` is mutually exclusive with the",
|
|
19166
|
+
" fix-delegation labels.** A PR is **either** in the fix-delegation",
|
|
19167
|
+
" loop (`review:needs-worker` and/or `review:fixing`) **or** handed",
|
|
19168
|
+
" off to a human (`review:awaiting-human`) \u2014 **never both**. The",
|
|
19169
|
+
" combination `review:awaiting-human` + `review:needs-worker`,",
|
|
19170
|
+
" `review:awaiting-human` + `review:fixing`, or all three together",
|
|
19171
|
+
" is a **violation**.",
|
|
19172
|
+
"2. **`review:fixing` WITHOUT `review:needs-worker` is NOT a",
|
|
19173
|
+
" violation** \u2014 it is the **confirm-pending** state (the worker",
|
|
19174
|
+
" finished and cleared its marker; a confirm pass owns the PR and",
|
|
19175
|
+
" will release the lease). Do **not** strip `review:fixing` here.",
|
|
19176
|
+
"3. **`review:fixing` WITH `review:needs-worker` is NOT a violation**",
|
|
19177
|
+
" \u2014 it is a valid **in-flight delegation** (the work is durably",
|
|
19178
|
+
" queued and a top-level `issue-worker` pass will consume it). Do",
|
|
19179
|
+
" **not** treat this combination as a contradiction.",
|
|
19180
|
+
"4. **`status:needs-attention` is additive but must not coexist with",
|
|
19181
|
+
" an in-flight delegation that is making progress.** When the PR",
|
|
19182
|
+
" carries an active in-flight delegation (`review:fixing` +",
|
|
19183
|
+
" `review:needs-worker`) with a fix-list newer than the flag and no",
|
|
19184
|
+
" failed-fix pushback, `status:needs-attention` contradicts the",
|
|
19185
|
+
" live progress signal and is a **violation**. (A",
|
|
19186
|
+
" `status:needs-attention` flag that coexists with a *stalled* or",
|
|
19187
|
+
" *failed* delegation, an unresolved `thinking_face` pushback, or a",
|
|
19188
|
+
" `human-required` hand-off is **legitimate** \u2014 leave it.)",
|
|
19189
|
+
"",
|
|
19190
|
+
"### Canonical resolution table",
|
|
19191
|
+
"",
|
|
19192
|
+
"For each detected violation, resolve to the single correct state",
|
|
19193
|
+
"below. The winning label is chosen by the **mode the reviewer is",
|
|
19194
|
+
"about to act in** (Phase 2.75) and the **current loop position**",
|
|
19195
|
+
"(the lease/marker labels present), so the surviving set always",
|
|
19196
|
+
"matches the action this pass will actually take:",
|
|
19197
|
+
"",
|
|
19198
|
+
"| Violation combo | Loop position / mode | Resolution (winner) | Why |",
|
|
19199
|
+
"|-----------------|----------------------|---------------------|-----|",
|
|
19200
|
+
"| `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. |",
|
|
19201
|
+
"| `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. |",
|
|
19202
|
+
"| `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. |",
|
|
19203
|
+
"",
|
|
19204
|
+
"Resolution is **conservative about human intent**: when the pass is",
|
|
19205
|
+
"genuinely `human-required` the human-facing labels win and the",
|
|
19206
|
+
"fix-delegation labels are cleared; when the pass is `auto-merge` and",
|
|
19207
|
+
"a delegation is live, the delegation wins and the stray",
|
|
19208
|
+
"`review:awaiting-human` is cleared. Never resolve a violation by",
|
|
19209
|
+
"*adding* a label \u2014 only by removing the contradicting one(s) per the",
|
|
19210
|
+
"table.",
|
|
19211
|
+
"",
|
|
19212
|
+
"### Detect and apply",
|
|
19213
|
+
"",
|
|
19214
|
+
"1. List the PR's current labels:",
|
|
19215
|
+
"",
|
|
19216
|
+
" ```bash",
|
|
19217
|
+
" gh pr view <pr-number> --json labels --jq '.labels[].name'",
|
|
19218
|
+
" ```",
|
|
19219
|
+
"",
|
|
19220
|
+
"2. Evaluate the invariants above against the label set, the mode from",
|
|
19221
|
+
" Phase 2.75, and the lease/marker position. If no violation exists,",
|
|
19222
|
+
" record `Label reconciliation: consistent` and proceed \u2014 this is",
|
|
19223
|
+
" the common case and the phase is a cheap no-op.",
|
|
19224
|
+
"",
|
|
19225
|
+
"3. For each violation, remove the losing label(s) named in the",
|
|
19226
|
+
" resolution table:",
|
|
19227
|
+
"",
|
|
19228
|
+
" ```bash",
|
|
19229
|
+
" gh pr edit <pr-number> --remove-label '<losing-label>'",
|
|
19230
|
+
" ```",
|
|
19231
|
+
"",
|
|
19232
|
+
"4. **Log every correction in the sticky `## Reviewer notes` comment**",
|
|
19233
|
+
" (Phase 4.5) on a `**Label reconciliation:**` line, naming the",
|
|
19234
|
+
" detected violation combo, the labels removed, and the surviving",
|
|
19235
|
+
" self-consistent set \u2014 for example:",
|
|
19236
|
+
" `Label reconciliation: removed review:awaiting-human (contradicted in-flight review:fixing+review:needs-worker delegation); set is now {review:fixing, review:needs-worker}`.",
|
|
19237
|
+
" The correction is part of the audit trail; it must never be a",
|
|
19238
|
+
" silent label mutation.",
|
|
19239
|
+
"",
|
|
19240
|
+
"After this phase the PR holds a **self-consistent** review-label set:",
|
|
19241
|
+
"at most one of {`review:awaiting-human`} versus the fix-delegation",
|
|
19242
|
+
"pair, and no `status:needs-attention` shadowing a live delegation.",
|
|
19243
|
+
"Phase 3.5 and Phase 4 then branch on a clean state.",
|
|
19244
|
+
"",
|
|
18532
19245
|
"## Phase 3: Compare Diff to Acceptance Criteria",
|
|
18533
19246
|
"",
|
|
18534
19247
|
"Read the issue body for an **Acceptance Criteria** (or equivalent) section.",
|
|
@@ -19091,6 +19804,7 @@ var prReviewerSubAgent = {
|
|
|
19091
19804
|
"**CI status:** green | pending | red",
|
|
19092
19805
|
"**Outstanding:** <list of comments still open with their classification and author>",
|
|
19093
19806
|
"**Pushbacks:** <list of disputes with reasons>",
|
|
19807
|
+
"**Label reconciliation:** <consistent | corrections applied this pass>",
|
|
19094
19808
|
"**Last pass:** <ISO timestamp>",
|
|
19095
19809
|
"```",
|
|
19096
19810
|
"",
|
|
@@ -19110,6 +19824,11 @@ var prReviewerSubAgent = {
|
|
|
19110
19824
|
"- **Pushbacks** \u2014 every comment the reviewer reacted",
|
|
19111
19825
|
" `thinking_face` to on this or any prior pass, with the reason",
|
|
19112
19826
|
" captured in the pushback reply. Empty list when there are none.",
|
|
19827
|
+
"- **Label reconciliation** \u2014 the outcome of Phase 2.8: either",
|
|
19828
|
+
" `consistent` (no mutually-exclusive labels found) or a list of",
|
|
19829
|
+
" the corrections applied this pass (the detected violation combo,",
|
|
19830
|
+
" the label(s) removed, and the resulting self-consistent set).",
|
|
19831
|
+
" Every reconciliation correction is recorded here for auditability.",
|
|
19113
19832
|
"- **Last pass** \u2014 the ISO 8601 timestamp of this run.",
|
|
19114
19833
|
"",
|
|
19115
19834
|
"### Step 3: Create or edit in place",
|
|
@@ -19448,16 +20167,23 @@ var prReviewerSubAgent = {
|
|
|
19448
20167
|
"### Stale-lease reclaim",
|
|
19449
20168
|
"",
|
|
19450
20169
|
"A crashed worker must not wedge a PR forever. A `review:fixing` lease",
|
|
19451
|
-
"is **
|
|
20170
|
+
"is **orphaned** when it has no `review:needs-worker` companion",
|
|
19452
20171
|
"**and** no consuming worker is making progress \u2014 i.e. the lease is",
|
|
19453
20172
|
"older than the stale threshold (the same in-progress threshold the",
|
|
19454
20173
|
"maintenance sweep applies, 72h by default) with no worker-report",
|
|
19455
20174
|
"comment newer than the fix-list. The reclaim is wired into the",
|
|
19456
|
-
"maintenance sweep, not a reviewer pass: the sweep
|
|
19457
|
-
"
|
|
19458
|
-
"`review:fixing` lease and
|
|
19459
|
-
"
|
|
19460
|
-
"
|
|
20175
|
+
"maintenance sweep, not a reviewer pass: the sweep **re-applies**",
|
|
20176
|
+
"`review:needs-worker` (re-arming the durable work marker, leaving the",
|
|
20177
|
+
"`review:fixing` lease untouched) and posts an audit-trail note",
|
|
20178
|
+
"comment, so the Phase B1 feedback drain retries the delegation",
|
|
20179
|
+
"autonomously \u2014 no human is needed to free the lease. The maintenance",
|
|
20180
|
+
"sweep also auto-reconciles the **consumed-but-uncleared** wedge (both",
|
|
20181
|
+
"labels present, branch HEAD advanced past the fix-list, no",
|
|
20182
|
+
"worker-report) by removing `review:needs-worker` so the reviewer",
|
|
20183
|
+
"confirm pass can merge. A lease is never silently force-released \u2014 every",
|
|
20184
|
+
"reconcile posts an audit-trail note comment. See the **Stale-lease",
|
|
20185
|
+
"reclaim** subsection of the `pr-review-feedback-protocol` rule for the",
|
|
20186
|
+
"full lifecycle.",
|
|
19461
20187
|
"",
|
|
19462
20188
|
"## Phase 5: Branch Cleanup and Issue Closure Verification",
|
|
19463
20189
|
"",
|
|
@@ -19848,7 +20574,6 @@ function buildPrReviewBundle(policy = resolvePrReviewPolicy()) {
|
|
|
19848
20574
|
"",
|
|
19849
20575
|
"human-required:",
|
|
19850
20576
|
" paths:",
|
|
19851
|
-
' - "docs/src/content/docs/requirements/architectural-decisions/**"',
|
|
19852
20577
|
' - "docs/src/content/docs/project-context.md"',
|
|
19853
20578
|
' - ".github/workflows/**"',
|
|
19854
20579
|
' - ".github/CODEOWNERS"',
|
|
@@ -19947,6 +20672,35 @@ function buildPrReviewBundle(policy = resolvePrReviewPolicy()) {
|
|
|
19947
20672
|
"the carve-out check, so the rule only relaxes the threshold for",
|
|
19948
20673
|
"PRs whose **every** changed path is doc-only.",
|
|
19949
20674
|
"",
|
|
20675
|
+
"### ADRs auto-merge as `Proposed`",
|
|
20676
|
+
"",
|
|
20677
|
+
"Architectural Decision Records (under",
|
|
20678
|
+
"`docs/src/content/docs/requirements/architectural-decisions/**`)",
|
|
20679
|
+
"are **not** a `human-required.paths` trigger. An ADR-only PR with",
|
|
20680
|
+
"green CI and met acceptance criteria resolves to `auto-merge` and",
|
|
20681
|
+
"squash-merges with no `review:awaiting-human` and no human action.",
|
|
20682
|
+
"",
|
|
20683
|
+
"Auto-merging an ADR does **not** ratify the decision it records.",
|
|
20684
|
+
"An ADR is authored in `Proposed` status, and merging it simply",
|
|
20685
|
+
"lands the proposal in the docs tree as written \u2014 its status stays",
|
|
20686
|
+
"`Proposed`. Promotion `Proposed` \u2192 `Accepted` is a separate",
|
|
20687
|
+
"human / governance step performed out of band by a",
|
|
20688
|
+
"decision-maker; it is **not** a merge gate and nothing in the",
|
|
20689
|
+
"review loop flips an ADR to `Accepted`. Routing ADRs to",
|
|
20690
|
+
"`human-required` only piled them up at `review:awaiting-human`",
|
|
20691
|
+
"waiting for a merge decision that was never the human's job \u2014",
|
|
20692
|
+
"the human's job is the later acceptance decision, not the merge.",
|
|
20693
|
+
"",
|
|
20694
|
+
"The `requirements-writer` flow already authors ADRs in",
|
|
20695
|
+
"`Proposed` status (its Decision section reads",
|
|
20696
|
+
'"Pending human review"), so the merged-as-`Proposed` terminal',
|
|
20697
|
+
"state is supplied by the author, not enforced at the merge gate.",
|
|
20698
|
+
"Consumers that genuinely need a human to gate ADR *merges* (not",
|
|
20699
|
+
"just acceptance) cannot re-add the glob via policy config \u2014 the",
|
|
20700
|
+
"`human-required.paths` list is not consumer-configurable today;",
|
|
20701
|
+
"they would apply the `review:human-required` label per-PR or",
|
|
20702
|
+
"fork the bundle.",
|
|
20703
|
+
"",
|
|
19950
20704
|
"The `pr-reviewer` sub-agent records the decided mode, the",
|
|
19951
20705
|
"triggering reason, and the numeric **matched-rule index** (2\u20136",
|
|
19952
20706
|
"for human-required matches; `null` for rule 1 force-auto or",
|
|
@@ -20263,8 +21017,15 @@ function buildPrReviewBundle(policy = resolvePrReviewPolicy()) {
|
|
|
20263
21017
|
"#### Stale-lease reclaim",
|
|
20264
21018
|
"",
|
|
20265
21019
|
"A crashed or never-launched worker must not wedge a PR by holding",
|
|
20266
|
-
"the lease forever
|
|
20267
|
-
"
|
|
21020
|
+
"the lease forever, and a worker that pushes but skips its hand-off",
|
|
21021
|
+
"must not wedge the PR either. The **maintenance sweep** (not a",
|
|
21022
|
+
"reviewer pass) owns reconcile for **both** stuck states \u2014 its",
|
|
21023
|
+
"`check-blocked.sh maintenance` invocation runs the reconcile",
|
|
21024
|
+
"directly and emits a `LEASE_RECONCILE orphaned=<N>",
|
|
21025
|
+
"consumed_uncleared=<M>` summary line. No human is needed to free a",
|
|
21026
|
+
"stuck PR.",
|
|
21027
|
+
"",
|
|
21028
|
+
"**Orphaned lease.** A `review:fixing` lease is **orphaned** when",
|
|
20268
21029
|
"**both** hold:",
|
|
20269
21030
|
"",
|
|
20270
21031
|
"- The PR carries `review:fixing` but **not**",
|
|
@@ -20276,11 +21037,90 @@ function buildPrReviewBundle(policy = resolvePrReviewPolicy()) {
|
|
|
20276
21037
|
"",
|
|
20277
21038
|
"Together these mean a delegation was kicked off, the marker was",
|
|
20278
21039
|
"consumed-or-dropped, but no worker result ever landed \u2014 the lease",
|
|
20279
|
-
"is orphaned. The maintenance sweep
|
|
20280
|
-
"`
|
|
20281
|
-
"
|
|
20282
|
-
"
|
|
20283
|
-
"
|
|
21040
|
+
"is orphaned. The maintenance sweep **re-applies**",
|
|
21041
|
+
"`review:needs-worker` (re-arming the durable work marker so the",
|
|
21042
|
+
"Phase B1 feedback drain retries the delegation) and posts an",
|
|
21043
|
+
"audit-trail note comment. The `review:fixing` lease itself is left",
|
|
21044
|
+
"untouched, so the drain stays idempotent. This is a deliberate",
|
|
21045
|
+
"re-arm for autonomy \u2014 never a silent force-release: the note",
|
|
21046
|
+
"comment is the audit trail proving the re-arm was the sweep's",
|
|
21047
|
+
"doing.",
|
|
21048
|
+
"",
|
|
21049
|
+
"**Consumed-but-uncleared wedge.** The existing orphaned-lease",
|
|
21050
|
+
"precondition (`review:fixing` *without* `review:needs-worker`)",
|
|
21051
|
+
"structurally cannot see a worker that pushed its fix and then",
|
|
21052
|
+
"skipped the hand-off \u2014 the marker is still set. The sweep detects",
|
|
21053
|
+
"this wedge when a PR carries **both** `review:needs-worker` and",
|
|
21054
|
+
"`review:fixing`, its branch HEAD commit is **newer** than the",
|
|
21055
|
+
"fix-list comment, and there is **no** worker-report. It",
|
|
21056
|
+
"auto-reconciles by **removing** `review:needs-worker` (the",
|
|
21057
|
+
"hand-off the worker skipped) and posting an audit-trail reconcile",
|
|
21058
|
+
"note comment, flipping the PR into the lease-without-marker",
|
|
21059
|
+
"confirm-trigger state so the reviewer confirm pass takes over and",
|
|
21060
|
+
"merges. As with the orphaned-lease path, the `review:fixing` lease",
|
|
21061
|
+
"is left for that confirm pass to release.",
|
|
21062
|
+
"",
|
|
21063
|
+
"### Review-Label Invariants (Phase 2.8 reconciliation)",
|
|
21064
|
+
"",
|
|
21065
|
+
"A PR must never carry **mutually-exclusive review-workflow",
|
|
21066
|
+
"labels** after a reviewer pass \u2014 the PR equivalent of the",
|
|
21067
|
+
'"exactly one `status:*`" discipline issues already follow.',
|
|
21068
|
+
"Successive passes layering labels with no reconciler can drive a",
|
|
21069
|
+
"PR into an impossible state (a real PR once held",
|
|
21070
|
+
"`review:awaiting-human` + `status:needs-attention` +",
|
|
21071
|
+
"`review:fixing` + `review:needs-worker` at the same time). The",
|
|
21072
|
+
"reviewer's **Phase 2.8 \u2014 Label Reconciliation** step enforces",
|
|
21073
|
+
"the invariants below early in every pass, after Phase 2.75",
|
|
21074
|
+
"decides the mode and after the confirm-trigger lease detection,",
|
|
21075
|
+
"but before any phase branches on review state. Every correction",
|
|
21076
|
+
"is logged on a `**Label reconciliation:**` line in the sticky",
|
|
21077
|
+
"`## Reviewer notes` comment \u2014 labels are never mutated silently.",
|
|
21078
|
+
"",
|
|
21079
|
+
"**The invariants:**",
|
|
21080
|
+
"",
|
|
21081
|
+
"1. **`review:awaiting-human` is mutually exclusive with the",
|
|
21082
|
+
" fix-delegation labels (`review:needs-worker`,",
|
|
21083
|
+
" `review:fixing`).** A PR is **either** in the fix-delegation",
|
|
21084
|
+
" loop **or** handed to a human \u2014 never both. Any of",
|
|
21085
|
+
" `review:awaiting-human` + `review:needs-worker`,",
|
|
21086
|
+
" `review:awaiting-human` + `review:fixing`, or all three is a",
|
|
21087
|
+
" violation.",
|
|
21088
|
+
"2. **`review:fixing` WITHOUT `review:needs-worker` is the",
|
|
21089
|
+
" confirm-pending state, not a violation.** The worker finished",
|
|
21090
|
+
" and cleared its marker; a confirm pass owns the PR and will",
|
|
21091
|
+
" release the lease. The reconciler must not strip it.",
|
|
21092
|
+
"3. **`review:fixing` WITH `review:needs-worker` is a valid",
|
|
21093
|
+
" in-flight delegation, not a violation.** The work is durably",
|
|
21094
|
+
" queued for a top-level `issue-worker` pass.",
|
|
21095
|
+
"4. **`status:needs-attention` is additive but must not coexist",
|
|
21096
|
+
" with a live, progressing in-flight delegation.** When",
|
|
21097
|
+
" `review:fixing` + `review:needs-worker` are present, the",
|
|
21098
|
+
" fix-list is newer than the flag, and there is no failed-fix",
|
|
21099
|
+
" pushback, the flag contradicts the live progress signal and is",
|
|
21100
|
+
" removed. A flag coexisting with a *stalled* / *failed*",
|
|
21101
|
+
" delegation, an unresolved `thinking_face` pushback, or a",
|
|
21102
|
+
" `human-required` hand-off is legitimate and stays.",
|
|
21103
|
+
"",
|
|
21104
|
+
"(`review:human-required` and `review:auto-ok` are **policy",
|
|
21105
|
+
"inputs** read in Phase 2.75, not workflow-state labels \u2014 the",
|
|
21106
|
+
"reconciler never touches them.)",
|
|
21107
|
+
"",
|
|
21108
|
+
"**Canonical resolution.** The losing label is chosen by the",
|
|
21109
|
+
"Phase 2.75 mode plus the current loop position so the surviving",
|
|
21110
|
+
"set matches the action the pass will take:",
|
|
21111
|
+
"",
|
|
21112
|
+
"| Violation combo | Loop position / mode | Resolution (winner) |",
|
|
21113
|
+
"|-----------------|----------------------|---------------------|",
|
|
21114
|
+
"| `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 |",
|
|
21115
|
+
"| `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 |",
|
|
21116
|
+
"| `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 |",
|
|
21117
|
+
"",
|
|
21118
|
+
"Resolution is **conservative about human intent**: a genuine",
|
|
21119
|
+
"`human-required` pass clears the fix-delegation labels and keeps",
|
|
21120
|
+
"the human-facing label; an `auto-merge` pass with a live",
|
|
21121
|
+
"delegation keeps the delegation labels and clears the stray",
|
|
21122
|
+
"`review:awaiting-human`. The reconciler only ever **removes** a",
|
|
21123
|
+
"contradicting label \u2014 never adds one.",
|
|
20284
21124
|
"",
|
|
20285
21125
|
"### Sticky `## Reviewer notes` Comment",
|
|
20286
21126
|
"",
|
|
@@ -20304,6 +21144,9 @@ function buildPrReviewBundle(policy = resolvePrReviewPolicy()) {
|
|
|
20304
21144
|
" reviewer reaction (`eyes`, open `thinking_face`).",
|
|
20305
21145
|
"- **Pushbacks** \u2014 every unresolved `thinking_face` the reviewer",
|
|
20306
21146
|
" has left, with the reason captured in its pushback reply.",
|
|
21147
|
+
"- **Label reconciliation** \u2014 the Phase 2.8 outcome: `consistent`",
|
|
21148
|
+
" or the corrections applied this pass (violation combo, labels",
|
|
21149
|
+
" removed, resulting self-consistent set), recorded for audit.",
|
|
20307
21150
|
"- **Last pass** \u2014 the ISO 8601 timestamp of the most recent run.",
|
|
20308
21151
|
"",
|
|
20309
21152
|
"The sticky is updated on every pass \u2014 including passes that ended",
|
|
@@ -20327,7 +21170,7 @@ function buildPrReviewBundle(policy = resolvePrReviewPolicy()) {
|
|
|
20327
21170
|
"| `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. |",
|
|
20328
21171
|
"| `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. |",
|
|
20329
21172
|
"| `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). |",
|
|
20330
|
-
"| `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
|
|
21173
|
+
"| `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. |",
|
|
20331
21174
|
"| `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. |",
|
|
20332
21175
|
"",
|
|
20333
21176
|
"### Reviewing Human-Authored PRs: the `--allow-human-author` Flag",
|
|
@@ -30120,13 +30963,13 @@ var VERSION = {
|
|
|
30120
30963
|
/**
|
|
30121
30964
|
* Version of Astro to pin for AstroProject scaffolding.
|
|
30122
30965
|
*/
|
|
30123
|
-
ASTRO_VERSION: "6.4.
|
|
30966
|
+
ASTRO_VERSION: "6.4.7",
|
|
30124
30967
|
/**
|
|
30125
30968
|
* CDK CLI for workflows and command line operations.
|
|
30126
30969
|
*
|
|
30127
30970
|
* CLI and lib are versioned separately, so this is the CLI version.
|
|
30128
30971
|
*/
|
|
30129
|
-
AWS_CDK_CLI_VERSION: "2.
|
|
30972
|
+
AWS_CDK_CLI_VERSION: "2.1127.0",
|
|
30130
30973
|
/**
|
|
30131
30974
|
* CDK Version to use for construct projects.
|
|
30132
30975
|
*
|