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

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

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

CopilotAI 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
FileDescription
scripts/pr_review.pyAdds comment subcommand and GraphQL documents for PR conversation comments.
scripts/tests/test_pr_review.pyAdds comment command tests and updates write-document assertions.
scripts/README.mdDocuments the new comment workflow for suppressed findings.
GOVERNANCE.mdDeclares provider connectors read-only for fleet mutations and routes writes via hub tooling/gh.
.github/skills/pr-review-conduct/SKILL.mdInstructs using pr_review.py comment for suppressed findings and forbids connector mutations.
.agents/skills/pr-review-conduct/SKILL.mdSame guidance as the GitHub skill distribution copy.
.claude-plugin/fleet-skills/skills/pr-review-conduct/SKILL.mdSame guidance as the Claude skill distribution copy.
.github/copilot-instructions.mdUpdates runbook to include comment for PR conversation responses.
.claude-plugin/fleet-skills/.source-digestUpdates skill distribution digest to match regenerated content.

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

Comment threadscripts/pr_review.py Outdated
CopilotAI review requested due to automatic review settings August 18, 2026 14:08

CopilotAI 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:

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

ptr727 commented Aug 18, 2026

Copy link
Copy Markdown
OwnerAuthor

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.

CopilotAI 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())

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

CopilotAI 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.

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

Copy link
Copy Markdown
OwnerAuthor

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.

CopilotAI 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 developAug 18, 2026
8 checks passed
@ptr727
ptr727 deleted the issue-805 branch August 18, 2026 14:38
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Route GitHub Writes Through Portable Tooling by ptr727 · Pull Request #808 · ptr727/ProjectTemplate · GitHub
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

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

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

CopilotAI 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
FileDescription
scripts/pr_review.pyAdds comment subcommand and GraphQL documents for PR conversation comments.
scripts/tests/test_pr_review.pyAdds comment command tests and updates write-document assertions.
scripts/README.mdDocuments the new comment workflow for suppressed findings.
GOVERNANCE.mdDeclares provider connectors read-only for fleet mutations and routes writes via hub tooling/gh.
.github/skills/pr-review-conduct/SKILL.mdInstructs using pr_review.py comment for suppressed findings and forbids connector mutations.
.agents/skills/pr-review-conduct/SKILL.mdSame guidance as the GitHub skill distribution copy.
.claude-plugin/fleet-skills/skills/pr-review-conduct/SKILL.mdSame guidance as the Claude skill distribution copy.
.github/copilot-instructions.mdUpdates runbook to include comment for PR conversation responses.
.claude-plugin/fleet-skills/.source-digestUpdates skill distribution digest to match regenerated content.

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

Comment threadscripts/pr_review.py Outdated
CopilotAI review requested due to automatic review settings August 18, 2026 14:08

CopilotAI 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:

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

ptr727 commented Aug 18, 2026

Copy link
Copy Markdown
OwnerAuthor

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.

CopilotAI 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())

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

CopilotAI 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.

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

Copy link
Copy Markdown
OwnerAuthor

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.

CopilotAI 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 developAug 18, 2026
8 checks passed
@ptr727
ptr727 deleted the issue-805 branch August 18, 2026 14:38
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Route GitHub Writes Through Portable Tooling by ptr727 · Pull Request #808 · ptr727/ProjectTemplate · GitHub
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

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

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

CopilotAI 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
FileDescription
scripts/pr_review.pyAdds comment subcommand and GraphQL documents for PR conversation comments.
scripts/tests/test_pr_review.pyAdds comment command tests and updates write-document assertions.
scripts/README.mdDocuments the new comment workflow for suppressed findings.
GOVERNANCE.mdDeclares provider connectors read-only for fleet mutations and routes writes via hub tooling/gh.
.github/skills/pr-review-conduct/SKILL.mdInstructs using pr_review.py comment for suppressed findings and forbids connector mutations.
.agents/skills/pr-review-conduct/SKILL.mdSame guidance as the GitHub skill distribution copy.
.claude-plugin/fleet-skills/skills/pr-review-conduct/SKILL.mdSame guidance as the Claude skill distribution copy.
.github/copilot-instructions.mdUpdates runbook to include comment for PR conversation responses.
.claude-plugin/fleet-skills/.source-digestUpdates skill distribution digest to match regenerated content.

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

Comment threadscripts/pr_review.py Outdated
CopilotAI review requested due to automatic review settings August 18, 2026 14:08

CopilotAI 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:

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

ptr727 commented Aug 18, 2026

Copy link
Copy Markdown
OwnerAuthor

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.

CopilotAI 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())

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

CopilotAI 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.

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

Copy link
Copy Markdown
OwnerAuthor

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.

CopilotAI 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 developAug 18, 2026
8 checks passed
@ptr727
ptr727 deleted the issue-805 branch August 18, 2026 14:38
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Route GitHub Writes Through Portable Tooling by ptr727 · Pull Request #808 · ptr727/ProjectTemplate · GitHub
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

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

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

CopilotAI 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
FileDescription
scripts/pr_review.pyAdds comment subcommand and GraphQL documents for PR conversation comments.
scripts/tests/test_pr_review.pyAdds comment command tests and updates write-document assertions.
scripts/README.mdDocuments the new comment workflow for suppressed findings.
GOVERNANCE.mdDeclares provider connectors read-only for fleet mutations and routes writes via hub tooling/gh.
.github/skills/pr-review-conduct/SKILL.mdInstructs using pr_review.py comment for suppressed findings and forbids connector mutations.
.agents/skills/pr-review-conduct/SKILL.mdSame guidance as the GitHub skill distribution copy.
.claude-plugin/fleet-skills/skills/pr-review-conduct/SKILL.mdSame guidance as the Claude skill distribution copy.
.github/copilot-instructions.mdUpdates runbook to include comment for PR conversation responses.
.claude-plugin/fleet-skills/.source-digestUpdates skill distribution digest to match regenerated content.

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

Comment threadscripts/pr_review.py Outdated
CopilotAI review requested due to automatic review settings August 18, 2026 14:08

CopilotAI 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:

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

ptr727 commented Aug 18, 2026

Copy link
Copy Markdown
OwnerAuthor

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.

CopilotAI 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())

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

CopilotAI 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.

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

Copy link
Copy Markdown
OwnerAuthor

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.

CopilotAI 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 developAug 18, 2026
8 checks passed
@ptr727
ptr727 deleted the issue-805 branch August 18, 2026 14:38
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Route GitHub Writes Through Portable Tooling by ptr727 · Pull Request #808 · ptr727/ProjectTemplate · GitHub
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

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

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

CopilotAI 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
FileDescription
scripts/pr_review.pyAdds comment subcommand and GraphQL documents for PR conversation comments.
scripts/tests/test_pr_review.pyAdds comment command tests and updates write-document assertions.
scripts/README.mdDocuments the new comment workflow for suppressed findings.
GOVERNANCE.mdDeclares provider connectors read-only for fleet mutations and routes writes via hub tooling/gh.
.github/skills/pr-review-conduct/SKILL.mdInstructs using pr_review.py comment for suppressed findings and forbids connector mutations.
.agents/skills/pr-review-conduct/SKILL.mdSame guidance as the GitHub skill distribution copy.
.claude-plugin/fleet-skills/skills/pr-review-conduct/SKILL.mdSame guidance as the Claude skill distribution copy.
.github/copilot-instructions.mdUpdates runbook to include comment for PR conversation responses.
.claude-plugin/fleet-skills/.source-digestUpdates skill distribution digest to match regenerated content.

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

Comment threadscripts/pr_review.py Outdated
CopilotAI review requested due to automatic review settings August 18, 2026 14:08

CopilotAI 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:

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

ptr727 commented Aug 18, 2026

Copy link
Copy Markdown
OwnerAuthor

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.

CopilotAI 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())

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

CopilotAI 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.

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

Copy link
Copy Markdown
OwnerAuthor

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.

CopilotAI 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 developAug 18, 2026
8 checks passed
@ptr727
ptr727 deleted the issue-805 branch August 18, 2026 14:38
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Route GitHub Writes Through Portable Tooling by ptr727 · Pull Request #808 · ptr727/ProjectTemplate · GitHub
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

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

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

CopilotAI 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
FileDescription
scripts/pr_review.pyAdds comment subcommand and GraphQL documents for PR conversation comments.
scripts/tests/test_pr_review.pyAdds comment command tests and updates write-document assertions.
scripts/README.mdDocuments the new comment workflow for suppressed findings.
GOVERNANCE.mdDeclares provider connectors read-only for fleet mutations and routes writes via hub tooling/gh.
.github/skills/pr-review-conduct/SKILL.mdInstructs using pr_review.py comment for suppressed findings and forbids connector mutations.
.agents/skills/pr-review-conduct/SKILL.mdSame guidance as the GitHub skill distribution copy.
.claude-plugin/fleet-skills/skills/pr-review-conduct/SKILL.mdSame guidance as the Claude skill distribution copy.
.github/copilot-instructions.mdUpdates runbook to include comment for PR conversation responses.
.claude-plugin/fleet-skills/.source-digestUpdates skill distribution digest to match regenerated content.

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

Comment threadscripts/pr_review.py Outdated
CopilotAI review requested due to automatic review settings August 18, 2026 14:08

CopilotAI 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:

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

ptr727 commented Aug 18, 2026

Copy link
Copy Markdown
OwnerAuthor

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.

CopilotAI 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())

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

CopilotAI 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.

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

Copy link
Copy Markdown
OwnerAuthor

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.

CopilotAI 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 developAug 18, 2026
8 checks passed
@ptr727
ptr727 deleted the issue-805 branch August 18, 2026 14:38
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Route GitHub Writes Through Portable Tooling by ptr727 · Pull Request #808 · ptr727/ProjectTemplate · GitHub
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

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

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

CopilotAI 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
FileDescription
scripts/pr_review.pyAdds comment subcommand and GraphQL documents for PR conversation comments.
scripts/tests/test_pr_review.pyAdds comment command tests and updates write-document assertions.
scripts/README.mdDocuments the new comment workflow for suppressed findings.
GOVERNANCE.mdDeclares provider connectors read-only for fleet mutations and routes writes via hub tooling/gh.
.github/skills/pr-review-conduct/SKILL.mdInstructs using pr_review.py comment for suppressed findings and forbids connector mutations.
.agents/skills/pr-review-conduct/SKILL.mdSame guidance as the GitHub skill distribution copy.
.claude-plugin/fleet-skills/skills/pr-review-conduct/SKILL.mdSame guidance as the Claude skill distribution copy.
.github/copilot-instructions.mdUpdates runbook to include comment for PR conversation responses.
.claude-plugin/fleet-skills/.source-digestUpdates skill distribution digest to match regenerated content.

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

Comment threadscripts/pr_review.py Outdated
CopilotAI review requested due to automatic review settings August 18, 2026 14:08

CopilotAI 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:

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

ptr727 commented Aug 18, 2026

Copy link
Copy Markdown
OwnerAuthor

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.

CopilotAI 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())

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

CopilotAI 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.

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

Copy link
Copy Markdown
OwnerAuthor

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.

CopilotAI 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 developAug 18, 2026
8 checks passed
@ptr727
ptr727 deleted the issue-805 branch August 18, 2026 14:38
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Route GitHub Writes Through Portable Tooling by ptr727 · Pull Request #808 · ptr727/ProjectTemplate · GitHub
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

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

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

CopilotAI 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
FileDescription
scripts/pr_review.pyAdds comment subcommand and GraphQL documents for PR conversation comments.
scripts/tests/test_pr_review.pyAdds comment command tests and updates write-document assertions.
scripts/README.mdDocuments the new comment workflow for suppressed findings.
GOVERNANCE.mdDeclares provider connectors read-only for fleet mutations and routes writes via hub tooling/gh.
.github/skills/pr-review-conduct/SKILL.mdInstructs using pr_review.py comment for suppressed findings and forbids connector mutations.
.agents/skills/pr-review-conduct/SKILL.mdSame guidance as the GitHub skill distribution copy.
.claude-plugin/fleet-skills/skills/pr-review-conduct/SKILL.mdSame guidance as the Claude skill distribution copy.
.github/copilot-instructions.mdUpdates runbook to include comment for PR conversation responses.
.claude-plugin/fleet-skills/.source-digestUpdates skill distribution digest to match regenerated content.

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

Comment threadscripts/pr_review.py Outdated
CopilotAI review requested due to automatic review settings August 18, 2026 14:08

CopilotAI 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:

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

ptr727 commented Aug 18, 2026

Copy link
Copy Markdown
OwnerAuthor

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.

CopilotAI 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())

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

CopilotAI 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.

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

Copy link
Copy Markdown
OwnerAuthor

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.

CopilotAI 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 developAug 18, 2026
8 checks passed
@ptr727
ptr727 deleted the issue-805 branch August 18, 2026 14:38
Sign up for freeto 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

@ptr727