Skip to content

fix(devtools): make PR scope CI authoritative - #3848

Merged
Sinity merged 11 commits into
masterfrom
feature/fix/pr-scope-carrier-followup
Aug 6, 2026
Merged

fix(devtools): make PR scope CI authoritative#3848
Sinity merged 11 commits into
masterfrom
feature/fix/pr-scope-carrier-followup

Conversation

@Sinity

@Sinity Sinity commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Summary

Make the structured PR-scope gate authoritative across CI and merge execution. CircleCI now validates the exact checkout head using the base revision's validator when available, and merge receipts bind the complete carrier state.

Problem

The first carrier implementation ran from the pull request checkout, so a PR could modify the validator used to judge its own scope. CircleCI builds can also lack CIRCLE_PULL_REQUEST, and the old PR-state workflow enforced a prose convention with a regular expression instead of a structured contract.

Solution

devtools.pr_scope now resolves PR metadata through GitHub REST, supports exact-head PR lookup, validates the carrier schema without accepting unknown fields, and runs the base revision validator in an isolated subprocess. CircleCI calls check-ci with repository metadata and CIRCLE_SHA1. Merge receipts bind the scope digest, Bead digest, and assigned Bead IDs, while the merge command uses --match-head-commit. The prose-parsing PR-state workflow is removed, and lane and contributor instructions point at the structured carrier.

Verification

  • mypy: Success: no issues found in 2672 source files
  • devtools test tests/unit/devtools/test_pr_scope.py tests/unit/devtools/test_merge_gate.py tests/unit/devtools/test_merge_boundary.py: 66 passed
  • devtools verify --quick: every step exited 0
  • git diff --check: no output

Bead disposition matrix

Assigned Bead Whole-Bead disposition Evidence refs Named successor for residual work
polylogue-z7sv3 satisfied commit:a03b02a62, commit:b5fe5291a, commit:a4c0d7ffe, commit:f1085c920, commit:859b54052, commit:1a45ca2c3, commit:e409a5182, commit:14724cc0a, commit:4b686ab21, commit:9d5585126, test:66 focused devtools tests passed, command:mypy, command:devtools verify --quick n/a

Ref polylogue-z7sv3.

Follow-ups

polylogue-1cbeh remains open for a GitHub-visible merge-gate status that can support safe auto-merge. Until that status is wired, the repository's merge boundary requires the local structured carrier and fresh receipt checks. The current CircleCI configuration also cannot establish an external trust root for its own launcher, so the base-validator check is a defense within the existing CI trust boundary and the status-workflow work remains separately tracked.

Sinity and others added 3 commits August 6, 2026 08:13
Problem: PR scope and residual Bead work were inferred from prose and did not reach CI or the merge boundary.

What changed: add a versioned embedded JSON carrier, command-surface render/check commands, CircleCI enforcement, merge-gate receipt binding, and lane/reviewer instructions. Replace the prose reconciliation probe with typed whole-Bead dispositions and successor validation.

Verification: devtools test tests/unit/devtools/test_pr_scope.py tests/unit/devtools/test_merge_gate.py tests/unit/devtools/test_merge_boundary.py (49 passed); devtools verify --quick (success).
Problem: the initial structured PR-scope gate ran the validator from the pull request checkout, allowed CircleCI builds without a pull-request URL to fail before validation, and left merge receipts weaker than the carrier they certified.

What changed: resolve pull-request metadata from GitHub REST using the exact checkout head, run the validator from the base revision when available, validate the carrier schema strictly, bind receipts to scope and Bead digests, and make the merge use a matching head commit. Remove the prose-parsing PR state workflow and document the structured CI path.

Verification: mypy; devtools test tests/unit/devtools/test_pr_scope.py tests/unit/devtools/test_merge_gate.py tests/unit/devtools/test_merge_boundary.py; devtools verify --quick; git diff --check.

Co-Authored-By: Claude <noreply@anthropic.com>
Record the structured CI authority follow-up and make it a prerequisite of the remaining merge-gate status-check bead.

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Sinity, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 52 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d27a6177-fa1b-4411-aaa3-c74f2a739781

📥 Commits

Reviewing files that changed from the base of the PR and between 4b686ab and 9d55851.

📒 Files selected for processing (1)
  • CLAUDE.md
📝 Walkthrough

Walkthrough

Changes

PR scope enforcement

Layer / File(s) Summary
PR-scope carrier contract
devtools/pr_scope.py, tests/unit/devtools/test_pr_scope.py
Adds structured enums, metadata types, field validation, durable successor checks, carrier validation, and related tests.
CI scope validation
.circleci/config.yml, devtools/pr_scope.py, devtools/command_catalog.py, tests/unit/devtools/test_pr_scope.py
Adds exact-head PR lookup, base-revision validator execution, check-ci, SHA and draft checks, and diagnostic artifacts.
Merge receipt and head binding
devtools/merge_gate.py, devtools/merge_boundary.py, devtools/command_catalog.py, tests/unit/devtools/test_merge_gate.py, tests/unit/devtools/test_merge_boundary.py
Validates scope receipts after checkout checks, detects digest and assigned-Bead changes, requires the carrier, and passes --match-head-commit to merges.
Publication workflow and command surface
CLAUDE.md, .claude/agents/lane.md, .codex/agents/*.toml, CONTRIBUTING.md, .beads/issues.jsonl, .github/workflows/pr-state-guard.yml
Moves carrier rendering and publication to coordinators, updates PR and merge requirements, changes authoritative CI guidance, adds the supporting Bead dependency, and removes the PR state guard workflow.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CircleCI quick-gate
  participant pr_scope.check_ci
  participant GitHub REST API
  participant Base-revision validator
  CircleCI quick-gate->>pr_scope.check_ci: pass repository and expected head SHA
  pr_scope.check_ci->>GitHub REST API: resolve the open PR by exact head
  GitHub REST API-->>pr_scope.check_ci: return PR metadata and base SHA
  pr_scope.check_ci->>Base-revision validator: validate the PR-scope carrier
  Base-revision validator-->>pr_scope.check_ci: return validation status
  pr_scope.check_ci-->>CircleCI quick-gate: emit verdict and diagnostic log
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely identifies the main change: making PR-scope CI authoritative.
Description check ✅ Passed The description covers the required change, problem, solution, verification, Bead disposition, and follow-up details with concrete evidence.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/fix/pr-scope-carrier-followup

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.circleci/config.yml:
- Around line 74-87: Update the “Structured PR scope carrier” command around
`check-ci` so non-master builds without a resolvable candidate PR do not fail
`quick-gate`. Skip the check or treat the specific no-open-PR result as
successful, while preserving failures for network/API and other genuine
validation errors; continue passing the PR number when `CIRCLE_PULL_REQUEST` is
available.

In @.codex/agents/narrow-worker.toml:
- Around line 30-35: Resolve the publication ownership contradiction in both
.codex/agents/narrow-worker.toml lines 30-35 and .codex/agents/worker.toml lines
38-45: remove rendering, validation, and PR publication responsibilities from
these no-push roles and assign them explicitly to the coordinator, or define an
explicit role permitted to push. Ensure the coordinator owns rendering the
PR-scope carrier, validating it, and publishing the non-draft PR.

In `@devtools/command_catalog.py`:
- Around line 833-835: Fix the workspace merge description string around the
command catalog entry by removing the leftover “auto-records a” fragment after
“merge <PR>” so the concatenated text reads grammatically and contains only the
intended merge-gate receipt wording. Keep the existing structured scope
validation and receipt behavior text unchanged.

In `@devtools/merge_gate.py`:
- Around line 222-235: Move the pr_scope.validate_pr_body call and its
invalid-scope refusal block in the record flow below the local-head and
clean-tree guards. Ensure validation occurs only after the checkout is confirmed
to match the PR head, so the carrier digest is read from and bound to the
verified tree; preserve the existing validation behavior and return code.

In `@devtools/pr_scope.py`:
- Around line 439-441: Update fetch_base_validator_source and its
check_ci_metadata caller to read devtools/pr_scope.py from the checked-out base
object when available instead of fetching it through the GitHub API. Handle an
absent base commit explicitly by fetching it or raising a clear error, and do
not pass optional missing data to sys.executable for execution.

In `@tests/unit/devtools/test_merge_gate.py`:
- Around line 201-207: Add a third row to the parametrization for the mutation
test, using receipt_field "pr_scope_digest", a distinct mutated value
representing a changed body digest, and reason "pr_scope_digest". Keep the
existing pr_scope_beads_digest and pr_scope_assigned_beads cases unchanged.

In `@tests/unit/devtools/test_pr_scope.py`:
- Around line 174-222: Add parameterized coverage for both head-authority guards
in check_ci_metadata: one case with a mismatched checkout_head_sha and one with
a mismatched expected_head_sha while metadata.head_sha remains HEAD_SHA. Assert
exit code 2 and verify fetch_base_validator_source is not called, confirming
refusal occurs before base-validator handling.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6c0d64c5-9424-4d2b-8dcc-92b59fe840d0

📥 Commits

Reviewing files that changed from the base of the PR and between 497d3d6 and b5fe529.

📒 Files selected for processing (21)
  • .beads/issues.jsonl
  • .circleci/config.yml
  • .claude/agents/lane.md
  • .codex/agents/narrow-worker.toml
  • .codex/agents/reviewer.toml
  • .codex/agents/worker.toml
  • .github/pull_request_template.md
  • .github/workflows/pr-state-guard.yml
  • CLAUDE.md
  • CONTRIBUTING.md
  • devtools/command_catalog.py
  • devtools/lane_brief.py
  • devtools/merge_boundary.py
  • devtools/merge_gate.py
  • devtools/pr_scope.py
  • devtools/verify_bead_pr_reconciliation.py
  • docs/devtools.md
  • docs/tracker-authority.md
  • tests/unit/devtools/test_merge_boundary.py
  • tests/unit/devtools/test_merge_gate.py
  • tests/unit/devtools/test_pr_scope.py
💤 Files with no reviewable changes (2)
  • .github/workflows/pr-state-guard.yml
  • devtools/verify_bead_pr_reconciliation.py

Comment thread .circleci/config.yml Outdated
Comment thread .codex/agents/narrow-worker.toml Outdated
Comment thread devtools/command_catalog.py Outdated
Comment thread devtools/merge_gate.py Outdated
Comment thread devtools/pr_scope.py
Comment thread tests/unit/devtools/test_merge_gate.py
Comment thread tests/unit/devtools/test_pr_scope.py

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

"'no data' to a reader. New silent sites must add a log call, or add a typed signal "
"plus a rationale entry in docs/plans/degrade-loudly-allowlist.yaml."
),
examples=("devtools verify degrade-loudly", "devtools verify degrade-loudly --json"),

P2 Badge Retain post-merge Bead reconciliation

Removing this command eliminates the only check for Beads that remain open after their referenced PR merges; the carrier is only a pre-merge declaration and neither closes records nor audits them afterward. This commit itself declares polylogue-z7sv3 satisfied while adding its canonical record with status: open, demonstrating that the new mechanism does not replace the deleted reconciliation step and can leave completed work on the ready queue indefinitely.

AGENTS.md reference: AGENTS.md:L286-L299

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

branches: [master]
types:
- opened
- edited

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Revalidate scope when the PR body changes

After CircleCI records a successful quick-gate status for a head SHA, editing the PR body does not push a commit or start another CircleCI pipeline, so removing the only pull_request.edited trigger leaves that success attached even if the carrier is subsequently removed or altered. The local merge wrapper may detect this, but branch protection or auto-merge can consume the stale CI result; retain a PR-metadata-triggered check or otherwise invalidate the status on body edits.

AGENTS.md reference: AGENTS.md:L381-L389

Useful? React with 👍 / 👎.

Comment thread devtools/pr_scope.py
Comment on lines +472 to +478
"check",
"--body-file",
str(body_path),
"--head-sha",
metadata.head_sha,
"--beads-path",
str(beads_path.resolve()),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Pass draft state to the base validator

When check-ci finds a validator on the base revision, this subprocess invokes check --body-file, whose code hardcodes is_draft=False; consequently, a valid carrier on a draft PR passes this supposedly authoritative path even though validate_carrier explicitly rejects drafts. The bootstrap path correctly passes metadata.is_draft, so the behavior changes after the first landing; preserve or pre-check the fetched draft state before accepting the base-validator result.

Useful? React with 👍 / 👎.

Comment on lines -56 to -59
pattern = re.compile(
r"\b(?:close(?:s|d)?|fix(?:es|ed)?|resolve(?:s|d)?)\s*:?\s+"
r"(?:(?:[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+)?#\d+\b|"
r"https://github\.com/[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+/issues/\d+\b)",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve the resolver-keyword guard

The structured carrier validates only its embedded JSON and never inspects the PR title or surrounding prose, so deleting this regex removes the sole automated rejection of Fixes #N/Closes #N references. In that scenario, merging the PR can close a GitHub issue even when the carrier records partial or deferred scope; retain this check in an active CI path unless the structured validator gains equivalent protection.

AGENTS.md reference: AGENTS.md:L318-L321

Useful? React with 👍 / 👎.

Comment thread .circleci/config.yml Outdated
Comment on lines +84 to +87
~/.local/bin/uv run devtools workspace pr-scope check-ci \
"${PR_ARGS[@]}" \
--repo "${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}" \
--expected-head-sha "${CIRCLE_SHA1}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Run the CI launcher from the base revision

Although check-ci eventually downloads the base revision's validator, CircleCI first invokes the devtools dispatcher and pr_scope.main from the untrusted PR checkout. A PR can therefore change this entrypoint to return success without calling fetch_base_validator_source (or simply reroute the command), so the base validator is never reached while the quick-gate job still passes; the trusted launcher itself must come from the base revision or an externally enforced CI configuration.

AGENTS.md reference: AGENTS.md:L381-L389

Useful? React with 👍 / 👎.

Comment thread devtools/pr_scope.py
Comment on lines +269 to +274
for successor in successors:
record = records.get(successor)
if record is None:
reasons.append(f"{bead_id}: successor {successor} is unknown")
elif record.get("status") == "closed":
reasons.append(f"{bead_id}: successor {successor} is closed")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Verify successors are linked to their source Bead

For a partial, deferred, or superseded disposition, this loop accepts any existing non-closed Bead ID as the successor without checking that the canonical Bead graph contains a relationship to the assigned Bead. A typo that happens to name an unrelated live issue therefore passes while bd show and graph-based planning cannot trace the residual work back to the original acceptance gap; require a durable dependency/discovered-from relationship rather than existence alone.

AGENTS.md reference: AGENTS.md:L294-L299

Useful? React with 👍 / 👎.

Sinity and others added 2 commits August 6, 2026 09:03
Problem: review found that the structured PR scope check could accept an
ambiguous CI state, consult the wrong validator revision, and record receipts
before verifying the local tree. Agent publication instructions also assigned
carrier ownership inconsistently.

What changed: distinguish commits with no open PRs from API failures, prefer the
checked-out base validator object, defer scope validation until checkout guards
pass, and cover the new failure paths with focused tests. Clarify that the
coordinator owns carrier rendering and PR publication.

Compatibility/migration: non-master CircleCI builds with no open PR now skip
the scope check; network and metadata failures remain blocking.

Ref polylogue-z7sv3

Co-Authored-By: Claude <noreply@anthropic.com>
Problem: residual Bead successors were accepted when they merely existed, and draft pull requests could pass the base-validator subprocess because its body-check path defaulted to non-draft.

What changed: require a durable Beads relationship for every residual successor and refuse draft PRs before invoking the authoritative base checker. Added focused acceptance and rejection tests.

Ref polylogue-z7sv3

Co-Authored-By: Claude <noreply@anthropic.com>
@Sinity

Sinity commented Aug 6, 2026

Copy link
Copy Markdown
Owner Author

Review triage for the structured PR-scope carrier:

  • The seven initial findings are addressed in a4c0d7ffe and f1085c920. The focused devtools set is now 65 tests, and the quick gate is green at f1085c920.
  • Draft state is rejected before the base-validator subprocess, and residual successors must have a durable blocks, discovered-from, relates-to, or supersedes relationship in the committed Beads graph.
  • The body-edit finding is a real remaining process boundary. The merge wrapper revalidates the current PR body, while polylogue-1cbeh tracks the GitHub-visible merge-gate status needed before safe auto-merge can rely on a status that is refreshed independently of commits.
  • The base-launcher finding is an external CI trust-boundary concern. A PR-local CircleCI config cannot make its own launcher trusted. check-ci now runs the base revision validator when launched, and the separate status/branch-protection work remains open.
  • The resolver-keyword finding is intentionally not restored. This repository uses Beads rather than GitHub Issues, and its standing policy forbids prose-pattern gates. The structured carrier records whole-Bead dispositions and named graph-linked residuals without making natural language load-bearing.

The PR body carrier has been regenerated and validated against the exact head SHA.

Sinity and others added 6 commits August 6, 2026 09:18
Problem: the authoritative checker prefers a validator from the checked-out base object, but that selection was not directly covered.

What changed: add a focused test proving a locally available base validator is returned without a GitHub fallback.

Ref polylogue-z7sv3

Co-Authored-By: Claude <noreply@anthropic.com>
Problem: the CircleCI scope-gate launcher used shell array syntax even though the job's shell contract is not part of the repository interface.

What changed: branch explicitly between PR-number lookup and exact-head lookup, keeping both invocations portable while preserving the same strict arguments.

Ref polylogue-z7sv3

Co-Authored-By: Claude <noreply@anthropic.com>
Bring the published follow-up branch onto the current master tree so the PR is mergeable. Preserve the hardened structured scope carrier while incorporating the merged blob-liveness and display-label changes.

Verification: devtools verify --quick passed at the merged tree.

Co-Authored-By: Claude <noreply@anthropic.com>
Problem: CircleCI project metadata is not a stable GitHub owner/repository contract for this project, so the scope gate could fail before reaching its validator.

What changed: pass the explicit Sinity/polylogue repository slug to both PR metadata paths in the project-specific CircleCI job.

Ref polylogue-z7sv3

Co-Authored-By: Claude <noreply@anthropic.com>
Problem: CircleCI failures in the early gates were not inspectable without an authenticated Circle account.

What changed: tee public-claims and structured-scope output into temporary logs and always upload those logs as job artifacts, preserving the command exit status.

Ref polylogue-z7sv3

Co-Authored-By: Claude <noreply@anthropic.com>
Problem: CircleCI validates the carrier against the pushed head, so a body-only carrier update after push leaves the first run with stale metadata.\n\nWhat changed: Record the required order in the repository workflow: create the final commit, render its exact carrier, update the PR body, verify the carrier, then push.\n\nCompatibility/migration: This changes coordinator procedure only.\n\nRef polylogue-z7sv3\n\nCo-Authored-By: Claude <noreply@anthropic.com>
@Sinity

Sinity commented Aug 6, 2026

Copy link
Copy Markdown
Owner Author

Review triage for the refreshed head 9d5585126:

  • The repeated base-validator comment is addressed by the current implementation. fetch_base_validator_source first executes git show <base_sha>:devtools/pr_scope.py against the checked-out object, and only falls back to the GitHub raw endpoint when the base object is absent. check_ci_metadata never passes a missing response to the subprocess. The focused tests cover the local-preference path and the quick gate is green.
  • The post-merge Bead reconciliation comment is a valid process concern, but it is outside this PR's carrier-authority slice. The carrier deliberately records evidence and residual graph links; it does not close Beads. The existing bead-reimport-guard reconcile command and the coordinator's post-merge bd close step remain the reconciliation path. polylogue-1cbeh tracks the remaining GitHub-visible merge-gate status needed to automate that boundary.
  • The body-edit status concern is now documented as an explicit publication-order rule: render and publish the carrier after the final commit and before pushing. The merge wrapper still revalidates the live body, and the body now matches the pushed head exactly. A body-only edit cannot rerun CircleCI, so the workflow does not claim otherwise.

The draft-state and resolver-keyword comments remain intentionally triaged as before. Drafts are rejected before base validation; prose-pattern enforcement is not restored because this Beads repository uses the structured carrier and its standing policy rejects natural-language gates.

@Sinity
Sinity merged commit 685f2ca into master Aug 6, 2026
3 checks passed
@Sinity
Sinity deleted the feature/fix/pr-scope-carrier-followup branch August 6, 2026 08:02

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9d55851260

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread devtools/pr_scope.py
Comment on lines +621 to +623
except NoOpenPullRequestError as exc:
print(f"pr-scope CI skip: {exc}", file=sys.stderr)
return 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Fail closed when PR discovery returns no match

When CIRCLE_PULL_REQUEST is absent and the commit-to-PR lookup returns no open match, this path reports success without validating any carrier. The inspected CircleCI configuration enables “Only build pull requests” and skips master before invoking check-ci, so a missing match on this path indicates lookup lag or inconsistent PR metadata rather than a legitimate branch build; returning zero can publish a green quick-gate for a PR whose body and base validator were never checked. Treat this as an error and retry or fail closed.

AGENTS.md reference: AGENTS.md:L390-L392

Useful? React with 👍 / 👎.

Comment thread devtools/pr_scope.py

def _successor_is_linked(source_id: str, successor_id: str, records: dict[str, dict[str, Any]]) -> bool:
"""Require a durable Beads relationship between a source and its successor."""
for record_id, target_id in ((source_id, successor_id), (successor_id, source_id)):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Respect direction when validating successor links

Fresh evidence in this revision is the new symmetric relationship check: when the assigned Bead has a supersedes dependency on an older Bead, this loop accepts that older Bead as its successor even though the relationship means the assigned Bead replaces it. A partial/deferred/superseded disposition can therefore point residual work at an obsolete issue and pass validation; validate direction according to relationship type—for example, a successor must supersede or be discovered from the assigned Bead, not vice versa.

AGENTS.md reference: AGENTS.md:L384-L386

Useful? React with 👍 / 👎.

Comment thread .circleci/config.yml
Comment on lines +78 to +79
if [ "${CIRCLE_BRANCH:-}" = "master" ]; then
exit 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Do not skip fork PRs named master

When a fork submits a PR from its default branch named master, CircleCI exposes the head branch name through CIRCLE_BRANCH, so this unconditional check exits before inspecting the populated CIRCLE_PULL_REQUEST. That gives the fork PR a green structured-scope step without fetching its body or executing the base validator; the previous ordering only skipped master when no PR URL existed. Restrict this bypass to a confirmed non-PR default-branch build rather than the branch name alone.

AGENTS.md reference: AGENTS.md:L390-L392

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant