diff --git a/docs/specs/docs-hygiene-sweep-unapplied-remediations.md b/docs/specs/docs-hygiene-sweep-unapplied-remediations.md index 9f50a61e5..c7849fe71 100644 --- a/docs/specs/docs-hygiene-sweep-unapplied-remediations.md +++ b/docs/specs/docs-hygiene-sweep-unapplied-remediations.md @@ -344,13 +344,30 @@ citing text the audit quoted. > **Closure stamp, 2026-08-28. All 34 rows below are closed. The tables are left verbatim as the > inventory this record exists to preserve; only this note is added.** The sentence directly above -> is the one thing in this section that was never true: #3380 wrote it and fixed 32 of the 34 in the -> same commit, so it asserts a re-verification of citing text it had already deleted. Three separate -> later passes each re-derived this roster from scratch because of it. Rows closed by -> [#3380](https://github.com/melodic-software/claude-code-plugins/pull/3380) (`6c7a1032`): 22 of -> Group 1, **all 8 of Group 2**, and both of Group 3. `V-review-13` and `V-review-14` closed later, -> in [#3475](https://github.com/melodic-software/claude-code-plugins/pull/3475). Group 2's eight -> were rewritten from the bare `skills//` form to the anchored +> went stale rather than starting false. It was written on 2026-08-26 by +> [#3362](https://github.com/melodic-software/claude-code-plugins/pull/3362) (`3fbe9789`), the +> commit that created this file and this whole section, while all 34 rows were open; it was true +> then. Rows closed by [#3380](https://github.com/melodic-software/claude-code-plugins/pull/3380) +> (`6c7a1032`): 22 of Group 1, **all 8 of Group 2**, and both of Group 3. #3380 fixed those 32 in +> the citing files and never touched this section — `git show 6c7a1032 -- ` has hunks +> only in "Status at the stamp", L2 structure, L6 and L7 — so the summary above kept asserting a +> re-verification of citing text that no longer stood. Three separate later passes each re-derived +> this roster from scratch because of it. +> +> **Correction, 2026-08-28 (seventh review round).** An earlier version of this stamp said the +> sentence "was never true" and that "#3380 wrote it … in the same commit". Both are false, and the +> generalizable rule the sweep spec drew from them was drawn from something that did not happen. +> `git log --diff-filter=A -- docs/specs/docs-hygiene-sweep-unapplied-remediations.md` returns +> `3fbe9789` (#3362), and `git blame -L 340,343` puts the sentence on `3fbe97898`. The corrected +> rule is in the sweep spec's "The L4 roster is closed" section. +> +> `V-review-13` and `V-review-14` closed later, in +> [#3468](https://github.com/melodic-software/claude-code-plugins/pull/3468) (`c66f26ce`), which +> rewrote all three `docs/conventions/native-references/README.md` sites to slash invocations. An +> earlier version of this stamp credited #3475; that PR touched only that convention's CHANGELOG. +> The 34-closed total is unaffected either way. +> +> Group 2's eight were rewritten from the bare `skills//` form to the anchored > `${CLAUDE_PLUGIN_ROOT}/skills//` form clause 3 requires, and all seven distinct targets > resolve on disk. Group 3's two anchors were dropped to file-level links. **Do not re-derive this > roster again; verify against the sweep spec's closure section instead.** diff --git a/docs/specs/extract-ssot-sweep-2026-08-28.md b/docs/specs/extract-ssot-sweep-2026-08-28.md index 115037a6c..faf48055e 100644 --- a/docs/specs/extract-ssot-sweep-2026-08-28.md +++ b/docs/specs/extract-ssot-sweep-2026-08-28.md @@ -378,20 +378,43 @@ kept set. Every one of the twelve above was written by the fix commit itself, so individually against the test now written into [ADR 0018](../adr/0018-treat-the-plugin-as-the-encapsulation-boundary-for-skill-citation.md)'s amendment, not accepted as a class. Every one sits inside a dated entry whose claim is what a named -file contained on that date, and each is quoted as the string the entry removed, with the public -invocation that replaced it named in the same sentence. No reader is sent to any of them to get a -rule, so none is an address. Three sub-rulings the class needed: +file contained on that date, and each is quoted as the string the entry removed. No reader is sent +to any of them to get a rule, so none is an address. Three sub-rulings the class needed: - The three `config-cascade` rows quote plugin-relative forms (`skills/audit/scripts/detect.sh`, `skills/setup/SKILL.md`, `run-e2e/context/e2e-config.md`) that resolve against nothing from that - file, and the entry says so in the same sentence. Clause 3 does not fire on them: the entry - asserts their non-resolution rather than offering them as addresses, so requiring them to resolve - would delete the finding. + file, and the entry says so. Clause 3 does not fire on them: the entry asserts their + non-resolution rather than offering them as addresses, so requiring them to resolve would delete + the finding. - The other nine all resolve on disk today from the base their own form implies, checked one at a - time, so clause 3 is satisfied where it does apply. + time, so clause 3 is satisfied where it does apply. They cover **eight** distinct targets, not + eleven: `plugins/review/skills/fanout/SKILL.md` is cited by both `detector-findings` `:44` and + `native-references` `:17`. Eleven is the distinct-target count across all twelve rows, the nine + plus `config-cascade`'s three; #3477's merged message applied it to the nine, where it cannot + hold. - None of the twelve carries a line pin or a step pin, which is the part the amendment says rots first. Nothing to drop. +**Two wording corrections, seventh review round.** This section previously said each of the twelve +names "the public invocation that replaced it **in the same sentence**", and that `config-cascade`'s +entry asserts non-resolution "in the same sentence" as the quoted forms. Neither is accurate as +written, and the rulings do not depend on it. +The `detector-findings` bullet beginning "The `docs-hygiene:audit-noise` adopter row stops +path-citing the producer's shape library" names **no slash invocation as the replacement** — the row +"now says 'its shape library' and 'the scanner'", a rename to the row's own terms rather than a +routing fix — and the other eleven name the invocation in a **later sentence of the same bullet**. +`config-cascade`'s non-resolution assertion ("All three are plugin-relative paths that resolve +against nothing from this file") is likewise the sentence that follows the three quoted forms rather +than the sentence carrying them. The unit that carries the evidence claim is the bullet, not the +sentence, and the substance holds at that unit: every row states what it removed and why. + +A first attempt at this correction said that bullet "names **no** invocation at all", which its own +text refutes: it names `docs-hygiene:audit-noise` and `claude-config:audit-instructions`, just not as +the replacement. That attempt also pinned the `config-cascade` sentences at `:13-14` and `:11-13` +when the quoted forms are on 12, 13 and 14 and the assertion runs 14 to 16 — a line pin written into +the very file whose decay rule says the check is the text. Both are corrected here on text anchors, +and both were caught by the round verifying this one. + The judgment is what was missing, and it is now recorded so a pass that re-derives this shape reads a ruling instead of buying twelve fresh ones. The general lesson is worth more than the twelve rows: **a sweep that documents each fix by quoting the citation it removed manufactures new instances of @@ -452,21 +475,113 @@ because the encapsulation pass kept that record's five file-and-frontmatter cita strength of* its re-trigger clause, which means the clause was read and its own condition was not checked. Whoever re-runs the review owns the record; the citations are fine either way. +### Corrections to the merged messages of #3477 and #3478 + +A merged commit subject and body cannot be edited, so four claims those two messages make are +corrected here, where a reader who follows the refs will meet them. None changes an adjudication; +all four are the record misdescribing itself. + +**The `dometrain` subject over-claims, and the file it added does not.** `dd6c11fe`'s subject is +"…and flag a **fired** security re-trigger". Nothing in the change establishes that the re-trigger +fired. The note it added says the opposite, correctly: whether any of the eleven releases added a +trust surface "cannot be settled either way by reading this page", and the re-review is logged as +owed rather than performed. What is established is a stale review record and an unadjudicated +condition. **Read the subject as "flag a possibly-fired security re-trigger"**; the playbook text is +the accurate statement and needs no edit. Recorded rather than left, because a security claim +reading stronger in the log than in the artifact is the direction that misleads. + +**The `:943` re-anchoring was good practice for a reason that was not true.** `dd6c11fe`'s message +says the spec's `dometrain` entry pinned `MIGRATION-PLAYBOOK.md:943`, "a line this change's own edit +would have invalidated", and claims the decay rule was for the first time "caught before landing". +The insertion lands below that line: + +```console +$ git show dd6c11fe --unified=0 --format='' -- docs/MIGRATION-PLAYBOOK.md | grep '^@@' +@@ -944,0 +945,7 @@ ### Review record — `dometrain` (ACCEPT, 2026-07-22) +``` + +A pure insertion after 944 does not move 943. Re-anchoring a pin onto heading text instead of a line +number is still the right call and the entry keeps it, but the justification and the credit both go. +No violation was caught; a hazard was avoided that was not present on this diff. + +**"Two checks were run … which the note says" is false about the note.** `dd6c11fe`'s message says +two checks were run to avoid claiming a trust surface was added, "which the note says". The note +says nothing about any checks — it states the reviewed version, the shipping version, that the +question is unadjudicated, and that the re-review is owed. Whether the two checks ran is not +recoverable from the diff either. Treat the note's own text as the whole of what this pass +established. + +**"Every one of #3468's ADR-0018 citation fixes wrote a CHANGELOG entry" is false, in the +harmless direction.** `c66f26ce` also fixed two sites that produced no changelog entry: the +Convention registry row in `docs/PLUGIN-PHILOSOPHY.md`, and a `skills/confirm/SKILL.md` parenthetical +in `docs/conventions/pre-pr-ordering/README.md` — a convention that ships no `CHANGELOG.md` at all +(`ls docs/conventions/pre-pr-ordering/` returns `README.md` alone). Both were resolved by deleting +the path rather than by quoting it, so neither manufactured a new citation. The twelve-row count and +the "16 fixed and 35 kept" arithmetic are unaffected; only the universal is wrong. It matters +because the sweep's own lesson — that documenting a fix by quoting the citation it removed +manufactures the shape being swept — is a tendency of the changelog form, not a law of the pass, and +these two are the counter-examples that show the tendency is escapable. + ## The L4 roster is closed, all 34 rows, and Group 2 was never open A pass dispatched to fix the predecessor roster's eight Group 2 rows found **nothing to fix**. All eight were closed on 2026-08-26 by -[#3380](https://github.com/melodic-software/claude-code-plugins/pull/3380) (`6c7a1032`) — the same -commit that wrote the roster. Its own message says so in a clause nobody carried forward: "eight -citations written with an implied base of the plugin root while the real base was `reference/` — -none of them resolved for any reader". It fixed them and left the roster's summary line asserting -that all 34 still resolved to the citing text the audit quoted. +[#3380](https://github.com/melodic-software/claude-code-plugins/pull/3380) (`6c7a1032`). Its own +message says so in a clause nobody carried forward: "eight citations written with an implied base of +the plugin root while the real base was `reference/` — none of them resolved for any reader". It +fixed them in the citing files and left the roster's summary line asserting that all 34 still +resolved to the citing text the audit quoted. + +**#3380 did not write the roster, and that is the whole point.** An earlier version of this section, +and the merged message of +[#3478](https://github.com/melodic-software/claude-code-plugins/pull/3478) (`e7e3a368`), both called +`6c7a1032` "the same commit that wrote the roster". Both are false. The roster was created two +hours earlier the same night, by +[#3362](https://github.com/melodic-software/claude-code-plugins/pull/3362) (`3fbe9789`, 01:28), the +commit that also wrote the summary sentence, at a time when all 34 rows were open and the sentence +was true. #3380 (03:36) never touched the roster's L4 section at all: + +```console +$ git log --diff-filter=A --format='%h %s' -- docs/specs/docs-hygiene-sweep-unapplied-remediations.md +3fbe9789 docs: run all eight docs-hygiene audits repo-wide, ... (#3362) +$ git blame -L 340,343 -- docs/specs/docs-hygiene-sweep-unapplied-remediations.md # all four lines: 3fbe97898 +$ git show 6c7a1032 --unified=0 -- docs/specs/docs-hygiene-sweep-unapplied-remediations.md | grep '^@@' +@@ -75 +75 @@ ## Status at the stamp +@@ -223 +223 @@ ### `blind-pointer`, 22 +@@ -229,0 +230,31 @@ ### `blind-pointer`, 22 +@@ -577,0 +609,18 @@ ## L6 compression: 1 finding +@@ -603 +652 @@ ### P3, a pointer opens on the routing verb ... +@@ -635,0 +685,118 @@ ### P3, a pointer opens on the routing verb ... +``` + +L4 sat at 307–403 in that revision. Every hunk is outside it. **That one stale sentence has now caused four passes to re-derive the same roster**, this one included. It is the most expensive line in the sweep record, and it is expensive precisely because -it sits above an inventory whose own decay rule says the status column is its weakest part. The -lesson is not about these eight rows: **a record that fixes findings and updates its own summary in -the same commit must update the summary, or the summary outranks the fix for every later reader.** +it sits above an inventory whose own decay rule says the status column is its weakest part. + +**Corrected lesson (seventh review round).** This section previously drew the rule *"a record that +fixes findings and updates its own summary in the same commit must update the summary, or the +summary outranks the fix for every later reader."* That rule describes an event that did not happen: +no commit here both fixed the findings and touched the summary. It is also close to backwards, since +it lets a commit off the hook whenever it happens not to author the record. The rule the evidence +actually supports is the near-inverse: + +> **A commit that closes findings inventoried in a record it did not author still owes that record's +> summary an update.** Cross-file staleness is the default outcome, not the exception: the fix and +> the record live in different files, nothing in the toolchain links them, and the commit has no +> reason of its own to open the record. #3380 closed 32 of 34 rows spread across a `.claude/rules/` +> file, `docs/PLUGIN-PHILOSOPHY.md`, four convention READMEs and several plugins' trees, and left a +> two-hour-old roster in `docs/specs/` asserting the opposite, and four later passes paid for it. +> +> An earlier version of this paragraph said "three plugins' files", which `git show --stat 6c7a1032` +> refutes: the majority of the 32 are not plugin files at all. Corrected by the round that verified +> this one, and left visible because a rule stated over a miscounted example invites the next reader +> to re-derive it. + +The operational form is: when a change closes something a spec has rostered, edit the spec's status +line in the same PR, even when the spec is somebody else's and the diff would otherwise touch no +`docs/specs/` file at all. ### The eight, verified against the live tree @@ -488,7 +603,13 @@ rewritten from the bare `skills//` form to the anchored All seven distinct targets exist on disk. Group 3's two heading anchors are closed by the same commit, dropped to file-level links, so **the 34-row roster stands at 34 closed, 0 open**: 22 of Group 1 plus all of Groups 2 and 3 by #3380, and `V-review-13` and `V-review-14` by -[#3475](https://github.com/melodic-software/claude-code-plugins/pull/3475). +[#3468](https://github.com/melodic-software/claude-code-plugins/pull/3468) (`c66f26ce`), which +rewrote all three `docs/conventions/native-references/README.md` sites — the Boundary section's +worked model and both Adopters rows — to `/review:quality-gate`, `/review:fanout` and +`/claude-ops:audit-install-state`. An earlier version of this line, and the merged messages of +both #3477 and #3478, credited #3475; `git show --stat 02e1d8b0` shows that PR touched +only `docs/conventions/native-references/CHANGELOG.md`, never the README the two rows cite. +The 34-closed total is unaffected. Derived twice with unrelated expressions, per this file's own discipline. First by matching the roster's quoted bare-form text at each citing path: zero matches remain, and a regex for any @@ -496,8 +617,72 @@ roster's quoted bare-form text at each citing path: zero matches remain, and a r `${CLAUDE_PLUGIN_ROOT}` returns zero across both plugins' `reference/` trees. Second, without reference to the roster at all, by resolving **every** citation token in every plugin-level `reference/`, `context/` and `agents/` tree and every plugin README against the base its own form -implies: **52 tokens, 0 clause 3 failures.** That population strictly contains the eight, so the -second derivation confirms the first without sharing its search expression. +implies. + +**The second derivation's result was reported as "52 tokens, 0 clause 3 failures". That is false: +the population held three failures, and the first derivation was structurally unable to see them.** +Its regex requires a `(reference|context|actions|evals|templates)/` tail, and all three of these end +in `SKILL.md`. A third derivation, run on 2026-08-28 with a wider expression — every +`skills/…` path token ending in a real file extension, resolved against the base its own form +implies, over the same population — returned **119 tokens and 3 clause-3 failures**, each one the +exact defect class ADR 0018's correction 1 names, an implied base of the plugin root against a real +base of the citing file's directory: + +| Citing `path:line` | Token as written | Resolved against | Fixed to | +|---|---|---|---| +| `plugins/source-control/reference/config-resolution.md:124` | `skills/babysit-prs/SKILL.md` | `plugins/source-control/reference/`, absent | `/source-control:babysit-prs`, the public invocation | +| `plugins/work-items/reference/permission-preflight.md:45` | `skills/work/SKILL.md` | `plugins/work-items/reference/`, absent | `${CLAUDE_PLUGIN_ROOT}/skills/work/SKILL.md` | +| `plugins/songwriting/context/pat-pattison/research/lyric-melodic-roadmaps.md:203` | `skills/meter-prosody/SKILL.md` | `…/research/`, absent | `${CLAUDE_PLUGIN_ROOT}/skills/meter-prosody/SKILL.md` | + +**Two** are fixed to the form their own file already uses elsewhere: `permission-preflight.md` +already anchors its `preflight.sh` invocation line that way, and `songwriting`'s `research/` tree +anchors its script paths the same way. +Neither file is fetched from outside its plugin, so `${CLAUDE_PLUGIN_ROOT}` denotes the right +installation for every reader either has. + +**The third is fixed to the public invocation instead**, and the reason is the subsection below. +`config-resolution.md` is fetched across the plugin boundary, so the anchored form would have named +a `babysit-prs` skill that does not exist in the fetching plugin. The anchored form was what this +change first shipped; a review pass caught it before merge. Recorded rather than quietly amended, +because the wrong remedy was chosen by reasoning this same document had already written down and +then failed to apply to its own fix. + +Re-running the third expression after the fixes leaves no clause-3 failure in the three files. The +`config-resolution.md` row leaves the path population altogether, since an invocation is not a path. + +The token counts differ between derivations because the expressions do — 52 against 119 — and per +this file's own recall-limits discipline neither is a total. The **failure** count is the claim that +matters, and 0 was wrong. The lesson generalises past these three rows: **a second derivation +confirms a first only if it can fail differently.** The first two here missed the same three rows, +each of which cites a `SKILL.md` directly rather than a file beneath a `reference/`-shaped +subdirectory, so reporting them as independent overstated the evidence. + +**What is established and what is inferred.** Derivation 1's expression is recorded verbatim in this +file and does require that subdirectory shape, so its blindness is a fact. Derivation 2's expression +was never written down anywhere; the record describes it as resolving "every citation token", which +would not have that blind spot. All that the evidence settles is that derivation 2 was narrower than +its own description, since it returned 52 tokens and 0 failures where a third expression returns 119 +and 3. The shared *mechanism* is a plausible reconstruction, not a verified one, and an unrecorded +expression is itself the defect worth carrying forward: a derivation nobody can re-run cannot be +audited, only believed. + +**A fourth derivation is owed and not performed here.** The third is `skills/`-scoped, so it is +blind by construction to the same defect class in tokens that name no skill. The verifying round +found three such tokens in `plugins/discovery/reference/topic-docs.md`, whose `agents/explorer.md`, +`agents/researcher.md` and `agents/intent-tracer.md` imply a base of the plugin root against a real +base of `reference/`. Verified against the tree, fixed in this change to the anchored form, and +called out here because of where they sat: **three lines above `V-disc-04` through `V-disc-06`, +which this sweep did close.** A pass looked at that paragraph, corrected the citations below these +three, and left these three standing, because its expression could not see them. + +That is the strongest available argument that the `skills/`-scoped population was never the right +population. The class is "a path whose implied base is the plugin root while its real base is the +citing file's directory", and nothing in that definition mentions skills. Whoever runs the fourth +derivation should build it from the class, not from the token shape the last three happened to +share. + +The corrected population still strictly contains the eight Group 2 rows, so the roster's closure +stands unchanged; what does not stand is the claim that the tree around it was clean. ### Judgment: ADR 0018 barely reaches this class, and its encapsulation half does not @@ -507,16 +692,44 @@ clause would have been easy. **Group 2 was never an encapsulation defect.** The roster says so itself: "Legal as citations under ADR 0018, defective as paths." Clause 1 names this exact citing surface — it covers "plugin-level `context/`, `reference/` and `agents/` docs" reaching a sibling skill's private files — and -legalises it. Clause 2 cannot reach them: both files ship inside one plugin, so the runtime absence -that motivates clause 2, and the fetched-contract problem the amendment builds on it, cannot occur. -A consumer enabling `source-control` gets `reference/review-discipline.md` and -`skills/babysit-prs/reference/safety.md` or gets neither. +legalises it. Clause 2 does not reach them: both files ship inside one plugin, so for a reader +inside that plugin the runtime absence motivating clause 2 does not arise. A consumer enabling +`source-control` gets `reference/review-discipline.md` and `skills/babysit-prs/reference/safety.md` +or gets neither. + +**Softened, seventh review round.** An earlier version said the fetched-contract problem the +amendment builds on clause 2 "cannot occur" for intra-plugin citations. It can, by one indirect +route, and the counter-instance is in this repo: +`plugins/work-items/skills/work/SKILL.md:208` sends its reader to +`plugins/source-control/reference/config-resolution.md` over `raw.githubusercontent.com`. That +reader is running `work-items`, so `${CLAUDE_PLUGIN_ROOT}` resolves to `work-items` and the +intra-plugin citations inside the fetched file address paths that are absent for them. The +mechanism is that a *cross*-plugin fetch drags an intra-plugin citation across the boundary its form +assumed. + +**And that does change the remedy, which the first version of this paragraph denied.** It claimed +"the remedy is still form rather than routing", on the ground that a fetched reader cannot follow +`skills/babysit-prs/SKILL.md` either way. True of the bare form, false of the choice it was used to +justify: the anchored `${CLAUDE_PLUGIN_ROOT}/skills/babysit-prs/SKILL.md` is *also* unfollowable for +that reader, because the variable denotes their plugin and not this one, while +`/source-control:babysit-prs` is followable by every reader regardless of which plugin fetched the +document. So this row went to the invocation. The paragraph reasoned its way to the exposure and +then declined to draw the consequence for the fix sitting in the same commit; a review pass drew it. + +Clause 1 still legalises the citation and only clause 3 has teeth on it — that much stands. What +does not is the inference from "clause 3 only" to "path form only". Where a file is fetched across +the boundary, clause 3 alone can force the invocation, because for the fetched reader no path form +resolves. A pass auditing intra-plugin citation forms must treat "who fetches this file" as a live +question, and must treat it as bearing on the remedy, not only on the diagnosis. So **only clause 3 reaches Group 2**, and clause 3 is a resolvability rule, not an encapsulation rule. The amendment's fix-an-address / keep-evidence test does not apply either: that test divides clause 2 applications, and these are not clause 2 matters. Had the eight still been open, the remedy -would have been the path form and nothing else — no routing to a slash invocation, no promotion of -content to a shared location. **Intra-plugin genuinely is a different case, and the file that says +would have been the path form for any of them whose file is read only from inside its own plugin, +and the invocation for any that is fetched across the boundary — never a promotion of content to a +shared location. **Which of the eight are fetched was not checked**, because all eight were already +closed; a pass that reopens one owes that check first, on the evidence of the row above, where +exactly that question decided the remedy. **Intra-plugin genuinely is a different case, and the file that says so is the ADR's own correction 1**, which withdrew the bare-relative breakage claim as a category error and named this narrower shape as the real defect: an implied base of the plugin root against a real base of the citing file's directory. diff --git a/plugins/discovery/.claude-plugin/plugin.json b/plugins/discovery/.claude-plugin/plugin.json index 0006f1cb2..11e9194b5 100644 --- a/plugins/discovery/.claude-plugin/plugin.json +++ b/plugins/discovery/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "discovery", - "version": "0.16.16", + "version": "0.16.17", "description": "Structured discovery before changes: explore the local codebase, run disciplined multi-source external research, and reconstruct why a past decision was made from evidence outside the code — each dispatching a purpose-built subagent by default so the reading stays out of the main conversation, with source tiers, falsification, recency gates, an intent-evidence tier, and a corpus-coverage ledger — persisting EXPLORE.md / RESEARCH.md / INTENT.md index-plus-sidecar handoff artifacts.", "author": { "name": "Melodic Software", diff --git a/plugins/discovery/CHANGELOG.md b/plugins/discovery/CHANGELOG.md index 636db0865..a442890fd 100644 --- a/plugins/discovery/CHANGELOG.md +++ b/plugins/discovery/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog — discovery plugin +## [0.16.17] + +### Fixed + +- **`reference/topic-docs.md` cited its three agent definitions by a path that + resolved against nothing.** The return-payload sentence named `agents/explorer.md`, + `agents/researcher.md` and `agents/intent-tracer.md`, whose implied base is the + plugin root while their real base is `reference/`, the defect class + [ADR 0018](../../docs/adr/0018-treat-the-plugin-as-the-encapsulation-boundary-for-skill-citation.md)'s + correction 1 names. All three now carry `${CLAUDE_PLUGIN_ROOT}/`, the form the + next sentence of the same paragraph already uses for the three dispatch docs. + This file is not fetched from outside the plugin, so the anchored form resolves + for every reader it has and the invocation is not needed. + + Found by the round verifying the sweep's own third derivation. That derivation + was `skills/`-scoped and therefore blind by construction to citations naming no + skill, which is why three defects of the same class survived it three lines + above rows the sweep had already closed. + ## [0.16.16] ### Changed diff --git a/plugins/discovery/reference/topic-docs.md b/plugins/discovery/reference/topic-docs.md index 588e6e443..7bdb7d111 100644 --- a/plugins/discovery/reference/topic-docs.md +++ b/plugins/discovery/reference/topic-docs.md @@ -82,8 +82,9 @@ checkout (worktree or background session) returns findings by value instead, and the memory slice. **Where that rule is reachable from.** A worker does not choose the by-value mode by reading this -file; it is `persistence: by-value` in the return payload (`agents/explorer.md`, -`agents/researcher.md`, `agents/intent-tracer.md`), and the parent acts on it at the +file; it is `persistence: by-value` in the return payload +(`${CLAUDE_PLUGIN_ROOT}/agents/explorer.md`, `${CLAUDE_PLUGIN_ROOT}/agents/researcher.md`, +`${CLAUDE_PLUGIN_ROOT}/agents/intent-tracer.md`), and the parent acts on it at the `persistence: by-value` rung of each family's recovery ladder — `${CLAUDE_PLUGIN_ROOT}/skills/explore/reference/dispatch.md`, `${CLAUDE_PLUGIN_ROOT}/skills/research/context/dispatch.md` and diff --git a/plugins/songwriting/.claude-plugin/plugin.json b/plugins/songwriting/.claude-plugin/plugin.json index 242197f98..d32ae0cf5 100644 --- a/plugins/songwriting/.claude-plugin/plugin.json +++ b/plugins/songwriting/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "songwriting", - "version": "1.4.17", + "version": "1.4.18", "description": "Songwriting craft companion — nine concern-scoped lyric-craft skills (workflow router, rhyme, object-writing, metaphor, meter-prosody, song-form, co-write, diagnose, practice) applying Pat Pattison's methods, with an object-writing agent that performs the sensory exercise itself and per-skill emission boundaries that route generation to the skill that owns it, plus Suno v5.5 prompt engineering (style prompts, tagged lyrics, genre templates, troubleshooting).", "author": { "name": "Melodic Software", diff --git a/plugins/songwriting/CHANGELOG.md b/plugins/songwriting/CHANGELOG.md index d08ca3b07..20077d1ce 100644 --- a/plugins/songwriting/CHANGELOG.md +++ b/plugins/songwriting/CHANGELOG.md @@ -3,6 +3,20 @@ All notable changes to the `songwriting` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [1.4.18] + +### Fixed + +- **`lyric-melodic-roadmaps.md` cited `meter-prosody` by an unresolvable path.** The + keep-these-four-consistent sentence named `prosody.md` and `meter.md`, which are siblings and + resolve, alongside `skills/meter-prosody/SKILL.md`, whose implied base is the plugin root while + its real base is `context/pat-pattison/research/`, the defect class + [ADR 0018](../../docs/adr/0018-treat-the-plugin-as-the-encapsulation-boundary-for-skill-citation.md)'s + correction 1 names. It now reads `${CLAUDE_PLUGIN_ROOT}/skills/meter-prosody/SKILL.md`, the + anchored form this `research/` tree already uses for the Datamuse script. The sentence is the + plugin's own prose, not printed Pat Pattison text, so the distilled-corpus exclusion does not + cover it. Intra-plugin citation, legal under clause 1; clause 3 only, so the target is unchanged. + ## [1.4.17] ### Added diff --git a/plugins/songwriting/context/pat-pattison/research/lyric-melodic-roadmaps.md b/plugins/songwriting/context/pat-pattison/research/lyric-melodic-roadmaps.md index e9b31e5f5..c71d2ad48 100644 --- a/plugins/songwriting/context/pat-pattison/research/lyric-melodic-roadmaps.md +++ b/plugins/songwriting/context/pat-pattison/research/lyric-melodic-roadmaps.md @@ -200,7 +200,7 @@ is in the second one. Matching a lyric to a *model lyric* (verse 2 against verse *melody* — the frame of this whole file — a mismatch in **either** direction is a greedy spot, because either one fights the bar. That two-frame split is the plugin's, not Pat's, and it is stated the same way in `prosody.md`, `meter.md` -and `skills/meter-prosody/SKILL.md`; keep the four consistent. +and `${CLAUDE_PLUGIN_ROOT}/skills/meter-prosody/SKILL.md`; keep the four consistent. Pat's printed passage, which is the *model-lyric* frame: diff --git a/plugins/source-control/.claude-plugin/plugin.json b/plugins/source-control/.claude-plugin/plugin.json index d1e9a8a92..84847b64e 100644 --- a/plugins/source-control/.claude-plugin/plugin.json +++ b/plugins/source-control/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "source-control", - "version": "0.55.29", + "version": "0.55.30", "description": "Git and GitHub delivery workflow: /commit (Conventional Commits + Co-authored-by trailer via safe heredoc mechanics), /pull-request (prep, create, CI monitoring, review-comment triage, merge, CI-log fetch), /babysit-prs (self-pacing fleet loop \u2014 safe by default; opt-in worker/autopilot tiers add gate-checked merge and thread resolution behind a deterministic Python engine), /babysit-loop (the loop-lane merge lane: a standing or drain loop that invokes babysit-prs per cycle, configured through repo-scoped babysit_loop_* keys on the layered source-control.md seam, with merge authority human-only until the target repo's tracked config adopts the lane, a gate-proven C2-mechanical baseline once adopted, and standing merge-rung raises binding from the team-tracked layer only \u2014 with one named exception, where an invocation line explicitly typing both the autopilot tier keyword and the dedicated raise argument --merge c3-this-run widens that single invocation's merge authority up to C3 behind a fresh independent frontier-tier resolver, while C4-structural and C5-untrusted-provenance stay unconditionally human-merge), /worktree (create, status, cleanup, audit for parallel-session isolation), /setup (check the effective commit-subject / PR-title convention merged across its config layers and the babysit-prs config, or apply \u2014 interview the repo and write the convention config to a chosen layer), and /resolve-conflicts (intent-first merge/rebase conflict resolution with a semantic-conflict sweep \u2014 never --abort). The commit-subject / PR-title convention is configurable via a source-control.md config written by a re-runnable setup skill, layered across a ~/.claude user-global file, the tracked team file, and a gitignored .claude/source-control.local.md personal overlay merged per key; Conventional Commits is the default when no convention is declared.", "author": { "name": "Melodic Software", diff --git a/plugins/source-control/CHANGELOG.md b/plugins/source-control/CHANGELOG.md index b9b1cf370..5d2e7bc1d 100644 --- a/plugins/source-control/CHANGELOG.md +++ b/plugins/source-control/CHANGELOG.md @@ -3,6 +3,31 @@ All notable changes to the `source-control` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.55.30] + +### Fixed + +- **`reference/config-resolution.md` cited `babysit-prs` by a path that resolved + against nothing.** The autonomy-table pointer read + `skills/babysit-prs/SKILL.md`, whose implied base is the plugin root while its + real base is `reference/`, the defect class + [ADR 0018](../../docs/adr/0018-treat-the-plugin-as-the-encapsulation-boundary-for-skill-citation.md)'s + correction 1 names. It now names the public invocation, + `/source-control:babysit-prs`, keeping the section name. + + **The `${CLAUDE_PLUGIN_ROOT}` form this fix first took was wrong for the reader + that most needs it.** `work-items`'s `work` skill fetches this file over + `raw.githubusercontent.com`, and for that reader `${CLAUDE_PLUGIN_ROOT}` denotes + the `work-items` installation, so the anchor resolved to a `babysit-prs` skill + that does not exist there. This sentence is the doc's address for the autonomy + obligation, which is the case + [ADR 0018](../../docs/adr/0018-treat-the-plugin-as-the-encapsulation-boundary-for-skill-citation.md)'s + 2026-08-28 amendment routes to the invocation rather than to a path whose + meaning depends on which plugin fetched the document. Found by a third + derivation over the plugin-level `reference/`, `context/` and `agents/` trees + whose predecessor could not see citations of a `SKILL.md` itself; the remedy + corrected by review before merge. + ## [0.55.29] ### Changed diff --git a/plugins/source-control/reference/config-resolution.md b/plugins/source-control/reference/config-resolution.md index b31b4e0c3..0f9c8b246 100644 --- a/plugins/source-control/reference/config-resolution.md +++ b/plugins/source-control/reference/config-resolution.md @@ -121,7 +121,7 @@ binding layer, never unioned). | `babysit_loop_trusted_internal_bot_logins` | flat Markdown bullet list (`- ` per line) of exact GitHub App bot logins the repository attests as its own internal automation — the C5 trust test's reviewed internal-bot trust signal; **honored in the team-tracked layer only** ("the C5 trust test's one reviewed widening" below) | none — empty set: the trust test accepts `OWNER`/`MEMBER` only | Dimension semantics — what each tier value grants per dimension — are owned by the babysit-prs -autonomy table (`skills/babysit-prs/SKILL.md`, "Autonomy tiers (per action class)") and are not +autonomy table (`/source-control:babysit-prs`, "Autonomy tiers (per action class)") and are not restated here. The merge dimension's rung semantics are owned by the loop-lane convention's autonomy ladder (`docs/conventions/loop-lane/README.md` §1 in the marketplace repository). diff --git a/plugins/work-items/.claude-plugin/plugin.json b/plugins/work-items/.claude-plugin/plugin.json index d9850f21a..ac7149954 100644 --- a/plugins/work-items/.claude-plugin/plugin.json +++ b/plugins/work-items/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "work-items", - "version": "0.39.38", + "version": "0.39.39", "description": "Manages development work items through a provider-neutral tracker seam that ships with the plugin (bundled dispatcher plus github, local-markdown, jira, gitea, and linear adapters; seam plugin-dir canonical, adapters consumer-local-first): dashboard, taxonomy-labeled creation, a race-safe assignee-plus-lease claim protocol, recurring-schedule checks, TODO scanning, stale-lease auditing, plan decomposition into vertical-slice items, a macro-journey router over spec containers (rollup, per-container execution shape, next-step routing), raw-intake triage (issues and unsolicited PRs through raw, verified, briefed, autonomous-eligible states), plus the two work-items loop lanes of the loop-lane convention: a self-paced autonomous work-loop drain (work-class admission gate, adaptive item cap, PR-only) and an attended attend-queue escalation lane. The re-runnable setup skill binds the provider (.work-item-tracker.json), seeds the recurring-schedule seam (.github/recurring-schedule.json), and remaps canonical role labels.", "author": { "name": "Melodic Software", diff --git a/plugins/work-items/CHANGELOG.md b/plugins/work-items/CHANGELOG.md index c80c3c2a4..dc66a71af 100644 --- a/plugins/work-items/CHANGELOG.md +++ b/plugins/work-items/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to the `work-items` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.39.39] + +### Fixed + +- **`reference/permission-preflight.md` cited the `work` skill by an unresolvable path.** The Step 0 + pointer for the `reclaim` classifier-denial mitigation read `skills/work/SKILL.md`, whose implied + base is the plugin root while its real base is `reference/`, the defect class + [ADR 0018](../../docs/adr/0018-treat-the-plugin-as-the-encapsulation-boundary-for-skill-citation.md)'s + correction 1 names. It now reads `${CLAUDE_PLUGIN_ROOT}/skills/work/SKILL.md`, the form the same + file already uses for `preflight.sh`. Intra-plugin citation, legal under clause 1; clause 3 only, + so the target is unchanged and no routing moves. + ## [0.39.38] ### Changed diff --git a/plugins/work-items/reference/permission-preflight.md b/plugins/work-items/reference/permission-preflight.md index 2ed276e27..c183b0cac 100644 --- a/plugins/work-items/reference/permission-preflight.md +++ b/plugins/work-items/reference/permission-preflight.md @@ -42,7 +42,8 @@ matching "arbitrary-code-execution patterns" as routed through the classifier re defining that pattern set precisely enough to say which side a script invocation (`work-item-tracker.sh reclaim `) falls on. Do not write a rule into the standards floor on the strength of this doc alone; confirm the carve-out first. `/work-items:work`'s Step 0 treats a classifier denial of -`reclaim` as a non-blocking, report-once-and-skip condition (see `skills/work/SKILL.md` "Step 0") — +`reclaim` as a non-blocking, report-once-and-skip condition (see +`${CLAUDE_PLUGIN_ROOT}/skills/work/SKILL.md` "Step 0") — that is the current mitigation; a permission-rule fix, if one applies, still lives operator-side per the pattern above.