@codedrifters/configulator 0.0.350 → 0.0.351

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.mjs CHANGED
@@ -17445,12 +17445,18 @@ var pnpmBundle = {
17445
17445
  var DEFAULT_PATHS_EXEMPT_FROM_SIZE = [
17446
17446
  "docs/**"
17447
17447
  ];
17448
+ var DEFAULT_REQUIRED_WORKFLOWS = [];
17448
17449
  function resolvePrReviewPolicy(config) {
17449
17450
  const pathsExemptFromSize = config?.autoMerge?.pathsExemptFromSize ?? DEFAULT_PATHS_EXEMPT_FROM_SIZE;
17451
+ const requiredWorkflows = config?.ciVerification?.requiredWorkflows ?? DEFAULT_REQUIRED_WORKFLOWS;
17450
17452
  assertValidPathsExemptFromSize(pathsExemptFromSize);
17453
+ assertValidRequiredWorkflows(requiredWorkflows);
17451
17454
  return {
17452
17455
  autoMerge: {
17453
17456
  pathsExemptFromSize: [...pathsExemptFromSize]
17457
+ },
17458
+ ciVerification: {
17459
+ requiredWorkflows: [...requiredWorkflows]
17454
17460
  }
17455
17461
  };
17456
17462
  }
@@ -17466,6 +17472,15 @@ function assertValidPathsExemptFromSize(paths) {
17466
17472
  }
17467
17473
  }
17468
17474
  }
17475
+ function assertValidRequiredWorkflows(workflows) {
17476
+ for (const workflow of workflows) {
17477
+ if (typeof workflow !== "string" || workflow.trim().length === 0) {
17478
+ throw new Error(
17479
+ "prReviewPolicy.ciVerification.requiredWorkflows entries must be non-empty strings"
17480
+ );
17481
+ }
17482
+ }
17483
+ }
17469
17484
 
17470
17485
  // src/agent/bundles/pr-review.ts
17471
17486
  var prReviewerSubAgent = {
@@ -17507,6 +17522,125 @@ var prReviewerSubAgent = {
17507
17522
  "",
17508
17523
  "---",
17509
17524
  "",
17525
+ "## CI Verification (primary read + Actions-runs fallback)",
17526
+ "",
17527
+ "Every CI-status decision in this agent \u2014 the Phase 1.5 eligibility",
17528
+ "filter, the Phase 3 checklist, the Phase 4 merge gate, the Phase 4",
17529
+ "step (h) re-enable condition, and the Phase 4.5 sticky `CI status`",
17530
+ "field \u2014 resolves CI through the procedure below. It yields one of",
17531
+ "three verdicts: **green** (every required check succeeded),",
17532
+ "**pending** (no failures, but at least one required check is still",
17533
+ "running or queued), or **red** (at least one required check",
17534
+ "failed). Never enable auto-merge unless the verdict is **green**.",
17535
+ "",
17536
+ "### Step 1: Primary read \u2014 check-runs / statusCheckRollup",
17537
+ "",
17538
+ "Read CI from the GitHub check-runs rollup, the canonical source",
17539
+ "GitHub itself uses to gate branch protection:",
17540
+ "",
17541
+ "```bash",
17542
+ "gh pr checks <pr-number>",
17543
+ "# equivalently, the rollup field:",
17544
+ "gh pr view <pr-number> --json statusCheckRollup",
17545
+ "```",
17546
+ "",
17547
+ "This read aggregates **every** check context \u2014 GitHub Actions,",
17548
+ "third-party CI, GitHub Apps, and commit statuses. When it returns",
17549
+ "one or more readable contexts, it is authoritative: map each",
17550
+ "required context's conclusion with the table in Step 4 and do",
17551
+ "**not** fall back. It is strictly more complete than the",
17552
+ "Actions-runs view in Step 3.",
17553
+ "",
17554
+ "### Step 2: Detect the fine-grained-PAT 403",
17555
+ "",
17556
+ "The primary read fails closed for one specific credential: a",
17557
+ "**fine-grained personal access token**. GitHub exposes no `Checks`",
17558
+ "permission for fine-grained PATs (it is GitHub-App-only), so the",
17559
+ "check-runs / `statusCheckRollup` request returns:",
17560
+ "",
17561
+ "```",
17562
+ "HTTP 403: Resource not accessible by personal access token",
17563
+ "```",
17564
+ "",
17565
+ "Trigger the Step 3 fallback **only** when the primary read either:",
17566
+ "",
17567
+ "- returns an explicit **403** (`Resource not accessible by personal",
17568
+ " access token`) on the check-runs / `statusCheckRollup` request,",
17569
+ " **or**",
17570
+ "- returns **no readable check contexts at all** (an empty rollup)",
17571
+ " for a head SHA that does have CI configured.",
17572
+ "",
17573
+ "A primary read that returns one or more readable contexts is",
17574
+ "authoritative \u2014 **never** fall back in that case (GitHub-App and",
17575
+ "classic-PAT consumers keep the complete check-runs view). **Never**",
17576
+ "treat a 403 or an unreadable check as green: the 403 is a",
17577
+ "visibility failure, not a passing signal.",
17578
+ "",
17579
+ "### Step 3: Fallback read \u2014 Actions runs API",
17580
+ "",
17581
+ "A fine-grained PAT with `Actions: Read-only` (which **is**",
17582
+ "grantable) can read workflow-run conclusions even when check-runs",
17583
+ "is denied. Read every workflow run for the PR's head SHA:",
17584
+ "",
17585
+ "```bash",
17586
+ "head_sha=$(gh pr view <pr-number> --json headRefOid --jq '.headRefOid')",
17587
+ 'gh api "repos/{{repository.owner}}/{{repository.name}}/actions/runs?head_sha=${head_sha}&per_page=100"',
17588
+ "```",
17589
+ "",
17590
+ "Each run carries a `name`, `status`, and `conclusion`. **Collapse",
17591
+ "re-runs:** when a workflow `name` appears more than once for the",
17592
+ "same head SHA, keep only the most recent run (highest",
17593
+ "`run_number` / latest `created_at`) for that name.",
17594
+ "",
17595
+ "This fallback only sees GitHub Actions runs. It is sound for repos",
17596
+ "whose CI is entirely GitHub Actions; if a consumer adds a",
17597
+ "non-Actions required check, a fine-grained-PAT credential cannot",
17598
+ "see it and the consumer must move the reviewer to a GitHub App /",
17599
+ "classic PAT to regain the complete check-runs view.",
17600
+ "",
17601
+ "### Step 4: Map conclusions to a verdict",
17602
+ "",
17603
+ "Apply this mapping to the set of required checks (Step 5 defines",
17604
+ '"required"):',
17605
+ "",
17606
+ "| status / conclusion | Treatment |",
17607
+ "|---------------------|-----------|",
17608
+ "| `completed` / `success` | pass |",
17609
+ "| `completed` / `skipped` | non-blocking (ignore) |",
17610
+ "| `completed` / `neutral` | non-blocking (ignore) |",
17611
+ "| `completed` / `failure` | **block \u2192 red** |",
17612
+ "| `completed` / `cancelled` | **block \u2192 red** |",
17613
+ "| `completed` / `timed_out` | **block \u2192 red** |",
17614
+ "| `completed` / `action_required` | **block \u2192 red** |",
17615
+ "| `in_progress` / `queued` / `requested` / `waiting` / null conclusion | not-yet-green (pending) |",
17616
+ "",
17617
+ "- If any required check is **red**, the verdict is **red**.",
17618
+ "- Else if any required check is **pending**, the verdict is",
17619
+ " **pending**.",
17620
+ "- Else (every required check passed or was non-blocking) the",
17621
+ " verdict is **green**.",
17622
+ "",
17623
+ '### Step 5: Which workflows are "required"',
17624
+ "",
17625
+ 'In the **Step 1 primary path**, "required" means the contexts',
17626
+ "GitHub marks required under branch protection \u2014 the rollup already",
17627
+ "reflects this.",
17628
+ "",
17629
+ "In the **Step 3 fallback path**, the Actions runs API does not say",
17630
+ "which workflows are required, so consult the policy's",
17631
+ "`ci-verification.required-workflows` list (rendered in the",
17632
+ "`PR Review Policy` block in CLAUDE.md):",
17633
+ "",
17634
+ "- **Non-empty list** \u2014 gate only on the workflow `name`s in the",
17635
+ " list. A listed workflow with **no** run for the head SHA is",
17636
+ " treated as not-yet-green (pending), never green.",
17637
+ "- **Empty list (default)** \u2014 treat **every** workflow run observed",
17638
+ " for the head SHA as required. This is the conservative",
17639
+ " zero-config default: an unknown failing workflow blocks rather",
17640
+ " than slips through.",
17641
+ "",
17642
+ "---",
17643
+ "",
17510
17644
  "## Phase 1: Identify the PR",
17511
17645
  "",
17512
17646
  "If a PR number was provided in your instructions, use that. Otherwise stop",
@@ -17525,7 +17659,12 @@ var prReviewerSubAgent = {
17525
17659
  '1. `mergeable == "MERGEABLE"` (no merge conflicts).',
17526
17660
  "2. No **failing** required checks in `statusCheckRollup` \u2014 CI must be",
17527
17661
  " green or still pending. Any `FAILURE`, `TIMED_OUT`, `CANCELLED`, or",
17528
- " `ERROR` conclusion on a required check disqualifies the PR.",
17662
+ " `ERROR` conclusion on a required check disqualifies the PR. If the",
17663
+ " `statusCheckRollup` read returns a 403 `Resource not accessible by",
17664
+ " personal access token` (fine-grained PAT) or an empty rollup,",
17665
+ " resolve CI via the **CI Verification** section's Actions-runs",
17666
+ " fallback before deciding eligibility \u2014 do **not** treat the 403 as",
17667
+ " either a pass or an automatic disqualification.",
17529
17668
  "3. The PR body contains a linked issue via one of the closing keywords:",
17530
17669
  " `Closes #N`, `Fixes #N`, or `Resolves #N` (case-insensitive).",
17531
17670
  "",
@@ -17743,7 +17882,9 @@ var prReviewerSubAgent = {
17743
17882
  "- **Convention compliance** \u2014 PR title uses a conventional commit prefix,",
17744
17883
  " body includes a closing keyword, branch name follows project conventions",
17745
17884
  "- **Test coverage** \u2014 new or changed behavior has tests",
17746
- "- **CI status** \u2014 `gh pr checks` reports all required checks passing",
17885
+ "- **CI status** \u2014 resolve CI via the **CI Verification** section",
17886
+ " (primary check-runs read, with the Actions-runs fallback on a",
17887
+ " fine-grained-PAT 403). The verdict must be **green**.",
17747
17888
  "- **Scope creep** \u2014 diff stays within the issue's stated scope",
17748
17889
  "",
17749
17890
  "## Phase 3.5: Classify Comments",
@@ -18118,7 +18259,9 @@ var prReviewerSubAgent = {
18118
18259
  " pushbacks added in step (a) and the failure pushbacks added in",
18119
18260
  " step (f).",
18120
18261
  "4. CI is green or still pending (any failing required check",
18121
- " disqualifies re-enablement).",
18262
+ " disqualifies re-enablement). Resolve CI via the **CI",
18263
+ " Verification** section, including the Actions-runs fallback on a",
18264
+ " fine-grained-PAT 403.",
18122
18265
  "",
18123
18266
  "When all four hold, re-enable auto-merge with the same command used",
18124
18267
  "in the auto-merge branch below:",
@@ -18517,7 +18660,9 @@ var prReviewerSubAgent = {
18517
18660
  "- **AC status** \u2014 the checklist produced in Phase 3 (met, partial,",
18518
18661
  " or missing), with links to the files or tests that provide the",
18519
18662
  " evidence.",
18520
- "- **CI status** \u2014 derived from `gh pr checks`.",
18663
+ "- **CI status** \u2014 the verdict from the **CI Verification** section",
18664
+ " (primary check-runs read, or the Actions-runs fallback when",
18665
+ " check-runs returns a fine-grained-PAT 403).",
18521
18666
  "- **Outstanding** \u2014 the comments still carrying a non-terminal",
18522
18667
  " reviewer reaction from Phase 3.5 (typically `eyes` for queued",
18523
18668
  " in-scope items and `nit` / `question` items that remain open).",
@@ -18642,7 +18787,11 @@ var prReviewerSubAgent = {
18642
18787
  "2. **Never merge without a linked issue.** If the PR body has no",
18643
18788
  " `Closes #N` / `Fixes #N` / `Resolves #N`, comment and stop.",
18644
18789
  "3. **Never merge with failing CI.** Even if every criterion is met,",
18645
- " block on red checks.",
18790
+ " block on red checks. Resolve CI status via the **CI",
18791
+ " Verification** section: read check-runs first, and only on a",
18792
+ " fine-grained-PAT 403 (or an empty rollup) fall back to the",
18793
+ " Actions runs API. A 403 is a visibility failure, **never** a",
18794
+ " passing check \u2014 do not treat an unreadable check as green.",
18646
18795
  "4. **Never bypass review conventions.** Always use `--squash`, `--auto`,",
18647
18796
  " and `--delete-branch` for merges. Do not force-merge.",
18648
18797
  "5. **Never auto-merge a `human-required` PR.** When Phase 2.75 resolves",
@@ -18824,7 +18973,10 @@ var reviewPrsSkill = {
18824
18973
  '2. `mergeable == "MERGEABLE"` (no conflicts).',
18825
18974
  "3. No required check in `statusCheckRollup` has a failing conclusion",
18826
18975
  " (`FAILURE`, `TIMED_OUT`, `CANCELLED`, `ERROR`). CI green or still",
18827
- " pending is fine.",
18976
+ " pending is fine. When `statusCheckRollup` is empty or denied with",
18977
+ " a fine-grained-PAT 403, keep the PR in the queue \u2014 the per-PR",
18978
+ " pipeline resolves CI authoritatively via the reviewer's CI",
18979
+ " Verification Actions-runs fallback.",
18828
18980
  "4. The PR body contains a linked issue (`Closes #N` / `Fixes #N` /",
18829
18981
  " `Resolves #N`, case-insensitive).",
18830
18982
  "",
@@ -18943,6 +19095,12 @@ function buildPrReviewBundle(policy = resolvePrReviewPolicy()) {
18943
19095
  ...renderPathsExemptFromSizeYaml(
18944
19096
  policy.autoMerge.pathsExemptFromSize
18945
19097
  ),
19098
+ "",
19099
+ "ci-verification:",
19100
+ " required-workflows:",
19101
+ ...renderRequiredWorkflowsYaml(
19102
+ policy.ciVerification.requiredWorkflows
19103
+ ),
18946
19104
  "```",
18947
19105
  "",
18948
19106
  "## Precedence",
@@ -19024,7 +19182,69 @@ function buildPrReviewBundle(policy = resolvePrReviewPolicy()) {
19024
19182
  "out only kicks in for **code-heavy** PRs that legitimately trip",
19025
19183
  "rule #6 (mixed-content diffs whose non-doc paths fail the",
19026
19184
  "`paths-exempt-from-size` check, or consumers that disable the",
19027
- "doc-only carve-out entirely)."
19185
+ "doc-only carve-out entirely).",
19186
+ "",
19187
+ "## CI Verification",
19188
+ "",
19189
+ "Before enabling auto-merge the reviewer confirms CI is green.",
19190
+ "The **primary** read is the GitHub check-runs rollup",
19191
+ "(`gh pr checks` / `statusCheckRollup`) \u2014 the same source",
19192
+ "GitHub uses for branch protection, covering **every** check",
19193
+ "context (Actions, third-party CI, GitHub Apps, commit",
19194
+ "statuses). It stays primary for every consumer because it is",
19195
+ "strictly more complete than the Actions-only fallback below.",
19196
+ "",
19197
+ "### Fine-grained-PAT fallback to the Actions runs API",
19198
+ "",
19199
+ "When the reviewer authenticates with a **fine-grained personal",
19200
+ "access token**, the check-runs read returns",
19201
+ "`HTTP 403: Resource not accessible by personal access token`.",
19202
+ "This is not grantable away: GitHub exposes **no `Checks`",
19203
+ "permission for fine-grained tokens** (it is GitHub-App-only),",
19204
+ "so the token permission picker has no entry to add. On that",
19205
+ "specific 403 (or when the rollup returns no readable contexts",
19206
+ "at all), the reviewer falls back to the **Actions runs API**:",
19207
+ "",
19208
+ "```",
19209
+ "GET /repos/{owner}/{repo}/actions/runs?head_sha={head_sha}&per_page=100",
19210
+ "```",
19211
+ "",
19212
+ "which a fine-grained PAT with `Actions: Read-only` **can**",
19213
+ "read. Auto-merge is then gated on the required workflows'",
19214
+ "latest run per workflow name concluding `success`",
19215
+ "(`skipped` / `neutral` are non-blocking; `failure` /",
19216
+ "`cancelled` / `timed_out` / `action_required` block; a run",
19217
+ "still `in_progress` / `queued`, or a required workflow with no",
19218
+ "run at all, counts as not-yet-green). The 403 is detected",
19219
+ "explicitly and is **never** treated as a passing check \u2014 it is",
19220
+ "a visibility failure, not a green signal.",
19221
+ "",
19222
+ "The fallback fires **only** when the primary check-runs read",
19223
+ "is denied, so GitHub-App and classic-PAT consumers (which can",
19224
+ "read check-runs) are unaffected and keep the complete view.",
19225
+ "The fallback only sees GitHub Actions runs; a consumer whose",
19226
+ "CI includes a non-Actions required check cannot verify it on a",
19227
+ "fine-grained PAT and must move the reviewer to a GitHub App /",
19228
+ "classic PAT to regain the complete check-runs view.",
19229
+ "",
19230
+ "### Configuring required workflows",
19231
+ "",
19232
+ "The `ci-verification.required-workflows` list in the policy",
19233
+ "YAML names the workflows the fallback gates on:",
19234
+ "",
19235
+ "- **Non-empty list** \u2014 gate only on those workflow `name`s.",
19236
+ " A listed workflow with no run for the head SHA is treated as",
19237
+ " not-yet-green (pending), never green.",
19238
+ "- **Empty list (the default)** \u2014 treat **every** workflow run",
19239
+ " observed for the head SHA as required. This is the",
19240
+ " conservative zero-config default so an unknown failing",
19241
+ " workflow blocks rather than slips through.",
19242
+ "",
19243
+ "Consumers tune the list via",
19244
+ "`agentConfig.prReviewPolicy.ciVerification.requiredWorkflows`.",
19245
+ "The list governs **only** the fallback path; the primary",
19246
+ 'check-runs read derives "required" from branch protection',
19247
+ "directly."
19028
19248
  ].join("\n"),
19029
19249
  tags: ["policy", "review"]
19030
19250
  },
@@ -19310,6 +19530,12 @@ function renderPathsExemptFromSizeYaml(paths) {
19310
19530
  }
19311
19531
  return paths.map((path8) => ` - "${path8}"`);
19312
19532
  }
19533
+ function renderRequiredWorkflowsYaml(workflows) {
19534
+ if (workflows.length === 0) {
19535
+ return [" []"];
19536
+ }
19537
+ return workflows.map((workflow) => ` - "${workflow}"`);
19538
+ }
19313
19539
  var prReviewBundle = buildPrReviewBundle();
19314
19540
 
19315
19541
  // src/agent/bundles/projen.ts