Skip to content

feat: add docs-hygiene plugin - #57

Merged
kyle-sexton merged 4 commits into
mainfrom
feat/publish-docs-hygiene
Jul 11, 2026
Merged

feat: add docs-hygiene plugin#57
kyle-sexton merged 4 commits into
mainfrom
feat/publish-docs-hygiene

Conversation

@kyle-sexton

@kyle-sexton kyle-sexton commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Closes melodic-software/medley#1285.

Publishes the docs-hygiene plugin per docs/MIGRATION-PLAYBOOK.md (per-plugin gate + acceptance security review). One cohesive capability — documentation hygiene — bundling five skills.

What ships

  • /docs-hygiene:compress — flavor-trims markdown behind a mandatory fresh-context semantic-diff audit that reverts any semantic loss; optional caveman plugin backend (qualified /caveman:compress invocation, graceful in-session Edit fallback); optional snapshots persist under the plugin data directory.
  • /docs-hygiene:declutter — read-only classifier for five markdown noise shapes with internalized shape definitions, tier semantics, exemptions, and opt-out markers (no source-repo rule dependencies).
  • /docs-hygiene:extract-ssot — Rule-of-Three deduplication into a single source of truth with refuse-fast verification gates and internalized evidence discipline.
  • /docs-hygiene:encapsulation-audit — detects citations into skill-private surfaces; ships its own context/public-surface-contract.md; detector generalized to scan any consumer repo's instruction surfaces.
  • /docs-hygiene:rename-references — 12-form stale-reference pattern library (slash tokens, moved-file relative paths, frontmatter chains/globs) with audit, half-rename, and apply modes.

Adaptation notes: source-repo rule citations internalized or routed to the consuming repo's own CLAUDE.md/rules; scripts resolve paths via BASH_SOURCE and scan the repo they run in; ${CLAUDE_SKILL_DIR} anchors all script invocations; taught placeholder names written without dollar-brace wrappers (substitution lesson from PR #53); eval suites intentionally NOT shipped (the eval runner is authoring-repo-side; shipping them would be dead weight with broken references).

Gate evidence

  • claude plugin validate ./plugins/docs-hygiene --strict — PASS; claude plugin validate . --strict (catalog) — PASS
  • claude plugin details token cost: ~1,161 tok always-on (compress ~340, declutter ~280, encapsulation-audit ~150, extract-ssot ~170, rename-references ~230); on-invoke ~2.6k–6.4k per skill
  • Script tests: 73 checks across 4 self-contained suites (compress 9, declutter 17, encapsulation-audit 32, extract-ssot 15) — all pass, network-free, fixture-repo based
  • shellcheck (repo rcfile) clean on all 9 shell files; shfmt clean; markdownlint 0 errors (24 files); typos clean; editorconfig-checker clean
  • --plugin-dir smoke test in a clean non-source repo — PASS: /docs-hygiene:declutter invoked, answered the five noise shapes, namespace confirmed as docs-hygiene:declutter

Security review (playbook acceptance)

  • No hooks, no MCP servers, no agents, no userConfig.
  • Code execution surface: bundled scripts are read-only detectors and fact emitters (grep/awk over the consuming repo's tracked files). Zero network egress — verified by grep over all shell files (no curl/wget/nc; the only http hit is a URL string inside a test fixture).
  • Cross-plugin trust: compress can delegate mechanical compression to the third-party caveman plugin ONLY when the consumer has installed it; detection is capability-probing, invocation is the qualified /caveman:compress form, and the built-in fallback keeps the skill fully functional without it. No other plugin is referenced.
  • Cache isolation: no ../ reach-outs; state (optional compress snapshots) goes to the plugin data directory.
  • No PII / secrets.

Merge note: PRs #53 and #56 also touch marketplace.json + root README.md — the playbook prescribes serializing final merges; whichever lands later rebases the two shared files.


Note

Low Risk
Documentation and read-only/local shell tooling only—no hooks, MCP, network calls, or automatic repo writes beyond what users invoke via skills; optional third-party caveman compression is opt-in.

Overview
Adds the docs-hygiene plugin to the marketplace catalog and root README, bundling five on-demand skills for keeping tracked markdown lean, deduplicated, and correctly referenced in any consumer repo.

/docs-hygiene:compress tightens prose by cutting flavor while a mandatory fresh-context semantic-diff pass reverts semantic loss; it optionally uses the caveman plugin as a mechanical backend with an in-session Edit fallback, snapshots, and markdownlint-cli2 gates. declutter is read-only noise classification (five shapes, tiered findings) backed by detect.sh and shared shape detectors. extract-ssot encodes Rule-of-Three markdown dedup with identify / verify / plan / execute / batch / unwind, private action docs, and emit-verify-facts.sh. encapsulation-audit ships public-surface-contract.md plus detect.sh (private skill paths, heading anchors, schemas; scripts/ carve-out). rename-references is documented as the post-rename sweep skill (12-form patterns); sibling skills cite it after migrations.

Scripts are repo-local, read-only where applicable, always-exit-0 or explicit exit codes for audits, and covered by self-contained bash test suites (detect-caveman, declutter, encapsulation-audit, extract-ssot).

Reviewed by Cursor Bugbot for commit e19b05c. Bugbot is set up for automated code reviews on this repo. Configure here.

Bundles five documentation-hygiene skills adapted repo-agnostic from
the authoring repo: compress (flavor-trim behind a mandatory
fresh-context semantic-diff audit, optional caveman-plugin backend with
in-session fallback), declutter (read-only five-shape noise classifier
with internalized shape definitions and treatments), extract-ssot
(Rule-of-Three deduplication with refuse-fast verification gates),
encapsulation-audit (skill-private-surface citation detector shipping
its own public-surface contract), and rename-references (12-form stale
reference sweep). Source-repo rule citations are internalized or routed
to the consuming repo's own CLAUDE.md/rules; scripts resolve paths
relative to themselves and are read-only with zero network egress;
eval suites are intentionally not shipped (the eval runner is
authoring-repo-side).

Co-Authored-By: Claude <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_ba0b460a-9eef-4e22-9e04-14d8e499c295)

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale comment

Risk: medium. Not approving because Cursor Bugbot skipped (usage limit reached) and did not provide a clean automated review signal. Human review is needed; no reviewers were assigned because no suitable non-author maintainers were identified in this repository.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

…iene

# Conflicts:
#	.claude-plugin/marketplace.json
#	README.md
@cursor

cursor Bot commented Jul 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_504a51b9-37d9-4649-83f5-562bcfc709ae)

@claude

claude Bot commented Jul 11, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 3m 58s —— View job


PR Review: docs-hygiene plugin

  • Gather context (CLAUDE.md, PR diff, changed files)
  • Review plugin manifest and marketplace registration
  • Review shell scripts for correctness and security
  • Review skill instruction files (SKILL.md files)
  • Review context/action documents
  • Assess security, isolation, and repo-agnostic compliance
  • Compile and post final review

Overall, this is a well-crafted, production-ready plugin. The structure is clean, the security posture is strong, and the test suites are thorough. Three issues follow — one medium (silent false negatives on macOS), one low (doc/code mismatch on opt-out semantics), one cosmetic (unconventional return convention).


Finding 1 — Medium: BRE \| alternation breaks silently on macOS (BSD grep)

File: plugins/docs-hygiene/skills/encapsulation-audit/scripts/detect.sh

The detection pattern on line 88 uses BRE syntax (\| for alternation, \+ for one-or-more):

PATTERN='\.claude/skills/[a-z][a-z0-9-]\+/[a-z][a-z0-9_-]\+/\|\.claude/skills/[a-z][a-z0-9-]\+/SKILL\.md#\|...'

\| as alternation is a GNU grep extension — it is not part of POSIX BRE and is absent from macOS's BSD grep. On macOS, grep with this BRE pattern would either error or (worse) silently match nothing, giving a false "clean" result when violations actually exist. The consequence is that consumers on macOS running /encapsulation-audit detect see no violations even when their repo has encapsulation breaks.

The inconsistency is visible in the same file: SCRIPTS_RE on line 102 already uses ERE syntax (+ without backslash) and is correctly invoked with grep -vE. The same fix applies to the main pattern.

Fix — convert to ERE and switch to grep -E:

# line 88 — was BRE with \+ and \|
PATTERN='\.claude/skills/[a-z][a-z0-9-]+/[a-z][a-z0-9_-]+/|\.claude/skills/[a-z][a-z0-9-]+/SKILL\.md#|\.claude/skills/[a-z][a-z0-9-]+/[^/]+\.schema\.json'
# ...
# line 111 — was grep -rno; change to grep -rnoE
grep -rnoE "$PATTERN" \
  --include='*.md' --include='*.sh' --include='*.json' \
  --include='*.yml' --include='*.yaml' \
  "${SCOPE_DIRS[@]}" 2>/dev/null || true
# line 117 — was grep -Hno; change to grep -HnoE
grep -HnoE "$PATTERN" "${SCOPE_FILES[@]}" 2>/dev/null || true

Fix this →


Finding 2 — Low: Opt-out marker suppresses one line, not a paragraph (doc/code mismatch)

Files:

SKILL.md documents two distinct markers:

(covers the next **paragraph**) (next line)

But declutter_line_skipped() in noise-shapes.sh treats them identically — it only inspects the immediately preceding line:

declutter_line_skipped() {
  local prev="$1" line="$2"
  [[ "$prev" == *'markdown-discipline-ignore'* ]] && return 0   # prev line only
  [[ "$line" == *'markdown-discipline-ignore'* ]] && return 0   # current line
  return 1
}

This means `` placed before a multi-line paragraph suppresses only the first line, not the entire paragraph. The test suite in detect.test.sh only covers the single-line case, so the mismatch goes undetected.

Either:

  • Update SKILL.md to document the actual behavior (single-line suppression only — two markers behave identically), or
  • Implement true paragraph-level suppression in detect.sh with a flag that stays raised until an empty line is encountered.

Fix this →


Finding 3 — Cosmetic: declutter_detect_shapes returns non-zero to signal "found"

File: plugins/docs-hygiene/skills/declutter/scripts/lib/noise-shapes.sh (line 63)

return "$found"   # found=0 (nothing), found=1 (at least one shape)

Returning 1 to signal "found something" is the inverse of bash convention (non-zero = error). The caller correctly guards this with || true, but the pattern is a future-maintenance trap — a contributor who doesn't see || true in detect.sh and adds set -e to the library sourcer would get silent skips on every line that produced a match.

Consider changing to always return 0 and let callers rely solely on whether stdout was non-empty (which they already do via shapes="$(...)" + [[ -n "$shapes" ]]).


Security & compliance — no issues

  • No network egress, no hooks, no MCP, no userConfig
  • All scripts read-only (grep/awk/git) over the consumer repo ✅
  • ${CLAUDE_SKILL_DIR} anchors all script invocations; state in ${CLAUDE_PLUGIN_DATA}
  • No ../ reach-outs; no PII or hardcoded paths ✅
  • Cross-plugin caveman trust: capability-probed, detect-caveman.sh gracefully degrades to unknown when either claude or jq is absent; in-session fallback is fully functional without caveman ✅
  • allowed-tools: Bash(bash *declutter/scripts/detect.sh*) on declutter nicely restricts Bash surface for the read-only skill ✅

Test coverage — solid

73 checks across 4 self-contained fixture-based suites, all network-free. The encapsulation-audit suite covers the mixed-line (scripts/ carve-out) case specifically, which is the trickiest path. The emit-verify-facts suite verifies .md-only scope and zero-match exits correctly.

Minor observations (no action needed)

  • detect-caveman.sh uses set -uo pipefail without set -e and documents the omission — correct for the always-exit-0 contract.
  • encapsulation-audit/detect.sh uses mktemp + trap ... EXIT correctly for HITS_FILE cleanup.
  • emit-verify-facts.sh's citation_regex is lowercase-only ([a-z0-9./_-]+) — fine given the tool's narrow purpose.
  • public-surface-contract.md references platform.claude.com/docs/en/agents-and-tools/... URLs; these are cited-for-reference only (not fetched at runtime) so staleness doesn't affect functionality.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale comment

Risk: medium. Not approving because Cursor Bugbot skipped (usage limit reached) and did not provide a clean automated review signal. Human review is needed; no reviewers were assigned because no suitable non-author maintainers were identified in this repository.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a1731b8c9e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/docs-hygiene/skills/extract-ssot/scripts/emit-verify-facts.sh Outdated
Comment thread plugins/docs-hygiene/skills/declutter/scripts/detect.sh
detect.sh now expands directory targets to the .md files inside them so
`detect.sh <dir>` batch-audits instead of silently skipping non-files;
emit-verify-facts.sh passes patterns to git grep via -e so a
dash-prefixed cluster phrase (e.g. --no-verify) is not parsed as an
option. Both fixes carry regression test cases.

Co-Authored-By: Claude <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_81ea0092-d2dc-4ea4-aaf2-314b17b46f91)

@claude

claude Bot commented Jul 11, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 2m 10s —— View job


PR Review: docs-hygiene plugin — follow-up (d9b1bf3)

  • Examine new commit vs previous reviewed commit
  • Check whether previous findings were addressed
  • Review new/changed files in the follow-up commit
  • Post updated findings

Follow-up commit (d9b1bf3)

This commit addresses the two Codex-flagged issues from the earlier review round. Both fixes look correct with regression tests.

1. Directory expansion in detect.sh — fix is sound. find "$target" -type f -name '*.md' expands recursively, and the expanded targets flow into the existing mapfile -t SORTED < <(... | LC_ALL=C sort -u) at line 100, so the deterministic-sort contract documented in SKILL.md is maintained. Regression test covers a nested directory case.

2. Dash-prefixed git grep in emit-verify-facts.sh — all three git grep calls (lines 77–81) now pass the pattern via -e, correctly preventing a phrase like --no-verify from being parsed as a flag. Regression test covers exactly that case with assert_contains "dash-prefixed phrase counted" "$dash_out" "Instance hit count: 1".

No new issues introduced by this commit.


Open findings from previous round (still unaddressed)

Three issues from the prior Claude review remain in the code. They are reproduced here for completeness:


Finding 1 — Medium: BRE \| alternation breaks silently on macOS (BSD grep)

File: plugins/docs-hygiene/skills/encapsulation-audit/scripts/detect.sh line 88

The PATTERN variable still uses BRE \| and \+ — GNU grep extensions absent from macOS BSD grep. On macOS, the scan silently emits no hits (false-clean). The same file already uses ERE in SCRIPTS_RE (line 102, invoked with grep -vE); apply the same treatment to PATTERN.

# line 88 — convert to ERE
PATTERN='\.claude/skills/[a-z][a-z0-9-]+/[a-z][a-z0-9_-]+/|\.claude/skills/[a-z][a-z0-9-]+/SKILL\.md#|\.claude/skills/[a-z][a-z0-9-]+/[^/]+\.schema\.json'
# line 110 — grep -rnoE
grep -rnoE "$PATTERN" ...
# line 117 — grep -HnoE
grep -HnoE "$PATTERN" ...

Fix this →


Finding 2 — Low: Opt-out marker suppresses one line, not a paragraph (doc/code mismatch)

Files:

Either update SKILL.md to say "next line" for both markers, or implement paragraph-level suppression in detect.sh by raising a flag that stays active until the next blank line is encountered.

Fix this →


Finding 3 — Cosmetic: declutter_detect_shapes returns non-zero to signal "found"

File: plugins/docs-hygiene/skills/declutter/scripts/lib/noise-shapes.sh line 63

return "$found" returns 1 when a shape is detected — the inverse of bash convention. The call site at detect.sh line 127 already guards with || true, so this is safe today but a future-maintenance trap. Consider always returning 0 and letting callers rely solely on non-empty stdout.


Security & compliance

No new concerns from the follow-up commit. The directory expansion uses find (read-only, local), no network egress, no change to the security surface.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale comment

Risk: medium. Not approving because Cursor Bugbot skipped (usage limit reached) and did not provide a clean automated review signal. Human review is needed; no reviewers were assigned because no suitable non-author maintainers were identified in this repository.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d9b1bf3f0d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/docs-hygiene/skills/rename-references/context/patterns.md
Comment thread plugins/docs-hygiene/skills/declutter/scripts/detect.sh
…iene

# Conflicts:
#	.claude-plugin/marketplace.json
#	README.md
@cursor

cursor Bot commented Jul 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_0e3fe30c-22eb-4fe2-a251-72ec2a88287d)

@claude

claude Bot commented Jul 11, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 2m 48s —— View job


PR Review: docs-hygiene plugin — follow-up (e19b05c)

  • Examine new commit vs previous reviewed commits
  • Check whether previous findings were addressed
  • Review any new changes
  • Post updated findings

New commit (e19b05c) — merge only, no docs-hygiene changes

This commit is a git merge origin/main to pick up the boris plugin (#56). It touches only .claude-plugin/marketplace.json, README.md, and the new plugins/boris/ and plugins/thariq-skills/ trees. No docs-hygiene files were modified. The three findings from prior rounds remain open.


Open findings — still unaddressed

Finding 1 — Medium: BRE \| alternation breaks silently on macOS (BSD grep)

File: plugins/docs-hygiene/skills/encapsulation-audit/scripts/detect.sh#L88

PATTERN still uses BRE \| and \+ — GNU grep extensions absent from macOS BSD grep. On macOS the scan silently produces no hits (false-clean), making /encapsulation-audit detect unreliable on the dominant consumer platform.

The same file already uses ERE correctly for SCRIPTS_RE (line 102 with grep -vE). Apply the same treatment to PATTERN:

# line 88 — ERE instead of BRE
PATTERN='\.claude/skills/[a-z][a-z0-9-]+/[a-z][a-z0-9_-]+/|\.claude/skills/[a-z][a-z0-9-]+/SKILL\.md#|\.claude/skills/[a-z][a-z0-9-]+/[^/]+\.schema\.json'

# lines 110, 117 — add -E flag
grep -rnoE "$PATTERN" ...
grep -HnoE "$PATTERN" ...

Fix this →


Finding 2 — Low: Opt-out marker suppresses one line, not a paragraph (doc/code mismatch)

Files:

declutter_line_skipped() receives only prev and line — there is no mechanism to hold state across lines, so a multi-line paragraph after `` has only its first line suppressed. The doc–code mismatch is confirmed in the latest Codex round too.

Simplest fix: update SKILL.md line 54 to match the actual behavior — say "next line" for both markers — and update the test comment. Or implement a paragraph-level flag in detect.sh that stays set until the next blank line.

Fix this →


Finding 3 — Cosmetic: declutter_detect_shapes returns non-zero to signal "found"

File: plugins/docs-hygiene/skills/declutter/scripts/lib/noise-shapes.sh#L63

return "$found" returns 1 when shapes are found — the inverse of bash convention. The call site guards with || true today, but any future contributor adding set -e to the sourcing script would silently skip every line that matched a shape.

Consider returning 0 always and letting callers rely solely on non-empty stdout, which they already check via shapes="$(...)" + [[ -n "$shapes" ]].


New observations from this pass

Two additional items flagged by the latest Codex round are worth noting, though both are lower severity than Finding 1:

patterns.md Form 1 — <old> substitution ambiguity (low)

plugins/docs-hygiene/skills/rename-references/context/patterns.md#L15-L20

Form 1 pattern is \B/<old>\b. The instruction says "Substitute <old> with the actual old token." When a user invokes /rename-references audit blast /verify to /verify-changes, the rename pair is <old>=/verify — and a model that substitutes literally gets \B//verify\b, which matches nothing. All other forms (context/<old>\.md, skills/<old>/) make it clear <old> is the bare name; Form 1 should say so too. Consider adding: "Strip any leading / from <old> when building this pattern — the slash is already in the template."

emit-verify-facts.sh — url_regex misses common primary-source hosts (low)

plugins/docs-hygiene/skills/extract-ssot/scripts/emit-verify-facts.sh#L76

url_regex covers code.claude.com, platform.anthropic.com, IETF RFCs, and Microsoft Learn — but not www.anthropic.com, developer.mozilla.org, developer.apple.com, or other common spec/vendor hosts. Gate 3 (REFUSE-primary-source-citation-gate) would miss clusters where call sites cite these sources. The fact emitter is a hint tool (not a hard gate), so impact is bounded — the model still applies its own judgment. But widening the regex reduces silent misses on common citation patterns.


Security & compliance

No new concerns from the merge commit. Boris plugin additions are out of scope for this review; they were reviewed in PR #56.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Risk: medium. Not approving because Cursor Bugbot did not complete successfully and did not provide a clean automated review signal. Human review is needed; no reviewers were assigned because no suitable non-author maintainers were identified in this repository.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e19b05cb79

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/docs-hygiene/skills/declutter/scripts/detect.sh
Comment thread plugins/docs-hygiene/skills/encapsulation-audit/scripts/detect.sh
@kyle-sexton
kyle-sexton merged commit 8c35a5f into main Jul 11, 2026
22 checks passed
@kyle-sexton
kyle-sexton deleted the feat/publish-docs-hygiene branch July 11, 2026 11:40
kyle-sexton added a commit that referenced this pull request Jul 11, 2026
Closes melodic-software/medley#1293.

Publishes the `fable-5-playbook` plugin per `docs/MIGRATION-PLAYBOOK.md`
(per-plugin gate + acceptance security review).

## What ships

- `plugins/fable-5-playbook/` — one knowledge skill
(`/fable-5-playbook:fable-5-playbook`): Claude Fable 5's operating
doctrine, authored by Fable 5 as introspected standing instructions.
Core doctrine arms the session on invocation; twelve trigger-routed
chapters under `context/` (calibration, reasoning-moves,
problem-framing, planning, execution, debugging, orchestration,
verification, communication, recovery, context-economy,
trust-and-authority) plus `context/opus-adaptation.md` for non-Fable
models.
- Marketplace entry: `category: learning`, tags `knowledge` + component
tags. Explicit `version: 0.1.0` in `plugin.json` only.
- The source skill was already repo-agnostic (no repo-specific paths,
tools, or slash references); the only content deltas from the source are
the frontmatter description compressed to two sentences and one typo fix
(`mis-framed` → `misframed`).

## Gate evidence

- `claude plugin validate ./plugins/fable-5-playbook --strict` — PASS;
`claude plugin validate . --strict` (catalog) — PASS
- `claude plugin details` token cost: **~207 tok always-on**, ~4.7k
on-invoke (single skill)
- markdownlint 0 errors (15 files); typos clean; editorconfig-checker
clean
- `--plugin-dir` smoke test in a clean non-source repo — PASS: skill
invoked, answered the four meta-rules (Precedence, One home per
doctrine, Model adaptation, Silent application), namespace confirmed as
`fable-5-playbook:fable-5-playbook`

## Security review (playbook acceptance)

- Pure knowledge skill: no hooks, no MCP servers, no agents, no
`userConfig`, no scripts, no state, zero network access.
- Cache isolation: all references are skill-internal (`context/*.md`
self-citations); no `../` reach-outs.
- No PII / secrets.

Merge note: open PRs #53, #56, #57 also touch `marketplace.json` + root
`README.md` — merge serially; later ones rebase/merge the two shared
files (this branch is based on post-context7 main, so it conflicts only
with those unmerged siblings).

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Markdown-only plugin packaging and catalog updates; no executable
code, credentials, or runtime side effects beyond skill text loaded into
Claude Code.
> 
> **Overview**
> Adds the **`fable-5-playbook`** plugin to the marketplace and root
catalog — a pure knowledge skill (no hooks, MCP, scripts, or
`userConfig`) that arms sessions with Claude Fable 5’s operating
doctrine.
> 
> **`SKILL.md`** loads core standing instructions on invoke (bare /
`full` / chapter name), defines four meta-rules, effort floors, a
chapter routing table, and cites twelve on-demand **`context/*.md`**
chapters (calibration through trust-and-authority) plus mandatory
**`opus-adaptation.md`** for non-Fable models. Plugin **`README.md`**
and **`plugin.json`** (`0.1.0`, learning category) document install and
scope.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
03fa989. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Claude <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Jul 11, 2026
Closes melodic-software/medley#1296.

Publishes the `firecrawl` plugin per `docs/MIGRATION-PLAYBOOK.md`
(per-plugin gate + acceptance security review).

## What ships

- `plugins/firecrawl/` — one skill (`/firecrawl:firecrawl`): wraps the
`firecrawl-cli` binary for
scrape/search/crawl/map/parse/interact/agent/monitor with the core
write-to-disk-then-Read pattern (results land in tempfiles via `-o`; the
agent reads only the needed slice — 32–35× token savings vs the MCP per
the Scalekit benchmark cited in the skill).
- `context/commands.md` (full flag tables, carried verbatim),
`context/configuration.md` + `context/update-flow.md` (adapted
repo-agnostic).
- Maintainer-facing `scripts/update.sh` (`--check` read-only CLI-version
+ upstream-SHA drift report; `--apply` npm upgrade + `UPSTREAM.md`
rewrite behind approval gates; never touches SKILL.md — content
integration is a gated manual step) with a new self-contained
`update.test.sh` (17 checks, network-free).
- `UPSTREAM.md` sidecar (SHA-tracking sync state + rollback version).
- Marketplace entry: `category: utilities`. Explicit `version: 0.1.0` in
`plugin.json` only.

## Gate evidence

- `claude plugin validate ./plugins/firecrawl --strict` — PASS; catalog
`--strict` — PASS
- `claude plugin details` token cost: **~253 tok always-on**, ~4.9k
on-invoke
- `update.test.sh` 17/17 PASS; shellcheck (repo rcfile) clean; shfmt
clean; markdownlint 0 errors; typos clean; editorconfig-checker clean
- Smoke test via `--plugin-dir` — PASS: skill body loaded, answered the
write-to-disk flag (`-o`) from the body, namespace confirmed as
`firecrawl:firecrawl`. The smoke run surfaced two real
headless-permission defects that are fixed in this PR: a
credential-shaped `printenv FIRECRAWL_API_KEY` preamble line was
rejected by permission preflight (removed — `firecrawl --status` already
reports auth), and the status/sync preamble lines needed narrow
`allowed-tools` grants (`Bash(command -v firecrawl*)`, `Bash(firecrawl
--status*)`, `Bash(grep -m1 *UPSTREAM.md*)`). Caveat: in a fully
sandboxed scratch dir the preamble lines may still fall back to their
error text; the skill body loads and functions regardless.

## Security review (playbook acceptance)

- No hooks, no MCP servers, no agents, no `userConfig`.
- Data egress (normal invocation): the user-installed `firecrawl-cli`
calls `api.firecrawl.dev` (or a self-hosted `FIRECRAWL_API_URL`) — that
is the plugin's documented purpose. The credential is the consumer-owned
`FIRECRAWL_API_KEY` env var; never stored in or written by the plugin.
Env-var auth is preferred over `firecrawl login`/`config` explicitly to
avoid a second credential store.
- Data egress (update path, maintainer-invoked only):
`registry.npmjs.org` (version metadata) + `www.firecrawl.dev` (upstream
skill source, hashed in a tmpdir). `npm install -g` and any SKILL.md
rewrite sit behind two explicit approval gates; `--check` is read-only.
- The skill hard-prohibits `firecrawl init` (would install a parallel
MCP + skill copy) and documents the login/config divergence risk.
- Cache isolation: script resolves paths relative to itself; preamble
reads its own `UPSTREAM.md` via the skill-dir substitution; no `../`
reach-outs.
- No PII / secrets.

Merge note: open PRs #53, #56, #57, #59 also touch `marketplace.json` +
root `README.md` — merge serially; later ones need a conflict-merge of
the two shared files.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> New plugin steers agents toward external Firecrawl API egress and
credit use via a user-installed CLI and `FIRECRAWL_API_KEY`; maintainer
`--apply` runs `npm install -g`, but there are no hooks/MCP and updates
are gated.
> 
> **Overview**
> **Adds a new `firecrawl` plugin** to the marketplace and root catalog,
shipping `/firecrawl:firecrawl` as the maintained `firecrawl-cli`
integration (scrape, search, crawl, map, parse, interact, agent,
monitor) instead of the Firecrawl MCP.
> 
> The skill centers on **write-to-disk then `Read`** (`-o` tempfiles)
with escalation tables for when to use Firecrawl vs WebFetch, narrow
**`allowed-tools`** for the status/sync preamble (`firecrawl --status`,
`UPSTREAM.md` grep), and prohibitions against `firecrawl init` /
login-style config drift. Supporting **`context/`** docs cover flags,
env defaults, and the maintainer update pipeline; **`UPSTREAM.md`**
records upstream SHA and CLI rollback versions.
> 
> **Maintainer tooling:** `scripts/update.sh` (`--check` read-only drift
vs npm + upstream skill; `--apply` global `npm install` + `UPSTREAM.md`
rewrite only, not `SKILL.md`) and network-free **`update.test.sh`**
regression checks.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
3184b4e. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Claude <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