@codedrifters/configulator 0.0.221 → 0.0.223
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.js +559 -18
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +559 -18
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
package/lib/index.mjs
CHANGED
|
@@ -5362,7 +5362,7 @@ var prReviewerSubAgent = {
|
|
|
5362
5362
|
"## Phase 2: Gather Context",
|
|
5363
5363
|
"",
|
|
5364
5364
|
"```bash",
|
|
5365
|
-
"gh pr view <pr-number> --json number,title,body,headRefName,baseRefName,isDraft,state,labels,reviews",
|
|
5365
|
+
"gh pr view <pr-number> --json number,title,body,headRefName,baseRefName,isDraft,state,labels,reviews,files,additions,deletions",
|
|
5366
5366
|
"gh pr diff <pr-number>",
|
|
5367
5367
|
"gh pr checks <pr-number>",
|
|
5368
5368
|
"```",
|
|
@@ -5370,12 +5370,159 @@ var prReviewerSubAgent = {
|
|
|
5370
5370
|
"Extract the linked issue number from the PR body using the closing keywords",
|
|
5371
5371
|
"(`Closes #N`, `Fixes #N`, or `Resolves #N`) identified in Phase 1.5.",
|
|
5372
5372
|
"",
|
|
5373
|
-
"Then fetch the linked issue
|
|
5373
|
+
"Then fetch the linked issue, including its `issueType` so Phase 2.75 can",
|
|
5374
|
+
"evaluate the issue-type portion of the review policy:",
|
|
5374
5375
|
"",
|
|
5375
5376
|
"```bash",
|
|
5376
|
-
"gh issue view <issue-number>",
|
|
5377
|
+
"gh issue view <issue-number> --json number,title,body,labels,state,issueType",
|
|
5377
5378
|
"```",
|
|
5378
5379
|
"",
|
|
5380
|
+
"## Phase 2.5: Gather Comments",
|
|
5381
|
+
"",
|
|
5382
|
+
"Before deciding review mode, collect every human comment on the PR so",
|
|
5383
|
+
"that Phase 3.5 can classify each one and Phase 4.5 can render the",
|
|
5384
|
+
"sticky **Reviewer notes** summary. GitHub exposes PR comments across",
|
|
5385
|
+
"three distinct endpoints; the reviewer merges all three into a single",
|
|
5386
|
+
"queue.",
|
|
5387
|
+
"",
|
|
5388
|
+
"### Step 1: Fetch all three comment sources",
|
|
5389
|
+
"",
|
|
5390
|
+
"```bash",
|
|
5391
|
+
"# PR-level issue comments (top-level discussion thread)",
|
|
5392
|
+
"gh pr view <pr-number> --json comments",
|
|
5393
|
+
"",
|
|
5394
|
+
"# Inline code-review comments (line-anchored in the diff)",
|
|
5395
|
+
"gh api repos/{{repository.owner}}/{{repository.name}}/pulls/<pr-number>/comments",
|
|
5396
|
+
"",
|
|
5397
|
+
"# Formal review bodies and their APPROVED / CHANGES_REQUESTED / COMMENTED state",
|
|
5398
|
+
"gh api repos/{{repository.owner}}/{{repository.name}}/pulls/<pr-number>/reviews",
|
|
5399
|
+
"```",
|
|
5400
|
+
"",
|
|
5401
|
+
"For each item, capture: the comment id, author login, body, creation",
|
|
5402
|
+
"time, the URL, and any reactions already present (including which",
|
|
5403
|
+
"reactions the reviewer itself has previously applied). For inline",
|
|
5404
|
+
"review comments, also capture the thread / conversation resolution",
|
|
5405
|
+
"state so Step 2 can drop resolved threads.",
|
|
5406
|
+
"",
|
|
5407
|
+
"### Step 2: Apply filtering rules",
|
|
5408
|
+
"",
|
|
5409
|
+
"Drop a comment from classification when **any** of the following hold:",
|
|
5410
|
+
"",
|
|
5411
|
+
"1. **Reviewer's own comments.** The author login matches the invoking",
|
|
5412
|
+
" agent identity (for example, the bot account used to post prior",
|
|
5413
|
+
" reviewer replies, sticky summaries, or fix-list comments). The",
|
|
5414
|
+
" reviewer never classifies or reacts to its own output.",
|
|
5415
|
+
"2. **Bot authors.** The author login matches `*[bot]` \u2014 CI bots,",
|
|
5416
|
+
" Dependabot, CodeRabbit, GitHub Actions, and similar automation.",
|
|
5417
|
+
"3. **Terminal reviewer reactions already present.** The comment",
|
|
5418
|
+
" already carries a reaction **authored by the reviewer** in the set",
|
|
5419
|
+
" `+1` (accepted), `rocket` (landed), or `-1` (declined as",
|
|
5420
|
+
" out-of-scope). These signal the item has reached a terminal state",
|
|
5421
|
+
" on a previous pass and requires no further action.",
|
|
5422
|
+
"4. **Resolved threads.** Inline comments belonging to a conversation",
|
|
5423
|
+
" that GitHub marks as resolved.",
|
|
5424
|
+
"",
|
|
5425
|
+
"A comment whose only reviewer-authored reaction is `eyes` is **not**",
|
|
5426
|
+
'terminal. `eyes` means "seen on a previous pass but not yet resolved"',
|
|
5427
|
+
"\u2014 keep it in the queue so Phase 3.5 can re-evaluate and possibly",
|
|
5428
|
+
"promote it to a terminal state once the corresponding action",
|
|
5429
|
+
"completes.",
|
|
5430
|
+
"",
|
|
5431
|
+
"A comment whose only reviewer-authored reaction is `thinking_face` is",
|
|
5432
|
+
"also **not** terminal \u2014 it indicates an open dispute the reviewer",
|
|
5433
|
+
"raised on a prior pass that has not yet been resolved by the human.",
|
|
5434
|
+
"Phase 4 uses the presence of unresolved `thinking_face` reactions as",
|
|
5435
|
+
"the pushback gate.",
|
|
5436
|
+
"",
|
|
5437
|
+
"### Step 3: Record the gathered set",
|
|
5438
|
+
"",
|
|
5439
|
+
"Persist the filtered comment list in memory for Phase 3.5 and Phase",
|
|
5440
|
+
"4.5. For each surviving comment record at minimum:",
|
|
5441
|
+
"",
|
|
5442
|
+
"```",
|
|
5443
|
+
"- id: <comment or review id>",
|
|
5444
|
+
" source: <pr-comment | inline-comment | review-body>",
|
|
5445
|
+
" author: <login>",
|
|
5446
|
+
" url: <html_url>",
|
|
5447
|
+
" body: <text>",
|
|
5448
|
+
" reactions: <list of reactions with authors>",
|
|
5449
|
+
"```",
|
|
5450
|
+
"",
|
|
5451
|
+
"If there are no unhandled comments after filtering, record that fact",
|
|
5452
|
+
"and proceed \u2014 Phase 3.5 will short-circuit, and the Phase 4.5 sticky",
|
|
5453
|
+
"summary will simply list no outstanding items.",
|
|
5454
|
+
"",
|
|
5455
|
+
"## Phase 2.75: Determine Review Mode",
|
|
5456
|
+
"",
|
|
5457
|
+
"Before comparing the diff to the acceptance criteria, evaluate the PR",
|
|
5458
|
+
"against the **PR Review Policy** embedded in this repository's",
|
|
5459
|
+
"`CLAUDE.md` (rendered from the `pr-review-policy` rule). The decision",
|
|
5460
|
+
"here governs whether Phase 4 enables auto-merge or hands off to a",
|
|
5461
|
+
"human reviewer.",
|
|
5462
|
+
"",
|
|
5463
|
+
"### Step 1: Load the policy",
|
|
5464
|
+
"",
|
|
5465
|
+
"Read `CLAUDE.md` from the repo root and extract the fenced YAML block",
|
|
5466
|
+
"under the `## PR Review Policy` heading. Parse the block into an",
|
|
5467
|
+
"in-memory object with the following top-level fields: `version`,",
|
|
5468
|
+
"`default`, `human-required`, `auto-merge`.",
|
|
5469
|
+
"",
|
|
5470
|
+
"If the policy section is missing or unparseable, fall back to",
|
|
5471
|
+
"`mode = human-required` with `reason = 'policy missing or unreadable'`",
|
|
5472
|
+
"and skip to Step 3. Do **not** auto-merge when the policy is absent.",
|
|
5473
|
+
"",
|
|
5474
|
+
"### Step 2: Evaluate in precedence order",
|
|
5475
|
+
"",
|
|
5476
|
+
"Walk the following checks in order. The **first match wins** and fixes",
|
|
5477
|
+
"the mode; record the triggering condition as the `reason`. Mixed-match",
|
|
5478
|
+
"PRs (signals from both sides) resolve conservatively to",
|
|
5479
|
+
"`human-required` \u2014 force-auto only wins when it is the single highest",
|
|
5480
|
+
"match and no later human-required signal changes the outcome under",
|
|
5481
|
+
"step 2c.",
|
|
5482
|
+
"",
|
|
5483
|
+
"1. **Force-auto label** \u2014 if the PR carries any label listed under",
|
|
5484
|
+
" `auto-merge.labels-that-force-auto` (e.g. `review:auto-ok`), set",
|
|
5485
|
+
" `mode = auto-merge`.",
|
|
5486
|
+
"2. **Force-human label (reserved)** \u2014 if the PR carries a",
|
|
5487
|
+
" `review:human-required` label, set `mode = human-required`.",
|
|
5488
|
+
"3. **Labels that force human** \u2014 if the PR carries any label listed",
|
|
5489
|
+
" under `human-required.labels-that-force-human` (e.g.",
|
|
5490
|
+
" `priority:critical`), set `mode = human-required`.",
|
|
5491
|
+
"4. **Path globs** \u2014 if any file in the PR diff matches any glob in",
|
|
5492
|
+
" `human-required.paths`, set `mode = human-required`. Record the",
|
|
5493
|
+
" first matching path + glob pair as the reason.",
|
|
5494
|
+
"5. **Issue type** \u2014 if the linked issue's GitHub issue type",
|
|
5495
|
+
" (fetched in Phase 2) matches any entry in",
|
|
5496
|
+
" `human-required.issue-types` (case-insensitive), set",
|
|
5497
|
+
" `mode = human-required`.",
|
|
5498
|
+
"6. **Size thresholds** \u2014 if the PR exceeds either threshold under",
|
|
5499
|
+
" `human-required.size` (`files` count or `insertions` count), set",
|
|
5500
|
+
" `mode = human-required`.",
|
|
5501
|
+
"7. **Default** \u2014 if no rule above matched, apply the `default` field",
|
|
5502
|
+
" from the policy (typically `auto-merge`).",
|
|
5503
|
+
"",
|
|
5504
|
+
"#### Mixed-match resolution",
|
|
5505
|
+
"",
|
|
5506
|
+
"Apart from rule (1), which is an explicit opt-in and wins outright,",
|
|
5507
|
+
"**any** match from rules (2) through (6) forces `human-required` even",
|
|
5508
|
+
"if a non-force-auto signal would otherwise have allowed auto-merge.",
|
|
5509
|
+
"The conservative choice wins. Rule (1) is the sole escape hatch and",
|
|
5510
|
+
"requires a maintainer to have applied the force-auto label.",
|
|
5511
|
+
"",
|
|
5512
|
+
"### Step 3: Record the decision",
|
|
5513
|
+
"",
|
|
5514
|
+
"Persist the evaluated mode and reason for later phases so Phase 4 and",
|
|
5515
|
+
"any downstream summary writer can cite it:",
|
|
5516
|
+
"",
|
|
5517
|
+
"```",
|
|
5518
|
+
"Review mode: <auto-merge | human-required>",
|
|
5519
|
+
"Reason: <short explanation \u2014 label name, path+glob, issue type, size threshold, default>",
|
|
5520
|
+
"```",
|
|
5521
|
+
"",
|
|
5522
|
+
"Phases 3 (acceptance-criteria comparison) and CI verification run",
|
|
5523
|
+
"unchanged regardless of mode. Only the terminal action in Phase 4",
|
|
5524
|
+
"branches on the decided mode.",
|
|
5525
|
+
"",
|
|
5379
5526
|
"## Phase 3: Compare Diff to Acceptance Criteria",
|
|
5380
5527
|
"",
|
|
5381
5528
|
"Read the issue body for an **Acceptance Criteria** (or equivalent) section.",
|
|
@@ -5393,10 +5540,181 @@ var prReviewerSubAgent = {
|
|
|
5393
5540
|
"- **CI status** \u2014 `gh pr checks` reports all required checks passing",
|
|
5394
5541
|
"- **Scope creep** \u2014 diff stays within the issue's stated scope",
|
|
5395
5542
|
"",
|
|
5543
|
+
"## Phase 3.5: Classify Comments",
|
|
5544
|
+
"",
|
|
5545
|
+
"For every comment that survived Phase 2.5 filtering, assign exactly",
|
|
5546
|
+
"one classification and take the corresponding action. The reviewer",
|
|
5547
|
+
"acts only on unhandled comments; anything already in a terminal state",
|
|
5548
|
+
"was dropped in Phase 2.5 and is left alone.",
|
|
5549
|
+
"",
|
|
5550
|
+
"### Classifications",
|
|
5551
|
+
"",
|
|
5552
|
+
"#### `in-scope`",
|
|
5553
|
+
"",
|
|
5554
|
+
"The comment requests a change that falls **inside** the linked",
|
|
5555
|
+
"issue's acceptance criteria (or is an obvious defect in code the PR",
|
|
5556
|
+
"itself introduced).",
|
|
5557
|
+
"",
|
|
5558
|
+
"Action on this pass:",
|
|
5559
|
+
"",
|
|
5560
|
+
"- React `eyes` on the comment to mark it seen.",
|
|
5561
|
+
"- Queue the comment for later delegation. **Delegation wiring is out",
|
|
5562
|
+
" of scope for this phase** \u2014 the fix-list comment and the",
|
|
5563
|
+
" issue-worker hand-off land in a follow-up issue. For now, record",
|
|
5564
|
+
" the queued items in memory so Phase 4.5 can list them as",
|
|
5565
|
+
" outstanding.",
|
|
5566
|
+
"- Do **not** apply `+1` or `rocket` yet. Those are terminal",
|
|
5567
|
+
" reactions reserved for later passes once the fix has been accepted",
|
|
5568
|
+
" into the PR (`+1`) and actually landed on the branch (`rocket`).",
|
|
5569
|
+
"",
|
|
5570
|
+
"```bash",
|
|
5571
|
+
"# React eyes on a PR-level issue comment",
|
|
5572
|
+
"gh api repos/{{repository.owner}}/{{repository.name}}/issues/comments/<comment-id>/reactions \\",
|
|
5573
|
+
" -X POST -f content=eyes",
|
|
5574
|
+
"",
|
|
5575
|
+
"# React eyes on an inline code-review comment",
|
|
5576
|
+
"gh api repos/{{repository.owner}}/{{repository.name}}/pulls/comments/<comment-id>/reactions \\",
|
|
5577
|
+
" -X POST -f content=eyes",
|
|
5578
|
+
"```",
|
|
5579
|
+
"",
|
|
5580
|
+
"#### `out-of-scope`",
|
|
5581
|
+
"",
|
|
5582
|
+
"The comment requests work that falls **outside** the linked issue's",
|
|
5583
|
+
"acceptance criteria \u2014 new functionality, a refactor that would",
|
|
5584
|
+
"expand the diff, a cleanup in a neighbouring module, and so on. It",
|
|
5585
|
+
"is a legitimate request, just not for this PR.",
|
|
5586
|
+
"",
|
|
5587
|
+
"Action:",
|
|
5588
|
+
"",
|
|
5589
|
+
"1. Create a new tracking issue following the `Create Issue Workflow`",
|
|
5590
|
+
" in CLAUDE.md. Derive the title prefix (`feat:`, `fix:`, `chore:`,",
|
|
5591
|
+
" etc.) from the content of the comment. Apply the correct",
|
|
5592
|
+
" `type:*`, `priority:*`, and `status:*` labels and assign the",
|
|
5593
|
+
" GitHub issue type via the documented GraphQL mutation.",
|
|
5594
|
+
"2. Reply to the original comment with a link to the new issue:",
|
|
5595
|
+
" `Tracked separately in #<new-issue>.`",
|
|
5596
|
+
"3. React `-1` on the original comment. `-1` is the terminal",
|
|
5597
|
+
" reaction for out-of-scope and is only applied **after** the new",
|
|
5598
|
+
" issue has been successfully created and the reply posted.",
|
|
5599
|
+
"",
|
|
5600
|
+
"```bash",
|
|
5601
|
+
"# Reply on the same thread",
|
|
5602
|
+
"gh pr comment <pr-number> --body 'Tracked separately in #<new-issue>.'",
|
|
5603
|
+
"",
|
|
5604
|
+
"# React -1 on the original comment once the new issue exists",
|
|
5605
|
+
"gh api repos/{{repository.owner}}/{{repository.name}}/issues/comments/<comment-id>/reactions \\",
|
|
5606
|
+
" -X POST -f content=-1",
|
|
5607
|
+
"```",
|
|
5608
|
+
"",
|
|
5609
|
+
"#### `dispute`",
|
|
5610
|
+
"",
|
|
5611
|
+
"The comment conflicts with an acceptance criterion, a documented",
|
|
5612
|
+
"CLAUDE.md convention, or the project-context doc; or it is ambiguous",
|
|
5613
|
+
"enough that implementation would require guessing at intent. The",
|
|
5614
|
+
"reviewer pushes back rather than silently complying.",
|
|
5615
|
+
"",
|
|
5616
|
+
"Action:",
|
|
5617
|
+
"",
|
|
5618
|
+
"1. React `thinking_face` on the comment to mark it as disputed.",
|
|
5619
|
+
" This reaction is **not** terminal \u2014 it persists until the human",
|
|
5620
|
+
" resolves the dispute.",
|
|
5621
|
+
"2. Post a reply on the same thread explaining the pushback. Cite",
|
|
5622
|
+
" the specific acceptance criterion, convention, or project-context",
|
|
5623
|
+
" section that the comment conflicts with, or name the ambiguity",
|
|
5624
|
+
" that needs resolution.",
|
|
5625
|
+
"3. The presence of an unresolved `thinking_face` reaction by the",
|
|
5626
|
+
" reviewer blocks auto-merge in Phase 4 regardless of the review",
|
|
5627
|
+
" mode decided in Phase 2.75.",
|
|
5628
|
+
"",
|
|
5629
|
+
"```bash",
|
|
5630
|
+
"# React thinking_face on the disputed comment",
|
|
5631
|
+
"gh api repos/{{repository.owner}}/{{repository.name}}/issues/comments/<comment-id>/reactions \\",
|
|
5632
|
+
" -X POST -f content=confused",
|
|
5633
|
+
"",
|
|
5634
|
+
"# Post the pushback reply",
|
|
5635
|
+
"gh pr comment <pr-number> --body '<pushback explanation>'",
|
|
5636
|
+
"```",
|
|
5637
|
+
"",
|
|
5638
|
+
"Note: GitHub's reactions API uses `confused` as the content string",
|
|
5639
|
+
"for the `thinking_face` reaction; use `content=confused` when",
|
|
5640
|
+
"POSTing the reaction.",
|
|
5641
|
+
"",
|
|
5642
|
+
"#### `nit` / `question`",
|
|
5643
|
+
"",
|
|
5644
|
+
"The comment is a minor stylistic preference, a clarifying question",
|
|
5645
|
+
"with a short answer, or a drive-by note that does not request a",
|
|
5646
|
+
"code change.",
|
|
5647
|
+
"",
|
|
5648
|
+
"Action:",
|
|
5649
|
+
"",
|
|
5650
|
+
"- React `eyes` to mark the comment seen.",
|
|
5651
|
+
"- Optionally post a brief reply when the question has a short,",
|
|
5652
|
+
" factual answer. Skip the reply when there is nothing useful to",
|
|
5653
|
+
" add \u2014 an `eyes` reaction alone is sufficient.",
|
|
5654
|
+
"- Never apply `+1`, `rocket`, or `-1` to a `nit` / `question`",
|
|
5655
|
+
" comment; those reactions are reserved for their documented",
|
|
5656
|
+
" terminal meanings.",
|
|
5657
|
+
"",
|
|
5658
|
+
"### Reaction protocol summary",
|
|
5659
|
+
"",
|
|
5660
|
+
"| Reaction | Meaning | Terminal? |",
|
|
5661
|
+
"|----------|---------|-----------|",
|
|
5662
|
+
"| `eyes` | Seen by reviewer; awaiting further action | No |",
|
|
5663
|
+
"| `thinking_face` (`confused`) | Reviewer disputes this comment | No |",
|
|
5664
|
+
"| `+1` | Reviewer accepts the comment's request | **Yes** |",
|
|
5665
|
+
"| `rocket` | The accepted change has landed on the branch | **Yes** |",
|
|
5666
|
+
"| `-1` | Reviewer declined as out-of-scope; tracked in a new issue | **Yes** |",
|
|
5667
|
+
"",
|
|
5668
|
+
"Terminal reactions (`+1`, `rocket`, `-1`) **must only be applied**",
|
|
5669
|
+
"when the corresponding action is truly complete:",
|
|
5670
|
+
"",
|
|
5671
|
+
"- `+1` \u2014 only after the reviewer has confirmed the comment's",
|
|
5672
|
+
" request is in-scope and the fix has been accepted for this PR.",
|
|
5673
|
+
"- `rocket` \u2014 only after the accepted fix has actually landed on the",
|
|
5674
|
+
" PR's branch (a commit addressing the comment is present).",
|
|
5675
|
+
"- `-1` \u2014 only after a new tracking issue has been successfully",
|
|
5676
|
+
" created for the out-of-scope request and the reply linking to it",
|
|
5677
|
+
" has been posted.",
|
|
5678
|
+
"",
|
|
5679
|
+
"Never pre-emptively apply a terminal reaction. Applying one signals",
|
|
5680
|
+
"to humans and to future reviewer passes that the item is closed;",
|
|
5681
|
+
"applying it early creates a false record of completion.",
|
|
5682
|
+
"",
|
|
5396
5683
|
"## Phase 4: Decide and Act",
|
|
5397
5684
|
"",
|
|
5685
|
+
"### Pushback gate (runs before every merge decision)",
|
|
5686
|
+
"",
|
|
5687
|
+
"Before taking any merge-enabling action in this phase, verify that no",
|
|
5688
|
+
"**unresolved `thinking_face` reactions by the reviewer** remain on",
|
|
5689
|
+
"any comment gathered in Phase 2.5.",
|
|
5690
|
+
"",
|
|
5691
|
+
"A `thinking_face` reaction is considered **unresolved** when:",
|
|
5692
|
+
"",
|
|
5693
|
+
"- The reviewer applied it on this pass or a prior pass, and",
|
|
5694
|
+
"- The underlying comment has not since received a resolution signal",
|
|
5695
|
+
" from the human \u2014 for example, the comment has not been withdrawn,",
|
|
5696
|
+
" the human has not posted a clarifying reply that the reviewer has",
|
|
5697
|
+
" since marked `+1`, and no `review:auto-ok` label has been applied",
|
|
5698
|
+
" to the PR as an explicit override.",
|
|
5699
|
+
"",
|
|
5700
|
+
"If any unresolved `thinking_face` reaction exists, **do not enable",
|
|
5701
|
+
"auto-merge** and **do not apply `review:awaiting-human` as a success",
|
|
5702
|
+
"hand-off**. This gate fires regardless of the review mode decided in",
|
|
5703
|
+
"Phase 2.75 \u2014 pushback blocks the merge pathway even when the mode is",
|
|
5704
|
+
"`auto-merge`. Skip straight to Phase 4.5 to update the sticky summary",
|
|
5705
|
+
"with the outstanding pushbacks, then stop. A downstream issue",
|
|
5706
|
+
"refines this gate further; for now, pushback simply blocks the",
|
|
5707
|
+
"merge pathway.",
|
|
5708
|
+
"",
|
|
5709
|
+
"If no unresolved `thinking_face` reactions exist, proceed with the",
|
|
5710
|
+
"branches below based on the review mode decided in Phase 2.75.",
|
|
5711
|
+
"",
|
|
5398
5712
|
"### If all acceptance criteria are met and CI is green",
|
|
5399
5713
|
"",
|
|
5714
|
+
"Branch on the **review mode** decided in Phase 2.75:",
|
|
5715
|
+
"",
|
|
5716
|
+
"#### Mode `auto-merge`",
|
|
5717
|
+
"",
|
|
5400
5718
|
"Enable squash auto-merge with branch deletion. This queues the merge to",
|
|
5401
5719
|
"happen once required checks pass; no separate approval review is needed.",
|
|
5402
5720
|
"",
|
|
@@ -5410,6 +5728,27 @@ var prReviewerSubAgent = {
|
|
|
5410
5728
|
"`feat(scope): description`). The body should bullet the changes and end",
|
|
5411
5729
|
"with `Closes #<issue-number>`.",
|
|
5412
5730
|
"",
|
|
5731
|
+
"#### Mode `human-required`",
|
|
5732
|
+
"",
|
|
5733
|
+
"Do **not** run `gh pr merge --auto`. Instead, hand the PR off to a",
|
|
5734
|
+
"human reviewer:",
|
|
5735
|
+
"",
|
|
5736
|
+
"1. Apply the `review:awaiting-human` label so the PR is discoverable",
|
|
5737
|
+
" in the human-review queue:",
|
|
5738
|
+
"",
|
|
5739
|
+
" ```bash",
|
|
5740
|
+
" gh pr edit <pr-number> --add-label 'review:awaiting-human'",
|
|
5741
|
+
" ```",
|
|
5742
|
+
"",
|
|
5743
|
+
"2. Exit cleanly after the acceptance-criteria check completes and any",
|
|
5744
|
+
" summary comment the reviewer posts. Proceed to Phase 5 only if a",
|
|
5745
|
+
" merge occurred \u2014 in `human-required` mode the reviewer stops at",
|
|
5746
|
+
" the hand-off and does not poll for merge.",
|
|
5747
|
+
"",
|
|
5748
|
+
"The reason captured in Phase 2.75 should be included in any summary",
|
|
5749
|
+
"comment so maintainers know why human review was required (path hit,",
|
|
5750
|
+
"issue type, size threshold, label, or default).",
|
|
5751
|
+
"",
|
|
5413
5752
|
"### If any criterion is missing, partial, or CI is failing",
|
|
5414
5753
|
"",
|
|
5415
5754
|
"Post a plain comment (not a formal review block) with grouped findings:",
|
|
@@ -5427,10 +5766,90 @@ var prReviewerSubAgent = {
|
|
|
5427
5766
|
"--request-changes`: it is lighter-weight, doesn't require the author to",
|
|
5428
5767
|
"dismiss a formal review, and composes cleanly with the multi-PR loop.",
|
|
5429
5768
|
"",
|
|
5769
|
+
"## Phase 4.5: Update Sticky Summary",
|
|
5770
|
+
"",
|
|
5771
|
+
"On **every pass**, create or update a single **`## Reviewer notes`**",
|
|
5772
|
+
"comment on the PR. This sticky comment is the human-facing single",
|
|
5773
|
+
"source of truth for the PR's state \u2014 one comment per PR, edited in",
|
|
5774
|
+
"place across passes, never duplicated. Do not post a fresh",
|
|
5775
|
+
'"pass N summary" on each iteration.',
|
|
5776
|
+
"",
|
|
5777
|
+
"### Step 1: Find the existing sticky comment (if any)",
|
|
5778
|
+
"",
|
|
5779
|
+
"List PR-level comments and look for one authored by the reviewer",
|
|
5780
|
+
"whose body starts with `## Reviewer notes`:",
|
|
5781
|
+
"",
|
|
5782
|
+
"```bash",
|
|
5783
|
+
"gh api repos/{{repository.owner}}/{{repository.name}}/issues/<pr-number>/comments",
|
|
5784
|
+
"```",
|
|
5785
|
+
"",
|
|
5786
|
+
"If multiple candidates exist (an older run double-posted before this",
|
|
5787
|
+
"phase existed), keep the earliest and plan to delete the duplicates",
|
|
5788
|
+
"on a later pass. Never delete another author's comment.",
|
|
5789
|
+
"",
|
|
5790
|
+
"### Step 2: Compose the sticky body",
|
|
5791
|
+
"",
|
|
5792
|
+
"The body uses the following shape:",
|
|
5793
|
+
"",
|
|
5794
|
+
"```",
|
|
5795
|
+
"## Reviewer notes",
|
|
5796
|
+
"",
|
|
5797
|
+
"**Mode:** auto-merge | human-required \u2014 <reason from Phase 2.75>",
|
|
5798
|
+
"**AC status:** <met / partial / missing> (evidence links)",
|
|
5799
|
+
"**CI status:** green | pending | red",
|
|
5800
|
+
"**Outstanding:** <list of comments still open with their classification and author>",
|
|
5801
|
+
"**Pushbacks:** <list of disputes with reasons>",
|
|
5802
|
+
"**Last pass:** <ISO timestamp>",
|
|
5803
|
+
"```",
|
|
5804
|
+
"",
|
|
5805
|
+
"Populate each field from the phases above:",
|
|
5806
|
+
"",
|
|
5807
|
+
"- **Mode / reason** \u2014 the mode and reason recorded in Phase 2.75.",
|
|
5808
|
+
"- **AC status** \u2014 the checklist produced in Phase 3 (met, partial,",
|
|
5809
|
+
" or missing), with links to the files or tests that provide the",
|
|
5810
|
+
" evidence.",
|
|
5811
|
+
"- **CI status** \u2014 derived from `gh pr checks`.",
|
|
5812
|
+
"- **Outstanding** \u2014 the comments still carrying a non-terminal",
|
|
5813
|
+
" reviewer reaction from Phase 3.5 (typically `eyes` for queued",
|
|
5814
|
+
" in-scope items and `nit` / `question` items that remain open).",
|
|
5815
|
+
" List each as `<classification>: <author> \u2014 <short summary> (<url>)`.",
|
|
5816
|
+
"- **Pushbacks** \u2014 every comment the reviewer reacted",
|
|
5817
|
+
" `thinking_face` to on this or any prior pass, with the reason",
|
|
5818
|
+
" captured in the pushback reply. Empty list when there are none.",
|
|
5819
|
+
"- **Last pass** \u2014 the ISO 8601 timestamp of this run.",
|
|
5820
|
+
"",
|
|
5821
|
+
"### Step 3: Create or edit in place",
|
|
5822
|
+
"",
|
|
5823
|
+
"If no existing sticky comment was found in Step 1, create one:",
|
|
5824
|
+
"",
|
|
5825
|
+
"```bash",
|
|
5826
|
+
"gh pr comment <pr-number> --body '<sticky body>'",
|
|
5827
|
+
"```",
|
|
5828
|
+
"",
|
|
5829
|
+
"If an existing sticky comment was found, edit it in place using the",
|
|
5830
|
+
"comment id. Do not delete and re-create \u2014 editing preserves the",
|
|
5831
|
+
"comment's URL and any reactions humans have added to the summary:",
|
|
5832
|
+
"",
|
|
5833
|
+
"```bash",
|
|
5834
|
+
"gh api repos/{{repository.owner}}/{{repository.name}}/issues/comments/<sticky-comment-id> \\",
|
|
5835
|
+
" -X PATCH -f body='<sticky body>'",
|
|
5836
|
+
"```",
|
|
5837
|
+
"",
|
|
5838
|
+
"The sticky summary must be updated on every pass through Phase 4.5,",
|
|
5839
|
+
"including passes that ended in a pushback-gated skip, a",
|
|
5840
|
+
"`NEEDS_CHANGES` findings comment, or the `human-required` hand-off.",
|
|
5841
|
+
"Humans rely on the sticky comment to see the current state of the",
|
|
5842
|
+
"PR at a glance \u2014 it must never go stale while the reviewer is",
|
|
5843
|
+
"actively processing the PR.",
|
|
5844
|
+
"",
|
|
5430
5845
|
"## Phase 5: Branch Cleanup and Issue Closure Verification",
|
|
5431
5846
|
"",
|
|
5432
|
-
"
|
|
5433
|
-
"
|
|
5847
|
+
"Skip this phase entirely when the review mode from Phase 2.75 is",
|
|
5848
|
+
"`human-required` \u2014 no merge was initiated, so there is nothing to poll",
|
|
5849
|
+
"and no branch to clean up. Report the hand-off and stop.",
|
|
5850
|
+
"",
|
|
5851
|
+
"In `auto-merge` mode, auto-merge may not be immediate. Poll the PR",
|
|
5852
|
+
"state up to 10 times, waiting 30 seconds between polls:",
|
|
5434
5853
|
"",
|
|
5435
5854
|
"```bash",
|
|
5436
5855
|
"gh pr view <pr-number> --json state --jq '.state'",
|
|
@@ -5473,7 +5892,9 @@ var prReviewerSubAgent = {
|
|
|
5473
5892
|
"```",
|
|
5474
5893
|
"PR #<number> \u2014 <title>",
|
|
5475
5894
|
"Linked issue: #<issue-number>",
|
|
5476
|
-
"
|
|
5895
|
+
"Review mode: <auto-merge | human-required>",
|
|
5896
|
+
"Reason: <short explanation from Phase 2.75>",
|
|
5897
|
+
"Verdict: AUTO_MERGE_ENABLED | AWAITING_HUMAN | NEEDS_CHANGES | INELIGIBLE | BLOCKED",
|
|
5477
5898
|
"",
|
|
5478
5899
|
"Acceptance criteria:",
|
|
5479
5900
|
" [x] <criterion> \u2014 <evidence>",
|
|
@@ -5485,7 +5906,7 @@ var prReviewerSubAgent = {
|
|
|
5485
5906
|
" - Suggested: <items>",
|
|
5486
5907
|
" - Nitpick: <items>",
|
|
5487
5908
|
"",
|
|
5488
|
-
"Action taken: <enable-auto-merge | commented-on-the-pr | none>",
|
|
5909
|
+
"Action taken: <enable-auto-merge | label-awaiting-human | commented-on-the-pr | none>",
|
|
5489
5910
|
"Branch state: <merged | open | closed>",
|
|
5490
5911
|
"Issue state: <closed | open>",
|
|
5491
5912
|
"```",
|
|
@@ -5503,15 +5924,47 @@ var prReviewerSubAgent = {
|
|
|
5503
5924
|
" block on red checks.",
|
|
5504
5925
|
"4. **Never bypass review conventions.** Always use `--squash`, `--auto`,",
|
|
5505
5926
|
" and `--delete-branch` for merges. Do not force-merge.",
|
|
5506
|
-
"5. **
|
|
5927
|
+
"5. **Never auto-merge a `human-required` PR.** When Phase 2.75 resolves",
|
|
5928
|
+
" to `human-required`, Phase 4 applies `review:awaiting-human` and",
|
|
5929
|
+
" exits. Even if every acceptance criterion is met and CI is green,",
|
|
5930
|
+
" `gh pr merge --auto` is forbidden in that mode.",
|
|
5931
|
+
"6. **Do not implement code.** You review, decide, and orchestrate. If",
|
|
5507
5932
|
" the PR needs changes, comment and stop.",
|
|
5508
|
-
"
|
|
5933
|
+
"7. **Never push commits to the PR's branch.** If the PR needs changes,",
|
|
5509
5934
|
" comment and stop \u2014 do not attempt to fix it yourself. The PR author",
|
|
5510
5935
|
" owns the branch; pushing to someone else's branch is out of scope.",
|
|
5511
|
-
"
|
|
5936
|
+
"8. **In loop mode (`/review-prs`), never stop early.** If any review",
|
|
5512
5937
|
" fails, comment and move to the next PR. Only abort the loop on a",
|
|
5513
5938
|
" fatal error (e.g. `gh` auth failure, network outage).",
|
|
5514
|
-
"
|
|
5939
|
+
"9. **Follow CLAUDE.md conventions** for all `git` and `gh` operations.",
|
|
5940
|
+
"10. **Follow the reaction protocol.** Use `eyes` to mark a comment",
|
|
5941
|
+
" seen, `thinking_face` (`confused`) to dispute it, `+1` to accept",
|
|
5942
|
+
" its request, `rocket` when the accepted change has landed, and",
|
|
5943
|
+
" `-1` when the request is out-of-scope and has been tracked in a",
|
|
5944
|
+
" new issue. Apply reactions on the same comment endpoint the",
|
|
5945
|
+
" comment came from (`issues/comments/...` for PR-level, ",
|
|
5946
|
+
" `pulls/comments/...` for inline).",
|
|
5947
|
+
"11. **Terminal reactions require completed actions.** `+1`, `rocket`,",
|
|
5948
|
+
" and `-1` must only be applied once the corresponding action is",
|
|
5949
|
+
" truly complete (respectively: the fix accepted, the fix landed,",
|
|
5950
|
+
" or the new out-of-scope issue created and linked in a reply).",
|
|
5951
|
+
" Never apply a terminal reaction pre-emptively; doing so falsely",
|
|
5952
|
+
" signals to humans and to future reviewer passes that the item",
|
|
5953
|
+
" is closed.",
|
|
5954
|
+
"12. **Maintain one sticky `## Reviewer notes` comment per PR.** On",
|
|
5955
|
+
" each pass, find the existing sticky comment authored by the",
|
|
5956
|
+
" reviewer and edit it in place with `gh api ... -X PATCH`;",
|
|
5957
|
+
" create it only when none exists. Never post per-pass summary",
|
|
5958
|
+
" comments alongside the sticky \u2014 the sticky is the single",
|
|
5959
|
+
" human-facing source of truth for PR state.",
|
|
5960
|
+
"13. **Pushback blocks auto-merge.** Any unresolved `thinking_face`",
|
|
5961
|
+
" reaction authored by the reviewer on any comment must prevent",
|
|
5962
|
+
" Phase 4 from enabling auto-merge, regardless of the review mode",
|
|
5963
|
+
" decided in Phase 2.75. The gate clears only when the human has",
|
|
5964
|
+
" resolved the dispute \u2014 by withdrawing the comment, by replying",
|
|
5965
|
+
" in a way that satisfies the reviewer (who then replaces the",
|
|
5966
|
+
" `thinking_face` with `+1`), or by applying the `review:auto-ok`",
|
|
5967
|
+
" label as an explicit override."
|
|
5515
5968
|
].join("\n")
|
|
5516
5969
|
};
|
|
5517
5970
|
var reviewPrSkill = {
|
|
@@ -5679,6 +6132,88 @@ var prReviewBundle = {
|
|
|
5679
6132
|
// still exclude it explicitly via `excludeBundles` if desired.
|
|
5680
6133
|
appliesWhen: () => true,
|
|
5681
6134
|
rules: [
|
|
6135
|
+
{
|
|
6136
|
+
name: "pr-review-policy",
|
|
6137
|
+
description: "Declarative policy that tells the pr-reviewer which PRs may auto-merge and which must wait for a human reviewer",
|
|
6138
|
+
scope: AGENT_RULE_SCOPE.ALWAYS,
|
|
6139
|
+
content: [
|
|
6140
|
+
"# PR Review Policy",
|
|
6141
|
+
"",
|
|
6142
|
+
"The `pr-reviewer` sub-agent evaluates every PR it reviews against the",
|
|
6143
|
+
"policy below and routes the PR into one of two modes:",
|
|
6144
|
+
"",
|
|
6145
|
+
"- **`auto-merge`** \u2014 the reviewer may enable squash auto-merge once",
|
|
6146
|
+
" all acceptance criteria are met and CI is green.",
|
|
6147
|
+
"- **`human-required`** \u2014 the reviewer runs the full AC/CI check but",
|
|
6148
|
+
" never calls `gh pr merge --auto`. It applies the",
|
|
6149
|
+
" `review:awaiting-human` label and hands off to a human reviewer.",
|
|
6150
|
+
"",
|
|
6151
|
+
"## Policy",
|
|
6152
|
+
"",
|
|
6153
|
+
"```yaml",
|
|
6154
|
+
"version: 1",
|
|
6155
|
+
"default: auto-merge",
|
|
6156
|
+
"",
|
|
6157
|
+
"human-required:",
|
|
6158
|
+
" paths:",
|
|
6159
|
+
' - "docs/adrs/**"',
|
|
6160
|
+
' - "docs/project-context.md"',
|
|
6161
|
+
' - ".github/workflows/**"',
|
|
6162
|
+
' - ".github/CODEOWNERS"',
|
|
6163
|
+
' - ".projenrc.ts"',
|
|
6164
|
+
' - "projenrc/**"',
|
|
6165
|
+
' - "CLAUDE.md"',
|
|
6166
|
+
' - ".claude/**"',
|
|
6167
|
+
' - "packages/**/package.json"',
|
|
6168
|
+
" issue-types:",
|
|
6169
|
+
" - release",
|
|
6170
|
+
" - hotfix",
|
|
6171
|
+
" size:",
|
|
6172
|
+
" files: 10",
|
|
6173
|
+
" insertions: 500",
|
|
6174
|
+
" labels-that-force-human:",
|
|
6175
|
+
' - "review:human-required"',
|
|
6176
|
+
' - "priority:critical"',
|
|
6177
|
+
"",
|
|
6178
|
+
"auto-merge:",
|
|
6179
|
+
" labels-that-force-auto:",
|
|
6180
|
+
' - "review:auto-ok"',
|
|
6181
|
+
"```",
|
|
6182
|
+
"",
|
|
6183
|
+
"## Precedence",
|
|
6184
|
+
"",
|
|
6185
|
+
"The reviewer walks the following checks in order. The **first match**",
|
|
6186
|
+
"fixes the mode; any mixed-match PR (signals from both sides) resolves",
|
|
6187
|
+
"conservatively to `human-required` \u2014 `auto-merge` only wins when the",
|
|
6188
|
+
"force-auto label is the single top-priority match.",
|
|
6189
|
+
"",
|
|
6190
|
+
"1. **`auto-merge.labels-that-force-auto`** \u2014 if the PR carries any of",
|
|
6191
|
+
" these labels (e.g. `review:auto-ok`), the mode is `auto-merge`",
|
|
6192
|
+
" outright. This is the only escape hatch from the conservative",
|
|
6193
|
+
" default; it requires a maintainer to apply the label explicitly.",
|
|
6194
|
+
"2. **`review:human-required` label** \u2014 reserved force-human label;",
|
|
6195
|
+
" if present (and no force-auto label beat it in step 1), the mode",
|
|
6196
|
+
" is `human-required`.",
|
|
6197
|
+
"3. **`human-required.labels-that-force-human`** \u2014 any listed label on",
|
|
6198
|
+
" the PR (e.g. `priority:critical`) forces `human-required`.",
|
|
6199
|
+
"4. **`human-required.paths`** \u2014 if any file in the PR diff matches",
|
|
6200
|
+
" any glob here, the mode is `human-required`. Matching uses",
|
|
6201
|
+
" standard glob semantics (`**` for recursive directories,",
|
|
6202
|
+
" `*` for a single path segment).",
|
|
6203
|
+
"5. **`human-required.issue-types`** \u2014 if the linked issue's GitHub",
|
|
6204
|
+
" issue type matches any entry (case-insensitive), the mode is",
|
|
6205
|
+
" `human-required`.",
|
|
6206
|
+
"6. **`human-required.size`** \u2014 if the PR exceeds either the `files`",
|
|
6207
|
+
" count or the `insertions` count, the mode is `human-required`.",
|
|
6208
|
+
"7. **`default`** \u2014 applied only when no rule above matched",
|
|
6209
|
+
" (normally `auto-merge`).",
|
|
6210
|
+
"",
|
|
6211
|
+
"The `pr-reviewer` sub-agent records the decided mode and the triggering",
|
|
6212
|
+
"reason in its Phase 2.75 output so downstream phases and any sticky",
|
|
6213
|
+
"summary can cite the specific rule that applied."
|
|
6214
|
+
].join("\n"),
|
|
6215
|
+
tags: ["policy", "review"]
|
|
6216
|
+
},
|
|
5682
6217
|
{
|
|
5683
6218
|
name: "pr-review-workflow",
|
|
5684
6219
|
description: "Describes the /review-pr and /review-prs skills and their delegation to the pr-reviewer sub-agent",
|
|
@@ -5699,15 +6234,21 @@ var prReviewBundle = {
|
|
|
5699
6234
|
" has a linked issue). Ineligible PRs get a short comment and are",
|
|
5700
6235
|
" skipped.",
|
|
5701
6236
|
"2. Fetches the PR, its diff, CI status, and the linked issue",
|
|
5702
|
-
"3.
|
|
5703
|
-
"
|
|
5704
|
-
"
|
|
5705
|
-
"
|
|
5706
|
-
"
|
|
6237
|
+
"3. **Evaluates the PR Review Policy** (see the `PR Review Policy`",
|
|
6238
|
+
" section above) to decide whether the PR is `auto-merge` or",
|
|
6239
|
+
" `human-required`, and records the triggering reason",
|
|
6240
|
+
"4. Builds a checklist from the issue's acceptance criteria",
|
|
6241
|
+
"5. Verifies the diff satisfies each criterion and that CI is green",
|
|
6242
|
+
"6. **Enables squash auto-merge** (with `--delete-branch`) when all",
|
|
6243
|
+
" checks pass **and** the review mode is `auto-merge`",
|
|
6244
|
+
"7. **Applies `review:awaiting-human`** and hands off to a human",
|
|
6245
|
+
" reviewer when the review mode is `human-required` (no auto-merge,",
|
|
6246
|
+
" even if every acceptance criterion is met)",
|
|
6247
|
+
"8. **Comments with grouped findings** when any check fails (plain",
|
|
5707
6248
|
" `gh pr comment`, not a formal `--request-changes` review)",
|
|
5708
|
-
"
|
|
6249
|
+
"9. After a successful merge, verifies the linked issue is closed",
|
|
5709
6250
|
" and closes it explicitly if the merge commit did not",
|
|
5710
|
-
"
|
|
6251
|
+
"10. Cleans up the local branch after merge",
|
|
5711
6252
|
"",
|
|
5712
6253
|
"The reviewer **never** implements code and **never** pushes commits",
|
|
5713
6254
|
"to a PR's branch \u2014 it only reviews, decides, and orchestrates merge",
|