diff --git a/docs/conventions/upstream-drift/CHANGELOG.md b/docs/conventions/upstream-drift/CHANGELOG.md index 13a5177f1c..e55a692a10 100644 --- a/docs/conventions/upstream-drift/CHANGELOG.md +++ b/docs/conventions/upstream-drift/CHANGELOG.md @@ -4,6 +4,35 @@ Notable changes to the upstream-drift contract (SemVer). Changing a required par name, or an enforceability verdict is a major bump; additive guidance is a minor bump; docs-only clarification is a patch. +## 1.4.0 — 2026-08-12 + +Closes the **adoption** gap rather than a design one: the contract already owned verification +stamps, recheck triggers, and the rule that the name binds on touch, but a plugin restating an +upstream harness fact in bare prose had no row and nothing made the stale claim surface +([#2273](https://github.com/melodic-software/claude-code-plugins/issues/2273)). Additive guidance; +no required part, canonical name, or enforceability verdict changed. + +- **`architecture` joins Adopters, and the table now says how a post-1.0.0 row got there.** The + preamble read "Migrated at this contract's 1.0.0", which an appended row would have quietly + falsified. It now distinguishes the eight migrated rows from later on-touch adoptions, requires + each later row to name the release that added it, and states the bar the third column implies: a + row is added only once the surface conforms, so a *known* unstamped carrier is a tracked issue, + never a table row. The `architecture` row records the concrete case — `improve` §Gotchas asserted + that `${CLAUDE_PLUGIN_DATA}` does not substitute in skill content while `plugins-reference` puts + skill and agent content in the "anywhere the placeholder appears" row; corrected and stamped in + `architecture` 0.5.1 ([#2207](https://github.com/melodic-software/claude-code-plugins/issues/2207)). +- **A `*-gate` CI check for adoption is deferred, recorded as a decision with its own trigger.** + The load-bearing finding is that the check already named in §Enforceability — flag a + `Verified ` with no trigger — **would not have caught the case that prompted the + question**: that surface carried no stamp at all, so a stamp-anchored grep had nothing to match. + The named check is shaped for a half-conforming record; the failure that ships is the zero-part + one, and separating an upstream restatement from an in-repo fact is a judgment about meaning + (reasoning-only under the tiers doc). A harness-vocabulary grep would fire on every correct + citation too, and a gate that forces routine suppression trains authors to bypass it. Recorded + with a basis and an event trigger — a third unstamped carrier reaching `main`, or a demonstrated + detector needing no suppression list — so the deferral can expire on evidence rather than on a + date. + ## 1.3.0 — 2026-08-11 Closes two holes in [§Reading the basis — the fetch route](README.md#reading-the-basis--the-fetch-route) diff --git a/docs/conventions/upstream-drift/README.md b/docs/conventions/upstream-drift/README.md index ef0a6deb11..d6d6e9ab29 100644 --- a/docs/conventions/upstream-drift/README.md +++ b/docs/conventions/upstream-drift/README.md @@ -277,9 +277,46 @@ Classified per `melodic-software/standards` `conventions/engineering/enforceabil | The trigger clears the observability bar | **Reasoning-only** — whether an event is decidable from evidence is a judgment about meaning. | | A trigger has fired | **Reasoning-only** today; **detect-then-judge** if a hash store lands — the hash mismatch flags, and judgment decides whether the page change touches the claim, because a changed page is not a changed fact. | +### Recorded decision — a `*-gate` check for adoption is deferred, and the named check would have missed the motivating case + +**Decided 2026-08-12 UTC: no CI gate is built for this convention, in either candidate shape.** +Recorded here as a decision rather than left implicit, because this repo's `*-gate` CI pattern is +the standing precedent for promoting a convention to a check, and the question was asked directly +([#2273](https://github.com/melodic-software/claude-code-plugins/issues/2273)). + +The premise that settles it: the candidate check named in the table above — *flag any +`Verified ` line or row whose surface states no trigger* — **would not have caught +[#2207](https://github.com/melodic-software/claude-code-plugins/issues/2207)**, the finding that +prompted the question. That surface carried no stamp at all, so a stamp-anchored grep had nothing +to match on; the check is shaped for a *half-conforming* record and the failure that actually +shipped was a *zero-part* one. The named check therefore stays named-not-built on its own build +trigger, unchanged, and is not evidence that mechanization covers this class. + +The zero-part shape has no deterministic check available. Deciding whether a sentence restates an +upstream-owned specific — as against an in-repo fact, a paraphrase of the surface's own behaviour, +or ordinary prose — is a judgment about meaning, which is **reasoning-only** under the tiers doc. +A grep for harness vocabulary (`PostToolUse`, `${CLAUDE_*}`, `settings.json`, and so on) would fire +on every correct citation and every 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. + +- **Basis** — `melodic-software/standards` `conventions/engineering/enforceability-tiers.md` + (the reasoning-only tier and the worth-mechanizing routing rule), plus the two worked instances + above. +- **Recheck trigger** — a third unstamped upstream-fact carrier reaches `main` after this decision + (two are on the record: `plugin-quality`, corrected in its 0.4.0, and `architecture`, corrected + in its 0.5.1), **or** a detector is demonstrated that separates an upstream restatement from an + in-repo one without a suppression list. Either event reopens the shape question; neither is a + date. + ## Adopters -Migrated at this contract's 1.0.0 to the single name, each citing this doc with content intact. +The first eight rows were migrated at this contract's 1.0.0 to the single name, each citing this +doc with content intact. **Rows added later are surfaces that adopted on touch** — the mechanism +the note below the table already required — and each such row names the release that added it, so +the table never implies a surface was migrated at 1.0.0 when it was not. A row is added +only once the surface actually conforms; a carrier known to be unstamped is a tracked issue, not a +table row, because the third column is a promise to the reader. The rows are not all the same thing, and the table says which is which. A **conforming record** carries the four required parts for an upstream-derived claim or decision. A **named trigger** shares the canonical name, the observability bar, and @@ -298,6 +335,7 @@ contract to fit its exceptions. | [MIGRATION-PLAYBOOK](../../MIGRATION-PLAYBOOK.md) decision records | "Revisit trigger", and "Re-trigger" on the plugin-acceptance review record | Mixed — the dated component-decision records cite upstream bases and conform; the org-internal records (e.g. the ratification and plugin-acceptance review records) are named triggers; the skill-quality retrofit record is a third kind, terminal exclusions that state "no recheck trigger" by design — decided out, so nothing fires. | | [ecosystem-commands](../ecosystem-commands/README.md) task-runner deferral | "Revisit triggers" | Named triggers only — an undated in-repo deferral; not a four-part record. | | [topic-docs](../topic-docs/README.md) §Implementers restate the rules | "What would reopen it" | Named trigger only — an in-repo source-hoisting decision; not a four-part record. | +| [`architecture`](../../../plugins/architecture/skills/improve/SKILL.md) `improve` §Gotchas — *adopted on touch, added 1.4.0* | bare prose: an upstream substitution claim with no basis, no date, and no trigger | One conforming record — the `${CLAUDE_PLUGIN_DATA}` bullet cites `plugins-reference` §Environment variables with a UTC fetch date and a divergence-at-fetch trigger naming the specific table row the claim rests on. It is the plugin's only surface restating an upstream specific (swept at adoption), so the row covers the plugin, not one bullet. | Elsewhere the name binds on touch: living surfaces still saying "revisit trigger", "re-trigger", "re-derivation trigger", or "what would reopen it" (several plugin reference docs already use the diff --git a/plugins/architecture/.claude-plugin/plugin.json b/plugins/architecture/.claude-plugin/plugin.json index 24c9df79d2..5e2dcda01f 100644 --- a/plugins/architecture/.claude-plugin/plugin.json +++ b/plugins/architecture/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "architecture", - "version": "0.5.0", + "version": "0.5.1", "description": "Scans an existing codebase for module-level architecture friction — shallow modules, seam leaks, and locality gaps — using Ousterhout's deep-module lens, presents candidates as a self-contained HTML report, and runs an interview loop on the selected candidate before handing off for planning.", "author": { "name": "Melodic Software", diff --git a/plugins/architecture/CHANGELOG.md b/plugins/architecture/CHANGELOG.md index 87ca795e09..a806dcfcb2 100644 --- a/plugins/architecture/CHANGELOG.md +++ b/plugins/architecture/CHANGELOG.md @@ -3,6 +3,44 @@ All notable changes to the `architecture` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.5.1] + +### Fixed + +- **`improve`: the `${CLAUDE_PLUGIN_DATA}` Gotcha stated a false mechanism; the rule it justified + now rests on the true one.** The bullet asserted that the token "does not substitute in skill + markdown content (it is a hook/monitor/MCP path substitution only)". It **does** substitute: the + plugins reference's per-component table puts *skill and agent content* in the "anywhere the + placeholder appears" row, alongside hook and monitor commands, with no version qualifier + (, §Environment variables, re-fetched + 2026-08-12 UTC over the raw-markdown channel — `200`, `text/markdown`, 95,338 bytes / 1,314 + lines, first heading `# Plugins reference`, slug confirmed canonical against `llms.txt`, SHA-256 + `f6627de35a3f285d18cf22494843bb328d65e3b867fbc1856865caa47ea3ea64`). The routing decision the + sentence defended is **unchanged and still correct**, on three legs the same page supplies and + this release states in its place: the token resolves to `~/.claude/plugins/data/{id}/`, which has + no project dimension and so collides candidates across codebases; uninstalling from the last + remaining scope deletes that directory by default; and its named use is installed dependencies, + generated code, and caches. The corrected sentence lands as a conforming upstream-drift record — + basis, as-of date, and a recheck trigger — so a later reader can tell a fresh claim from a stale + one, which is what let this one survive four releases. (Closes + melodic-software/claude-code-plugins#2207. The same false sentence was authored into + `plugin-quality` and corrected there in 0.4.0 via #1808; both plugins' histories now converge on + one explanation.) + +### Erratum — the 0.3.6 entry's stated reason, left as it shipped + +- **The 0.3.6 "Fixed" entry below gives a false reason for a change that was itself correct, and is + deliberately not edited.** It says the artifact path stopped using `${CLAUDE_PLUGIN_DATA}` + because that token "does not substitute in skill markdown content" — the claim corrected above. + The *path* change 0.3.6 made was right and stays right; only its stated mechanism was wrong. The + 0.4.1 entry's promotion of that rationale to a permanent Gotcha is left standing for the same + reason: shipped history is never rewritten, so an erratum points forward rather than editing the + record (`docs/conventions/upstream-drift/README.md` §Adopters). This note does **not** claim the + 0.3.6 symptom was imaginary. What a 0.3.5 consumer observed is not settled here and is out of + scope: an unexpanded token reaching a consumer is fully consistent with the correction above, + since reading a file returns its literal bytes whatever the loader substitutes at load time, and + 0.3.5 carried the token in a `Read`-loaded `actions/*.md` step rather than in a `SKILL.md` body. + ## [0.5.0] ### Removed diff --git a/plugins/architecture/skills/improve/SKILL.md b/plugins/architecture/skills/improve/SKILL.md index 1e20479347..241e11fd47 100644 --- a/plugins/architecture/skills/improve/SKILL.md +++ b/plugins/architecture/skills/improve/SKILL.md @@ -68,5 +68,5 @@ Graceful degradation — where a named step below is not available in the consum Observed failure history — patterns that have actually bitten. Add here when a new one surfaces. -- **The durable candidate artifact is a per-project memory-tier file, never `${CLAUDE_PLUGIN_DATA}`.** That token does not substitute in skill markdown content (it is a hook/monitor/MCP path substitution only), and even resolved it points at a plugin-global dir that collides candidates across projects. The artifact resolves through the marketplace topic-docs convention (the plugin's topic-docs [binding](../../reference/topic-docs.md)) — memory tier, default `.work//`. A `${CLAUDE_PROJECT_DIR}/.claude/...` path is also wrong: `.claude/` generated output is reserved for observability, and an unignored artifact there leaks scan output into git. +- **The durable candidate artifact is a per-project memory-tier file, never `${CLAUDE_PLUGIN_DATA}`.** That token **does** resolve in skill content — the plugins reference puts skill and agent content in the "anywhere the placeholder appears" row alongside hook and monitor commands (, §Environment variables, fetched 2026-08-12 UTC; recheck trigger: a read-time re-fetch of that section finds the "Skill and agent content" row changed or removed). The rule rests on **where the path points**, not on whether it expands: the same page resolves the token to `~/.claude/plugins/data//` — a plugin-global directory with no project dimension, so candidates from every codebase collide in one place — records that uninstalling from the last remaining scope deletes that directory by default, and names its use as installed dependencies, generated code, and caches. The artifact resolves through the marketplace topic-docs convention (the plugin's topic-docs [binding](../../reference/topic-docs.md)) — memory tier, default `.work//`. A `${CLAUDE_PROJECT_DIR}/.claude/...` path is also wrong: `.claude/` generated output is reserved for observability, and an unignored artifact there leaks scan output into git. - **Scan-agent claims are shipped only after Phase 1.5 reproduction.** Explore agents have a demonstrated error rate: a real run reported a service "registered but never composed — a bug in the seam" that one grep disproved (it *is* consumed, via a different consumer, with tests). Any candidate headed for a `Strong` badge and any runtime-bug / dead-code claim is reproduced against the actual code before it reaches the user-facing report — the report lends every claim its authority, so an unreproduced overstatement is cheap to make and expensive to reputation.