Skip to content

fix: correct plugin-system inaccuracies and harden references - #2

Merged
kyle-sexton merged 1 commit into
mainfrom
chore/audit-accuracy-fixes
Jun 22, 2026
Merged

fix: correct plugin-system inaccuracies and harden references#2
kyle-sexton merged 1 commit into
mainfrom
chore/audit-accuracy-fixes

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

Summary

Full per-file audit of the repo against current official Claude Code docs (re-verified this session per the repo''s fresh-docs mandate). The vast majority of existing content was confirmed accurate; this PR fixes the real inaccuracies found and strengthens references. No code, only manifest/docs.

Real defects fixed

  • marketplace.json — off-schema owner.url. The documented owner object supports only name (required) + email (optional) — url is not a valid owner field. Replaced with the documented contact field using the info@melodicsoftware.com shared inbox (matches the docs'' DevTools Team / devtools@example.com team-alias example; no personal PII). Source: plugin-marketplaces "Owner fields".
  • MIGRATION-PLAYBOOK.md — wrong namespacing. Components are namespaced by the plugin''s own name, not the marketplace name. Corrected /melodic-software:foo/<plugin-name>:foo. Source: plugins-reference (plugin-dev:agent-creator example).

Polish / accuracy

  • marketplace.json — added $schema → published SchemaStore marketplace schema (editor validation; Claude Code ignores it at load time).
  • MIGRATION-PLAYBOOK.mduserConfig types also include directory/file; non-sensitive values stored under pluginConfigs[<id>].options.
  • CLAUDE.md — canonical-docs table made comprehensive (plugin dependencies, slash commands, memory, .claude directory, tools reference) + cited the two SchemaStore JSON Schemas.

Verified-correct (no change needed)

All plugin env vars/paths (CLAUDE_PLUGIN_ROOT/DATA/PROJECT_DIR, cache/data paths), userConfig→keychain storage, hooks/hooks.json, agent shadowing precedence, extraKnownMarketplaces + CLAUDE_CODE_PLUGIN_SEED_DIR headless guidance, claude plugin validate / --plugin-dir, all README commands, and .gitignore (CLAUDE.local.md and .claude/rules/ are both current, documented features).

Validation

claude plugin validate . → passes (exit 0; only the expected "no plugins defined" warning). JSON parses.

🤖 Generated with Claude Code

Audited every file against current official Claude Code docs (verified
this session) and fixed the inaccuracies found:

- marketplace.json: drop off-schema `owner.url` (the documented owner
  object supports only `name` + `email`) and use the documented contact
  field with a role-based shared inbox; add the `$schema` pointer to the
  published SchemaStore marketplace schema for editor validation.
- MIGRATION-PLAYBOOK.md: components are namespaced by the plugin's own
  `name`, not the marketplace name (`/<plugin-name>:foo`); correct the
  prior `/melodic-software:foo` claim. Tighten userConfig detail:
  supported types include directory/file, and non-sensitive values are
  stored under `pluginConfigs[<id>].options`.
- CLAUDE.md: make the canonical-docs table comprehensive (plugin
  dependencies, slash commands, memory, the .claude directory, tools
  reference) and cite the SchemaStore JSON Schemas for the repo's JSON.

Sources: plugins-reference, plugin-marketplaces, sub-agents, memory docs
at code.claude.com; schemas at json.schemastore.org. `claude plugin
validate .` passes (only the expected "no plugins defined" warning).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kyle-sexton
kyle-sexton merged commit bd5c35a into main Jun 22, 2026
1 check passed
@kyle-sexton
kyle-sexton deleted the chore/audit-accuracy-fixes branch June 22, 2026 21:02
@claude claude Bot mentioned this pull request Jul 11, 2026
kyle-sexton added a commit that referenced this pull request Jul 12, 2026
Address two more Codex P2 findings plus the analogous coaching case:

- codebase-detection case (#2): the eval repo has no real auth-flow
  module, so grounding would fail or reward inventing sources. Reframe to
  the routing + graceful-degradation invariant — resolve to codebase
  mode, discover from live files, and ask the user to point when no
  grounding exists rather than inventing repo sources.
- primary-source case (#5) and coaching case (#4): a fresh topic
  invocation runs the mission interview before teaching, so expecting
  immediate content rewarded skipping the mission gate. Make both
  gate-aware — respect the new-workspace mission flow while asserting the
  grounding / one-question-coaching invariants.
kyle-sexton added a commit that referenced this pull request Jul 13, 2026
… hardening (#138)

Applies the resolved `planning/setup` hardening to `knowledge/setup`'s
`library_dir` seam (same single-directory `userConfig` shape, same
latent issues).

## Changes

**`plugins/knowledge/skills/setup/SKILL.md`**
- **Precedence** — step 1 now resolves the full documented order
(Managed > `--settings` > Local > Project > User), warns when higher
layers are unreadable instead of declaring a lower value authoritative,
and surfaces layer shadowing before the project write.
- **Portability** — step 5 guards the tracked project write: never
propagate a machine-specific personal-layer value into team settings;
route personal-only overrides to `.claude/settings.local.json`
(portability required only for the shared project write).
- **Declared-convention alignment** — inspect the repo's declared
working-notes/artifacts convention even when a value is set; surface
divergence and offer to reconcile.

**`plugins/codebase-audit/skills/setup/SKILL.md`** (partial match —
writes a tracked `.md`, not settings)
- Applied only the precedence/shadowing subset: step 1 reports the
*effective additively-merged* config across user-global → team → local
layers (and warns on unreadable layers), instead of summarizing the team
file alone. Settings-write portability specifics do not apply.

## Deviations (own-flagged)

1. **Fix #3 premise softened for knowledge.** The issue's fix #3
parenthetical assumed knowledge "honors that convention over the config
at write time" (true for planning). Verified via
`skills/youtube/extraction/lib/work-root.js` and the youtube pipeline
that **knowledge resolves `library_dir` directly at write time — no
skill overrides it with a repo convention at runtime.** Documenting that
behavior would be false, so I softened the imported write-time-override
claim: `library_dir` is runtime-authoritative, and setup's job is to
keep it *aligned* with any declared convention. Fixes #1 and #2 are
unaffected.
2. **`codebase-audit` version bump not in issue scope.** Patch-bumped
`0.1.0 → 0.1.1` because its SKILL behavior changed; the issue only
specified the `knowledge` minor bump.

## Verification
- `knowledge` `plugin.json` minor bump `0.2.0 → 0.3.0`; `codebase-audit`
`0.1.0 → 0.1.1`.
- `claude plugin validate` clean on both plugins.
- markdownlint clean on both edited files.

Refs melodic-software/medley#1463

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Changes are limited to plugin skill documentation and version
metadata; no application runtime or security-sensitive code paths are
modified.
> 
> **Overview**
> **Hardens setup skills** for the `knowledge` and `codebase-audit`
plugins so interactive setup reflects layered config reality instead of
treating a single team file as authoritative.
> 
> For **`knowledge/setup`**, step 1 now follows the full Claude Code
precedence chain (Managed → `--settings` → Local → Project → User),
warns when higher layers are unreadable, and calls out when a project
write would stay shadowed. A new step reconciles `library_dir` with
repo-declared working-notes conventions even when a value is already
set. Persistence (step 5) blocks copying machine-specific personal paths
into tracked project settings, routes personal-only overrides to
`.claude/settings.local.json`, and the output section documents honest
pipeline behavior (`book-distill` ignores `library_dir`; YouTube does
not yet honor it). **`knowledge`** bumps **0.2.0 → 0.3.0**.
> 
> For **`codebase-audit/setup`**, step 1 is expanded to summarize the
**effective merged** config across user-global → team → local layers
(including dimension opt-outs via empty source lists), explain that only
the team file is written, and warn when overlays block re-enabling
dimensions. **`codebase-audit`** patch-bumps **0.1.0 → 0.1.1**.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f13139a. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
kyle-sexton added a commit that referenced this pull request Jul 15, 2026
## Summary

Executes the owner-approved tier-2 restores from the salvage sweep
(items #2#12 plus semantic-drift items D1–D4): pre-migration behavior
and guidance dropped at the cutover, restored and genericized to the
marketplace's repo-agnostic seams. Every touched plugin gets a version
bump and CHANGELOG entry.

| Plugin | Version | Restored |
|---|---|---|
| claude-config-audit | 0.4.0 | Pre-computed context blocks (3 skills) +
`allowed-tools` scoping; all script paths
`${CLAUDE_PLUGIN_ROOT}`-rooted; every `!` command empirically tested
with fallbacks |
| event-storming | 0.3.0 | `--design-level` missing-prerequisite guard
(never fabricate a process model) + eval id 7; bare "memory" refs swept
to the `${CLAUDE_PLUGIN_DATA}/history.jsonl` seam |
| planning | 0.9.0 | Agent-team vs fan-out composition guidance in
/architect Step 4.5 (decompose by context boundary, never lifecycle
role; disjoint file ownership); baseline capture routes to
`/implementation:verify-improvement` SSOT when installed;
devils-advocate regains the `/implementation:verify-changes` pointer |
| session-flow | 0.4.0 | Retro ecosystem-improvement catalog
(`reference/`, 221 lines) — hook-event table reconciled against the
current hooks doc (8 events added, 2 medley errors fixed); handoff
failure-pattern `context/gotchas.md` |
| review-toolkit | 0.5.0 | Normalization-pipeline model assignment
(Stage 0/3 Sonnet, 1–2 deterministic/Haiku, 4 deterministic) + per-stage
heading annotations |
| implementation | 0.5.0 | Optional `tool-pin` version-drift warning in
/lint + ecosystem-commands contract 1.1.0 (additive schema key, per the
contract's own versioning rule); /implement over-correction trap logs to
the session retro when installed |
| codebase-audit | 0.2.0 | Background/unattended Phase 1 fan-out variant
(graceful-degrade framing) |
| code-tidying | 0.4.0 | Stdlib-only frontmatter-fence integrity check
in the self-update lane (pass/fail paths tested) |
| prototype | 0.2.1 | Composition table (fully-qualified marketplace
names, `when installed` gating); named `session-flow:handoff` seam in
the auto-invoke gate |

## Playbook compliance

- Repo-agnostic: coupling grep over all added lines is clean (no medley
paths, no consumer-repo names, no reach-outs); cross-plugin references
use fully-qualified names with graceful "when installed" degrade.
- Fresh-docs: `disable-model-invocation`/frontmatter,
`${CLAUDE_PLUGIN_ROOT}` substitution scope ("Skill and agent content —
anywhere the placeholder appears"), and the hook-event table were
verified against code.claude.com docs this session.
- `docs/conventions/ecosystem-commands/` confirmed repo-owned (not a
standards-managed materialization) before the schema edit.
- All nine plugins pass `claude plugin validate`; catalog passes `claude
plugin validate --strict`; new/changed markdown passes markdownlint-cli2
(0 errors); the new eval validates against `evals.schema.json`.

## Security review note (claude-config-audit 0.4.0)

The pre-computed context blocks add a code-execution-at-skill-load
surface: `!` commands run when the skill is invoked. Scope check per the
plugin-acceptance review: all commands invoke scripts **bundled inside
the plugin** via `${CLAUDE_PLUGIN_ROOT}` (no `../` reach-outs, no
absolute paths), are read-only inventory/count operations, carry `||
echo`-style fallbacks so load never hard-fails, and make no network
calls. The `allowed-tools` entry pre-approves exactly the one bundled
read-only script, nothing broader.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_011xHkkNc7CR98L8Xz9Mu7ZA

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Jul 16, 2026
… follow-ups) (#205)

## Summary

The three follow-ups deliberately deferred out of #204 (recorded in its
PR body), each decision-gated with the maintainer before editing. Net
**−341 lines**; no plugin manifest, schema, or skill behavior touched.

## #1 — Retire the audit snapshots

Delete `docs/evals-coverage.md` and
`docs/extensibility-contract-grading.md`. They were hand-stamped,
point-in-time records that drift the moment a plugin changes (the reorg
already forced a two-layer temporal re-stamp).

**Retire over generate.** The durable policy already lives in
`docs/MIGRATION-PLAYBOOK.md` — the warrant rule + consumer-verify recipe
("Evals — warrant policy and consumer-verify recipe") and the four-seams
contract ("Extensibility contract v2.1"). A generator could derive only
eval *presence* (a live glob) — the minority of one doc and none of the
other; class, contract grades, and medley program state stay irreducibly
hand-graded or externally-owned. Generating only the presence slice
yields a half-generated hybrid that still drifts on its biggest surface.
Retire is the clean fit.

**Gaps captured first.** Two warranted-but-unowned eval gaps were
recorded *only* in the retired snapshot (verified still live against the
tree): `context7/setup` and `planning/wayfind`. Filed durably before
deletion:
- `melodic-software/medley#1537` — evals(context7/setup)
- `melodic-software/medley#1538` — evals(planning/wayfind)

Inbound pointers updated: README doc-index (2 bullets removed) and the
playbook's evals section (now states on-demand verification instead of
pointing at a deleted snapshot). No dangling references remain
(repo-wide grep clean).

## #2 — Reclassify the depth-variant convention tension

The playbook stated a depth/intensity variant "takes an argument, never
a sibling," yet `discovery`'s `explore-deep` / `research-deep` ship as
sibling skills. Inspection shows they are **structural, not depth**:

- `explore-deep` — `context: fork` + `agent: general-purpose`: a
distinct execution *topology* (isolated forked subagent), declared in
frontmatter, not expressible as a runtime argument.
- `research-deep` — a dispatcher to the heaviest isolated tier (workflow
engine, forked subagent, or inline fallback), with its own body and
auto-invocation description.

The convention needed no exception — it needed a sharper
structural/depth test. Amended to classify **execution tier as a
structural axis** (sibling) and bind the `-deep` suffix to that axis, so
the naming no longer reads as a violation and a future reader does not
re-flag it. A true effort knob on one execution path still takes an
argument. No skills renamed.

## #3 — README revisit-condition dedup

Assessed, closed **no-op**. The coupling flagged in #204 is a
documented, directional SSOT+index: `docs/CATALOG-TAXONOMY.md` (L71–73)
declares plugin-scoped revisit conditions are *owned by each plugin's
README* and the taxonomy "Trigger register" lists them "only as
pointers." The READMEs are the single owners of genuine plugin-specific
rationale; the register summarizes them. Nothing to dedup. Confirmed
none of the three sections cross-names the taxonomy doc.

## Verification

- `scripts/validate-plugins.sh`: pass (all manifests + strict catalog
sync)
- `scripts/run-plugin-tests.sh`: 7 passed, 0 failed
- `markdownlint-cli2`: 0 errors on both touched markdown files
- Repo-wide grep for the retired doc names: no remaining references

## Note (not in this PR)

`docs/hook-migration-audit.md` is the same "point-in-time audit" genus
as the two retired here. Left untouched; flagged for a consistency
decision in a later pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_0163dXPBdRYFpx4wTtS648tE

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Aug 11, 2026
The refuting pass found real defects in the orchestrator's own work for the
sixth session running, and the review gate was right twice more.

WRONG BOOK ON SIX LINES. The punctuation sweep asked "is the ASCII form absent
from ANY of the four books?" That is not "does the book this passage cites print
it that way?", and the difference is load-bearing: the 2009 book genuinely prints
ASCII apostrophes (2,373 ASCII against 6 curly in its own EPUB) while 1991, 2011
and 2014 print curly, so every line Pat reprinted in 2009 got a free pass.

- song-forms.md:581,582,584,587 — a block cited to 1991 at :567, in a section
  whose own line 564 warns that 2009 prints the same lyric differently. The file
  documented the trap and the sweep walked into it.
- brainstorm.md:148, object-writing.md:420 — the two lines settled by hand; both
  blocks are cited to 2011 and both were aligned against 2009. Anchor uniqueness
  within 2009 was never the question.

Each repair is asserted present in its citing book and absent before the change.

RECEIPT ACCURACY. The changelog reported 468/468 and 393 quotation marks. The
shipped totals are 470/470 and 396 — 308 apostrophes plus 396 quotes, 704
characters. The old figures described the state before the two hand-applied
lines. Corrected, along with the same error in T4's line-number citations.

TWO CLAIMS IN voices.md WERE FALSE.

- The public-toggle warning was described as disputed in its own thread. It is
  not: a reader asked a clarifying question and the poster re-affirmed it. Being
  told to discount a safety warning on the strength of a dispute that does not
  exist is worse than not raising it. The source is the poster, not "one
  commenter", and the warning applies to every voice creation.
- The section asserted in bold that the bootstrap "agrees with" the file's
  existing "sing actual melodies, not spoken word" rule. It does not. That rule's
  reason is that the model must learn your sung timbre; here the only audio a
  human performs is speech, and voice #2 learns from Suno's synthesis of a
  speech-trained clone. Record the tension, never resolve it away — the first
  version broke this project's own standing rule. Now stated as unresolved, with
  the better-supported route named, plus two further unrecorded interactions: the
  anti-impersonation phrase compares against "your uploaded singing" while stage
  4 uploads generated audio, and the reported ~95-100% Audio Influence sits above
  the 85%+ over-fit tier this same file describes.

REVIEW GATE. troubleshoot.md:19's effect column still read "Trailing tags
ignored" as a certainty after its cause column was hedged. Softened to match.

NEWLY INCOHERENT STEP. troubleshoot.md's "Exclusions are being ignored" fix list
opened with a step that then told the reader it was not a verified rule — a fix
list whose first step fixes nothing. Moved out of the numbered list to prose.

Also: v55-features.md now says "no source was found placing them" rather than
asserting a completed search; the [Fade In] qualifier moved out of the table cell
to prose, matching the [Synth Solo] precedent it cites; book-references.md no
longer claims the README carries all four full catalogue titles (1991's dc:title
carries a subtitle the README drops); and README.md now points back at
book-references.md, since the regrowth guard only protected one direction.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Aug 11, 2026
…y finding, and stop calling the addition mechanical (#2206)

## Summary

`claude-config`'s `audit` skill had a two-link defect chain in Category
B. Batch-4 reconciliation
**AD-13** requires both links ship as one change, and they do.

**Link 1 — no channel for hook coverage to retract a baseline finding
(#2201).** Category B iterates the
baseline permission patterns and states flatly that each "must appear"
in `permissions.deny`, rated
`error`. Its only two off-ramps are keyed on the *consuming repo*
writing prose: a documented exemption
in its own rules files (`required-permissions.md:138-142`), or its own
documented hook conventions
(`:157-160`). Neither is keyed on a hook that is actually installed and
enabled, and `grep -rn "hook"`
across the whole skill returns no `hooks.json` read, no plugin-hook
enumeration, and no coverage concept
at all. So a repo that blocks `git push --force` with a `PreToolUse`
hook exiting 2 — which
[permissions.md](https://code.claude.com/docs/en/permissions.md) says
"stops the tool call before
permission rules are evaluated, so the block applies even when an allow
rule would otherwise let the call
proceed" (raw fetch, 2026-08-11) — was told its security floor was
missing.

"Narrowing the baseline" now carries a third narrowing: a family already
blocked by an **installed,
enabled** `PreToolUse` hook is `info`, not `error`, whether the hook
came from the repo or from a plugin.
It obliges the report to name the residual — plugin disable/uninstall,
per-guard opt-out, and
`allowManagedHooksOnly` / `strictPluginOnlyCustomization` — because hook
coverage is contingent in ways a
deny rule is not, and an `info` that hides that is worse than the
`error` it replaced. And because the
skill genuinely cannot enumerate a plugin's `hooks/hooks.json`, a run
that took no inventory now states
the finding **conditionally** ("if a `PreToolUse` hook on `Bash` already
blocks this family, this finding
is void") rather than asserting it. Fail open, not fail silent.

**Verification sharpened the wiring half.** The two existing off-ramps
were not in Category B's
instruction path at all — the category delegates by *pattern* ("iterate
the patterns in
required-permissions.md") and `audit-checklist.md:21-24` says "assert
presence per sub-category". Neither
names the off-ramp sections. A third off-ramp added to
`required-permissions.md` alone would inherit that
same weak wiring, so Category B and the checklist's B.1–B.3 severity
table now both point at "Narrowing
the baseline", and the table says its ratings are the *unnarrowed* ones.
(`audit-checklist.md` is not in
the ledger's fix sketch; it is added deliberately under AD-13's own
logic — leaving a flat `error` rating
there would have left a third file asserting the opposite.)

**Link 2 — the false positive was routed into `--fix` as mechanical
(#2202).** `procedures.md:49` graded
"Add missing baseline deny rules" `Auto-fixable: Yes (from checklist)` /
`Requires judgment: No`, and
`SKILL.md:212-214` restated that in prose. It is now judgment-required
with the judgment written out —
is the family already covered, and would the addition suppress a gate
the project built deliberately.
*Moving* a deny rule from local to project stays mechanical (that is
#8961 placement, not a policy
change), and `SKILL.md` splits the two the same way.

**Corrected rationale, stated so it is not shipped wrong.** The filed
claim was "no human judgment gate",
which is accurate as written and must not be read as "no human gate" — a
*confirmation* gate exists at
`SKILL.md:187-193` and is already pinned by eval #2. Adding a
confirmation prompt is therefore **not** the
fix. The residual harm is narrower: the matrix told the user this class
of edit needed no thought, next to
an offered reply `'all'` that applies the lot in one keystroke. Two more
scope statements kept honest —
the applied change was *more* deny rules, which is fail-closed rather
than a security regression; and the
ask-suppression harm requires a hook that **returns an `ask` decision**,
since a hook blocking by `exit 2`
short-circuits before permission rules and suppresses nothing.

**What review added, and it materially improved the change.** Seven
threads, all substantive, all
addressed:

- **The narrowing was too generous, three ways.** It is now fenced by
three preconditions. The hook must
be *live*: `disableAllHooks`, `allowManagedHooksOnly`, and
`strictPluginOnlyCustomization` were named
only as a future residual, and a hook one of them has already switched
off blocks nothing, so under
any of them the finding stands unnarrowed. The hook must be on the tool
surface the pattern defends:
`sensitive-file-deny` is a `Read`-pattern family, so a `Bash`-only hook
leaves `Read`/`Grep`/`Glob`
open and retires nothing there. And it must block *that* family —
force-push coverage says nothing
  about `git clean -fd`, nor a long flag about its short spelling.
- **The liveness precondition cited a check that did not exist.** It
told the auditor to take the lever
reading from Category D; Category D checks paths, readability, timeouts,
matchers, exec-form
resolution, duplicates, and events, and never asked whether the hooks it
inventoried could run. All
three lever names appeared nowhere in the skill. That is the same
false-assurance shape this PR set
out to remove, so **Category D now reads and reports all three** (`info`
— a repo may set them
deliberately, and the reading is state, not a defect), and where the
reading was not taken the
  narrowing is **unavailable** rather than assumed clear.
- **And the reading is sequenced.** Category B owns the narrowing and
runs before Category D. A–I is
presentation order, not a dependency ban, so Category B says to pull the
reading forward or defer the
downgrade and revise the severity after Category D runs. On a
scope-filtered run like
`/audit permissions`, which never reaches Category D, the narrowing is
unavailable unless the operator
  supplies the state.
- **Three pointer sites had gone stale** against my own tightening,
still saying "installed, enabled".
  Fixed, then swept.
- **The changelog shape misrepresented the bump.** Everything sat under
`### Fixed` while the bump is
minor. Two graded outputs genuinely move, so the behavior changes are
now under `### Changed` with the
reason up front, the wiring repairs under `### Fixed`, and the new
material under `### Added`.

Three evals, not one, and they grade the discriminations rather than the
happy path:

| # | Case | Grades |
|---|---|---|
| 8 | `baseline-deny-narrowed-by-installed-hook` | per-family narrowing
— force-push and hard-reset drop to `info` under a live Bash hook, while
`git clean` patterns it does not match and `sensitive-file-deny` Read
patterns it cannot reach hold at `error` |
| 9 | `no-hook-inventory-states-the-finding-conditionally` | the
fail-open half — no inventory means a conditional finding, not an
assertion |
| 10 | `suppressed-hook-does-not-narrow-the-baseline` | the negative
case the liveness fence exists for — a declared hook under
`disableAllHooks: true` narrows nothing |

No trust surface widened: no new hook, no new grant, no new external
read or write. The permission
guidance moves in the direction of fewer manufactured deny-rule
additions, and the new Category D row is
a read-and-report of settings the audit already has in hand.

## Test plan

There is no executable test for this change — it is skill content plus
`evals.json`, and this skill's
`scripts/` cover plugin-drift and settings structure, not Category B
prose. The honest gates are the
static ones, all run against the working tree:

```
$ jq empty plugins/claude-config/skills/audit/evals/evals.json && echo "evals.json: valid JSON"
evals.json: valid JSON
$ jq empty plugins/claude-config/.claude-plugin/plugin.json && echo "plugin.json: valid JSON"
plugin.json: valid JSON

$ bash plugins/skill-quality/scripts/check-evals-quality.sh plugins/claude-config/skills/audit/evals/evals.json
check-evals-quality: PASS (0 warning(s) across 1 file(s))
# (this one earned its keep — it caught eval 9 sharing eval 1's prompt verbatim,
#  which would have made the two gradeable only by out-of-band context)

$ CHECK_SKILL_SKILLS_ROOT="$PWD/plugins/claude-config/skills" bash plugins/skill-quality/scripts/check-skill.sh audit
INFO: description length 444/1536 chars
INFO: all 3 base-ref trigger phrase(s) preserved
INFO: SKILL.md 256/500 lines
INFO: markdownlint clean
INFO: script test passed: scripts/check-plugin-drift.test.sh
INFO: script test passed: scripts/check-structure.test.sh
INFO: script test passed: scripts/fix-plugin-drift.test.sh
WARN: SKILL.md is 256 lines (soft target 200 — consider pushing detail to progressive-disclosure spokes)
WARN: no Gotchas surface (inline '## Gotchas' or context/gotchas.md) — confirm the skill has no observed failure history
INFO: no metadata.category in frontmatter (optional — category not machine-readable)
INFO: shell: declared — dynamic-context injection portability is the author's explicit choice
INFO: summary 90/100 codepoints

CHECK-SKILL audit: PASS — 0 errors, 2 warning(s)

$ npx --no-install markdownlint-cli2 --config .markdownlint-cli2.jsonc plugins/claude-config/CHANGELOG.md
markdownlint-cli2 v0.23.2 (markdownlint v0.41.1)
Summary: 0 issues in 0 files
```

Both `check-skill` warnings pre-date this change (the SKILL.md soft
target and the absent Gotchas
surface); this diff adds 4 lines to `SKILL.md`. Every gate above was
re-run after each review round;
the output shown is from the final tree.

## Related

Closes #2201
Closes #2202

Inbox item:
`20260810-225905-claude-config-audit-category-b-hook-blindness.md`
(batch-4 ledger `I2`,
rows `A1` + `A3`; row `V1` is folded into `A3`'s judgment wording per
the ledger and is deliberately
**not** filed separately).

Ledger rows in `I2` left filed-not-fixed by design: `A2` (baseline
recommends the pattern class upstream
calls fragile — MED, adjacent section of the same file), `A4` (nothing
reads a plugin's `hooks/hooks.json`
— MED, and the reason the new off-ramp has to fail open rather than
enumerate), `B5`'s Category G half
(belongs to item `…-category-g-unmeasurable`), `MN1` (LOW). Issue filing
for those rows is held pending
the operator's call on batch-4 filing volume (RECONCILE OR-4).

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Aug 15, 2026
Fills PLAN.md's empty `## Plan` with an eight-phase sequence and records the
Tier B design early-exit that gates it.

The spine is ordered by two constraints that are easy to miss. Fanout is
findings producer #1, so the first detector of any kind makes producer #2 and
the single-file consumer becomes a silent-shadowing bug -- coexistence is
strictly phase 1, not merely early. And the owner doc precedes the *second*
adopter, so the Pattern-C proof slice runs before the detector contract is
written rather than after it.

Draft only: the fresh-context stress-test has not been applied yet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Aug 15, 2026
…sues, contract-slice prune (#2686)

No linked issue

## Summary

Answers "what can we do with the maintenance-routine pattern" for this
marketplace, and lands the answer as durable artifacts rather than a
document. Eight research lanes and three verification passes ran to
completion; this PR graduates what they settled and prunes the working
slice.

The research inverted the original framing three times, and the plan
encodes the inverted shape:

1. **The apply machinery already exists and is reachable by file format
alone.** What is missing, class after class, is a **detector** to feed
it. Validated empirically, not inferred: a hand-written conforming file
from a non-fanout producer passed the fix action's locator, frontmatter
gate, exact-branch check, and table parse.
2. **Merge rate cannot justify any of this.** Peer-reviewed
observational work, a large-N regression, and a randomized trial all
find artifact quality weakly-to-not coupled to acceptance. The
verification contract is justified on defect escape and reviewer burden,
never acceptance. Nothing here cites the source's 388/180 figures as
evidence of efficacy — a single self-report with no independent
corroboration and no published methodology.
3. **Class-level beats instance-level.** Three lanes converged from
different literatures: durable wins come from policy and mechanism, not
from better per-instance agent judgement.

## Fix

**ADR 0010 — merge findings across producers, and mark consumption
explicitly.** The correctness gate the whole effort turns on.
`review:fanout`'s fix action consumes exactly one findings file and
merges nothing (`context/fix-pass-mode.md:3,7`), which is safe only
while fanout is the sole producer. The first detector of any kind makes
producer #2, at which point the later timestamp silently wins and the
earlier producer's findings are never applied — no error, no warning,
run reports success. Three decisions, each with a rejected alternative
that had a real case:

- The consumer merges the conforming set instead of picking the newest,
and unions the coverage fields rather than reporting one producer's.
- Cross-producer dedup is **presence-only**. The existing ±3-line key
sits behind a Sonnet semantic stage the fix action does not have, and
adopting the bucket without the semantics would invert the pipeline's
own minimise-false-merge rule and silently discard a remediation.
- The applied-plan record becomes a **consumption ledger** written on
every apply path. It is currently written only under `--yes` in a
non-interactive session, so any bound anchored on it is a no-op on the
path most runs take.

**Eight phase issues**, each carrying its own ADR-0004 incumbent
evidence inlined as `path:line` — deliberately not a pointer into the
gitignored `.work/` tree, which no delegated worker, fresh session, or
second machine can read:

| Issue | Phase |
|---|---|
| #2678 | `feat(review)`: merge findings across producers (implements
ADR 0010) |
| #2679 | `docs(conventions)`: detector-findings owner doc (stub) |
| #2680 | `feat(mutation-testing)`: persist survivors as a conforming
findings file |
| #2681 | `docs(conventions)`: harden detector-findings with the rule-id
to severity crosswalk |
| #2682 | `feat(autonomy)`: catalog rows for every routine class
considered |
| #2683 | `feat(autonomy)`: reviewer-burden promotion term, recorded as
deferred |
| #2684 | `feat(testing)`: can't-fail test audit plus fail-closed
`--check` mode |
| #2685 | `spike`: per-repo routine capability detection, promoted to
its own topic |

**The contract slice is pruned** in this PR's final commit, per
`docs/conventions/topic-docs/README.md:43`. Recover the full PLAN.md and
the design resolution from the commit before the prune:

```bash
git show 5341117:docs/topics/boris-routines-adoption/PLAN.md
git show 5341117:docs/topics/boris-routines-adoption/design/design-resolution.md
```

## Verification

- `bash scripts/check-contract-slice-prune.sh --check-diff origin/main`
— exits 1 before the prune commit (it named both slice paths), exits 0
after. That transition is the point of the final commit.
- `npx markdownlint-cli2` — 0 issues across ADR 0010, PLAN.md, and
design-resolution.md.
- Per-phase sanity-check invariant, measured rather than asserted: `awk
'/^### Phase [0-9]/{p=$0;c[p]=0} /Sanity Check/{if(p!="")c[p]++} END{for
(k in c) if (c[k]==0) print k}'` printed nothing — all ten numbered
phases carried at least one mechanically verifiable check.
- Two independent fresh-context review passes ran against the plan with
the authoring rationale withheld: an adversarial pass (2 CRITICAL, 8
HIGH) and a mechanics pass (1 CRITICAL, 7 IMPORTANT). Every finding
acted on was re-verified against the file before the plan was changed.
Details in the collapsed section below.

<details>
<summary><b>What the review passes caught</b></summary>

Both CRITICALs from the adversarial pass landed on the coexistence
design and both held:

- **The staleness bound could not exist on the path the plan runs.**
`fix-pass-mode.md:76` — "Interactive and headless-stop paths write no
record". The solo shape is the interactive path, so the merge set would
have grown without limit, re-injecting findings that `:95`'s required
post-fix re-review had already resolved. The draft would have regressed
a documented loop while claiming to close a correctness gate.
- **The dedup key was not mechanically available.**
`findings-normalization.md:77` places dedup at "Stage 3 Sonnet (semantic
merge)"; `:66` orders "Minimize FALSE-MERGE over FALSE-SPLIT — a false
merge silently drops a real issue". The fix action runs no LLM stage.

The mechanics pass then executed rather than argued its CRITICAL:
`check-contract-slice-prune.sh --check-diff origin/main` exits 1 on this
branch, which is what produced the prune commit and the branch-shape
decision. It also repaired five sanity checks that could not pass as
written — a bare `check-changelog-parity.sh` exits 2 on usage; a `grep
-c … returns 0` check inverts its own exit code, so the success case
failed and a wrongly staged file passed; a forbidden-metric grep passed
vacuously on zero matches; two checks named a state with no command.

Other corrections worth recording: `docs/PLUGIN-PHILOSOPHY.md:471` is a
**deadline** ("before a second plugin adopts it"), not a licence to
author an owner doc late — and the pilot phase is itself the second
adopter, hence the stub-then-harden split. `routines.md:192,195` already
carry `dead-code-sweep` and `coverage-mutation-watch`, so the catalog
phase gained an existing-row sweep as its first work item. The new skill
takes the `audit` leaf and joins the registered owner set rather than
picking `scan` to sidestep the argument the registry asks for. And the
routine-delivery gap is bound to `liveness-assertion`'s two-limb Core
contract instead of being deferred by scope, which was not one of the
permitted answers.

</details>

<details>
<summary><b>The locked Brief (the contract this plan was built
to)</b></summary>

## Brief

### TLDR

Generalize the maintenance-routine pattern reported by @bcherny
(2026-08-13) into tool-, org-, and
product-agnostic capability for this marketplace: **detectors** that
emit conforming findings, plus
**catalog rows** governing them, plus the **substrate** both need. Not a
port of his eleven routines,
and not a new plugin.

The research inverted the original framing three times, and the Brief
encodes the inverted shape:

1. **The apply machinery already exists and is reachable by file format
alone** (validated, below).
   What is missing, class after class, is a **detector** to feed it.
2. **Merge rate cannot justify any of this.** Three independent lines —
peer-reviewed observational,
large-N regression, randomized trial — find artifact quality
weakly-to-not coupled to acceptance.
The verification contract is justified on **defect escape** and
**reviewer burden**, never on
   acceptance.
3. **Class-level beats instance-level.** Three lanes converged from
different literatures: durable
wins come from policy and mechanism, not from better per-instance agent
judgement.

### Goal

Ship, in dependency order:

- **Tier 0 substrate** — the four items below, which every candidate
class depends on.
- **Tier 1 detectors** — three classes with the strongest evidence and a
real local surface.
- **Catalog rows** for every class considered, including the ones
deliberately not built, so the
  reasoning is recorded rather than re-litigated.

### Constraints

**Binding repository rules** (verified, `path:line` in the research
record):

- **ADR 0005** — a new class extends the existing catalog: a
`reference/` edit plus a `CHANGELOG.md`
entry plus a version bump. **Not a new catalog, not a new skill, not a
new plugin.** This closed
  the original "where does it land" question; it is not reopened here.
- **ADR 0004 incumbent-first gate is binding** — no remediation ships
until it proves no existing
skill covers it, with `path:line` evidence. Satisfied for all eight
classes by
`research/V1-coverage-negatives.md`; each issue carries its own
evidence.
- **ADR 0008** — a row is admitted only when its observable is anchored
to text that is present. An
obligation a surface *should* satisfy, anchored to nothing, does not
become a row however well
  sourced.
- Version bump **and** matching CHANGELOG entry in the same PR
(CI-enforced, zero exemptions);
`metadata.workflow-stage` required; regenerate `docs/CATALOG.md` and
`docs/SKILL-CHEAT-SHEET.md`;
SKILL.md under 500 lines; **evals required for any new skill**; only
`docs/topics/` is
docs-only-allowlisted, so anything under `plugins/**` runs the full CI
suite.

**Product constraints** (verified at primary,
`code.claude.com/docs/en/routines.md`, 2026-08-14):

- Routines are available on **Pro, Max, Team, and Enterprise** — the
mechanism is reachable on this
account. Claude Tag (the Slack surface the source used) is
Team/Enterprise-only and is out of
  reach; only that delivery surface is unavailable, not the capability.
- **Minimum schedule interval is one hour.** Runs count against a
per-account daily allowance;
  **one-off runs do not**, which is the pilot lever.
- **No permission containment during a run** — "no permission-mode
picker and no approval prompts".
Containment is repo selection, environment, connector list, and the
`claude/`-branch push rule.
- **Repo `.claude/` loads; user-scope `~/.claude` does not.**
`pluginConfigs` is ignored at project
scope by design, so any plugin taking `userConfig` has no cloud-run way
to receive values.
- **Green status ≠ success** — "It does not mean the task in your prompt
succeeded." Efficacy reads
  logs, never statuses.
- **Workflows do not travel into scheduled runs**; custom slash commands
do.

**Evidentiary constraint:** the source is a single self-report with zero
independent corroboration
and no published methodology. Nothing in this plan may cite 388/180 as
evidence of efficacy.

### Acceptance criteria

Per-unit close-out loop — one class at a time: incumbent evidence
recorded → row derived through the
catalog's own mapping rules → detector or deferral shipped → CI green →
CHANGELOG + version bump in
the same PR. A class is **closed** when its row exists with a derived
guardrail class and either a
shipped detector or a `join:` trigger naming what would unblock it.

1. **Findings-file coexistence is settled before a second producer
ships.** The fix action consumes
exactly one file and merges nothing; two producers in one branch
directory means the later
timestamp silently wins. Green run, hidden findings. This is a
correctness gate, not a nicety.
2. **Every detector emits machine-computed severity**, not prose routed
through an LLM crosswalk. No
crosswalk row exists for a deterministic surface today; that is contract
work, not a detail.
3. **Every class-level gate satisfies items 1-2 of the trust-path
definition** (below). Items 3-5 are
   org-scale and explicitly deferred at solo volume.
4. **No acceptance-rate metric anywhere** — not as a promotion input,
not as an efficacy signal.
5. Each shipped detector carries evals, per the CI gate.

### Captured assumptions

- The format-only path stays supported. **Validated 2026-08-14, not
assumed**: a hand-written
conforming file from a non-fanout producer passed the fix action's
locator, frontmatter gate,
exact-branch check, and table parse, including the cell-escaping rule.
Probe deleted afterward —
while it existed it *was* the newest file in that directory and would
have shadowed a real review.
- Detectors are scripts unless a named agent is earned. The repo's own
philosophy prefers one script
"wherever the judgment is mechanical", and fanout can dispatch **agents
only** — which is why
`mutation-testing:audit`, the best deterministic detector in the fleet,
reaches no relay today.
- Catalog rows derive their guardrail class through the existing mapping
rules, never by hand.

### The class-level trust path (the operative definition)

An **instance-level** path asks a judge to evaluate each change on its
merits. A **class-level** path
decides once, for a category, what condition makes any member acceptable
— so the per-instance
question collapses from a judgement to a check. The mechanism:
per-instance persuasion is subject to
habituation; a standing class rule is not.

| # | Requirement | Portable? |
|---|---|---|
| 1 | Class definition narrow enough that membership is decidable
without judgement | **yes** |
| 2 | Machine-checkable gate that fails closed | **yes** |
| 3 | A denominator — enough instances to compute a rate | org-scale |
| 4 | An outcome signal that is **not** the merge decision | org-scale |
| 5 | A lookback window and a demotion rule | org-scale |

"Dead-code removal where the code is provably unreachable" is a class.
"Code quality improvements"
is not. If deciding membership needs the judgement you were eliminating,
it is an instance-level path
wearing a class-level label.

Solo shape: **the gate without the statistics** — narrow class,
machine-checkable gate, run it
*before* the PR opens, human on the merge. The earned auto-merge tier is
deferred with a trigger.

### Scope — tiers

**Tier 0 — substrate. Blocks everything.**

| Item | Why |
|---|---|
| Findings-file coexistence | Silent-shadowing correctness bug the
moment a second producer exists |
| Detector contract | Machine-computed severity, rule/threshold
vocabulary, suppression; owner doc must precede the **second** adopter |
| Per-repo capability detection | The agnostic core: which classes bind,
resolved from repo state (build files, language, test framework, flag
system, architecture config, MCP servers, CLI tools) |
| Repo-scope plugin declaration | User-scope does not load in cloud;
**gated on the cloud probe** (below) |

**Tier 1 — build.** Formal-logic modeling (decision tables +
property-based testing; strongest
evidence, and its mechanical artifacts *are* the verification payload) ·
useless-test **repair**
queue (genuinely uncovered; the fleet names the capability it lacks) ·
layering enforcement, **inform-human posture** (most mechanical once
rules exist; propose-and-baseline, never impose-and-fail).

**Tier 2 — rows now, build later.** Dead code, both postures, with a
**30-90 day** window floor and
staged quarantine — never the source's one-day window · clone
**detection** + trend gating (the unify
*decision* has no automation precedent in twenty years) · stale-flag
removal (strong prior art;
consumer-facing, no local surface).

**Tier 3 — rows recording why not.** Logic simplification above
expression level (no published
effectiveness evidence; excluded by name in `tidyings.md`) · abstraction
flattening (no validated
detector exists, and the fault data runs backwards — Speculative
Generality and Middle Man sometimes
*reduce* faults) · ant-only shipper (the decision is a human product
call) · GUI crash fuzzing (no
local surface; 36.6% crash-replay reproducibility).

### Out of scope

- A new plugin, a new catalog, or a parallel governance surface (ADR
0005).
- A self-tuning routine class. Across 22 verified papers, none tunes
from deployed production
outcomes with a human gate; the famous citations are within-episode and
do not persist. The
existing promotion apparatus is the better-grounded shape and already
avoids the merge-rate
  confound by keying on completions, gate passes, and reverts.
- Auto-merge without human review at solo volume — requirements 3-5
above are unmeetable here.
- Porting the source's prompts. They are a **meta-prompt** (instructions
to *create* routines), one
  layer above any stored prompt.

### Deferred questions

- **Q12 (arbiter: USER-RESERVED)** — repo-scope plugin declaration in
cloud. **Filed as

[#2660](#2660
(`needs-human`).
Two official pages contradict each other on whether repo-declared
marketplace plugins install;
workspace trust for a cloud clone is undocumented, and if untrusted the
declaration is ignored
**silently**; private-marketplace auth in cloud is undocumented. One
probe settles all three, and
it cannot run unattended — browser selection, account mutation, and
metered usage all require the
human. Tier 0's fourth item is blocked on it; the documented alternative
(components committed
directly to `.claude/`) is the fallback and needs no marketplace fetch,
trust step, or credentials.
- **Q4 follow-on (arbiter: `/planning:plan`)** — add a reviewer-burden
term to the existing promotion
predicate, and keep any future tuner's signal set disjoint from
promotion evidence. Composition
hazard if not: a tuner could raise the metric that promotes the cell
that reduces scrutiny of the
  tuner's own output.
- **Q2 (resolved, recorded)** — `join: proven recurring manual pattern`
stays our-own-proven. The
source's run is named-product evidence and belongs in the
routine-catalog research record, not the
non-normative precedent-pointers section, whose own scope line routes it
elsewhere.
- **Live daily run-cap numbers (arbiter: USER-RESERVED)** — the docs
direct readers to
`claude.ai/code/routines`; published figures trace to a stale April blog
post. Needs an
  authenticated session.

</details>

## The plan's shape

Ten phases, sequential. Blast radius HIGH. Full bodies, work items, and
sanity checks live in the eight issues above; the spine is:

```text
P1 coexistence ──> P2 convention stub ──> P3 Pattern-C pilot ──> P4 harden ──> P7 detector
                        (must merge to main)                                      ^
P5 catalog rows ──> P6 predicate term ────────────────────────────────────────────┘

P8 capability detection ── promoted to its own topic
P9 repo-scope declaration ── blocked on #2660
P10 graduate + prune ── this PR
```

Three ordering constraints, none obvious:

- **P1 before any detector** — fanout is producer #1, so the first
detector of any kind makes producer #2.
- **P2 before P3** — a new cross-plugin convention lands in an owner doc
*before a second plugin adopts it*, and P3 is that second adopter.
- **P2 merged to `main` before P3** — a plugin cannot cite a
repo-relative `docs/conventions/` path, because it installs standalone.
The established form is a raw URL to `main`, which only resolves once
the convention is merged.

## Approved reductions against the Brief

Both were surfaced as scope cuts rather than absorbed, and accepted:

- **Tier 1: three detectors to one.** Ships can't-fail tests (#2684);
formal-logic modeling and layering enforcement become catalog rows with
named triggers.
- **Detection, not repair.** The Brief names a repair *queue*; a
judgment-shaped finding is surfaced rather than auto-applied, so the
queue-and-apply half needs its own decision.
- **One deviation:** the Brief's per-unit close-out loop is batched
stage-at-a-time, because the substrate phases are shared by every class
and a per-class loop would re-pay them N times.

## Follow-up outside this PR

`AGENTS.md` is 28 lines at HEAD and no longer carries the exec-bit or
Windows-filemode guidance — commit e22190e's managed sync deleted the
34 lines 7c2a9b3 had added four commits earlier. It is a managed
materialization, so a local patch is removed by the next sync; the fix
belongs upstream in `melodic-software/standards`. The exec-bit CI gate
still runs and is ungated by the docs-only allowlist, so the constraint
is live while its documentation is not.

## Related

- Refs #2678, #2679, #2680, #2681, #2682, #2683, #2684, #2685 — the
eight phase issues this PR files
- Refs #2660 — repo-scope plugin declaration in a cloud run
(`needs-human` spike); Tier 0's fourth item is blocked on it, and the
documented fallback proceeds regardless
- Refs #2649, #2650 — mutator-gating defects found during the research
sweep
- ADR 0010 —
`docs/adr/0010-merge-findings-across-producers-and-mark-consumption-explicitly.md`

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Aug 15, 2026
… reviewer-burden term (#2694)

Closes #2682
Closes #2683

Phases 5 and 6 of the boris-routines-adoption plan, in **one PR by
design** — one autonomy version
bump, one CHANGELOG entry. Splitting them either duplicates the bump or
strands one without its
changelog line, and `check-changelog-parity.sh` fails on both.
Independent of the detector chain
(#2690 / #2692); nothing here blocks on those merging.

## Why rows for classes we are not building

A catalog that lists only what shipped cannot be reasoned from. A reader
asking *"why is there no
clone unifier?"* finds silence, and silence reads as an oversight rather
than a decision. **Nine
rows added, one existing row amended**, and every derivation run
**through the mapping rules**
(`routines.md` "Mapping rules (catalog to matrix)"), never by hand —
that is this phase's whole
discipline.

## Existing-row sweep (first work item)

Run against `routines.md` itself, not the research record. Per candidate
class, "no row" or the
existing row's identity:

| Candidate | Sweep result |
|---|---|
| dead code | **Row exists** — `dead-code-sweep`, `DET detect \| DC
(review-gated PR) \| repo \| n/a — no agent session \| not-a-routine`. →
**amended**, not duplicated. |
| clone work | **No row.** The nearest row, `coverage-mutation-watch`,
is a **different observable** — coverage and mutation score, not clone
density — so it is no match and was not amended. → new row. |
| the other eight | **No row.** → new rows. |

`clone-trend-gate` ships a **byte-identical cell signature** to
`coverage-mutation-watch`
(`DET | R (digest/gate) | repo | n/a — no agent session |
not-a-routine`). The rows are genuinely
distinct — clone density and its trend versus coverage and mutation
score — and because nothing in
the six cells says so, a class parameter now states it. Two rows that
read as a copy-paste duplicate
need the difference written down somewhere.

**The issue's line citations had drifted.** It cites `dead-code-sweep`
at `:192` and
`coverage-mutation-watch` at `:195`; they are at `:191` and `:193` on
`main`. The row *identities*
and their full cell text match exactly, so the sweep result stands — but
the offsets are not uniform
(1 and 2), so the numbers were re-resolved rather than adjusted.

## ADR-0004 incumbent gate — the search record

#2682: *"ADR-0004's incumbent gate applies to rows here, not only to
detectors."* ADR-0004 D-1
requires the search carry `path:line` evidence. It is recorded here
rather than in `routines.md`
because that contract is deployment-agnostic — an adopting org does not
ship this marketplace, and a
binding parameter grounded in what *this* repository happens to contain
is the same defect as
grounding one in this fleet's hardware. What the search *changed* in the
contract is in the contract;
the evidence trail is here.

| # | Class | Verdict | Evidence |
|---|---|---|---|
| 1 | `formal-logic-modeling` | **No incumbent** | Searched `TLA+`,
`Alloy`, model-checking, invariant-verification, design-by-contract
vocabulary across `plugins/`. No hits that were not false positives. |
| 2 | `cant-fail-test-repair` | **Partial** |
`plugins/mutation-testing/skills/audit/SKILL.md:126` — surviving-mutant
disposition surfaces tests that cannot fail a given mutant. Remediation
(`:201-209`) authors **new** killing tests via `/testing:write`; it does
not repair the existing tautological assertion, which is this class's
whole content. |
| 3 | `layering-enforcement` | **Incumbent** |
`plugins/review/agents/architecture-guardian.md:3` — "Reviews code for
dependency-direction violations, layer boundary breaches…"; `:33` checks
"inner layers must not reference outer layers; follow the project's
stated layer rules." Close match, same inform-human posture. **Already
reflected in the row**: its join trigger requires "a recurring manual
pattern the incumbent reviewer does not already cover", and its
parameter requires clearing the incumbent gate against the existing
architecture-review surface. |
| 4 | `clone-trend-gate` | **No incumbent** | Searched clone-detection
tool names, `clone densit`, `copy-paste detector`, `code clone`.
`plugins/review/agents/code-reviewer.md:46` flags "Duplicated Code" ad
hoc during diff review — not a density trend or a gate. |
| 5 | `stale-flag-removal` | **Partial (weak)** |
`plugins/code-tidying/skills/tidy/templates/host-wiring-lane.template.md:16`
lists "stale feature-flag branches" as one example under the Dead Code
tidying. A bare example phrase inside a glob-scoped lane; no flag-age
tracking, no staleness detector, no single-variation-everywhere trigger.
|
| 6 | `logic-simplification-sweep` | **No incumbent, at either
altitude** | Above expression level: `tidyings.md` has no cross-function
control-flow restructuring; Beck's Guard Clauses
(`plugins/code-tidying/skills/tidy/reference/tidyings.md:15`)
restructures within one method only. At expression level: searched
`boolean expression`, De Morgan, `redundant condition`,
`simplif.*expression` across `plugins/code-tidying/` — **zero matches**.
`plugins/code-tidying/skills/batch-simplify/SKILL.md:140` delegates to
an external agent not present in this repo, with instructions naming no
altitude. |
| 7 | `abstraction-flattening` | **Partial — the closest call in the
set** |
`plugins/architecture/skills/improve/research/deepening/scan-briefing.md:49-51`
(two-adapter rule → "speculative indirection") and
`research/deepening/vocabulary.md:28` (the deletion test: "If complexity
vanishes, it was a pass-through") detect the same smells this class
targets. But the lens's remedy is *deepening*, it applies no fix itself,
and it routes through a human interview and planning handoff
(`SKILL.md:63`) — there is no autonomous change path. |
| 8 | `ant-only-shipper` | **No incumbent** | Searched
champion/challenger, canary, shadow deploy, A/B, promote-to-production,
competing-implementation vocabulary.
`plugins/prototype/skills/explore-directions/SKILL.md` is adjacent —
throwaway UI variations picked by a human in-browser — not an
evidence-based promotion recommender. |
| 9 | `gui-crash-fuzzing` | **No incumbent** | Searched `fuzz`,
monkey-test, random-click, GUI-crash, UI-stress vocabulary. All hits
false positives. |
| 10 | `dead-code-sweep` (amended) | **Partial** |
`plugins/code-tidying/skills/tidy/reference/tidyings.md:21-25` — Beck #2
Dead Code covers detection and verified deletion inside a scoped lane.
It has **no quarantine-then-judge staging**, which is the entire
normative content of the amendment. |

### What the search changed

- **`abstraction-flattening`'s "no validated detector" was
under-qualified.** Heuristic detectors for
exactly these smells ship — including in this marketplace. The parameter
now says what is actually
true and what the join trigger actually names: *a scanner is not the
join trigger; a published
validated detector is*, and none surveyed is validated against a
fault-outcome ground truth.
- **`logic-simplification-sweep`'s "already covered by structure-only
tidying surfaces" was false**,
and the search is what established that — there is no incumbent at
either altitude. The claim is
  removed rather than restated.
- **No verdict removed a row.** Two partials (`cant-fail-test-repair`,
`dead-code-sweep`) are
"detection exists, the remediation shape does not", which is a
capability gap rather than a
duplicate. `layering-enforcement`'s real incumbent was already gated in
the row before this search.

## Rows added

**Tier 1 — join triggers**

| Class | Judgment | Output | Access | Derived | Status |
|---|---|---|---|---|---|
| `formal-logic-modeling` | AGT | R | repo | `C1` | join: a stated
invariant or specification artifact exists to model against |
| `cant-fail-test-repair` | hybrid: DET detect; AGT repair judgment is
the routine | DC (PR) | repo | `C3` | join: proven recurring manual
pattern |
| `layering-enforcement` | AGT/HUM | R | repo | `C1`; disposition
human-gated | join: layering rules stated as text, and a recurring
manual pattern the incumbent reviewer does not already cover |

**Tier 2**

| Class | Note |
|---|---|
| `dead-code-sweep` | **Amended.** Was `DET detect` only; the
quarantine-exit judgment makes it hybrid, and that portion derives `C3`
— liveness is *not* mechanically checkable, since reflection, dynamic
dispatch, and out-of-tree callers each defeat the build that would
otherwise prove it. Window floor **30–90 days with staged quarantine,
never one day**, and not tunable downward by an org binding. |
| `clone-trend-gate` | `DET \| R (digest/gate) \| repo \| n/a \|
not-a-routine`. Detection and trend gating **only**. |
| `stale-flag-removal` | hybrid; removal portion derives **`C4`** — a
flag definition is a configuration surface, and the
structural-blast-radius rule composes above `C2`/`C3`. Disposition
human-gated. |

**Tier 3 — recording why not**

| Class | Why not |
|---|---|
| `logic-simplification-sweep` | `C3`; `join (external)`: published
effectiveness evidence exists. |
| `abstraction-flattening` | `C4` (structural surface); `join
(external)`: a validated detector is published. The fault data also runs
*backwards* — Speculative Generality and Middle Man are in some studies
associated with **fewer** faults. |
| `ant-only-shipper` | `AGT/HUM`, `C1`, human-gated. The promotion
decision is a product call. |
| `gui-crash-fuzzing` | `not-a-routine` (DET). Reported crash-replay
reproducibility is low enough that filing every crash would degrade the
governed queue rather than feed it, so its `WI` output is replay-gated.
The row also carries the isolation consequence the catalog had skipped:
unattended GUI actuation requires `L3`. |

## Exclusions are exclusions, not deferrals

Recorded as such, because a deferral invites a future PR to "finish" the
class:

- **`clone-trend-gate`** — the unify *decision* is excluded, not a
deferred posture. No surveyed
clone-detection tool automates deciding which clones to unify, across a
detection literature the
survey found spanning two decades. On that record there is nothing to
defer *to*, so adding a
  unify posture re-opens the class rather than extending it.
- **`gui-crash-fuzzing`** — judging a filed crash beyond replay is
excluded the same way. A filed
crash is ordinary queue intake, owned by the issue-lifecycle classes.
Without this the row's
`DET → not-a-routine` exit would be skipping a judgment portion, which
is precisely the misreading
  `routines.md` §"What a routine is" is worded to prevent.
- **`stale-flag-removal` / `ant-only-shipper`** — the disposition never
automates. Which branch
survives, and whether to promote, are product calls. That is why both
rows are `AGT/HUM`.
- **`layering-enforcement`** — inform-human posture only; a
direct-change posture derives `C4` and
  no surveyed precedent supports one.

## The contract is now three tiers, explicitly

The new `Class parameters` section carries normative detail six table
cells cannot hold — stated as
**binding**, so a leaf contradicting one is non-conforming. That created
a contradiction with three
statements in the same file saying definition depth exists only for the
`v1` classes, while
`clone-trend-gate` and `gui-crash-fuzzing` — neither of which will ever
gain a leaf — carry
parameters.

**Resolved by widening, not collapsing.** The hub now declares three
tiers: catalog plus mapping
rules; class parameters, binding any class leaf or not; leaf-level depth
for the ten `v1` classes.
Collapsing the parameters back into row cells was the alternative and
was rejected — the section
exists precisely because the cells cannot carry the detail, and several
parameters bind `v1` and
hybrid rows generally rather than one deferred class.

## Four general derivation rules now live in the mapping rules

`## Mapping rules` exists, in its own words, *"so an adopting org can
classify a **novel** routine
class end-to-end… without a contract change."* Three general rules were
filed under
`### Class parameters` instead — two of them titled with a class token
while generalizing in their
last sentence (*"The same reading applies to every `AGT/HUM` row"*; the
structural axis *"keys on
blast radius"*). An org reading the mapping rules would not have found
them.

All three moved: the hybrid portion-split rule onto the hybrid bullet
under *Judgment and output*;
the `AGT/HUM` clarification onto its existing bullet; the
target-not-file rule onto *Structural blast
radius*. A **fourth** was stranded the same way inside a
`dead-code-sweep` note and is now stated
generally: a risk-raising axis evaluates **per item** as well as
class-wide, so a class whose axis
fires on only some items derives the lower class and records the
escalation rather than deriving the
higher one wholesale.

**One honest limitation now stated in the rules themselves.** The
structural axis keys on the
change's *target*, and **no catalog column records a target** — which is
why
`logic-simplification-sweep` and `abstraction-flattening` carry
byte-identical axis cells
(`AGT | DC (PR) | repo`) and derive `C3` and `C4`. Rather than leave a
reader to conclude the three
axis columns are sufficient when they are not, the rule now says the
target comes from the class's
own definition and that a row turning on it says so in its `Derived row`
cell.

## A second `join` semantic, separated

Every pre-existing `join:` trigger is a condition the adopting **org**
can satisfy: connect a
telemetry surface, write the layering rules down, accumulate a manual
pattern.
`published effectiveness evidence exists` and `a validated detector is
published` are world state no
adopter can act on. One token carrying both semantics made those two
rows read as backlog items.

A `join (external): …` legend row now separates them. Rewording the two
triggers into
adopter-actionable form was the alternative and would have been
dishonest — the point is that the
org *cannot* fire them. An `excluded:` status was also rejected: these
classes are genuinely
deferred pending evidence, unlike the unify decision, which is excluded
outright. Every other
`join:` row in the table was re-checked against the new definition; none
belongs under the new one.

## #2683 — the predicate side

- **What may never enter a predicate.** An acceptance or merge rate is
never a promotion input and
is not an efficacy signal, in either role, at any cell, at any
threshold.
- **Two shipped terms sit close to that line, and both are now
distinguished.**
`0 human-reverted merges` is a *correctness* signal — a human asserting
the change was wrong after
it landed — not an acceptance rate. And `≥ 20 autonomous C2 merges over
≥ 14 days` is a **volume
floor**, not a rate: a ratio rises when its denominator shrinks, so
attempting less — or attempting
only what is certain to land — raises it with no change in the work. A
count has no denominator to
  shrink. Selectivity leaves it flat.
- **The term inventory is now complete.** It previously enumerated four
term types and the table has
**seven** — merge counts, advisory-review counts, and
missed-blocking-finding counts were all
missing. All three are correctness- or volume-side, so nothing in the
argument moved.
- **Reviewer-burden term: deferred with an explicit trigger, not
omitted.** It needs a denominator,
and a denominator needs three org-scale things this contract does not
have — a population to
divide by, a non-merge outcome signal, and a lookback window with a
demotion rule. Without them the
term moves with *volume* rather than trustworthiness, which rewards a
cell for producing less.
Trigger: the volume **and** a non-merge outcome signal; volume alone is
not the trigger.
- **Standing constraint on any future tuner** — its signal set stays
**disjoint** from promotion
evidence. Overlap is a self-dealing loop: a tuner optimizing a signal
that also promotes a cell can
raise that signal to reduce the scrutiny applied to the tuner's own
output. Binds the tuner's
inputs, not its intent, and binds whether or not the reviewer-burden
term is ever activated.

## Two claims in #2682 that did not verify — and one of the replacements
did not either

**#2682 says logic simplification above expression level is "excluded by
name in `tidyings.md`".**
It is not: `plugins/code-tidying/skills/tidy/reference/tidyings.md`
contains **zero** occurrences of
`simplif`, case-insensitive.

**The first replacement for that claim was also false.** An earlier
revision of this description said
expression-level simplification is "already covered by structure-only
tidying surfaces" and that
simplification above that level "changes behavior in the general case".
Both fail:

- The incumbent search found **no incumbent at either altitude** — no
cross-function control-flow
restructuring in `tidyings.md`, and zero expression-simplification
matches anywhere in
  `plugins/code-tidying/`.
- "Changes behavior in the general case" is contradicted by
`plugins/code-tidying/skills/batch-simplify/SKILL.md:174` —
*"Simplification is
behavior-preserving"* — which treats behavior alteration as a
**regression** its verification
exists to catch. It also contradicted the row's own cell, which claims
only that equivalence above
  expression level is not mechanically checkable: weaker, and correct.

A checkable-and-false claim had been replaced by an uncheckable one. The
parameter now uses the row
cell's own wording and drops the coverage comparison entirely; the
`path:line` evidence lives in the
incumbent table above, where it cannot rot a deployment-agnostic
contract.

## Deployment-specific fact removed from normative text

A binding parameter read: *"The fleet ships no GUI to fuzz, so the class
has no observable here at
all"* — inside a section declaring *"A parameter here binds the class;
it is not commentary"*, in a
contract whose own closing line is *"The contract assumes no machine,
org size, or budget"* and whose
hosting stance makes substrate a deployment-owned binding. An adopting
org that ships GUIs would read
a binding parameter grounded in **this** fleet's inventory.

Struck. The deployment-independent half stays, and the class's
`not-a-routine` derivation never
depended on the inventory in the first place — it follows from Judgment
`DET`, which holds for any
deployment.

**On #2682's present-observable admission check** (*"Drop any candidate
anchored to nothing"*): the
observable here is crashes surfaced by actuating a GUI — a real,
nameable artifact class, not
nothing. A deployment without a GUI simply never schedules the class,
which is true of every
access-gated row in the catalog and is not an admission question. The
row is admitted; what was
wrong was grounding its *parameter* in one deployment's inventory, not
the row's presence.

## Empirical claims, hedged to the register the evidence supports

The supporting research record is gitignored, so no in-tree reader can
check any empirical claim in
this contract. Several were stated at a confidence the reader has no way
to audit:

| Was | Is |
|---|---|
| "Published practice at scale runs an order of magnitude longer than a
day" — ~10 days, which does not reach the 30-day floor it was offered to
support | The floor derives from what the window must **out-last**: 30
days is the shortest window spanning a monthly invocation cadence at
all, 90 spans a quarterly one, and a one-day window spans nothing |
| "twenty years of clone-detection tooling produced no production
automation" — a universal negative stated as fact | "no **surveyed**
clone-detection tool automates the choice…, across a detection
literature the survey found spanning two decades" |
| "The flag-lifecycle tools that lead this space" | "The flag-lifecycle
tooling **surveyed**" |
| "No published effectiveness evidence supports automating it" —
universal negative | "No effectiveness evidence… **surfaced in the
surveyed literature**" |
| "a direct-change posture … has no evidence behind it" | "**no surveyed
precedent** supports one" |
| "reproducibility around 36.6%" — two significant figures, no citation
| "low enough that filing every crash would degrade the queue" — and the
population shift is fixed too: the figure measured replay of *crashes*,
and was being applied to *filed work items* |
| "weakest precedent of the catalog" — a superlative over all forty-nine
rows | "among the weakest precedent the survey found" |
| "Three independent lines of evidence — peer-reviewed observational
work, large-N regression, and a randomized trial", citing exactly one |
The rule now rests on the one finding **verified at primary source**
(Lenarduzzi et al., quoted verbatim); the other two design families are
named as survey context, explicitly not checked |

The target register is the one already-well-calibrated claim in the
section — *"in some studies
associated with fewer faults"* — which is left as it stands.

## Fresh-context verification, and the two contradictions it caught

The edits above were checked by a **separate fresh-context agent** with
the authoring session's
reasoning withheld, briefed to judge whether each finding actually no
longer holds, whether any fix
introduced a new in-tree contradiction, whether the remaining empirical
claims are calibrated, and
whether every row still derives correctly. It re-derived six rows from
the mapping rules and axis
cells alone before reading the `Derived row` column: **six of six
matched.**

It found two real contradictions, both now closed:

- **`gui-crash-fuzzing`'s Output cell (`R + WI`) contradicted its own
binding parameter**, which
said filing would degrade the governed queue. The previous revision
masked this — *"the fleet
ships no GUI to fuzz"* made the whole row moot, so the Output cell never
had to agree with the
parameter. Removing that escape exposed it. The `WI` output is now
admission-constrained: an item
is filed only where re-running the recorded input sequence reproduces
the crash, and the rest stay
in the `R` half. That gate is a re-run rather than a judgment, so it
adds no `AGT` portion and the
  `DET` exit stays complete.
- **`work-classes.md` deferred the reviewer-burden term on "the
org-scale trust-path requirements
this contract already defers"** — a phrase with **zero** other
occurrences anywhere in the
repository. A back-reference leaked from the gitignored research record
into normative text,
asserting a prior decision no in-tree reader can locate. The three
requirements were already
enumerated inline, so the phantom reference is dropped rather than
manufactured.

It also caught the stranded per-item rule, the missing-target-column
limitation, the four
over-claimed hedges above, and one SSOT gap outside the three files in
play:
**`guardrails/isolation-ladder.md` scoped `L3` to untrusted-provenance
(`C5`) work alone**, while
the catalog's access rule has always also required it for unattended GUI
actuation — a demand that
reaches classes deriving no work class, so it cannot travel through the
matrix's min-isolation
column. That leaf is the contract's source of truth for when a level
applies, and was incomplete
against its own charter. Fixed at the root rather than papered over in
`routines.md`.

## Other corrections in this pass

- **The posture-qualified-identity mandate was unsatisfiable for seven
of the nine hybrid rows.**
The new parameter made it mandatory for every hybrid row, while *Routine
identity* says posture
tokens are owned by the class's definition leaf — and seven hybrid rows
are `join:`-deferred with
no leaf. Scoped: tokens are minted with the leaf, so the obligation
binds at leaf time; until then
a deferred class records its split in its Judgment cell and binds
nothing.
- **The `L3` on `gui-crash-fuzzing` does not come from the matrix.** The
guardrail matrix's
min-isolation column is indexed by work class (`C1`–`C5`); a row
deriving no class cannot reach
it. The floor comes from the GUI-actuation mapping rule directly, and
the row and its parameter
now say so rather than implying a matrix lookup that would not resolve.
- **`## Precedent pointers`' scope line claimed coverage it did not
have.** It declared itself
pointers "for the deferred and deterministic rows"; all nine new rows
are deferred or
deterministic and none got one. Narrowed to the rows where a shipped
pattern was surveyed, with
an explicit note that absence is not a claim that no pattern exists —
rather than inventing nine
  pointers this pass has no evidence for.
- **`dead-code-sweep`'s precedent pointer was stale against the amended
row.** It described deletion
pipelines with no quarantine stage while the row's whole normative
content is staged quarantine —
so it read as precedent for the unstaged form. It now says the staged
quarantine is the row's own
  normative content, not a property read off those pipelines.
- **`### Reviewer-burden term` sits under a preamble that did not cover
it.** The preamble said
"the threshold values below are suggested defaults the org binds"; a
deliberately-not-live term
with no threshold is not a suggested default. Promoting it to a sibling
`##` was the alternative
and was **rejected** — #2683 names §"Suggested default predicates" as
its placement. The preamble
was narrowed to the table instead, and now states that the two
subsections after it are not
  defaults and carry no bindable threshold.
- **CHANGELOG bullets re-filed per Keep a Changelog**, which the file's
own header cites. The
`dead-code-sweep` amendment and the derivation-rule bullet change
existing content and moved to
`### Changed`. The row count is now exact: **nine added, one amended** —
class rows go 40 → 49,
and "ten rows added" double-counted the amendment. (Commit `21fce8eb`'s
body carries the same
  off-by-one; history is not rewritten, the durable surface is fixed.)

## Sanity checks — actual output, re-run at `c0795c93`

- **No two rows share a class token** — `awk -F'|' '/^\| [a-z]/ {print
$2}' … | sort | uniq -d`
returns **empty**. Verified non-vacuous: the same pipeline yields **51**
distinct tokens, against
**41** on `origin/main`. The delta is **+10, not +9**: nine new class
rows plus the new
`join (external): …` status-legend row, which the pipeline also matches
because legend rows begin
  `| join…`. Class rows alone go 40 → 49.
- `grep -n "388\|180 merged" plugins/autonomy/reference/routines.md` →
**empty**.
- `grep -ci "never a promotion input\|no acceptance-rate\|not an
efficacy signal" …work-classes.md`
  → **1**.
- `grep -Eci "predicate .*(merge|acceptance) rate|(merge|acceptance)
rate .*(threshold|>=)"
  …work-classes.md` → **0**.
- `scripts/check-changelog-parity.sh --check-bump origin/main` → **exit
0** (autonomy
  0.16.12 → 0.17.0).
- `scripts/check-changed-skills.sh origin/main` → "No changed skills
under `plugins/*/skills/`".
- `markdownlint-cli2` on all four changed files → **0 issues**.

## Declared human gate — evidence recorded, disposition open

#2682: *"a reviewer who did not author the rows re-derives three of them
from the mapping rules and
the row's own axis cells alone. No command self-clears this."*

**A fresh-context agent performed the re-derivation. No human re-derived
these rows, and this PR
does not claim the gate is cleared.** An earlier revision of this
description said CLEARED; that was
the authoring session grading its own homework, and a fresh-context
same-vendor agent is the middle
rung of the independence hierarchy, not the reviewer #2682 names.

The full record — the withheld-answer protocol, the agent's unprompted
provenance statement, the
three derivations, and this same caveat — is posted as a durable comment
on **both** #2682 and this
PR, so it does not live only in a commit body and a PR description
written by the session that
produced the rows.

| Class | Independently derived | Authored | Match |
|---|---|---|---|
| `dead-code-sweep` | `C3` | `C3` | yes |
| `stale-flag-removal` | `C4` | `C4` | yes |
| `abstraction-flattening` | `C4` | `C4` | yes |

Three of three. **The run predates three subsequent commits**, so it was
performed against a
superseded revision — but the later verification pass re-derived all
three classes against the
current text and reached the same three answers, so the result survives
the edits rather than
merely predating them.

More useful than the match: the derivation showed the mapping rules
*imply* three things they never
*stated*, each of which the agent had to reason out to avoid a wrong
answer. All three are now
stated in `## Mapping rules` itself, alongside the fourth the
verification pass found stranded.

**What a human still owes this gate:** deciding whether an agent
re-derivation satisfies it. The
record exists so that call can be made against the actual protocol
rather than against a summary.

## Related

Independent of #2690 / #2692. Blocks the can't-fail test detector's row
amendment (#2684).

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Aug 16, 2026
…, machine-health, source-control babysit)

Second-pass application of simplification items the first pass had deferred,
for the _scripts, knowledge#1, machine-health#1/#2 and source-control#1
buckets. Each bucket was verified by a fresh-context verifier agent (pass;
knowledge#1 after one revise cycle). Adds small shared helpers:
scripts/lib/{sync-cluster.sh,report-first-difference.mjs},
plugins/knowledge/skills/map-corpus/lib/gate_common.py,
plugins/machine-health/skills/audit/tests/helpers/Invoke-CheckScript.ps1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant