Skip to content

Route GitHub Writes Through Portable Tooling - #808

Merged
ptr727 merged 5 commits into
developfrom
issue-805
Aug 18, 2026
Merged

Route GitHub Writes Through Portable Tooling#808
ptr727 merged 5 commits into
developfrom
issue-805

Conversation

@ptr727

@ptr727 ptr727 commented Aug 18, 2026

Copy link
Copy Markdown
Owner

Summary

  • route fleet GitHub mutations through provider-neutral hub tooling or authenticated gh
  • add pr_review.py comment for suppressed-finding responses in the PR conversation
  • update the review skill and Copilot runbook, then regenerate the Claude and Copilot skill distributions

Why

Codex's GitHub connector can report repository access while its mutation token receives 403 Resource not accessible by integration. The verified gh session already has the required access. A common hub-tooling path gives Codex, Claude, opencode, and terminal users the same write behavior.

Addresses #805.

Verification

  • 724 Python unit tests under coverage
  • pr_review.py coverage at 97%
  • ruff check and format
  • mypy
  • audit and write-guard self-tests
  • distribution, repository, prose, schema, and JSON gates
  • EditorConfig, shellcheck, and PSScriptAnalyzer

Copilot AI lite review requested due to automatic review settings August 18, 2026 14:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This pull request standardizes fleet GitHub mutations to go through portable hub tooling (or authenticated gh) and extends scripts/pr_review.py with a comment subcommand to post PR-conversation responses for suppressed findings.

Changes:

  • Add scripts/pr_review.py comment to post and confirm PR conversation comments (target PR node ID read live in-run).
  • Extend unit tests and docs to cover comment, and tighten the “writes owned by this script” guardrails.
  • Update governance and distributed skills/runbook guidance to avoid provider-connector writes for fleet mutations.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
scripts/pr_review.py Adds comment subcommand and GraphQL documents for PR conversation comments.
scripts/tests/test_pr_review.py Adds comment command tests and updates write-document assertions.
scripts/README.md Documents the new comment workflow for suppressed findings.
GOVERNANCE.md Declares provider connectors read-only for fleet mutations and routes writes via hub tooling/gh.
.github/skills/pr-review-conduct/SKILL.md Instructs using pr_review.py comment for suppressed findings and forbids connector mutations.
.agents/skills/pr-review-conduct/SKILL.md Same guidance as the GitHub skill distribution copy.
.claude-plugin/fleet-skills/skills/pr-review-conduct/SKILL.md Same guidance as the Claude skill distribution copy.
.github/copilot-instructions.md Updates runbook to include comment for PR conversation responses.
.claude-plugin/fleet-skills/.source-digest Updates skill distribution digest to match regenerated content.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread scripts/pr_review.py Outdated
Copilot AI review requested due to automatic review settings August 18, 2026 14:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

Suppressed comments (1)

scripts/pr_review.py:1603

  • Normalize newlines in the --body text before sending and confirming it. GitHub stores comment bodies with \n, so if a Windows shell passes \r\n the comment can land successfully but this code returns COMMENT_NOT_CONFIRMED because the echoed body differs only by line endings.
    edge = (gh_graphql(M_COMMENT, subjectId=target["id"], body=body).get("addComment") or {}).get(
        "commentEdge"
    ) or {}
    comment = edge.get("node") or {}
    if not comment.get("url") or (comment.get("body") or "") != body:

Copilot AI review requested due to automatic review settings August 18, 2026 14:14
@ptr727

ptr727 commented Aug 18, 2026

Copy link
Copy Markdown
Owner Author

Suppressed findings (1) in review round: scripts/pr_review.py:1603 "Normalize newlines in the --body text before sending and confirming it." Fixed in 6285cd4. The command normalizes CRLF and bare CR to LF before sending, then compares GitHub response against the normalized body. A regression test covers both forms.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

Suppressed comments (2)

scripts/pr_review.py:14

  • comment documents exit code 64 as "the target is under another owner", but comment_on_pr() returns 64 for any out-of-scope write, including when origin_owner() is unreadable. Update the docstring so callers do not misinterpret a missing-origin refusal as a cross-owner target.
  comment  Post one PR-conversation answer, including a suppressed-finding disposition. The PR
           node id is read in the same run, and the returned comment URL and body confirm the
           write. Exit 0 = done, 64 = the target is under another owner, 65 = the PR could not
           be read, 66 = the response did not confirm the comment.

scripts/tests/test_pr_review.py:2426

  • Add coverage for the comment out-of-scope path when origin_owner() is unreadable. Today reply covers this scenario, but comment does not, and a regression could allow a write (or a confusing error) when scope cannot be established.
    def test_a_target_under_another_owner_is_refused_before_the_pr_read(self) -> None:
        self.wire({"id": "PR_wrong_owner", "url": "https://github.com/x/r/pull/7"})
        self.assertEqual(64, self.run_comment(repo="x/r"))
        self.assertEqual([], self.calls)
        self.assertIn("OUT_OF_SCOPE", self.out.getvalue())

Copilot AI review requested due to automatic review settings August 18, 2026 14:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings August 18, 2026 14:27
@ptr727

ptr727 commented Aug 18, 2026

Copy link
Copy Markdown
Owner Author

Suppressed findings (2) in review round. (1) scripts/pr_review.py:14 "comment documents exit code 64 as the target is under another owner." Fixed in dea0e97. The command now documents both an unreadable origin and an excluded target. (2) scripts/tests/test_pr_review.py:2426 "Add coverage for the comment out-of-scope path when origin_owner() is unreadable." Fixed in dea0e97. The regression test verifies exit 64, no GraphQL call, and the OUT_OF_SCOPE result.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

@ptr727
ptr727 marked this pull request as ready for review August 18, 2026 14:33
@ptr727
ptr727 merged commit fcf0e43 into develop Aug 18, 2026
8 checks passed
@ptr727
ptr727 deleted the issue-805 branch August 18, 2026 14:38
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.

2 participants