Skip to content

Skillscript

v0.14.1 Breaking

This release includes 2 breaking changes for platform teams planning a safe upgrade.

✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →

✓ No known CVEs patched in this version

Topics

agents dsl llm mcp skills workflow

Affected surfaces

auth breaking_upgrade rbac

Summary

AI summary

Updates Internal, Tests, and New error classes across a mixed release.

Full changelog

Cold-adopter Phase 1 v4 dogfood against v0.14.0 closed clean on substrate-portability

  • package-only sufficiency, but surfaced four findings on contract-vs-runtime parity
    cases where the language reference / spec described a guarantee that only lint
    enforced, leaving callers who bypassed lint (execute_skill({source})) silently
    slipping through. v0.14.1 makes the runtime the load-bearing enforcement boundary;
    lint stays advisory.

Per the "discipline-only contracts are bugs" invariant (banked this release as
sibling to the substrate-portability architecture invariant): when the spec
classifies an op or feature as requiring authorization/validation/sequencing,
runtime enforcement is mandatory — every layer that knows the contract should
enforce it.

Breaking-ish: mutation gate now throws at runtime

$ data_write / file_write / $ <mutating-name-tool> ops now throw
UnconfirmedMutationError at the runtime boundary
unless one of three
authorization signals is present:

  1. # Autonomous: true skill-header (cron/agent-fired skills)
  2. A preceding ?? / ask(...) in the same target (interactive confirmation)
  3. approved="reason" per-op kwarg (per-op intent marker)

Pre-v0.14.1 these signals were lint-warned but runtime-permitted; lint-tier
warnings don't block execution, and execute_skill({source}) bypassed lint
preflight entirely. v0.14.1 closes both bypass paths:

  • Layer A (load-bearing)execOps checks each op before dispatch.
  • Layer B (regression guard)execOpInner re-checks at the $ /
    file_write dispatch sites. Same predicate, fail-closed default authState.

Migration: cron / agent-fired skills with mutation ops need # Autonomous: true.
Bundled example skills updated; corpus authors set the header once at the top.

Pattern-shape (mutation classes): $ data_write MCP dispatch, $ <tool> with
mutating-name prefix (write_, update_, delete_, archive_, prune_,
deploy_, etc.), file_write(...) runtime-intrinsic.

Breaking-ish: substrate-side strict filters on $ data_read

DataStoreMcpConnector now enforces every non-base filter key against the
wrapped DataStore.manifest().supported_filters
, throwing
UnsupportedFilterError for unknowns. Closes the silent-scope-leak class
where pre-v0.14.1 substrates dropped unsupported filters (e.g., a skill
passing vault="team" against a substrate without vault semantics got
unfiltered results back, with no signal that the scoping was ignored).

Per-call opt-out: permissive_filters: true on the query acknowledges
"unknown keys are advisory; substrate may ignore them" — for cases where
the author knows their substrate is permissive by design.

Substrate implementor responsibility: declare every filter your query()
actually honors in manifest().supported_filters. Omissions become
"this filter is rejected at the bridge."

Docs

  • runtime_capabilities.shellExecution.description rewritten to lead with
    canonical shell(command="...") syntax; legacy @ <cmd> / @ unsafe <body>
    noted as deprecated-symbol-op aliases that parse identically.
  • scaffold/config.toml — stale @@ reference replaced with canonical
    shell(command=..., unsafe=true) form.
  • README MCP-surface section — execute_skill now distinguishes
    {skill_name} mode (subject to v0.9.0 hash-token approval gate) vs {source}
    mode (ad-hoc inline; never persisted; bypasses SkillStore + approval gate);
    explicitly calls out that v0.14.1 mutation gate applies in both modes.
  • docs/adopter-playbook.md — substrate-neutral rewrite. New "What the
    runtime promises connector implementors" section flat-lists the 5 typed
    contract methods + explicit "what's NOT in the contracts" boundary (vaults,
    namespaces, expiration, auth — all implementor concerns). Case 1 vs Case 2
    table updated. Mutation-gate + strict-filters added to the "things the
    playbook should be honest about" list.

Examples sweep — v0.14.1 contract compliance

  • examples/onboarding-scaffold/bootstrap.ts — wires data_write bridge
    alongside data_read (matches bundled src/bootstrap.ts pattern; one
    bridge instance, two connector names).
  • examples/onboarding-scaffold/file-data-store.tsmanifest() declares
    supported_filters: [] with comment explaining the substring scorer
    doesn't filter on fields; teaches the v0.14.1 strict-default contract.
  • examples/connectors/DataStoreTemplate/manifest() + query() docs
    explain v0.14.1 strict-filters enforcement at the bridge and how
    supported_filters is now load-bearing.
  • examples/custom-bootstrap.example.ts — commented wiring example mirrors
    the bundled both-names pattern.
  • examples/skillscripts/feedback-sentiment-scan, service-health-watch,
    classify-support-ticket rewritten to v0.14.1 contract (# Autonomous: true;
    canonical $ data_write content=... tags=[...]; envelope ${X.items}
    iteration; tokens recomputed). cut-release-tag shell-quote hygiene
    warnings cleaned.
  • examples/programmatic-trace-demo.mjs + docs/sqlite-skill-store.md
    legacy ! <text> shorthand replaced with canonical emit(text="...").

New error classes (src/errors.ts)

  • UnconfirmedMutationError extends OpErroropShape ("data_write" /
    "mutating_tool" / "file_write") + detail (tool name or path) +
    requiredSignals[] + concrete one-line suggestion in remediation.
  • UnsupportedFilterError extends OpErrorunsupportedKeys[] +
    supportedKeys[] + substrate name; remediation names 3 paths
    (drop / opt out / switch substrate).

Internal

  • New src/mutation-gate.ts (~85 LOC): classifyMutation,
    authorizationGranted, buildAuthorizationSuggestion,
    MUTATING_TOOL_PATTERN. Single source of truth — both lint and runtime
    call into the same classifier.
  • New src/connectors/filter-enforcement.ts (~40 LOC):
    enforceSupportedFilters(filters, supportedKeys, substrateName) helper +
    base-shape-key allowlist.
  • src/lint.ts UNCONFIRMED_MUTATION rule refactored to call the shared
    classifier (net -25 LOC).
  • src/runtime.ts execOps / execOp / execOpInner signatures plumb
    MutationAuthState; recursive foreach / if / else calls pass the
    same authState reference (sawConfirm propagates across nesting).
  • src/connectors/data-store-mcp.ts lazily caches supported_filters from
    the wrapped substrate's manifest (one async call per bridge instance).
  • Narrow-core LOC ceiling bumped 9550 → 9700 per Scott's "ceiling is a
    signal, not a budget" rule. File count (22) unchanged.

Tests

  • tests/v0.14.1-mutation-gate.test.ts — 8 cases: unauthorized throws + no
    dispatch; approved= works; # Autonomous: true works; preceding ask()
    authorizes (sawConfirm path); mutating-name shape throws + no dispatch;
    file_write paths.
  • tests/v0.14.1-strict-filters.test.ts — 7 cases: unknown key throws +
    no substrate call; error names keys; permissive_filters: true bypasses;
    base keys never flagged; declared keys pass; empty manifest fails closed;
    manifest fetched once / cached.
  • Test corpus migration: 4 test files (file_write / $ data_write fixtures)
    got # Autonomous: true to keep passing under the new runtime gate.

Suite: 1296 passing (+8 since v0.14.0).

Breaking Changes

  • $ data_write / file_write now throw UnconfirmedMutationError at runtime unless one of: # Autonomous: true skill header, preceding ask/?? confirmation, or approved="reason" per-op kwarg.
  • DataStoreMcpConnector enforces every non-base filter against manifest().supported_filters, throwing UnsupportedFilterError for unknowns (opt‑out via permissive_filters:true).

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

Share this release

Track Skillscript

Get notified when new releases ship.

Sign up free

About Skillscript

All releases →

Related context

Earlier breaking changes

  • v0.35.0 Editing `# Deadline:` on an approved skill drops it to Draft (signature invalidates).

Beta — feedback welcome: [email protected]