This release adds 3 notable features for engineering teams evaluating rollout.
✓ No known CVEs patched in this version
Topics
Summary
AI summaryUpdates What's new Parser (src/parser.ts), Tests, and transcript across a mixed release.
Full changelog
A skill's body text — the prose between the frontmatter and the first
target — is now its declarative output template. The runtime interpolates
${VAR} references against final vars and publishes the rendered string
as the skill's canonical output. Per Scott + Perry's c7ddfc50 design lock
- 920078c8 / ad0b868e sign-off.
Why
The emit(text="${SUMMARY}") ceremony for what is structurally just
"render this template and output it" was the highest-leverage authorability
tax on the most common operation. From Perry's c7ddfc50:
Author writes the sentence they want; the compute block fills in the
holes. The same skill stripped of its compute block still emits the
template with whatever defaults# Vars:declares.
Wins:
- Declarative output (author writes the sentence they want)
- No throwaway
${SUMMARY}var ceremony - Branch resolved into vars; template stays single-shape
- Strip the compute block → still a valid skill that emits the template
What's new
Parser (src/parser.ts):
ParsedSkill.outputTemplate: string | null— the captured template
(null when none authored). Internal blanks preserved; leading/trailing
blanks trimmed.- Pin 4 disambiguation rule (
nextNonBlankLineIsIndentedlookahead): a
target is<name>:with an indented op-block on the next non-blank
line. Content-after-colon (Summary: hot today) without an op-block
is template text. Bare<word>:alone with no op-block in the template
region is captured AND recorded as ambiguous for lint. ParsedSkill.templateAmbiguousLines: number[]— line numbers for the
tier-2 lint surface.
Runtime (src/runtime.ts):
- When
parsed.outputTemplate !== null, render once viasubstituteRuntime
with the final vars map; the rendered string ownsoutputs[key]across
all# Output:kinds. Legacy emit-only path (no template) preserved
byte-equivalent —outputs.textfalls back toemissions.slice()/
lastBoundVarexactly as before. - Complementary channels:
emit()continues to populateemissions[]
(transcript) independently. Template = canonical output; emit =
transcript. No competition.
CLI (src/cli.ts):
skillfile executenow prints the rendered template when one is
authored (matching the canonical-output channel). Emit-only skills
continue to print emissions exactly as before.
Lint (src/lint.ts) — four new rules:
unset-template-var(tier-1, error) — every${VAR}in the template
must resolve to a# Vars:input, ambient ref, or$set/->binding
somewhere in the skill body. Tier-1 because an unbound ref renders
empty silently.template-looks-like-target(tier-2, warning) — bare<word>:alone
in the template region, no following op-block. Reads ambiguously;
author should disambiguate.body-template-detected(tier-3, info) — template captured but has
no${...}interpolations AND no text-consuming# Output:. Suggests
"I wrote prose; it became template by accident."emit-with-template(tier-3, info) — skill has both a template AND
emit(text=...)calls; confirms the channel-shift is intentional
(template owns canonical output; emit goes to transcript).
Migration
Additive — emit-based skills work unchanged. Bundled corpus verified
clean (13 skills; no body-template content; all produce
outputTemplate: null).
The lookahead disambiguation rule is stricter than the pre-v0.19.4
target detection: a line at column 0 matching <identifier>: parses
as a target only when the next non-blank line is indented. Every real
target has an op-block under it, so no observed corpus skill regresses.
The legacy target: dep_a dep_b deps-form is preserved (lookahead sees
the indented op-block and confirms target intent). The explicit
needs: dep_a dep_b keyword form is recommended for new skills.
Docs
- README quickstart + canonical autonomous skill updated to use the
template shape; new "fourth thing to notice" callout in the autonomous
example. docs/adopter-playbook.mdgains a new "Output template — body text IS
the output" section covering the shape, complementary channels,
output kinds, target syntax rules, and the four lints.
Tests
tests/v0.19.4-output-template.test.ts— 34 tests: parser extraction- Pin 4 disambiguation + migration safety + runtime render + output-kind
matrix + complementary channels + 4 lints (positive + negative) + e2e
(compile + execute + lint preflight blocking).
- Pin 4 disambiguation + migration safety + runtime render + output-kind
- Live HTTP probe + idempotent twice-run + edge cases (multi-line, special
chars, lint preflight, emit + template).
1860 tests total (+34 net new). Narrow-core LOC ceiling bumped
11100 → 11250 per the signal-not-budget rule (clear code wins).
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]