docs(playbook): add reintegration (consumer-adoption) section#21
Conversation
The migration playbook documented the forward path (migrate -> publish) but stopped there. Add the back-half: how a consumer repo retires its in-repo hook and adopts the published plugin, preserving its specifics through its OWN extension seams (settings env, CLAUDE.md/rules, and especially its telemetry sink) rather than teaching the plugin consumer-specific behavior. Captures the verified key insight from the biome-format/medley audit: the telemetry-sink envelope contract is the adaptation seam — a consumer restores a divergent observability contract (e.g. status=error on a violation, a legacy hook name) by remapping the generic envelope in its own sink, after verifying how its observability actually keys events. Includes a cutover checklist and the bootstrap-direction caveat (don't flip a still-source repo to consumer incidentally). Decision context: medley's biome-format reintegration is deferred — medley stays the harvest source for now — so this captures the reusable pattern without changing any consumer. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WWt8nQzh8BAoZXRZRt2ARU
|
Claude finished @kyle-sexton's task in 1m 25s —— View job Review
The section is well-positioned and the core mental model (plugin stays generic, consumer's seams restore specifics, telemetry sink as the translation layer) is exactly right. Four issues worth flagging, ordered by severity. 1. Cutover checklist step order creates a coverage gap (medium)Steps 3 and 4 are in the wrong order for safe cutover:
Deleting before verifying means there's a window where neither hook is active and the only signal is a missing test. The standard "blue-green" approach is: verify the replacement works first, then remove the old one. Swapping to verify → delete eliminates the gap with no other change needed. Fix this → 2. Fresh-docs mandate —
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9756dd92d3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
PR #21 review fixes: - Cutover checklist: verify-before-retire (blue-green) — reorder so the plugin is confirmed working (incl. the telemetry sink receiving the expected envelope) before the in-repo hook is deleted, closing the no-active-hook window. Note the brief both-hooks overlap is harmless (formatting is idempotent). - Fold the telemetry-sink check into the verify step. - Fresh-docs: cite the 2026-06-29 verification of extraKnownMarketplaces / enabledPlugins against the discover-plugins "Configure team marketplaces" guide, in the intro provenance line. - Disambiguate "its" -> "the repo's" ported plugins. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WWt8nQzh8BAoZXRZRt2ARU
|
Claude finished @kyle-sexton's task in 3m 19s —— View job Review
All four findings from the prior review are addressed in the follow-up commit. One issue introduced in the original diff — flagged by Codex but not by the prior review — remains open. Prior review: all four findings resolved
Remaining issue: "the plugin already reads" is incorrect for hook-based plugins (medium)The reintegration section (line 122) says:
This claim is inaccurate for hook-centric plugins. The extensibility model table (line 39) is precise about this — it says "The skill reads the consuming project's own context and rules." Skills run in Claude's model context and do receive CLAUDE.md. Hook scripts do not. The fix is either to scope the claim to skill components of the plugin, or to note that for hook-based plugins, conventions route through
Or, if this section is explicitly targeted at hook cutover: drop the CLAUDE.md bullet and let the kill-switch env var bullet carry it. Fix this → Overall: the follow-up commit is solid — every prior finding has a clean fix. The one remaining item is the hook-vs-skill distinction on CLAUDE.md; it's medium priority because a consumer who follows the current guidance for a hook-based plugin would silently lose the convention with no error. |
|
Thanks — all four addressed in 69d4772: #1 (cutover step order, medium) — Fixed. Reordered to verify-before-retire (blue-green): step 3 now confirms the plugin works with the old hook still in place, step 4 retires the old hook only after. Added a note that the brief both-hooks overlap is harmless since formatting is idempotent. #2 (fresh-docs mandate, medium) — Verified this session. Confirmed #3 (verify the sink, low) — Folded into the reordered verify step: "the telemetry sink receives the expected envelope (so a broken remap is caught now, not when observability is next needed)." #4 ("its" ambiguous, low) — Changed to "the repo's ported plugins." Lint lanes green. |
PR #21 re-review: the "project conventions -> CLAUDE.md" bullet was inaccurate for hook plugins. Hook scripts (biome-format, bash-lint) never receive CLAUDE.md — only a plugin's skill/agent components do (model context). Hooks read project conventions from the consumer's own file-based tool config (biome.json, .shellcheckrc, .editorconfig). A consumer routing a convention to CLAUDE.md for a hook plugin would have it silently ignored. Scope the bullet to file-based config for hooks and note CLAUDE.md reaches only skill/agent components. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WWt8nQzh8BAoZXRZRt2ARU
|
Fixed in 7358e0b — you're right, and it's an important distinction for a section whose worked example is a hook. Scoped the bullet: for hook plugins, project conventions route through the consumer's own file-based tool config ( |
|
Claude finished @kyle-sexton's task in 1m 33s —— View job Review
All findings across both prior review rounds are resolved. This is a clean pass. All prior findings — resolved
7358e0b fix is accurateThe corrected bullet at line 122–125:
This is technically correct and consistent with the extensibility model table (line 39), which already scoped Overall: the section is substantively correct, every review finding has a clean fix, and the hook-vs-skill distinction is now precise and consistent with the rest of the playbook. Ready to merge. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7358e0b314
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ers) PR #21 review: the verify step called the both-hooks overlap "harmless: formatting is idempotent" — incorrect. Matching PostToolUse hooks run concurrently, so the old in-repo formatter and the plugin would race on the just-edited file (last-writer-wins clobbering + doubled telemetry/ context). Idempotence only makes serial re-runs converge, not concurrent writes safe. Fix: disable the old hook (kill switch / comment out its registration, don't delete) before verifying the plugin, then delete after. This keeps the blue-green property (plugin active throughout, old hook recoverable if verify fails) AND avoids concurrent mutation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WWt8nQzh8BAoZXRZRt2ARU
|
Claude finished @kyle-sexton's task in 1m 38s —— View job Review
4f47218 correctly addresses the Codex P2 finding. Clean pass. 4f47218 fix is accurateThe corrected step 3 at lines 147–156 replaces the prior "idempotent overlap is harmless" claim with a disable-before-verify procedure. The fix is technically correct on all three counts:
Full finding history — all resolved
Overall: every finding across all review rounds has a clean fix. The section is substantively correct, internally consistent with the extensibility model table, and the cutover procedure is now safe. Ready to merge. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4f4721871d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
PR #21 review, two flaws in the verify step: - "comment out its settings.json registration" — settings.json is JSON; a // comment makes it invalid. Disable via the kill-switch env var (set to "false"), or remove the registration entry if it has none. - On verify failure I had "re-enable the old hook while the plugin stays active" — that recreates the both-active concurrent race. Corrected to disable the plugin first, then re-enable the old hook: exactly one formatter is active at any time, with no no-hook gap. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WWt8nQzh8BAoZXRZRt2ARU
|
Claude finished @kyle-sexton's task in 1m 25s —— View job Review
df82e0f fixes are accurateCodex P2 / "Avoid recommending comments in settings JSON" The old step 3 offered "flip its kill switch or comment out its
✅ Correct. Standard JSON does not support Codex P2 / "Disable the plugin before falling back" The old failure path said "re-enable the old hook; the plugin stays active throughout" — which would have recreated the concurrent two-formatter race that the rest of step 3 explicitly warns against. The new text at lines 157–159:
✅ Correct. The rollback sequence now obeys the same "exactly one active at a time" invariant as the forward path. The "always flip one off as you turn the other on" phrasing generalizes the rule cleanly across both paths. Full finding history — all resolved
Overall: every finding across all review rounds has a clean fix. The "exactly one hook active at a time" invariant now holds on both the happy path and the rollback path, the JSON validity constraint is explicit, and the section is technically consistent throughout. Ready to merge. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: df82e0f6e6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…d the marketplace PR #21 review: the headless/CI note only called `claude plugin marketplace add`, but registering a marketplace does not install its plugins (the interactive trust prompt is what installs the enabled plugin). Without an install, a headless consumer disables the old hook in step 3 while the plugin is still absent, so the verify edit runs with no hook. Add the explicit `claude plugin install <plugin>@<marketplace> --scope project`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WWt8nQzh8BAoZXRZRt2ARU
|
Claude finished @kyle-sexton's task in 1m 39s —— View job Review
56bebfc fix is accurateThe updated step 1 (lines 142–147):
Three claims, all verified against fresh docs:
The failure mode is also correctly described: marketplace known but plugin absent means step 3's verify edit fires with no plugin hook active — precisely the gap the Codex finding flagged. Full finding history — all resolved
Overall: every finding across all review rounds has a clean fix. The cutover checklist is now correct for both interactive and headless/CI consumers, the "exactly one hook active at a time" invariant holds on both the happy path and rollback path, and all schema/CLI claims are verified against fresh docs. Ready to merge. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 56bebfca83
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| marketplace does not install its plugins, so do both explicitly: `claude plugin marketplace add <repo>` | ||
| then `claude plugin install <plugin>@<marketplace> --scope project` — otherwise the marketplace is known | ||
| but the plugin is absent, and step 3's verify edit would run with no plugin hook. | ||
| 2. Rewire the kill-switch env var to the plugin's name; keep the `HOOK_TELEMETRY_SINK` wiring and the |
There was a problem hiding this comment.
Use the hook's documented kill switch
This assumes the env var is derived from the plugin manifest name, but markdown-formatter already disproves that: its manifest name is markdown-formatter, while the hook calls hook::check_enabled "MARKDOWN_FORMAT" and the README documents HOOK_MARKDOWN_FORMAT_ENABLED. A consumer following this step would set/flip HOOK_MARKDOWN_FORMATTER_ENABLED, which the hook never reads, so the plugin could remain active during cutover or rollback; point to each plugin's documented kill switch instead of deriving it from the plugin name.
Useful? React with 👍 / 👎.
| marketplace does not install its plugins, so do both explicitly: `claude plugin marketplace add <repo>` | ||
| then `claude plugin install <plugin>@<marketplace> --scope project` — otherwise the marketplace is known | ||
| but the plugin is absent, and step 3's verify edit would run with no plugin hook. |
There was a problem hiding this comment.
Reload the plugin before verifying it
In an existing Claude Code session, the headless install/enabled path here is followed immediately by step 3's edit, but installed/enabled plugins are not activated until the session reloads them; the official Discover plugins guide (https://code.claude.com/docs/en/discover-plugins) says, "After installing, run /reload-plugins to activate the plugin," and its CLI section repeats this for install/enable/disable. Without an explicit /reload-plugins or restart before the verify edit, the old hook can be disabled while the plugin hook is still absent, causing a false fallback or a no-hook window.
Useful? React with 👍 / 👎.
What
Adds the missing back-half of the plugin lifecycle to the migration playbook. The doc covered migrate → publish but stopped there; reintegration — a consumer repo retiring its in-repo hook and adopting the published plugin — is the pattern that repeats for every port, and it was undocumented.
The new section is general and reusable, grounded in the verified biome-format ↔ medley audit:
CLAUDE.md/rules, and especially the telemetry sink. The key insight: the plugin emits the generic telemetry envelope toHOOK_TELEMETRY_SINK, and the consumer's sink translates it into the consumer's local observability shape. A consumer whose prior hook used a different status/identity (e.g.status=erroron a violation, a legacy hook name) restores that contract in its own sink — after verifying how its observability actually keys events (status vs derived exit_code/findings) — not by changing the plugin.Context
medley's biome-format reintegration is deferred — medley stays the harvest source for now — so this PR captures the reusable pattern without touching any consumer. Docs-only.
Lint lanes (markdownlint, typos, editorconfig) pass locally.
🤖 Generated with Claude Code