{"id":"bae80c39-9c8c-437a-8bdd-d1bb6ca58263","entityType":"agent","slug":"clawhub-drumrobot-github-flow","name":"github-flow","canonicalUrl":"https://www.xpersona.co/agent/clawhub-drumrobot-github-flow","canonicalPath":"/agent/clawhub-drumrobot-github-flow","generatedAt":"2026-10-10T01:12:11.332Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T12:44:38.185Z","emptyReason":null},"description":"GitHub issue/PR workflow automation. Topics — auth-scope (gh CLI priority + account mapping + batch scope refresh + 404 checklist), commit-message-discipline (commit message authoring + amend refresh + PUBLIC English enforcement), dependencies (blocked-by/sub-issues via GraphQL), epic-bundle (deferred findings → Epic + sub-issues), expand (expand-vs-split mid-work), identity-auth (gh account map + scope refresh + GH_TOKEN fallback), merge (CI/review gates + no autonomous push), plan-to-issue (MD → issue body), pr (PR with test plan), publish (branch + draft PR + CI watch + ready + merge, one topic), push-guards (branch/push-reject/force-push/main-push), register (dup check + strategy), review (structured comments), review-apply (deferred feedback apply), sanitize (PUBLIC repo personal data scan), upstream-issue (external OSS feature/bug). Use when: \"plan to issue\", \"issue register\", \"create PR\", \"PR body\", \"code review\", \"merge PR\", \"PR squash\", \"sanitize\", \"PII\", \"expand PR\", \"blocked by\", \"epic bundle\", \"upstream issue\", \"review apply\", \"sub-issue\", \"gh auth\", \"force push\", \"push reject\", \"branch change forbid\", \"auth scope\", \"account mapping\", \"scope refresh\", \"commit message\", \"PUBLIC repo English\".","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 2.6K downloads reported by the source. Last updated 10/9/2026.","installCommand":"clawhub skill install s17ay1v6v88r2m102pvvc44gz183qcrm:github-flow","sourceUrl":"https://clawhub.ai/drumrobot/github-flow","homepage":"https://clawhub.ai/drumrobot/skills/github-flow","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/drumrobot/github-flow","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/drumrobot/skills/github-flow","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":68,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"github-flow technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-09T12:44:38.185Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T12:44:38.185Z","emptyReason":null},"stars":null,"forks":null,"downloads":2628,"packageName":null,"latestVersion":"0.11.3","tractionLabel":"2.6K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T12:44:38.185Z","emptyReason":null},"lastUpdatedAt":"2026-10-09T12:44:38.185Z","lastCrawledAt":"2026-10-09T12:44:38.185Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-10T12:44:38.185Z","lastVerifiedAt":null,"highlights":[{"version":"0.11.3","createdAt":"2026-09-27T15:52:02.009Z","changelog":"- Documentation updates across multiple guides, including CHANGELOG.md, epic-bundle.md, identity-auth.md, merge.md, pr.md, and publish.md - Removed deprecated or obsolete file: skill-card.md - No changes to core logic or code functionality; updates focus on content and guide maintenance","fileCount":26,"zipByteSize":128445},{"version":"0.11.2","createdAt":"2026-09-24T14:19:36.184Z","changelog":"- Updated documentation: revised CHANGELOG.md and auth-scope.md to reflect recent changes. - Removed skill-card.md file. - No functional changes; this update is documentation and cleanup only.","fileCount":26,"zipByteSize":125065},{"version":"0.11.1","createdAt":"2026-09-20T11:23:11.835Z","changelog":"- Updated documentation in CHANGELOG.md and auth-scope.md. - Removed obsolete skill-card.md file. - No functional changes to the skill logic.","fileCount":26,"zipByteSize":124443},{"version":"0.11.0","createdAt":"2026-09-18T15:53:31.493Z","changelog":"- Removed the skill-card.md file. - Updated content in CHANGELOG.md and merge.md. - No changes to the primary SKILL.md. - Minor documentation and topic/guide adjustments.","fileCount":26,"zipByteSize":123495},{"version":"0.10.2","createdAt":"2026-09-10T05:56:10.573Z","changelog":"- Removed obsolete file: skill-card.md. - Updated guides for merge, pr, and publish processes. - Revised documentation in CHANGELOG.md. - Minor edits across multiple topic guide files for clarity and accuracy.","fileCount":26,"zipByteSize":122883},{"version":"0.10.1","createdAt":"2026-09-01T22:38:00.993Z","changelog":"- Removed the redundant skill-card.md file. - Updated CHANGELOG.md and pr.md with latest changes. - No changes to core logic or documentation in SKILL.md.","fileCount":26,"zipByteSize":122296},{"version":"0.10.0","createdAt":"2026-08-30T11:13:27.968Z","changelog":"github-flow 0.10.0 - Updated documentation: CHANGELOG.md, merge.md, publish.md, and resources/block-pr-url-gate.sh received changes to clarify or improve workflow guidance. - Removed the outdated skill-card.md file. - No functional runtime logic changes; updates are documentation and guide improvements only.","fileCount":26,"zipByteSize":121843},{"version":"0.9.1","createdAt":"2026-08-26T17:25:58.749Z","changelog":"- Added resources/block-pr-url-gate.sh (shell script for validating PR URLs in AskUserQuestion payloads). - pr topic doc updated: clarified that block-pr-url-gate.sh is not currently registered in any hook config; PR URL rule is author-enforced, not runtime-enforced. - Updated documentation in SKILL.md, merge.md, and CHANGELOG.md to reflect PR URL gate script and rule clarification. - Removed obsolete skill-card.md file.","fileCount":26,"zipByteSize":118492}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17ay1v6v88r2m102pvvc44gz183qcrm:github-flow","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s17ay1v6v88r2m102pvvc44gz183qcrm:github-flow` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/drumrobot/github-flow before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-drumrobot-github-flow/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-drumrobot-github-flow/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-drumrobot-github-flow/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-drumrobot-github-flow/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-drumrobot-github-flow/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-drumrobot-github-flow/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T01:12:11.327Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-drumrobot-github-flow/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-drumrobot-github-flow/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-drumrobot-github-flow/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-drumrobot-github-flow/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T12:44:38.185Z","emptyReason":null},"readme":"Skill: github-flow\n\nOwner: drumrobot\n\nSummary: GitHub issue/PR workflow automation. Topics — auth-scope (gh CLI priority + account mapping + batch scope refresh + 404 checklist), commit-message-discipline (commit message authoring + amend refresh + PUBLIC English enforcement), dependencies (blocked-by/sub-issues via GraphQL), epic-bundle (deferred findings → Epic + sub-issues), expand (expand-vs-split mid-work), identity-auth (gh account map + scope refresh + GH_TOKEN fallback), merge (CI/review gates + no autonomous push), plan-to-issue (MD → issue body), pr (PR with test plan), publish (branch + draft PR + CI watch + ready + merge, one topic), push-guards (branch/push-reject/force-push/main-push), register (dup check + strategy), review (structured comments), review-apply (deferred feedback apply), sanitize (PUBLIC repo personal data scan), upstream-issue (external OSS feature/bug). Use when: \"plan to issue\", \"issue register\", \"create PR\", \"PR body\", \"code review\", \"merge PR\", \"PR squash\", \"sanitize\", \"PII\", \"expand PR\", \"blocked by\", \"epic bundle\", \"upstream issue\", \"review apply\", \"sub-issue\", \"gh auth\", \"force push\", \"push reject\", \"branch change forbid\", \"auth scope\", \"account mapping\", \"scope refresh\", \"commit message\", \"PUBLIC repo English\".\n\nTags: latest:0.11.3\n\nVersion history:\n\nv0.11.3 | 2026-09-27T15:52:02.009Z | auto\n\n- Documentation updates across multiple guides, including CHANGELOG.md, epic-bundle.md, identity-auth.md, merge.md, pr.md, and publish.md\n- Removed deprecated or obsolete file: skill-card.md\n- No changes to core logic or code functionality; updates focus on content and guide maintenance\n\nv0.11.2 | 2026-09-24T14:19:36.184Z | auto\n\n- Updated documentation: revised CHANGELOG.md and auth-scope.md to reflect recent changes.\n- Removed skill-card.md file.\n- No functional changes; this update is documentation and cleanup only.\n\nv0.11.1 | 2026-09-20T11:23:11.835Z | auto\n\n- Updated documentation in CHANGELOG.md and auth-scope.md.\n- Removed obsolete skill-card.md file.\n- No functional changes to the skill logic.\n\nv0.11.0 | 2026-09-18T15:53:31.493Z | auto\n\n- Removed the skill-card.md file.\n- Updated content in CHANGELOG.md and merge.md.\n- No changes to the primary SKILL.md.\n- Minor documentation and topic/guide adjustments.\n\nv0.10.2 | 2026-09-10T05:56:10.573Z | auto\n\n- Removed obsolete file: skill-card.md.\n- Updated guides for merge, pr, and publish processes.\n- Revised documentation in CHANGELOG.md.\n- Minor edits across multiple topic guide files for clarity and accuracy.\n\nv0.10.1 | 2026-09-01T22:38:00.993Z | auto\n\n- Removed the redundant skill-card.md file.\n- Updated CHANGELOG.md and pr.md with latest changes.\n- No changes to core logic or documentation in SKILL.md.\n\nv0.10.0 | 2026-08-30T11:13:27.968Z | auto\n\ngithub-flow 0.10.0\n\n- Updated documentation: CHANGELOG.md, merge.md, publish.md, and resources/block-pr-url-gate.sh received changes to clarify or improve workflow guidance.\n- Removed the outdated skill-card.md file.\n- No functional runtime logic changes; updates are documentation and guide improvements only.\n\nv0.9.1 | 2026-08-26T17:25:58.749Z | auto\n\n- Added resources/block-pr-url-gate.sh (shell script for validating PR URLs in AskUserQuestion payloads).\n- pr topic doc updated: clarified that block-pr-url-gate.sh is not currently registered in any hook config; PR URL rule is author-enforced, not runtime-enforced.\n- Updated documentation in SKILL.md, merge.md, and CHANGELOG.md to reflect PR URL gate script and rule clarification.\n- Removed obsolete skill-card.md file.\n\nv0.9.0 | 2026-08-21T05:41:01.149Z | auto\n\n- Added account-switch-merge.md to document account switching during merge operations.\n- Updated CHANGELOG.md, merge.md, and pr.md with workflow and process improvements.\n- Removed skill-card.md, streamlining documentation.\n- General content and rule refinements for improved clarity and maintainability.\n\nv0.8.3 | 2026-08-18T05:41:42.705Z | auto\n\n- Added a new rule: check for existing open PRs before starting repo-wide or config-level fix work (HARD STOP).\n- Updated SKILL.md to include Rule 4, detailing how and why to avoid redundant or conflicting PRs.\n- Removed file: skill-card.md.\n- Minor clarifications and documentation changes across guides.\n- No changes to workflow logic or automation behavior.\n\nv0.8.2 | 2026-08-09T14:11:19.954Z | auto\n\n- Added dependency on the \"cleanup\" skill.\n- Removed obsolete skill-card.md file.\n- Updated documentation in SKILL.md and supporting guides for clarity and topic coverage.\n- Refined topic dependencies and usage descriptions.\n- Minor documentation and structural improvements across workflow topics.\n\nv0.8.1 | 2026-08-06T09:21:43.395Z | auto\n\n- Updated CHANGELOG.md, merge.md, and pr.md with latest changes.\n- Removed skill-card.md file.\n- Documentation and guides for merge and PR processes improved.\n- No changes to core logic or topic structure.\n\nv0.8.0 | 2026-08-04T07:32:56.445Z | auto\n\n- Added new \"publish\" topic guiding the full branch → draft PR → CI → ready → merge workflow in one sequence.\n- Updated SKILL.md to document the \"publish\" topic and its purpose.\n- Removed obsolete skill-card.md file.\n- Clarified the \"pr\" topic with details on PR references and link requirements.\n- Minor restructuring and cleanup in SKILL.md topic descriptions.\n\nv0.7.0 | 2026-07-23T13:39:30.522Z | auto\n\n## github-flow 0.7.0\n\n- Removed: `skill-card.md` file.\n- Updated: `CHANGELOG.md` file to reflect recent changes.\n- No updates to skill logic or user-facing documentation in SKILL.md.\n\nv0.6.1 | 2026-07-19T05:39:01.430Z | auto\n\n## github-flow 0.6.1\n\n- Updated documentation in CHANGELOG.md and sanitize.md to improve accuracy and clarity.\n- Removed skill-card.md from the project.\n- No functional or behavioral changes; this release is documentation cleanup and maintenance.\n\nv0.6.0 | 2026-07-17T08:32:28.183Z | auto\n\n**Major expansion: Auth scope management and commit message discipline topics added, tightening GitHub workflow controls.**\n\n- Added topics: `auth-scope` (CLI/account/scope refresh/404 detection) and `commit-message-discipline` (authoring, amend refresh, PUBLIC repo English, operation type, verb consistency).\n- Updated documentation to include these new guides and usage triggers (e.g., \"auth scope\", \"commit message\", \"PUBLIC repo English\").\n- Added supporting files: `auth-scope.md`, `commit-message-discipline.md`, plus helper scripts.\n- Removed deprecated guide: `skill-card.md`.\n- Revised topic list, applicability, and sample usage to reflect broader and stricter workflow automation coverage.\n\nv0.5.0 | 2026-07-08T14:27:37.584Z | auto\n\n- Added new \"epic-bundle\" topic: bundle deferred findings from multiple PRs into a single Epic issue with checklist, sub-issues, and epic label.\n- Updated architecture: clarified dependencies and flow for epic-bundle, including integration with plan-to-issue, register, and dependencies.\n- Expanded usage wording to include \"epic bundle\" in activation triggers.\n- Updated and expanded documentation for multiple topics and topic dependencies.\n\nv0.4.3 | 2026-07-04T07:20:46.239Z | auto\n\n- Improved documentation for review and review-apply workflows.\n- Clarified guide content in review.md and review-apply.md.\n- Updated CHANGELOG.md with recent changes.\n- No changes to SKILL.md logic or APIs.\n\nv0.4.2 | 2026-06-26T16:24:15.875Z | auto\n\n## GitHub Flow v0.4.2\n\n- Updated documentation: pr.md, sanitize.md, CHANGELOG.md with latest workflow and usage details.\n- Improved test plan verification logic in scripts/check-test-plan.js.\n- Removed outdated skill-card.md for clarity and maintenance.\n- General documentation cleanup and internal workflow refinements.\n\nv0.4.1 | 2026-06-19T23:10:48.253Z | auto\n\n## github-flow 0.4.1 Changelog\n\n- Updated documentation for: dependencies, identity-auth, merge, pr, and push-guards topics.\n- Improved and clarified content in markdown guides across several workflow topics.\n- Removed redundant skill-card.md file.\n- No functional workflow or API changes; all updates are documentation and content structure improvements.\n\nv0.4.0 | 2026-06-12T15:36:41.271Z | auto\n\nVersion 0.4.0\n\n- Added identity-auth: maps commit author to GitHub account, handles auth scope refresh, and GH_TOKEN fallback.\n- Added push-guards: prompts on branch changes/push rejection, restricts force pushes and main/shared branch pushes, checks CI before force push.\n- Changed: improved description and topics to reflect new authentication and push protection features.\n- Updated merge and pr to clarify lack of autonomous pushes and enhanced CI/review checks.\n- Removed outdated skill-card.md documentation.\n\nv0.3.0 | 2026-06-01T16:35:53.337Z | auto\n\n- Major update: Expanded skill to cover full GitHub issue/PR lifecycle including dependencies, merge/sanitize, and upstream issue registration.\n- Added new guides: dependencies, expand, merge, register, review-apply, sanitize, upstream-issue.\n- Introduced HARD STOP personal data (PII) scan for public repos before posting issue/PR content.\n- Workflow now manages native GitHub Issue Relationships (blocked-by/blocking) and enforces pre-merge dependency checks.\n- Skill automatically evaluates duplicate issues and supports deferred review feedback application.\n- Removed obsolete skill-card.md; improved modularity and topic organization.\n\nv0.1.0 | 2026-04-16T08:09:54.434Z | user\n\nInitial release: GitHub issue/PR workflow automation with plan-to-issue, structured PR creation, and code review topics\n\nArchive index:\n\nArchive v0.11.3: 26 files, 128445 bytes\n\nFiles: account-switch-merge.md (2649b), auth-scope.md (9434b), CHANGELOG.md (17343b), commit-message-discipline.md (8498b), dependencies.md (16295b), epic-bundle.md (11137b), expand.md (6107b), identity-auth.md (14990b), LICENSE (1063b), merge.md (62953b), plan-to-issue.md (15088b), pr.md (60437b), publish.md (4008b), push-guards.md (17493b), register.md (7524b), resources/block-pr-url-gate.sh (9860b), review-apply.md (7785b), review.md (3178b), sanitize.md (18839b), scripts/check-test-plan.js (3839b), scripts/gh-as.sh (708b), scripts/review-as.sh (2289b), skill-card.md (1970b), SKILL.md (8663b), upstream-issue.md (5551b), _meta.json (131b)\n\nFile v0.11.3:SKILL.md\n\n---\nname: github-flow\nmetadata:\n  author: es6kr\n  version: \"0.1.0\"\ndepends-on:\n  - cleanup\n  - code-workflow\n  - web-browser\ndescription: |\n  GitHub issue/PR workflow automation. Topics — auth-scope (gh CLI priority + account mapping + batch scope refresh + 404 checklist), commit-message-discipline (commit message authoring + amend refresh + PUBLIC English enforcement), dependencies (blocked-by/sub-issues via GraphQL), epic-bundle (deferred findings → Epic + sub-issues), expand (expand-vs-split mid-work), identity-auth (gh account map + scope refresh + GH_TOKEN fallback), merge (CI/review gates + no autonomous push), plan-to-issue (MD → issue body), pr (PR with test plan), publish (branch + draft PR + CI watch + ready + merge, one topic), push-guards (branch/push-reject/force-push/main-push), register (dup check + strategy), review (structured comments), review-apply (deferred feedback apply), sanitize (PUBLIC repo personal data scan), upstream-issue (external OSS feature/bug). Use when: \"plan to issue\", \"issue register\", \"create PR\", \"PR body\", \"code review\", \"merge PR\", \"PR squash\", \"sanitize\", \"PII\", \"expand PR\", \"blocked by\", \"epic bundle\", \"upstream issue\", \"review apply\", \"sub-issue\", \"gh auth\", \"force push\", \"push reject\", \"branch change forbid\", \"auth scope\", \"account mapping\", \"scope refresh\", \"commit message\", \"PUBLIC repo English\".\n---\n\n# GitHub Flow\n\nConvert plans, research, and implementation results into GitHub issues and PRs.\n\n## Topics\n\n| Topic | Description | Guide |\n|-------|-------------|-------|\n| auth-scope | gh CLI priority + account mapping + batch scope refresh + org-repo 404 checklist | [auth-scope.md](./auth-scope.md) |\n| commit-message-discipline | Commit message authoring, message update on amend, PUBLIC repo English enforcement, git operation type continuity, verb selection (`.md` as source code) | [commit-message-discipline.md](./commit-message-discipline.md) |\n| dependencies | Manage native Issue Relationships (blocked-by/blocking) via addBlockedBy/removeBlockedBy GraphQL mutations | [dependencies.md](./dependencies.md) |\n| epic-bundle | Bundle deferred review findings across multiple PRs into one Epic tracking issue (checklist + native sub-issues + epic label) | [epic-bundle.md](./epic-bundle.md) |\n| expand | Decide expand-vs-split when new findings emerge mid-work and update title/body | [expand.md](./expand.md) |\n| identity-auth | Owner-based gh account mapping for commit author identity + gh auth scope refresh + GH_TOKEN env fallback for org repo 404 | [identity-auth.md](./identity-auth.md) |\n| merge | CI success and AI review check then merge with commit cleanup, including pre-merge blockedBy verification | [merge.md](./merge.md) |\n| plan-to-issue | Convert plan/research MD to GitHub issue body or comments | [plan-to-issue.md](./plan-to-issue.md) |\n| pr | Create PR with structured body, test plan, and optional visual attachments. Every distinct PR number in an AskUserQuestion payload needs its own clickable URL — this is an authoring rule you apply yourself. `resources/block-pr-url-gate.sh` exists but is **not currently registered in any hook config**, so nothing enforces it at runtime | [pr.md](./pr.md) |\n| publish | Package a working-tree change into its own branch + draft PR against a staging-base branch, watch CI, ready-transition, content-review ask, merge — the full repeated sequence in one topic | [publish.md](./publish.md) |\n| push-guards | Branch-change ask + push rejection ask + force-push CI status check + main/master push restriction + shared-branch direct-push restriction | [push-guards.md](./push-guards.md) |\n| register | Evaluate duplicates and decide registration strategy (new issue vs comment vs sub-issue) | [register.md](./register.md) |\n| review | Review PR code and post structured review comments | [review.md](./review.md) |\n| review-apply | Apply deferred [REVIEW_FEEDBACK] items from fix_plan to code, update PR Summary | [review-apply.md](./review-apply.md) |\n| sanitize | HARD STOP scan for personal data before posting to PUBLIC repos | [sanitize.md](./sanitize.md) |\n| upstream-issue | Register feature requests/bug reports on external open-source repos with duplicate check + draft + sanitize | [upstream-issue.md](./upstream-issue.md) |\n\n## Topic Dependencies\n\n```text\ngithub-flow (issue/PR workflow)\n  ├─→ plan-to-issue (issue body content)\n  ├─→ epic-bundle (deferred findings across PRs → one Epic issue)\n  │     ├─→ uses plan-to-issue (Epic body) + register (dup check) + dependencies (sub-issues)\n  │     └─→ receives from: consolidate next step (auto-suggest when deferred findings accumulate)\n  ├─→ register (evaluate duplicates and decide strategy)\n  ├─→ pr (PR body content + visual attachments)\n  ├─→ review (post structured review comments)\n  ├─→ expand (mid-work scope expansion)\n  ├─→ dependencies (Issue Relationships: blocked-by/blocking)\n  │     └─→ used by merge step 5 (pre-merge blockedBy check)\n  ├─→ merge (CI/Review/Test Plan/blockedBy verification → squash+merge)\n  ├─→ review-apply (deferred [REVIEW_FEEDBACK] → code fix → Summary update)\n  │     └─→ receives from: consolidate Step 7 (deferred registration)\n  ├─→ sanitize (HARD STOP scan before posting to PUBLIC repos)\n  └─→ upstream-issue (external repo feature request/bug report with duplicate check + draft + sanitize)\n```\n\n- **dependencies → merge**: dependencies adds blockedBy relationships. merge.md step 5 queries the same field to gate merge until predecessors are CLOSED\n- **plan-to-issue → dependencies**: when a plan has frontmatter `chain:` declaring a sequential issue order, dependencies applies it to GitHub\n- All topics → sanitize: any text published to PUBLIC repos (issue body, PR body, comments, review text) must pass sanitize HARD STOP first\n\n## Applicability\n\nThis skill applies automatically when `git remote get-url origin` contains `github.com`. For non-GitHub remotes (GitLab, Bitbucket, etc.), this skill does not apply.\n\n## Core Rules\n\n### 1. Verification Plan Required\n\nEvery issue body and PR body must include a verification/test plan section. This is shared with code-workflow's plan step.\n\n### 2. No Internal Paths in Issues/PRs\n\n`.ralph/docs/`, `.ralph/fix_plan.md`, `.omc/` and other internal working paths must **never** appear in GitHub issue body, comments, or PR body. These are local-only artifacts.\n\n**Instead of**: \"See `.ralph/docs/generated/plan-180.md`\"\n**Write**: The actual content inline, or \"See the implementation plan comment below\"\n\n### 3. Body vs Comment Selection\n\n| Content Type | Target | Reason |\n|-------------|--------|--------|\n| Implementation plan (confirmed) | Issue body update | Stable reference for the issue |\n| Checklist (impl/verify) | Issue body update | Trackable via GitHub checkbox |\n| Discussion items / open questions | Issue comment | Threaded, time-stamped, doesn't clutter body |\n| Progress updates | Issue comment | Chronological record |\n| Review feedback summary | Issue comment | Preserves review history |\n\n### 4. Check for existing open PRs before starting repo-wide fix work (HARD STOP)\n\nBefore starting work on a repo-wide or config-level problem (broken CI config, a stale/misconfigured file affecting many components, a systemic lint failure, etc.), run `gh pr list -R <owner>/<repo> --state open` and skim titles for the same problem. Someone (including a past session under your own account) may have already fixed it in an unmerged PR.\n\n**Why**: independently re-deriving a fix that already exists in an open PR wastes the work, and — worse — if both land, the later one can silently supersede or conflict with the earlier one without either author knowing. Case: a claude-plugins CI-fix session spent significant work rebuilding `release-please-config.json`'s `packages` list from scratch, unaware that PR #17 (same author, ~7 hours earlier) had already implemented the identical fix; PR #17 had to be closed as superseded once the duplication was discovered mid-review.\n\n| # | Don't | Do |\n|---|-------|-----|\n| 1 | Jump straight into fixing a CI/config-level problem because it's clearly broken | `gh pr list --state open` first — skim titles for the same file/problem area |\n| 2 | Assume \"I'd have noticed if this were already being worked on\" | Open PRs from earlier in the same day (even your own past sessions) are easy to miss without an explicit check |\n| 3 | Only check open PRs when multiple sessions are known to be active | Run the check unconditionally before repo-wide fix work — it's a single `gh pr list` call |\n\nFile v0.11.3:_meta.json\n\n{\n  \"ownerId\": \"kn74k8yfvftx6f062qa8fzyd8h8373jd\",\n  \"slug\": \"github-flow\",\n  \"version\": \"0.11.3\",\n  \"publishedAt\": 1790524322009\n}\n\nFile v0.11.3:account-switch-merge.md\n\n# Account-Switch Merge (`account-switch-merge`)\n\nUse this topic when performing a PR merge requiring a specific merger account (e.g., `DrumRobot` bot account for CI/release isolation or protected branch policies) with automatic post-merge account restoration.\n\n## Purpose\n\nAutomates the manual 6-condition check, temporary `gh auth` user switch, squash/merge execution, and guaranteed restoration of the developer's original GitHub account state.\n\n---\n\n## 6 Pre-Merge Conditions Checklist (MANDATORY)\n\nBefore initiating an account switch or executing `gh pr merge`, ALL 6 conditions MUST be verified and pass:\n\n1. **CI Success**: `gh pr checks <N>` returned all `SUCCESS` (no pending, no failed).\n2. **AI Review Summary Posted**: `/consolidate pr <N>` has completed and the AI Review Summary comment is present (or PR is consolidate-exempt).\n3. **Test Plan Checked**: All `- [ ]` checklist items in the PR body are marked completed (`- [x]`).\n4. **Mergeable Status**: `gh pr view <N> --json mergeable` returns `\"MERGEABLE\"`.\n5. **Base Branch Alignment**: PR is up to date with the latest base branch (no merge conflicts).\n6. **Pre-Commit / Pre-Push Sanity**: Working tree is clean or changes are safely stashed.\n\n---\n\n## Automated 5-Step Account-Switch & Merge Protocol\n\n### Step 1: Pre-Merge Verification\n```bash\n# Verify 6 pre-merge conditions\ngh pr view <PR_NUMBER> --json state,mergeable,reviews,checks,body\n```\n\n### Step 2: Record Current Active User\n```bash\nORIGINAL_USER=$(gh api user --jq .login)\necho \"Current active GH user: $ORIGINAL_USER\"\n```\n\n### Step 3: Switch to Target Merger Account\nIf `$ORIGINAL_USER` is not the target merger account (e.g. `DrumRobot`), switch to it:\n```bash\nTARGET_USER=\"DrumRobot\"\nif [ \"$ORIGINAL_USER\" != \"$TARGET_USER\" ]; then\n  gh auth switch -u \"$TARGET_USER\"\nfi\n```\n\n### Step 4: Execute Squash & Merge\n```bash\ngh pr merge <PR_NUMBER> --squash --delete-branch\n```\n\n### Step 5: Guaranteed Original Account Restoration (HARD STOP)\nRegardless of merge success or failure, ALWAYS restore the original user account immediately:\n```bash\nif [ \"$ORIGINAL_USER\" != \"$TARGET_USER\" ]; then\n  gh auth switch -u \"$ORIGINAL_USER\"\nfi\n```\nVerify restored identity:\n```bash\ngh api user --jq .login\n```\n\n---\n\n## Don't / Do Table\n\n| # | Don't | Do |\n|---|-------|----|\n| 1 | Merge without checking all 6 pre-merge conditions | Verify CI, Review, Test Plan, and Mergeable status BEFORE switching account |\n| 2 | Leave active `gh auth` as `DrumRobot` after merge | ALWAYS restore `$ORIGINAL_USER` in Step 5 immediately after merge |\n| 3 | Use direct `git push origin main` bypass | Always merge via `gh pr merge <N> --squash` |\n\nFile v0.11.3:auth-scope.md\n\n# Auth Scope — gh CLI Priority + Account Mapping + Batch Scope Refresh + 404 Checklist\n\n## gh CLI Priority and Browser Agent Restriction (HARD STOP)\n\n**All GitHub operations (PR lookup, review, comment, merge, etc.) must use the `gh` CLI tool first; routing around via a browser agent is strictly forbidden.**\n\n| # | Don't | Do |\n|---|-------|----|\n| 1 | Call a browser agent to check/consolidate PR reviews | Combine `gh pr view`, `gh api`, `gh pr checks`, etc. to extract data from the CLI |\n| 2 | Skip the CLI based on the subjective judgment \"the browser is more accurate\" | The `gh` CLI maintains auth and context — it is the most reliable source. Consider the browser only when the CLI fails |\n| 3 | Wait for browser rendering for simple info lookups (e.g., comment lists) | Parse JSON with `gh api`. Much faster and uses fewer tokens |\n\nUse the browser agent **only for special situations that are genuinely impossible via the CLI** (e.g., complex GUI configuration, visual layout verification), and only with prior user approval.\n\n## Account Mapping (per organization)\n\n| Account | Purpose | git author identity |\n|---------|---------|---------------------|\n| `DrumRobot` | es6kr org repositories (es6kr/skills, claude-code-sessions, etc.) | `DrumRobot <drumrobot43@gmail.com>` |\n| `<personal-account>` | Personal org / personal repositories | `<personal-account> <personal@email.com>` |\n\n**Account switching**: `gh auth switch --user <account>`. On failure, inject `GH_TOKEN=\"$(gh auth token --user <account>)\"` as an environment variable instead (must be passed via a script file — env vars are not preserved between separate Bash calls).\n\n## commit author + PR account must map to repo owner (HARD STOP)\n\n**The gh account mapping applies not only to push/PR auth but also to commit author identity.** When committing/PRing to an es6kr org repository (including PUBLIC ones), proceeding with the `gh` active account still set to a non-primary account (a residual from other work) will permanently bake the wrong author into PUBLIC history. **Switch git author identity + gh account to match the repo owner before committing.**\n\n| # | Don't | Do |\n|---|-------|----|\n| 1 | Commit to an es6kr org repo while the active account is a non-primary account → wrong author baked in | Before committing: `git -C <repo> config user.name \"<correct-name>\" && git -C <repo> config user.email \"<correct-email>\"` |\n| 2 | Only switch the gh account for push/PR while leaving commit author as the wrong account | author + committer + push + PR must all match the repo owner's identity. Author is permanently recorded in PUBLIC history, so they must match |\n| 3 | Assume \"auth is only needed at push time\" | Commit author is baked in at commit time. An already-committed author can only be changed via amend/rebase |\n| 4 | Commit without checking the repo owner, relying on the current git config | Right before committing, run `git remote get-url origin` to confirm the owner → apply identity per the mapping table |\n\n**Self-check (every time before committing — based on repo owner)**:\n1. `git -C <repo> remote get-url origin` → confirm owner (es6kr / `<your-org>` / `<personal-account>`)\n2. es6kr org → apply the es6kr git author identity + at push/PR time: `gh auth switch --user <es6kr-account>` or `GH_TOKEN=\"$(gh auth token --user <es6kr-account>)\"`\n3. Other org/personal repos → apply the corresponding git author identity per your mapping table\n4. If current `git config user.email` does not match the mapping, correct it before committing. If already committed incorrectly and **unpushed**, use `git commit --amend --reset-author` (no force push needed)\n5. PR creation also uses the same mapped account (`gh pr create` uses the active account → `gh auth switch` or `GH_TOKEN` injection beforehand)\n\n## Required gh CLI Scopes (by operation)\n\n**On a 404 or when a scope top-up is instructed, batch-refresh all permissions listed below in one go so the user is not asked to authenticate in the browser multiple times (HARD STOP).**\n\n| Operation | Required scope | Notes |\n|-----------|---------------|-------|\n| Public repository read | `repo` (or `public_repo`) | |\n| Private repository (org) | `repo`, `read:org` | Required for org repositories (e.g., private GitHub orgs) |\n| Create / update / merge PR | `repo` | |\n| Create / update / comment on issue | `repo` | |\n| Query / trigger GitHub Actions workflows | `repo`, `workflow` | For `gh run`, `gh workflow` commands |\n| Create / upload release | `repo` | |\n| Discussions | `repo`, `read:discussion` | |\n| Codespaces | `codespace` | |\n| Copilot settings | `copilot` | e.g., registering Copilot as a reviewer |\n| Query user email | `user:email` | |\n| Create / update Gist | `gist` | |\n| Pages management | `repo`, `pages` | |\n\n**Recommended minimum / default scope combination (batch-apply target)**: `repo,read:org,workflow,copilot`\n\n## gh auth Permission Refresh and Top-up Rules (HARD STOP)\n\n| # | Don't | Do |\n|---|-------|----|\n| 1 | On a scope top-up, only refresh `repo,read:org` and then add `copilot` separately later, forcing multiple browser authentications | As soon as a scope top-up is instructed or a missing scope is detected, batch-refresh the full set `repo,read:org,workflow,copilot` with the `-s` option in one go |\n| 2 | When topping up permissions for multiple accounts sequentially, cut between accounts and repeat `switch` inefficiently | Minimize the number of `gh auth switch` invocations and browser authentication prompts — keep the design simple enough that a single-pass batch apply is possible |\n\n```bash\n# Batch-refresh all scopes including copilot\nenv -u GITHUB_TOKEN gh auth refresh --user <account> --scopes \"repo,read:org,workflow,copilot\"\n```\n\n## Org Repository 404 Checklist\n\nAttempt the following steps in order before asking the user:\n\n1. **Check account**: `gh auth status` → confirm the active account has permissions for the target org\n2. **Check scopes**: inspect \"Token scopes\" in `gh auth status` output — do all required scopes from the table above appear? If not, run `gh auth refresh --user <account> --scopes \"...\"`\n3. **GH_TOKEN env var injection workaround (most common fix)**: even after switching via `auth switch`, a known gh CLI bug prevents some commands from using the active account. Work around it with the following pattern:\n   ```bash\n   GH_TOKEN=\"$(gh auth token --user <account>)\" gh repo view <org>/<repo>\n   ```\n   If this succeeds, scope/membership is fine — the issue is in the gh CLI itself, no user action needed\n4. **Check org membership**: if all three steps above still produce 404, ask the user whether they are a member of the org\n\n**Script-file variant (reusing the token across many `gh` calls, e.g. a batch loop over PR/issue numbers)**: don't capture the token into a variable named with `TOKEN`/`SECRET`/`AUTH`/etc. and then use that same variable inside a script that also contains any output-producing command (`echo`/`printf`/`tee`/...) — even when the output has nothing to do with the token itself. A PreToolUse:Bash secret-echo guard (`block-secret-echo.sh` in the `ask-user` plugin) matches on that combination existing *anywhere* in the command text, not on whether the token variable is actually the thing being printed, so a plain `printf '%s\\n' \"$result\"` elsewhere in the same script file trips it. Name the variable something outside that keyword set (e.g. `DJ_CRED`) and only ever pass it inline as `GH_TOKEN=\"$DJ_CRED\" gh ...` (assignment, never `$GH_TOKEN`/`${GH_TOKEN}` interpolation) — write the whole thing to a script file and run that file via Bash, per the \"must be passed via a script file\" note above.\n\n## Multi-Account + SSH Remote Publish Gotcha (HARD STOP)\n\nWhen managing multiple GitHub accounts, switching accounts via `gh auth switch --user <account>` ONLY updates the gh CLI token and the Git credential helper for HTTPS remotes. If the target repository remote is configured with an **SSH URL (`git@github.com:...`)**, Git routes operations through the ambient SSH agent/key (often tied to a personal default key) instead of the switched gh CLI account. This triggers silent authentication mismatch or push failures such as `ERROR: Permission to <org>/<repo>.git denied to <wrong-user>`.\n\n| # | Don't | Do |\n|---|-------|----|\n| 1 | Rely on `gh auth switch` alone while git remote URL is an SSH endpoint (`git@github.com:...`) | Inspect remote URL (`git remote get-url origin`). If SSH, convert to HTTPS or configure account-specific SSH Host aliases |\n| 2 | Try pushing via SSH with the wrong key repeatedly, triggering permission-denied errors | Switch remote to HTTPS: `git remote set-url origin https://github.com/<org>/<repo>.git` and run `gh auth setup-git` to let `gh` authenticate git push seamlessly |\n| 3 | Hardcode personal SSH key as global default without checking repository organization owner | For SSH-only requirements, configure Host aliases in `~/.ssh/config` (`Host github-es6kr`, `IdentityFile ...`) and set remote to `git@github-es6kr:...` |\n\n### Recommended Remediation Procedure (HTTPS Switch)\n\n```bash\n# 1. Switch active gh account to target account\ngh auth switch --user DrumRobot\n\n# 2. Configure git credential helper for gh\ngh auth setup-git\n\n# 3. Convert git remote from SSH to HTTPS\ngit remote set-url origin https://github.com/es6kr/skills.git\n\n# 4. Verify push authentication\ngit push origin <branch>\n```\n\nFile v0.11.3:CHANGELOG.md\n\n# Changelog\n\n## [0.11.3](https://github.com/es6kr/skills/compare/github-flow-v0.11.2...github-flow-v0.11.3) (2026-09-27)\n\n\n### Bug Fixes\n\n* **github-flow:** add optional graph-render dispatch for large epic-bundle bundles ([#549](https://github.com/es6kr/skills/issues/549)) ([45e3629](https://github.com/es6kr/skills/commit/45e362987eb52cf35272b484918a22c0fdd8bafc))\n* **github-flow:** add PR-blocking-vehicle check before delivery-vehicle ask ([#550](https://github.com/es6kr/skills/issues/550)) ([89d9812](https://github.com/es6kr/skills/commit/89d98129de5530c7e13f827d5e3f7751b55bab97))\n* **github-flow:** document IDE-subshell token override, merge-permission gap, and worktree sweep ([#546](https://github.com/es6kr/skills/issues/546)) ([ebb366a](https://github.com/es6kr/skills/commit/ebb366a06fde5d1f28b42cbc8d483fc335d3d9d3))\n* **github-flow:** restore pre-merge state recheck in merge.md ([74ae392](https://github.com/es6kr/skills/commit/74ae39229444d0b039bb25bcb34cacea50ac1874))\n\n## [0.11.2](https://github.com/es6kr/skills/compare/github-flow-v0.11.1...github-flow-v0.11.2) (2026-09-24)\n\n\n### Bug Fixes\n\n* **git-repo:** add prune_merged_worktrees.py + 7 accumulated fixes ([3d2ee94](https://github.com/es6kr/skills/commit/3d2ee9425285347d8f7e7698049d6e5769f73f92))\n* **github-flow:** document multi-account and ssh remote publish gotchas ([4a772a8](https://github.com/es6kr/skills/commit/4a772a89adc8302f65da48c85e36588d2792f576))\n\n## [0.11.1](https://github.com/es6kr/skills/compare/github-flow-v0.11.0...github-flow-v0.11.1) (2026-09-20)\n\n\n### Bug Fixes\n\n* **github-flow:** document the batch-script secret-echo gotcha for token injection ([91e3205](https://github.com/es6kr/skills/commit/91e320570dca3acfa9925f3a4afcb532e786d423))\n\n## [0.11.0](https://github.com/es6kr/skills/compare/github-flow-v0.10.2...github-flow-v0.11.0) (2026-09-18)\n\n\n### Features\n\n* **task-plan,github-flow:** adopt artifact sibling guard in task-plan and prohibit multi-commit squash ([9938985](https://github.com/es6kr/skills/commit/9938985161fe1e0ddae934980b3c9307e7dfd5f4))\n\n\n### Bug Fixes\n\n* **cleanup:** make the session-end report table self-sufficient ([#487](https://github.com/es6kr/skills/issues/487)) ([c4a0255](https://github.com/es6kr/skills/commit/c4a02557fb8de3b32cf337c549f62535dabf824b))\n* **github-flow:** prohibit squash merge on multi-commit PRs in skills and plugins repos ([8db57f8](https://github.com/es6kr/skills/commit/8db57f8fe76357bda3f3d26fed7e4c253bfffbb3))\n\n## [0.10.2](https://github.com/es6kr/skills/compare/github-flow-v0.10.1...github-flow-v0.10.2) (2026-09-08)\n\n\n### Bug Fixes\n\n* **github-flow:** document merge-commit policy, promotion PR discipline, and develop routing ([ace6bd4](https://github.com/es6kr/skills/commit/ace6bd4d445a2f805a8183946f70bdf34d48289f))\n\n## [0.10.1](https://github.com/es6kr/skills/compare/github-flow-v0.10.0...github-flow-v0.10.1) (2026-09-01)\n\n\n### Bug Fixes\n\n* **githooks:** fix set -e crash in BASE-7 guard + weigh review-cost in pr.md Step -1 ([#405](https://github.com/es6kr/skills/issues/405)) ([e651cc4](https://github.com/es6kr/skills/commit/e651cc49fa7051cdea819562b161964588979699))\n* staging branch next-fix sync into main ([bbbd460](https://github.com/es6kr/skills/commit/bbbd460bf3b6b1cba4c6d07b3641afa734c89860))\n\n## [0.10.0](https://github.com/es6kr/skills/compare/github-flow-v0.9.1...github-flow-v0.10.0) (2026-08-29)\n\n\n### Features\n\n* **works-config:** implement v0.2.0 role-based resolution & neutral SSOT guards config ([e22e117](https://github.com/es6kr/skills/commit/e22e117371370c59b18b77c72bdb926dcb1897cb))\n\n\n### Bug Fixes\n\n* address CodeRabbit and Copilot review feedback on PR [#389](https://github.com/es6kr/skills/issues/389) ([db4dfff](https://github.com/es6kr/skills/commit/db4dfff2829632bf263d93e0bbfdd1244772a5b2))\n* **github-flow:** require a fresh PR-state recheck immediately before gh pr merge ([#381](https://github.com/es6kr/skills/issues/381)) ([b0ba553](https://github.com/es6kr/skills/commit/b0ba553db9fc9139d44e64dcd37e2d563c1fe622))\n* **github-flow:** sync block-pr-url-gate.sh from the diverged downstream copy ([5cc5e14](https://github.com/es6kr/skills/commit/5cc5e140271a98adb2af53dbe5d58c38007b0c43))\n* **hook-kit:** document --json mode and scope WSCFG_* to hook scripts ([373634c](https://github.com/es6kr/skills/commit/373634c022b0e2b114a3bbb799bb9a8934c9fbb2))\n* **hook-kit:** scope PR-URL bare-ref check to per-number match, allow force-push in worktrees ([dd50dce](https://github.com/es6kr/skills/commit/dd50dced989eed4847daaf9a0cd4be12a04426e1))\n* promote next-fix batch (task plugin split, claudify matcher, pr recheck, omz chezmoi fix) ([3e90fd5](https://github.com/es6kr/skills/commit/3e90fd56ade0522d6773eb03f38760a317dd5180))\n* **review:** apply copilot review feedback on hooks and test suites ([cba86f4](https://github.com/es6kr/skills/commit/cba86f4ebbf274a0c979ab21aeea6d483f8cb8f3))\n\n\n### Refactor\n\n* **hooks:** sync hook registry, enhance bash-guard, and retire obsolete guards ([15d4a58](https://github.com/es6kr/skills/commit/15d4a58752d0d458f88c86cb41c537f90e3ca4dd))\n\n## [0.9.1](https://github.com/es6kr/skills/compare/github-flow-v0.9.0...github-flow-v0.9.1) (2026-08-26)\n\n\n### Bug Fixes\n\n* accumulate 16 patch-level bug fixes and guard enhancements across skills ([d214e5d](https://github.com/es6kr/skills/commit/d214e5dcc7fac1bc07baf3b6cec62999aea732f0))\n* **core:** align workflow steps, next suggestion patterns, and browser topics ([c68d489](https://github.com/es6kr/skills/commit/c68d489d01a79862b8933b4a0542168cf676cd3a))\n* **github-flow:** stop claiming the PR-URL gate is registered and enforcing ([cbb433a](https://github.com/es6kr/skills/commit/cbb433a9e59bc1bd79bf292736aaacb069d791f1))\n* promote accumulated skill fixes from the working checkout ([770bed2](https://github.com/es6kr/skills/commit/770bed2386266fc13f7d605505c2996037d4c371))\n* promote next-fix batch (consolidate fabrication guard, session rewind, config-driven PR base) ([7ca0ccb](https://github.com/es6kr/skills/commit/7ca0ccbf13cefafedc33a16a7361756c95f8b8f6))\n\n## [0.9.0](https://github.com/es6kr/skills/compare/github-flow-v0.8.3...github-flow-v0.9.0) (2026-08-20)\n\n\n### Features\n\n* promote next-feat staging (lifecycle guards, triage automation, and workflow safety procedures) ([77d58ac](https://github.com/es6kr/skills/commit/77d58ac3a771a4897043c9eea8b149ea1e8ba2ff))\n\n## [0.8.3](https://github.com/es6kr/skills/compare/github-flow-v0.8.2...github-flow-v0.8.3) (2026-08-17)\n\n\n### Bug Fixes\n\n* **github-flow:** CI-gate-only base check before ready-transition claims ([435d43c](https://github.com/es6kr/skills/commit/435d43cd023e91688da8e5ffcd5c3c655605abbb))\n* **github-flow:** CI-gate-only base means skip ready transition, not just no review cost ([9418c40](https://github.com/es6kr/skills/commit/9418c408a4503402167bbd17706656f62789a287))\n* **github-flow:** forbid raw draft paths in plan-to-issue --body-file ([d0911f0](https://github.com/es6kr/skills/commit/d0911f0f0e742dd7cdf239ce880d4dfce3e0ab9e))\n* **github-flow:** require CI-gate-only base check before ready-transition claims ([6a94549](https://github.com/es6kr/skills/commit/6a9454941f40e26a9e7ef544db915c63f3b007cf))\n* **github-flow:** require open-PR check before repo-wide fix work ([#329](https://github.com/es6kr/skills/issues/329)) ([5da8855](https://github.com/es6kr/skills/commit/5da88554a3e425738ef5003e20ff32b96d96b4a5))\n* **github-flow:** verify PR creation via authoritative commit fields, not diff listing ([568ec87](https://github.com/es6kr/skills/commit/568ec874e2ad18f88b1c45bcc15e809786f5822d))\n* plan-to-issue frontmatter guard, cleanup gap-baseline sync, pre-commit placeholder exemption ([20e1698](https://github.com/es6kr/skills/commit/20e1698b3b3ee435b8c2705dfe32124567eedd29))\n* promote next-fix staging (30 fixes across 14 skills) ([ee467c0](https://github.com/es6kr/skills/commit/ee467c045d779d7b80d30f160763ec3534a9742b))\n* **wip:** cross-ref PR-URL and TaskCreate subject repo-qualifier rules ([#186](https://github.com/es6kr/skills/issues/186)) ([4982364](https://github.com/es6kr/skills/commit/49823641a7b08123ebd0325273892bee41bc3280))\n\n## [0.8.2](https://github.com/es6kr/skills/compare/github-flow-v0.8.1...github-flow-v0.8.2) (2026-08-09)\n\n\n### Bug Fixes\n\n* **consolidate:** address CodeRabbit/Copilot review findings on PR [#270](https://github.com/es6kr/skills/issues/270) ([3b11a73](https://github.com/es6kr/skills/commit/3b11a730b5ad68803d35a8264eda540e48265d75))\n* declare undeclared skill-to-skill dependencies (7 skills) ([#271](https://github.com/es6kr/skills/issues/271)) ([36a9f9d](https://github.com/es6kr/skills/commit/36a9f9d7c1fac9bb1c4c96b325a067ab92ad0da7))\n* **github-flow:** add merged-PR/stale-tracker branch to review-apply.md ([#237](https://github.com/es6kr/skills/issues/237)) ([5a880fb](https://github.com/es6kr/skills/commit/5a880fb936cc474ea791f2fa2e24edc2fd018142))\n* **github-flow:** align merge.md evidence format with fix-plan/format.md schema ([#244](https://github.com/es6kr/skills/issues/244)) ([ea609cf](https://github.com/es6kr/skills/commit/ea609cf3a1725298383d96a297252f19596d0e10))\n* **github-flow:** always disclose commit list in merge asks, not just 3+-commit ones ([#248](https://github.com/es6kr/skills/issues/248)) ([8c19508](https://github.com/es6kr/skills/commit/8c19508d6b3967af783fb372d452fecceec6953c))\n* **github-flow:** document rebase-conflict cost of squashing distinct-concern PRs ([#245](https://github.com/es6kr/skills/issues/245)) ([dc6cb34](https://github.com/es6kr/skills/commit/dc6cb3417ae945c8e9393d18d700aa6eccb0dfd5))\n* **github-flow:** gate squash-merge recommendation on commit count/distinctness ([45176ab](https://github.com/es6kr/skills/commit/45176ab8ee4d7a9e80c58f4062035e64143bc1bf))\n* promote accumulated next-fix fixes to main ([95656e9](https://github.com/es6kr/skills/commit/95656e9b551ee0bb77904a0a571d49c53bc01cc9))\n\n## [0.8.1](https://github.com/es6kr/skills/compare/github-flow-v0.8.0...github-flow-v0.8.1) (2026-08-05)\n\n\n### Bug Fixes\n\n* **github-flow:** correct stale five/four-condition wording after 6th gate added ([738e92e](https://github.com/es6kr/skills/commit/738e92ed078e6c5f81cdc2325f7b85e91d830d14))\n* promote next-fix staging (38 fixes across 16 skills) ([94f8c33](https://github.com/es6kr/skills/commit/94f8c33800ce411ae63e22c5259cdae8435508a4))\n\n## [0.8.0](https://github.com/es6kr/skills/compare/github-flow-v0.7.0...github-flow-v0.8.0) (2026-08-03)\n\n\n### Features\n\n* **github-flow:** add publish topic ([#206](https://github.com/es6kr/skills/issues/206)) ([4aba1b6](https://github.com/es6kr/skills/commit/4aba1b63fdf7357b636118a30d674a0f7db71706))\n* promote next-feat to main ([4fbe313](https://github.com/es6kr/skills/commit/4fbe31332c58bf24327d819cc9204ebda2d4afa8))\n\n## [0.7.0](https://github.com/es6kr/skills/compare/github-flow-v0.6.1...github-flow-v0.7.0) (2026-07-23)\n\n\n### Features\n\n* **hook-kit:** add pre-tool AskUserQuestion context gate ([#123](https://github.com/es6kr/skills/issues/123)) ([271b5b3](https://github.com/es6kr/skills/commit/271b5b37df5e64cf3185b2c81c3d97b66789e9ab))\n\n\n### Bug Fixes\n\n* **next-fix:** accumulate bug fixes for docxport, wip, fix-plan, and hook-kit ([6eec083](https://github.com/es6kr/skills/commit/6eec083b7fbc429bdabcfcc89d7778b185dd7497))\n* skills body bundle — consolidate/fix/hook-kit refinements + English-clean guard hooks (Ralph-loop bypass) ([2e26f41](https://github.com/es6kr/skills/commit/2e26f412a5b963984898e13caaca186c3617ca08))\n\n## [0.6.1](https://github.com/es6kr/skills/compare/github-flow-v0.6.0...github-flow-v0.6.1) (2026-07-19)\n\n\n### Bug Fixes\n\n* externalize internal-host detection tokens (edit-guard + sanitize doc) ([0bb7f83](https://github.com/es6kr/skills/commit/0bb7f831c752ecc5272611da752325f44e3c32a6))\n\n## [0.6.0](https://github.com/es6kr/skills/compare/github-flow-v0.5.0...github-flow-v0.6.0) (2026-07-17)\n\n\n### Features\n\n* **github-flow:** add auth-scope, commit-message-discipline topics + review-as.sh script ([907d730](https://github.com/es6kr/skills/commit/907d7307de59725bd15af0a6a64ca4906406242e))\n* **github-flow:** add gh-as.sh wrapper for command-scoped gh account switching ([#97](https://github.com/es6kr/skills/issues/97)) ([cd043ed](https://github.com/es6kr/skills/commit/cd043ed54ed5aaa351e65dbe804fededc1842556))\n* promote next-feat to main (hook-kit, github-flow, claude-session, todowrite, claudify, cleanup) ([7c598eb](https://github.com/es6kr/skills/commit/7c598ebdbfdb21cf421e8f814ea1a2513ad27a58))\n\n\n### Bug Fixes\n\n* **github-flow:** genericize private-org name in sanitize.md example ([0acc74a](https://github.com/es6kr/skills/commit/0acc74abc3aeee4de086e4a099b458759b74dda0))\n* **github-flow:** harden identity-auth/merge/plan-to-issue/pr/register/sanitize topics ([3458595](https://github.com/es6kr/skills/commit/3458595fbacf8bf21eb474c60f721c5111753291))\n* **github-flow:** per-ref evidence gate for mixed-result push output ([ed2d643](https://github.com/es6kr/skills/commit/ed2d6438f64d1a3bc4ce0166717b72b164cdf309))\n\n## [0.5.0](https://github.com/es6kr/skills/compare/github-flow-v0.4.3...github-flow-v0.5.0) (2026-07-07)\n\n\n### Features\n\n* **docxport:** promote initial registration to main ([8265ba3](https://github.com/es6kr/skills/commit/8265ba33b13ab6054c3595943d068f5c1c13625a))\n* **github-flow,next:** draft-PR default + sync remaining pr-review→pr topic refs ([ca64425](https://github.com/es6kr/skills/commit/ca644253c8b84b41f8a90d7869ac16fa8c7c7124))\n* **github-flow:** add epic-bundle topic row + [e2e]/[deploy] test plan prefixes + branch verification ([31d629f](https://github.com/es6kr/skills/commit/31d629fa405639995a53ec8296ff95f33672b435))\n* **skills:** drift sync bundle — cc-plugin/github-flow/wip/next/check-hangul ([ac5d15d](https://github.com/es6kr/skills/commit/ac5d15d7231e67b3b53cae3861bb6132a2f3beff))\n\n## [0.4.3](https://github.com/es6kr/skills/compare/github-flow-v0.4.2...github-flow-v0.4.3) (2026-07-03)\n\n\n### Bug Fixes\n\n* **github-flow:** update stale pr-review topic refs to pr after archive ([1e6c0ad](https://github.com/es6kr/skills/commit/1e6c0ad27fa75be13690343b32b3d05e9f4869a4))\n* **skills:** patch bundle — consolidate/next/fix/skill-kit/github-flow ([3cb90cb](https://github.com/es6kr/skills/commit/3cb90cb7601f619b63518860bebfb693d58a7633))\n\n## [0.4.2](https://github.com/es6kr/skills/compare/github-flow-v0.4.1...github-flow-v0.4.2) (2026-06-25)\n\n\n### Bug Fixes\n\n* apply PR [#62](https://github.com/es6kr/skills/issues/62) AI review findings (14) ([8132a2b](https://github.com/es6kr/skills/commit/8132a2b001fbd10e3db618decf989f8cf84b1b6b))\n* **fix:** split Step 2 medium by content type — case history to failed-attempts.md ([#62](https://github.com/es6kr/skills/issues/62)) ([747b3f9](https://github.com/es6kr/skills/commit/747b3f957ca0fefdbc5044eb08f66b8aafc1e26a))\n* **github-flow:** split [e2e] into PR-CI required vs [deploy] deploy-gated ([f7cdada](https://github.com/es6kr/skills/commit/f7cdada2c06ea0608f1d73aaa8c53fa2d48a5143))\n* **github-flow:** translate Artifacts references to English ([1bc17a4](https://github.com/es6kr/skills/commit/1bc17a4e30ddb81f110c4f2cc2d5f232affade4e))\n\n## [0.4.1](https://github.com/es6kr/skills/compare/github-flow-v0.4.0...github-flow-v0.4.1) (2026-06-19)\n\n\n### Bug Fixes\n\n* bundle skill patches across github-flow, skill-kit, fix ([0ef74c1](https://github.com/es6kr/skills/commit/0ef74c14aabfbdc2f802c34b3a1b431217e95208))\n* **github-flow:** abstract ralph references and priority-compatible BLOCKED grep ([b735f41](https://github.com/es6kr/skills/commit/b735f41ccd4b6fedd980895a07b59f7ba3068864))\n* **github-flow:** add PR lifecycle guards across identity, workflow YAML, merge, and push ([5c5bc86](https://github.com/es6kr/skills/commit/5c5bc86a1ee1b6fe1bbae8e416afe5b31b790829))\n* **skill-kit,github-flow:** address CodeRabbit + Internal Review feedback on PR [#54](https://github.com/es6kr/skills/issues/54) ([c5c741d](https://github.com/es6kr/skills/commit/c5c741da5631a042860e684580d1c92687b59eec))\n\n## [0.4.0](https://github.com/es6kr/skills/compare/github-flow-v0.3.0...github-flow-v0.4.0) (2026-06-12)\n\n\n### Features\n\n* decompose workflow/git rules + rename web-ui-test→web-browser ([#50](https://github.com/es6kr/skills/issues/50)) ([e10d48f](https://github.com/es6kr/skills/commit/e10d48fea4e507b95888de44812b53484d32128d))\n\n## [0.3.0](https://github.com/es6kr/skills/compare/github-flow-v0.2.0...github-flow-v0.3.0) (2026-06-01)\n\n\n### Features\n\n* **github-flow:** multi-topic structure + English body + internal-id sanitization ([#39](https://github.com/es6kr/skills/issues/39)) ([881aaf3](https://github.com/es6kr/skills/commit/881aaf3be5cd57edf3173e88f40273ccd3640330))\n\n## [0.2.0](https://github.com/es6kr/skills/compare/github-flow-v0.1.0...github-flow-v0.2.0) (2026-05-24)\n\n\n### Features\n\n* **ci:** add lint jobs and untrack LICENSE ([#7](https://github.com/es6kr/skills/issues/7) Phase 1) ([03a8587](https://github.com/es6kr/skills/commit/03a85872c575c6ffdf72f5ca2bdb353fdc947a73))\n* publish 7 new skills, update 4 existing skills ([dce016d](https://github.com/es6kr/skills/commit/dce016da291f4c9da03746f8be668fa5db04e578))\n\n\n### Bug Fixes\n\n* address CodeRabbit review findings on PR [#4](https://github.com/es6kr/skills/issues/4) ([bbaefdc](https://github.com/es6kr/skills/commit/bbaefdc8a88f26b0b072e115d0696e732ac52e0c))\n\nFile v0.11.3:commit-message-discipline.md\n\n# Commit Message Discipline — commit message authoring + message update on amend + PUBLIC repo English enforcement + git operation type continuity + verb selection (`.md` as source code)\n\n## Conventional Commit Format\n\n- Use Conventional Commit format: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`, `ci`, `perf`\n- **No tags outside the list above** (`infra:`, `build:`, `wip:`, and all other ad-hoc tags are forbidden)\n- Choose language based on repository visibility: **PUBLIC = English mandatory, PRIVATE = Korean default** — the same visibility rule applies uniformly to commits, PRs, issues, and comments\n\n## PUBLIC Repo Commit Message English Enforcement — Self-check (HARD STOP)\n\n**Before every commit, confirm repository visibility + language via a first-hand source. English is mandatory for PUBLIC repos.** Blocks the pattern of dumping non-English thoughts directly into commit messages.\n\n**Why**:\n- PUBLIC repo commit history is permanent (even force-push amends remain in forks/clones)\n- The mixed pattern of \"Conventional Commit tags (`ci:`/`feat:`) in English but body parenthetical annotations in another language\" is common\n- Non-English thinking leaking directly into commit bodies occurs more often at the commit-message authoring stage than in code itself\n\n| # | Don't | Do |\n|---|-------|----|\n| 1 | Commit message containing non-English words/sentences in a PUBLIC repo | Write the subject, body, and all parenthetical annotations in English |\n| 2 | Mixed pattern: \"Conventional Commit tags in English, body in another language\" | All of tag + subject + body in English. Notes after hyphens must also be English |\n| 3 | \"The user decided/instructed in Korean, so use Korean in the commit message too\" | User decision language does not equal commit message language. The commit medium always defers to the visibility rule |\n| 4 | Skipping visibility confirmation before committing (\"I already know it's a PUBLIC repo\") | Confirm visibility from a first-hand source before every commit: `gh repo view <repo> --json isPrivate -q '.isPrivate'` |\n| 5 | Assuming English enforcement is waived for PoC / draft / temporary commits | English is mandatory even for PoC commits in a PUBLIC repo. Even after a branch is deleted, git history persists in forks/clones |\n\n**Self-check (before every commit message)**:\n\n1. Is the target repo PUBLIC? — Latest visibility check result + `isPrivate=false`. If PRIVATE, this rule does not apply.\n2. Does the written commit message subject + body contain non-ASCII characters in the Hangul syllable block (U+AC00 through U+D7A3)?\n3. 1+ match — translate to English immediately\n4. Visually scan the full message immediately before running `git commit -m`/`-F` or heredoc input\n5. For cases corrected via amend + force push, verify post-hoc: `git log -1 --format=%B | grep -P '[\\x{AC00}-\\x{D7A3}]'` must return 0 matches\n\n## Preserving Git Operation Type Continuity (HARD STOP)\n\n**If the user specified a git operation type (amend / new commit / cherry-pick / rebase / squash / force push) in a prior ask/turn, maintaining the same type is the default for all subsequent related decisions.** Switching to a different operation type requires an explicit confirmation ask to the user.\n\n### Don't / Do\n\n| # | Don't | Do |\n|---|-------|----|\n| 1 | Processing a follow-up decision as a separate commit right after the user specified amend | Maintain the same amend type. If switching to a different type, ask the user explicitly |\n| 2 | Defaulting to \"a separate commit is safer (avoids force push)\" | If the user specified amend, amend is the default. Proceed safely using `--force-with-lease` |\n| 3 | Correcting a wrong commit made by an automation tool (e.g., a release-please 0.5.0 bump) with a separate downgrade commit | Directly amend the automation tool's commit. Maintain a single clean commit at the PR head |\n| 4 | Interpreting the user-specified operation as \"one-time only for the last turn\" | User specifying a type means it applies for the entire current work flow. Automatically maintain the same type for subsequent decisions |\n| 5 | Avoiding force push after amend under the premise \"force push is risky\" and adding a separate commit instead | If the user specified amend + force push, `--force-with-lease` is the correct approach |\n\n### Self-check (before every commit)\n\n1. Did the user specify a git operation type in a prior ask/turn? (amend, new commit, rebase, cherry-pick, squash, force push, etc.)\n2. If so, is the current decision also the same type?\n3. Considering a different type? — Stop immediately and ask the user for explicit confirmation\n4. Is this a situation where a wrong commit made by an automation tool needs to be corrected? — Prioritize history cleanliness and choose amend\n\n### Exceptions\n\n- User did not specify a type → default = new commit (safe)\n- The amend target is another person's published commit or a protected branch like main/master → force push itself is forbidden\n\n## Mandatory Message Update on --amend\n\n**When adding/changing files via `git commit --amend`, the commit message must also be updated.**\n\n- Do not use `--no-edit` (it leaves the message out of sync with the actual changes)\n- **Exception**: minor changes such as typo fixes or formatting where a message update is unnecessary\n\n## Commit Tag Selection Criteria\n\n- `feat`: new functionality end users interact with directly (UI, API endpoints, CLI commands, etc.)\n- `test`: adding or modifying test code (test files, fixture data, test configuration)\n- `ci`: CI/CD workflows, test infrastructure configuration (GitHub Actions, Playwright setup, CI configuration)\n- **When test infrastructure and test code are mixed**: use `ci`\n- `feat` must not be used for: adding e2e tests, adding test fixtures, adding CI pipelines\n\n## Verb Selection — skill/rule `.md` files are source code (HARD STOP)\n\n**Commit message verbs for changes to `skills/**/*.md`, `rules/**/*.md`, and `.claude/rules/**/*.md` files must describe a behavior change. Documentation verbs (`document`, `describe`, `note`) are forbidden.**\n\nRationale: These files are **directives** consumed by the AI agent at runtime. Adding or editing Markdown text means adding or modifying agent behavior — not documenting pre-existing behavior.\n\n### Allowed vs Forbidden Verbs\n\n| Type | Verbs |\n|------|-------|\n| **Behavior-change verbs** (use for skill/rule `.md`) | `add`, `introduce`, `require`, `mandate`, `enforce`, `prohibit`, `forbid`, `allow`, `replace`, `restructure`, `remove`, `tighten`, `relax`, `extend` |\n| **Documentation verbs** (forbidden for skill/rule `.md`) | `document`, `describe`, `note`, `clarify wording`, `fix typo` (limited to behavior-neutral changes such as typo fixes and copy cleanup) |\n\n### Don't / Do\n\n| # | Don't | Do |\n|---|-------|----|\n| 1 | `feat(wip): document Copilot rate-limit cache write` | `feat(wip): require Copilot rate-limit reset timestamp shared-cache write` |\n| 2 | `docs(skill-X): describe new behavior` (when in fact new behavior is being added) | `feat(skill-X): add/introduce/enforce <new behavior>` — the `docs:` prefix is reserved for behavior-neutral changes such as typo fixes, formatting, and link updates |\n| 3 | Defaulting to \"`docs:` for any `.md` text addition\" | skill/rule `.md` files are AI source. Adding a new rule/HARD STOP/Don't-Do row = `feat:`. Removing a rule = `feat:` (behavior change). Meaning-identical refactoring = `refactor:` |\n| 4 | Using a behavior verb in the subject but framing the body as \"documents that X must Y\" | Frame the body as \"this commit changes how the agent behaves: X must now Y\" — explicitly describe the behavior change |\n\n### Self-check (before drafting every commit message)\n\n1. Is at least one changed file a `skills/**/*.md`, `rules/**/*.md`, or `.claude/rules/**/*.md`?\n2. If yes, does the commit message verb match an entry in the \"Forbidden verbs\" table?\n3. If it matches — re-check whether the diff actually adds new behavior / HARD STOP / Don't-Do rows / self-check steps\n4. If it is a behavior change — select a verb from the \"Allowed verbs\" table. If the type prefix was `docs:`, replace it with `feat:`\n\n### Exceptions\n\n- The file is a skill/rule `.md` but the change is purely a typo fix, formatting, or link correction with no behavior change → `docs:` + documentation verb is acceptable\n- Only external references or example text in a skill/rule `.md` are updated (rules/procedures unchanged) → `docs:` is acceptable\n\nFile v0.11.3:dependencies.md\n\n# Issue Dependencies & Sub-issues\n\nManage GitHub native **Issue Relationships**: blocked-by / blocking dependencies AND parent-child (sub-issue) hierarchies. Uses `addBlockedBy` / `removeBlockedBy` for sequential dependencies and `addSubIssue` / `removeSubIssue` for hierarchical breakdown.\n\n## When to Use\n\n- After creating issues in a multi-issue feature chain that has a clear sequential order\n- After confirming a plan (e.g., `code-workflow` step 2) where downstream issues exist\n- Before starting work on an issue — verify all blocked-by predecessors are resolved\n- Before merging a PR — verify the issue's blockedBy is empty (or all resolved)\n- **After concluding a PR/issue priority order in chat** — when analysis lands on \"X must merge before Y\" (file overlap, base-branch typecheck regression, base dependency, etc.), immediately apply `addBlockedBy(issueId=Y, blockingIssueId=X)`. The chat conclusion is itself the explicit trigger — do not wait for the user to say \"please apply the block now\"\n\n### PR-PR Dependencies (HARD STOP — native unsupported, must use a workaround)\n\n**GitHub Issue Dependencies is Issue-only.** The `PullRequest` type has no `blockedBy` / `blocking` fields, and the `addBlockedBy` mutation returns `Field 'blockedBy' doesn't exist on type 'PullRequest'` against PR node IDs. Verification:\n\n```bash\ngh api graphql -f query='query { repository(owner:\"<o>\", name:\"<r>\") {\n  issueOrPullRequest(number:<PR#>) { __typename ... on PullRequest { blockedBy(first:1) { nodes { number } } } }\n} }'\n# → undefinedField error\n```\n\nTherefore, PR-to-PR dependencies are expressed via:\n\n| Method | When to apply | Effect |\n|--------|---------------|--------|\n| (A) Add a `## Depends on\\n- #<upstream>` section in the downstream PR body + a \"rebase after #N merge\" note in the Test Plan | Merge-order dependency between PRs that share the same base (both target main) | GitHub UI shows cross-links automatically + reviewer sees the order |\n| (B) Set the downstream PR's base to the upstream PR's head (Stacked PRs) | When the dependent code itself is required (working on top of upstream changes) | GitHub auto-rebases when the base merges |\n| (C) Set `addBlockedBy` on a shared tracking issue (each PR closes that issue) | Multiple PRs implementing one issue in parts | Uses the issue's Relationships panel |\n\n**For this trigger case (priority conclusion), choosing the medium requires AskUserQuestion** — let the user choose between \"(A) body cross-link only is enough\" and \"(C) create a new tracking issue then register native blocked-by\". (B) applies only when there is a code dependency.\n\n| Option | Effect | Cost |\n|--------|--------|------|\n| (A) `## Depends on` in the downstream PR body | Reviewer sees it in the body + GitHub timeline cross-link | 0 (text only). Not searchable / filterable |\n| (C) Shared tracking issue (may be newly created) — create the tracking issue with `gh issue create`, then call `Issue.addBlockedBy` | Native blocked-by displayed in GitHub Relationships panel + searchable / dashboard visible | 1–2 extra issues |\n\n**Self-check (right after a PR-PR priority conclusion)**: if option (C) is feasible, **emit an AskUserQuestion that defaults to recommending (C)**. Do not silently apply (A) only — keep (A) alone only when the user picks \"body is enough\". Because of the `git.md` \"do not autonomously create issues\" rule, the (C) issue creation must wait for explicit user approval.\n\n| # | Don't | Do |\n|---|-------|-----|\n| 1 | Assume without verifying that \"PRs are Issue nodes so `addBlockedBy` works\" and call the mutation | Run a Step 2 query first to confirm `__typename` and `blockedBy` field existence. If it is a PR, branch into (A) / (B) / (C) |\n| 2 | Report the priority conclusion in chat without applying it to GitHub state | The conclusion is itself the call trigger. In the same response turn, update the (A) PR body or invoke (C) `addBlockedBy` on the issue |\n| 3 | Over-apply the \"scope discipline\" rule with \"the user did not explicitly ask, so I'll defer\" | Fact analysis implies applying the result to GitHub. Scope discipline forbids adding **new work** the user did not ask for, NOT applying the **answer** that was concluded |\n\n**Self-check (every time, right before reporting a PR/issue priority conclusion)**:\n1. Does the report text contain priority words such as \"merge X first\", \"Y blocked by X\", \"X → Y rebase is natural\"?\n2. If yes → check the node type → if Issue, invoke Step 2 → 3 → 4; if PR, branch (A)/(B)/(C) and execute\n3. Include the call result (URL or PR number) on the last line of the report\n\n## GitHub Issue Dependencies (Native Feature)\n\nGitHub Issues exposes the following GraphQL fields for issue-level dependencies:\n\n| Field | Description |\n|-------|-------------|\n| `Issue.blockedBy` | Issues that block this one (must complete first) |\n| `Issue.blocking` | Issues that this one blocks |\n| `Issue.issueDependenciesSummary` | `{ totalBlockedBy, totalBlocking }` summary counts |\n| `Issue.duplicateOf` | Duplicate-of relationship |\n\nUI display: Issue detail page → **Relationships** panel → \"Blocked by\" / \"Blocking\" sections.\n\nThis is distinct from:\n- **Sub-issues** (`Issue.subIssues` / `Issue.parent`) — hierarchical parent-child, used for breaking down a large issue into smaller ones\n- **GitHub Projects v2 Dependencies** — Project-scoped, requires Project board setup\n- **Cross-references** (timeline `CrossReferencedEvent`) — auto-generated from `#N` mentions in body/comments, no semantic meaning\n\n### Avoid confusing Sub-issue vs Blocked-by (HARD STOP)\n\n| Relationship | Meaning | Direction | Example |\n|--------------|---------|-----------|---------|\n| **sub-issue** | A is a sub-task of B (containment) | A.parent = B | #306 (environment fix) is a sub-issue of #283 (E2E automation) |\n| **blocked-by** | A cannot start until B finishes (sequential) | A.blockedBy = [B] | #282 (test hardening) starts only after #255 (redirect normalization) completes |\n\n**Never set parent blocked-by on a sub-issue**: if sub-issue A is set as blocked-by on parent B, a circular contradiction results — B's completion needs A, and A's start needs B's completion. The sub-issue relationship already expresses containment; a separate blocked-by is unnecessary.\n\n| # | Don't | Do |\n|---|-------|-----|\n| 1 | Set a sub-issue as blocked-by on its parent | Keep only the sub-issue relationship; do not set blocked-by |\n| 2 | Mechanically convert \"below in the diagram\" to \"blocked-by\" | Decide the relationship type first (containment vs sequence), then set only the appropriate relationship |\n\n## Procedure\n\n### Step 1: Source the Dependency Map\n\nIdentify the chain to apply. Two valid sources:\n\n| Source | When | Format |\n|--------|------|--------|\n| `code-workflow` plan frontmatter | Plan was written with explicit `blocked_by` matrix | YAML `chain:` array |\n| ad-hoc text instruction | User describes the chain in conversation | Build matrix from conversation |\n\nPlan frontmatter example:\n\n```yaml\n---\nplan: <name>\nchain:\n  - issue: 282\n    blocked_by: [255]\n  - issue: 253\n    blocked_by: [282]\n---\n```\n\n### Step 2: Fetch Issue Node IDs\n\nGraphQL `addBlockedBy` requires GitHub node IDs (not issue numbers). Fetch in one query:\n\n```bash\nGH_TOKEN=\"$(gh auth token --user <account>)\" gh api graphql -f query='\n  query {\n    repository(owner:\"<owner>\", name:\"<repo>\") {\n      i255: issue(number:255) { id }\n      i282: issue(number:282) { id }\n      i253: issue(number:253) { id }\n    }\n  }\n'\n```\n\nSave IDs into the plan frontmatter `node_ids:` map for reuse.\n\n### Step 3: Inspect Existing Dependencies\n\nBefore adding, query the current state to avoid duplicate mutations:\n\n```bash\nGH_TOKEN=\"$(gh auth token --user <account>)\" gh api graphql -f query='\n  query {\n    repository(owner:\"<owner>\", name:\"<repo>\") {\n      issue(number: <N>) {\n        blockedBy(first:10) { nodes { number title } }\n        blocking(first:10) { nodes { number title } }\n        issueDependenciesSummary { totalBlockedBy totalBlocking }\n      }\n    }\n  }\n'\n```\n\nCompare with the desired matrix → identify only the missing relationships.\n\n### Step 4: Add Dependencies (one at a time, sequentially)\n\nFor each missing relationship, run `addBlockedBy`:\n\n```bash\nGH_TOKEN=\"$(gh auth token --user <account>)\" gh api graphql \\\n  -f query='mutation($issueId:ID!,$blockingIssueId:ID!) {\n    addBlockedBy(input:{issueId:$issueId, blockingIssueId:$blockingIssueId}) {\n      issue { number issueDependenciesSummary { totalBlockedBy } }\n    }\n  }' \\\n  -f issueId=\"<TARGET_ID>\" \\\n  -f blockingIssueId=\"<BLOCKING_ID>\"\n```\n\n- `issueId`: the issue being blocked (downstream)\n- `blockingIssueId`: the issue that blocks (upstream)\n\n**Do not repeatedly call external APIs** — apply 1 at a time, verify response, get user confirmation before next.\n\n### Step 5: Verify\n\nAfter applying, re-query Step 3 → confirm `blockedBy` matches the plan's `blocked_by` array.\n\n```bash\nfor N in <list of issue numbers>; do\n  GH_TOKEN=\"$(gh auth token --user <account>)\" gh api graphql \\\n    -f query=\"query { repository(owner:\\\"<owner>\\\", name:\\\"<repo>\\\") { issue(number:$N) { blockedBy(first:5) { nodes { number } } } } }\"\ndone\n```\n\nUI verification: open each issue page → Relationships panel → confirm \"Blocked by\" lists the predecessors.\n\n## Sub-issue Management (Parent-Child Hierarchy)\n\nGitHub Issues supports native **sub-issue** relationships via `addSubIssue` / `removeSubIssue` GraphQL mutations and `Issue.subIssues` / `Issue.parent` query fields.\n\n**Sub-issue ≠ Blocked-by**: Sub-issues represent hierarchical breakdown (A is part of B), NOT sequential dependency (A must finish before B starts). See the \"Avoid confusing Sub-issue vs Blocked-by\" table above.\n\n### When to Use Sub-issues\n\n| Scenario | Use Sub-issue? | Example |\n|----------|---------------|---------|\n| Task is a sub-task of a larger Epic/Issue | **Yes** | #314 (translate permissions list) is a sub-issue of #343 (user management feature) |\n| Multiple small tasks compose one feature | **Yes** | Break #200 (SSO integration) into #201, #202, #203 |\n| Task must finish before another starts | **No** — use blocked-by | #255 must complete before #282 starts |\n\n### Sub-issue Procedure\n\n#### Step S1: Identify Parent and Child Issue Node IDs\n\n```bash\nGH_TOKEN=\"$(gh auth token --user <account>)\" gh api graphql -f query='\n  query {\n    repository(owner:\"<owner>\", name:\"<repo>\") {\n      parent: issue(number:<PARENT_NUMBER>) { id }\n      child: issue(number:<CHILD_NUMBER>) { id }\n    }\n  }\n'\n```\n\n#### Step S2: Check Existing Sub-issues\n\n```bash\nGH_TOKEN=\"$(gh auth token --user <account>)\" gh api graphql -f query='\n  query {\n    repository(owner:\"<owner>\", name:\"<repo>\") {\n      issue(number:<PARENT_NUMBER>) {\n        subIssues(first:20) { nodes { number title state } }\n        subIssuesSummary { total completed percentCompleted }\n      }\n    }\n  }\n'\n```\n\nIf the child issue already appears in `subIssues.nodes`, skip Step S3.\n\n#### Step S3: Add Sub-issue\n\n```bash\nGH_TOKEN=\"$(gh auth token --user <account>)\" gh api graphql \\\n  -f query='mutation($parentId:ID!,$childId:ID!) {\n    addSubIssue(input:{issueId:$parentId, subIssueId:$childId}) {\n      issue { number subIssuesSummary { total completed percentCompleted } }\n      subIssue { number title }\n    }\n  }' \\\n  -f parentId=\"<PARENT_NODE_ID>\" \\\n  -f childId=\"<CHILD_NODE_ID>\"\n```\n\n- `issueId` (parentId): the parent issue that contains the sub-issue\n- `subIssueId` (childId): the issue to add as a sub-issue\n\n#### Step S4: Verify\n\nRe-query Step S2 → confirm the child appears in `subIssues.nodes`.\n\n### Remove Sub-issue\n\n```bash\nGH_TOKEN=\"$(gh auth token --user <account>)\" gh api graphql \\\n  -f query='mutation($parentId:ID!,$childId:ID!) {\n    removeSubIssue(input:{issueId:$parentId, subIssueId:$childId}) {\n      issue { number subIssuesSummary { total } }\n      subIssue { number }\n    }\n  }' \\\n  -f parentId=\"<PARENT_NODE_ID>\" \\\n  -f childId=\"<CHILD_NODE_ID>\"\n```\n\n### Sub-issue Don't / Do\n\n| # | Don't | Do |\n|---|-------|-----|\n| 1 | Add only a `- #N` text link in the body and call \"sub-issue registration done\" | Create the native relationship via the `addSubIssue` GraphQL mutation |\n| 2 | Update only the parent body after `gh issue create` | `gh issue create` → `addSubIssue` → update parent body (all three steps are required) |\n| 3 | Substitute Sub-issue for blocked-by | Sub-issue = containment (A is part of B). Blocked-by = sequence (B before A). Do not mix |\n\n## Removal\n\nTo remove an incorrect blocked-by relationship:\n\n```bash\nGH_TOKEN=\"$(gh auth token --user <account>)\" gh api graphql \\\n  -f query='mutation($issueId:ID!,$blockingIssueId:ID!) {\n    removeBlockedBy(input:{issueId:$issueId, blockingIssueId:$blockingIssueId}) {\n      issue { number }\n    }\n  }' \\\n  -f issueId=\"<TARGET_ID>\" \\\n  -f blockingIssueId=\"<BLOCKING_ID>\"\n```\n\n## Pre-merge Check (Integration with merge.md)\n\nBefore squashing/merging a PR, verify the linked issue's `blockedBy` is empty or all resolved:\n\n```bash\nGH_TOKEN=\"$(gh auth token --user <account>)\" gh api graphql -f query='\n  query { repository(owner:\"<owner>\", name:\"<repo>\") {\n    issue(number:<N>) {\n      blockedBy(first:10) { nodes { number state title } }\n    }\n  } }\n'\n```\n\nIf any node has `state: OPEN`, **block the merge** and report the predecessor issue. The merge of the dependent should wait until predecessors are CLOSED.\n\n## Auto-population from `code-workflow` Plan\n\nWhen `code-workflow/steps.md` step 3 (User Review) generates a plan with downstream work, the plan frontmatter should declare `chain:` and `blocked_by:`. After plan approval, the dependencies topic procedure applies the chain to GitHub.\n\n```text\ncode-workflow plan (frontmatter chain:)\n  └─→ github-flow/dependencies (Step 2-4: apply to GitHub)\n        └─→ github-flow/merge (Step 5: pre-merge blockedBy check)\n```\n\n## Don't / Do\n\n| # | Don't (forbidden) | Do (correct alternative) |\n|---|-------------------|--------------------------|\n| 1 | Use `Closes #N` / `Fixes #N` keywords for issue-issue blocking | These work only for PR → issue. Use `addBlockedBy` for issue → issue |\n| 2 | Manually write `## Blocked by\\n- #N` in issue body | Issue body markdown is not parsed by GitHub for dependencies. Use `addBlockedBy` so it appears in the Relationships panel |\n| 3 | Add 5+ dependencies in a single bash for-loop | API rate limit + abuse detection. Apply 1 at a time with user confirmation |\n| 4 | Skip Step 3 (existing dependencies query) | `addBlockedBy` is idempotent but wastes API calls. Always query first |\n| 5 | Use Sub-issues for sequential blocking | Sub-issues = hierarchical breakdown, not blocking. Use blockedBy for \"must complete X before Y\" |\n| 6 | Hardcode issue node IDs in conversation | IDs change across forks/clones. Always fetch via Step 2, store in plan frontmatter |\n| 7 | Add only a `- #N` text link in the body and declare \"sub-issue done\" | Create the native relationship via the `addSubIssue` mutation. Body links are a supplement |\n| 8 | Update only the parent body after `gh issue create` | `gh issue create` → `addSubIssue` → update parent body (all three steps required) |\n\n## Rules\n\n- **Default off for creation-time auto-application**: Do NOT auto-apply `addBlockedBy` on every issue/PR creation. Apply only on these triggers:\n  - User explicitly requests blocked-by application\n  - Plan with `chain:` frontmatter exists\n  - **Chat-time priority conclusion** (PR-PR or issue-issue ordering decided in the current conversation) — apply immediately, same turn as the conclusion report\n- **PR repo language**: Same as plan-to-issue.md — GraphQL mutations don't post text, but if the dependency check is reported in fix_plan or PR comments, apply Korean/English rules per repo visibility.\n- **fix_plan reflection only**: For local-only tracking without GitHub UI changes, record the dependency map in plan frontmatter and reference from fix_plan.md. Skip Step 4 (no `addBlockedBy` calls).\n\n## Related\n\n- `plan-to-issue.md` — issue body/comment management. Dependencies are separate from body content\n- `merge.md` — Step 5 pre-merge check uses Step 3 query\n- \"Do not repeatedly call external APIs\" principle — applied to Step 4 (1 at a time, confirm before next)\n\nFile v0.11.3:epic-bundle.md\n\n# Epic Bundle — Deferred Review Findings → One Epic Issue\n\nBundle **deferred review findings** scattered across multiple PRs into a single **Epic tracking issue**: one issue with a checklist body, native sub-issue relationships for any split-out work, and an `epic` label. This turns a pile of \"fix later\" review items into one assignable, trackable unit (a checklist Epic).\n\n## When to Use\n\n- After several PRs merged, each leaving non-blocking `[REVIEW_FEEDBACK]` findings deferred for later\n- When the deferred items span 2+ PRs and would otherwise be lost in scattered tracking entries\n- When a maintainer wants a single hand-off artifact a junior/teammate can pick up (flexible split)\n\n### Triggers\n\n| Trigger | Source |\n|---------|--------|\n| Explicit call | User names the PRs to bundle (e.g., \"bundle the deferred findings from #A #B #C into an epic\") |\n| Auto-suggest | `consolidate` next step proposes this when deferred findings accumulate across N+ PRs (see consolidate → next). The suggestion is an offer, not an auto-run — issue creation still needs explicit user approval (see Rules) |\n\n## Input Sources\n\nFindings are collected from two media, **checklist first, PR comments as supplement**:\n\n| Source | What | Priority |\n|--------|------|----------|\n| Deferred-tracking checklist | The local checklist where `[REVIEW_FEEDBACK]` deferred items were already recorded (one line per finding, PR-tagged) | Primary — reuse the already-classified entries |\n| PR review comments | The Internal Review / AI Review Summary comments on each PR | Supplement — catch findings not yet written to the checklist |\n\n> The deferred-tracking checklist is a local-only artifact. Per Core Rule #2, **never** name its path in the Epic body — describe items by their content, not their checklist location.\n\n## Procedure\n\n### Step 1: Gather Deferred Findings\n\nFor each target PR:\n\n1. Read the deferred-tracking checklist entries tagged with that PR (primary source).\n2. Fetch the PR's review comments as a supplement to catch un-recorded findings:\n   ```bash\n   GH_TOKEN=\"$(gh auth token --user <account>)\" gh pr view <PR> -R <owner>/<repo> --comments\n   ```\n3. Build a flat finding list. For each finding keep: `{pr, severity, type, title, file:line, author-or-ownership}`.\n\n### Step 2: Dedup + Group\n\n- **Dedup**: drop findings already resolved by a later merged PR (cross-check the checklist for `[x]`/resolved markers). Same-file+same-line duplicates collapse to one.\n- **Group by source PR (primary)**: the checklist body is organized under one section per source PR, so the PR ref lives once in the section header (autolinked) and never repeats inline on each line. Do NOT group the checklist by theme — theme groups mix PRs and force a per-line `(#PR)` token.\n- **Theme is secondary (prose only)**: capture cross-PR themes separately for the \"Suggested grouping\" prose block, which informs the split without polluting the checklist.\n\n### Step 3: Confirm Scope + Split (AskUserQuestion)\n\nPresent the bundle and let the user decide the split shape (mirrors a \"flexible split\" epic):\n\n```text\nAskUserQuestion {\n  question: \"<N> deferred findings across <PRs>. How should the Epic be split?\",\n  multiSelect: false,\n  options: [\n    { label: \"Single Epic checklist (Recommended)\", description: \"One issue, all findings as a checklist. Splitting into child PRs is left to whoever picks it up\" },\n    { label: \"Epic + grouped sub-issues\", description: \"One Epic + native sub-issues per theme group (uses dependencies/addSubIssue)\" },\n    { label: \"Adjust grouping\", description: \"Re-cluster before creating\" }\n  ]\n}\n```\n\nOwnership note: findings on **another author's branch** are tracked in the Epic checklist but stay comment-only on the PR itself (branch ownership boundary). Mark such items so the picker knows they need the author or a fresh branch.\n\n### Step 4: Create the Epic Issue\n\nBuild the Epic body via the **plan-to-issue** topic (MD → issue body), then create the issue. Run the **register** topic first to avoid duplicating an existing Epic.\n\nEpic body shape — **group findings under per-PR section headers** so the source PR ref appears once (autolinked) in the header, never repeated inline on every checklist line:\n\n```markdown\n## Background\n\nConsolidated deferred review findings from #<PR-a>, #<PR-b>, #<PR-c> (non-blocking, deferred at merge time).\n\n## Findings (flexible split — bundling/splitting into PRs is the picker's call)\n\n### #<PR-a> — <theme summary> (@<author>)\n\n- [ ] 1. <severity> <type>: <title> — `<file>:<line>`\n- [ ] 2. <severity> <type>: <title> — `<file>:<line>`\n\n### #<PR-b> — <theme summary> (@<author>)\n\n- [ ] 3. <severity> <type>: <title> — `<file>:<line>`\n\n## Suggested grouping (prose — cross-PR theme combos for the picker)\n\n- <theme X> (items 1, 3) → recommended combined PR\n- <theme Y> (item 2) → standalone\n\n## Verification\n\nEach finding's PR carries its own test plan; this Epic closes when every checklist item is resolved (or explicitly de-scoped).\n```\n\n- **Hoist the PR ref to the section header, not every line** — a section header `### #<PR> — <theme>` autolinks the PR once and reads cleanly; repeating `(#<PR>)` on every checklist item is per-line noise that degrades readability.\n- **Use bare `#N`** for real PR/issue references in headers and prose (GitHub autolinks them); use plain `1.`/`2.` finding numbers as list labels, never bare `#N` that would cross-link unrelated issues.\n- **Sanitize** the body before posting (PUBLIC repos) — run the `sanitize` topic.\n- `gh issue create` requires **explicit user approval** (see Rules). Create with `--label epic`:\n  ```bash\n  GH_TOKEN=\"$(gh auth token --user <account>)\" gh issue create -R <owner>/<repo> \\\n    --title \"[Epic] <theme> — deferred review findings from #<PR-a>/#<PR-b>/#<PR-c>\" \\\n    --body-file <epic-body.md> --label epic\n  ```\n  If the `epic` label is missing, create it first (`gh label create epic --color 7B68EE`).\n\n### Step 4.5: Optional Visualization Dispatch (many-PR bundles)\n\nFor a bundle spanning many source PRs, the per-PR-section checklist (Step 4) can get hard to scan. Offer a **d3 force-directed render** of the Epic structure as an additional, opt-in deliverable — reusing the same abstract `--render=<skill>:<topic>` dispatch contract already proven by `skill-kit/graph` and `cc-plugin/clustering` (see `skill-kit/portability` Rule B — do NOT hardcode a specific receiver).\n\n**When to offer**: bundle spans ≥4 source PRs, or the user explicitly asks for a visual. Below that threshold the markdown checklist stays clearer and cheaper — this is additive, never a replacement for Step 4's body.\n\n**Schema mapping** (caller transforms Epic data into the receiver's `{groups, skillHubs, topics, links}` schema):\n\n| Epic element | Schema field |\n|---|---|\n| Epic issue | one `skillHubs` node (the hub) |\n| each source PR | a `topics` node, `owner: <Epic hub id>` (auto-generates the membership link) |\n| finding count on that PR | `links[].weight` (clamp to the schema's 1–10 range) |\n| theme summary (Step 2 \"Suggested grouping\") | `links[].note` |\n\n**Dispatch**:\n\n```bash\n/github-flow epic-bundle <PRs> --render=<receiver-skill>:<receiver-topic>\n```\n\nWhen the flag is supplied, invoke the receiver with the transformed JSON after Step 4 (Epic body already built) and report the rendered HTML path alongside the issue URL. When omitted, the procedure stops at the markdown Epic body — no visualization step runs.\n\n#### Don't / Do\n\n| # | Don't | Do |\n|---|-------|-----|\n| 1 | Default this on for every bundle | Offer it only when the PR count crosses the threshold, or on explicit request — small bundles are cheaper as a checklist |\n| 2 | Hardcode a specific render receiver in this topic body | Use the abstract `--render=<skill>:<topic>` flag — caller chooses the receiver (`skill-kit/portability` Rule B) |\n| 3 | Treat the render as a second SSOT for Epic state | The rendered HTML is a point-in-time snapshot of the Epic body at dispatch time, not a live view — re-dispatch after significant body edits if a fresh render matters |\n\n### Step 5: Sub-issues (only if \"Epic + grouped sub-issues\" chosen)\n\nFor each child issue, use the **dependencies** topic Sub-issue Procedure (`addSubIssue`) to create the native parent-child relationship — a `- #N` body link alone is not enough.\n\n### Step 6: Cross-reference Back\n\n- Update the deferred-tracking checklist: replace the scattered per-PR deferred lines with a single pointer to the Epic issue number, so future scans see them as bundled (not unbundled).\n- If any finding was resolved by a merged PR during gathering, map it `[x]` in the Epic body with the resolving PR number.\n\n## Don't / Do\n\n| # | Don't | Do |\n|---|-------|-----|\n| 1 | Name the internal deferred-tracking checklist path in the Epic body | Describe findings by content; the checklist is local-only (Core Rule #2) |\n| 2 | `gh issue create` autonomously because findings exist | Issue creation needs explicit user approval (`git.md` \"no autonomous issue create\"). The auto-suggest is an offer only |\n| 3 | Wrap real PR/issue refs in backticks (`` `#N` ``) | Bare `#N` so GitHub autolinks; use `1.` labels for finding numbers to avoid stray cross-links |\n| 3a | Repeat `(#PR)` inline on every checklist line (group by theme → mixes PRs) | Group the checklist by source PR; hoist the `#PR` to the section header once (autolink, clean). Inline per-line PR ref is readability noise |\n| 4 | Add only `- #N` body links and call sub-issues done | Create native relationships via `addSubIssue` (dependencies topic) |\n| 5 | Bundle another author's branch findings as actionable in our scope | Track in the Epic checklist but flag as author-owned (comment-only on their PR) |\n| 6 | Re-bundle findings already resolved by a merged PR | Dedup against resolved/`[x]` markers in Step 2 first |\n| 7 | Post the Epic body to a PUBLIC repo without scanning | Run `sanitize` before `gh issue create` |\n\n## Self-check (before `gh issue create`)\n\n1. Did the user explicitly approve creating the issue? If no → stop, ask.\n2. Is the body free of internal checklist paths and any personal data (sanitize passed)?\n3. Are all real PR/issue refs bare `#N` (not backticked)?\n3a. Is the checklist grouped by source PR (PR ref in section header), with **no inline `(#PR)`** repeated on each line?\n4. Are resolved findings already mapped `[x]` (not re-bundled as open)?\n5. Does the title carry `[Epic]` + the source PR numbers, and is `--label epic` applied?\n\n## Related\n\n- `plan-to-issue.md` — builds the Epic body (MD → issue body)\n- `register.md` — duplicate-Epic check before create\n- `dependencies.md` — Sub-issue Procedure (`addSubIssue`) for the grouped-sub-issues split\n- `sanitize.md` — HARD STOP personal-data scan before posting\n- `consolidate` next step — emits the auto-suggest that routes here\n- `skill-kit/graph.md` / `cc-plugin/clustering.md` — the `--render=<skill>:<topic>` abstract dispatch contract Step 4.5 reuses\n- `es6kr-graph` — the standalone D3-force receiver this repo already has for the schema in Step 4.5\n\nFile v0.11.3:expand.md\n\n# PR / Issue Scope Expansion\n\nWhen new findings emerge during in-progress work, decide whether to **expand** the existing PR/issue or **split** into a separate one — and update title/body accordingly.\n\n## When to Use\n\n- Mid-implementation, you discover an additional change required to make the original work coherent (e.g., a config refactor, a structural fix, a related bug)\n- The new finding shares the same blast radius as the in-progress work (same files, same review context, same deploy unit)\n- The user says \"expand the PR/issue\", \"widen the scope\", \"include that too\", or rejects splitting\n\n**Anti-pattern (the \"nickel-and-dime\" pattern)**: Defaulting to \"small PR is good\" and pushing every related fix into a follow-up PR or \"post-merge cleanup\". Small ≠ correct. Coherence matters more than line count.\n\n## Decision Matrix — Expand vs Split\n\nUse this table to decide:\n\n| Signal | Expand current PR/issue | Split into new PR/issue |\n|---|---|---|\n| Same file or directly coupled file | ✅ | |\n| Required for the original work to verify end-to-end | ✅ | |\n| Same deploy unit / same release window | ✅ | |\n| Reverting one without the other leaves broken state | ✅ | |\n| User said \"include it\" or \"expand\" | ✅ | |\n| Different reviewer / domain expertise needed | | ✅ |\n| Different release cadence | | ✅ |\n| Independent of original work (could ship alone) | | ✅ |\n| Adds significant unrelated diff (>100 LOC + different concern) | | ✅ |\n\n**Default bias**: when in doubt, **expand**. The cost of splitting too eagerly (post-merge cleanup, forgotten follow-ups, broken coherence) is higher than a slightly larger PR.\n\n## Mandatory Procedure (Expansion)\n\nWhen you decide to expand, **all four steps are required** — partial expansion (commit added but title/body stale) is a violation:\n\n### 1. Commit the new change in the same branch\n\nAdd the new finding's commits to the existing PR's branch. Do not create a separate branch.\n\n### 2. Update the PR/issue title\n\nThe title must reflect the **expanded scope**, not the original narrow scope.\n\n```bash\ngh pr edit <N> -R <repo> --title \"<expanded title>\"\ngh issue edit <N> -R <repo> --title \"<expanded title>\"\n```\n\nTitle pattern: `<type>(<scope>): <primary work> + <expansion>` or restructure entirely if the scope shifted.\n\n### 3. Update the PR/issue body\n\nThe body must:\n- Add the new finding to the **Summary / Changes** section\n- Update the **Test Plan** with new verification items (and check off completed ones)\n- Add to **Files to modify** or equivalent\n- Update **Relates to** with any new linked issues\n\n```bash\ngh pr edit <N> -R <repo> --body-file <updated-body>\ngh issue edit <N> -R <repo> --body-file <updated-body>\n```\n\n### 4. Cross-link in linked issues / epic\n\nIf the PR is linked to an epic or other issues, update those bodies too — the expanded scope changes what they track.\n\n## Examples\n\n### Example 1: PR scope expansion (infra repo, integration apply)\n\n**Original PR scope**: integration terraform apply (namespace rename for an internal project)\n\n**Discovered mid-work**:\n- `secrets.production.auto.tfvars` leaks into all env plans (structural defect)\n- A shared module needs additional variables to preserve imported values for two downstream projects\n- The main repo's `secrets.*.auto.tfvars` should be renamed to `secrets.*.tfvars`\n\n**Wrong approach** (the \"nickel-and-dime\" pattern):\n- PR = code changes only (Makefile, .gitignore, module.tf, variables.tf)\n- \"The secrets rename happens after this PR merges\"\n- Title stays narrow: \"fix(PAM): integration apply\"\n\n**Correct approach** (expansion):\n- PR = all 4 changes bundled (code + secrets rename + import preservation + secrets defect fix)\n- Title updated: `fix(PAM): integration apply + module import preservation + secrets auto-load defect fix`\n- Body updated: Summary + Test Plan + Files to modify all reflect 4 areas\n- Reason: all four changes share the same blast radius (the IaC directory) and the original work's verification (`make plan ENV=integration` clean) requires all four\n\n### Example 2: Issue scope expansion\n\n**Original issue**: \"fix(PAM): apply OAuth Source rename to dev-A environment (follow-up to #306)\"\n\n**Discovered**: dev-A also needs VPN URL config + automation-template arg update + `dt-source-auto-redirect` flow rename impact.\n\n- Update issue title: `fix(PAM): apply OAuth Source rename in dev-A + adjacent environment hardening (follow-up to #306)`\n- Update issue body: add discovered scope to Verification table\n- Cross-link epic: epic body's Phase 4 row updated to reflect expanded scope\n\n## Forbidden — Cleanup-Deferral Pattern\n\nThese phrases are red flags that you are splitting when you should be expanding:\n\n- \"Do X after the PR merges\"\n- \"X as a follow-up PR\"\n- \"Stage A in this PR, Stage B as a separate issue\"\n- \"Code now, cleanup later\"\n\nIf the deferred work is required for the original work to be **complete and verifiable**, it belongs in this PR. Use this skill's decision matrix to challenge the deferral instinct.\n\n## Title/Body Update Checklist (HARD STOP)\n\nBefore marking expansion complete, verify all of these:\n\n- [ ] Commits added to existing branch (not a separate branch)\n- [ ] PR/issue title updated with `gh pr edit` / `gh issue edit`\n- [ ] PR/issue body Summary section reflects expanded scope\n- [ ] Test Plan items added/updated for new findings\n- [ ] Files to modify list updated\n- [ ] Linked epic/parent issue body updated if scope changed\n- [ ] Cross-references (`Relates to #N`) added for newly linked issues\n\nSkipping any of these = \"expanded the work but left metadata stale\" — the same coherence loss the expansion was meant to prevent.\n\n## Cross-references\n\n- `code-workflow` Step 4 (Implement) — call this skill the moment a new finding emerges, not after PR is created\n- `pr` topic (`pr.md`) — initial PR creation. Use `expand` when adding to an existing PR mid-work\n- `plan-to-issue` topic — initial issue body. Use `expand` when issue scope grows during implementation\n- `commit-tidy` — handles commit-level split/squash. `expand` handles PR/issue-level scope decisions\n\nFile v0.11.3:identity-auth.md\n\n# Identity and Auth\n\n`gh` CLI is the first-choice GitHub interface. Owner-based commit-author identity mapping. `gh auth refresh` scope management. `GH_TOKEN` env fallback for org-repo 404.\n\n## When to use\n\n- Before every commit on a repo whose remote owner you have not verified this session\n- Before every PR creation / push that requires push authorization\n- On 404 / 403 from `gh repo view`, `gh issue create`, `gh pr create`, etc.\n- When switching between multiple `gh auth` accounts (multi-account workflows)\n- When invoking `gh run`, `gh workflow`, `gh release`, `gh copilot` and getting a scope error\n\n## gh CLI first (HARD STOP)\n\n**For ALL GitHub-related work (PR view, review, comment, merge, etc.), `gh` CLI is the first-choice tool.** Forbid escape-to-browser-agent (`browser_subagent`) for routine GitHub tasks.\n\n| # | Don't | Do |\n|---|-------|-----|\n| 1 | Invoke a browser agent to verify / consolidate PR review | Combine `gh pr view`, `gh api`, `gh pr checks` to extract data from CLI |\n| 2 | Skip CLI on the subjective belief \"the browser is more accurate\" | `gh` CLI is the most reliable source — authentication and context are preserved. Consider the browser ONLY when CLI fails |\n| 3 | Wait for browser-rendering of a simple data query (e.g., comment list) | `gh api` with JSON parse. Much faster, fewer tokens |\n\nThe browser agent is reserved for **situations CLI cannot handle** (e.g., complex GUI configuration, visual layout verification), with user pre-approval.\n\n### IDE Subshell GITHUB_TOKEN override rule (HARD STOP)\n\nIn IDE subshell environments (e.g. Antigravity), a dummy or environment-injected `GITHUB_TOKEN` (such as `github_pat_antigravitydummytoken`) may exist in environment variables. `gh` CLI prioritizes `GITHUB_TOKEN` over stored keyring accounts, causing 401 Bad Credentials errors.\n- **Rule**: When executing `gh` CLI commands in subshells where `GITHUB_TOKEN` is present, always use `env -u GITHUB_TOKEN gh ...` (or unset `GITHUB_TOKEN` before calling `gh`) so `gh` uses stored keyring credentials.\n\n\n## Owner-based commit-author identity mapping (HARD STOP)\n\n**`gh` account mapping applies not only to push / PR auth but also to commit-author identity.** When committing to an org repo (PUBLIC included), if the `gh` active account is a different identity (e.g., leftover from a different repo's work), the commit author gets stamped wrong and the wrong identity becomes permanent in PUBLIC history.\n\n**Before commit: switch `git author identity` + `gh account` to match the repo owner.**\n\n### Don't / Do\n\n| # | Don't | Do |\n|---|-------|-----|\n| 1 | Commit to an org repo with the active account left from a previous workflow → wrong author stamped | Before commit: `git -C <repo> config user.name \"<name-for-owner>\" && git -C <repo> config user.email \"<email-for-owner>\"` |\n| 2 | Push / PR uses the right identity but commit author left unchanged | Author + committer + push + PR all use the same identity. PUBLIC history permanently records the author, so consistency is mandatory |\n| 3 | \"Auth is needed only at push time\" reasoning | Commit author is stamped at commit time. An already-wrong author can only be fixed via amend / rebase |\n| 4 | Commit without checking the repo owner | Right before commit, run `git remote get-url origin` to confirm the owner → set identity per the owner-identity mapping |\n\n### Self-check (every time before commit — owner-based)\n\n1. `git -C <repo> remote get-url origin` — determine the owner\n2. Look up the owner in your **owner-identity mapping table** (workspace-specific; live in `~/.agents/.claude/rules/identity.md` or a workspace `.claude/rules/identity.md`, NOT in this generic skill)\n3. Set `git config user.name` + `user.email` + `gh auth switch` (or inject `GH_TOKEN`) to match the owner mapping\n4. If `git config user.email` does not match the mapping, fix BEFORE commit. If already committed wrong AND **unpushed**: `git commit --amend --reset-author` (no force-push needed)\n5. PR creation also uses the matched account (`gh pr create` consumes the active account → pre-switch via `gh auth switch` or inject `GH_TOKEN`)\n\n### Self-check (every time before push / PR creation — push-identity track)\n\n**Commit-author identity ≠ PR-creator identity.** Commit `author` is stamped from `git config user.*` at commit time and is independent from the `gh` account or SSH key used at push or PR-create time. GitHub assigns **PR `author` = the gh account that runs `gh pr create`** (or, on the web UI, whichever account is signed in when \"Create pull request\" is clicked) — *not* the commit's `author` field, and not \"whoever pushed\" as a separate step. In the standard CLI flow that account is the one whose token/SSH key also authorized the immediately preceding push, so push identity and PR author usually coincide, but the canonical source is the PR-create action, not the push by itself. A wrong PR-create identity records a wrong PR author and **cannot be fixed by `git commit --amend`** — the PR `author` is immutable on GitHub once recorded.\n\n1. `git -C <repo> remote get-url origin` — determine the owner (same step as commit track)\n2. Look up the owner in the owner-identity mapping table → `<expected gh account>`\n3. **Primary-source check** — confirm the active push identity matches:\n   - `gh auth status` → identify the `Active account` line. It must equal `<expected gh account>`\n   - `gh api user --jq '.login'` → the response login must equal `<expected gh account>`\n   - SSH-only repos: `ssh -T git@github.com 2>&1 | grep -oE 'Hi [^!]+!'` → the matched name must equal `<expected gh account>`\n4. Mismatch → `gh auth switch --user <expected>` (or `scripts/gh-as.sh <expected> <gh-args...>` — wraps the `GH_TOKEN=\"$(gh auth token --user <expected>)\"` injection), and for SSH ensure `core.sshCommand` or `ssh-add -l` points to the key registered on `<expected gh account>`\n5. **Only after Steps 3-4 pass** → run `git push` or `gh pr create`\n6. If push already happened with the wrong identity → the PR `author` is immutable. Options: (a) close the wrong-author PR + reopen from the correct account on a fresh branch; (b) accept the wrong author (PR `author` shows on the PR forever)\n\n### Don't / Do (push-identity track)\n\n| # | Don't | Do |\n|---|-------|-----|\n| 1 | Trust that `git config user.email` matches → assume push identity is also right | Run `gh api user --jq '.login'` separately. Commit identity and push identity are independent tracks |\n| 2 | Push first, \"fix the author later via `--amend`\" | `--amend --reset-author` only fixes commit author. PR `author` (GitHub user that pushed) is immutable once the PR is created |\n| 3 | Skip the SSH-key check when remote is `git@github.com:...` | SSH-only repos route through the loaded key's GitHub account. `ssh -T` test must return the expected name |\n| 4 | Switch `gh auth` after `gh pr create` already ran | `gh pr create` consumes the active account at call time. Switch BEFORE the call |\n| 5 | Multi-account setup: rely on memory (\"I think DrumRobot is active\") | Always run `gh auth status` + `gh api user` immediately before push/PR-create. The `gh` active account can drift between sessions |\n\n### Owner-identity mapping (defined elsewhere)\n\nThe actual `<owner> → <git author identity>` + `<gh account>` mapping table is **workspace-scoped**, not part of this skill. Maintain it in `~/.agents/.claude/rules/identity.md` (per-user) or `<workspace>/.claude/rules/identity.md` (per-project). Example shape (the specifics belong elsewhere):\n\n```text\n| Owner           | git author identity                   | gh account     |\n| --------------- | ------------------------------------- | -------------- |\n| org-A           | Identity-for-org-A <email-A@host>     | gh-account-A   |\n| org-B           | Identity-for-org-B <email-B@host>     | gh-account-B   |\n```\n\n### Failure pattern\n\nSee failed-attempts.md HOT entry \"PUBLIC repo commit with leftover account identity\" — a PUBLIC-repo commit landed with the previous workspace's account as author. Caught while still unpushed and corrected via `git commit --amend --reset-author`.\n\n## `gh` CLI scope (by task)\n\n### Common scope cheat sheet\n\n| Task | Required scopes | Note |\n|------|----------------|------|\n| Read public repo | `repo` (or `public_repo`) | |\n| Private repo (org) | `repo`, `read:org` | Required for org-owned private repos |\n| PR create / edit / merge | `repo` | |\n| Issue create / edit / comment | `repo` | |\n| GitHub Actions workflow query / dispatch | `repo`, `workflow` | `gh run`, `gh workflow` |\n| Release create / upload | `repo` | |\n| Discussions | `repo`, `read:discussion` | |\n| Codespaces | `codespace` | |\n| Copilot config (e.g., reviewer add) | `copilot` | |\n| User email read | `user:email` | |\n| Gist create / edit | `gist` | |\n| Pages management | `repo`, `pages` | |\n\n**Recommended combined scope (Ralph / autonomous workflows)**: `repo,read:org,workflow,copilot`\n\n### Permission-grant batching rule (HARD STOP)\n\n**On 404 detection or any \"scope insufficient\" instruction, refresh the FULL recommended scope set in ONE `-s`-flag call. Forbid splitting into multiple browser auth prompts.**\n\n| # | Don't | Do |\n|---|-------|-----|\n| 1 | Refresh only `repo,read:org` first, then later refresh `copilot` separately → user opens browser twice | On the first scope-shortage detection, refresh the **entire** recommended scope set with a single `--scopes \"repo,read:org,workflow,copilot\"` call |\n| 2 | Multi-account scope refresh done one account at a time with inefficient `switch` repetition | Minimize the number of `gh auth switch` + browser auth-window openings via a streamlined design that supports one-click bulk apply |\n\n```bash\n# Refresh including copilot in a single call\nenv -u GITHUB_TOKEN gh auth refresh --user <account> --scopes \"repo,read:org,workflow,copilot\"\n```\n\n## Org-repo 404 troubleshooting (self-resolve in order)\n\nRun these in order BEFORE asking the user:\n\n1. **Account switch check**: `gh auth status` → confirm the active account has access to the org\n2. **Scope check**: `gh auth status` output's \"Token scopes\" — verify against the table above. If missing scope → `gh auth refresh --user <account> --scopes \"...\"`\n3. **`GH_TOKEN` env injection (most frequent fix)**: even after `gh auth switch`, some commands fail to honor the active account due to a known gh CLI bug. Use this pattern to bypass:\n\n   ```bash\n   GH_TOKEN=\"$(gh auth token --user <account>)\" gh repo view <org>/<repo>\n   ```\n\n   If this succeeds, your scope / membership is fine — it was a gh CLI internal issue, no user intervention needed.\n\n   **Shorthand**: `scripts/gh-as.sh <account> <gh-args...>` wraps this exact pattern — use it instead of repeating the `GH_TOKEN=\"$(gh auth token --user ...)\"` prefix by hand. Example: `scripts/gh-as.sh <account> repo view <org>/<repo>`.\n4. **Org membership confirmation**: if steps 1-3 all fail with 404, ask the user about membership status\n\n## Self-check (before any gh-auth-requiring command)\n\n1. Is the target an org repo? — `gh repo view <org>/<repo> --json owner -q '.owner.login'`\n2. If org → confirm the active `gh auth status` user has access\n3. If 404 → run the troubleshooting list above (steps 1 through 4) before asking the user\n4. About to refresh scopes? → use the **single** combined scope refresh (don't split into multiple browser prompts)\n\n## Related topics\n\n- `merge` — merge requires `repo` scope for write operations\n- `pr` — PR creation requires `repo` scope; check `dependencies` for `addBlockedBy` GraphQL mutations\n- `push-guards` — `gh run list` (used in force-push CI status check) requires `repo`, `workflow` scope\n\n## Self-review account switch (scripted)\n\nWhen a PR author must review their own PR, the review must post from a dedicated review account, then restore the acting account. `scripts/review-as.sh` implements the full register → switch → verify → POST → restore sequence in one call:\n\n```bash\nscripts/review-as.sh --repo <owner/repo> --pr <N> --reviewer <review-account> \\\n  --acting <acting-account> --input <review-payload.json> [--skip-register]\n```\n\nThe acting account is restored on every exit path (`trap EXIT`), preventing review-account leakage into follow-up commits/comments.\n\n## PAT Scope Assignment Don't / Do (HARD STOP)\n\nActing accounts (DrumRobot / daegunjhy) canonical scope set = `repo,read:org,workflow,gist,copilot,read:packages` (6). Special-purpose accounts (daegunsoft-web review-only) use purpose-minimum set.\n\n| # | Don't | Do |\n|---|-------|----|\n| 1 | Add `read:packages` alone on GHCR pull denied, or `admin:repo_hook` alone for webhook-delivery diagnostics | Combined refresh: the new scope + the full canonical set in one `-s` call — avoid repeated browser auth. Narrow single-scope refreshes cost a full browser device-flow round-trip each time |\n| 2 | `gh auth refresh` manual guide only | Call `web-browser/credential-issue` topic first (auto auth). Manual guide is fallback |\n| 3 | Add scopes outside the matrix (over-grant) | Matrix 5 scopes + explicitly needed extras only |\n| 4 | Skip scope matrix check on new operation | Check matrix every time → if missing, add to this rule |\n| 5 | Run `gh auth login`/`refresh` without `-s` (only grants default `gist,read:org,repo`) | Always specify `-s` 5-scope — missing `workflow` on merge/push blocks `.github/workflows/*` changes |\n| 6 | Copy-paste browser PAT issue/edit URL from a previous case (`scopes=repo,read:org` re-use) | Check \"account × required operation\" against matrix before each issue — acting account uses `scopes=repo,read:org,workflow,gist,copilot,read:packages` prefill |\n\n### Merge permission ≠ push/comment/PR-create permission (es6kr/skills — HARD STOP)\n\n**`daegunjhy` can push, comment, and create PRs on `es6kr/skills`, but lacks `MergePullRequest` permission** — `gh pr merge` fails with `GraphQL: daegunjhy does not have the correct permissions to execute MergePullRequest (mergePullRequest)` even though every prior operation on the same PR succeeded under that account. `DrumRobot` (the canonical `es6kr` owner account) has merge rights. Before merging on `es6kr/skills`, switch: `GH_TOKEN=\"$(gh auth token --user DrumRobot)\" gh pr merge <N> -R es6kr/skills --merge` (or `gh auth switch --user DrumRobot` first). Don't assume the account that pushed/reviewed successfully also has merge rights — verify per-operation, not per-session.\n\n### Self-check (before any scope-modifying gh auth command)\n\n1. Is this an acting account (DrumRobot/daegunjhy)? → 6-scope set required\n2. Is this a special-purpose account? → purpose-minimum set only\n3. Is a browser PAT being issued? → All 6 scopes must be listed (PAT has no implicit scopes)\n4. Is this a `gh auth refresh`? → Use `-s repo,read:org,workflow,copilot,read:packages` (gist is already a gh OAuth default)\n5. Was `write:packages` needed? → Separate explicit issue (not included in canonical set)\n\nFile v0.11.3:merge.md\n\n# Merge\n\nPerform a final quality check on a PR (CI / Review), then merge and clean up the commit message according to the rules.\n\n## When to Use\n\n- On requests like \"merge the PR\", \"confirm reviews and merge\", \"merge if CI passed\"\n- When integrating a fully implemented and reviewed PR into the main branch\n- Whenever you want a final, pre-merge sanity check on CI success and AI-review actionable status\n\n## Merge condition checks (every condition must pass)\n\n**Even when supervising / reporting, check these first** — never ask \"shall we merge?\" on a PR that does not satisfy the conditions.\n\n### 1. CI success (real-time)\n\n```bash\ngh pr checks <PR_NUMBER>\n```\n- If any `fail`, stop. If `pending`, wait.\n- Required to be confirmed **in real time** — don't rely on a state recorded in fix_plan.\n\n#### CI rerun result verification (MANDATORY when `gh run rerun` / `gh workflow run` was invoked)\n\nAfter triggering CI (`gh run rerun <run-id> --failed`, `gh workflow run`, etc.) the **final result must be reported** — reporting only \"in_progress\" is forbidden.\n\nProcedure:\n1. Trigger: `gh run rerun <run-id> --failed` or `gh workflow run`\n2. Wait for completion: `gh run watch <run-id>` (or poll `gh run view --json status,conclusion` every 30s)\n3. Report SUCCESS/FAILURE; on failure, summarize the root cause\n\nIf the wait is expected to exceed 2 minutes, launch `gh run watch` with `run_in_background: true` and report on the completion notification.\n\n#### Post-CI followup decision table (MANDATORY after CI SUCCESS)\n\nAfter confirming CI success, run this table sequentially — do not stop at \"CI passed\".\n\n| Condition | Action | Command |\n|-----------|--------|---------|\n| CI SUCCESS | **Check whether the AI Review Summary comment is posted** | `gh pr view <N> --json comments` → search for the user-authored AI Review Summary comment |\n| AI Review Summary **missing** | **Run `/consolidate pr` FIRST** — consolidate precedes Test Plan verification, which only runs after consolidate completes | `Skill(\"consolidate\", \"pr\")` |\n| AI Review Summary **posted** (or consolidate-exempt PR) | Check the PR body Test Plan | `gh pr view <N> --json body` |\n| Test Plan has unchecked `- [ ]` items | Verify the unchecked items (deploy, Playwright, API call, etc.) → on pass, mark `- [x]` | `gh pr edit <N> --body` |\n| Test Plan fully `[x]` | Record CI success in `fix_plan.md` and check off the entry | Edit `fix_plan.md` |\n| Related issue exists | Check off the relevant items in the issue body checklist | `gh issue edit <N> --body` |\n| All complete | Move to the next pending item (fix_plan or TaskList) | — |\n\n**CI success ≠ work complete**: every Test Plan item checked + fix_plan reflected + issue body updated is the actual completion criterion.\n\n##### Direct-to-master projects (no PR) — fix_plan reflection still mandatory\n\nFor projects pushing directly to master (e.g., infra-provisioning repos), commit + push + CI success **still requires** `fix_plan.md` reflection.\n\n| Condition | Action |\n|-----------|--------|\n| commit + push + CI passed | Mark the relevant `fix_plan.md` item `[x]` or update its status |\n| Related TaskList entry exists | `TaskUpdate(status: \"completed\")` |\n| New infrastructure artifact (deploy, migration, etc.) | Record the result in `fix_plan.md` (commit SHA, environment, status) |\n\n| # | Don't | Do |\n|---|-------|-----|\n| 1 | Stop at \"commit + CI confirmed\" without updating `fix_plan.md` | Update the relevant `fix_plan.md` entry to `[x]` + `TaskUpdate completed` |\n| 2 | Assume \"no PR workflow, so no fix_plan update needed\" | Whether PR-based or master-push, `fix_plan` reflection is equally mandatory |\n\n### 2. AI Review Summary — every Actionable item addressed\n\n**Default procedure (HARD STOP — strict order)**:\n\n0. **Verify a real Copilot review error** (explicit error keywords only — beware of false positives):\n\n   ```bash\n   gh pr view <PR_NUMBER> --json reviews -q '.reviews[] | select(.author.login == \"copilot-pull-request-reviewer\") | select(.body | test(\"encountered an error|unable to review\"; \"i\")) | {state, bodyLen: (.body | length)}'\n   ```\n\n   - Result empty → proceed to Step 1 (a short body or the absence of a \"Reviewed changes\" section may still be a normal review on a simple PR — do NOT flag a false positive)\n   - Result matched → real error → re-request Copilot (`gh pr edit <PR_NUMBER> --add-reviewer copilot-pull-request-reviewer`) → wait for the normal review to arrive, then proceed to Step 1\n\n   **Forbidden**: declaring a partial failure just because the `Reviewed changes` section is missing or the bodyLen is short. Copilot does post short reviews to simple PRs (e.g. PR #110 merged, bodyLen 2040, inline comments only, no `Reviewed changes` section).\n\n1. **Check whether the AI Review Summary comment exists**:\n   ```bash\n   gh api repos/{owner}/{repo}/issues/<PR_NUMBER>/comments --jq '.[] | select(.body | startswith(\"## AI Review Summary\"))'\n   ```\n\n2. **No Summary comment → unconditionally auto-invoke `/consolidate pr`**:\n   - **Antigravity Unapproved PR clawo Delegation Gate (HARD STOP)**: In Antigravity (Gemini), directly executing `/consolidate pr` or remediating unapproved PRs in the main chat turn is strictly forbidden (`HARD STOP`). You MUST delegate unapproved PR review consolidation and remediation to `clawo` (`clawo session-send <session_name>` or `Skill(\"clawo\", \"launch\")`).\n   - **If any AI review (CodeRabbit / Copilot / etc.) is present, consolidate is the default** — not optional\n   - After consolidate, confirm the Summary comment was posted → continue to Step 3\n   - **Forbidden**: asking the user a merge / apply option without the Summary. consolidate must run first\n\n3. **Summary comment exists → count 🔴 Critical (HARD STOP)**:\n\n   ```bash\n   # Count 🔴 Critical entries in the Summary body.\n   # CROSS-PLATFORM (HARD STOP): NEVER `grep -c '🔴 Critical'` — Windows Git Bash emoji\n   # byte-matching returns false 0 (silent merge-gate bypass). Count inside jq (UTF-8 native):\n   gh api repos/{owner}/{repo}/issues/<PR_NUMBER>/comments \\\n     --jq '[.[] | select(.body | startswith(\"## AI Review Summary\")) | .body | [scan(\"🔴 Critical\")] | length] | add // 0'\n   ```\n\n   - **🔴 Critical ≥ 1 → merge is absolutely forbidden**. Address the Critical items in code, then refresh the Summary before merging. \"deferred\" is not allowed — Critical items must be addressed\n   - 🔴 Critical 0 + `Actionable > 0` not yet addressed → use AskUserQuestion to confirm the action (apply / deferred / skip)\n   - If everything is addressed or explicitly deferred, continue to Step 2.5\n\n**Forbidden patterns**:\n- ❌ AI review exists, but you bypass consolidate and ask the user to merge directly\n- ❌ Interpreting \"if no Summary, run consolidate\" as \"you can skip it\"\n- ❌ Looking only at CodeRabbit and missing the Copilot review (both must be consolidated)\n\n### 2.5. Verify deferred Actionable items are registered in a tracking medium (HARD STOP)\n\n**If ≥1 Actionable items are explicitly marked \"deferred\" on the Summary, before merging, verify they are registered as `[BLOCKED]` in a tracking medium.** If not registered, block the merge.\n\n#### Verification procedure\n\n1. **Identify deferred items**: count items decided as deferred on the Summary body (e.g. \"🟡 Minor (optional)\", \"🟡 Minor (No action)\", \"🔴 Critical not addressed\")\n2. **Verify tracking-medium registration** (per environment):\n\n   ```bash\n   # fix_plan tracker — workspace-relative path per fix-plan SKILL.md `task-tracker` config\n   # (e.g., Ralph wrappers place it at {workspace}/.ralph/fix_plan.md; vanilla workspaces use {workspace}/fix_plan.md)\n   # Note: the inner class uses an explicit set (`[A-Za-z0-9:]+`) instead of `[^]]+` —\n   # BSD grep (macOS) raises \"brackets ([ ]) not balanced\" on `[^]]`, so the explicit\n   # set is the portable form across GNU + BSD ERE.\n   grep -cE '\\[BLOCKED(:[A-Za-z0-9:]+)?\\].*\\[REVIEW_FEEDBACK\\].*PR #<N>' <fix_plan tracker path>\n\n   # checklist tracker (non-Ralph workspaces) — same BSD-portable class\n   grep -cE '\\[BLOCKED(:[A-Za-z0-9:]+)?\\].*PR #<N>' {workspace}/checklist.md\n\n   # GitHub Issue tracker\n   gh issue list --search \"deferred from PR #<N>\" --state open --json number\n   ```\n\n   The `[BLOCKED(:[^]]+)?\\]` pattern matches both the plain `[BLOCKED]` form and the priority-annotated `[BLOCKED:P0-P3:reason]` form (see fix-plan/priority.md).\n\n3. **Compare counts**: deferred-item count ≤ medium-registration count → proceed. deferred-item count > medium-registration count → block the merge\n\n#### Don't / Do\n\n| # | Don't | Do |\n|---|-------|-----|\n| 1 | Treat the \"deferred\" tag in the Summary table as registration | The Summary is a one-shot GitHub comment. Registration in a medium (fix_plan / checklist / Issue) must be verified separately |\n| 2 | Interpret \"if deferred is stated, merge is allowed\" as \"merge regardless of medium registration\" | Merge requires BOTH explicit deferred + medium registration |\n| 3 | On missing registration, ask the user \"shall I register?\" via options | `consolidate/post.md` Step 7.6 handles auto-registration. Missing = consolidate-procedure violation → re-invoke consolidate, then re-verify |\n| 4 | Treat a \"we'll register when the user picks merge\" promise as actual registration | A promise ≠ an action. Decide based on actual lines existing in the medium file |\n\n#### Self-check (every time, before merging)\n\n1. Is there ≥1 deferred Actionable item on the AI Review Summary?\n2. If yes, did you check medium-registration counts with grep / gh per environment?\n3. Did you confirm `deferred count = registered count`? (Block on mismatch)\n4. Did you include the registration medium path / Issue number in the merge decision report?\n\n### 3. Test Plan — per-category merge guard\n\nApply the PR-body Test Plan category classification rule (pr.md \"Test Plan category classification\" section) at merge time. Guards differ by category prefix (`[general]` / `[UI]` / `[post-merge]`).\n\n```bash\ngh pr view <PR_NUMBER> --json body\n# Or chain a project-local verification script:\ngh pr view <PR_NUMBER> --json body --jq '.body' | node scripts/check-test-plan.js\n```\n\n| Category prefix | Guard when unchecked |\n|-----------------|----------------------|\n| `[general]` | **Cannot merge** (HARD STOP, no exception) |\n| `[UI]` | **Cannot merge** (HARD STOP, no exception) |\n| `[e2e]` | If the suite runs on **PR CI** → the CI check is the guard (**cannot merge** until green). If **deploy-branch-only** → treated like `[post-merge]` (merge allowed; tracking required) |\n| `[post-merge]` / `[deploy]` | **Merge allowed** (but tracking-medium registration must be verified — procedure below) |\n| No prefix (legacy) | Treated as `[general]` or `[UI]` — **cannot merge** |\n\n#### `[post-merge]` items — verify tracking-medium registration (HARD STOP)\n\nIf ≥1 `[post-merge]` items exist, confirm they are registered in a tracking medium before merging:\n\n```bash\n# Extract [post-merge] items from the PR body\n# Category prefix output format is **[post-merge]** (bold bracket); tolerate legacy `[post-merge]` (backtick) too.\ngh pr view <PR_NUMBER> --json body --jq '.body' | grep -E '^- \\[.\\] (\\*\\*\\[post-merge\\]\\*\\*|`\\[post-merge\\]`)'\n\n# Verify each item names a tracking link (issue # or fix_plan path)\n# 0 items without a tracking link is required to merge\n```\n\n| # | Don't | Do |\n|---|-------|-----|\n| 1 | `[post-merge]` item without a tracking medium → post-merge verification gets dropped | Inline `(tracking: gh issue #N)` or `(tracking: fix_plan.md [BLOCKED])` in the item description before merging |\n| 2 | Misclassify essential validation as `[post-merge]` to bypass the merge guard | Apply the \"essential vs adjacent follow-up\" self-check — essential validation belongs to `[general]` / `[UI]` |\n\n#### Runtime-verification → PR-body sync (HARD STOP)\n\nAfter verifying a Test Plan item at runtime (API call, Playwright, `curl`, etc.), immediately mark the corresponding `- [ ]` in the **PR body** to `- [x]`. Checking only `fix_plan.md` is insufficient — the PR body is the primary tracking medium.\n\n| # | Don't | Do |\n|---|-------|-----|\n| 1 | Check off `fix_plan.md` `[x]` but skip updating the PR body | `fix_plan` `[x]` + `gh pr edit --body` so the PR body also shows `[x]` |\n| 2 | Conclude \"the PR is MERGED, so updating the body is pointless\" | A MERGED PR body can still be edited — record the verification trail for auditability |\n\n#### \"Check the Test Plan\" command handling (HARD STOP)\n\nWhen the user issues \"check the PR Test Plan\", \"verify tests\", \"check it for me\", etc., **all items must be re-run + results reported + then [x]/[ ] decided**. A simple grep that keeps existing `[x]` rows untouched and PATCHes only unchecked rows is a violation. Per-item workflow: **(a) execute → (b) report result → (c) decide [x]/[ ]**.\n\n##### Per-item handling\n\n| Item type | Execution medium | Treatment |\n|-----------|-----------------|-----------|\n| `pnpm test` / `pnpm check-types` / unit-test command | Run directly on the PR head commit (or a worktree) | Pass → `[x]` + result meta (e.g., \"313/313 PASS, YYYY-MM-DD\") / Fail → `[ ]` + reason |\n| `CI E2E` / `Playwright` / other CI-run items | Query latest CI run result (`gh run view <ID>`) | `conclusion=success` → `[x]` + run ID + date / unrun or failed → `[ ]` |\n| `curl <URL>` / `[runtime] <service> behavior` | Call directly (or via Playwright) | Verified response → `[x]` + response status + date / Fail → `[ ]` + response body |\n| `[post-merge]` / `[deploy]` prefix | Out of this cycle (separate post-merge cycle) | Keep `[ ]` + note \"out of this cycle — follow-up work\" |\n| **Existing `[x]` items (already checked)** | Re-run if visibility is in doubt (env drift, time passed) | Re-verified → keep `[x]` + add re-check meta / Re-fail → flip to `[ ]` + report |\n\n##### Don't / Do\n\n| # | Don't | Do |\n|---|-------|-----|\n| 1 | \"Already `[x]`, so skip\" — only PATCH the unchecked items | **Re-run every item**. After environment changes (drift, time), re-verification is the 1st-priority outcome |\n| 2 | PATCH PR-body Test Plan `[x]` based only on overall CI status | Map each Test Plan item to the specific CI job that verified it → state job conclusion + run ID + date |\n| 3 | Mark `[x]` from a code Read / `package.json` script inspection (\"it could run, so I declare pass\") | **Actually execute the command + capture output**. Reading code is not a verification medium |\n| 4 | One command (`pnpm --filter dt test`) produces N `[x]` marks at once | Map each Test Plan item to the command executed 1:1 in the report. Unmapped items stay `[ ]` |\n| 5 | Report only the unchecked items PATCHed; skip re-verifying existing `[x]` | Re-verify the existing `[x]` in this same cycle and report the result (add \"re-verified pass\" meta) |\n| 6 | Omit result meta (run ID / date / response status / N/M PASS) | Each `[x]` carries verification medium + result + date so future readers can trace \"when, by what, verified\" |\n\n##### Self-check (every time the user issues \"check Test Plan\")\n\n1. Enumerate **every** Test Plan item in the PR body (`[x]` and `[ ]`). Reporting only the unchecked rows is forbidden\n2. Identify each item's execution medium (match the table above)\n3. Re-run **every item** (including existing `[x]`). Map results 1:1 per item in the report\n4. After reporting, decide `[x]`/`[ ]` → `gh pr edit --body` or `gh api PATCH .../pulls/<N>` (multi-line bodies go via a JSON file per `git.md`)\n5. `[post-merge]` / `[deploy]` items: stay `[ ]` and note \"out of this cycle\"\n6. Summarize the report as \"Test Plan re-run: X/Y passing, Z out of cycle\"\n\n##### Exceptions\n\n- User explicitly says \"only the unchecked items\" / \"verify only the unchecked\" → skipping re-verification of existing `[x]` is allowed\n- Without an explicit instruction, default = re-run all\n\nLegacy PRs (Test Plan without category prefix): the existing HARD STOP applies — if even one `- [ ]` is unchecked, you cannot merge. For items not executable before merge, change to a tracking annotation like `- [x] (verify post-deploy — tracked in issue #N)` + AskUserQuestion approval (but NEVER use the tracking annotation to bypass essential validation).\n\nA PR with no Test Plan is unaffected by this condition.\n\n### 3.5. Blocked by — all predecessor issues CLOSED (HARD STOP)\n\nIf the issue this PR closes (or the PR itself) has GitHub Issue Dependencies (`blockedBy`) set, **every predecessor issue must be CLOSED** to merge. See [dependencies.md](./dependencies.md) for details.\n\n```bash\n# Extract issues the PR closes (Closes/Fixes keywords + linked issues)\ngh pr view <PR_NUMBER> --json closingIssuesReferences -q '.closingIssuesReferences[].number'\n\n# For each soon-to-close issue, query blockedBy\nGH_TOKEN=\"$(gh auth token --user <account>)\" gh api graphql -f query='\n  query { repository(owner:\"<owner>\", name:\"<repo>\") {\n    issue(number:<N>) {\n      blockedBy(first:10) { nodes { number state title } }\n      issueDependenciesSummary { totalBlockedBy }\n    }\n  } }\n'\n```\n\n**Decision rule**:\n\n| `blockedBy` node state | Action |\n|------------------------|--------|\n| All `CLOSED` | OK — can merge |\n| ≥1 `OPEN` | **Cannot merge** — report the OPEN predecessor's number + title, ask via AskUserQuestion (e.g. \"predecessor issue #N is unresolved. How shall we proceed?\") |\n| `blockedBy` empty | OK — no dependencies |\n\n**Forbidden patterns**:\n- ❌ Merging on your own judgment \"it's unrelated\" when `blockedBy` has an OPEN issue\n- ❌ Force-closing the predecessor at the last minute then merging (actual work incomplete)\n\n**If the predecessor will soon be closed by another PR**: re-order so this PR merges after that PR. Use AskUserQuestion to get the user's decision.\n\n#### Distinguish PR essential validation vs adjacent follow-up validation (HARD STOP)\n\nWhen marking an unchecked Test Plan item as `[x] (post-merge verification — tracked separately)`, **always self-check the essential vs adjacent classification**. Do not use the tracking annotation to bypass essential validation.\n\n**Classification rule**:\n\n| Class | Definition | Handling |\n|-------|------------|----------|\n| **PR essential validation** | The goal stated in the PR title / body. This validation must SUCCEED for the PR to truly solve the problem | **Must verify before or immediately after merge.** Tracking annotation `[x]` is forbidden |\n| Adjacent follow-up | A byproduct of the PR change. Environment impact, regression monitoring, etc. | Tracking annotation `[x]` is allowed |\n\n**Self-check procedure (right before marking a Test Plan item as `[x]` tracking)**:\n1. Extract the PR's core goal in one sentence (\"the essence of this PR is solving X\")\n2. Determine whether the unchecked item is a direct verification of X:\n   - \"X workflow SUCCESS check\" / \"X behavior verified\" / \"X passed\" → **essential validation**\n   - \"environment impact monitoring\" / \"regression tracking\" / \"follow-up PR work\" → adjacent follow-up\n3. If essential → do NOT mark `[x]`. Consider triggers that can be executed before or immediately after merge:\n   - manual `workflow_dispatch`\n   - cross-repo trigger (e.g. PAT-authenticated `repository_dispatch`)\n   - real user-scenario reproduction (curl, Playwright)\n4. If no immediately-executable trigger → **do not merge**. Use AskUserQuestion only to decide \"how to verify\". Merging while unchecked is absolutely forbidden\n\n**Correct flow** (essential validation):\n1. If the unchecked item is essential → attempt a trigger before merge (e.g. manual workflow_dispatch + watch, infra dry-run, curl)\n2. After SUCCESS, check `[x]` → merge\n3. If a trigger is impossible → **do not merge**. Decide a verification approach with the user, execute it, check `[x]`, then merge\n\n**Absolutely forbidden (2nd recurrence — HARD STOP strengthened)**:\n- The \"merge with unchecked items after user consent\" path is closed. Even if the user says \"go ahead\", do not run `gh pr merge` while any `- [ ]` remains\n- \"Record and proceed\" = \"record this fact\" + \"proceed to the next step (verification / deploy)\", NOT \"approval to merge unchecked\"\n\n#### HARD STOP — Self-check for the merge-option AskUserQuestion (six conditions)\n\nBefore recommending merge (AskUserQuestion option includes \"proceed merge\" / \"squash merge\"), **self-check all six conditions**:\n\n| # | Condition | How to verify | If not satisfied |\n|---|-----------|---------------|------------------|\n| 1 | All CI PASS | `gh pr checks <N>` → confirm bucket=pass | Exclude \"merge\" from options |\n| 2 | All Test Plan `[x]` | `gh pr view <N> --json body --jq '.body' \\| node scripts/check-test-plan.js` → exit 0 | Exclude \"merge\" from options |\n| 3 | AI Review Summary comment posted | `gh pr view <N> --json comments` → confirm a user-authored \"AI Review Summary\" body | consolidate invocation required |\n| 4 | Mergeable | `gh pr view <N> --json mergeable` → MERGEABLE | Resolve conflicts first |\n| 5 | Cross-repo infrastructure dependency | Inspect PR body / code for cross-repo env-var or infrastructure changes | Block merge until the dependent repo's change is merged + deployed |\n| 6 | Merge method matches repo policy | Run the \"Merge-method policy pre-check\" above (`viewerDefaultMergeMethod` / `.release-please-manifest.json` / `.changeset/`) | If the repo signals merge-commit policy, the option must use `--merge`, never `--squash` — do not default to squash just because it satisfies conditions 1-5 |\n\n**Condition 5 in detail — cross-repo dependency (HARD STOP)**:\n- The code references a new env var (`process.env.X`, `lookup('env', 'X')`) that is supplied by an infra repo's inventory / template\n- **The infra-repo PR must be merged + deployed first** before the app code can merge\n- Order: infra variable-addition PR merged → infra deploy → app code PR merged → app deploy\n- **Forbidden**: merging the app code first and deferring the infra as a \"follow-up PR\" — at deploy time the missing env var breaks the feature\n\n**Exception — base branch's ROLE is a CI gate, not a review gate**: what matters is *why* the base branch exists, not its literal name. Some long-lived branches (e.g. `next-feat`/`next-fix` in a two-tier staging model) exist purely to accumulate CI-passing commits ahead of a later, separately-reviewed promotion PR (staging → main) — for that role, condition 3 (AI Review Summary) does not apply to PRs merging INTO it. Don't pattern-match on branch name; verify the role: `gh pr checks <N>` reporting `Review skipped: reviews are disabled for this base branch` is the actual signal that this base is a CI-gate-only branch, regardless of what it's called. Do not wait for a walkthrough that will never arrive, and do not run `/consolidate pr` for it. Conditions 1 (CI), 2 (Test Plan), 4 (Mergeable) still apply in full; the real review gate for that commit happens later, at the promotion PR into the branch that IS reviewed.\n\n| # | Don't | Do |\n|---|-------|-----|\n| 1 | Assume the exception applies because the base branch is literally named `next-feat`/`next-fix` | Verify the branch's actual role via `gh pr checks <N>` — the CodeRabbit-disabled signal, not the name, is what confirms this is a CI-gate-only base |\n| 2 | Treat a CI-gate-only base's missing AI Review Summary as \"waiting for CodeRabbit\" and leave it pending indefinitely | `Review skipped: reviews are disabled for this base branch` means condition 3 is structurally exempt for this base's role, not unmet |\n| 3 | Run `/consolidate pr` on a PR into a CI-gate-only base because a review artifact \"should\" exist | Skip consolidate for this base — CI green + Test Plan + Mergeable is the full gate; review happens at the later promotion PR |\n\n**If even one condition is unsatisfied, ALL of the following are forbidden**:\n- Including \"proceed merge\" / \"squash merge\" / \"merge recommended\" in AskUserQuestion options\n- Bypassing unsatisfied conditions with phrases like \"Playwright will run separately\", \"ZAP will follow\", while still recommending merge\n- Concluding \"the core passed, so merge is fine\" on your own judgment\n- Concluding \"AI bot comments exist, so OK\" on your own (the consolidate Summary is separate)\n\n#### CI fail — analyze the essence + state the merge value (HARD STOP)\n\nBefore recommending merge on a PR with CI fails, **state both**:\n\n1. **Essence analysis of each CI fail (self-check per fail entry)**:\n   - **Is the fail resolved by this PR?** → if so, wait until it passes, then merge\n   - **Is the fail unrelated to this PR?** → register a separate issue + name the issue in the PR body + guarantee the fail is not permanently masked by this PR\n   - **Is the fail intentional `continue-on-error`?** → record the GUARD reason in the PR body + name a separate tracking issue\n\n2. **Merge value (diff with merging vs not merging)**:\n   - What changes between pre-merge and post-merge? (code coherence, regression prevention, unblocking subsequent work — concretely)\n   - If merging is not strictly required, deferral may be a better option — if the value is unclear, offer a defer option\n\n**Forbidden pattern** (no statement of \"what got better\" from the user's POV):\n- ❌ 2 CI fails → \"continue-on-error / tracked separately\" → recommend merge. No value statement\n- ❌ Abstract phrasing like \"merging restores env coherence with the master fixture\". State concrete changes\n- ❌ Treating fails as \"deferred\" without a separate tracking issue and merging — tracking lost\n\n**Correct flow** (PR with CI fails):\n1. Report the essence-analysis result text per fail\n2. On detecting \"fails this PR does not resolve\" → **prefer reusing an existing tracking issue** (Step 2-A) → if none, register a new issue (Step 2-B)\n3. State the merge value in one line (concrete): \"Merging makes the master fixture use `service-A-source` → prevents regressions in the next PR + guarantees coherence at dev-A/integration/production rollout\"\n4. Then issue AskUserQuestion or auto-merge\n\n**Step 2-A: prefer reusing an existing issue (HARD STOP)**\n\nBefore suggesting a new issue, search:\n\n```bash\n# 1. PR trigger issue (look at Resolves / Relates to / Closes keywords in the PR body)\ngh pr view <PR> --json body -q '.body' | grep -iE 'Resolves|Relates to|Closes|Fixes' | head\n\n# 2. Open issues with the same label / area\ngh issue list -R <owner>/<repo> --state open --label <label> --json number,title\n\n# 3. Existing issues by fail keyword\ngh search issues \"<fail keyword>\" --repo <owner>/<repo> --state open\n```\n\n**Decision**:\n- If a trigger issue exists and the fail falls in its scope → **add the unresolved item to the trigger-issue body** (do not close; reopen or leave as-is)\n- If an open issue in the same area is found → **add the fail item to that issue body**\n- If no search hits → register a new issue (Step 2-B)\n\n**Forbidden pattern**:\n- ❌ Suggesting a new issue without checking the trigger issue. The same environment inconsistency ends up split across issues with fragmented tracking\n- ❌ When `Resolves #N` is stated in the PR, suggesting a new issue after solving only part of it → adding the unresolved item to `#N`'s body is the canonical fix\n\n**Step 2-B: register a new issue (only when no existing issue applies)**\n\nUse `/github-flow plan-to-issue` or `gh issue create`.\n\n**Correct flow** (on any unsatisfied condition):\n1. Test Plan unchecked → run verification directly → check `[x]`\n2. AI Review Summary missing → invoke the consolidate skill → Summary posted → actionable addressed\n3. CI failure → root-cause analysis + fix\n4. Conflicts → resolve conflicts\n5. Only after all four are satisfied may you offer a merge option. Merge only when the user explicitly says \"merge now\" (auto-recommendation is forbidden)\n\n#### Pre-approved context — skip AskUserQuestion (auto-merge)\n\nWhen all four merge conditions are satisfied AND **the user pre-approved a workflow that includes merging**, skip AskUserQuestion and run squash merge immediately. Asking again is redundant and delays progress.\n\n**Pre-approval patterns** (the user's answer / instruction contains expressions like):\n- \"wait for the predecessor PR to merge\" / \"proceed after the PR merges\" / \"next step after merge\"\n- \"merge if conditions are satisfied\" / \"merge once CI passes\" / \"squash once it passes\"\n- \"handle the preliminary work\" + the workflow includes a merge step\n- \"run it through to the end\" / \"do it all in one go\" + the workflow is named\n\n**❌ Non-pre-approval patterns (HARD STOP — do not auto-recommend the merge option)**:\n\nThe following expressions mean \"inspect / review / check\" — NOT permission to merge. Even if a merge keyword appears in the option description, auto-recommending merge is a violation:\n\n- \"review merge conditions\" / \"check merge conditions\"\n- \"see if mergeable\" / \"look into whether it can merge\"\n- \"inspect conditions\" / \"review\" / \"check\" / \"inspect\" (when used alone)\n- A merge word in the option description, when the verb is \"review / check / inspect / look\", is not approval\n- The user must add an explicit **action verb** like \"then merge\" / \"merge once it passes\" / \"proceed when conditions hold\"\n\n**Decision rule (option self-check)**:\n\n| User answer / option phrasing | Intent | Auto-recommend the merge option |\n|-------------------------------|--------|---------------------------------|\n| \"merge if conditions are satisfied\" | Approval (conditional action) | ✅ auto-merge or recommend the option |\n| \"merge after CI passes\" | Approval | ✅ |\n| \"review merge conditions\" | Non-approval (inspect) | ❌ exclude merge from options; offer \"report conditions only\" |\n| \"check if mergeable\" | Non-approval (inspect) | ❌ |\n| \"inspect conditions\" | Non-approval (inspect) | ❌ |\n| \"run it through to the end\" + workflow names merge | Approval | ✅ |\n\n**Correct flow** (non-approval pattern + conditions satisfied):\n1. Report the six-condition self-check result as text (\"CI ✅, AI Review ✅, Test Plan ✅, Mergeable ✅, Cross-repo dependency ✅, Merge-method policy ✅\")\n2. Use AskUserQuestion to **confirm merge intent separately** — \"All conditions satisfied. Proceed with merge?\" (options: \"merge now\" / \"defer\" / \"additional review\")\n3. Run `gh pr merge --squash` only when the user picks \"merge now\"\n\n**Auto-merge procedure**:\n1. Self-check the six conditions (CI / Test Plan / AI Review Summary / Mergeable / Cross-repo dependency / Merge-method policy)\n2. If all satisfied → skip AskUserQuestion, run `gh pr merge --squash`\n3. If any unsatisfied → AskUserQuestion explaining the blocker + suggesting how to clear it (independent of pre-approval)\n\n**Exception — AI Review Summary structurally exempt (CI-gate-only staging base) (HARD STOP)**: \"skip AskUserQuestion\" in step 2 assumes the AI Review Summary already gave the user visibility into the actual diff before this point. When condition 3 is exempt because the base is CI-gate-only (staging branch, e.g. `next-fix`/`next-feat` — see the CI-gate-only exception above), that visibility never happened, and an explicit merge command + the remaining 5 conditions is not the same thing as the user having seen the content. In this case, do NOT skip AskUserQuestion — present a final content-review ask (the PR URL + a one-line summary of the change) before running `gh pr merge`, even though the user already gave an explicit merge instruction. This is not re-confirming *intent to merge* (already given) — it's the only remaining chance for the user to catch something they'd reject (e.g. a wrongly-scoped skill topic) before an irreversible squash.\n\n**Self-check (before skipping AskUserQuestion in the auto-merge procedure)**: is AI Review Summary satisfied because it was actually posted, or because it's structurally exempt (staging base)? If exempt → this exception applies, ask before merging regardless of pre-approval wording.\n\n**Forbidden patterns**:\n- \"Wait for the predecessor PR to merge\" answer → after the PR is created + six conditions satisfied → asking \"shall I merge?\" again (redundant)\n- Mis-interpreting a pre-approval answer as \"inspect intent\" instead of \"merge intent\"\n\n### 4. Mergeable status\n\n```bash\ngh pr view <PR_NUMBER> --json mergeable\n```\n- If `CONFLICTING`, resolve conflicts first.\n\n**Empty-PR guard (HARD STOP)**: before `gh pr ready` or `gh pr merge`, also confirm the PR actually has content — `gh pr view <PR_NUMBER> --json commits,additions,deletions,changedFiles`. A PR created via a non-standard path (cross-repo/temp-fork source, a GraphQL `createPullRequest` workaround after the standard `gh pr create` shorthand failed) can register with `commits: []` even though `gh pr diff --name-only` still prints file names — that command reflects a diff computation, not the PR's own registered commit range, and is not proof of content. `mergeable` staying `UNKNOWN`/`null` for an unusually long time after creation is a signal to check this before assuming it's just slow to compute.\n\n### Per-repository Formal Review policy\n\n| Repository profile | Self-approve | Formal Review |\n|--------------------|--------------|---------------|\n| Org-protected app repo | Not allowed | **Skip** — replaced by CI + AI Review + Test Plan |\n| Solo-maintained infra repo | Allowed (solo) | Replaced by AI Review APPROVE |\n\n- For an org-protected app repository where self-approve is not allowed, the formal-review condition is skipped.\n- If all six conditions above pass, the PR can be merged.\n\n## Merge Execution\n\n### Merge-method policy pre-check (HARD STOP — before proposing a merge method)\n\nSquash is the default recommendation below, but some repos treat **merge-commit as policy, not squash** — most notably **release-please / changesets** repos. release-please parses the individual Conventional Commits landed on the default branch, and changesets relies on the per-commit changeset files; squashing collapses that history and breaks the release tooling. Before offering a merge method (or building an AskUserQuestion merge option), confirm the repo's allowed/default method:\n\n```bash\ngh api graphql -f query='{repository(owner:\"<owner>\",name:\"<repo>\"){viewerDefaultMergeMethod mergeCommitAllowed squashMergeAllowed}}'\n# viewerDefaultMergeMethod = the configured default; mergeCommitAllowed/squashMergeAllowed = the reliable allowed-method booleans (fallback when the default field is unavailable).\n```\n\nSignal that merge-commit is the policy: a release-please manifest/config in the repo root (`.release-please-manifest.json`, `release-please-config.json`) or a `.changeset/` directory. When present, propose `--merge` (below), not `--squash`.\n\n**This pre-check is condition 6 of the \"Self-check for the merge-option AskUserQuestion\" gate below, not a separate optional step.** Composing a squash-merge option after satisfying only CI/Test Plan/AI Review Summary/Mergeable (conditions 1-4) without re-running this check is a HARD STOP violation — a release-please/changesets repo with a multi-commit PR against an accumulation branch needs `--merge` even when the other four conditions all look green.\n\n#### Skills and Plugins Repositories Squash Prohibition Gate (HARD STOP)\n\nIn repositories managing skills or plugins (e.g. `es6kr/skills`, `es6kr/claude-plugins`):\n- **Squash Merge Recommendation Prohibited**: Recommending or executing a squash merge (`gh pr merge --squash`) is strictly prohibited (`HARD STOP`) because release automation (`semantic-release` / changelog generators) parses individual Conventional Commits across packages to determine package release versions and changelog entries. Squashing collapses distinct package-level commits into a single commit, corrupting release tags and changelog generation.\n- **Strict Exception (1 Real Commit)**: A PR containing **exactly 1 real commit** excluding merge commits (`git log --no-merges ... | wc -l == 1`). If and only if there is a single real commit, squash merge may be recommended/used.\n- **Multi-Commit PRs (`real_commits >= 2`)**: The agent MUST recommend and execute **`Merge commit` (`gh pr merge <N> --merge`)** to preserve granular Conventional Commit history.\n\n### Commit-count / distinctness gate (HARD STOP — before defaulting to squash)\n\n**\"Squash Merge (recommended)\" below is the default only for PRs whose commits are not independently meaningful.** A PR with 3+ commits spanning genuinely distinct concerns (e.g. separate hook registrations, separate bug fixes bundled together, separate feature slices) loses that per-concern traceability when squashed — the option description must disclose this trade-off, not silently default to squash.\n\n**Concrete operational cost, not just traceability**: in a workspace running multiple concurrent worktree branches against the same target branch (a common pattern here), squashing collapses commits that other in-flight branches may already share as ancestors — those branches then hit avoidable conflicts the next time they rebase onto the target, because the target's history no longer contains the individual commit objects they diverged from. `--merge` (preserving the original commits) avoids this. This is a second, independent reason (beyond traceability) to route distinct-concern multi-commit PRs to `--merge`.\n\n**The PR's OWN source branch is the certain case, not the probabilistic one (HARD STOP)**: the paragraph above points outward, at *sibling* branches that may or may not share the commits. The branch this PR is merged **from** always holds them — and in a worktree workflow it is still checked out, still on those exact commits, after the squash lands a single unrelated commit on the target. Checking siblings and calling the local-history risk assessed is the exact gap this rule closes: the rare case gets inspected while the guaranteed one goes unexamined.\n\nSquash-merging while that branch survives locally leaves two histories for the same change with no common commit. The next rebase or merge of that worktree replays all N commits onto a target that already contains their squashed equivalent — conflicts on every hunk, and the branch cannot be fast-forwarded away, so it has to be force-reset or deleted by hand later, from a state the operator no longer remembers.\n\n**Therefore: before offering `Squash merge` as an option at all, verify the source branch's local state and its cleanability.**\n\n```bash\nR=<repo-path>; B=<pr-head-branch>\ngit -C \"$R\" rev-parse --verify --quiet \"$B\" >/dev/null && echo \"branch present locally\"\ngit -C \"$R\" worktree list | grep -F \"[$B]\"          # is a worktree pinned to it?\nW=$(git -C \"$R\" worktree list --porcelain | grep -B2 \"branch refs/heads/$B\" | sed -n 's/^worktree //p')\n# Cleanability — all three must be empty for the branch to be safely removable after merge\ngit -C \"${W:-$R}\" status --porcelain                 # uncommitted work\ngit -C \"${W:-$R}\" stash list                         # stashed work\ngit -C \"${W:-$R}\" log @{u}..HEAD --oneline           # commits not on the remote\n```\n\n| Source-branch state | Squash allowed? |\n|---------------------|-----------------|\n| Branch absent locally (already deleted) | Yes — no residue to diverge |\n| Branch present, **cleanable** (no uncommitted / stashed / unpushed work) | Yes, **only if** the post-merge branch deletion is stated in the merge ask and actually carried out |\n| Branch present with uncommitted, stashed, or unpushed work | **No — squash forbidden.** Either preserve history with `--merge`, or surface the residue to the user and let them decide what to salvage first. Never delete or reset a branch holding unpushed work to make squash viable |\n\nReport the state in the merge ask itself, so the user weighs a fact rather than an assumption.\n\n**Sibling stale-worktree sweep (repo-wide, HARD STOP — 2nd recurrence 2026-09-13)**: the residue check above only covers the PR's *own* source branch. Before finalizing the merge ask, also run `git worktree list` for the repo and check every OTHER branch it points at — not just the one being merged:\n\n```bash\ngit -C \"$R\" worktree list --porcelain | awk '/^branch /{print $2}' | sed 's#refs/heads/##' | while read -r b; do\n  [ \"$b\" = \"$B\" ] && continue   # skip the PR's own branch — already checked above\n  merged=$(gh pr list -R <owner>/<repo> --head \"$b\" --state merged --json number -q '.[0].number')\n  ahead=$(git -C \"$R\" log origin/<base>..\"$b\" --oneline | wc -l)\n  echo \"$b: merged_pr=${merged:-none} ahead_of_base=$ahead\"\ndone\n```\n\nA sibling branch is a stale-worktree candidate when `merged_pr` is set (its PR already landed) **or** `ahead_of_base` is 0 (its commits are already contained in the base, whether via this branch or a differently-named duplicate). Report any hits alongside the merge ask — as a *separate* cleanup/reuse callout, not folded into the current PR's own residue verdict — rather than silently leaving them for a future session to rediscover.\n\n| # | Don't | Do |\n|---|-------|-----|\n| 1 | Check the PR's own source branch, conclude the residue check is done, and stop | Also sweep every other worktree the repo holds — the PR's branch being clean says nothing about siblings left over from already-merged PRs |\n| 2 | Treat a stale sibling as out of scope because \"it's not this PR's branch\" | Surface it in the same report; per `git-repo` worktree-reuse conventions its resolution (reclaim/rename/leave) is a separate but adjacent decision the user should see now, not after another session re-discovers it |\n\n| # | Don't | Do |\n|---|-------|-----|\n| 1 | Recommend \"Squash merge\" without stating the commit count in the option description | Query `gh api --paginate repos/{owner}/{repo}/pulls/<N>/commits \\| jq -s 'add \\| length'` before composing the option — the bare (non-paginated) form silently caps at the API's default page size (30), undercounting larger PRs; `--paginate` alone still applies `--jq` per page rather than aggregating, so slurp+combine with an external `jq -s`. State the count (e.g. \"6 commits\") in the description regardless of which method is recommended |\n| 2 | Treat \"3+ commits\" as automatically requiring `--merge` | Commit count alone is not the trigger — count *distinct concerns* among the commits (different files/subsystems touched, different one-line summaries). 5 commits from one incremental refactor still squash cleanly; 3 commits fixing 3 unrelated bugs do not |\n| 3 | Present only \"Squash merge (Recommended)\" as an option when commit count ≥ 3 and concerns are distinct | Present both `Squash merge` and `Merge commit (preserve history)` as co-equal options **only when repository policy permits both** — let the user weigh the trade-off, do not silently pick one |\n| 4 | Bury the commit list in a follow-up message after the user asks for it | Include the commit SHA + one-line summary list directly in the option description (or the question text) the first time a multi-commit PR's merge is proposed |\n| 5 | State only a commit **count** (\"1 commit\", \"3 commits\") without listing the actual commit(s) — even for a single-commit PR | Always show the commit SHA + one-line summary for every commit being merged, regardless of count. A bare count is an unverifiable assertion; the list lets the user check it themselves instead of having to ask |\n| 6 | Check whether *sibling* branches share the commits as ancestors, get \"no\", and treat the local-history risk as assessed | Siblings are the probabilistic case; the PR's own source branch is the certain one. Run the source-branch residue check above **as well** — a clean sibling report says nothing about the branch being merged from |\n| 7 | Offer `Squash merge` for a PR whose source branch still holds uncommitted, stashed, or unpushed work | That state makes squash unsafe — the branch cannot be cleaned up afterwards without losing work. Offer `--merge`, or surface the residue and let the user salvage it first |\n| 8 | Delete or force-reset the source branch on your own to make squash viable | Branch deletion after merge is fine when the branch is already clean **and** the ask said so. Destroying unpushed work to unblock a merge method is not a cleanup step |\n\n**Policy-required exception (release-please / changesets repos)**: when the merge-method policy pre-check above (condition 6) signals that individual commits must be preserved, `Squash merge` is not a valid co-equal option for that PR — squashing collapses the Conventional Commit history release-please/changesets parses per-commit, breaking their version-bump detection. Present `Merge commit (preserve history)` as the only method, still disclosing the commit count and per-commit summaries so the user can verify the list, but do not offer squash as a choice to weigh.\n\n**Why disclosure isn't just a 3+-commit rule**: the count-only pattern above reads as scoped to the distinctness trigger (3+ commits), but the underlying reason — don't make the user trust an assertion they can't independently verify — applies to every merge ask, including 1-commit ones. A miscounted or mischaracterized single commit is just as much a trust problem as an undisclosed multi-commit bundle.\n\n**Self-check (before composing ANY merge-recommendation option, in addition to the six-condition gate)**:\n1. Run the commit-count query above. Is it ≥ 3?\n2. If yes, do the commits span distinct concerns (different subsystems/files/one-line summaries)? — if unclear, list them and let the user judge, don't decide unilaterally\n3. Does the option set include the actual commit SHA + one-line summary list (not just a count), and — when count ≥ 3 with distinct concerns — both squash and merge-commit as\n\nArchive v0.11.2: 26 files, 125065 bytes\n\nFiles: account-switch-merge.md (2649b), auth-scope.md (9434b), CHANGELOG.md (16364b), commit-message-discipline.md (8498b), dependencies.md (16295b), epic-bundle.md (8757b), expand.md (6107b), identity-auth.md (13460b), LICENSE (1063b), merge.md (61071b), plan-to-issue.md (15088b), pr.md (57777b), publish.md (3623b), push-guards.md (17493b), register.md (7524b), resources/block-pr-url-gate.sh (9860b), review-apply.md (7785b), review.md (3178b), sanitize.md (18839b), scripts/check-test-plan.js (3839b), scripts/gh-as.sh (708b), scripts/review-as.sh (2289b), skill-card.md (2763b), SKILL.md (8663b), upstream-issue.md (5551b), _meta.json (131b)\n\nArchive v0.11.1: 26 files, 124443 bytes\n\nFiles: account-switch-merge.md (2649b), auth-scope.md (7691b), CHANGELOG.md (15911b), commit-message-discipline.md (8498b), dependencies.md (16295b), epic-bundle.md (8757b), expand.md (6107b), identity-auth.md (13460b), LICENSE (1063b), merge.md (61071b), plan-to-issue.md (15088b), pr.md (57777b), publish.md (3623b), push-guards.md (17493b), register.md (7524b), resources/block-pr-url-gate.sh (9860b), review-apply.md (7785b), review.md (3178b), sanitize.md (18839b), scripts/check-test-plan.js (3839b), scripts/gh-as.sh (708b), scripts/review-as.sh (2289b), skill-card.md (3133b), SKILL.md (8663b), upstream-issue.md (5551b), _meta.json (131b)\n\nArchive v0.11.0: 26 files, 123495 bytes\n\nFiles: account-switch-merge.md (2649b), auth-scope.md (6687b), CHANGELOG.md (15608b), commit-message-discipline.md (8498b), dependencies.md (16295b), epic-bundle.md (8757b), expand.md (6107b), identity-auth.md (13460b), LICENSE (1063b), merge.md (61071b), plan-to-issue.md (15088b), pr.md (57777b), publish.md (3623b), push-guards.md (17493b), register.md (7524b), resources/block-pr-url-gate.sh (9860b), review-apply.md (7785b), review.md (3178b), sanitize.md (18839b), scripts/check-test-plan.js (3839b), scripts/gh-as.sh (708b), scripts/review-as.sh (2289b), skill-card.md (2116b), SKILL.md (8663b), upstream-issue.md (5551b), _meta.json (131b)\n\nArchive v0.10.2: 26 files, 122883 bytes\n\nFiles: account-switch-merge.md (2649b), auth-scope.md (6687b), CHANGELOG.md (14876b), commit-message-discipline.md (8498b), dependencies.md (16295b), epic-bundle.md (8757b), expand.md (6107b), identity-auth.md (13460b), LICENSE (1063b), merge.md (60035b), plan-to-issue.md (15088b), pr.md (57777b), publish.md (3623b), push-guards.md (17493b), register.md (7524b), resources/block-pr-url-gate.sh (9860b), review-apply.md (7785b), review.md (3178b), sanitize.md (18839b), scripts/check-test-plan.js (3839b), scripts/gh-as.sh (708b), scripts/review-as.sh (2289b), skill-card.md (2143b), SKILL.md (8663b), upstream-issue.md (5551b), _meta.json (131b)\n\nArchive v0.10.1: 26 files, 122296 bytes\n\nFiles: account-switch-merge.md (2649b), auth-scope.md (6687b), CHANGELOG.md (14563b), commit-message-discipline.md (8498b), dependencies.md (16295b), epic-bundle.md (8757b), expand.md (6107b), identity-auth.md (13460b), LICENSE (1063b), merge.md (59192b), plan-to-issue.md (15088b), pr.md (57104b), publish.md (3683b), push-guards.md (17493b), register.md (7524b), resources/block-pr-url-gate.sh (9860b), review-apply.md (7785b), review.md (3178b), sanitize.md (18839b), scripts/check-test-plan.js (3839b), scripts/gh-as.sh (708b), scripts/review-as.sh (2289b), skill-card.md (2457b), SKILL.md (8663b), upstream-issue.md (5551b), _meta.json (131b)\n\nArchive v0.10.0: 26 files, 121843 bytes\n\nFiles: account-switch-merge.md (2649b), auth-scope.md (6687b), CHANGELOG.md (14071b), commit-message-discipline.md (8498b), dependencies.md (16295b), epic-bundle.md (8757b), expand.md (6107b), identity-auth.md (13460b), LICENSE (1063b), merge.md (59192b), plan-to-issue.md (15088b), pr.md (55802b), publish.md (3683b), push-guards.md (17493b), register.md (7524b), resources/block-pr-url-gate.sh (9860b), review-apply.md (7785b), review.md (3178b), sanitize.md (18839b), scripts/check-test-plan.js (3839b), scripts/gh-as.sh (708b), scripts/review-as.sh (2289b), skill-card.md (2834b), SKILL.md (8663b), upstream-issue.md (5551b), _meta.json (131b)\n\nArchive v0.9.1: 26 files, 118492 bytes\n\nFiles: account-switch-merge.md (2649b), auth-scope.md (6687b), CHANGELOG.md (12261b), commit-message-discipline.md (8498b), dependencies.md (16295b), epic-bundle.md (8757b), expand.md (6107b), identity-auth.md (13460b), LICENSE (1063b), merge.md (58553b), plan-to-issue.md (15088b), pr.md (55802b), publish.md (3512b), push-guards.md (17493b), register.md (7524b), resources/block-pr-url-gate.sh (4294b), review-apply.md (7785b), review.md (3178b), sanitize.md (18839b), scripts/check-test-plan.js (3839b), scripts/gh-as.sh (708b), scripts/review-as.sh (2289b), skill-card.md (2631b), SKILL.md (8663b), upstream-issue.md (5551b), _meta.json (130b)\n\nArchive v0.9.0: 25 files, 116373 bytes\n\nFiles: account-switch-merge.md (2649b), auth-scope.md (6687b), CHANGELOG.md (11286b), commit-message-discipline.md (8498b), dependencies.md (16295b), epic-bundle.md (8757b), expand.md (6107b), identity-auth.md (13460b), LICENSE (1063b), merge.md (58183b), plan-to-issue.md (15088b), pr.md (55802b), publish.md (3512b), push-guards.md (17493b), register.md (7524b), review-apply.md (7785b), review.md (3178b), sanitize.md (18839b), scripts/check-test-plan.js (3839b), scripts/gh-as.sh (708b), scripts/review-as.sh (2289b), skill-card.md (3056b), SKILL.md (8616b), upstream-issue.md (5551b), _meta.json (130b)\n\nArchive v0.8.3: 24 files, 112314 bytes\n\nFiles: auth-scope.md (6687b), CHANGELOG.md (10973b), commit-message-discipline.md (8498b), dependencies.md (16295b), epic-bundle.md (8757b), expand.md (6107b), identity-auth.md (13460b), LICENSE (1063b), merge.md (53324b), plan-to-issue.md (15088b), pr.md (53905b), publish.md (3512b), push-guards.md (17493b), register.md (7524b), review-apply.md (7785b), review.md (3178b), sanitize.md (18839b), scripts/check-test-plan.js (3839b), scripts/gh-as.sh (708b), scripts/review-as.sh (2289b), skill-card.md (2934b), SKILL.md (8616b), upstream-issue.md (5551b), _meta.json (130b)","readmeExcerpt":"Skill: github-flow Owner: drumrobot Summary: GitHub issue/PR workflow automation. Topics — auth-scope (gh CLI priority + account mapping + batch scope refresh + 404 checklist), commit-message-discipline (commit message authoring + amend refresh + PUBLIC English enforcement), dependencies (blocked-by/sub-issues via GraphQL), epic-bundle (deferred findings → Epic + sub-issues), expand (expand-vs-split mid-work), identi","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"github-flow (issue/PR workflow)\n  ├─→ plan-to-issue (issue body content)\n  ├─→ epic-bundle (deferred findings across PRs → one Epic issue)\n  │     ├─→ uses plan-to-issue (Epic body) + register (dup check) + dependencies (sub-issues)\n  │     └─→ receives from: consolidate next step (auto-suggest when deferred findings accumulate)\n  ├─→ register (evaluate duplicates and decide strategy)\n  ├─→ pr (PR body content + visual attachments)\n  ├─→ review (post structured review comments)\n  ├─→ expand (mid-work scope expansion)\n  ├─→ dependencies (Issue Relationships: blocked-by/blocking)\n  │     └─→ used by merge step 5 (pre-merge blockedBy check)\n  ├─→ merge (CI/Review/Test Plan/blockedBy verification → squash+merge)\n  ├─→ review-apply (deferred [REVIEW_FEEDBACK] → code fix → Summary update)\n  │     └─→ receives from: consolidate Step 7 (deferred registration)\n  ├─→ sanitize (HARD STOP scan before posting to PUBLIC repos)\n  └─→ upstream-issue (external repo feature request/bug report with duplicate check + draft + sanitize)"},{"language":"bash","snippet":"# Verify 6 pre-merge conditions\ngh pr view <PR_NUMBER> --json state,mergeable,reviews,checks,body"},{"language":"bash","snippet":"ORIGINAL_USER=$(gh api user --jq .login)\necho \"Current active GH user: $ORIGINAL_USER\""},{"language":"bash","snippet":"TARGET_USER=\"DrumRobot\"\nif [ \"$ORIGINAL_USER\" != \"$TARGET_USER\" ]; then\n  gh auth switch -u \"$TARGET_USER\"\nfi"},{"language":"bash","snippet":"gh pr merge <PR_NUMBER> --squash --delete-branch"},{"language":"bash","snippet":"if [ \"$ORIGINAL_USER\" != \"$TARGET_USER\" ]; then\n  gh auth switch -u \"$ORIGINAL_USER\"\nfi"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: github-flow\nmetadata:\n  author: es6kr\n  version: \"0.1.0\"\ndepends-on:\n  - cleanup\n  - code-workflow\n  - web-browser\ndescription: |\n  GitHub issue/PR workflow automation. Topics — auth-scope (gh CLI priority + account mapping + batch scope refresh + 404 checklist), commit-message-discipline (commit message authoring + amend refresh + PUBLIC English enforcement), dependencies (blocked-by/sub-issues via GraphQL), epic-bundle (deferred findings → Epic + sub-issues), expand (expand-vs-split mid-work), identity-auth (gh account map + scope refresh + GH_TOKEN fallback), merge (CI/review gates + no autonomous push), plan-to-issue (MD → issue body), pr (PR with test plan), publish (branch + draft PR + CI watch + ready + merge, one topic), push-guards (branch/push-reject/force-push/main-push), register (dup check + strategy), review (structured comments), review-apply (deferred feedback apply), sanitize (PUBLIC repo personal data scan), upstream-issue (external OSS feature/bug). Use when: \"plan to issue\", \"issue register\", \"create PR\", \"PR body\", \"code review\", \"merge PR\", \"PR squash\", \"sanitize\", \"PII\", \"expand PR\", \"blocked by\", \"epic bundle\", \"upstream issue\", \"review apply\", \"sub-issue\", \"gh auth\", \"force push\", \"push reject\", \"branch change forbid\", \"auth scope\", \"account mapping\", \"scope refresh\", \"commit message\", \"PUBLIC repo English\".\n---\n\n# GitHub Flow\n\nConvert plans, research, and implementation results into GitHub issues and PRs.\n\n## Topics\n\n| Topic | Description | Guide |\n|-------|-------------|-------|\n| auth-scope | gh CLI priority + account mapping + batch scope refresh + org-repo 404 checklist | [auth-scope.md](./auth-scope.md) |\n| commit-message-discipline | Commit message authoring, message update on amend, PUBLIC repo English enforcement, git operation type continuity, verb selection (`.md` as source code) | [commit-message-discipline.md](./commit-message-discipline.md) |\n| dependencies | Manage native Issue Relationships (blocked-by/blocking) via addBlockedBy/removeBlockedBy GraphQL mutations | [dependencies.md](./dependencies.md) |\n| epic-bundle | Bundle deferred review findings across multiple PRs into one Epic tracking issue (checklist + native sub-issues + epic label) | [epic-bundle.md](./epic-bundle.md) |\n| expand | Decide expand-vs-split when new findings emerge mid-work and update title/body | [expand.md](./expand.md) |\n| identity-auth | Owner-based gh account mapping for commit author identity + gh auth scope refresh + GH_TOKEN env fallback for org repo 404 | [identity-auth.md](./identity-auth.md) |\n| merge | CI success and AI review check then merge with commit cleanup, including pre-merge blockedBy verification | [merge.md](./merge.md) |\n| plan-to-issue | Convert plan/research MD to GitHub issue body or comments | [plan-to-issue.md](./plan-to-issue.md) |\n| pr | Create PR with structured body, test plan, and optional visual attachments. Every distinct PR number in an AskUserQuestion payload needs its own clickable URL"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn74k8yfvftx6f062qa8fzyd8h8373jd\",\n  \"slug\": \"github-flow\",\n  \"version\": \"0.11.3\",\n  \"publishedAt\": 1790524322009\n}"},{"path":"account-switch-merge.md","content":"# Account-Switch Merge (`account-switch-merge`)\n\nUse this topic when performing a PR merge requiring a specific merger account (e.g., `DrumRobot` bot account for CI/release isolation or protected branch policies) with automatic post-merge account restoration.\n\n## Purpose\n\nAutomates the manual 6-condition check, temporary `gh auth` user switch, squash/merge execution, and guaranteed restoration of the developer's original GitHub account state.\n\n---\n\n## 6 Pre-Merge Conditions Checklist (MANDATORY)\n\nBefore initiating an account switch or executing `gh pr merge`, ALL 6 conditions MUST be verified and pass:\n\n1. **CI Success**: `gh pr checks <N>` returned all `SUCCESS` (no pending, no failed).\n2. **AI Review Summary Posted**: `/consolidate pr <N>` has completed and the AI Review Summary comment is present (or PR is consolidate-exempt).\n3. **Test Plan Checked**: All `- [ ]` checklist items in the PR body are marked completed (`- [x]`).\n4. **Mergeable Status**: `gh pr view <N> --json mergeable` returns `\"MERGEABLE\"`.\n5. **Base Branch Alignment**: PR is up to date with the latest base branch (no merge conflicts).\n6. **Pre-Commit / Pre-Push Sanity**: Working tree is clean or changes are safely stashed.\n\n---\n\n## Automated 5-Step Account-Switch & Merge Protocol\n\n### Step 1: Pre-Merge Verification\n```bash\n# Verify 6 pre-merge conditions\ngh pr view <PR_NUMBER> --json state,mergeable,reviews,checks,body\n```\n\n### Step 2: Record Current Active User\n```bash\nORIGINAL_USER=$(gh api user --jq .login)\necho \"Current active GH user: $ORIGINAL_USER\"\n```\n\n### Step 3: Switch to Target Merger Account\nIf `$ORIGINAL_USER` is not the target merger account (e.g. `DrumRobot`), switch to it:\n```bash\nTARGET_USER=\"DrumRobot\"\nif [ \"$ORIGINAL_USER\" != \"$TARGET_USER\" ]; then\n  gh auth switch -u \"$TARGET_USER\"\nfi\n```\n\n### Step 4: Execute Squash & Merge\n```bash\ngh pr merge <PR_NUMBER> --squash --delete-branch\n```\n\n### Step 5: Guaranteed Original Account Restoration (HARD STOP)\nRegardless of merge success or failure, ALWAYS restore the original user account immediately:\n```bash\nif [ \"$ORIGINAL_USER\" != \"$TARGET_USER\" ]; then\n  gh auth switch -u \"$ORIGINAL_USER\"\nfi\n```\nVerify restored identity:\n```bash\ngh api user --jq .login\n```\n\n---\n\n## Don't / Do Table\n\n| # | Don't | Do |\n|---|-------|----|\n| 1 | Merge without checking all 6 pre-merge conditions | Verify CI, Review, Test Plan, and Mergeable status BEFORE switching account |\n| 2 | Leave active `gh auth` as `DrumRobot` after merge | ALWAYS restore `$ORIGINAL_USER` in Step 5 immediately after merge |\n| 3 | Use direct `git push origin main` bypass | Always merge via `gh pr merge <N> --squash` |"},{"path":"auth-scope.md","content":"# Auth Scope — gh CLI Priority + Account Mapping + Batch Scope Refresh + 404 Checklist\n\n## gh CLI Priority and Browser Agent Restriction (HARD STOP)\n\n**All GitHub operations (PR lookup, review, comment, merge, etc.) must use the `gh` CLI tool first; routing around via a browser agent is strictly forbidden.**\n\n| # | Don't | Do |\n|---|-------|----|\n| 1 | Call a browser agent to check/consolidate PR reviews | Combine `gh pr view`, `gh api`, `gh pr checks`, etc. to extract data from the CLI |\n| 2 | Skip the CLI based on the subjective judgment \"the browser is more accurate\" | The `gh` CLI maintains auth and context — it is the most reliable source. Consider the browser only when the CLI fails |\n| 3 | Wait for browser rendering for simple info lookups (e.g., comment lists) | Parse JSON with `gh api`. Much faster and uses fewer tokens |\n\nUse the browser agent **only for special situations that are genuinely impossible via the CLI** (e.g., complex GUI configuration, visual layout verification), and only with prior user approval.\n\n## Account Mapping (per organization)\n\n| Account | Purpose | git author identity |\n|---------|---------|---------------------|\n| `DrumRobot` | es6kr org repositories (es6kr/skills, claude-code-sessions, etc.) | `DrumRobot <drumrobot43@gmail.com>` |\n| `<personal-account>` | Personal org / personal repositories | `<personal-account> <personal@email.com>` |\n\n**Account switching**: `gh auth switch --user <account>`. On failure, inject `GH_TOKEN=\"$(gh auth token --user <account>)\"` as an environment variable instead (must be passed via a script file — env vars are not preserved between separate Bash calls).\n\n## commit author + PR account must map to repo owner (HARD STOP)\n\n**The gh account mapping applies not only to push/PR auth but also to commit author identity.** When committing/PRing to an es6kr org repository (including PUBLIC ones), proceeding with the `gh` active account still set to a non-primary account (a residual from other work) will permanently bake the wrong author into PUBLIC history. **Switch git author identity + gh account to match the repo owner before committing.**\n\n| # | Don't | Do |\n|---|-------|----|\n| 1 | Commit to an es6kr org repo while the active account is a non-primary account → wrong author baked in | Before committing: `git -C <repo> config user.name \"<correct-name>\" && git -C <repo> config user.email \"<correct-email>\"` |\n| 2 | Only switch the gh account for push/PR while leaving commit author as the wrong account | author + committer + push + PR must all match the repo owner's identity. Author is permanently recorded in PUBLIC history, so they must match |\n| 3 | Assume \"auth is only needed at push time\" | Commit author is baked in at commit time. An already-committed author can only be changed via amend/rebase |\n| 4 | Commit without checking the repo owner, relying on the current git config | Right before committing, run `git remote get-url origin` to confirm the owner → apply identity per the mappin"},{"path":"CHANGELOG.md","content":"# Changelog\n\n## [0.11.3](https://github.com/es6kr/skills/compare/github-flow-v0.11.2...github-flow-v0.11.3) (2026-09-27)\n\n\n### Bug Fixes\n\n* **github-flow:** add optional graph-render dispatch for large epic-bundle bundles ([#549](https://github.com/es6kr/skills/issues/549)) ([45e3629](https://github.com/es6kr/skills/commit/45e362987eb52cf35272b484918a22c0fdd8bafc))\n* **github-flow:** add PR-blocking-vehicle check before delivery-vehicle ask ([#550](https://github.com/es6kr/skills/issues/550)) ([89d9812](https://github.com/es6kr/skills/commit/89d98129de5530c7e13f827d5e3f7751b55bab97))\n* **github-flow:** document IDE-subshell token override, merge-permission gap, and worktree sweep ([#546](https://github.com/es6kr/skills/issues/546)) ([ebb366a](https://github.com/es6kr/skills/commit/ebb366a06fde5d1f28b42cbc8d483fc335d3d9d3))\n* **github-flow:** restore pre-merge state recheck in merge.md ([74ae392](https://github.com/es6kr/skills/commit/74ae39229444d0b039bb25bcb34cacea50ac1874))\n\n## [0.11.2](https://github.com/es6kr/skills/compare/github-flow-v0.11.1...github-flow-v0.11.2) (2026-09-24)\n\n\n### Bug Fixes\n\n* **git-repo:** add prune_merged_worktrees.py + 7 accumulated fixes ([3d2ee94](https://github.com/es6kr/skills/commit/3d2ee9425285347d8f7e7698049d6e5769f73f92))\n* **github-flow:** document multi-account and ssh remote publish gotchas ([4a772a8](https://github.com/es6kr/skills/commit/4a772a89adc8302f65da48c85e36588d2792f576))\n\n## [0.11.1](https://github.com/es6kr/skills/compare/github-flow-v0.11.0...github-flow-v0.11.1) (2026-09-20)\n\n\n### Bug Fixes\n\n* **github-flow:** document the batch-script secret-echo gotcha for token injection ([91e3205](https://github.com/es6kr/skills/commit/91e320570dca3acfa9925f3a4afcb532e786d423))\n\n## [0.11.0](https://github.com/es6kr/skills/compare/github-flow-v0.10.2...github-flow-v0.11.0) (2026-09-18)\n\n\n### Features\n\n* **task-plan,github-flow:** adopt artifact sibling guard in task-plan and prohibit multi-commit squash ([9938985](https://github.com/es6kr/skills/commit/9938985161fe1e0ddae934980b3c9307e7dfd5f4))\n\n\n### Bug Fixes\n\n* **cleanup:** make the session-end report table self-sufficient ([#487](https://github.com/es6kr/skills/issues/487)) ([c4a0255](https://github.com/es6kr/skills/commit/c4a02557fb8de3b32cf337c549f62535dabf824b))\n* **github-flow:** prohibit squash merge on multi-commit PRs in skills and plugins repos ([8db57f8](https://github.com/es6kr/skills/commit/8db57f8fe76357bda3f3d26fed7e4c253bfffbb3))\n\n## [0.10.2](https://github.com/es6kr/skills/compare/github-flow-v0.10.1...github-flow-v0.10.2) (2026-09-08)\n\n\n### Bug Fixes\n\n* **github-flow:** document merge-commit policy, promotion PR discipline, and develop routing ([ace6bd4](https://github.com/es6kr/skills/commit/ace6bd4d445a2f805a8183946f70bdf34d48289f))\n\n## [0.10.1](https://github.com/es6kr/skills/compare/github-flow-v0.10.0...github-flow-v0.10.1) (2026-09-01)\n\n\n### Bug Fixes\n\n* **githooks:** fix set -e crash in BASE-7 guard + weigh review-cost in pr.md Step"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":2143,"uniquenessScore":36,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-09T12:44:38.185Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-09T12:44:38.185Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T01:12:11.332Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}