Skip to content

fix: clarify draft ready GraphQL mutation - #1985

Closed
stranske wants to merge 3 commits into
mainfrom
sync-review-1836-graphql
Closed

fix: clarify draft ready GraphQL mutation#1985
stranske wants to merge 3 commits into
mainfrom
sync-review-1836-graphql

Conversation

@stranske

Copy link
Copy Markdown
Owner

Summary

  • Moves the draft ready-for-review GraphQL mutation into a named constant with the outer selection set explicit.
  • Adds a focused runner test assertion that the emitted mutation is the ready-for-review mutation and has balanced braces.

Validation

  • node --test .github/scripts/tests/keepalive-orchestrator-gate-runner.test.js
  • git diff --check

Source fix for sync-generated consumer PR review thread: stranske/Travel-Plan-Permission#1004.

Copilot AI review requested due to automatic review settings April 30, 2026 07:24
@stranske-keepalive

stranske-keepalive Bot commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Automated Status Summary

Head SHA: fd540e9
Latest Runs: ⏳ pending — Gate
Required contexts: Gate / gate, Health 45 Agents Guard / guard
Required: core tests (3.12): ⏳ pending, core tests (3.13): ⏳ pending, docker smoke: ⏳ pending, gate: ⏳ pending

Workflow / Job Result Logs
(no jobs reported) ⏳ pending

Coverage Overview

  • Coverage history entries: 1

Coverage Trend

Metric Value
Current 93.12%
Baseline 85.00%
Delta +8.12%
Minimum 70.00%
Status ✅ Pass

Top Coverage Hotspots (lowest coverage)

File Coverage Missing
src/cli_parser.py 81.8% 4
src/percentile_calculator.py 95.0% 1
src/aggregator.py 95.0% 2
src/__init__.py 100.0% 0
src/ndjson_parser.py 100.0% 0

Updated automatically; will refresh on subsequent CI/Docker completions.


Keepalive checklist

Scope

No scope information available

Tasks

  • No tasks defined

Acceptance criteria

  • No acceptance criteria defined

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 PR clarifies the “mark draft PR ready for review” GraphQL mutation used by the keepalive orchestrator gate runner by centralizing the mutation text in a named constant and adding a targeted regression assertion in the runner test.

Changes:

  • Introduces a named MARK_DRAFT_READY_FOR_REVIEW_MUTATION constant with an explicit outer selection set.
  • Updates the gate runner to pass the constant into github.graphql(...) instead of an inline template literal.
  • Adds a test assertion that the emitted mutation is the expected ready-for-review mutation and that braces are balanced.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
templates/consumer-repo/.github/scripts/keepalive_orchestrator_gate_runner.js Intended to mirror the mutation-constant refactor for consumer templates.
.github/scripts/keepalive_orchestrator_gate_runner.js Refactors the ready-for-review GraphQL mutation into a named constant and uses it in markDraftReadyForReview.
.github/scripts/__tests__/keepalive-orchestrator-gate-runner.test.js Adds assertions validating the mutation emitted for checklist-complete draft PR conversion.

Comment on lines +439 to +442
const braceBalance = [...github.__calls.graphql[0].query].reduce(
(balance, char) => balance + (char === '{' ? 1 : char === '}' ? -1 : 0),
0
);

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

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

The brace-balance assertion only checks the final {/} count, so it can still pass for improperly nested braces (e.g., a leading } followed by { later). If the goal is to ensure the mutation has properly balanced braces, also assert that the running balance never drops below 0 while iterating through the query string.

Suggested change
const braceBalance = [...github.__calls.graphql[0].query].reduce(
(balance, char) => balance + (char === '{' ? 1 : char === '}' ? -1 : 0),
0
);
let braceBalance = 0;
for (const char of github.__calls.graphql[0].query) {
if (char === '{') {
braceBalance += 1;
} else if (char === '}') {
braceBalance -= 1;
}
assert.ok(braceBalance >= 0);
}

Copilot uses AI. Check for mistakes.
Comment on lines 114 to 123
}

async function markDraftReadyForReview({ github, pr, core, summary }) {
const nodeId = String(pr?.node_id || '').trim();
if (!nodeId || typeof github.graphql !== 'function') {
summary.addRaw('Draft PR could not be converted automatically: missing GraphQL PR node id.').addEOL();
return false;
}

try {

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

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

The consumer template version of this runner is still using an inline anonymous GraphQL mutation string in markDraftReadyForReview, which means it won’t get the clarified named/fully-braced mutation used by the repo-local script. To keep consumer templates in sync with the source script, introduce the shared MARK_DRAFT_READY_FOR_REVIEW_MUTATION constant here and pass it to github.graphql(...) just like in .github/scripts/keepalive_orchestrator_gate_runner.js.

Copilot uses AI. Check for mistakes.
stranske added a commit that referenced this pull request May 5, 2026
…back (#2010)

* fix(keepalive): handle no-checklist draft PRs with accurate disposition

Phase 6 sync-PR review surfaced two related bugs in
keepalive_orchestrator_gate_runner.js (Copilot review on stranske/*
sync PRs):

- routeDraftToHuman() emitted "0 unchecked checklist item(s)" when
  the PR had no checkboxes at all, suggesting the user just needed
  to check boxes that didn't exist.
- The branching at line 404 fell through to the same "needs human"
  path for both genuine missing-acceptance-items cases and PRs that
  legitimately have no checklist at all.

This change distinguishes the no-checklist case end-to-end:

- Adds a noChecklist flag in the caller (computed once where
  checkboxCounts is built).
- Threads noChecklist through routeDraftToHuman so the comment body
  and summary line accurately describe "no acceptance checklist
  found" vs "N unchecked items".
- Adds a distinct reason key 'pr-draft-no-checklist' so weekly
  metrics can distinguish the two cases.

Lockstep edit: canonical .github/scripts/ + templates/consumer-repo/
both updated identically. node --check passes on both.

Out of scope here: the perceived "missing closing brace" Copilot
flagged was already addressed by PR #1985 / #1986 on 2026-04-30 —
the GraphQL mutation block in markDraftReadyForReview() has the
correct three closing braces. The isConcreteAgentLabel() concern
about agent:rate-limited / agent:retry routing as concrete agent
labels is separate and needs broader review of the keepalive
loop's label-routing semantics; deferred.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(state-fingerprint): graceful fallback on 401/403 + use BRANCH_PROTECTION_TOKEN in health-44

Wave 1's state-fingerprint helper (#1998 + #2002 wireup) broke
Health 44 enforce because the workflow's GITHUB_TOKEN can't access
the actions/variables endpoint even with `actions: write` set —
that endpoint requires a token with Variables permission (PAT,
GitHub App, or fine-grained PAT).

Resulting failure observed on every PR running Health 44 enforce
since #2002 merged (incl. PR #2006, PR #2007 today):

  GET /repos/stranske/Workflows/actions/variables/STATE_FINGERPRINT_HEALTH_44_GATE_BRANCH_PROTECTION_*
  failed: 403 "Resource not accessible by integration"

Two-part fix:

1) `scripts/state_fingerprint.py` — `RepoVariableStorage` now treats
   401/403 from the variables API as "storage unavailable" rather
   than fatal. Read returns None (no prior fingerprint), write skips
   silently, and a warning goes to stderr so the operator sees the
   misconfiguration in workflow logs. The existing 404 (no prior)
   path is unchanged.

   Effect: any workflow that adopts `--storage repo-variable` but
   doesn't have the right token degrades gracefully (skips the
   optimization, runs anyway) instead of failing outright. Future
   Wave 1+ workflows using repo-variable storage benefit from this.

2) `.github/workflows/health-44-gate-branch-protection.yml` — uses
   `BRANCH_PROTECTION_TOKEN` (already used downstream by `enforce`)
   when present, falling back to `GITHUB_TOKEN`. Now the
   fingerprint optimization actually works when the secret is
   configured.

Existing 6 tests in tests/scripts/test_state_fingerprint.py still
pass. py_compile clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore: apply Black formatting to state_fingerprint.py 401/403 fallback

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@stranske

Copy link
Copy Markdown
Owner Author

Closing as superseded by current main and #2117. The named ready-for-review mutation is already on main, and #2117 addressed the remaining actionable review note by checking running brace balance instead of only final brace counts.

@stranske stranske closed this May 14, 2026
@stranske
stranske deleted the sync-review-1836-graphql branch May 14, 2026 23:47
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