[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6C3DRSTXY09QEQ3WSHM45ME":3,"skill-same:01M6C3DRSTXY09QEQ3WSHM45ME":123},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":27,"publishedAt":59,"linkOnly":60,"markdownContent":61,"markdownBody":62,"frontMatter":63,"refName":84,"commitSha":85,"skillDirectory":86,"forksCount":87,"repositoryHtmlUrl":88,"repositoryHomepageUrl":6,"ownerHtmlUrl":89,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":90,"install":91,"resources":104},"01M6C3DRSTXY09QEQ3WSHM45ME","claude-commands-export-superset",null,"Audit, rebase, supersede, and ship the jleechanorg\u002Fclaude-commands export pipeline.\nFive-session playbook covering consolidation, supersession, fresh export, AND the\ncleanup-PR + script-patch archetype (Pitfall 10) for excluding content categories like\n`_archive\u002F` that should never have shipped. v1.2.0 adds Pitfalls 11 + 12 covering\ncross-vendor re-sync staleness (vendored copy drifts from upstream between exports)\nand content-filter rewrites BODY-but-not-FILENAMES (install scripts that reference\nfilter-rewritten filenames break at install time). Triggers on \"consolidate the open\nclaude-commands PRs\", \"fresh \u002Fexportcommands\", \"remove the archive from the PR and\nmodify \u002Fexportcommands to stop exporting it\", \"supersede #N\", \"edit the export to\nexclude _archive\u002F\", \"the cmux-goal pair isn't on main\", \"re-sync the vendored\nwatchdog\", \"stale cmux_resume_watchdog in the export\", \"install script fails\nwith no such file\", \"com.$USER.cmux-resume-watchdog.plist not found\", etc.\nEncodes twelve pitfalls.","jleechanorg\u002Fjleechan-skills","jleechanorg","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F221404966?v=4","01M6C1VJ99XG950X1DWPEBCBGX","01M6C1VJDK5YVDNT3362RT5WSB",6,"MIT","https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002Fhermes\u002Fskills\u002Fgithub\u002Fclaude-commands-export-superset\u002FSKILL.md",[17,22],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",{"categoryNo":23,"categoryName":24,"taxonomyType":25,"taxonomyTypeDesc":26},"01JBSEEDCAT000000000000038","人力资源","PROFESSION","适用职业",[28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58],"export","claude commands export superset","superset","commands","consolidation","never","goal","time","fresh","filter","remove","re","categories","at","break","supersede","export pipeline","safe","install","edit","pair","rebase","open","ship","watchdog","playbook","pipeline","audit","cleanup","sync","workflow","2026-11-10 10:12:30",false,"---\nname: claude-commands-export-superset\ndescription: |\n  Audit, rebase, supersede, and ship the jleechanorg\u002Fclaude-commands export pipeline.\n  Five-session playbook covering consolidation, supersession, fresh export, AND the\n  cleanup-PR + script-patch archetype (Pitfall 10) for excluding content categories like\n  `_archive\u002F` that should never have shipped. v1.2.0 adds Pitfalls 11 + 12 covering\n  cross-vendor re-sync staleness (vendored copy drifts from upstream between exports)\n  and content-filter rewrites BODY-but-not-FILENAMES (install scripts that reference\n  filter-rewritten filenames break at install time). Triggers on \"consolidate the open\n  claude-commands PRs\", \"fresh \u002Fexportcommands\", \"remove the archive from the PR and\n  modify \u002Fexportcommands to stop exporting it\", \"supersede #N\", \"edit the export to\n  exclude _archive\u002F\", \"the cmux-goal pair isn't on main\", \"re-sync the vendored\n  watchdog\", \"stale cmux_resume_watchdog in the export\", \"install script fails\n  with no such file\", \"com.$USER.cmux-resume-watchdog.plist not found\", etc.\n  Encodes twelve pitfalls.\nversion: 1.2.0\nplatforms: [macos, linux]\nmetadata:\n  hermes:\n    tags: [github, claude-commands, export, supersession, rebase, audit, drive-pr-to-green, exclude-paths, script-patch, vendoring, cross-vendor-sync] \n    related_skills: [drive-pr-to-green, github-pr-automation-debug, github-pr-workflow, patch-tool-safe-editing]\n---\n\n# claude-commands-export-superset\n\nAudit, rebase, supersede, and ship the `jleechanorg\u002Fclaude-commands` export pipeline. This is the\ncanonical workflow when the user wants \"the latest `~\u002F.claude\u002F` shipped\" — multiple sessions have\nhit this same task with subtle differences (open PRs vary, some already merged, some still stale,\nsometimes the auto-opened PR contains content the user wants excluded), and the playbook below\nlocks in the four most common pitfalls PLUS the 5th-archetype cleanup workflow discovered 2026-07-13.\n\n## Trigger\n\nAny of these messages should fire this skill:\n\n- \"consolidate the open claude-commands PRs\" \u002F \"consolidate #N\u002F#M\u002F#O into one PR\"\n- \"fresh \u002Fexportcommands and check the PRs\"\n- \"the export is stale \u002F has new content since last run\"\n- \"see what else is needed \u002F what's incremental\" (mid-task state re-check)\n- \"supersede #N\" \u002F \"close #N as superseded\"\n- \"remove the archive from the PR and modify \u002Fexportcommands to stop exporting it\"\n- \"\u002Fexportcommands [from ~\u002Fyour-project.com]\"\n- \"the cmux-goal \u002F ironclad pair isn't on main yet\"\n- \"the latest commands\u002Fskills aren't in jleechanorg\u002Fclaude-commands\"\n- \"edit the export to exclude _archive\u002F\" \u002F \"stop exporting archive paths\"\n\n## Pitfall 1 — Always re-check current state BEFORE planning (added 2026-07-13)\n\nThe user may have merged some PRs mid-task, or some may have closed, between your first `gh pr list`\nand your final action. **Re-run the state-recency check after every user message and after every\nOOB directive**, not just at session start. Specifically:\n\n```bash\n# Step 0 of every task in this class — re-run on any pivot\nHOME=$HOME GH_TOKEN=\"\" gh api 'repos\u002Fjleechanorg\u002Fclaude-commands\u002Fpulls?state=open&per_page=20&sort=created&direction=desc' \\\n  --jq '[.[] | {n: .number, title: .title, state: .state, headRefName: .head.ref, headSha: .head.sha, baseSha: .base.sha, mergeable: .mergeable, mergeable_state: .mergeable_state, additions: .additions, deletions: .deletions, commits: .commits}]'\n\n# Also verify main SHA right now (not from earlier in the session)\nHOME=$HOME GH_TOKEN=\"\" gh api 'repos\u002Fjleechanorg\u002Fclaude-commands\u002Fbranches\u002Fmain' \\\n  --jq '{sha: .commit.sha, lastCommit: .commit.commit.message, lastCommitDate: .commit.commit.author.date}'\n```\n\nVerified 2026-07-13: an earlier session plan started \"consolidate #324\u002F#325\u002F#326 into one PR.\" A\nmid-task user OOB (\"i just merged some of those PRs\") revealed that #325 and #326 had already\nlanded on main at `337dc6d7` 8 minutes before the task. The original plan was obsolete; the\ncorrect response was to (a) supersede #324 as no-longer-net-new, (b) run a fresh\n`\u002Fexportcommands` for the incremental, (c) close the original 3-PR plan entirely.\n\n**Anti-pattern:** building a consolidation strategy on stale state. Even if your first `gh pr list`\nreturned 3 open PRs, a user pivot 60s later may have already merged 2 of them. Always re-verify.\n\n## Pitfall 2 — `mergeable_state: dirty` on a stale-base PR means BASE != main (added 2026-07-13)\n\nWhen you see `mergeable_state: dirty` or `mergeable: false` on a PR, the FIRST diagnostic is\n**base vs main comparison**, not the file list. The PR may simply be 200+ commits behind main\nbecause it was cut before several merges.\n\n```bash\n# Verify the staleness\nHOME=$HOME GH_TOKEN=\"\" gh api 'repos\u002F\u003Cowner>\u002F\u003Crepo>\u002Fpulls\u002F\u003CN>' \\\n  --jq '{baseSha: .base.sha, headSha: .head.sha, baseRef: .base.ref, mergeable: .mergeable, mergeable_state: .mergeable_state}'\n\nHOME=$HOME GH_TOKEN=\"\" gh api 'repos\u002F\u003Cowner>\u002F\u003Crepo>\u002Fbranches\u002Fmain' \\\n  --jq '{main: .commit.sha}'\n\n# If baseSha != main, the PR is stale. Three options:\n#   1. git merge origin\u002Fmain into the PR branch (merge-commit pattern, preserves N-commit history)\n#   2. git rebase origin\u002Fmain onto the PR branch (cleaner history, but replays N commits)\n#   3. Compare file content vs current main — if no truly-new content, supersede without merging\n```\n\nFor the `claude-commands` export PRs specifically, the **third option is often correct**: the\nPR's \"content\" is `cp` from `~\u002F.claude\u002F`, and if `~\u002F.claude\u002F` hasn't changed since the branch was\ncut, the rebase just produces duplicate work.\n\nVerified 2026-07-13: PR #324 (`add-cmux-goal-ironclad-thin-commands`) had `mergeable_state: dirty`,\nbase `a30c037` (3 days stale), 300 files vs current main, 200 commits. On rebase audit:\n- 0 truly net-new files (excluding `backup\u002F`, `.beads\u002F`, `.agentloop\u002F`)\n- 183 files where #324 had older content (main was ~4× larger in those paths)\n- 42 files in main but not in #324 (came from #325\u002F#326 merges)\n\nConclusion: #324 was obsolete and would re-introduce the `backup\u002F` security leak it pre-dated.\nRight action: **supersede, do not rebase**.\n\n## Pitfall 3 — `~\u002F.claude\u002Fcommands\u002Fexportcommands.sh` is NOT the canonical version (added 2026-07-13)\n\nTwo scripts coexist:\n\n| Path | Version | Hermes superset? |\n|---|---|---|\n| `~\u002F.claude\u002Fcommands\u002Fexportcommands.sh` (466 lines) | Original 2024-06 version | ❌ NO — `CLAUDE_DIRS=(commands skills hooks agents scripts)` only |\n| `your-project.com\u002F.claude\u002Fcommands\u002Fexportcommands.sh` | Live (per `export-commands-orchestration-contract`) | ✅ YES — adds `HERMES_DIRS=(skills commands)` (PR #8135) |\n\nThe \"live\" version lives in the your-project.com repo and is the one you want for `\u002Fexportcommands`\nruns targeting `jleechanorg\u002Fclaude-commands`. The global one still ships, but its hermes surface\nis missing.\n\n**Run recipe (verified 2026-07-13):**\n\n```bash\n# Run from your-project.com so the hermes-aware union-merge fires\ncd ~\u002Fyour-project.com\nHOME=$HOME PROJECT_ROOT=$HOME\u002Fyour-project.com \\\n  bash $HOME\u002F.claude\u002Fcommands\u002Fexportcommands.sh\n\n# Output structure (script writes to stdout in this exact shape):\n#   ▶ Cloning jleechanorg\u002Fclaude-commands...\n#   ✅ commands (global-only:N  project-only:N  identical:N  auto-resolved:N)\n#   ✅ skills (...)  ✅ hooks (...)  ✅ agents (...)  ✅ scripts (...)\n#   ✅ orchestration  ✅ automation  ✅ ralph  ✅ workflows\n#   ✅ Filters applied\n#   ▶ Scanning for leaked paths...\n#   ▶ Updating README.md via Claude...\n#   ⚠️  Claude CLI failed — keeping existing README unchanged   ← safe to ignore if non-blocking\n#   git secret guard: scanning outgoing range \u003CBASE>..\u003CHEAD> for refs\u002Fheads\u002Fexport-YYYYMMDD-HHMMSS\n#   ✅ Export complete!\n#      PR: https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fclaude-commands\u002Fpull\u002F\u003CN>\n#      Branch: export-YYYYMMDD-HHMMSS\n```\n\n**Branch naming is deterministic:** `export-YYYYMMDD-HHMMSS` (local PT timezone). The PR\nauto-opens via the script's `gh pr create --head \u003Cbranch> --base main` step.\n\n**Per-file byte-identity audit** (not file-list audit) is the correct delta test:\n\n```bash\n# For each file in the diff, fetch main's content and branch's content and compare bytes\ngit show origin\u002Fmain:\u003Cpath>     # main's version\ngit show origin\u002F\u003Cbranch>:\u003Cpath>  # branch's version\n# If identical → no net change\n# If branch has older\u002Fsmaller content → obsolete\n# If branch has net-new content → genuinely incremental\n```\n\n## Pitfall 4 — Bot rate-limit faux-green on the auto-opened export PR (added 2026-07-13)\n\nThe export script's auto-opened PR almost always posts **CodeRabbit status = success** BUT with\n**body = \"Review limit reached\"**. Same for Cursor Bugbot with **\"Bugbot couldn't run - usage limit\nreached\"**. These are NOT real reviews — they're webhook-level \"success\" statuses the bot posted\nto clear the queue without doing work.\n\n**Verification recipe (every time the export script's auto-PR is involved):**\n\n```bash\n# 1. Get the bot comments\nHOME=$HOME GH_TOKEN=\"\" gh api 'repos\u002Fjleechanorg\u002Fclaude-commands\u002Fissues\u002F\u003CN>\u002Fcomments?per_page=10' \\\n  --jq '[.[] | select(.user.login | test(\"coderabbitai|cursor|chatgpt-codex-connector\"; \"i\")) | {login: .user.login, body: .body[:200]}]'\n\n# 2. Match for the rate-limit telltales\n#   coderabbitai[bot]: contains \"Review limit reached\" or \"rate limited\"\n#   cursor[bot]: contains \"Bugbot couldn't run\" or \"usage limit reached\"\n#   chatgpt-codex-connector[bot]: contains \"Codex usage limits\"\n# If any of these phrases appears → status=success is FAUX. Document in the PR with a comment\n# citing coderabbit-slow-bot-policy from SOUL.md and proceed with the merge anyway.\n\n# 3. Also check the actual review state (not the status webhook)\nHOME=$HOME GH_TOKEN=\"\" gh api 'repos\u002Fjleechanorg\u002Fclaude-commands\u002Fpulls\u002F\u003CN>\u002Freviews' \\\n  --jq '[.[] | {state: .state, login: .user.login, submitted_at: .submitted_at}]'\n# Empty array = no real review was submitted = faux-green.\n```\n\n**Pattern (verified 2026-07-13, PR #327):** all three bots posted rate-limit comments within 60s\nof each other at PR creation; the status webhooks all showed `success`; the actual review array\nwas empty. Per `coderabbit-slow-bot-policy` in SOUL.md, this is non-blocking after ONE once-per-head\nreview attempt. Document the timeout in a PR comment with the same phrases the bots used, then\nproceed with the green-check + human-merge handoff.\n\n## Pitfall 5 — `git secret guard` output IS the security pre-check (added 2026-07-13)\n\nThe export script runs `git secret guard` on the outgoing range and prints to stdout. Look for:\n\n```\ngit secret guard: scanning outgoing range \u003CBASE>..\u003CHEAD> for refs\u002Fheads\u002F\u003CBRANCH>\n```\n\nA line WITHOUT a `FAIL` after it = clean. A line WITH `FAIL` or `WARNING` = block the PR until\nresolved. This is the ONLY security check the script does — there's no pre-commit hook or\nworkflow gate. If the script's stdout doesn't show this line at all, run `git secret scan\n\u003CBASE>..\u003CHEAD>` yourself before pushing.\n\n## Pitfall 6 — `localexportcommands.md` and `exportcommands.md` are DOCS, not scripts (added 2026-07-13)\n\nThree documents live in `~\u002F.claude\u002Fcommands\u002F`:\n\n| File | Role |\n|---|---|\n| `exportcommands.sh` (466 lines, 19.1K) | **The script.** Invoked by `\u002Fexportcommands`. |\n| `exportcommands.md` (45.1K) | **Operator doc** — explains what `\u002Fexportcommands` does, full superset spec, hermes-deploy-pipeline relationship. |\n| `localexportcommands.md` (23.2K) | **Local-only doc** — variant for projects that want to skip the global union and ship only their own `.claude\u002F` dir. |\n| `exportcommands.py` (96.4K) | Companion Python (alternative entry point; not invoked by `\u002Fexportcommands`). |\n| `tests\u002Ftest_exportcommands.py` | Contract tests for the Python entry. |\n\nWhen users say \"\u002Fexportcommands\", they mean the **bash script**, not the docs or the Python.\n\n## Pitfall 7 — The auto-opened PR has no `.github\u002Fworkflows\u002F` (verified 2026-07-13)\n\n`jleechanorg\u002Fclaude-commands` has CI at `.\u002Fworkflows\u002F*.yml`, NOT at `.github\u002Fworkflows\u002F`. Earlier\n`gh api .github\u002Fworkflows` returns 404 — that's expected. The CI is:\n\n- `workflows\u002Fcoderabbit-ping-on-push.yml` (CodeRabbit webhook ping)\n- `workflows\u002Fclaude-code.yml` (some Claude Code integration)\n- `workflows\u002Fclaude-processor.yml`\n- Plus 30+ others\n\nWhen driving an export PR to green, **don't look for `.github\u002Fworkflows\u002F`**. The \"green\" check\non this repo is:\n- `mergeable_state: clean` (REST pulls endpoint)\n- `statusCheckRollup` empty (no GH Actions runs on the export PR's head)\n- Real bot reviews OR documented rate-limit timeout per Pitfall 4\n\n## Pitfall 8 — Supersession comment template (verified 2026-07-13)\n\nWhen posting a supersession comment on a STALE PR (before closing), include:\n\n1. **Base staleness evidence** — the SHA the PR branched from and main's current SHA.\n2. **Per-file diff math** — total files, net-new, modified, main-only counts.\n3. **Why it's superseded** — concrete examples (empty files, security-leak files, files where\n   main has 4× the content).\n4. **Forward path** — where the incremental went instead (the new fresh-export PR).\n5. **Co-Authored-By** — Claude Code attribution.\n\n```markdown\n## Closing as superseded — consolidation audit findings\n\nAfter the merges of [PR #325](...) and [PR #326](...) landed on `main` @ `\u003CMAIN_SHA>`,\nthis PR's value collapsed. Detailed audit:\n\n### Diff math\n- Total files in #N: **\u003CN>** (vs current main)\n- Files in #N *only* (not in main): **\u003CX>** truly net-new (excluding `backup\u002F`, `.beads\u002F`, ...)\n- Files *modified* in #N vs main: **\u003CY>**\n- Files in main but not in #N: **\u003CZ>** (came from #N+1\u002F#N+2 merges)\n\nFor the \u003CY> files where #N differs from current main, main has ~\u003CM> MB of content vs #N's ~\u003Cm> MB.\n- `\u003Cfile_a>`, `\u003Cfile_b>` in this PR are **empty files**; main has the real implementations.\n- 29 `workflows\u002F*.yml` files predate the `security(backup)` gitignore; rebase reintroduces leaks.\n\n### Security incident this PR still contains\n`backup\u002F\u003CHOSTNAME>\u002F...` — \u003CN> files. The original 2026-07-12 home-config snapshot leak that\nprompted the `security: gitignore backup\u002F` commit. **Merging would re-introduce that leak.**\n\n### Recommendation\n- **`\u003Ckey feature>` is on main** (via [\u003CPR>](...) merge \u003CDATE>).\n- All remaining valuable content is **already represented** in main via #N+1+#N+2.\n\nClosing as superseded.\n\n? Generated with [Claude Code](https:\u002F\u002Fclaude.com\u002Fclaude-code). Co-Authored-By: Claude \u003Cnoreply@anthropic.com>\n```\n\n## Pitfall 9 — `\u002Fexportcommands` from a non-main branch (verified 2026-07-13)\n\nThe export script uses `git rev-parse --show-toplevel` to detect `PROJECT_ROOT`, NOT\n`--abbrev-ref HEAD`. So it works from any branch. BUT — if you're on `feat\u002Fissue-8084` with N\nuncommitted files, those files don't affect the export (uncommitted = not in worktree), but the\nexport still uses the WORKTREE'S HEAD for diff calculations.\n\n**Recipe:** if you want a \"true diff vs prior export\", check out the branch that matches the\nprior export's source state, run `\u002Fexportcommands` from there, then post the diff against the\nprior PR's branch. Verified 2026-07-13: running from `feat\u002Fissue-8084` produced PR #327 (66 files,\n+7,436\u002F−19) — clean against current main `337dc6d7`. Branch mismatch didn't corrupt anything\nbecause the union-merge ignores branch identity.\n\n## Pitfall 11 — Vendored-source re-sync staleness (verified 2026-08-01, PR #38 → #40)\n\nWhen the export bundles source files (Python scripts + tests) that originated in\na DIFFERENT upstream repo (e.g. `user_scope\u002Fscripts\u002Fcmux_resume_watchdog.py`\nre-shipped as `your-project.com\u002F.claude\u002Fskills\u002Fcmux-resume-watchdog\u002Fcmux_resume_watchdog.py`),\nthe export's snapshot has a *second* decay axis the existing 10 pitfalls don't\ncover: **the vendored copy can drift from upstream between export runs**. The\nsignal is the bug-by-bug re-discovery cycle:\n\n1. Run `\u002Fexportcommands` from your-project.com → snapshot of `cmux_resume_watchdog.py` from this exact moment lands in the export branch.\n2. Meanwhile, `user_scope` main advances (a real bug fix lands: 3 new quota regex anchors, 10 new network patterns).\n3. Live daemon on this machine is now running the upstream HEAD (auto-pulled by launchd), but the vendored copy in `your-project.com` (and downstream in `claude-commands`) is still pre-fix.\n4. The **first \u002Fadvice review** returns \"vendored copy is stale, missing 13 patterns\". Round-trip fix: re-copy from upstream, re-sync both PRs.\n5. **Second \u002Fadvice review** returns \"vendored test file uses `REPO_ROOT = Path(__file__).resolve().parents[1]`\" — but in the vendored location the script lives in `parents[0]`. **Every test fails on `importlib.SpecNotFound`.** Round-trip fix: patch REPO_ROOT in the vendored copy only.\n6. **Web-advice review** independently catches a fixture leak (`\"$USER@jeffreys-macbook-pro: ~\u002Fprojects\u002Fcold-reviewer\"` in a `Surface()` test fixture) that survived the SUBS filter because the regex `s|\\bjleechan\\b|$USER|g` rewrote `$USER` but the hostname + project path survived verbatim.\n\nThe cure (recipe, 2026-08-01):\n\n```bash\n# Phase A — re-sync the script AND its sibling test file\ncp $HOME\u002Fprojects\u002F\u003Cupstream>\u002Fscripts\u002F\u003Cscript>.py \\\n   $HOME\u002F.worktrees\u002F\u003Cexport-wt>\u002F.claude\u002Fskills\u002F\u003Cskill>\u002F\u003Cscript>.py\ncp $HOME\u002Fprojects\u002F\u003Cupstream>\u002Ftests\u002Ftest_\u003Cscript>.py \\\n   $HOME\u002F.worktrees\u002F\u003Cexport-wt>\u002F.claude\u002Fskills\u002F\u003Cskill>\u002Ftest_\u003Cscript>.py\n\n# Phase B — fix REPO_ROOT in the test file if it was authored for upstream's\n# tree layout (parents[N]) but the vendored location has a different depth.\n# Common case: upstream test does Path(__file__).resolve().parents[1] \u002F \"scripts\" \u002F X\n# → vendored test needs Path(__file__).resolve().parent \u002F X\n\n# Phase C — grep both files for fixture-style literals that the SUBS regex\n# won't catch (usernames, hostnames, project paths). Replace with placeholders.\n# Per SUBS spec (lines 220-260 of exportcommands.sh), `\\bjleechan\\b` is rewritten\n# to `$USER`, but `$USER@\u003Chostname>` is rewritten only on the prefix half.\n# Always run:\nrg -n '\\bjleechan\\b|@.*-macbook-pro|~\u002Fprojects\u002F[^\u002F]+\u002F' \\\n   $HOME\u002F.worktrees\u002F\u003Cexport-wt>\u002F.claude\u002Fskills\u002F\u003Cskill>\u002F\n\n# Phase D — run the test suite IN THE VENDORED LOCATION, not upstream\ncd $HOME\u002F.worktrees\u002F\u003Cexport-wt>\u002F.claude\u002Fskills\u002F\u003Cskill>\u002F\n~\u002F.local\u002Forch-venv\u002Fbin\u002Fpython3 -m pytest test_\u003Cscript>.py -q\n# Expect: same pass count as upstream, but RUN from this dir so the REPO_ROOT\n# lookup targets the vendored layout.\n\n# Phase E — only after test D passes, amend + force-push the export branches\ngit add .claude\u002Fskills\u002F\u003Cskill>\u002F\u003Cscript>.py .claude\u002Fskills\u002F\u003Cskill>\u002Ftest_\u003Cscript>.py\ngit commit --amend --no-edit\ngit push --force-with-lease=\u003Cexpected_old_sha> origin HEAD\n# Mirror to downstream (claude-commands export branch):\ncd $HOME\u002F.worktrees\u002F\u003Cdownstream-wt>\ncp ... same files ...\ngit add ... same files ...\ngit commit -m \"feat(skills\u002F\u003Cskill>): re-sync from \u003Cupstream> PR #N\"\ngit push origin HEAD\n```\n\nThree anti-patterns the recipe explicitly avoids:\n\n- ❌ **Re-running `\u002Fexportcommands`** to \"refresh\" the vendored copy — the export script does a UNION-MERGE of all skill files; if upstream's file is functionally newer than the export's, the union-merge may not even detect the change because the export's content filters rewrite upstream's bytes too. Re-run is the wrong tool.\n- ❌ **Patching only the script** (not the test file). The test file's `REPO_ROOT` resolution depends on the file's position in the vendored tree, which differs from upstream's tree. Always ship both files together.\n- ❌ **Trusting the SUBS regex to filter fixture leaks**. The regex is fine-grained for `$USER` standalone but mechanically blind to the surrounding context (`$USER@\u003Chost>`, `~\u002Fprojects\u002F\u003Cpath>\u002F`). Always run the Phase C leak grep after every re-sync.\n\n**The cross-vendor re-sync is a three-PR pipeline** (verified 2026-08-01):\n- Upstream: `jleechanorg\u002Fuser_scope` PR #40 — canonical fix lands here.\n- Source-side: `$GITHUB_REPOSITORY` PR #8681 — re-sync the vendored copy + force-push.\n- Downstream: `jleechanorg\u002Fclaude-commands` PR #346 — mirror the re-sync + push.\n\nAll three PRs must move together or the merge decouples. Force-push only to branches you own; use `gh pr view --json headRefName,author` to verify branch ownership before each `--force-with-lease=\u003Cexpected_old_sha>`.\n\n## Pitfall 12 — Content-filter regex rewrites BODY but not FILENAMES (verified 2026-08-01, install_cmux_resume_watchdog.sh)\n\nThe export's `perl -pi -e 's|...|...|g'` SUBS regexes rewrite CONTENT of filtered files in place. Filenames are NOT filtered. This is a sharp edge when an install script or shell wrapper does *both*:\n\n1. Defines a `LABEL=com.\u003Cgithubuser>.\u003Cskill>` constant in CONTENT (gets filter-rewritten to `LABEL=com.$USER.\u003Cskill>`).\n2. References `$SKILL_DIR\u002F$LABEL.\u003Cext>` to find a sibling file on disk (FILENAME on disk is NOT rewritten — still `com.\u003Cgithubuser>.\u003Cskill>.\u003Cext>`).\n\n**Symptom** (verified 2026-08-01, `install_cmux_resume_watchdog.sh:18`): script does `sed -e \"s|@HOME@|$HOME|g\" ... \"$SKILL_DIR\u002F$LABEL.plist.template\"` where `$LABEL` is post-filter `com.$USER.cmux-resume-watchdog` but the shipped template file is `com.$USER.cmux-resume-watchdog.plist.template`. The `set -euo pipefail` script aborts on `ls` returning empty — and **the install is broken for every downstream user**, not just the bad commit author.\n\n**Three cure recipes**, pick the one that matches the install script's structure:\n\n```bash\n# Recipe A — rename the file to be filter-stable (drop the user-name prefix).\n#   Before: com.$USER.cmux-resume-watchdog.plist.template\n#   After:  cmux-resume-watchdog.plist.template\n# Pros: zero install-script changes needed (the file path becomes predictable).\n# Cons: doesn't help if the script reaches for files by user-derived names.\n\n# Recipe B — use @PLACEHOLDER@ in the file's CONTENT and `sed \"s|@PLACEHOLDER@|$LABEL|g\"`\n# in the installer. The export's SUBS regex is non-greedy on `@` so `@LABEL@`,\n# `@DEST@`, `@HOME@` survive the filter intact.\n# Pros: any user-derived token can be parameterized without filter breakage.\n# Cons: the install script must explicitly run the sed pass; a literal-substitute\n#   installer will break.\n\n# Recipe C — pick a vendor-neutral name that doesn't contain the github username.\n#   com.localhost.\u003Cskill>           — stable across users; macOS launchd accepts\n#                                     labels with localhost domain; no filter\n#                                     rewrite is needed even if the content\n#                                     mentions the literal string.\n#   com.example.\u003Cskill>             — same idea\n# Pros: zero filter interaction at all.\n# Cons: many users' machines already have a com.\u003Ctheir-actual-github-user>.\u003Cskill>\n#   entry in \u002FLibrary\u002FLaunchAgents, so first install requires explicit bootout\n#   of the old label.\n```\n\n**Detection recipe** (run BEFORE every export of a skill that has shell installers):\n\n```bash\n# For every shell\u002Fscript file in the staged export, list every reference to a\n# github-username-prefixed file path:\nHOME=$HOME git -C $HOME\u002F.worktrees\u002F\u003Cexport-wt> diff --name-only \\\n  --diff-filter=AM HEAD~1..HEAD | grep -E '\\.(sh|bash|zsh|fish)$' | while read f; do\n    echo \"=== $f ===\"\n    grep -nE \"com\\\\.\\\\w+|com\\\\.\\\\\\$USER|\u002F\\\\\\$LABEL\u002F\\\\\\$|\\\\\\$SKILL_DIR\u002F\\\\\\$LABEL\" \"$f\"\n  done\n# Each \"Yes I do\" hit → apply Recipe A, B, or C above.\n```\n\n**The mental model:** filter rewrites apply to *content*. Any cross-reference between\na content-managed variable (like `LABEL=...`) and a filesystem name is a latent\nbreakage waiting for a fresh export on a different host. Audit every `ls $X`,\n`@file_template`, `$CONFIG_DIR\u002F...` reference for this property before pushing.\n\n## Pitfall 10 — The 5th archetype: cleanup-PR + script-patch workflow (added 2026-07-13)\n\nThe export script has **no exclude logic for content categories**. It's a copy-everything\nunion-merge. A fresh export will ship every file under `~\u002F.claude\u002Fskills\u002F_archive\u002F`,\n`~\u002F.claude\u002Fskills\u002F_archived_loose_md\u002F`, `.beads\u002F`, etc. — local history-keeping surfaces that\nshould never reach the public `jleechanorg\u002Fclaude-commands` repo.\n\nWhen the user says *\"remove the archive from the PR and modify \u002Fexportcommands to stop exporting\nit\"*, the correct response is a two-track atomic edit:\n\n### Track A — patch `exportcommands.sh` so future runs skip the category\n\nThe script has TWO union-merge surfaces plus an rsync for root-level dirs. Each needs its own\nexclude:\n\n```bash\n# Surface 1: union_dir() global find — add to the `\\( -not -path ... \\)` block\n\\( -not -path '*\u002F_archive\u002F*' \\) \\\n\n# Surface 2: union_dir() project find — same exclude, different anchor context\n\\( -not -path '*\u002F_archive\u002F*' \\) \\\n\n# Surface 3: rsync block for orchestration\u002Fautomation\u002Fralph — add to --exclude list\n--exclude='_archive\u002F' \\\n--exclude='*\u002F_archive' \\\n```\n\nThe script's `find` calls have ~25 lines of `--not -path` clauses between them — use unique\nsurrounding context (e.g. the `union_dir()` body or `while IFS= read -r -d '' f; do` lines) to\ndisambiguate. After patching, run `bash -n ~\u002F.claude\u002Fcommands\u002Fexportcommands.sh` to confirm syntax.\n\n**Smoke-test the patch** before pushing: extract the union_dir function and run it against a\nfixture with files in both `_archive\u002F` and non-`_archive\u002F` paths. Confirm the count of returned\nfiles matches the expected (non-archive) total.\n\n### Track B — amend the auto-opened PR to drop the unwanted content\n\nIn a fresh worktree of the PR branch:\n\n```bash\n# 1. Get the diff-list and identify files in the unwanted category\nHOME=$HOME git -C ~\u002Fworktrees\u002F\u003Cbranch> diff --name-only --diff-filter=AM HEAD~1..HEAD \\\n  | grep '\u003Cunwanted-category-pattern>' > \u002Ftmp\u002Frm_files.txt\n\n# 2. git rm the matching files\nHOME=$HOME git -C ~\u002Fworktrees\u002F\u003Cbranch> rm -rf $(cat \u002Ftmp\u002Frm_files.txt)\n\n# 3. Commit and force-push\nHOME=$HOME git -C ~\u002Fworktrees\u002F\u003Cbranch> commit -F \u003Ccommit-message-file>\nHOME=$HOME git -C ~\u002Fworktrees\u002F\u003Cbranch> push --force-with-lease origin \\\n  HEAD:refs\u002Fheads\u002F\u003Cbranch>\n```\n\n### CRITICAL — distinguish \"files I ADDED\" vs \"files main already had\"\n\nThe auto-opened PR may include files that **already existed on main** (in modified form, because\nthe export's content filters changed them by ~30 bytes). Removing those files wholesale will\nmake them disappear from main on merge, which is wrong.\n\n**Recipe to keep main's version intact** while still removing only the unwanted category:\n\n```bash\n# For each \"already-on-main\" file the script modified, restore it to main's exact bytes\ngit restore --source=\u003CMAIN_SHA> --staged --worktree -- \u003Cfile-path>\n\n# Verify byte identity before committing\ngit show \u003CMAIN_SHA>:\u003Cfile> | git hash-object --stdin\ncat \u003Cfile> | git hash-object --stdin\n# Both SHAs must match — if they differ by even 1 byte, the content-filter stripped a trailing newline\n```\n\n**Don't use `git checkout HEAD~1 -- \u003Cfile>`** — that restores to the export-PR's modified version\n(before the cleanup), not to main's original. `git restore --source=\u003CMAIN_SHA>` is the only path\nthat ensures zero net diff vs main.\n\n### Final shape\n\nAfter Track A + Track B, the PR diff shrinks from \"all categories\" to \"the actual incremental\nthe user wanted\". Verified 2026-07-13 with PR #327: original 66 files → 5 files after the\ncleanup. The 5-file PR contained exactly `\u002Fharness --optimize` flag, new `\u002Fslackbots` command,\n`\u002Fsocial` draft-only semantics, plus the two backing skill files.\n\n**Always close by posting a follow-up PR comment** that summarizes the cleanup (what was\nremoved, why, what the script patch prevents) — this is the durable record for future sessions\nand audit trails. CodeRabbit may now actually review the PR (since the bot rate limit resets\non push), so the post-cleanup push is also your chance to retrigger a real review.\n\n## The full sequence (execute in order, no pauses)\n\n### Phase 0 — Re-check state (Pitfall 1)\n\n```bash\nHOME=$HOME GH_TOKEN=\"\" gh api 'repos\u002Fjleechanorg\u002Fclaude-commands\u002Fpulls?state=open&per_page=20' \\\n  --jq '[.[] | {n: .number, title: .title, baseSha: .base.sha, mergeable: .mergeable, mergeable_state: .mergeable_state, headRefName: .head.ref, headSha: .head.sha, files: .changed_files, additions: .additions, deletions: .deletions, commits: .commits}]'\n\nHOME=$HOME GH_TOKEN=\"\" gh api 'repos\u002Fjleechanorg\u002Fclaude-commands\u002Fbranches\u002Fmain' \\\n  --jq '{main: .commit.sha, lastCommit: .commit.commit.message, lastCommitDate: .commit.commit.author.date}'\n```\n\nIf main advanced past the open PRs' bases, reclassify each open PR as:\n- **FRESH** — baseSha == main → drive to green directly\n- **STALE** — baseSha \u003C main → run Pitfall 2 audit (base audit + content audit)\n- **CLEANUP_NEEDED** — auto-opened export PR with files in unwanted categories → Pitfall 10\n- **AUTO-MERGED** — `state: closed, mergedAt: \u003Crecent>` → already in main, no action\n- **CLOSED-UNMERGED** — `state: closed, mergedAt: null` → archive, don't reopen\n\n### Phase 1 — Content audit on each STALE PR (Pitfall 2 + 3)\n\nFor each STALE PR, in a fresh clone:\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fclaude-commands.git \u002Ftmp\u002F\u003Cpurpose>-audit\ncd \u002Ftmp\u002F\u003Cpurpose>-audit\ngit fetch origin \u003Cbranch>\ngit checkout -B audit\u002F\u003Cpr-n> origin\u002F\u003Cbranch>\n\n# Per-file byte identity check (not just name overlap)\npython3 \u003C\u003C'PY'\nimport subprocess, os, time\n# ... fetch main's content + branch's content for each file in diff, compare bytes\nPY\n```\n\nThe output is one of:\n- **0 truly new files + N outdated files + security-leak files** → supersede\n- **\u003C10 truly new files + 0 outdated** → rebase + merge (preserves the unique work)\n- **Many new files, all in `.claude\u002F` not in `backup\u002F` etc** → rebase + merge\n- **Many new files in unwanted categories (`_archive\u002F`, etc.)** → Pitfall 10 cleanup-PR + script-patch\n\nIf supersede, post a detailed audit comment per the Pitfall 8 template.\n\n### Phase 2 — Run fresh \u002Fexportcommands (Pitfall 3 + 5)\n\n```bash\ncd ~\u002Fyour-project.com\nHOME=$HOME PROJECT_ROOT=$HOME\u002Fyour-project.com \\\n  bash $HOME\u002F.claude\u002Fcommands\u002Fexportcommands.sh\n```\n\nCapture:\n- Branch name (`export-YYYYMMDD-HHMMSS`)\n- Commit SHA\n- PR number (auto-opened)\n- `git secret guard` line (must be clean)\n- File count \u002F additions \u002F deletions\n\n### Phase 2.5 — (Optional) Cleanup-PR + script-patch (Pitfall 10)\n\nIf the auto-opened PR contains content the user wants excluded:\n\n1. Patch `~\u002F.claude\u002Fcommands\u002Fexportcommands.sh` (Track A) with the 3 exclude additions.\n2. Run `bash -n` to confirm syntax + a smoke-test fixture to confirm `find` no longer\n   picks up files in the unwanted category.\n3. In a fresh worktree, `git rm` the unwanted files, `git restore --source=\u003CMAIN_SHA>` the\n   already-on-main files that the script's content filters modified (Track B).\n4. `git commit --amend` to fold the restorations into the cleanup commit (or new commit).\n5. `git push --force-with-lease origin HEAD:refs\u002Fheads\u002F\u003Cbranch>`.\n6. Verify the PR's file list via REST: must show exactly the categories you want.\n\n### Phase 3 — Drive the new PR to green (Pitfall 4 + 7)\n\n```bash\n# REST (GraphQL is rate-limited; use REST for state)\nHOME=$HOME GH_TOKEN=\"\" gh api \"repos\u002Fjleechanorg\u002Fclaude-commands\u002Fpulls\u002F\u003CN>\" \\\n  --jq '{mergeable: .mergeable, mergeable_state: .mergeable_state, headSha: .head.sha, baseSha: .base.sha, changed_files: .changed_files, additions: .additions, deletions: .deletions}'\n\n# Bot faux-green check\nHOME=$HOME GH_TOKEN=\"\" gh api \"repos\u002Fjleechanorg\u002Fclaude-commands\u002Fissues\u002F\u003CN>\u002Fcomments?per_page=10\" \\\n  --jq '[.[] | {login: .user.login, body: .body[:150]}] | map(select(.login | test(\"coderabbit|cursor|chatgpt-codex\"; \"i\")))'\n\n# Status webhook (often shows success despite no real review)\nHOME=$HOME GH_TOKEN=\"\" gh api \"repos\u002Fjleechanorg\u002Fclaude-commands\u002Fcommits\u002F\u003CHEAD_SHA>\u002Fstatus\" \\\n  --jq '{state: .state, contexts: [.statuses[] | {context: .context, state: .state}]}'\n```\n\nIf bots rate-limited → post a documentation comment per the template in Pitfall 4 (cite\n`coderabbit-slow-bot-policy` from SOUL.md, ping `@coderabbitai` to retrigger, set a 2h SLA).\n\nIf bots substantive and CHANGES_REQUESTED → fix inline (the export script's content is generated,\nnot authored, so fixes are usually trivial content adjustments — re-run the script).\n\nIf bots substantive and APPROVED → ready to merge.\n\n### Phase 4 — Supersede any STALE PR (Pitfall 8)\n\nDo NOT close the STALE PR before the new fresh-export PR is verified clean. Close order matters:\nif you close #324 first and the new export PR turns out to be wrong, you've burned your reference\nstate. Post the supersession comment, leave the PR open until the new one is green, then close.\n\n### Phase 5 — Final reply (Slack thread + PR description)\n\nSame shape as `drive-pr-to-green` Step 10 — single reply with PR URL, gate-by-gate verdicts, and\nthe per-PR supersession receipts. Cite each bot's rate-limit timeout in the reply so the user\nknows why a \"green\" PR has no real review. If Phase 2.5 ran, include the script-patch path\n(`~\u002F.claude\u002Fcommands\u002Fexportcommands.sh` line ranges + before\u002Fafter file count) so the user can\nsee the durable prevention fix.\n\n## References\n\n- `references\u002Fsessions-recap.md` — session-by-session audit of what was learned across 2026-07-01, 2026-07-02, 2026-07-06, 2026-07-13 (1st cleanup session)\n- `references\u002Fcleanup-archetype-recipe.md` — detailed Track A (script-patch) + Track B (PR cleanup) workflow with the 5-file vs 66-file PR case study\n- `references\u002Fexportcommands-sh-contract.md` — full content-filter + union-merge spec extracted from the live script\n- `references\u002Fcross-vendor-resync-recipe.md` — Pitfall 11 deep-dive: the three-bug cycle (stale source → REPO_ROOT break → fixture leak) when an exported skill bundles code from a different upstream repo, with verified recipe (Phases A-F)\n- `references\u002Frouting-eval.jsonl` — `{intent, expected_skill, ambiguous_with?}` fixture for skill resolver routing evals\n\n## Resolver Trigger Entry\n\nFor the resolver, the heading line MUST contain the user-typed trigger phrases on the same line as the `##` heading. Add this entry to `~\u002F.hermes\u002Fskills\u002FRESOLVER.md` (the canonical resolver graph):\n\n```markdown\n## claude-commands-export-superset — consolidate claude-commands PRs, run fresh \u002Fexportcommands, cleanup-PR + script-patch to exclude categories, supersede stale PRs, drive to green\ntriggers: consolidate the open claude-commands PRs, fresh \u002Fexportcommands and check the PRs, the export is stale, see what else is needed \u002F what's incremental, supersede #N, \u002Fexportcommands from ~\u002Fyour-project.com, the cmux-goal \u002F ironclad pair isn't on main, the latest commands\u002Fskills aren't in jleechanorg\u002Fclaude-commands, run a fresh export of my claude config, audit the open export PRs, close #N as superseded, remove the archive from the PR and modify \u002Fexportcommands to stop exporting it, edit the export to exclude _archive\u002F, stop exporting archive paths, drop the archive from this PR\n```\n\n## Skills Index \u002F Discovery\n\nThis skill is referenced by \u002F related to:\n\n- `drive-pr-to-green` — general PR-to-green workflow; we use it for the new export PR's Phase 3 (faux-green detection)\n- `github-pr-automation-debug` — explains the bot-authoring pattern; useful for the Phase 3 bot rate-limit faux-green check\n- `github-pr-workflow` — low-level `gh pr` helpers used throughout Phases 0–4\n- `patch-tool-safe-editing` — relevant for the script-patch phase (Pitfall 10 Track A); the union-merge script has 3 surfaces with shared `\\( -not -path ... \\)` patterns that require unique surrounding context to disambiguate\n\nThe class is distinct from those because:\n1. The export script's auto-opened PR has **specific union-merge semantics** that other PRs don't (Pitfall 3, 5)\n2. The `mergeable_state: dirty` audit is **content-driven** not just branch-driven (Pitfall 2)\n3. The bot faux-green pattern shows up **reliably on every auto-opened export PR** (Pitfall 4)\n4. Supersession is a **first-class action** in this workflow, unlike other PR workflows\n5. Cleanup-PR + script-patch is the 5th archetype for content categories that should never have shipped (Pitfall 10)","# claude-commands-export-superset\n\nAudit, rebase, supersede, and ship the `jleechanorg\u002Fclaude-commands` export pipeline. This is the\ncanonical workflow when the user wants \"the latest `~\u002F.claude\u002F` shipped\" — multiple sessions have\nhit this same task with subtle differences (open PRs vary, some already merged, some still stale,\nsometimes the auto-opened PR contains content the user wants excluded), and the playbook below\nlocks in the four most common pitfalls PLUS the 5th-archetype cleanup workflow discovered 2026-07-13.\n\n## Trigger\n\nAny of these messages should fire this skill:\n\n- \"consolidate the open claude-commands PRs\" \u002F \"consolidate #N\u002F#M\u002F#O into one PR\"\n- \"fresh \u002Fexportcommands and check the PRs\"\n- \"the export is stale \u002F has new content since last run\"\n- \"see what else is needed \u002F what's incremental\" (mid-task state re-check)\n- \"supersede #N\" \u002F \"close #N as superseded\"\n- \"remove the archive from the PR and modify \u002Fexportcommands to stop exporting it\"\n- \"\u002Fexportcommands [from ~\u002Fyour-project.com]\"\n- \"the cmux-goal \u002F ironclad pair isn't on main yet\"\n- \"the latest commands\u002Fskills aren't in jleechanorg\u002Fclaude-commands\"\n- \"edit the export to exclude _archive\u002F\" \u002F \"stop exporting archive paths\"\n\n## Pitfall 1 — Always re-check current state BEFORE planning (added 2026-07-13)\n\nThe user may have merged some PRs mid-task, or some may have closed, between your first `gh pr list`\nand your final action. **Re-run the state-recency check after every user message and after every\nOOB directive**, not just at session start. Specifically:\n\n```bash\n# Step 0 of every task in this class — re-run on any pivot\nHOME=$HOME GH_TOKEN=\"\" gh api 'repos\u002Fjleechanorg\u002Fclaude-commands\u002Fpulls?state=open&per_page=20&sort=created&direction=desc' \\\n  --jq '[.[] | {n: .number, title: .title, state: .state, headRefName: .head.ref, headSha: .head.sha, baseSha: .base.sha, mergeable: .mergeable, mergeable_state: .mergeable_state, additions: .additions, deletions: .deletions, commits: .commits}]'\n\n# Also verify main SHA right now (not from earlier in the session)\nHOME=$HOME GH_TOKEN=\"\" gh api 'repos\u002Fjleechanorg\u002Fclaude-commands\u002Fbranches\u002Fmain' \\\n  --jq '{sha: .commit.sha, lastCommit: .commit.commit.message, lastCommitDate: .commit.commit.author.date}'\n```\n\nVerified 2026-07-13: an earlier session plan started \"consolidate #324\u002F#325\u002F#326 into one PR.\" A\nmid-task user OOB (\"i just merged some of those PRs\") revealed that #325 and #326 had already\nlanded on main at `337dc6d7` 8 minutes before the task. The original plan was obsolete; the\ncorrect response was to (a) supersede #324 as no-longer-net-new, (b) run a fresh\n`\u002Fexportcommands` for the incremental, (c) close the original 3-PR plan entirely.\n\n**Anti-pattern:** building a consolidation strategy on stale state. Even if your first `gh pr list`\nreturned 3 open PRs, a user pivot 60s later may have already merged 2 of them. Always re-verify.\n\n## Pitfall 2 — `mergeable_state: dirty` on a stale-base PR means BASE != main (added 2026-07-13)\n\nWhen you see `mergeable_state: dirty` or `mergeable: false` on a PR, the FIRST diagnostic is\n**base vs main comparison**, not the file list. The PR may simply be 200+ commits behind main\nbecause it was cut before several merges.\n\n```bash\n# Verify the staleness\nHOME=$HOME GH_TOKEN=\"\" gh api 'repos\u002F\u003Cowner>\u002F\u003Crepo>\u002Fpulls\u002F\u003CN>' \\\n  --jq '{baseSha: .base.sha, headSha: .head.sha, baseRef: .base.ref, mergeable: .mergeable, mergeable_state: .mergeable_state}'\n\nHOME=$HOME GH_TOKEN=\"\" gh api 'repos\u002F\u003Cowner>\u002F\u003Crepo>\u002Fbranches\u002Fmain' \\\n  --jq '{main: .commit.sha}'\n\n# If baseSha != main, the PR is stale. Three options:\n#   1. git merge origin\u002Fmain into the PR branch (merge-commit pattern, preserves N-commit history)\n#   2. git rebase origin\u002Fmain onto the PR branch (cleaner history, but replays N commits)\n#   3. Compare file content vs current main — if no truly-new content, supersede without merging\n```\n\nFor the `claude-commands` export PRs specifically, the **third option is often correct**: the\nPR's \"content\" is `cp` from `~\u002F.claude\u002F`, and if `~\u002F.claude\u002F` hasn't changed since the branch was\ncut, the rebase just produces duplicate work.\n\nVerified 2026-07-13: PR #324 (`add-cmux-goal-ironclad-thin-commands`) had `mergeable_state: dirty`,\nbase `a30c037` (3 days stale), 300 files vs current main, 200 commits. On rebase audit:\n- 0 truly net-new files (excluding `backup\u002F`, `.beads\u002F`, `.agentloop\u002F`)\n- 183 files where #324 had older content (main was ~4× larger in those paths)\n- 42 files in main but not in #324 (came from #325\u002F#326 merges)\n\nConclusion: #324 was obsolete and would re-introduce the `backup\u002F` security leak it pre-dated.\nRight action: **supersede, do not rebase**.\n\n## Pitfall 3 — `~\u002F.claude\u002Fcommands\u002Fexportcommands.sh` is NOT the canonical version (added 2026-07-13)\n\nTwo scripts coexist:\n\n| Path | Version | Hermes superset? |\n|---|---|---|\n| `~\u002F.claude\u002Fcommands\u002Fexportcommands.sh` (466 lines) | Original 2024-06 version | ❌ NO — `CLAUDE_DIRS=(commands skills hooks agents scripts)` only |\n| `your-project.com\u002F.claude\u002Fcommands\u002Fexportcommands.sh` | Live (per `export-commands-orchestration-contract`) | ✅ YES — adds `HERMES_DIRS=(skills commands)` (PR #8135) |\n\nThe \"live\" version lives in the your-project.com repo and is the one you want for `\u002Fexportcommands`\nruns targeting `jleechanorg\u002Fclaude-commands`. The global one still ships, but its hermes surface\nis missing.\n\n**Run recipe (verified 2026-07-13):**\n\n```bash\n# Run from your-project.com so the hermes-aware union-merge fires\ncd ~\u002Fyour-project.com\nHOME=$HOME PROJECT_ROOT=$HOME\u002Fyour-project.com \\\n  bash $HOME\u002F.claude\u002Fcommands\u002Fexportcommands.sh\n\n# Output structure (script writes to stdout in this exact shape):\n#   ▶ Cloning jleechanorg\u002Fclaude-commands...\n#   ✅ commands (global-only:N  project-only:N  identical:N  auto-resolved:N)\n#   ✅ skills (...)  ✅ hooks (...)  ✅ agents (...)  ✅ scripts (...)\n#   ✅ orchestration  ✅ automation  ✅ ralph  ✅ workflows\n#   ✅ Filters applied\n#   ▶ Scanning for leaked paths...\n#   ▶ Updating README.md via Claude...\n#   ⚠️  Claude CLI failed — keeping existing README unchanged   ← safe to ignore if non-blocking\n#   git secret guard: scanning outgoing range \u003CBASE>..\u003CHEAD> for refs\u002Fheads\u002Fexport-YYYYMMDD-HHMMSS\n#   ✅ Export complete!\n#      PR: https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fclaude-commands\u002Fpull\u002F\u003CN>\n#      Branch: export-YYYYMMDD-HHMMSS\n```\n\n**Branch naming is deterministic:** `export-YYYYMMDD-HHMMSS` (local PT timezone). The PR\nauto-opens via the script's `gh pr create --head \u003Cbranch> --base main` step.\n\n**Per-file byte-identity audit** (not file-list audit) is the correct delta test:\n\n```bash\n# For each file in the diff, fetch main's content and branch's content and compare bytes\ngit show origin\u002Fmain:\u003Cpath>     # main's version\ngit show origin\u002F\u003Cbranch>:\u003Cpath>  # branch's version\n# If identical → no net change\n# If branch has older\u002Fsmaller content → obsolete\n# If branch has net-new content → genuinely incremental\n```\n\n## Pitfall 4 — Bot rate-limit faux-green on the auto-opened export PR (added 2026-07-13)\n\nThe export script's auto-opened PR almost always posts **CodeRabbit status = success** BUT with\n**body = \"Review limit reached\"**. Same for Cursor Bugbot with **\"Bugbot couldn't run - usage limit\nreached\"**. These are NOT real reviews — they're webhook-level \"success\" statuses the bot posted\nto clear the queue without doing work.\n\n**Verification recipe (every time the export script's auto-PR is involved):**\n\n```bash\n# 1. Get the bot comments\nHOME=$HOME GH_TOKEN=\"\" gh api 'repos\u002Fjleechanorg\u002Fclaude-commands\u002Fissues\u002F\u003CN>\u002Fcomments?per_page=10' \\\n  --jq '[.[] | select(.user.login | test(\"coderabbitai|cursor|chatgpt-codex-connector\"; \"i\")) | {login: .user.login, body: .body[:200]}]'\n\n# 2. Match for the rate-limit telltales\n#   coderabbitai[bot]: contains \"Review limit reached\" or \"rate limited\"\n#   cursor[bot]: contains \"Bugbot couldn't run\" or \"usage limit reached\"\n#   chatgpt-codex-connector[bot]: contains \"Codex usage limits\"\n# If any of these phrases appears → status=success is FAUX. Document in the PR with a comment\n# citing coderabbit-slow-bot-policy from SOUL.md and proceed with the merge anyway.\n\n# 3. Also check the actual review state (not the status webhook)\nHOME=$HOME GH_TOKEN=\"\" gh api 'repos\u002Fjleechanorg\u002Fclaude-commands\u002Fpulls\u002F\u003CN>\u002Freviews' \\\n  --jq '[.[] | {state: .state, login: .user.login, submitted_at: .submitted_at}]'\n# Empty array = no real review was submitted = faux-green.\n```\n\n**Pattern (verified 2026-07-13, PR #327):** all three bots posted rate-limit comments within 60s\nof each other at PR creation; the status webhooks all showed `success`; the actual review array\nwas empty. Per `coderabbit-slow-bot-policy` in SOUL.md, this is non-blocking after ONE once-per-head\nreview attempt. Document the timeout in a PR comment with the same phrases the bots used, then\nproceed with the green-check + human-merge handoff.\n\n## Pitfall 5 — `git secret guard` output IS the security pre-check (added 2026-07-13)\n\nThe export script runs `git secret guard` on the outgoing range and prints to stdout. Look for:\n\n```\ngit secret guard: scanning outgoing range \u003CBASE>..\u003CHEAD> for refs\u002Fheads\u002F\u003CBRANCH>\n```\n\nA line WITHOUT a `FAIL` after it = clean. A line WITH `FAIL` or `WARNING` = block the PR until\nresolved. This is the ONLY security check the script does — there's no pre-commit hook or\nworkflow gate. If the script's stdout doesn't show this line at all, run `git secret scan\n\u003CBASE>..\u003CHEAD>` yourself before pushing.\n\n## Pitfall 6 — `localexportcommands.md` and `exportcommands.md` are DOCS, not scripts (added 2026-07-13)\n\nThree documents live in `~\u002F.claude\u002Fcommands\u002F`:\n\n| File | Role |\n|---|---|\n| `exportcommands.sh` (466 lines, 19.1K) | **The script.** Invoked by `\u002Fexportcommands`. |\n| `exportcommands.md` (45.1K) | **Operator doc** — explains what `\u002Fexportcommands` does, full superset spec, hermes-deploy-pipeline relationship. |\n| `localexportcommands.md` (23.2K) | **Local-only doc** — variant for projects that want to skip the global union and ship only their own `.claude\u002F` dir. |\n| `exportcommands.py` (96.4K) | Companion Python (alternative entry point; not invoked by `\u002Fexportcommands`). |\n| `tests\u002Ftest_exportcommands.py` | Contract tests for the Python entry. |\n\nWhen users say \"\u002Fexportcommands\", they mean the **bash script**, not the docs or the Python.\n\n## Pitfall 7 — The auto-opened PR has no `.github\u002Fworkflows\u002F` (verified 2026-07-13)\n\n`jleechanorg\u002Fclaude-commands` has CI at `.\u002Fworkflows\u002F*.yml`, NOT at `.github\u002Fworkflows\u002F`. Earlier\n`gh api .github\u002Fworkflows` returns 404 — that's expected. The CI is:\n\n- `workflows\u002Fcoderabbit-ping-on-push.yml` (CodeRabbit webhook ping)\n- `workflows\u002Fclaude-code.yml` (some Claude Code integration)\n- `workflows\u002Fclaude-processor.yml`\n- Plus 30+ others\n\nWhen driving an export PR to green, **don't look for `.github\u002Fworkflows\u002F`**. The \"green\" check\non this repo is:\n- `mergeable_state: clean` (REST pulls endpoint)\n- `statusCheckRollup` empty (no GH Actions runs on the export PR's head)\n- Real bot reviews OR documented rate-limit timeout per Pitfall 4\n\n## Pitfall 8 — Supersession comment template (verified 2026-07-13)\n\nWhen posting a supersession comment on a STALE PR (before closing), include:\n\n1. **Base staleness evidence** — the SHA the PR branched from and main's current SHA.\n2. **Per-file diff math** — total files, net-new, modified, main-only counts.\n3. **Why it's superseded** — concrete examples (empty files, security-leak files, files where\n   main has 4× the content).\n4. **Forward path** — where the incremental went instead (the new fresh-export PR).\n5. **Co-Authored-By** — Claude Code attribution.\n\n```markdown\n## Closing as superseded — consolidation audit findings\n\nAfter the merges of [PR #325](...) and [PR #326](...) landed on `main` @ `\u003CMAIN_SHA>`,\nthis PR's value collapsed. Detailed audit:\n\n### Diff math\n- Total files in #N: **\u003CN>** (vs current main)\n- Files in #N *only* (not in main): **\u003CX>** truly net-new (excluding `backup\u002F`, `.beads\u002F`, ...)\n- Files *modified* in #N vs main: **\u003CY>**\n- Files in main but not in #N: **\u003CZ>** (came from #N+1\u002F#N+2 merges)\n\nFor the \u003CY> files where #N differs from current main, main has ~\u003CM> MB of content vs #N's ~\u003Cm> MB.\n- `\u003Cfile_a>`, `\u003Cfile_b>` in this PR are **empty files**; main has the real implementations.\n- 29 `workflows\u002F*.yml` files predate the `security(backup)` gitignore; rebase reintroduces leaks.\n\n### Security incident this PR still contains\n`backup\u002F\u003CHOSTNAME>\u002F...` — \u003CN> files. The original 2026-07-12 home-config snapshot leak that\nprompted the `security: gitignore backup\u002F` commit. **Merging would re-introduce that leak.**\n\n### Recommendation\n- **`\u003Ckey feature>` is on main** (via [\u003CPR>](...) merge \u003CDATE>).\n- All remaining valuable content is **already represented** in main via #N+1+#N+2.\n\nClosing as superseded.\n\n? Generated with [Claude Code](https:\u002F\u002Fclaude.com\u002Fclaude-code). Co-Authored-By: Claude \u003Cnoreply@anthropic.com>\n```\n\n## Pitfall 9 — `\u002Fexportcommands` from a non-main branch (verified 2026-07-13)\n\nThe export script uses `git rev-parse --show-toplevel` to detect `PROJECT_ROOT`, NOT\n`--abbrev-ref HEAD`. So it works from any branch. BUT — if you're on `feat\u002Fissue-8084` with N\nuncommitted files, those files don't affect the export (uncommitted = not in worktree), but the\nexport still uses the WORKTREE'S HEAD for diff calculations.\n\n**Recipe:** if you want a \"true diff vs prior export\", check out the branch that matches the\nprior export's source state, run `\u002Fexportcommands` from there, then post the diff against the\nprior PR's branch. Verified 2026-07-13: running from `feat\u002Fissue-8084` produced PR #327 (66 files,\n+7,436\u002F−19) — clean against current main `337dc6d7`. Branch mismatch didn't corrupt anything\nbecause the union-merge ignores branch identity.\n\n## Pitfall 11 — Vendored-source re-sync staleness (verified 2026-08-01, PR #38 → #40)\n\nWhen the export bundles source files (Python scripts + tests) that originated in\na DIFFERENT upstream repo (e.g. `user_scope\u002Fscripts\u002Fcmux_resume_watchdog.py`\nre-shipped as `your-project.com\u002F.claude\u002Fskills\u002Fcmux-resume-watchdog\u002Fcmux_resume_watchdog.py`),\nthe export's snapshot has a *second* decay axis the existing 10 pitfalls don't\ncover: **the vendored copy can drift from upstream between export runs**. The\nsignal is the bug-by-bug re-discovery cycle:\n\n1. Run `\u002Fexportcommands` from your-project.com → snapshot of `cmux_resume_watchdog.py` from this exact moment lands in the export branch.\n2. Meanwhile, `user_scope` main advances (a real bug fix lands: 3 new quota regex anchors, 10 new network patterns).\n3. Live daemon on this machine is now running the upstream HEAD (auto-pulled by launchd), but the vendored copy in `your-project.com` (and downstream in `claude-commands`) is still pre-fix.\n4. The **first \u002Fadvice review** returns \"vendored copy is stale, missing 13 patterns\". Round-trip fix: re-copy from upstream, re-sync both PRs.\n5. **Second \u002Fadvice review** returns \"vendored test file uses `REPO_ROOT = Path(__file__).resolve().parents[1]`\" — but in the vendored location the script lives in `parents[0]`. **Every test fails on `importlib.SpecNotFound`.** Round-trip fix: patch REPO_ROOT in the vendored copy only.\n6. **Web-advice review** independently catches a fixture leak (`\"$USER@jeffreys-macbook-pro: ~\u002Fprojects\u002Fcold-reviewer\"` in a `Surface()` test fixture) that survived the SUBS filter because the regex `s|\\bjleechan\\b|$USER|g` rewrote `$USER` but the hostname + project path survived verbatim.\n\nThe cure (recipe, 2026-08-01):\n\n```bash\n# Phase A — re-sync the script AND its sibling test file\ncp $HOME\u002Fprojects\u002F\u003Cupstream>\u002Fscripts\u002F\u003Cscript>.py \\\n   $HOME\u002F.worktrees\u002F\u003Cexport-wt>\u002F.claude\u002Fskills\u002F\u003Cskill>\u002F\u003Cscript>.py\ncp $HOME\u002Fprojects\u002F\u003Cupstream>\u002Ftests\u002Ftest_\u003Cscript>.py \\\n   $HOME\u002F.worktrees\u002F\u003Cexport-wt>\u002F.claude\u002Fskills\u002F\u003Cskill>\u002Ftest_\u003Cscript>.py\n\n# Phase B — fix REPO_ROOT in the test file if it was authored for upstream's\n# tree layout (parents[N]) but the vendored location has a different depth.\n# Common case: upstream test does Path(__file__).resolve().parents[1] \u002F \"scripts\" \u002F X\n# → vendored test needs Path(__file__).resolve().parent \u002F X\n\n# Phase C — grep both files for fixture-style literals that the SUBS regex\n# won't catch (usernames, hostnames, project paths). Replace with placeholders.\n# Per SUBS spec (lines 220-260 of exportcommands.sh), `\\bjleechan\\b` is rewritten\n# to `$USER`, but `$USER@\u003Chostname>` is rewritten only on the prefix half.\n# Always run:\nrg -n '\\bjleechan\\b|@.*-macbook-pro|~\u002Fprojects\u002F[^\u002F]+\u002F' \\\n   $HOME\u002F.worktrees\u002F\u003Cexport-wt>\u002F.claude\u002Fskills\u002F\u003Cskill>\u002F\n\n# Phase D — run the test suite IN THE VENDORED LOCATION, not upstream\ncd $HOME\u002F.worktrees\u002F\u003Cexport-wt>\u002F.claude\u002Fskills\u002F\u003Cskill>\u002F\n~\u002F.local\u002Forch-venv\u002Fbin\u002Fpython3 -m pytest test_\u003Cscript>.py -q\n# Expect: same pass count as upstream, but RUN from this dir so the REPO_ROOT\n# lookup targets the vendored layout.\n\n# Phase E — only after test D passes, amend + force-push the export branches\ngit add .claude\u002Fskills\u002F\u003Cskill>\u002F\u003Cscript>.py .claude\u002Fskills\u002F\u003Cskill>\u002Ftest_\u003Cscript>.py\ngit commit --amend --no-edit\ngit push --force-with-lease=\u003Cexpected_old_sha> origin HEAD\n# Mirror to downstream (claude-commands export branch):\ncd $HOME\u002F.worktrees\u002F\u003Cdownstream-wt>\ncp ... same files ...\ngit add ... same files ...\ngit commit -m \"feat(skills\u002F\u003Cskill>): re-sync from \u003Cupstream> PR #N\"\ngit push origin HEAD\n```\n\nThree anti-patterns the recipe explicitly avoids:\n\n- ❌ **Re-running `\u002Fexportcommands`** to \"refresh\" the vendored copy — the export script does a UNION-MERGE of all skill files; if upstream's file is functionally newer than the export's, the union-merge may not even detect the change because the export's content filters rewrite upstream's bytes too. Re-run is the wrong tool.\n- ❌ **Patching only the script** (not the test file). The test file's `REPO_ROOT` resolution depends on the file's position in the vendored tree, which differs from upstream's tree. Always ship both files together.\n- ❌ **Trusting the SUBS regex to filter fixture leaks**. The regex is fine-grained for `$USER` standalone but mechanically blind to the surrounding context (`$USER@\u003Chost>`, `~\u002Fprojects\u002F\u003Cpath>\u002F`). Always run the Phase C leak grep after every re-sync.\n\n**The cross-vendor re-sync is a three-PR pipeline** (verified 2026-08-01):\n- Upstream: `jleechanorg\u002Fuser_scope` PR #40 — canonical fix lands here.\n- Source-side: `$GITHUB_REPOSITORY` PR #8681 — re-sync the vendored copy + force-push.\n- Downstream: `jleechanorg\u002Fclaude-commands` PR #346 — mirror the re-sync + push.\n\nAll three PRs must move together or the merge decouples. Force-push only to branches you own; use `gh pr view --json headRefName,author` to verify branch ownership before each `--force-with-lease=\u003Cexpected_old_sha>`.\n\n## Pitfall 12 — Content-filter regex rewrites BODY but not FILENAMES (verified 2026-08-01, install_cmux_resume_watchdog.sh)\n\nThe export's `perl -pi -e 's|...|...|g'` SUBS regexes rewrite CONTENT of filtered files in place. Filenames are NOT filtered. This is a sharp edge when an install script or shell wrapper does *both*:\n\n1. Defines a `LABEL=com.\u003Cgithubuser>.\u003Cskill>` constant in CONTENT (gets filter-rewritten to `LABEL=com.$USER.\u003Cskill>`).\n2. References `$SKILL_DIR\u002F$LABEL.\u003Cext>` to find a sibling file on disk (FILENAME on disk is NOT rewritten — still `com.\u003Cgithubuser>.\u003Cskill>.\u003Cext>`).\n\n**Symptom** (verified 2026-08-01, `install_cmux_resume_watchdog.sh:18`): script does `sed -e \"s|@HOME@|$HOME|g\" ... \"$SKILL_DIR\u002F$LABEL.plist.template\"` where `$LABEL` is post-filter `com.$USER.cmux-resume-watchdog` but the shipped template file is `com.$USER.cmux-resume-watchdog.plist.template`. The `set -euo pipefail` script aborts on `ls` returning empty — and **the install is broken for every downstream user**, not just the bad commit author.\n\n**Three cure recipes**, pick the one that matches the install script's structure:\n\n```bash\n# Recipe A — rename the file to be filter-stable (drop the user-name prefix).\n#   Before: com.$USER.cmux-resume-watchdog.plist.template\n#   After:  cmux-resume-watchdog.plist.template\n# Pros: zero install-script changes needed (the file path becomes predictable).\n# Cons: doesn't help if the script reaches for files by user-derived names.\n\n# Recipe B — use @PLACEHOLDER@ in the file's CONTENT and `sed \"s|@PLACEHOLDER@|$LABEL|g\"`\n# in the installer. The export's SUBS regex is non-greedy on `@` so `@LABEL@`,\n# `@DEST@`, `@HOME@` survive the filter intact.\n# Pros: any user-derived token can be parameterized without filter breakage.\n# Cons: the install script must explicitly run the sed pass; a literal-substitute\n#   installer will break.\n\n# Recipe C — pick a vendor-neutral name that doesn't contain the github username.\n#   com.localhost.\u003Cskill>           — stable across users; macOS launchd accepts\n#                                     labels with localhost domain; no filter\n#                                     rewrite is needed even if the content\n#                                     mentions the literal string.\n#   com.example.\u003Cskill>             — same idea\n# Pros: zero filter interaction at all.\n# Cons: many users' machines already have a com.\u003Ctheir-actual-github-user>.\u003Cskill>\n#   entry in \u002FLibrary\u002FLaunchAgents, so first install requires explicit bootout\n#   of the old label.\n```\n\n**Detection recipe** (run BEFORE every export of a skill that has shell installers):\n\n```bash\n# For every shell\u002Fscript file in the staged export, list every reference to a\n# github-username-prefixed file path:\nHOME=$HOME git -C $HOME\u002F.worktrees\u002F\u003Cexport-wt> diff --name-only \\\n  --diff-filter=AM HEAD~1..HEAD | grep -E '\\.(sh|bash|zsh|fish)$' | while read f; do\n    echo \"=== $f ===\"\n    grep -nE \"com\\\\.\\\\w+|com\\\\.\\\\\\$USER|\u002F\\\\\\$LABEL\u002F\\\\\\$|\\\\\\$SKILL_DIR\u002F\\\\\\$LABEL\" \"$f\"\n  done\n# Each \"Yes I do\" hit → apply Recipe A, B, or C above.\n```\n\n**The mental model:** filter rewrites apply to *content*. Any cross-reference between\na content-managed variable (like `LABEL=...`) and a filesystem name is a latent\nbreakage waiting for a fresh export on a different host. Audit every `ls $X`,\n`@file_template`, `$CONFIG_DIR\u002F...` reference for this property before pushing.\n\n## Pitfall 10 — The 5th archetype: cleanup-PR + script-patch workflow (added 2026-07-13)\n\nThe export script has **no exclude logic for content categories**. It's a copy-everything\nunion-merge. A fresh export will ship every file under `~\u002F.claude\u002Fskills\u002F_archive\u002F`,\n`~\u002F.claude\u002Fskills\u002F_archived_loose_md\u002F`, `.beads\u002F`, etc. — local history-keeping surfaces that\nshould never reach the public `jleechanorg\u002Fclaude-commands` repo.\n\nWhen the user says *\"remove the archive from the PR and modify \u002Fexportcommands to stop exporting\nit\"*, the correct response is a two-track atomic edit:\n\n### Track A — patch `exportcommands.sh` so future runs skip the category\n\nThe script has TWO union-merge surfaces plus an rsync for root-level dirs. Each needs its own\nexclude:\n\n```bash\n# Surface 1: union_dir() global find — add to the `\\( -not -path ... \\)` block\n\\( -not -path '*\u002F_archive\u002F*' \\) \\\n\n# Surface 2: union_dir() project find — same exclude, different anchor context\n\\( -not -path '*\u002F_archive\u002F*' \\) \\\n\n# Surface 3: rsync block for orchestration\u002Fautomation\u002Fralph — add to --exclude list\n--exclude='_archive\u002F' \\\n--exclude='*\u002F_archive' \\\n```\n\nThe script's `find` calls have ~25 lines of `--not -path` clauses between them — use unique\nsurrounding context (e.g. the `union_dir()` body or `while IFS= read -r -d '' f; do` lines) to\ndisambiguate. After patching, run `bash -n ~\u002F.claude\u002Fcommands\u002Fexportcommands.sh` to confirm syntax.\n\n**Smoke-test the patch** before pushing: extract the union_dir function and run it against a\nfixture with files in both `_archive\u002F` and non-`_archive\u002F` paths. Confirm the count of returned\nfiles matches the expected (non-archive) total.\n\n### Track B — amend the auto-opened PR to drop the unwanted content\n\nIn a fresh worktree of the PR branch:\n\n```bash\n# 1. Get the diff-list and identify files in the unwanted category\nHOME=$HOME git -C ~\u002Fworktrees\u002F\u003Cbranch> diff --name-only --diff-filter=AM HEAD~1..HEAD \\\n  | grep '\u003Cunwanted-category-pattern>' > \u002Ftmp\u002Frm_files.txt\n\n# 2. git rm the matching files\nHOME=$HOME git -C ~\u002Fworktrees\u002F\u003Cbranch> rm -rf $(cat \u002Ftmp\u002Frm_files.txt)\n\n# 3. Commit and force-push\nHOME=$HOME git -C ~\u002Fworktrees\u002F\u003Cbranch> commit -F \u003Ccommit-message-file>\nHOME=$HOME git -C ~\u002Fworktrees\u002F\u003Cbranch> push --force-with-lease origin \\\n  HEAD:refs\u002Fheads\u002F\u003Cbranch>\n```\n\n### CRITICAL — distinguish \"files I ADDED\" vs \"files main already had\"\n\nThe auto-opened PR may include files that **already existed on main** (in modified form, because\nthe export's content filters changed them by ~30 bytes). Removing those files wholesale will\nmake them disappear from main on merge, which is wrong.\n\n**Recipe to keep main's version intact** while still removing only the unwanted category:\n\n```bash\n# For each \"already-on-main\" file the script modified, restore it to main's exact bytes\ngit restore --source=\u003CMAIN_SHA> --staged --worktree -- \u003Cfile-path>\n\n# Verify byte identity before committing\ngit show \u003CMAIN_SHA>:\u003Cfile> | git hash-object --stdin\ncat \u003Cfile> | git hash-object --stdin\n# Both SHAs must match — if they differ by even 1 byte, the content-filter stripped a trailing newline\n```\n\n**Don't use `git checkout HEAD~1 -- \u003Cfile>`** — that restores to the export-PR's modified version\n(before the cleanup), not to main's original. `git restore --source=\u003CMAIN_SHA>` is the only path\nthat ensures zero net diff vs main.\n\n### Final shape\n\nAfter Track A + Track B, the PR diff shrinks from \"all categories\" to \"the actual incremental\nthe user wanted\". Verified 2026-07-13 with PR #327: original 66 files → 5 files after the\ncleanup. The 5-file PR contained exactly `\u002Fharness --optimize` flag, new `\u002Fslackbots` command,\n`\u002Fsocial` draft-only semantics, plus the two backing skill files.\n\n**Always close by posting a follow-up PR comment** that summarizes the cleanup (what was\nremoved, why, what the script patch prevents) — this is the durable record for future sessions\nand audit trails. CodeRabbit may now actually review the PR (since the bot rate limit resets\non push), so the post-cleanup push is also your chance to retrigger a real review.\n\n## The full sequence (execute in order, no pauses)\n\n### Phase 0 — Re-check state (Pitfall 1)\n\n```bash\nHOME=$HOME GH_TOKEN=\"\" gh api 'repos\u002Fjleechanorg\u002Fclaude-commands\u002Fpulls?state=open&per_page=20' \\\n  --jq '[.[] | {n: .number, title: .title, baseSha: .base.sha, mergeable: .mergeable, mergeable_state: .mergeable_state, headRefName: .head.ref, headSha: .head.sha, files: .changed_files, additions: .additions, deletions: .deletions, commits: .commits}]'\n\nHOME=$HOME GH_TOKEN=\"\" gh api 'repos\u002Fjleechanorg\u002Fclaude-commands\u002Fbranches\u002Fmain' \\\n  --jq '{main: .commit.sha, lastCommit: .commit.commit.message, lastCommitDate: .commit.commit.author.date}'\n```\n\nIf main advanced past the open PRs' bases, reclassify each open PR as:\n- **FRESH** — baseSha == main → drive to green directly\n- **STALE** — baseSha \u003C main → run Pitfall 2 audit (base audit + content audit)\n- **CLEANUP_NEEDED** — auto-opened export PR with files in unwanted categories → Pitfall 10\n- **AUTO-MERGED** — `state: closed, mergedAt: \u003Crecent>` → already in main, no action\n- **CLOSED-UNMERGED** — `state: closed, mergedAt: null` → archive, don't reopen\n\n### Phase 1 — Content audit on each STALE PR (Pitfall 2 + 3)\n\nFor each STALE PR, in a fresh clone:\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fclaude-commands.git \u002Ftmp\u002F\u003Cpurpose>-audit\ncd \u002Ftmp\u002F\u003Cpurpose>-audit\ngit fetch origin \u003Cbranch>\ngit checkout -B audit\u002F\u003Cpr-n> origin\u002F\u003Cbranch>\n\n# Per-file byte identity check (not just name overlap)\npython3 \u003C\u003C'PY'\nimport subprocess, os, time\n# ... fetch main's content + branch's content for each file in diff, compare bytes\nPY\n```\n\nThe output is one of:\n- **0 truly new files + N outdated files + security-leak files** → supersede\n- **\u003C10 truly new files + 0 outdated** → rebase + merge (preserves the unique work)\n- **Many new files, all in `.claude\u002F` not in `backup\u002F` etc** → rebase + merge\n- **Many new files in unwanted categories (`_archive\u002F`, etc.)** → Pitfall 10 cleanup-PR + script-patch\n\nIf supersede, post a detailed audit comment per the Pitfall 8 template.\n\n### Phase 2 — Run fresh \u002Fexportcommands (Pitfall 3 + 5)\n\n```bash\ncd ~\u002Fyour-project.com\nHOME=$HOME PROJECT_ROOT=$HOME\u002Fyour-project.com \\\n  bash $HOME\u002F.claude\u002Fcommands\u002Fexportcommands.sh\n```\n\nCapture:\n- Branch name (`export-YYYYMMDD-HHMMSS`)\n- Commit SHA\n- PR number (auto-opened)\n- `git secret guard` line (must be clean)\n- File count \u002F additions \u002F deletions\n\n### Phase 2.5 — (Optional) Cleanup-PR + script-patch (Pitfall 10)\n\nIf the auto-opened PR contains content the user wants excluded:\n\n1. Patch `~\u002F.claude\u002Fcommands\u002Fexportcommands.sh` (Track A) with the 3 exclude additions.\n2. Run `bash -n` to confirm syntax + a smoke-test fixture to confirm `find` no longer\n   picks up files in the unwanted category.\n3. In a fresh worktree, `git rm` the unwanted files, `git restore --source=\u003CMAIN_SHA>` the\n   already-on-main files that the script's content filters modified (Track B).\n4. `git commit --amend` to fold the restorations into the cleanup commit (or new commit).\n5. `git push --force-with-lease origin HEAD:refs\u002Fheads\u002F\u003Cbranch>`.\n6. Verify the PR's file list via REST: must show exactly the categories you want.\n\n### Phase 3 — Drive the new PR to green (Pitfall 4 + 7)\n\n```bash\n# REST (GraphQL is rate-limited; use REST for state)\nHOME=$HOME GH_TOKEN=\"\" gh api \"repos\u002Fjleechanorg\u002Fclaude-commands\u002Fpulls\u002F\u003CN>\" \\\n  --jq '{mergeable: .mergeable, mergeable_state: .mergeable_state, headSha: .head.sha, baseSha: .base.sha, changed_files: .changed_files, additions: .additions, deletions: .deletions}'\n\n# Bot faux-green check\nHOME=$HOME GH_TOKEN=\"\" gh api \"repos\u002Fjleechanorg\u002Fclaude-commands\u002Fissues\u002F\u003CN>\u002Fcomments?per_page=10\" \\\n  --jq '[.[] | {login: .user.login, body: .body[:150]}] | map(select(.login | test(\"coderabbit|cursor|chatgpt-codex\"; \"i\")))'\n\n# Status webhook (often shows success despite no real review)\nHOME=$HOME GH_TOKEN=\"\" gh api \"repos\u002Fjleechanorg\u002Fclaude-commands\u002Fcommits\u002F\u003CHEAD_SHA>\u002Fstatus\" \\\n  --jq '{state: .state, contexts: [.statuses[] | {context: .context, state: .state}]}'\n```\n\nIf bots rate-limited → post a documentation comment per the template in Pitfall 4 (cite\n`coderabbit-slow-bot-policy` from SOUL.md, ping `@coderabbitai` to retrigger, set a 2h SLA).\n\nIf bots substantive and CHANGES_REQUESTED → fix inline (the export script's content is generated,\nnot authored, so fixes are usually trivial content adjustments — re-run the script).\n\nIf bots substantive and APPROVED → ready to merge.\n\n### Phase 4 — Supersede any STALE PR (Pitfall 8)\n\nDo NOT close the STALE PR before the new fresh-export PR is verified clean. Close order matters:\nif you close #324 first and the new export PR turns out to be wrong, you've burned your reference\nstate. Post the supersession comment, leave the PR open until the new one is green, then close.\n\n### Phase 5 — Final reply (Slack thread + PR description)\n\nSame shape as `drive-pr-to-green` Step 10 — single reply with PR URL, gate-by-gate verdicts, and\nthe per-PR supersession receipts. Cite each bot's rate-limit timeout in the reply so the user\nknows why a \"green\" PR has no real review. If Phase 2.5 ran, include the script-patch path\n(`~\u002F.claude\u002Fcommands\u002Fexportcommands.sh` line ranges + before\u002Fafter file count) so the user can\nsee the durable prevention fix.\n\n## References\n\n- `references\u002Fsessions-recap.md` — session-by-session audit of what was learned across 2026-07-01, 2026-07-02, 2026-07-06, 2026-07-13 (1st cleanup session)\n- `references\u002Fcleanup-archetype-recipe.md` — detailed Track A (script-patch) + Track B (PR cleanup) workflow with the 5-file vs 66-file PR case study\n- `references\u002Fexportcommands-sh-contract.md` — full content-filter + union-merge spec extracted from the live script\n- `references\u002Fcross-vendor-resync-recipe.md` — Pitfall 11 deep-dive: the three-bug cycle (stale source → REPO_ROOT break → fixture leak) when an exported skill bundles code from a different upstream repo, with verified recipe (Phases A-F)\n- `references\u002Frouting-eval.jsonl` — `{intent, expected_skill, ambiguous_with?}` fixture for skill resolver routing evals\n\n## Resolver Trigger Entry\n\nFor the resolver, the heading line MUST contain the user-typed trigger phrases on the same line as the `##` heading. Add this entry to `~\u002F.hermes\u002Fskills\u002FRESOLVER.md` (the canonical resolver graph):\n\n```markdown\n## claude-commands-export-superset — consolidate claude-commands PRs, run fresh \u002Fexportcommands, cleanup-PR + script-patch to exclude categories, supersede stale PRs, drive to green\ntriggers: consolidate the open claude-commands PRs, fresh \u002Fexportcommands and check the PRs, the export is stale, see what else is needed \u002F what's incremental, supersede #N, \u002Fexportcommands from ~\u002Fyour-project.com, the cmux-goal \u002F ironclad pair isn't on main, the latest commands\u002Fskills aren't in jleechanorg\u002Fclaude-commands, run a fresh export of my claude config, audit the open export PRs, close #N as superseded, remove the archive from the PR and modify \u002Fexportcommands to stop exporting it, edit the export to exclude _archive\u002F, stop exporting archive paths, drop the archive from this PR\n```\n\n## Skills Index \u002F Discovery\n\nThis skill is referenced by \u002F related to:\n\n- `drive-pr-to-green` — general PR-to-green workflow; we use it for the new export PR's Phase 3 (faux-green detection)\n- `github-pr-automation-debug` — explains the bot-authoring pattern; useful for the Phase 3 bot rate-limit faux-green check\n- `github-pr-workflow` — low-level `gh pr` helpers used throughout Phases 0–4\n- `patch-tool-safe-editing` — relevant for the script-patch phase (Pitfall 10 Track A); the union-merge script has 3 surfaces with shared `\\( -not -path ... \\)` patterns that require unique surrounding context to disambiguate\n\nThe class is distinct from those because:\n1. The export script's auto-opened PR has **specific union-merge semantics** that other PRs don't (Pitfall 3, 5)\n2. The `mergeable_state: dirty` audit is **content-driven** not just branch-driven (Pitfall 2)\n3. The bot faux-green pattern shows up **reliably on every auto-opened export PR** (Pitfall 4)\n4. Supersession is a **first-class action** in this workflow, unlike other PR workflows\n5. Cleanup-PR + script-patch is the 5th archetype for content categories that should never have shipped (Pitfall 10)",{"name":5,"version":64,"metadata":65,"platforms":80,"description":83},"1.2.0",{"hermes":66},{"tags":67,"related_skills":76},[68,69,28,70,49,55,71,72,73,74,75],"github","claude-commands","supersession","drive-pr-to-green","exclude-paths","script-patch","vendoring","cross-vendor-sync",[71,77,78,79],"github-pr-automation-debug","github-pr-workflow","patch-tool-safe-editing",[81,82],"macos","linux","Audit, rebase, supersede, and ship the jleechanorg\u002Fclaude-commands export pipeline.\nFive-session playbook covering consolidation, supersession, fresh export, AND the\ncleanup-PR + script-patch archetype (Pitfall 10) for excluding content categories like\n`_archive\u002F` that should never have shipped. v1.2.0 adds Pitfalls 11 + 12 covering\ncross-vendor re-sync staleness (vendored copy drifts from upstream between exports)\nand content-filter rewrites BODY-but-not-FILENAMES (install scripts that reference\nfilter-rewritten filenames break at install time). Triggers on \"consolidate the open\nclaude-commands PRs\", \"fresh \u002Fexportcommands\", \"remove the archive from the PR and\nmodify \u002Fexportcommands to stop exporting it\", \"supersede #N\", \"edit the export to\nexclude _archive\u002F\", \"the cmux-goal pair isn't on main\", \"re-sync the vendored\nwatchdog\", \"stale cmux_resume_watchdog in the export\", \"install script fails\nwith no such file\", \"com.$USER.cmux-resume-watchdog.plist not found\", etc.\nEncodes twelve pitfalls.\n","main","42ccd02cbf5e8e47839dc3eab6fc754dc6b339cf","hermes\u002Fskills\u002Fgithub\u002Fclaude-commands-export-superset",0,"https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills","https:\u002F\u002Fgithub.com\u002Fjleechanorg","2026-11-12 14:45:07",{"source":8,"skillName":5,"commands":92,"prompt":102,"zipAvailable":103},[93,96,99],{"tool":94,"command":95},"npx","npx skills add jleechanorg\u002Fjleechan-skills --skill claude-commands-export-superset",{"tool":97,"command":98},"bunx","bunx skills add jleechanorg\u002Fjleechan-skills --skill claude-commands-export-superset",{"tool":100,"command":101},"pnpm","pnpm dlx skills add jleechanorg\u002Fjleechan-skills --skill claude-commands-export-superset","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002Fhermes\u002Fskills\u002Fgithub\u002Fclaude-commands-export-superset\u002FSKILL.md",true,[105,111,115,119],{"path":106,"resourceType":107,"resourceTypeDesc":108,"sizeBytes":109,"sourceHtmlUrl":110},"references\u002Fcleanup-archetype-recipe.md","REFERENCE","参考文档",8454,"https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002Fhermes\u002Fskills\u002Fgithub\u002Fclaude-commands-export-superset\u002Freferences\u002Fcleanup-archetype-recipe.md",{"path":112,"resourceType":107,"resourceTypeDesc":108,"sizeBytes":113,"sourceHtmlUrl":114},"references\u002Fcross-vendor-resync-recipe.md",11198,"https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002Fhermes\u002Fskills\u002Fgithub\u002Fclaude-commands-export-superset\u002Freferences\u002Fcross-vendor-resync-recipe.md",{"path":116,"resourceType":107,"resourceTypeDesc":108,"sizeBytes":117,"sourceHtmlUrl":118},"references\u002Fexportcommands-sh-contract.md",6353,"https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002Fhermes\u002Fskills\u002Fgithub\u002Fclaude-commands-export-superset\u002Freferences\u002Fexportcommands-sh-contract.md",{"path":120,"resourceType":107,"resourceTypeDesc":108,"sizeBytes":121,"sourceHtmlUrl":122},"references\u002Fsessions-recap.md",9818,"https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002Fhermes\u002Fskills\u002Fgithub\u002Fclaude-commands-export-superset\u002Freferences\u002Fsessions-recap.md",[124,142,159,173,186,202],{"skillNo":125,"name":126,"nameZh":6,"description":127,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":128,"categories":129,"keywords":130,"publishedAt":59},"01M716Y5MTJ6GYJZ2ATXCJK8G4","instinct","Use when the user invokes \u002Finstinct or \u002Fin, or asks to \"message Instinct\", \"ask Instinct\", \"tell Instinct\", \"check Instinct\", or read replies from the configured peer assistant. iMessage first, WhatsApp Web as fallback.","https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Finstinct\u002FSKILL.md",[],[126,131,132,133,134,135,136,137,138,139,140,141],"user","when","replies","check","use","identity","whatsapp","gmail","read","message","ask",{"skillNo":143,"name":144,"nameZh":6,"description":145,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":146,"categories":147,"keywords":149,"publishedAt":59},"01M716Y4HF7FVVMJSA2CCVN5VF","hr","Compatibility alias for history-resume; produce the same fresh-state, provenance-aware resume briefing.","https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fhr\u002FSKILL.md",[148],{"categoryNo":23,"categoryName":24,"taxonomyType":25,"taxonomyTypeDesc":26},[144,150,151,152,153,154,155,156,157,158,36],"resume","compatibility","provenance","for","history","produce","alias","briefing","state",{"skillNo":160,"name":161,"nameZh":6,"description":162,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":163,"categories":164,"keywords":166,"publishedAt":59},"01M716Y1FFNFKFJYYKF8HQA6T8","history-resume","Resume briefing for the current repository branch or worktree using fresh state and admitted history sources.","https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fhistory-resume\u002FSKILL.md",[165],{"categoryNo":23,"categoryName":24,"taxonomyType":25,"taxonomyTypeDesc":26},[154,150,167,168,131,169,157,170,153,171,172,158,36],"history resume","branch","analysis","repository","worktree","sources",{"skillNo":174,"name":175,"nameZh":6,"description":176,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":177,"categories":178,"keywords":179,"publishedAt":59},"01M716XWXJ8EPHK4RH9T14TR85","grok","Alias for the canonical grokbot browser conversation workflow; \u002Fgrok talks to the Grok bot the same way \u002Fdot talks to Dot.","https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fgrok\u002FSKILL.md",[],[175,180,181,58,153,182,156,183,184,185],"dot","bot","canonical","conversation","browser","grokbot",{"skillNo":187,"name":188,"nameZh":6,"description":189,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":190,"categories":191,"keywords":192,"publishedAt":59},"01M70N9Q07DTE0EW5KFXMMMSJ0","codexa-bench","Compare `codexa` and normal `codex` on a fair split of comparable work by default; use `--strict` for duplicate runs of the exact same task.","https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fcodexa-bench\u002FSKILL.md",[],[193,194,195,135,196,153,197,198,199,200,201],"codexa bench","work","split","default","duplicate","task","compare","normal","codex",{"skillNo":203,"name":204,"nameZh":6,"description":205,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":206,"licenseFileUrl":207,"sourceHtmlUrl":208,"categories":209,"keywords":219,"publishedAt":59},"01M6C24S2X60SP8BBFGAEKPEGW","frontend-design","Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML\u002FCSS layouts, or when styling\u002Fbeautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Ffrontend-design\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Ffrontend-design\u002FSKILL.md",[210,213,216],{"categoryNo":211,"categoryName":212,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000009","前端开发",{"categoryNo":214,"categoryName":215,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000015","视觉设计",{"categoryNo":217,"categoryName":218,"taxonomyType":25,"taxonomyTypeDesc":26},"01JBSEEDCAT000000000000032","设计师",[220,221,222,135,223,224,225,131,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,132,244],"frontend","design","frontend design","generic","ui design","react","html","components","code","artifacts","ui","aesthetics","Production","web components","landing","applications","quality","web","css","create","examples","with","react components","web ui","pages"]