fix(architecture): remove false CLAUDE_PLUGIN_DATA substitution claim from improve Gotcha - #2286
Conversation
The improve Gotcha incorrectly stated the token does not substitute in skill markdown. Plugins-reference puts skill and agent content in the 'anywhere the placeholder appears' row. The operative rule is unchanged: never use CLAUDE_PLUGIN_DATA for the durable candidate artifact because it collides across projects. Fixes #2207. Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
|
Claude finished @kyle-sexton's task in 30s —— View job Security review complete
No security issues found. This PR is a documentation-only change: a version bump in Scope reviewed: |
|
Claude finished @kyle-sexton's task in 1m 50s —— View job Claude finished the review
SummaryThis is a clean, surgical fix. I independently verified the central factual claim rather than trusting the PR description: I fetched
confirming Other checks:
No correctness, design, or maintainability issues found in the diff. No inline comments were needed — the change is minimal (2 lines) and each line checks out. |
|
Claude has reviewed this PR 1 time. The lane skips further automatic reviews after 5; deleting this comment resets the count. |
…eam-drift, and record the gate deferral (#2318) ## Summary Plugins restate upstream harness facts in bare prose — no source URL, no as-of date, no recheck trigger — so when the upstream behaviour changes, nothing makes the stale claim surface. `docs/conventions/upstream-drift/` already owns exactly this concern and already says the name **binds on touch**. The gap was **adoption, not design**, so nothing new is invented here. Docs-only. No plugin, script, hook, or CI behaviour changes. ### 1. The Adopters table now says how a post-1.0.0 row gets there — and what disqualifies one The preamble read *"Migrated at this contract's 1.0.0"*, which any appended row would have quietly falsified. It now separates the eight migrated rows from later on-touch adoptions and requires each later row to name the release that added it. It also writes down the bar the third column already implied but never stated: **a surface is tabled only once it actually conforms.** That column is a promise to a reader about what they can rely on, so a carrier *known* to be unstamped belongs in a tracked issue, never in a row — tabling it would assert the very thing the reader would then not get, which is this batch's own recurring defect class pointed at the convention meant to prevent it. ### 2. The fleet sweep — 12 carriers, filed rather than tabled A sweep of `plugins/**` for surfaces stating an upstream harness behaviour with no source, date, or trigger found **12 carriers across 11 plugins**, filed at #2297 with quoted lines and a per-plugin tally. The issue also records the files checked and found **conforming** (so the sweep is not one-sided) and states its own limitation plainly: the citation gate was **file-level**, so any file containing a docs URL anywhere was dropped from the carrier pass, which structurally under-represents mixed files — roughly 300 files were dropped that way. It is a **lower bound, not a census**, and it says so. None is tabled here, which is change 1 applied to its own findings. ### 3. `architecture` is deliberately NOT added to the table Row 1 of #2273 asks for exactly that row. It is not being added, and the reason is the point: #2286 (merged while this was in flight) removed the false substitution claim, closing #2207. But the surviving bullet on `main` still reads: > **The durable candidate artifact is a per-project memory-tier file, never `${CLAUDE_PLUGIN_DATA}`.** > **Even resolved it points at a plugin-global dir that collides candidates across projects.** … "Even resolved it points at a plugin-global dir" **is** an upstream-owned specific — `plugins-reference` §Environment variables → §Persistent data directory, which resolves the token to `~/.claude/plugins/data/{id}/`. It carries no URL, no date, and no trigger. So A-F4 (the unstamped- prose row of #2207) is untouched and `architecture` is still a carrier. Per change 1 it is recorded in #2297, not tabled. ### 4. Enforcement decided: deferred, as a recorded decision with its own trigger Row 3 asks whether this repo's `*-gate` CI pattern should enforce adoption. **No gate is built**, and the reason is a finding rather than a preference: The candidate check §Enforceability **already names** — *flag any `Verified <date>` line or row whose surface states no trigger* — **would not have caught #2207**, the case that prompted the question. That surface carried no stamp at all, so a stamp-anchored grep had nothing to match on. The named check is shaped for a **half-conforming** record; the failure that actually ships is the **zero-part** one. The existing named-not-built check and its own build trigger are left unchanged. The zero-part shape has no deterministic check available: deciding whether a sentence restates an upstream-owned specific — as against an in-repo fact or ordinary prose — is a judgment about meaning, **reasoning-only** under the tiers doc. A harness-vocabulary grep (`PostToolUse`, `${CLAUDE_*}`, `settings.json`) fires on every correct citation and in-repo mention alike, and a gate whose false-positive rate forces routine suppression trains authors to bypass it — worse than no gate, because it converts a real signal into noise with an approved silencer. Recorded as the doc's own **second record kind** with a basis and an event trigger — a third unstamped carrier reaching `main`, or a demonstrated detector needing no suppression list — so the deferral expires on evidence rather than on a date. ### Disposition of all three rows of #2273 | Row | Disposition | |---|---| | Add `architecture` to Adopters | **Not added, deliberately** — #2286 left an unstamped upstream specific in the same bullet, so the plugin does not conform. Recorded in #2297 instead, per the tabling rule this PR adds. | | Sweep fleet-wide, add each carrier | **Swept.** 12 carriers / 11 plugins filed at #2297 with evidence, conforming counter-examples, and the sweep's stated limits. Not tabled, same rule. | | Decide enforce vs document | **Decided: deferred**, recorded with basis and trigger, on the finding that the named candidate check would have missed the motivating case. | `upstream-drift` 1.3.0 → **1.4.0** (minor: additive guidance, per the contract's own versioning rule — no required part, canonical name, or enforceability verdict changed). ## Test plan ``` $ npx markdownlint-cli2 docs/conventions/upstream-drift/README.md \ docs/conventions/upstream-drift/CHANGELOG.md markdownlint-cli2 v0.23.2 (markdownlint v0.41.1) Linting: 2 files Summary: 0 issues in 0 files $ bash scripts/check-changelog-parity.sh --check-order All 75 changelog(s) read newest-first with no duplicate versions. $ bash scripts/check-changelog-parity.sh --check-bump $(git merge-base origin/main HEAD) Every plugin whose version changed vs c722271 has a '## [<version>]' CHANGELOG.md entry. ``` `--check-order` and `--check-bump` both read `docs/conventions/*/CHANGELOG.md`, so the convention changelog's `## 1.4.0 — 2026-08-12` heading form and its ordering are exercised by the run above, not assumed. The claim in §3 is quoted from `main` rather than recalled: ``` $ git show origin/main:plugins/architecture/skills/improve/SKILL.md | sed -n '71p' - **The durable candidate artifact is a per-project memory-tier file, never `${CLAUDE_PLUGIN_DATA}`.** Even resolved it points at a plugin-global dir that collides candidates across projects. ... ``` The upstream basis for calling that an upstream-owned specific was re-fetched at rung 1 during this work — `https://code.claude.com/docs/en/plugins-reference.md`, 2026-08-12 UTC, `200`, `text/markdown`, 95,338 bytes / 1,314 lines, first heading `# Plugins reference`, slug confirmed canonical against `llms.txt`, SHA-256 `f6627de35a3f285d18cf22494843bb328d65e3b867fbc1856865caa47ea3ea64` — line 709: "The `${CLAUDE_PLUGIN_DATA}` directory resolves to `~/.claude/plugins/data/{id}/` …". ## Related - Closes #2273 - Filed by this work: #2297 (the 12 fleet carriers, plus `architecture` per §3) - #2207 / #2286 — the per-plugin half; #2286 closed the false claim, this closes the fleet half - #1568, #1824 — the recurring false-claim family - #1638 — closed; established `docs/conventions/upstream-drift/` - Inbox item: `20260811-021645-plugin-audit-four-components-and-guard-deadlock-ownership` (ledger `I9-021645-four-components.md` § Lane E end) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Summary
Fixes #2207. The
improveskill's Gotcha asserted${CLAUDE_PLUGIN_DATA}"does not substitute in skill markdown content" — but the plugins reference puts skill and agent content in the "anywhere the placeholder appears" row (https://code.claude.com/docs/en/plugins-reference, Environment variables).Surgical fix per A-F2: delete the false mechanism clause only. The operative rule is unchanged — the durable candidate artifact must remain a per-project memory-tier file, never
${CLAUDE_PLUGIN_DATA}, because even resolved it points at a plugin-global dir that collides candidates across projects.The 0.3.6 CHANGELOG entry wording is preserved per upstream-drift convention; a corrective 0.5.1 entry is added additively.
Test plan
architecture0.5.0 → 0.5.1 with additive CHANGELOG entryRelated
plugin-quality)plugin-qualitycorrection)