diff --git a/docs/MIGRATION-PLAYBOOK.md b/docs/MIGRATION-PLAYBOOK.md index d72ab27714..74d1593d4d 100644 --- a/docs/MIGRATION-PLAYBOOK.md +++ b/docs/MIGRATION-PLAYBOOK.md @@ -1089,8 +1089,10 @@ alternative. Both vendors are unidentified operators with unstated retention — unknown, not waved through — and the untrusted-content risk is contained by advisory instruction that is labeled advisory. -**Re-trigger:** re-introducing a Bash or PowerShell pre-approval, shipping the deferred validating -`PreToolUse` hook, or adding an MCP surface each re-opens this review. +**Recheck trigger:** a named trigger on an in-repo decision +([upstream-drift](conventions/upstream-drift/README.md)) — re-introducing a Bash or PowerShell +pre-approval, shipping the deferred validating `PreToolUse` hook, or adding an MCP surface each +re-opens this review. ## Local development loop @@ -1250,16 +1252,21 @@ Alternatives weighed (docs verified 2026-07-03): - **Dependency plugin carrying the lib — rejected as not viable.** A hook sees only its own `${CLAUDE_PLUGIN_ROOT}` / `${CLAUDE_PLUGIN_DATA}`; no variable or documented mechanism exposes a *dependency's* install path, and cache directories are per-version (with a commit-SHA suffix for - tag-resolved dependencies), so computing the path is unsupported by design (plugins-reference - "Plugin caching and file resolution"; plugin-dependencies guide). Revisit iff Claude Code ships a - documented dependency-path variable — that would also allow sharing the lib beyond this marketplace. + tag-resolved dependencies), so computing the path is unsupported by design + (; + ). **Recheck trigger:** Claude Code + ships a documented dependency-path variable — that would also allow sharing the lib beyond this + marketplace. - **Marketplace-internal symlinks — deferred.** Documented mechanism: a symlink from a plugin to a file elsewhere in the same marketplace is dereferenced at install, copying the target's content into - the cache — native SSOT with no sync script (plugins-reference "Share files within a marketplace - with symlinks"). Deferred because such symlinks are *skipped* for `--plugin-dir` / local-path + the cache — native SSOT with no sync script + (). + Deferred because such symlinks are *skipped* for `--plugin-dir` / local-path installs (breaking the local development loop above) and are fragile to author and clone on Windows, - the primary environment on both the authoring and consuming side. Revisit if the dev loop stops - depending on `--plugin-dir` or the Windows constraint lifts. + the primary environment on both the authoring and consuming side. **Recheck trigger:** the dev + loop stops depending on `--plugin-dir`, the documented `--plugin-dir` / local-path handling changes + so marketplace symlinks are no longer skipped (the upstream premise this deferral rests on), or the + Windows constraint lifts. - **Copies with only a byte-identity CI gate — subsumed.** The chosen shape is that gate plus a canonical source and one sync script, removing the edit-×N-by-hand step at negligible cost. @@ -1311,41 +1318,50 @@ needs the same source. ## Deferred surfaces — decision record (2026-07-12) Three general-purpose surfaces in the harvest-source repo (`melodic-software/medley`) are held out of this -wave's plugin migration deliberately, each with an explicit revisit trigger — recorded here so the deferral +wave's plugin migration deliberately, each with an explicit +[recheck trigger](conventions/upstream-drift/README.md) — recorded here so the deferral is a decision, not a silent omission. The medley side carries a thin pointer back to this record at each surface (the workflow-engine authoring rule, the `onboard` skill, and the `gh-bot.sh` bot-identity convention), so a contributor who touches a deferred surface finds the trigger without leaving that repo. - **Workflow engines** (`code-review.js`, `codebase-review.js`, `deep-research.js`, - `research-deep-fanout.js`, `skills-audit.js`, `skills-evals.js`, `skills-remediate.js`): not a plugin - component per current docs — the `Workflow` tool loads an engine script from disk and a plugin manifest - has no native slot to ship one, so these may be removed entirely rather than migrated. **Revisit - trigger:** the engines survive the next usage review (still earning their keep) → package as a plugin - skill that dispatches the engine through the `Workflow` tool's `scriptPath`, resolved under - `${CLAUDE_PLUGIN_ROOT}`, with a smoke test specced for that dispatch path before packaging. + `research-deep-fanout.js`, `skills-audit.js`, `skills-evals.js`, `skills-remediate.js`): deferred + 2026-07-12 as not a plugin component, so these may be removed entirely rather than migrated. + Re-verified 2026-07-27: the no-native-slot premise no longer holds — plugins now ship workflow + scripts via a `workflows/` directory + () or the `workflows` + manifest field (), and a + plugin workflow runs plugin-namespaced + () — but the deferral + stands on the usage question alone. **Recheck trigger:** the engines survive the next usage review + (still earning their keep) → migrate through the native plugin `workflows/` slot, verifying each + engine script fits the documented workflow-script shape, with a smoke test specced for that + dispatch path before packaging. - **`onboard` skill:** repo-specific today — its phase gates encode this repo's exact runtime, linter, and - tooling pins. **Revisit trigger:** a second repo needs environment-prerequisite auditing → extract a + tooling pins. **Recheck trigger:** a second repo needs environment-prerequisite auditing → extract a generic core through the extensibility-contract seams (the convention-resolution ladder infers or asks for the per-repo pins), leaving repo specifics in tracked config rather than baked into the skill. -- **`tools/github-auth` (`gh-bot.sh`):** hardcodes the org's bot App / installation identity. **Revisit +- **`tools/github-auth` (`gh-bot.sh`):** hardcodes the org's bot App / installation identity. **Recheck trigger:** a second repo needs bot-actor GitHub operations → parameterize org / App / installation through the seams (`userConfig` scalars, `sensitive` for the key) instead of standing up a second hardcoded wrapper. ## Unused official plugin components — decision record (2026-07-12) -Three official plugin components the marketplace does not yet use, evaluated for adoption against the -enforcement hierarchy (default **REJECT** unless the value is concrete and not already covered by an -existing mechanism). Facts verified fresh 2026-07-12 per `CLAUDE.md` "Fresh-docs mandate". Verdict for -all three: **REJECT now**, each with an explicit revisit trigger — no implementation issues emitted (zero -accepted). +The three unused official plugin components raised as adoption candidates on this date, evaluated +against the enforcement hierarchy (default **REJECT** unless the value is concrete and not already +covered by an existing mechanism). This is that evaluation, not an index of every component the +marketplace does not use — the [component-stances table](PLUGIN-PHILOSOPHY.md#component-stances) is +that index, and it carries a stance for components never raised here. Facts verified fresh +2026-07-12 per `CLAUDE.md` "Fresh-docs mandate". Verdict for all three: **REJECT now**, each with an +explicit recheck trigger — no implementation issues emitted (zero accepted). - **Monitors** (`monitors/monitors.json` / `experimental.monitors`) — **REJECT.** Both candidates are either already covered or not concrete: a PR/CI watch duplicates `/source-control:pull-request monitor` and a consumer's channel-mode PR watch (no gap), and a claude-ops collector-health watch carries no concrete recurring pain that outweighs adopting an `experimental.*` component whose manifest schema may change between releases (and which is skipped on the hosts / telemetry-disabled configs where the - Monitor tool is unavailable). **Revisit trigger:** monitors leave the `experimental` key AND a concrete + Monitor tool is unavailable). **Recheck trigger:** monitors leave the `experimental` key AND a concrete recurring in-session watch need surfaces for a shipped plugin, scoped via the documented `when: "on-skill-invoke:"` monitor field so it starts only on demand rather than at session start. Upstream: @@ -1357,13 +1373,13 @@ accepted). invocation, which risks name collisions with the consumer's own commands, so it earns its place only where a script is meant to be run as a bare command by the consumer. The one live candidate — the knowledge plugin's extraction tooling — is owned by its publish issue #1373; the `bin/`-vs-`scripts/` - call belongs there, not duplicated here. **Revisit trigger:** a shipped plugin has a script the consumer + call belongs there, not duplicated here. **Recheck trigger:** a shipped plugin has a script the consumer invokes as a bare command (not an internal helper). Upstream: . - **`subagentStatusLine`** (plugin `settings.json`) — **REJECT.** Purely cosmetic: it re-formats the subagent panel row with no functional capability, so it does not clear the default-REJECT bar; its richest inputs (per-row model + context-window size for a context percentage) additionally require a - recent Claude Code minimum. Candidate home was claude-ops. **Revisit trigger:** a concrete operational + recent Claude Code minimum. Candidate home was claude-ops. **Recheck trigger:** a concrete operational need for custom subagent-row data during orchestration, not a presentation preference. Upstream: , . @@ -1384,8 +1400,15 @@ the wave's codification requirement puts convention decisions in tracked docs, n fresh analysis — the corpus is the durable substrate for re-runnable synthesis, not just derived text. LFS-backed: a `.gitattributes` tracking media globs (mp4/mov/webm/png/jpg/jpeg/gif/pdf/epub/ mp3/wav) plus pushed LFS objects. Git LFS is **not** expressible on the pulumi-github v6.14.0 - `Repository` resource (verified against the provider schema) → it is content-side, landing via a - follow-up content PR to the repo, not governed in IaC. GitHub's quotas, metering, and prices change; + `Repository` resource → it is content-side, landing via a follow-up content PR to the repo, not + governed in IaC. Basis: the provider schema at the pinned tag — + , + where `github:index/repository:Repository` declares 48 properties and 39 input properties, none + matching `lfs`, and the document contains no case-insensitive `lfs` match at all (fetched and + probed 2026-07-29; re-run the same fetch against the then-pinned tag when the trigger below fires). + **Recheck trigger:** a pulumi-github + release notes LFS support on `Repository`, or the pinned provider version moves past v6.14.0 → + re-derive the IaC-vs-content-side call. GitHub's quotas, metering, and prices change; verify the current account allowance, budget, and overage behavior in the [official Git LFS billing documentation](https://docs.github.com/en/billing/concepts/product-billing/git-lfs) before changing retention or ownership policy. @@ -1407,7 +1430,7 @@ the wave's codification requirement puts convention decisions in tracked docs, n The `skill-quality` plugin shipped only the generic static contract checker (`check-skill.sh`, seventeen model-free checks) plus the `evals.schema.json` validation asset. Its held-back scope is resolved here as **terminal exclusions** — decided out of the plugin for good, each with a permanent home, **not** deferrals -with a revisit trigger. (Contrast the "Deferred surfaces" record above, where the medley surface is held +with a recheck trigger. (Contrast the "Deferred surfaces" record above, where the medley surface is held *pending* a trigger; these are held *out*.) - **A/B eval runner** (`tools/evals/run-skill-comparison.sh`): a headless `claude -p` skill-body A/B @@ -1415,7 +1438,7 @@ with a revisit trigger. (Contrast the "Deferred surfaces" record above, where th plugin component; stays medley-owned in `tools/evals/`.** It is a *dynamic authoring experiment* harness, a distinct concern from this plugin's *static QA gate* (one cohesive capability per plugin — see the design charter), with a single consumer and ~29 KB of worktree / hub-safety / platform path-scrub - surface that would be marketplace upkeep for that one consumer. **No revisit trigger:** a genuine + surface that would be marketplace upkeep for that one consumer. **No recheck trigger:** a genuine second-consumer demand is a fresh publish issue, not standing debt. - **Contract libs** (`tools/skill-contract/`: portability, encapsulation, script-contract, dispatcher): enforce medley-**invented** regimes — the skill public-surface / encapsulation contract, BEHAVIOR.md @@ -1467,7 +1490,7 @@ So none is added. **The only real distinguisher (flagged, not imposed).** Cryptographic separation requires an identity agents do **not** hold — a distinct human-only GitHub account and/or a signing key kept off the agent runners, with branch protection requiring that identity's review on `docs/conventions/**`. That is an -infrastructure change with real operator cost. **Revisit trigger:** the operator wants provable human +infrastructure change with real operator cost. **Recheck trigger:** the operator wants provable human ratification, or a second human contributor joins (at which point identity separation exists naturally). **Interim posture.** Ratification stays **trust-based and visible**: a convention-seam change **should diff --git a/docs/OFFICIAL-DOCS.md b/docs/OFFICIAL-DOCS.md index c547a80c7f..5db1c797e6 100644 --- a/docs/OFFICIAL-DOCS.md +++ b/docs/OFFICIAL-DOCS.md @@ -12,7 +12,10 @@ training-data recall. > [`https://code.claude.com/docs/llms.txt`](https://code.claude.com/docs/llms.txt); if a page listed > here is missing from it, or a page you need isn't listed here, treat `llms.txt` as the source of > truth and update this file. Every row below was verified against a live fetch on the date shown — -> that date is the ceiling on how current the row still is, not a guarantee. +> that date is the ceiling on how current the row still is, not a guarantee. A fetch that no longer +> matches a row is that row's recheck trigger: update the row, refreshing its date with the +> outcome. The [upstream-drift convention](conventions/upstream-drift/README.md) owns this +> stamp-and-trigger discipline. ## Plugin components → doc page @@ -20,13 +23,18 @@ One row per plugin component type, per the current [Plugins reference](https://c `Commands` is the legacy flat-markdown form of a skill — the [Skills](https://code.claude.com/docs/en/skills) page is authoritative for both. Statusline is not its own plugin component: it is one of the two settings keys (`subagentStatusLine`) a plugin's `settings.json` may set. Channels are declared via a -`channels` manifest field bound to an MCP server, not a separate file location. +`channels` manifest field bound to an MCP server, not a separate file location. Workflows have no +per-component section in the Plugins reference — that page carries the slot in its standard-layout +and file-locations tables, and the [Workflows](https://code.claude.com/docs/en/workflows) page is +authoritative for the component. The manifest (`.claude-plugin/plugin.json`) is the container these +components are declared in, not a component, so it has no row. | Component | Official doc page | Verified date | |---|---|---| | Skills (`skills/`) | | 2026-07-17 | | Commands — legacy flat-file skills (`commands/`) | | 2026-07-17 | | Agents / subagents (`agents/`) | | 2026-07-17 | +| Workflows (`workflows/`) | | 2026-07-27 | | Hooks (`hooks/hooks.json`) | | 2026-07-17 | | MCP servers (`.mcp.json`) | | 2026-07-17 | | LSP servers (`.lsp.json`) | | 2026-07-17 | @@ -49,7 +57,7 @@ settings keys (`subagentStatusLine`) a plugin's `settings.json` may set. Channel | Hooks reference | | 2026-07-17 | | Automate actions with hooks (guide) | | 2026-07-17 | | Subagents | | 2026-07-17 | -| Dynamic workflows — script-held orchestration, runtime agent caps | | 2026-07-26 | +| Dynamic workflows — script-held orchestration, runtime agent caps | | 2026-07-27 | | MCP | | 2026-07-17 | | Connect to MCP servers (quickstart) | | 2026-07-17 | | Output styles | | 2026-07-17 | diff --git a/docs/PLUGIN-PHILOSOPHY.md b/docs/PLUGIN-PHILOSOPHY.md index f95fd6a427..caf9544b25 100644 --- a/docs/PLUGIN-PHILOSOPHY.md +++ b/docs/PLUGIN-PHILOSOPHY.md @@ -118,13 +118,16 @@ native one matures into fitness. > **Staleness disclaimer.** The platform changes constantly. Every row carries the date its facts > were verified against the linked official page. Always re-fetch the current page before acting on -> a row; never trust this table alone. +> a row; never trust this table alone. A fetch that diverges from a row is that row's recheck +> trigger: update the row, refreshing its verified date with the outcome. The +> [upstream-drift convention](conventions/upstream-drift/README.md) owns this stamp discipline. | Component | Stance | Rationale and constraints | Verified | |---|---|---|---| | [Skills](https://code.claude.com/docs/en/skills) | Primary surface | The default unit of capability. Newer frontmatter — `paths`, `context: fork` (+ `agent`), `arguments`, skill-scoped `hooks` with `once` — adopted case-by-case through the adoption gate. | 2026-07-17 | | [`commands/`](https://code.claude.com/docs/en/plugins-reference) | Prohibited | Officially merged into skills; docs direct "use `skills/` for new plugins". Existing flat commands migrate to skill directories. | 2026-07-17 | | [Agents](https://code.claude.com/docs/en/sub-agents) | Adopt on need | Plugin agents do not support `hooks`, `mcpServers`, or `permissionMode` (security restriction) — design within that limit rather than working around it. | 2026-07-17 | +| [Workflows](https://code.claude.com/docs/en/workflows) | Adopt on need | Native and not experimental: a script in `workflows/`, or wherever the `workflows` manifest field points (that field replaces the default scan), runs as a plugin-namespaced `/plugin:name` command. Availability, not maturity, is the constraint — workflows are paid-plan-gated, a consumer can switch them off (`disableWorkflows`, `CLAUDE_CODE_DISABLE_WORKFLOWS`), and an org can disable them fleet-wide in managed settings; so, as with `bin/`, never make a workflow the only path to a capability. Not "Wait": the [deferred workflow engines](MIGRATION-PLAYBOOK.md#deferred-surfaces--decision-record-2026-07-12) are a named candidate carrying a live trigger, so the gap is identified rather than hypothetical. None ship in this fleet today. | 2026-07-27 | | [Hooks](https://code.claude.com/docs/en/hooks) | Adopt on need | Exec form (`args`) is mandatory wherever `${user_config.*}` appears — shell form errors since v2.1.207; otherwise read the `CLAUDE_PLUGIN_OPTION_` mirror. Windows exec form spawns real executables only (no `.cmd`/`.bat` shims): use `"command": "node", "args": [...]`. | 2026-07-17 | | [MCP servers](https://code.claude.com/docs/en/mcp) | Adopt on need | Clears the plugin-acceptance security review for egress and trust delegation. | 2026-07-17 | | [LSP servers](https://code.claude.com/docs/en/plugins-reference) | Adopt on need | Consumer must have the language-server binary; declare the prerequisite per the failure-behavior rules. | 2026-07-17 | @@ -423,6 +426,7 @@ doc before a second plugin adopts it. Fleet audits check conformance per row. | Shell test-helper duplication and exit-code divergence | [`docs/conventions/shell-test-helpers/`](conventions/shell-test-helpers/README.md) | | Finding suppression (deliberately-kept audit findings) | [`docs/conventions/finding-suppression/`](conventions/finding-suppression/README.md) | | Fresh-eyes declaration pattern contract | `skill-quality` plugin (`skills/check/reference/fresh-eyes-declarations.md`) | +| Upstream-drift verification stamps and recheck triggers | [`docs/conventions/upstream-drift/`](conventions/upstream-drift/README.md) | ## Cross-platform contract diff --git a/docs/conventions/ecosystem-commands/CHANGELOG.md b/docs/conventions/ecosystem-commands/CHANGELOG.md index 16007d5334..26797995c5 100644 --- a/docs/conventions/ecosystem-commands/CHANGELOG.md +++ b/docs/conventions/ecosystem-commands/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog — ecosystem-commands convention +## 1.2.3 — 2026-07-26 + +Docs-only, no schema shape change: the task-runner deferral's "Revisit triggers" label becomes +"Recheck triggers" and cites the [upstream-drift convention](../upstream-drift/README.md) (#1638), +the new owner of the concept's single name and shape. The triggers themselves are unchanged. + ## 1.2.2 — 2026-07-26 Docs-only, no schema shape change: `examples/go.yaml`'s illustrative `proto-gen-freshness` gate diff --git a/docs/conventions/ecosystem-commands/README.md b/docs/conventions/ecosystem-commands/README.md index 92095914b2..2634d087b2 100644 --- a/docs/conventions/ecosystem-commands/README.md +++ b/docs/conventions/ecosystem-commands/README.md @@ -154,7 +154,7 @@ Because command values are opaque strings, later adoption is a mechanical value (`check-cmd: 'task lint:python'` or `check-cmd: 'lefthook run lint-python'`) with zero schema change — the demotion path is designed in. -**Revisit triggers** (either fires → re-evaluate): +**Recheck triggers** ([upstream-drift](../upstream-drift/README.md); either fires → re-evaluate): - The same logical verb's command string is maintained across 3+ execution surfaces such that one command bump requires 3+ coordinated edits; or diff --git a/docs/conventions/hook-config-delivery/CHANGELOG.md b/docs/conventions/hook-config-delivery/CHANGELOG.md index f6ff221a2d..d9ee1c7176 100644 --- a/docs/conventions/hook-config-delivery/CHANGELOG.md +++ b/docs/conventions/hook-config-delivery/CHANGELOG.md @@ -5,6 +5,14 @@ change to the decision rule or to a matrix row's verdict is a major bump; adding or a recheck trigger additively is a minor bump. The version-pinned facts table is evidence, not contract — refreshing a pin or recheck date without a verdict change is no bump. +## 1.1.0 — 2026-07-27 + +No verdict change: the Recheck-triggers section cites the +[upstream-drift convention](../upstream-drift/README.md) (#1638), the new owner of the +stamp-and-trigger discipline this doc already practiced, and gains an additive sixth trigger +covering facts 7–8 (body substitution and sensitive-value storage), which previously had no +event naming their recheck. + ## 1.0 — 2026-07-24 Initial published contract, codifying the channel decision matrix from the userConfig→hook delivery diff --git a/docs/conventions/hook-config-delivery/README.md b/docs/conventions/hook-config-delivery/README.md index f9824aed48..ccd7ebe1dd 100644 --- a/docs/conventions/hook-config-delivery/README.md +++ b/docs/conventions/hook-config-delivery/README.md @@ -137,7 +137,8 @@ authority it points to. ## Recheck triggers -Recheck the facts table (and re-derive the decision rule) when any of these fires: +Stamp-and-trigger discipline: [upstream-drift](../upstream-drift/README.md). Recheck the facts +table (and re-derive the decision rule) when any of these fires: - A Claude Code CHANGELOG entry touches `userConfig` substitution, the `default` field, or `CLAUDE_PLUGIN_OPTION_*` injection — facts 1–4; rows A/B/D. @@ -147,3 +148,5 @@ Recheck the facts table (and re-derive the decision rule) when any of these fire - The managed-settings paths or precedence change — F's exemplar reader. - CC docs begin specifying skill-hook value delivery — fact 6 moves from evidence-strong to doc-stated (or is contradicted). +- The plugins-reference user-configuration section changes what it documents about body + substitution or sensitive-value storage — facts 7–8. diff --git a/docs/conventions/loop-lane/CHANGELOG.md b/docs/conventions/loop-lane/CHANGELOG.md index 5fca41dc2e..0701d55c91 100644 --- a/docs/conventions/loop-lane/CHANGELOG.md +++ b/docs/conventions/loop-lane/CHANGELOG.md @@ -3,7 +3,16 @@ Notable changes to the loop-lane contract. The contract is versioned by SemVer; a change to the topology, the escalation contract, the capability-tier vocabulary, or any loop-layer invariant is a major bump, and additive guidance is a minor bump. A new model release re-audits the capability-tier -table (§3) and is recorded here. +table (§3); drift found by that audit is recorded here. + +## 3.1.1 — 2026-07-29 + +Docs-only, no topology, escalation, tier, or invariant change: §Versioning's "Re-derivation +triggers" label becomes "Recheck triggers" and cites the +[upstream-drift convention](../upstream-drift/README.md) (#1638), the new owner of the +stamp-and-trigger discipline; the generic date-is-never-authority rationale moves there. Both +triggers stay unchanged; the recording policy aligns with the owner doc — a firing that finds +drift lands here, a no-drift firing refreshes the claim's verification date only. ## 3.1.0 — 2026-07-27 diff --git a/docs/conventions/loop-lane/README.md b/docs/conventions/loop-lane/README.md index 9bd79edf7f..8d1d8d17d8 100644 --- a/docs/conventions/loop-lane/README.md +++ b/docs/conventions/loop-lane/README.md @@ -383,16 +383,16 @@ This contract is versioned in [`CHANGELOG.md`](CHANGELOG.md). A change to the to escalation contract, the tier vocabulary, or any loop-layer invariant is a major bump; additive guidance is a minor bump. -**Re-derivation triggers.** Two, and every one of them is recorded as a changelog entry: +**Recheck triggers** ([upstream-drift](../upstream-drift/README.md) owns the stamp-and-trigger +discipline). Two. A firing that finds drift lands its outcome as a changelog entry; a no-drift +firing refreshes the claim's verification date in place — no entry, no bump: - Any new model release re-audits the capability-tier table (§3). - Any change to this convention, or to a consuming lane, that RELIES on an upstream-sourced claim re-verifies that claim against its cited page first and refreshes the claim's verification date with the outcome. -A dated verification stamp in this document is an as-of record, never standing authority. The -upstream surfaces these claims rest on — the `/loop` seven-day expiry, the `ScheduleWakeup` bounds, -model-alias semantics, the rate-limit windows — move on a research-preview cadence, and a stamp -carrying no re-derivation trigger reads as a settled fact the longer it sits. Where re-verification -finds drift, the changed value lands here as a recorded entry rather than silently inside a lane -body. +The upstream surfaces these claims rest on — the `/loop` seven-day expiry, the `ScheduleWakeup` +bounds, model-alias semantics, the rate-limit windows — move on a research-preview cadence. Where +re-verification finds drift, the changed value lands here as a recorded entry rather than silently +inside a lane body. diff --git a/docs/conventions/topic-docs/CHANGELOG.md b/docs/conventions/topic-docs/CHANGELOG.md index 2d1d156feb..e722221d38 100644 --- a/docs/conventions/topic-docs/CHANGELOG.md +++ b/docs/conventions/topic-docs/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog — topic-docs convention +## 2.4.1 — 2026-07-29 + +Docs-only, no tier, key, slug, or visibility change: the no-hoisting decision's "What would +reopen it" label becomes "Recheck trigger" and cites the +[upstream-drift convention](../upstream-drift/README.md) (#1638), the new owner of the concept's +single name and shape. The ephemeral row's "Re-derivation trigger" label, added at 2.4.0 while +that migration was in review, adopts the same name and citation. Both triggers are unchanged. + ## 2.4.0 — 2026-07-27 - **An Ephemeral row joins the tier table** (additive). The table sorts diff --git a/docs/conventions/topic-docs/README.md b/docs/conventions/topic-docs/README.md index 8e55f62d45..50f2d8340c 100644 --- a/docs/conventions/topic-docs/README.md +++ b/docs/conventions/topic-docs/README.md @@ -151,11 +151,11 @@ supported surface are all closed as not-planned upstream has not merely failed to document it, it has declined three times to support it. -**Re-derivation trigger.** An upstream versioned interface for the -scratchpad that guarantees injection, lifecycle, ownership, quota, and -cleanup semantics reopens rule 2, and the change lands here as a -recorded changelog entry. The dated verification above is an as-of -record, never standing authority. +**Recheck trigger** ([upstream-drift](../upstream-drift/README.md)). An +upstream versioned interface for the scratchpad that guarantees +injection, lifecycle, ownership, quota, and cleanup semantics reopens +rule 2, and the change lands here as a recorded changelog entry. The +dated verification above is an as-of record, never standing authority. **Why the other three axes needed no change.** The placement question was re-derived across four axes and only lifetime was uncovered: @@ -526,7 +526,8 @@ one-owner-per-concern rule. Registration would also turn byte-identity into a gate, failing CI on the next legitimate divergence of exactly the kind `planning` already shows. -**What would reopen it:** a canonical source under [`lib/`](../../../lib/) +**Recheck trigger** ([upstream-drift](../upstream-drift/README.md)): +a canonical source under [`lib/`](../../../lib/) with a dedicated `scripts/sync-*.sh` — the mechanism `lib/hook-utils.sh` established and the [shell test-helpers doc](../shell-test-helpers/README.md) names as this marketplace's sanctioned way to share source across diff --git a/docs/conventions/upstream-drift/CHANGELOG.md b/docs/conventions/upstream-drift/CHANGELOG.md new file mode 100644 index 0000000000..4b40b8fc78 --- /dev/null +++ b/docs/conventions/upstream-drift/CHANGELOG.md @@ -0,0 +1,33 @@ +# Changelog — upstream-drift convention + +Notable changes to the upstream-drift contract (SemVer). Changing a required part, the canonical +name, or an enforceability verdict is a major bump; additive guidance is a minor bump; docs-only +clarification is a patch. + +## 1.0.0 — 2026-07-26 + +Initial published contract +([#1638](https://github.com/melodic-software/claude-code-plugins/issues/1638)): one name (recheck +trigger) and one shape (dated verification stamp + observable recheck trigger) for records derived +from upstream-owned sources. + +- Canonical name adopted from `melodic-software/standards` + `conventions/engineering/documentation-and-citations.md`; "revisit trigger", "re-trigger", + "re-derivation trigger", and "what would reopen it" become superseded synonyms that migrate on + touch. +- Required parts fixed: claim/decision, basis, as-of date, recheck trigger; observability bar + stated; date-is-never-authority rule stated. +- Firing procedure stated per record kind: four-part records re-fetch their cited basis and refresh + their date; named triggers on in-repo decisions re-derive from the state the trigger names. + Read-time validation is distinguished from a firing — a lookup that finds no drift obliges no + edit; divergence at fetch is what fires. +- Drift-signal finding recorded: no `ETag` and no per-page `Last-Modified` on the official docs' + raw-markdown endpoints (verified 2026-07-26 by header inspection), so content hashing is the only + viable mechanical drift signal; the fleet defers building a hash store, with its own recheck + trigger. +- Enforceability classified per `enforceability-tiers.md`; the stamp-carries-trigger presence check + named as the one deterministic candidate, deferred per the routing rule. +- Migrated citing surfaces: hook-config-delivery, ecosystem-commands, loop-lane, topic-docs, + PLUGIN-PHILOSOPHY (component stances + registry row), OFFICIAL-DOCS, MIGRATION-PLAYBOOK. The + adopter table states per row what the surface carries: conforming four-part records, named + triggers on an in-repo decision, or deliberately trigger-less terminal exclusions. diff --git a/docs/conventions/upstream-drift/README.md b/docs/conventions/upstream-drift/README.md new file mode 100644 index 0000000000..bcac23a274 --- /dev/null +++ b/docs/conventions/upstream-drift/README.md @@ -0,0 +1,189 @@ +# Upstream drift — verification stamps and recheck triggers + +Owner doc for **how this repository records a fact or decision derived from a source it does not +own** — an official doc page, an upstream issue thread, a probed platform behavior — so the record +stays honest as the upstream moves. One name and one shape: a dated **verification stamp** paired +with a **recheck trigger**, the stated observable event that obliges re-deriving the record. + +The fleet previously practiced this in five-plus places under four names — "recheck triggers" +([hook-config-delivery](../hook-config-delivery/README.md)), "revisit triggers" +([ecosystem-commands](../ecosystem-commands/README.md), the +[migration playbook](../../MIGRATION-PLAYBOOK.md)), "re-trigger" (the migration playbook again, on a +plugin-acceptance review record), "re-derivation triggers" +([loop-lane](../loop-lane/README.md)) — plus the unlabeled "What would reopen it" +([topic-docs](../topic-docs/README.md)) — with no shared definition of what a trigger must contain +and no statement of what makes one checkable. Under the +[convention registry](../../PLUGIN-PHILOSOPHY.md#convention-registry)'s one-owner-per-concern rule +that is the fragmentation this doc closes +([melodic-software/claude-code-plugins#1638](https://github.com/melodic-software/claude-code-plugins/issues/1638)). + +## Boundary + +`melodic-software/standards` `conventions/engineering/documentation-and-citations.md` owns the +general org-wide rule — upstream bodies are read-on-demand; prefer citing and fetching at read time +over storing a snapshot; a time-bound external claim in durable content needs a recheck trigger — +and this doc takes the concept's name from it. This doc owns the repo-level specialization: the +required parts of a conforming record, the observability bar a trigger must clear, the drift signal +for the doc pages this fleet depends on most, and the enforceability classification. It does not +own: + +- **In-repo duplication.** Facts this repo owns are governed by pointer-not-copy + (`melodic-software/standards` `conventions/engineering/reference-dont-duplicate.md`) and, for + byte-identical cross-plugin files, `scripts/cross-plugin-source-registry.txt`. +- **Synced materializations.** A `managed` component from the standards distribution drifts and + reconciles through its reviewed sync-PR pipeline, not through stamps in prose. +- **Where a refreshed outcome lands.** Each versioned convention's own `CHANGELOG.md` records its + rechecks' drift outcomes; this doc only requires that the outcome be recorded somewhere durable. + +One deliberate tightening, made explicit so it never reads as drift: the org standard accepts "a +date, an automation, or a tracked task" as recheck-trigger forms. The upstream surfaces this fleet +restates move without notice on research-preview cadences, where a bare date decays silently — so +here a date alone does not qualify; a trigger names an observable event (see +[the observability bar](#the-observability-bar)). This narrows only what this repository accepts; +the upstream form list is the org standard's to change. + +## A date is never authority + +A dated verification stamp is an **as-of record**: it tells the reader when the claim last matched +its source, and nothing more. It never confers standing authority — a stale stamp reads identically +to a fresh one, and upstream surfaces move without notice: Claude Code changes its own conventions +between releases, sometimes with no version signal on the surface in question, and experimental +surfaces churn outright. The load-bearing part of the record is therefore the **trigger**, not the +date: anything restating a volatile upstream specific carries a stated re-derivation event, or it +is drift waiting to happen. Before acting on any stamped claim, re-fetch the cited basis — the +stamp is the ceiling on how current the claim can be, never a guarantee. + +The discipline covers two record kinds, one shape: + +- a **verified-fact stamp** — a restated upstream specific ("verified 2026-07-17 against \"); +- a **recorded decision** — a deferral or rejection derived from upstream facts as they stood on a + date, whose premises can rot the same way the facts can. + +## Required parts + +A conforming record carries four parts: + +1. **The claim or decision** — what exactly was verified, or what was decided and on what premise. +2. **The basis** — the specific source it was derived against: the official page URL (with anchor + where one exists), the upstream issue, or the probe/method for an empirical finding. "Verified" + with no stated basis is not re-checkable. +3. **The as-of date** — when the derivation happened. +4. **The recheck trigger** — the observable event that obliges re-derivation. + +Prefer the pointer: where a surface can defer to the live source at read time, cite it and restate +nothing — then no stamp is needed at all. The four-part record is the fallback for surfaces that +must restate a volatile specific to function. + +## The observability bar + +A trigger names an event whose firing a reader — human or agent — can decide from evidence: a +release or changelog entry touching a named surface, an upstream issue changing state, a capability +shipping or leaving an experimental key, a second consumer appearing, a recurring occasion such as +each fleet audit. "Periodically", "when things change", or an unstated intention to revisit do not +qualify: a trigger whose firing cannot be checked is a date with extra words. + +## When a trigger fires + +A firing is a record-maintenance event, and the procedure follows what the trigger guards: + +- **A four-part record.** Re-fetch the cited basis and re-derive the claim or decision from what is + actually there — never patch the record from memory. Refresh the as-of date **with the outcome**, + drift or no drift. On a versioned surface a drift outcome lands as a changelog entry; refreshing + a date with no verdict change is no entry and no version bump. +- **A named trigger guarding an in-repo decision** ([Adopters](#adopters) says which rows these + are). There is no cited basis to re-fetch and no as-of date to refresh: re-derive the decision + from the state the trigger names — the decision guarded is in-repo; the firing event can live + anywhere, upstream included — and record the outcome durably where the decision lives: the record + itself or the owning surface's changelog. A re-derivation that ends up restating an upstream + specific adopts the four required parts in the refreshed record. The durable outcome is the part + this kind shares with the stamped kind. + +Whichever the kind, where re-derivation finds drift the changed value lands in the owning record, +never silently in a consuming surface. + +### Read-time validation is not a firing + +The standing rule to re-fetch a cited basis before acting on a stamped claim +([a date is never authority](#a-date-is-never-authority)) is per-use validation: it protects the +act, not the record, and a lookup that finds no drift obliges no edit anywhere. A record kept +current this way states divergence as its trigger — "a read-time re-fetch finds the source no +longer matching the record" is an event decidable from evidence — so the divergence, never the +lookup, is what fires, and only a firing invokes the maintenance procedure above. + +## Drift signal — content hashing, deferred + +There is no mechanical per-page change signal on the official Claude Code docs: the raw-markdown +endpoints serve no `ETag`, and `Last-Modified` is a deploy/serving stamp rather than a per-page +content date (verified 2026-07-26 by header inspection of three `code.claude.com/docs/en/*.md` +endpoints fetched seconds apart — each returned a `Last-Modified` matching its own fetch time; +recheck trigger: those endpoints start serving an `ETag` or a stable per-page `Last-Modified`). +**Content hashing of a fetched page body is therefore the only viable mechanical drift signal** for +these pages. + +The fleet **defers** storing hashes: no upstream-page hash store exists today, and every recheck is +a manual re-fetch at trigger time. Recheck trigger for the deferral itself: a stale stamp causes a +real defect a stored hash would have flagged, or a fleet audit completes without re-fetching every +stamped claim in its scope — at which point a hash store becomes its own designed issue, not an +inline addition here. + +## Enforceability + +Classified per `melodic-software/standards` `conventions/engineering/enforceability-tiers.md`: + +| Judgment | Tier | +|---|---| +| Every verification stamp carries a recheck trigger | **Deterministic** by nature (a presence check) once stamps and triggers use greppable forms. The candidate check — flag any `Verified ` line or row whose surface states no trigger — is named but **not built**: per the tiers doc's routing rule, worth-mechanizing defaults to "not yet". Build trigger: a trigger-less stamp lands on `main` again after this doc. | +| 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. | + +## Adopters + +Migrated at this contract's 1.0.0 to the single name, each citing this doc with content intact. +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 +[its own firing procedure](#when-a-trigger-fires), but guards an in-repo decision: in scope for the +name, outside the four-part requirement, which binds only records that restate something +upstream-owned. This narrows what a row advertises; it does not widen the +contract to fit its exceptions. + +| Surface | Was | What a reader can rely on | +|---|---|---| +| [hook-config-delivery](../hook-config-delivery/README.md) §Recheck triggers | already the canonical name | Conforming records — version-pinned facts table with per-fact basis, table-wide as-of dates, and fact-scoped event triggers. | +| [loop-lane](../loop-lane/README.md) §Versioning | "Re-derivation triggers" | Conforming records — dated upstream-claim stamps; drift outcomes recorded in its changelog. | +| [PLUGIN-PHILOSOPHY](../../PLUGIN-PHILOSOPHY.md) component-stances staleness disclaimer | unlabeled discipline | Conforming records — per-row claim, linked page, and verified date; the re-fetch-before-acting rule is [read-time validation](#read-time-validation-is-not-a-firing), and every row's stated trigger is a fetch diverging from the row. | +| [OFFICIAL-DOCS](../../OFFICIAL-DOCS.md) staleness warning and per-row verified dates | unlabeled discipline | Conforming records — same shape as the component-stances table: link + date, divergence-at-fetch as the stated trigger. | +| [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. | + +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 +canonical `## Recheck triggers` heading) adopt the canonical name, the observability bar, and their +kind's firing procedure the next time they change; a surface restating an upstream-owned specific +additionally adopts the required parts. **History is never rewritten**: `CHANGELOG.md` entries, +dated audit records, and ADR sections keep the wording they shipped with; a new ADR uses the +canonical name going forward. + +## Why this name + +"Recheck trigger" is what the org standard (`documentation-and-citations.md` §"Time-bound external +claims need a recheck trigger") already calls the concept — a repo-level owner doc renaming the +rule it specializes would fork the vocabulary one level up. It is also the majority name in this +fleet, and the `## Recheck triggers` heading is the one the docs-hygiene plugin's audit-noise +section-exemption list already recognizes. + +## Versioning + +This contract is versioned in [`CHANGELOG.md`](CHANGELOG.md). Changing a required part, the +canonical name, or an enforceability verdict is a major bump; additive guidance is a minor bump; +docs-only clarification is a patch. + +## External authority + +- `melodic-software/standards` `conventions/engineering/documentation-and-citations.md` — the + org-wide read-on-demand rule and the concept's name. +- `melodic-software/standards` `conventions/engineering/enforceability-tiers.md` — the tier + vocabulary and the routing rule. +- `melodic-software/standards` `conventions/engineering/reference-dont-duplicate.md` — the in-repo + counterpart this doc's boundary defers to.