From 78527a17b5ec4181dfcb0fae4c5c612aee87bd11 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Tue, 11 Aug 2026 23:22:15 -0400 Subject: [PATCH] chore(conventions): route unstamped upstream-fact carriers into upstream-drift, and record the gate deferral MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plugins restate upstream harness facts in bare prose — no source, no as-of date, no recheck trigger — so when the upstream behaviour changes nothing makes the stale claim surface. The convention already owned verification stamps, recheck triggers, and the rule that the name binds on touch; the gap was adoption, not design. Three changes, all additive guidance (1.3.0 -> 1.4.0): 1. The Adopters preamble read "Migrated at this contract's 1.0.0", which any appended row would have quietly falsified. It now separates the migrated rows from later on-touch adoptions, requires each later row to name the release that added it, and writes down the bar the third column already implied: a surface is tabled only once it CONFORMS, so a carrier known to be unstamped is a tracked issue rather than a row. That column is a promise to a reader. 2. A fleet sweep of plugins/** found 12 carriers across 11 plugins, filed at #2297 with quoted lines, the files checked and found conforming, and the sweep's own limitation stated (a file-level citation gate under-represents mixed files, so the list is a lower bound). None is tabled here, per the rule above. 3. A CI gate for adoption is deferred, recorded as a decision with a basis and an event trigger. The load-bearing finding: the check the doc already names — flag a `Verified ` with no trigger — would NOT have caught #2207, the case that prompted the question, because that surface carried no stamp at all for a stamp-anchored grep to match. The named check is shaped for a half-conforming record; the failure that ships is the zero-part one. Separating an upstream restatement from an in-repo fact is a judgment about meaning, reasoning-only under the tiers doc, and a harness-vocabulary grep would fire on every correct citation too. architecture is deliberately NOT added to the table: #2286 removed the false substitution claim but left an unstamped upstream specific in the same bullet ("even resolved it points at a plugin-global dir"), so the plugin does not yet conform. It is recorded in #2297 instead — which is exactly what change 1 says to do. Co-Authored-By: Claude Opus 5 (1M context) --- docs/conventions/upstream-drift/CHANGELOG.md | 34 ++++++++++++++++ docs/conventions/upstream-drift/README.md | 43 +++++++++++++++++++- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/docs/conventions/upstream-drift/CHANGELOG.md b/docs/conventions/upstream-drift/CHANGELOG.md index 13a5177f1c..54aef25c51 100644 --- a/docs/conventions/upstream-drift/CHANGELOG.md +++ b/docs/conventions/upstream-drift/CHANGELOG.md @@ -4,6 +4,40 @@ 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 plugins restating upstream +harness facts in bare prose had no route into the Adopters table and nothing made a 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. + +- **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 migrated rows from later on-touch adoptions and requires each + later row to name the release that added it. It also states the bar the third column already + implied but never wrote down: **a surface is tabled only once it conforms**, so a carrier known to + be unstamped is a tracked issue rather than a row. That column is a promise to a reader, and + tabling an unstamped surface would assert exactly what the reader would then not get. +- **The fleet's open carriers are recorded where that rule sends them.** A sweep of `plugins/**` for + surfaces stating an upstream harness behaviour with no source, date, or trigger found 12 carriers + across 11 plugins, filed with quoted lines at + [#2297](https://github.com/melodic-software/claude-code-plugins/issues/2297) — along with the + files checked and found *conforming*, and the sweep's own limitation (a file-level citation gate + under-represents mixed files, so the list is a lower bound and says so). None is tabled here. +- **An adoption CI gate is deferred, recorded as a decision with its own trigger.** The + load-bearing finding is that the check §Enforceability already names — flag a `Verified ` + with no trigger — **would not have caught the case that prompted the question** + ([#2207](https://github.com/melodic-software/claude-code-plugins/issues/2207)): 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 fires 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 expires on evidence rather than on a date. The existing named-not-built check and + its own build trigger are unchanged. + ## 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..f6367a5711 100644 --- a/docs/conventions/upstream-drift/README.md +++ b/docs/conventions/upstream-drift/README.md @@ -277,9 +277,50 @@ 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 — an adoption gate is deferred, and the check named above would have missed the case that prompted it + +**Decided 2026-08-12 UTC: no CI gate is built for adoption of this convention, in either candidate +shape.** Recorded 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 named check is shaped for a *half-conforming* record; the failure that actually ships +is the *zero-part* one. It 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 description 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) fires 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 worked instance above. +- **Recheck trigger** — a third unstamped upstream-fact carrier reaches `main` after this decision + (two are already on the record: `plugin-quality`, corrected in its 0.4.0, and `architecture`, + whose false claim was removed 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 rows below were migrated at this contract's 1.0.0 to the single name, each citing this doc with +content intact. **A row added after 1.0.0 is a surface that adopted on touch** — the mechanism the +note under the table already requires — and names the release that added it, so the table never +implies a surface was migrated at 1.0.0 when it was not. + +**A surface is tabled only once it actually conforms.** The third 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. The fleet's open +carriers are recorded that way in +[#2297](https://github.com/melodic-software/claude-code-plugins/issues/2297). + 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