Skip to content

docs(graphite-pr): reconcile vendored copy with runtime canonical#65

Merged
George-RD merged 4 commits into
mainfrom
docs/graphite-pr-merge-reconcile
May 1, 2026
Merged

docs(graphite-pr): reconcile vendored copy with runtime canonical#65
George-RD merged 4 commits into
mainfrom
docs/graphite-pr-merge-reconcile

Conversation

@George-RD
Copy link
Copy Markdown
Owner

@George-RD George-RD commented Apr 30, 2026

Summary

  • Reconcile two-way drift between the vendored .claude/skills/graphite-pr/SKILL.md and the runtime canonical at ~/.agents/skills/graphite-pr/SKILL.md. Each had improvements the other lacked.
  • Merged section "After submit: merge" now keeps:
    • Runtime side: scripts/gt-merge-cascade.sh for stacks; GraphQL pre-flight (reviewThreads + reviewDecision) for single-PR safety net before gh pr merge.
    • Vendored side: diagnostic for when the Graphite / AI Reviews check doesn't appear; bottom-up gh pr merge alternative; --delete-branch cascade-close warning + --base $(gt trunk) workaround; "record SHA before gt sync --force" tip.
  • Quick-reference: split the "track an untracked branch" row into first-time (use literal trunk name — gt trunk errors when HEAD itself is untracked) and existing-stack (the original $(gt trunk) form). This came from a real failure during a Nazgûl run earlier today.
  • Runtime canonical at ~/.agents/skills/graphite-pr/SKILL.md mirrored to match — Claude continues to read it via the existing symlink at ~/.claude/skills/graphite-pr; Codex picks it up via its [[skills.config]] entry.

Test plan

  • Open the file and skim the merged "After submit: merge" section reads coherently end-to-end (no leftover bullets from one side, no contradictions).
  • diff -q ~/.agents/skills/graphite-pr/SKILL.md .claude/skills/graphite-pr/SKILL.md returns no output (sync verified locally; re-verify on merge).
  • Markdown lint stays green per repo .markdownlint.json.

🤖 Generated with Claude Code


Summary by cubic

Reconciled the vendored ./.claude/skills/graphite-pr/SKILL.md with the runtime canonical and hardened the merge flow with a vendored cascade script, stricter GraphQL gates, and clearer recovery guidance to prevent unsafe merges on large PRs. Also validated cascade script CLI args to preserve the JSON error contract.

  • Refactors
    • Vendored scripts/gt-merge-cascade.sh; script now validates CLI poll/timeout as positive integers, validates the stack, blocks on unresolved threads, CHANGES_REQUESTED, and >100-thread truncation, maps branches→PRs safely (fails if any branch lacks an open PR), runs gt merge, polls to completion, and emits JSON.
    • Single-PR gate: GraphQL pre-flight uses reviewThreads(first:100) with pageInfo.hasNextPagetruncated; merge only when unresolved == 0, decision != "CHANGES_REQUESTED", and truncated == false.
    • Docs: fixed broken troubleshooting link to references/recovery.md; kept the Graphite/AI Reviews diagnostic, bottom-up gh pr merge alternative, --delete-branch warning + --base $(gt trunk) workaround, SHA-before-sync tip; quick-reference splits first-time vs existing-stack gt track.

Written for commit 73b7002. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • New Features

    • Added automated merge-cascade: validates stack readiness, gates on unresolved review threads/decisions, performs merges, and reports per-PR timing and failures.
    • Added single-PR preflight to block merges when reviews are unresolved or changes are requested.
  • Documentation

    • Simplified merge instructions, added a “Graphite merge queue” option, explicit recovery guidance, and clearer first-time vs existing-branch tracking steps.

Two-way drift had developed: runtime had `gt-merge-cascade.sh` + GraphQL
review-thread pre-flight; vendored had Graphite/AI Reviews diagnostic +
bottom-up `gh pr merge` cascade warning + SHA-record-before-sync tip.
Merged section keeps both. Also splits the "track an untracked branch"
quick-reference row into first-time vs. existing-stack — `gt trunk`
errors when HEAD itself is untracked, so the original `$(gt trunk)`
form fails the very first time you need to track a branch.

Mirrored to ~/.agents/skills/graphite-pr/SKILL.md (canonical runtime
shared with Codex; Claude reads it via the existing symlink).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@qodo-code-review
Copy link
Copy Markdown

ⓘ You've reached your Qodo monthly free-tier limit. Reviews pause until next month — upgrade your plan to continue now, or link your paid account if you already have one.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 30, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3c7f2c6b-1bb3-420c-9ebd-eb10637f592e

📥 Commits

Reviewing files that changed from the base of the PR and between 68a14b2 and 73b7002.

📒 Files selected for processing (1)
  • .claude/skills/graphite-pr/scripts/gt-merge-cascade.sh

📝 Walkthrough

Walkthrough

Adds a gt-merge-cascade script and updates the Graphite PR skill docs to gate merges on unresolved review threads via a GraphQL pre‑flight and dry‑run validation, replaces status-check rollup polling, refines single‑PR and branch‑tracking instructions, and emits JSON merge results with per‑PR latencies.

Changes

Cohort / File(s) Summary
Graphite PR Skill Documentation
​.claude/skills/graphite-pr/SKILL.md
Update post-submit flow: replace Graphite / AI Reviews status-check polling with direct merge gating; add GraphQL pre‑flight rules for single PRs (check reviewDecision, count unresolved non‑outdated reviewThreads, detect pagination truncation); add "Graphite merge queue" option; split branch‑tracking quick reference; point to recovery docs.
Merge Automation Script
​.claude/skills/graphite-pr/scripts/gt-merge-cascade.sh
Add gt-merge-cascade.sh: validates args, runs gt merge --dry-run and parses branches, resolves branches→PRs via gh pr list, queries GitHub GraphQL for reviewDecision and up to 100 reviewThreads, aborts on unresolved threads/CHANGES_REQUESTED/truncation, runs gt merge --no-interactive, polls PR states until merged or fails on closed/timeout, outputs JSON success/failure with per‑PR latencies.

Sequence Diagram(s)

sequenceDiagram
    participant Dev as Developer
    participant Script as gt-merge-cascade.sh
    participant GT as gt (Graphite)
    participant GH as GitHub GraphQL API
    participant PR as Pull Request records

    Dev->>Script: invoke cascade (optional interval/timeout)
    Script->>GT: gt merge --dry-run
    GT-->>Script: dry-run output (branch list / readiness)
    Script->>GH: map branches -> open PR numbers (gh pr list)
    Script->>GH: GraphQL query per-PR (reviewDecision, first 100 reviewThreads)
    GH-->>Script: reviewDecision, reviewThreads, pagination info
    alt any unresolved OR decision == "CHANGES_REQUESTED" OR truncated
        Script->>Dev: abort with JSON {reason, detail}
    else
        Script->>GT: gt merge --no-interactive
        GT-->>Script: merge initiated
        loop poll until all merged or timeout
            Script->>GH: gh pr view (PR state)
            GH-->>Script: state (MERGED/CLOSED/OPEN/other)
            alt state == MERGED
                Script-->>Script: record merge timestamp for PR
            else if state == CLOSED without MERGED
                Script->>Dev: fail cascade with JSON {reason, detail}
            end
        end
        Script->>Dev: output JSON success (total duration, PR count, per-PR latencies)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • cubic-dev-ai

Poem

🐰 I dry-run the hills and sniff the queue,
Checking threads so merges go true,
Cascades hum, each PR takes flight,
JSON counts latencies through the night,
I hop, I tap—everything's alright.


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
All Comments Resolved ❌ Error PR #65 has unresolved review comments from CodeRabbit requesting CLI input validation for POLL_INTERVAL and TIMEOUT_MINUTES parameters. Add regex validation in gt-merge-cascade.sh to ensure parameters are positive integers, emit JSON failure responses, and request re-review after code changes.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main objective of the PR: reconciling drift between vendored and runtime canonical files for the graphite-pr skill documentation.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/graphite-pr-merge-reconcile

Review rate limit: 2/5 reviews remaining, refill in 28 minutes and 19 seconds.

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

Copy link
Copy Markdown

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

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: 9efbd9c782

ℹ️ 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 .claude/skills/graphite-pr/SKILL.md
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/skills/graphite-pr/SKILL.md:
- Around line 94-95: Clarify that the merge gate condition ("unresolved == 0"
and "decision != \"CHANGES_REQUESTED\"") must be evaluated against the JSON
printed by the pre-flight command (the pre-flight/jq output that contains the
decision and unresolved fields), so update the wording to explicitly say
"compare the pre-flight JSON's decision and unresolved fields" (i.e., use the
JSON output from pre-flight as the source of truth) and note that a null
decision in that JSON is acceptable; keep the existing note that gt merge
ignores comment state so this JSON check is the safety net.
- Around line 88-92: The GraphQL query uses reviewThreads(first:50) which can
truncate results; update the query to request up to first:100 and add pageInfo {
hasNextPage endCursor } to detect truncation (or implement cursor-based
pagination) and loop using endCursor to fetch remaining reviewThreads until
hasNextPage is false; ensure you still extract reviewDecision and node fields
isResolved and isOutdated, and log/warn if more pages existed if you choose only
to warn instead of fully paginating.
🪄 Autofix (Beta)

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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d9674853-b132-4d47-b953-6d441df42ad9

📥 Commits

Reviewing files that changed from the base of the PR and between 46591aa and 9efbd9c.

📒 Files selected for processing (1)
  • .claude/skills/graphite-pr/SKILL.md

Comment thread .claude/skills/graphite-pr/SKILL.md
Comment thread .claude/skills/graphite-pr/SKILL.md Outdated
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 1 file

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".claude/skills/graphite-pr/SKILL.md">

<violation number="1" location=".claude/skills/graphite-pr/SKILL.md:82">
P1: `scripts/gt-merge-cascade.sh` is referenced as the primary stack-merge path but does not exist in the repository. Anyone (or any agent) following this instruction will hit "file not found" immediately. Either add the script at the documented path or rewrite this guidance to use an available command.</violation>
</file>
Architecture diagram
sequenceDiagram
    participant Agent as Claude / Codex
    participant Skills as SKILL.md (Canonical & Vendored)
    participant Local as Local Repo (git / gt CLI)
    participant Script as scripts/gt-merge-cascade.sh
    participant GH as GitHub API / CLI
    participant GCloud as Graphite Cloud (App)

    Note over Agent,Skills: Initialization: Agent loads instructions via symlink or config
    Agent->>Skills: Read merge & tracking protocols

    Note over Agent,Local: Flow A: Stack Management
    alt NEW: First-time tracking (HEAD untracked)
        Agent->>Local: gt track --parent <literal_trunk>
    else Existing stack tracking
        Agent->>Local: gt track --parent "$(gt trunk)"
    end

    Note over Agent,GH: Flow B: Single PR Merge (Manual)
    Agent->>GH: NEW: GraphQL query (reviewThreads + reviewDecision)
    GH-->>Agent: JSON (unresolved thread count)
    
    alt Safety Check: unresolved == 0 AND decision != CHANGES_REQUESTED
        Agent->>GH: gh pr merge --squash --delete-branch
    else Unhappy Path: Unresolved threads or blocked
        Agent->>Agent: Surface diagnostic to user
    end

    Note over Agent,Script: Flow C: Stack Merge (Automated)
    Agent->>Script: CHANGED: Execute gt-merge-cascade.sh
    activate Script
    Script->>GH: NEW: GraphQL pre-flight (unresolved threads)
    Script->>Local: gt merge (with 30s polling)
    Script-->>Agent: Return execution JSON
    deactivate Script

    Note over Agent,GCloud: Flow D: Alternative (Cloud Queue)
    Agent->>GCloud: Toggle "Merge when ready"
    GCloud->>GH: Bottom-up merge + auto-restack

    Note over Agent,Local: Post-Merge Cleanup
    Agent->>Local: git rev-parse (Record SHA)
    Agent->>Local: gt sync --no-interactive --force
    Note right of Local: Sync deletes local tracking for closed branches
Loading

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

Comment thread .claude/skills/graphite-pr/SKILL.md
…nate threads, clarify gate

- Vendor `scripts/gt-merge-cascade.sh` (codex P2): the runtime canonical
  had it but the repo path was broken — agents reading the vendored
  SKILL.md and following `scripts/gt-merge-cascade.sh` would fail.
- Bump GraphQL `reviewThreads` to `first:100` and add
  `pageInfo.hasNextPage` -> `truncated` (CodeRabbit Major): the previous
  `first:50` would silently miss unresolved threads on big PRs and let
  unsafe merges through.
- Tie merge-gate condition explicitly to "the JSON printed above"
  (CodeRabbit Minor): removes ambiguity about where decision/unresolved
  come from. Add `truncated == false` to the merge precondition.

Mirrored to ~/.agents/skills/graphite-pr/SKILL.md.

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

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/skills/graphite-pr/scripts/gt-merge-cascade.sh:
- Around line 36-40: The loop silently drops branches with no open PRs; instead,
change the logic in the branch iteration that uses BRANCHES and PR_LIST so it
fails fast when any branch has no mapped open PR: after calling gh pr list for a
given branch, if the result (variable pr) is empty, immediately call fail (the
existing fail function) with a clear error and include the branch name (e.g.,
"no-open-pr" and branch info) rather than continuing; continue to append valid
PR numbers to PR_LIST when present.
- Around line 49-55: The GraphQL query that computes n uses
reviewThreads(first:50) and misses pagination causing unresolved threads beyond
50 to be ignored; update the gh api/graphql call (the block that sets n and the
loop that aggregates UNRESOLVED_DETAIL) to page through reviewThreads using
pageInfo.hasNextPage and an after cursor, repeatedly requesting subsequent pages
until hasNextPage is false, accumulate the count (or unresolved nodes) across
pages instead of relying on a single first:50 response, and preserve the current
error handling that sets n="ERR" and appends to UNRESOLVED_DETAIL when
unresolved threads are found.
🪄 Autofix (Beta)

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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 774505de-ce4a-42cc-b5ca-013e3d713036

📥 Commits

Reviewing files that changed from the base of the PR and between 9efbd9c and 3939cfc.

📒 Files selected for processing (2)
  • .claude/skills/graphite-pr/SKILL.md
  • .claude/skills/graphite-pr/scripts/gt-merge-cascade.sh

Comment thread .claude/skills/graphite-pr/scripts/gt-merge-cascade.sh Outdated
Comment thread .claude/skills/graphite-pr/scripts/gt-merge-cascade.sh Outdated
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".claude/skills/graphite-pr/scripts/gt-merge-cascade.sh">

<violation number="1" location=".claude/skills/graphite-pr/scripts/gt-merge-cascade.sh:38">
P2: Branches with no open PR are silently dropped from `PR_LIST`. If only some stack branches have open PRs, the script proceeds with partial coverage — the review-thread gate and merge polling will only cover the mapped PRs, and the script can exit with `"result":"success"` even though unmapped branches were never checked or tracked. Fail explicitly when a branch cannot be mapped to an open PR.</violation>

<violation number="2" location=".claude/skills/graphite-pr/scripts/gt-merge-cascade.sh:49">
P2: The unresolved-thread merge gate only checks the first 50 review threads, so PRs with more threads can be merged even when unresolved threads still exist.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

Comment thread .claude/skills/graphite-pr/scripts/gt-merge-cascade.sh Outdated
Comment thread .claude/skills/graphite-pr/scripts/gt-merge-cascade.sh Outdated
Palantir debate (Sauron + Saruman) found four real defects on top of the
external-reviewer feedback already addressed in 3939cfc:

1. SKILL.md "load references/troubleshooting.md" pointed at a file that
   does not exist. Switched to references/recovery.md, which exists and
   covers cascade-recovery / split / conflicts / auth handoff.

2. Cascade script still queried reviewThreads(first:50) with no
   truncation guard — the SKILL.md inline pre-flight had been bumped to
   first:100 + truncated, but the *primary* hot path the doc tells you
   to use first was untouched. Bumped script to first:100, added
   pageInfo.hasNextPage, fail "review-threads-truncated" on >100.

3. Script gated only on unresolved threads; SKILL.md gated on that PLUS
   reviewDecision != CHANGES_REQUESTED. A PR a maintainer explicitly
   blocked with all threads resolved would sail through. Added
   reviewDecision to the GraphQL query and a "changes-requested" failure
   path so the script gate matches the documented gate.

4. Branch -> PR mapping used unquoted `for branch in $BRANCHES` (word
   split + glob expansion on branch names) and silently dropped any
   branch that had no open PR. Switched to `while IFS= read -r` and now
   fail loudly with "stack-branch-without-pr" listing the offenders, so
   the cascade does not merge a truncated subset of the dry-run-validated
   stack.

Mirrored to ~/.agents/skills/graphite-pr/. bash -n syntax-clean.

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

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

0 issues found across 2 files (changes from recent commits).

Requires human review: Auto-approval blocked by 1 unresolved issue from previous reviews.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/skills/graphite-pr/scripts/gt-merge-cascade.sh:
- Around line 15-17: Validate the CLI numeric inputs before performing shell
arithmetic or calling sleep: ensure POLL_INTERVAL and TIMEOUT_MINUTES (the
variables set in the top-level assignment and used to compute TIMEOUT_SECONDS)
are positive integers using a numeric check (e.g. regex or integer-only test)
and reject non-numeric, zero or negative values by emitting the same structured
JSON failure (the JSON error pattern referenced in lines 7-11) and exiting; do
the same validation immediately before the later sleep/usage at the location
around line 116 so no arithmetic or sleep is attempted with invalid values.
🪄 Autofix (Beta)

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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d09f175f-c500-4bef-8819-3cd92337697a

📥 Commits

Reviewing files that changed from the base of the PR and between 3939cfc and 68a14b2.

📒 Files selected for processing (2)
  • .claude/skills/graphite-pr/SKILL.md
  • .claude/skills/graphite-pr/scripts/gt-merge-cascade.sh

Comment thread .claude/skills/graphite-pr/scripts/gt-merge-cascade.sh Outdated
CodeRabbit Major (line 17): if either arg is non-numeric, the arithmetic
on TIMEOUT_MINUTES and the later `sleep "$POLL_INTERVAL"` call would
either error out or behave unpredictably, breaking the JSON failure
contract the script promises.

Moved json_str/fail above the arg parsing so we can fail loudly with a
proper JSON envelope, then validate both args against `^[1-9][0-9]*$`
(positive integer, no leading zero, no zero, no negative). Both argument
positions tested: invalid string -> "invalid-poll-interval" JSON, zero ->
same, valid args pass through to the gt merge stage as before.

Mirrored to ~/.agents/skills/graphite-pr/scripts/.

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

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

0 issues found across 1 file (changes from recent commits).

Requires human review: Auto-approval blocked by 1 unresolved issue from previous reviews.

@George-RD George-RD merged commit e639363 into main May 1, 2026
2 checks passed
@George-RD George-RD deleted the docs/graphite-pr-merge-reconcile branch May 1, 2026 05:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant