Skip to content

v0.15.0 — "Fable Ultra"

Choose a tag to compare

@not-stbenjam not-stbenjam released this 03 Jul 00:48
a1d7340

Our biggest release ever: 42 commits, 378 files changed, ~18.5k insertions
since v0.14.1. The headline is a full plugin architecture for distributing
lint rules as PyPI packages, alongside the removal of the built-in LLM fix
engine, a new dead-file detection rule, and a long list of autofix,
correctness, security, and performance fixes.

Highlights

Plugin architecture (#312, #311, #313, #314)

Rules can now be distributed as ordinary pip-installable packages via
skillsaw.plugins entry points — reviewable, versioned, and auditable,
unlike repo-local custom rule files.

  • Rule plugins: any package exposing a skillsaw.plugins entry point
    contributes rules, namespaced and attributed (source: plugin:<name>
    in JSON output).
  • Extension points: plugins can register custom repo types
    (SKILLSAW_REPO_TYPES) and lint-tree contributors
    (SKILLSAW_TREE_CONTRIBUTORS), pulling new file types into the parse
    tree and content linting.
  • Plugin CLIs: skillsaw <name> dispatches to a plugin's
    skillsaw-<name> console script — registered plugins only; arbitrary
    executables on PATH are never run.
  • Management: new skillsaw plugins command, --no-plugins flag, and
    plugins: {disable: [...]} config block. A plugin that fails to load
    reports a plugin-load-error violation instead of aborting the lint.
  • GitHub Action: new plugins input installs plugins in CI (#314).
  • Docs: a full authoring guide (docs/plugins.md), a scaffold example
    under examples/plugins/, and a skillsaw-create-plugin skill.

⚠️ Breaking: LLM fix engine removed (#310)

The built-in LLM autofix path is gone in favor of coding agents (see the
skillsaw-fix skill and per-rule skillsaw explain guidance):

  • Removed flags: skillsaw fix --llm/--ai, --model, --max-iterations,
    --all, -y/--yes, --workers, --patch-file, --apply-patch, and
    the hidden skillsaw lint --fix/--llm/--dry-run.
  • Removed pip extras: skillsaw[llm], [vertexai], [bedrock]
    (installing them now fails).
  • Removed rule API: AutofixConfidence.LLM, llm_fix_prompt,
    llm_fix_frontmatter — custom rules and plugins using them must update.
  • The llm: config section is now an ignored unknown-key warning;
    SKILLSAW_MODEL is ignored.

⚠️ Breaking: GitHub Action defaults to --no-custom-rules (#323)

For CI safety on untrusted PRs, the Action no longer executes repo-local
.skillsaw-custom.py rules by default. Nothing fails — custom rules
silently stop running.
Set no-custom-rules: false to opt back in, or
migrate to a rule plugin. The CLI default is unchanged, and custom-rule
loading now prints a clear one-line colored warning (#359).

New rule: agentskill-unreferenced-files (#347)

Detects dead files in skill directories — files never referenced from
SKILL.md or anything it transitively references. Warning severity,
enabled: auto on skill/plugin/marketplace repos, with an exclude
config parameter. Reachability is thorough: markdown links and text
mentions (case-insensitive), directory mentions (./fonts,
assets/fonts, fonts/), and Python import chains — both in .py
helpers and inside fenced code blocks — are all followed transitively.

Spec compliance & validation

  • metadata.pluginRoot honored when resolving marketplace plugin
    sources, per the Claude Code marketplace spec — bare source names now
    resolve, with a root-relative fallback for marketplaces that mix styles;
    traversing/absolute pluginRoots are rejected (#355).
  • marketplace.json source validation per the current spec: duplicate
    plugin names, ../absolute paths, typed-source required fields, unknown
    source types (#338).
  • Frontmatter hooks scanned: hooks-dangerous and hooks-prohibited
    now inspect hooks: declared in skill/agent frontmatter, not just
    hooks JSON files (#346).
  • Hooks & MCP validation synced with current Claude Code docs —
    exec-form args, MCP timeout, MessageDisplay event, ws
    transport (#336).
  • Digit-leading skill names (e.g. 1password) now valid per the
    agentskills.io spec (#337).

Autofix reliability

  • SAFE autofix corruption fixed: path truncation from backtrackable
    lookarounds, and duplicate name: keys from non-converging
    frontmatter fixes (#325).
  • BOM and CRLF line endings preserved byte-exactly across autofix (#332).
  • agentskill-name autofix no longer folds inline YAML comments into the
    rename manifest; comments are preserved on the rewritten line (#352).
  • content-broken-internal-reference resolves percent-encoded links and
    never emits unparseable destinations (#350).

Rule accuracy

  • content-embedded-secrets: entropy gating + placeholder allowlist
    kills documentation-placeholder false positives (password = "changeme", <your-api-key>, ${VAR} templates). Structured
    high-confidence tokens (AKIA…, ghp_…, JWTs, private keys) are always
    reported. Configurable via entropy-threshold and
    additional-placeholders (#354).
  • **-glob exclude semantics fixed: **/templates/** now matches a
    top-level templates/ directory, matching gitignore semantics — a
    strict superset of the old behavior, applied to global, per-rule, and
    agentskill-unreferenced-files excludes (#353).
  • agentskill-description max length is configurable via
    max_length (#348).
  • Four small bug fixes from the #322 sweep: custom-rule abstract-class
    guard, @~/ imports, stacked disable-next-line, docs crash (#351).

Security & performance

  • ReDoS protection: config-driven banned-references regexes run under a
    wall-clock timeout (regex-timeout, default 2s) (#330).
  • promptfoo file:// references contained to the repo root — traversal,
    absolute paths, and symlink escapes are rejected (#349).
  • Fixed O(n²) behavior in markdown_doc._ContentMap.locate (#328).
  • Benchmarks vs 0.14.1: synthetic suite at parity; plugin discovery adds
    no measurable startup cost (--version/--help never touch entry
    points).

Docs & DX

  • "How to fix" guidance added to every builtin rule page — also surfaced
    through skillsaw explain, feeding agent-driven fix loops (#309).
  • SARIF output docs, exit-code reference, configuration reference, clean
    skillsaw add scaffolds, stale pin cleanup (#326).
  • CLI internals: __main__.py god module split into a cli/ package
    (#308); block hierarchy extracted to skillsaw.blocks (#307);
    single-source rule registration (#311).

Upgrade notes — what may change on your repo

  • agentskill-unreferenced-files may fire new warnings (auto-enabled on
    skill-type repos).
  • Expanded marketplace-json-valid and frontmatter-hooks scanning may
    surface new violations; plugins under metadata.pluginRoot are now
    discovered and linted.
  • A top-level templates/ directory is now excluded by default; digit-
    leading skill names and placeholder-shaped "secrets" no longer flagged.
  • skillsaw plugins now lists installed plugin packages (exit 0) instead
    of linting the plugins/ directory — update CI that relied on the old
    behavior.
  • Action users: custom rules require no-custom-rules: false (see above).

Known issues

  • The secrets entropy gate trades false positives for some false
    negatives on generic key = "value" assignments (e.g. long digit-only
    values, values containing allowlisted words like token); structured
    token detection is unaffected.