This release includes 3 breaking changes for platform teams planning a safe upgrade.
✓ No known CVEs patched in this version
Topics
Affected surfaces
Summary
AI summaryBare-form MCP dispatch no longer falls back to primary; legacy symbol ops removed and ask intrinsic eliminated, requiring named form and canonical function calls.
Full changelog
Theme: structural discipline applied to source-level dispatch surfaces. Two
classes of dual-surface ambiguity collapsed simultaneously so downstream
audit + maintenance work has a single canonical surface to reason about.
Breaking changes (pre-adoption window — no external adopters)
Sub-charter A: bare-form / named-form discipline for MCP dispatch. Bare
$ <tool> no longer falls back to the primary connector. Bare form is
reserved for runtime intrinsics (execute_skill, json_parse) and the
typed-contract name-match pattern ($ <name> where <name> matches a
wired MCP connector, e.g. $ llm prompt=... against the llm bridge).
Substrate-specific MCP dispatch now requires named form $ <connector>.<tool>.
This closes the silent-failure mode where cron-fired skills using bare-form
substrate-specific tools ($ amp_olsen_task, $ github_create_issue)
errored at dispatch time because primary wasn't registered — no transcript,
no fallback, just a missing-connector error. With v0.16.0, the lint surface
and runtime error both direct adopters to named form with explicit
remediation copy.
Sub-charter B: legacy symbol-form ops eliminated. The six legacy symbol
forms (~, >, @, !, ??, &) now produce parse errors with
canonical-form remediation. Only the function-call canonical surface
survives at source level. AST kinds renamed in lockstep
(!→emit, @→shell, &→inline); the legacy
~/> AST kinds + their dedicated runtime paths deleted entirely (the
canonical replacements $ llm and $ data_read dispatch through the
LocalModelMcpConnector + DataStoreMcpConnector bridges).
Sub-charter C: ask runtime-intrinsic removed. ask(prompt="...") was
removed entirely (not renamed). The op conflated two unrelated concerns:
(1) user-surfacing, which requires an interactive channel the runtime
can't guarantee for cron/event-fired skills, and (2) mutation-gating,
which is already covered by per-op approved="reason" kwarg +
skill-level # Autonomous: true. The mutation-gate "preceding ask
authorizes following mutations" rule (sawConfirm path) is retired —
authorization now flows only through approved= and # Autonomous:.
For input-collection workflows, use emit(text="...") and have the
caller handle the round-trip. InteractiveOpInAutonomousModeError class
deleted (now unreachable).
The deprecated-symbol-op lint rule, the unknown-retrieval-arg lint rule,
the model-contention lint rule, and the sourceForm AST marker were
deleted as part of this collapse — all served the grace-period machinery
that no longer applies.
Parity fix: $ dispatch closes the discipline-only-contract gap
While analyzing the legacy elimination, we surfaced that the canonical
$ llm and $ data_read dispatch paths had been declared as parity
replacements for legacy ~ and > but lacked two semantics the legacy
forms supported:
-
Per-op
timeout=Nkwarg — legacy~acceptedtimeoutSeconds=N
in its structured-params bag; the generic$dispatch had no equivalent.
v0.16.0 addstimeout=Nas a reserved op-level kwarg on every$op
(intercepted at runtime before forwarding to the connector). -
Fallback-on-empty — the doc at
parser.ts:84-91claimed$fallback
fires "on throw or empty result", matching legacy~/>semantics, but
the code only handled throw. v0.16.0 fixes the code to match the doc:
fallback fires on empty string (after trim), empty array, or
null/undefinedresult in addition to throw.
These were latent gaps since v0.7.2. Adopters who migrated from ~/> to
$ llm/$ data_read lost per-op timeout + empty-result fallback silently —
v0.16.0 makes the canonical surface match the documented contract.
Migration mapping (mechanical)
| Legacy (parse error) | Canonical |
|---|---|
| ! text | emit(text="text") |
| ?? "prompt" -> R | (removed — ask op deleted; use emit(text="...") + caller round-trip, or approved="reason" for mutation gating) |
| @ cmd args | shell(command="cmd args") |
| @ unsafe cmd | shell(command="cmd", unsafe=true) |
| & skill-name | inline(skill="skill-name") |
| ~ prompt="..." -> R | $ llm prompt="..." -> R |
| > mode=... query=... -> R | $ data_read mode=... query=... -> R |
| Bare $ <substrate_tool> | $ <connector>.<substrate_tool> |
Bundled examples + docs updated
hello-world.skill.md, skill-store-roundtrip.skill.md, and
data-store-roundtrip.skill.md use canonical function-call syntax
throughout. Help content + lint code references swept for legacy-form
mentions.
Internal
- ~550 LOC removed from narrow core (parser + lint + runtime shrink)
OpKindtype union narrows from 14 to 11 (delete~,>,ask; rename three)SkillOpinterface dropslocalModelParams,retrievalParams,
sourceFormfieldsRUNTIME_INTRINSIC_FN_NAMESshrinks to 7 (deleteask)MutationAuthState.sawConfirmfield removed; mutation gate now relies
solely onop.approved+skillAutonomousInteractiveOpInAutonomousModeErrorclass deleted- LocalModelMcpConnector bridge auto-wired as
llmconnector unchanged
Breaking Changes
- Bare `$ ` no longer falls back to the `primary` connector; named form `$ . ` is required.
- Legacy symbol forms (`~`, `>`, `@`, `!`, `??`, `&`) now produce parse errors and are replaced by canonical function-call syntax.
- `ask(prompt=...)` runtime intrinsic removed entirely.
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
About Skillscript
All releases →Related context
Related tools
Earlier breaking changes
- v0.35.0 Editing `# Deadline:` on an approved skill drops it to Draft (signature invalidates).
Beta — feedback welcome: [email protected]