Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions docs/conventions/upstream-drift/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <date>` 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)
Expand Down
40 changes: 39 additions & 1 deletion docs/conventions/upstream-drift/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <date>` 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
Expand All @@ -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. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Do not certify the entire plugin from this one record

The claim that this is the plugin's only upstream-specific surface is contradicted by plugins/architecture/skills/improve/actions/deepening.md:26, which directs consumers to the upstream-owned Agent tool syntax subagent_type=Explore without a basis, date, or trigger. Because this row explicitly says it covers the whole plugin rather than the linked bullet, readers are told the plugin was swept and conforms when another durable operational surface remains unstamped; either scope the row to the bullet or disposition the other upstream-specific surfaces before making the plugin-wide claim.

Useful? React with 👍 / 👎.


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
Expand Down
2 changes: 1 addition & 1 deletion plugins/architecture/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
38 changes: 38 additions & 0 deletions plugins/architecture/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
(<https://code.claude.com/docs/en/plugins-reference>, §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
Expand Down
2 changes: 1 addition & 1 deletion plugins/architecture/skills/improve/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/<topic-slug>/`. 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 (<https://code.claude.com/docs/en/plugins-reference>, §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/<id>/` — 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/<topic-slug>/`. 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.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Cover every upstream fact in the recheck trigger

The trigger only fires when the "Skill and agent content" substitution row changes, but this same record also relies on three separate upstream facts: the resolved directory, last-scope uninstall deletion, and the directory's documented uses. If any of those change while the substitution row remains intact, the trigger never fires and the rationale becomes stale despite being advertised as a conforming four-part record. Expand the trigger to cover divergence in every upstream fact restated here, consistent with docs/conventions/upstream-drift/README.md:64-71 and 104-111.

Useful? React with 👍 / 👎.

- **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.