Skip to content

fix(architecture): remove false CLAUDE_PLUGIN_DATA substitution claim from improve Gotcha - #2286

Merged
kyle-sexton merged 1 commit into
mainfrom
cursor/fix-architecture-plugin-data-gotcha-63e1
Aug 12, 2026
Merged

fix(architecture): remove false CLAUDE_PLUGIN_DATA substitution claim from improve Gotcha#2286
kyle-sexton merged 1 commit into
mainfrom
cursor/fix-architecture-plugin-data-gotcha-63e1

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

Summary

Fixes #2207. The improve skill'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

  • Verify the Gotcha bullet no longer claims non-substitution in skill content
  • Verify collision/topic-docs routing prose is intact
  • Version bump architecture 0.5.0 → 0.5.1 with additive CHANGELOG entry

Related

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>
@cursor

cursor Bot commented Aug 12, 2026

Copy link
Copy Markdown

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

claude Bot commented Aug 12, 2026

Copy link
Copy Markdown

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


Security review complete

  • Gather context (PR diff, changed files)
  • Review plugins/architecture/.claude-plugin/plugin.json
  • Review plugins/architecture/CHANGELOG.md
  • Review plugins/architecture/skills/improve/SKILL.md
  • Assess for security issues (logic flaws, injection, secrets handling, GH Actions risk)
  • Post final findings

No security issues found.

This PR is a documentation-only change: a version bump in plugin.json (0.5.0 → 0.5.1), an additive CHANGELOG.md entry, and a one-sentence correction to a Gotcha bullet in skills/improve/SKILL.md that removes a false claim about ${CLAUDE_PLUGIN_DATA} substitution behavior. There is no code execution path, no GitHub Actions workflow touched, no secrets/token handling, no permission changes, and no dependency/action pinning affected by this diff. The remaining text (the operative rule that the durable candidate artifact must never live at ${CLAUDE_PLUGIN_DATA}) is preserved unchanged, so no new guidance that could lead to unsafe path handling was introduced.

Scope reviewed: plugins/architecture/.claude-plugin/plugin.json, plugins/architecture/CHANGELOG.md, plugins/architecture/skills/improve/SKILL.md (the three files changed in this PR, per git diff origin/main...HEAD).

@claude

claude Bot commented Aug 12, 2026

Copy link
Copy Markdown

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


Claude finished the review

  • Gather context (CLAUDE.md, REVIEW.md, diff, related conventions, precedent PRs)
  • Review plugin.json version bump
  • Review CHANGELOG.md entry
  • Review SKILL.md Gotcha edit for correctness/accuracy
  • Post findings

Summary

This is a clean, surgical fix. I independently verified the central factual claim rather than trusting the PR description: I fetched https://code.claude.com/docs/en/plugins-reference.md via WebFetch (note: this is a rung-2/summarizing fetch per this repo's own upstream-drift convention, not the rung-1 curl the convention prefers — but sufficient to confirm the table). The live doc's "Environment variables" section does list:

| Skill and agent content | Anywhere the placeholder appears |

confirming ${CLAUDE_PLUGIN_DATA} does substitute in skill/agent markdown. The deleted clause in plugins/architecture/skills/improve/SKILL.md ("That token does not substitute in skill markdown content ... hook/monitor/MCP path substitution only") was indeed false, and the PR removes exactly that clause while leaving the operative rule intact (never use ${CLAUDE_PLUGIN_DATA} for the durable candidate artifact — it's plugin-global and collides candidates across projects).

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.

@github-actions

Copy link
Copy Markdown

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

@kyle-sexton
kyle-sexton merged commit a12b340 into main Aug 12, 2026
35 checks passed
@kyle-sexton
kyle-sexton deleted the cursor/fix-architecture-plugin-data-gotcha-63e1 branch August 12, 2026 02:31
kyle-sexton added a commit that referenced this pull request Aug 12, 2026
…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>
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.

fix(architecture): improve's Gotcha asserts ${CLAUDE_PLUGIN_DATA} does not substitute in skill content — plugins-reference says it does

2 participants