Skip to content

docs(claude-ops): re-verify plugins skill probes against Claude Code 2.1.261 - #3760

Merged
kyle-sexton merged 4 commits into
mainfrom
docs/3734-plugins-recheck-cc-2-1-261
Sep 5, 2026
Merged

kyle-sexton merged 4 commits into
mainfrom
docs/3734-plugins-recheck-cc-2-1-261

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

Closes #3734

Summary

The claude-ops:plugins skill grounds sync on empirically probed Claude Code facts, each stamped with the CLI version it was observed on and carrying a recheck trigger. The newest stamps said 2.1.240 (one 2.1.218) against a 2.1.261 CLI, so the triggers were armed and unserviced. This pass re-runs every probe the issue lists, or marks it not re-run with the reason, and corrects prose where behaviour changed.

Fix

  • Re-verified on 2.1.261 in a throwaway project under $TEMP, never at user scope: update -s project writes no committed settings; the install/uninstall/enable/disable project-scope write matrix, key-created-when-absent, and whole-file re-serialization; enable -s project gates on the merged effective value; -s project keys on the literal cwd with no path flag; no CLI verb reaps an install record by path and prune remains a dependency axis.
  • Corrected: claude plugin update <bare-name> now resolves at project scope on 2.1.261, so the gotcha is re-worded (the skill already always passes full ids, no code change). The --ids refusing --all claim is re-attributed to fleet-state.sh's own guard, which is what actually enforces it.
  • Doc-sourced claims re-fetched 2026-09-05 and confirmed: pluginConfigs reads user, --settings, and managed only (project and local ignored since v2.1.207); monitors require a session restart; userConfig has no enum type; renames gate on v2.1.193.
  • Explicitly not re-run, with the reason written next to the claim and the old stamp kept: mid-session update path resolution and the /reload-plugins bare-vs---force warning (both need an interactive session); install-summary activation line (doc-confirmed only); prune v2.1.121 and --force v2.1.163 gates (docs state neither).
  • The userConfig unset-key placeholder probe, the highest-value one, was inconclusive, not a confirmation: its positive control failed (a key explicitly set via --settings pluginConfigs also rendered literal). SKILL.md now says so and treats the claim as still resting on the 2.1.218 probe. Filed as claude-ops:plugins: userConfig substitution probe failed its positive control on CC 2.1.261 (pluginConfigs via --settings rendered literal) #3759.
  • File-level headers in scope-semantics.md and gotchas.md name the pass date, state that per-claim stamps govern, and list the not-re-run claims by name.
  • claude-ops 0.42.6 -> 0.42.7 with CHANGELOG entry. Docs only; no script changed.

Verification

  • Probe ledger per claim is in the CHANGELOG entry and the per-claim stamps.
  • markdownlint-cli2 over plugins/claude-ops/**/*.md: 0 issues. node scripts/validate-plugin-contracts.mjs: validated. SKILL.md frontmatter unchanged.
  • Real machine state after the probe session: ~/.claude/settings.json semantically identical to the pre-probe backup (a marketplace add/remove round trip for the throwaway plugin flipped line endings only); installed_plugins.json has the same record set (user-scope versions advanced from the routine autoUpdate sweep that each claude -p probe session triggers). No throwaway marketplace or plugin remains registered.

Related

🤖 Generated with Claude Code

https://claude.ai/code/session_019gWgHogJFQeCne5U7vHKAE

kyle-sexton and others added 2 commits September 5, 2026 12:00
…3734)

Re-runs the empirical probes the plugins skill's recheck triggers arm, and
updates each stamp to the version it was actually re-verified on.

Confirmed unchanged on 2.1.261: update -s project writes no committed settings;
the install/uninstall/enable/disable project-scope write matrix including
key-created-when-absent and whole-file re-serialization; enable -s project
gating on the merged effective value; -s project keying on the literal cwd;
and no CLI verb reaping an install record by path.

Corrected: a bare plugin name now resolves for claude plugin update, so the
gotcha records the change and rests its rule on cross-marketplace ambiguity
instead; the --ids refusal of --all is fleet-state.sh's own guard, not a
Claude Code CLI fact, and the attribution is fixed rather than restamped.

Not re-run, each marked in place with its reason and keeping its old stamp:
the userConfig unset-key placeholder probe (attempted, inconclusive because the
positive control failed), mid-session update path resolution and the
/reload-plugins warning (both need an interactive session), and the prune and
--force version gates (current docs state neither version).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019gWgHogJFQeCne5U7vHKAE
…3734)

The gotchas header asserted that the CLI-behaviour sections were re-run, which
overclaimed: the plugin list/details section and the spoke-substitution section
were not part of the pass. It now names the re-run, changed, and not-re-run
sections individually.

The scope-semantics header stated a count of three not-re-run claims that its
own body contradicted further down. The count is gone and the list is complete.

The spoke-substitution gotcha now records that the same failed positive control
weakened the SKILL.md half of the contrast it rests on, and the userConfig
heading says "no enum type" rather than "no enum field", since the schema does
use an enum keyword to constrain type.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019gWgHogJFQeCne5U7vHKAE
@kyle-sexton
kyle-sexton marked this pull request as ready for review September 5, 2026 16:12
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 5, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-05T16:16:45.982194Z 3e04036 Draft marked ready
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@claude

claude Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 2m 33s —— View job


CI code review complete

  • Gather context (PR diff, changed files)
  • Check skip gate (open, ready for review, meaningful docs change — proceeding)
  • Review changed files for correctness/maintainability
  • Post findings (inline + summary)

This is a docs-only re-verification pass for the claude-ops:plugins skill (154/-41 across 8 files, version bump 0.42.6 → 0.42.7). The change is unusually careful about attaching per-claim version stamps and honestly reporting an inconclusive probe (userConfig unset-key rendering) rather than overclaiming it as confirmed — that discipline is the main thing this PR is protecting, and it's followed consistently.

One finding posted inline:

  • scope-semantics.md:74 — the "plugin update -s project does NOT write committed settings" claim is stamped "Re-verified on Claude Code 2.1.261 the same way" as the 2.1.228 probe, but the described 2.1.261 run was a no-op (plugin already at latest version, no actual update applied) — not the "hardest available conditions" test the 2.1.228 probe used. That's a weaker test than the stamp implies, in a document whose entire value proposition is precise, trustworthy stamps.

Checked and found consistent (no issues):

  • plugin.json version (0.42.7) matches the new top CHANGELOG.md entry.
  • The manifest's install_new / registry_dir userConfig entries both carry title, matching the new CHANGELOG claim that this plugin's own manifest already satisfies the schema's title requirement.
  • gotchas.md's file-level "what was/wasn't re-run" summary (lines 12–18) accurately maps to the sections actually changed in the diff (bare-name update, subdirectory-install, outlived-projectPath, spoke-substitution, mid-session self-update).
  • The sync.md correction (attributing the --ids/--all refusal to fleet-state.sh's own guard rather than Claude Code CLI behavior) and the gotchas.md bare-name-update correction are both self-consistent with the rest of the diff and with SKILL.md.
  • Version gates (prune ≥ 2.1.121, --force ≥ 2.1.163, renames ≥ 2.1.193) are stated consistently across scope-semantics.md and left correctly un-re-verified where the current docs don't name a version.
  • SKILL.md frontmatter is untouched, matching the PR's claim.

Not independently re-run: the probe session itself (throwaway project under $TEMP, real machine state diffing) — that's author-claimed verification I have no tool access to reproduce, so I'm treating it as reported, not confirmed.

@claude

claude Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 50s —— View job


Security review — /review:security-review

  • Gather context (PR is docs-only: claude-ops:plugins skill re-verification)
  • Run /review:security-review
  • Post findings

Skip gate hit — no findings. Per the skip gate in plugins/review/skills/security-review/SKILL.md, this pass stops early: the diff has no security-relevant surface.

All 8 changed files are prose/version-bump only:

  • plugins/claude-ops/.claude-plugin/plugin.json: version string 0.42.60.42.7.
  • CHANGELOG.md, SKILL.md, and the four context/*.md files: markdown prose updating CLI-version stamps, correcting/re-attributing two claims (bare-name update resolution, the --ids/--all guard's true owner), and marking several claims as inconclusive or not-re-run with reasons.

No scripts, no GitHub Actions workflows, no shell command construction, no credential/token handling, and no logic changes were touched — the PR body itself confirms "Docs only; no script changed," which matches the diff. Nothing here presents an injection, authorization, or trust-boundary surface for this lane to review.

@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Last security-reviewed head: 3e0403658578ac02094879f554eb2d10b2d39524. On the next push, the relevance gate compares only the commits since this SHA; delete this comment to force a full re-review.

Comment thread plugins/claude-ops/skills/plugins/context/scope-semantics.md Outdated
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Claude has reviewed this PR 1 time. The lane skips further automatic reviews after 5; deleting this comment resets the count.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3e04036585

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/claude-ops/skills/plugins/context/scope-semantics.md Outdated
kyle-sexton and others added 2 commits September 5, 2026 13:33
…ion bump (#3734)

The 2.1.261 re-run of the "update -s project does not write committed
settings" probe was a no-op update: the plugin was already at its latest
version, so nothing was written to installed_plugins.json and an empty
git status did not re-verify the invariant sync relies on.

Re-ran it against a throwaway local marketplace serving probe-plugin at
0.1.0, installed at project scope into a scratch repo, reverted the
dirtied committed settings to clean, bumped the marketplace, and updated:
the record advanced to 0.1.1 with a new lastUpdated and installPath while
git status stayed empty. A second 0.1.1 -> 0.1.2 cycle hash-compared both
settings.json and settings.local.json across the update.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019gWgHogJFQeCne5U7vHKAE
…dex (#3734)

The header block enumerates which claims carry the 2.1.261 stamp. The
update -s project settings exemption lives in its own section, so a
reader auditing that index could not trace it to "the write matrix".

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019gWgHogJFQeCne5U7vHKAE
@kyle-sexton
kyle-sexton merged commit 39442ff into main Sep 5, 2026
9 checks passed
@kyle-sexton
kyle-sexton deleted the docs/3734-plugins-recheck-cc-2-1-261 branch September 5, 2026 17:47
kyle-sexton added a commit that referenced this pull request Sep 6, 2026
…mmit (#3775)

Closes #3681

## Summary

`claude plugin update` re-points an install record's `gitCommitSha` in
`installed_plugins.json` without rewriting the plugin's cache directory
when the manifest version number is unchanged across the two commits,
because the cache is keyed by version. The record then claims the new
commit while the directory still holds the older build, and the
version-and-sha check every delivery step relies on passes in exactly
that state. On the reporting machine six plugins were in that state at
once, twelve stale files in the worst case, including a reviewed hook
dispatcher and two `hooks.json` files.

The issue asked for a decision between (a) a repo rule that every plugin
change bumps the version, (b) promoting the file-level compare into the
claude-ops plugin-fleet audit as a standing check, or (c) an upstream
report. This takes (b). (a) already exists as the CHANGELOG-parity gate
and only bites when a branch is delivered without a bump, so it cannot
catch the case that motivated the issue; (c) is worth filing but does
nothing for machines today, and the updater's behaviour on an unchanged
version may be intentional. (b) is local, cheap, and durable: every
record carries the sha and the marketplace's `installLocation` is a git
clone, so the files can be compared byte for byte.

## Fix

- New `cache-content-check.sh` in the `plugins` skill: a read-only
per-install compare of every file under a cache directory against the
recorded commit in the marketplace clone. Two git processes per install
(`git ls-tree -r <sha>` for the expected blob ids, one `git hash-object
--stdin-paths` batch for the cache files), set difference plus hash
inequality. Detects changed files, files the commit has that the cache
lacks, and files deleted at the commit but still in the cache. Honours
the marketplace's `.gitignore` (a live plugin root carries `__pycache__`
and `node_modules`, which the first real run flagged as stale until this
filter existed) and re-hashes mismatches with `--path` so
`.gitattributes` CRLF rules do not produce false positives. Never
writes: no `git fetch` (a sha absent from the clone reports
`sha-not-local`), no `claude plugin` call. Same CR-safe `--ids` contract
as `fleet-state.sh`, exit 2 on usage or malformed input.
- `sync.md` gains Step 5b running the check in both `sync` and `audit`
(from the run journal or scratch dir respectively), ungated, because an
unchanged version number is precisely the case in which every other step
reports success. SKILL.md's Report template gains a `Cache content:` row
naming affected ids and the remediation the issue proved (remove that
version directory under the cache and re-run `claude plugin update
<id>`); the check never repairs.
- `scope-semantics.md` records the mechanism (stamped Claude Code
2.1.259, issue evidence, not re-run) and the shallow-clone fact observed
on 2.1.261: the marketplace clone under
`~/.claude/plugins/marketplaces/` carries `.git/shallow` with three
commits, so records naming older commits are unverifiable without a
fetch the audit refuses to perform.
- claude-ops `0.42.12` -> `0.42.13` with CHANGELOG entry (main took
0.42.8 through 0.42.12 mid-flight).

## Verification

- `cache-content-check.test.sh`: 24 cases, 0 failed. Fixture-driven with
a throwaway git repo as `installLocation` at two commits: match; older
file in cache -> stale-content naming the path; file deleted at sha
still in cache -> stale-content; sha not in clone -> sha-not-local;
`--ids` emits only stale ids CR-free; malformed `installed_plugins.json`
-> exit 2; unknown marketplace -> exit 2 naming it; absent project path
skipped and counted; misaligned hash batch refused rather than compared
(stub git truncating the hash batch); plugin directory renamed between
commits still matches because the manifest is read at the recorded sha;
a pathspec matching nothing at the sha is `no-source-at-sha`, not stale;
non-ASCII filename round-trips NUL-safe; tracked symlink hashed
mode-aware (skips where the host cannot create one); record without
gitCommitSha yields `no-git-commit-sha`; process-count probe has a floor
so it cannot pass vacuously.
- `fleet-state.test.sh`: 86 cases, 0 failed. `shellcheck -S info` clean
on both new scripts. `typos` clean. `markdownlint-cli2`: 0 issues in 54
files. `validate-plugin-contracts.mjs`: pass. Test suites are
auto-discovered by `scripts/run-plugin-tests.sh`, no registry edit
needed.
- Real machine, read-only, against the committed script: `--marketplace
melodic-software --scope user` -> checked 74, match 63, stale_content 0,
unverifiable 11 (all `sha-not-local`, the shallow-clone case above),
skipped_absent_project_paths 0.
- `scripts/affected-tests.sh --run` not run locally (hangs on
`check-changed-skills.test.sh` on this host); CI is the statement of
record.

## Related

- #3688 (stale project-scope records; this check skips absent project
paths and counts them rather than reaching into them)
- #3763 (marketplace remove leaves a cache tree behind, found during
#3734)
- #3760 (the re-verification pass that stamped the no-reap-by-path claim
this check respects)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_019gWgHogJFQeCne5U7vHKAE

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Sep 6, 2026
…m and why nothing reaps them (#3786)

No related issue: this records verified facts for the #3688 decision
without closing it; the structural remediation stays open on that issue
for the operator.

## Summary

The `plugins` skill reports stale project-scope install records and
states that no CLI verb removes one by path, but it never recorded where
those records come from. A user reading a count in the hundreds had no
way to tell a careless install habit from a repo producing them on its
own. A review pass against the current Claude Code docs (plugins,
plugins-reference, settings-reference, cloud-environments,
discover-plugins, claude-directory, changelog through 2.1.261)
established the mechanism; this PR writes it down where the skill
reasons about those records.

## Fix

- New `scope-semantics.md` subsection "Where project-scope records come
from, and why the skill cannot reap them". A repo's committed
`.claude/settings.json` `enabledPlugins` block is the documented cloud
install mechanism; project scope outranks user scope in `enabledPlugins`
precedence; so every project-scope `true` that duplicates a user-scope
install gets its own version-pinned record keyed by that checkout's
absolute path. Nothing reaps the result: `git worktree remove` does not
touch `~/.claude`, no CLI verb removes a record by path, and the
documented retention sweep covers nothing under `~/.claude/plugins/`.
Changelog 2.1.224 shows per-project records are a live mechanism. Synced
plugins (`<name>@synced`, cloud and Cowork only, no install record) are
recorded as the contrast case.
- Two questions are recorded as open probes, not asserted: which code
path writes the records locally (one machine's 64 records sharing a
single `installedAt` second is written as an observation on 2.1.261,
with the probe that would settle it named), and whether a project-scope
`false` writes any record.
- `SKILL.md`'s stale-records section gains a short pointer to the
subsection and keeps its existing boundary that the tool owning the
directories is where records should be dropped. `gotchas.md` gains a
gotcha on a committed block manufacturing records, citing the
subsection. No remediation is proposed anywhere; that decision is open
on #3688.
- claude-ops `0.42.13` -> `0.42.14` with CHANGELOG entry. Docs only; no
script changed; SKILL.md frontmatter unchanged.

## Verification

- `markdownlint-cli2` over `plugins/claude-ops/**/*.md`: 0 issues in 54
files. `typos`: clean. `node scripts/validate-plugin-contracts.mjs`:
pass (the retirements append-only sub-check reports skipped locally
because `VALIDATE_CONTRACTS_BASE_REF` is unset; CI sets it).
- SKILL.md frontmatter diffed byte-identical against `origin/main`. No
em dashes in added prose.

## Related

- #3688 (the decision this documents; stays open)
- #3760 (re-verified the no-reap-by-path claim this section builds on)
- #3775 (cache-content check, which skips absent project paths on the
same reasoning)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_019gWgHogJFQeCne5U7vHKAE

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Sep 6, 2026
…63 (#3813)

No related issue: this records the two probe results the #3688 decision
was waiting on, without closing it; the structural remediation stays
open on that issue.

## Summary

`scope-semantics.md`'s "Where project-scope records come from" section
carried two open probes: whether a local session writes project-scope
install records for a repo's committed `enabledPlugins` block when the
user already holds the plugins at user scope, and whether a
project-scope `false` writes any record. Both were run on 2026-09-06
against Claude Code 2.1.263 in a scratch repository under the temp
directory, with the three plugin state files hashed before and after.

## Fix

- Probe 1: two `true` entries duplicating user-scope installs produced
exactly two new `scope: "project"` records at the first headless session
start, same `installedAt` millisecond, pinned to the user scope's
version, `installPath` pointing at the user scope's existing cache
directory. No cache directory was created. The section now states the
write as a verified fact with the recipe and drops the "open probe" and
"leading hypothesis" wording.
- Probe 2: one `false` entry for a user-installed plugin left
`installed_plugins.json` byte-identical and the session reported that
plugin's skill unavailable while a sibling stayed available. Recorded as
"a `false` writes nothing".
- Also observed and recorded: `claude plugin uninstall -s project`
rewrites the checkout's committed `.claude/settings.json`, deleting the
id from `enabledPlugins` and reordering top-level keys.
- `SKILL.md`'s stale-records section names the block as the source
rather than a candidate and points at the recipe; the `gotchas.md`
pointer line drops "two questions still open". Frontmatter unchanged.
- claude-ops `0.42.17` -> `0.42.18` with CHANGELOG entry. Docs only.

## Verification

- `markdownlint-cli2` over the three touched markdown files: 0 issues.
`typos`: clean. No em dashes in added lines.
- `SKILL.md` frontmatter diffed byte-identical against `origin/main`.
- Real state after the probes: `~/.claude/settings.json`,
`installed_plugins.json`, `known_marketplaces.json` all hash-identical
to the pre-probe copies once the two scratch records were uninstalled at
project scope from inside the scratch directory; the scratch directory
was deleted.

## Related

- #3688 (the decision these probes feed; stays open)
- #3786 (recorded the probes as open)
- #3760 (the 2.1.261 re-verification pass this extends)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_019gWgHogJFQeCne5U7vHKAE

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Sep 6, 2026
…3826)

Closes #3759

## Summary

The `plugins` skill's `install_new` render rests on the claim that an
unset `userConfig` key renders the literal `${user_config.<key>}`
placeholder rather than the manifest default. The 2.1.261
re-verification could not confirm or deny it because its positive
control failed: a key set through `--settings` `pluginConfigs` rendered
literal. Issue #3759 asked for a probe allowed to write real user
settings so the two explanations (`--settings` does not feed
substitution, or substitution regressed) could be separated.

## Fix

- Probe run 2026-09-06 on Claude Code 2.1.263 with a throwaway local
marketplace and a throwaway plugin carrying two `userConfig` string
keys, both with manifest defaults. `claude plugin install <id> --config
setkey=REALVALUE` wrote the real user-settings entry. Rendered skill
body: the set key substituted, the unset key rendered the literal
placeholder (not its default), `${CLAUDE_PLUGIN_ROOT}` substituted.
Claim holds; explanation (1) from the issue is the right one, and there
is no regression.
- Second run with `--settings
'{"pluginConfigs":{"<id>":{"options":{"unsetkey":"VIA_SETTINGS_FLAG"}}}}'`:
the flag-sourced value substituted alongside the user-settings one. So
`--settings` does feed skill-content substitution; the 2.1.261 control
failed because its payload put the key directly under the plugin id
instead of under `options`.
- `SKILL.md` replaces the "inconclusive" paragraph with the 2.1.263
stamp, the `options` shape, the `--config` recipe, and a note that the
current plugins-reference page says the default "is used if specified"
for an unset key while the render contradicts it for skill content.
`install_new` needs no fallback beyond the existing "placeholder means
`ask`" rule. Frontmatter unchanged.
- `scope-semantics.md` records the `options` nesting in the
`pluginConfigs` section and updates the preamble's not-re-run list.
- claude-ops version bump with CHANGELOG entry. Docs only.

## Verification

- `markdownlint-cli2` over the touched markdown: 0 issues. `typos`:
clean. No em dashes in added lines. `SKILL.md` frontmatter diffed
byte-identical against `origin/main`.
- Real state after the probe: throwaway plugin uninstalled, marketplace
removed; `~/.claude/settings.json`, `installed_plugins.json`,
`known_marketplaces.json` all hash-identical to the pre-probe backups.
The `pluginConfigs` entry the probe wrote was removed by the uninstall.

## Related

- #3734 and #3760 (the 2.1.261 pass whose control failed)
- #3763 (the cache-residue observation from the same marketplace round
trip, own PR)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

claude-ops:plugins — recheck triggers armed and unserviced: empirical CC probes stamped 2.1.240 (one at 2.1.218) against a 2.1.261 CLI

1 participant