From 96c2fbcd1807e4e182403b394b6614290c8b53e7 Mon Sep 17 00:00:00 2001 From: James Wiesebron Date: Fri, 21 Aug 2026 10:55:51 -0700 Subject: [PATCH 1/6] [jwbron/review-readme-manual-merge] review: stop recommending gh aw update in the consumer README The README told consumers to pull updates with gh aw update in 4 places. The review-consumer-bump skill (#357) documents it failing twice against this repo's tag scheme, both observed live on 2026-08-20: it treats review-v as a branch and repins to main's head SHA, and its 3-way merge emptied a consumer's installed review.md to 0 bytes (gh-aw v0.85.4). All 4 spots now describe the maintainer-driven bump flow (a manual git merge-file 3-way merge, one PR per consumer) and the install section names the failure modes so nobody rediscovers them. Follow-up from the #357 review; lands independently of #357, the skill-path reference just dangles for whichever merges first. --- .changeset/readme-no-gh-aw-update.md | 5 +++++ workflows/review/README.md | 17 +++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 .changeset/readme-no-gh-aw-update.md diff --git a/.changeset/readme-no-gh-aw-update.md b/.changeset/readme-no-gh-aw-update.md new file mode 100644 index 00000000..98fe6fb2 --- /dev/null +++ b/.changeset/readme-no-gh-aw-update.md @@ -0,0 +1,5 @@ +--- +"review": patch +--- + +Docs only: stop recommending `gh aw update` in the consumer-facing README. The review-consumer-bump skill (Khan/actions#357) documents it failing twice against this repo's tag scheme, observed live on 2026-08-20: it treats `review-v` as a branch and repins to main's head SHA, and its 3-way merge emptied a consumer's installed `review.md` to 0 bytes (gh-aw v0.85.4). The README told consumers to run it in 4 places; all 4 now describe the maintainer-driven bump flow (a manual `git merge-file` 3-way merge, one PR per consumer) and name the failure modes. No change to the shipped review workflow. diff --git a/workflows/review/README.md b/workflows/review/README.md index 1ad95ab5..663ecd54 100644 --- a/workflows/review/README.md +++ b/workflows/review/README.md @@ -178,13 +178,18 @@ gh aw add Khan/actions/workflows/review/review.md@review-v..` tag pins its own `pre-agent-steps` checkout `ref:` to that same version (the release -flow rewrites it; see [Versioning](#versioning)), so after `gh aw add` or -`gh aw update` the imported file already fetches the matching lib code and needs +flow rewrites it; see [Versioning](#versioning)), so after `gh aw add` or a +version bump the imported file already fetches the matching lib code and needs no manual fix-up of the ref. ### Onboarding a whole repo @@ -271,7 +276,7 @@ main workflow would override the import and discard your allowlist. Repo-specific frontmatter that imports can't merge (e.g. an `if:` condition to skip deploy/automation branches or forks) goes directly in your installed `review.md` as -a local edit; `gh aw update` preserves it. +a local edit; the bump merge preserves it. ### Per-lens payloads (`lenses/.md`) @@ -789,7 +794,7 @@ Two known interactions: rejects it, and the agent job dies at startup instead of skipping trace export (observed on Khan/actions#241). A repo without these secrets must comment out the `observability:` block in its installed `review.md` as a - local edit (which `gh aw update` preserves) and recompile. + local edit (which the bump merge preserves) and recompile. Optional: From 9c901e35317a1b0e401323a4be0b4a8f70073cc6 Mon Sep 17 00:00:00 2001 From: James Wiesebron Date: Fri, 21 Aug 2026 11:35:34 -0700 Subject: [PATCH 2/6] [jwbron/review-readme-manual-merge] review: ban gh aw update everywhere, not just the README The review on #371 found the onboarding skill still recommended gh aw update in 4 places and the shipped review.md observability comment in 1 more, so fixing the README alone relocated the inconsistency instead of removing it. Port #357's wording for the skill's 4 spots and the shipped comment verbatim (its rebase then collapses to just the new consumer-bump skill), fix the same comment in this repo's own install and recompile the lock with gh-aw v0.85.4 (the diff is the frontmatter hash line only), point the dangling skill path at #357, and give the README ban a revisit condition: neither failure is filed upstream (searched github/gh-aw issues, no reports), so re-test on a scratch install before trusting a newer gh-aw release. --- .changeset/readme-no-gh-aw-update.md | 2 +- .claude/skills/review-onboarding/SKILL.md | 15 +++++++++++---- .github/workflows/review.lock.yml | 2 +- .github/workflows/review.md | 2 +- workflows/review/README.md | 6 ++++-- workflows/review/review.md | 2 +- 6 files changed, 19 insertions(+), 10 deletions(-) diff --git a/.changeset/readme-no-gh-aw-update.md b/.changeset/readme-no-gh-aw-update.md index 98fe6fb2..c99d6d11 100644 --- a/.changeset/readme-no-gh-aw-update.md +++ b/.changeset/readme-no-gh-aw-update.md @@ -2,4 +2,4 @@ "review": patch --- -Docs only: stop recommending `gh aw update` in the consumer-facing README. The review-consumer-bump skill (Khan/actions#357) documents it failing twice against this repo's tag scheme, observed live on 2026-08-20: it treats `review-v` as a branch and repins to main's head SHA, and its 3-way merge emptied a consumer's installed `review.md` to 0 bytes (gh-aw v0.85.4). The README told consumers to run it in 4 places; all 4 now describe the maintainer-driven bump flow (a manual `git merge-file` 3-way merge, one PR per consumer) and name the failure modes. No change to the shipped review workflow. +Docs only: stop recommending `gh aw update` anywhere in this repo. The review-consumer-bump skill (Khan/actions#357) documents it failing twice against this repo's tag scheme, observed live on 2026-08-20: it treats `review-v` as a branch and repins to main's head SHA, and its 3-way merge emptied a consumer's installed `review.md` to 0 bytes (gh-aw v0.85.4). The consumer-facing README recommended it in 4 places and the review-onboarding skill in another 4; all 8 now describe the maintainer-driven bump flow (a manual `git merge-file` 3-way merge, one PR per consumer) and the README names the failure modes plus the condition for revisiting the ban (neither failure is filed upstream yet). The shipped `review.md` changes only in a frontmatter comment (the observability local-edit note no longer names `gh aw update` as the merger); no behavior change. diff --git a/.claude/skills/review-onboarding/SKILL.md b/.claude/skills/review-onboarding/SKILL.md index 327793f9..36cb2aef 100644 --- a/.claude/skills/review-onboarding/SKILL.md +++ b/.claude/skills/review-onboarding/SKILL.md @@ -168,7 +168,9 @@ listing the secrets the workflow references. Review each one before passing ## Step 2: local edits to the installed `review.md` -`gh aw update` preserves local edits via 3-way merge, so these survive upgrades. +Upgrades preserve local edits via a 3-way merge (the manual `git merge-file` +flow in `.claude/skills/review-consumer-bump/SKILL.md`, not `gh aw update`, +which mishandles the `review-v*` tag scheme), so these survive version bumps. Label each one with a ` LOCAL OVERRIDE:` comment saying *why*, so the next reader and the next merge conflict both have the reasoning. @@ -351,7 +353,7 @@ reviews nothing. | File | Lines | Regenerated by | | --- | --- | --- | - | `.github/workflows/review.md` | ~3000 | `gh aw update` (verbatim from the tag, except the local edits) | + | `.github/workflows/review.md` | ~3000 | 3-way merge per `review-consumer-bump` (verbatim from the tag, except the local edits) | | `.github/workflows/review.lock.yml` | ~1900 | `gh aw compile` — the workflow GitHub actually runs | | `.github/workflows/agentics-maintenance.yml` | ~600 | `gh aw compile` — gh-aw housekeeping | | `.github/aw/actions-lock.json` | ~15 | `gh aw compile` — third-party action SHA pins | @@ -424,10 +426,15 @@ the diff shows what a version bump changed. ```sh cd && git switch -c bump-shared-pr-reviewer -gh aw update # 3-way merge; preserves the Step 2 local edits +# 3-way merge per .claude/skills/review-consumer-bump/SKILL.md -- NOT `gh aw update`, +# which repins review-v* tags to main's head SHA and once emptied review.md to 0 bytes gh aw compile # --approve only after reviewing any new secret ``` +The merge mechanics, the compile side effects to keep or revert, and the +full verification list live in `.claude/skills/review-consumer-bump/SKILL.md`; +this section covers only what an update means for a repo this skill onboarded. + Then, in this order, because each step can invalidate the next: 1. **Read the release notes between the two versions** @@ -435,7 +442,7 @@ Then, in this order, because each step can invalidate the next: the new one). Semver is a behaviour contract here: a minor can change what gets reviewed, what a label means, or what the router does with an existing `ROUTING` line. This is the step that tells you what to look for in the rest. -2. **Confirm every local edit survived the merge.** `gh aw update` preserves them, +2. **Confirm every local edit survived the merge.** The merge preserves them, but "preserved" is not "still correct", and a conflict resolved badly is silent. Diff the installed `review.md` against the new tag's copy and check that what differs is exactly the Step 2 list and nothing else: diff --git a/.github/workflows/review.lock.yml b/.github/workflows/review.lock.yml index a8eb7fa1..e56ca7b0 100644 --- a/.github/workflows/review.lock.yml +++ b/.github/workflows/review.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"2697a35c593e8c4b5d4dc87c4d5ece790c4cf0ecf30ab17245b8cf8df137764e","body_hash":"9c724f09745cbf20d35a1d3b95a337a12c0c0149d5f35a5a497b44e3c91dad0e","compiler_version":"v0.85.4","strict":true,"agent_id":"claude","agent_model":"claude-opus-5","engine_versions":{"claude":"2.1.222"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"78268e0aef8af2d217404837fda98bde61571a7d1a5b6ebfb9ee96e4eaf97cee","body_hash":"9c724f09745cbf20d35a1d3b95a337a12c0c0149d5f35a5a497b44e3c91dad0e","compiler_version":"v0.85.4","strict":true,"agent_id":"claude","agent_model":"claude-opus-5","engine_versions":{"claude":"2.1.222"}} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","KHAN_ACTIONS_BOT_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/cache/save","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/checkout","sha":"93cb6efe18208431cddfb8368fd83d5badbf9bfd","version":"93cb6efe18208431cddfb8368fd83d5badbf9bfd"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"2709137ea6c5b0e19aa621454dc643ea8dc526b1","version":"v0.85.4"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.44","digest":"sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.44@sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.44","digest":"sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.44@sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.44","digest":"sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.44@sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.8","digest":"sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196","pinned_image":"ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196"},{"image":"ghcr.io/github/github-mcp-server:v1.8.0","digest":"sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520","pinned_image":"ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520"}],"has_pull_request":true} # This file was automatically generated by gh-aw (v0.85.4). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # diff --git a/.github/workflows/review.md b/.github/workflows/review.md index 287c10e1..6ad6dfe7 100644 --- a/.github/workflows/review.md +++ b/.github/workflows/review.md @@ -165,7 +165,7 @@ network: # Both secrets are hard-required while this block is present: a missing one compiles to # an empty value that the MCP gateway's OTLP config schema rejects, so the agent job # dies at startup instead of skipping trace export. A repo without them must comment -# this block out in its installed review.md (a local edit `gh aw update` preserves) +# this block out in its installed review.md (a local edit the 3-way merge update flow preserves) # and recompile. # # KHAN/ACTIONS LOCAL OVERRIDE: the `observability:` block is disabled here because this diff --git a/workflows/review/README.md b/workflows/review/README.md index 663ecd54..9c86b35e 100644 --- a/workflows/review/README.md +++ b/workflows/review/README.md @@ -181,10 +181,12 @@ This copies `review.md` into the consuming repo's `.github/workflows/`, records plus the consumer config files below. Version bumps arrive as PRs from the maintainers: a manual `git merge-file` 3-way merge that preserves your local edits (the playbook is `.claude/skills/review-consumer-bump/SKILL.md` in this -repo). Do not run `gh aw update` yourself: it treats `review-v*` tags as +repo, landing via [Khan/actions#357](https://github.com/Khan/actions/pull/357)). +Do not run `gh aw update` yourself: it treats `review-v*` tags as branches and repins to main's head commit as a raw SHA, and its own merge once emptied an installed `review.md` to 0 bytes (both observed on gh-aw -v0.85.4). +v0.85.4; neither failure is filed upstream yet, so re-test both on a scratch +install before trusting a newer gh-aw release with this). The tag is self-consistent: the `review.md` inside each `review-v` tag pins its own `pre-agent-steps` checkout `ref:` to that same version (the release diff --git a/workflows/review/review.md b/workflows/review/review.md index 536b035b..357610bc 100644 --- a/workflows/review/review.md +++ b/workflows/review/review.md @@ -158,7 +158,7 @@ network: # Both secrets are hard-required while this block is present: a missing one compiles to # an empty value that the MCP gateway's OTLP config schema rejects, so the agent job # dies at startup instead of skipping trace export. A repo without them must comment -# this block out in its installed review.md (a local edit `gh aw update` preserves) +# this block out in its installed review.md (a local edit the 3-way merge update flow preserves) # and recompile. observability: otlp: From 5c6893eb468e551bd4e7fb0fe051c1c2ccb507fb Mon Sep 17 00:00:00 2001 From: James Wiesebron Date: Mon, 24 Aug 2026 09:47:08 -0700 Subject: [PATCH 3/6] review: sweep the last runtime gh aw update mention; give the update block a stop line Two review catches: check-consumer-config's source-missing warning still framed gh aw update as the update mechanism (the one place a consumer met the stale recommendation at runtime rather than in prose), and the onboarding skill's update block had lost its only merge step, so following it literally recompiled an unmerged install and every later step silently passed on an empty diff. The warning now cites the reason source: still matters (the manual bump flow reads it), and the block carries an explicit unrunnable stop line where the merge command used to be. --- .claude/skills/review-onboarding/SKILL.md | 1 + workflows/review/lib/check-consumer-config.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.claude/skills/review-onboarding/SKILL.md b/.claude/skills/review-onboarding/SKILL.md index 36cb2aef..248ddbaa 100644 --- a/.claude/skills/review-onboarding/SKILL.md +++ b/.claude/skills/review-onboarding/SKILL.md @@ -428,6 +428,7 @@ the diff shows what a version bump changed. cd && git switch -c bump-shared-pr-reviewer # 3-way merge per .claude/skills/review-consumer-bump/SKILL.md -- NOT `gh aw update`, # which repins review-v* tags to main's head SHA and once emptied review.md to 0 bytes + gh aw compile # --approve only after reviewing any new secret ``` diff --git a/workflows/review/lib/check-consumer-config.ts b/workflows/review/lib/check-consumer-config.ts index 9b38dcc1..b03b7100 100644 --- a/workflows/review/lib/check-consumer-config.ts +++ b/workflows/review/lib/check-consumer-config.ts @@ -537,7 +537,7 @@ export const checkConsumerConfig = ( if (installed.source === undefined) { warn( "source-missing", - `${workflowPath} carries no \`source:\` field, so \`gh aw update\` cannot find its upstream.`, + `${workflowPath} carries no \`source:\` field, so the manual bump flow cannot tell which upstream release this install was copied from.`, ); } else if (installed.pinnedRef === undefined) { warn( From bb9af8994585db7bccf18fb33b8ed20f9e7efe74 Mon Sep 17 00:00:00 2001 From: James Wiesebron Date: Mon, 24 Aug 2026 11:15:26 -0700 Subject: [PATCH 4/6] review: rewrite the changeset for the post-#357 diff; make the stop line a comment Two findings from a reviewer run the dispatch gate blocked before posting (run 32758584548; the gate report carries them). The changeset still described the repo-wide sweep #357 already landed, crediting this release with edits it did not make; it now describes only this PR's remaining diff. And the line inside the sh fence was shell-hostile: bash parses it as a redirect, so a paste errors on that line and runs gh aw compile anyway. It is now a # comment, paste-safe and matching the two comment lines above it. --- .changeset/readme-no-gh-aw-update.md | 2 +- .claude/skills/review-onboarding/SKILL.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/readme-no-gh-aw-update.md b/.changeset/readme-no-gh-aw-update.md index c99d6d11..24d1e1b0 100644 --- a/.changeset/readme-no-gh-aw-update.md +++ b/.changeset/readme-no-gh-aw-update.md @@ -2,4 +2,4 @@ "review": patch --- -Docs only: stop recommending `gh aw update` anywhere in this repo. The review-consumer-bump skill (Khan/actions#357) documents it failing twice against this repo's tag scheme, observed live on 2026-08-20: it treats `review-v` as a branch and repins to main's head SHA, and its 3-way merge emptied a consumer's installed `review.md` to 0 bytes (gh-aw v0.85.4). The consumer-facing README recommended it in 4 places and the review-onboarding skill in another 4; all 8 now describe the maintainer-driven bump flow (a manual `git merge-file` 3-way merge, one PR per consumer) and the README names the failure modes plus the condition for revisiting the ban (neither failure is filed upstream yet). The shipped `review.md` changes only in a frontmatter comment (the observability local-edit note no longer names `gh aw update` as the merger); no behavior change. +Docs only, following up on the `gh aw update` ban Khan/actions#357 landed. The consumer-facing README now names the gh-aw version both failures were observed on (v0.85.4) and the condition for revisiting the ban: neither failure is filed upstream yet, so re-test both on a scratch install before trusting a newer gh-aw release. The consumer-config checker's `source-missing` warning no longer frames `gh aw update` as the update mechanism; it now cites the reason `source:` still matters (the manual bump flow reads it to tell which release the install was copied from). The onboarding skill's update block gains an explicit stop comment between the merge instructions and `gh aw compile`, so a reader cannot run the block straight through and recompile an unmerged install. This repo's own installed `review.md` changes only in a frontmatter comment (the observability local-edit note no longer names `gh aw update` as the merger; lock recompiled); no behavior change. diff --git a/.claude/skills/review-onboarding/SKILL.md b/.claude/skills/review-onboarding/SKILL.md index 248ddbaa..ec5dbe91 100644 --- a/.claude/skills/review-onboarding/SKILL.md +++ b/.claude/skills/review-onboarding/SKILL.md @@ -428,7 +428,7 @@ the diff shows what a version bump changed. cd && git switch -c bump-shared-pr-reviewer # 3-way merge per .claude/skills/review-consumer-bump/SKILL.md -- NOT `gh aw update`, # which repins review-v* tags to main's head SHA and once emptied review.md to 0 bytes - +# STOP HERE: run the 3-way merge from that skill and commit it, then return gh aw compile # --approve only after reviewing any new secret ``` From ccfbda9c9c3f2934d782a4736056bd464ee51ce9 Mon Sep 17 00:00:00 2001 From: James Wiesebron Date: Mon, 24 Aug 2026 11:39:08 -0700 Subject: [PATCH 5/6] review: soften the stop-comment claim, put the revisit condition in the bump skill, guard the ban in CI Three from the latest round plus the earlier fold: the changeset claimed a shell comment makes running the block straight through impossible (it cannot; the claim ships verbatim as the CHANGELOG entry, so it is softened to what the comment does), the no-expiry/re-test-on-scratch-install condition now lives in the bump skill the operator actually follows rather than only the consumer README, and a new test pins every tracked gh aw update mention to the files that ban it, so re-recommending the tool anywhere fails red. --- .changeset/readme-no-gh-aw-update.md | 2 +- .claude/skills/review-consumer-bump/SKILL.md | 4 ++ workflows/review/gh-aw-update-ban.test.ts | 65 ++++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 workflows/review/gh-aw-update-ban.test.ts diff --git a/.changeset/readme-no-gh-aw-update.md b/.changeset/readme-no-gh-aw-update.md index 24d1e1b0..dfb9333c 100644 --- a/.changeset/readme-no-gh-aw-update.md +++ b/.changeset/readme-no-gh-aw-update.md @@ -2,4 +2,4 @@ "review": patch --- -Docs only, following up on the `gh aw update` ban Khan/actions#357 landed. The consumer-facing README now names the gh-aw version both failures were observed on (v0.85.4) and the condition for revisiting the ban: neither failure is filed upstream yet, so re-test both on a scratch install before trusting a newer gh-aw release. The consumer-config checker's `source-missing` warning no longer frames `gh aw update` as the update mechanism; it now cites the reason `source:` still matters (the manual bump flow reads it to tell which release the install was copied from). The onboarding skill's update block gains an explicit stop comment between the merge instructions and `gh aw compile`, so a reader cannot run the block straight through and recompile an unmerged install. This repo's own installed `review.md` changes only in a frontmatter comment (the observability local-edit note no longer names `gh aw update` as the merger; lock recompiled); no behavior change. +Docs only, following up on the `gh aw update` ban Khan/actions#357 landed. The consumer-facing README now names the gh-aw version both failures were observed on (v0.85.4) and the condition for revisiting the ban: neither failure is filed upstream yet, so re-test both on a scratch install before trusting a newer gh-aw release. The consumer-config checker's `source-missing` warning no longer frames `gh aw update` as the update mechanism; it now cites the reason `source:` still matters (the manual bump flow reads it to tell which release the install was copied from). The onboarding skill's update block gains an explicit stop comment between the merge instructions and `gh aw compile`, telling the reader to run the 3-way merge and commit it before compiling (advisory: a shell comment cannot stop a straight paste, but the prior `` pseudo-tag was not valid shell at all). This repo's own installed `review.md` changes only in a frontmatter comment (the observability local-edit note no longer names `gh aw update` as the merger; lock recompiled); no behavior change. diff --git a/.claude/skills/review-consumer-bump/SKILL.md b/.claude/skills/review-consumer-bump/SKILL.md index 2b46f9d9..d3cbccc1 100644 --- a/.claude/skills/review-consumer-bump/SKILL.md +++ b/.claude/skills/review-consumer-bump/SKILL.md @@ -70,6 +70,10 @@ It is the obvious tool and it fails twice, both observed live: The manual merge below is what the tool would do if it worked. +Both failures were observed on gh-aw v0.85.4 and neither is filed upstream, +so this ban carries no expiry: before trusting a newer gh-aw release with a +bump, reproduce both failures on a scratch install first. + ## Step 2: the merge Work in a fresh clone of the consumer, on a new branch. From a `Khan/actions` diff --git a/workflows/review/gh-aw-update-ban.test.ts b/workflows/review/gh-aw-update-ban.test.ts new file mode 100644 index 00000000..dc40ae75 --- /dev/null +++ b/workflows/review/gh-aw-update-ban.test.ts @@ -0,0 +1,65 @@ +/** + * CI backstop for the `gh aw update` ban (the tool repins `review-v*` tags to + * main's head SHA and once emptied an installed `review.md` to 0 bytes; see + * `.claude/skills/review-consumer-bump/SKILL.md`). The ban lives entirely in + * prose, which no automation touches, so nothing but this test stops a future + * doc edit from recommending the tool again. Same shape as the repo's other + * untouched-by-automation backstops (review-pins.test.ts, the cache-miss + * guard): every tracked mention must sit in a file known to talk ABOUT the + * ban, and a mention anywhere else fails red so the author reads the skill + * before re-recommending. + * + * `.changeset/` is excluded (transient release notes describing the ban) and + * `gh-aw-review-lib/` is a runtime checkout, never tracked. + */ +import {spawnSync} from "node:child_process"; +import * as fs from "fs"; +import * as path from "path"; +import {describe, expect, it} from "vitest"; + +const repoRoot = path.resolve(new URL(".", import.meta.url).pathname, "../.."); + +/** + * Files allowed to mention the tool, every one prohibitively: the ban's own + * section in the bump skill, the two onboarding-skill warnings, the consumer + * README's warning, and review-pins.test.ts's doc comments about why the + * pins need a backstop at all. + */ +const ALLOWED = new Set([ + ".claude/skills/review-consumer-bump/SKILL.md", + ".claude/skills/review-onboarding/SKILL.md", + ".github/workflows/review-pins.test.ts", + "workflows/review/README.md", + "workflows/review/gh-aw-update-ban.test.ts", +]); + +describe("the gh aw update ban", () => { + it("is mentioned only where it is being banned", () => { + const ls = spawnSync("git", ["ls-files", "*.md", "*.ts"], { + cwd: repoRoot, + encoding: "utf8", + }); + expect(ls.status).toBe(0); + const offenders = ls.stdout + .split("\n") + .filter( + (file) => + file !== "" && + !file.startsWith(".changeset/") && + !ALLOWED.has(file) && + fs + .readFileSync(path.join(repoRoot, file), "utf8") + .includes("gh aw update"), + ); + expect(offenders).toEqual([]); + }); + + it("keeps every allowlisted file actually mentioning it (stale allowlist detector)", () => { + for (const file of ALLOWED) { + expect( + fs.readFileSync(path.join(repoRoot, file), "utf8"), + `${file} no longer mentions the tool; prune it from ALLOWED`, + ).toContain("gh aw update"); + } + }); +}); From fa9ee8f53e6487e8e1490ac1eb35b1a9da33b7cc Mon Sep 17 00:00:00 2001 From: James Wiesebron Date: Mon, 24 Aug 2026 12:09:00 -0700 Subject: [PATCH 6/6] review: the ban sweep scans every tracked file and spares the CHANGELOG The blocking catch: changeset version copies changeset bodies verbatim into workflows/review/CHANGELOG.md, so excluding .changeset/ but not the file it concatenates into just deferred the failure to the release PR. Also from the round: the eval corpus is excluded (case fixtures quote arbitrary text), the extension glob is gone entirely (the residue has turned up in .md, .ts, and a compiled .lock.yml, so an extension list is a bet on where the next one lands; reading a binary as utf8 cannot match), the ALLOWED docstring names all five entries including this file's own search string, and the header states the file-granularity limit so nobody over-trusts the backstop. --- workflows/review/gh-aw-update-ban.test.ts | 52 +++++++++++++++-------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/workflows/review/gh-aw-update-ban.test.ts b/workflows/review/gh-aw-update-ban.test.ts index dc40ae75..30f383e9 100644 --- a/workflows/review/gh-aw-update-ban.test.ts +++ b/workflows/review/gh-aw-update-ban.test.ts @@ -9,8 +9,15 @@ * ban, and a mention anywhere else fails red so the author reads the skill * before re-recommending. * - * `.changeset/` is excluded (transient release notes describing the ban) and - * `gh-aw-review-lib/` is a runtime checkout, never tracked. + * Known limit: the allowlist is file-granular. It catches the ban RELOCATING + * (a mention appearing in a new file) but not a recommending sentence added + * to a file already allowed to mention the tool; that stays a review-time + * judgment. Excluded from the sweep entirely: `.changeset/` and the package + * CHANGELOG.md files (changeset bodies describing the ban are copied + * verbatim into the CHANGELOG at `changeset version`, so both carry the + * phrase legitimately and transiently grow), and the eval corpus (case + * fixtures quote arbitrary text; vitest.config.ts already carves out its + * tree/ dirs for the same reason). */ import {spawnSync} from "node:child_process"; import * as fs from "fs"; @@ -20,10 +27,11 @@ import {describe, expect, it} from "vitest"; const repoRoot = path.resolve(new URL(".", import.meta.url).pathname, "../.."); /** - * Files allowed to mention the tool, every one prohibitively: the ban's own - * section in the bump skill, the two onboarding-skill warnings, the consumer - * README's warning, and review-pins.test.ts's doc comments about why the - * pins need a backstop at all. + * Files allowed to mention the tool: the ban's own section in the bump skill, + * the two onboarding-skill warnings, the consumer README's warning, + * review-pins.test.ts's doc comments about why the pins need a backstop at + * all, and this file, which carries the search string itself (the one + * non-prohibitive mention). */ const ALLOWED = new Set([ ".claude/skills/review-consumer-bump/SKILL.md", @@ -35,22 +43,30 @@ const ALLOWED = new Set([ describe("the gh aw update ban", () => { it("is mentioned only where it is being banned", () => { - const ls = spawnSync("git", ["ls-files", "*.md", "*.ts"], { + // Every tracked file, not an extension list: the ban's residue has + // already turned up in .md prose, .ts warning strings, and a + // compiled .lock.yml, so an extension filter is just a bet on where + // the next one lands. Reading a binary as utf8 cannot match the + // phrase, so no file type needs excluding for safety. + const ls = spawnSync("git", ["ls-files"], { cwd: repoRoot, encoding: "utf8", }); expect(ls.status).toBe(0); - const offenders = ls.stdout - .split("\n") - .filter( - (file) => - file !== "" && - !file.startsWith(".changeset/") && - !ALLOWED.has(file) && - fs - .readFileSync(path.join(repoRoot, file), "utf8") - .includes("gh aw update"), - ); + const offenders = ls.stdout.split("\n").filter( + (file) => + file !== "" && + !file.startsWith(".changeset/") && + // `changeset version` copies each changeset body verbatim + // into the package CHANGELOG.md, so the released notes + // inherit whatever mentions .changeset/ was excused for. + !file.endsWith("CHANGELOG.md") && + !file.startsWith("workflows/review/eval/corpus/") && + !ALLOWED.has(file) && + fs + .readFileSync(path.join(repoRoot, file), "utf8") + .includes("gh aw update"), + ); expect(offenders).toEqual([]); });