Release 0.9.0 — runtime-claim corrections, two defect fixes, compaction-budget guard - #1
Merged
Conversation
…ordered degradation Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhZZyCWnhiNQfwRkX6CNWL (cherry picked from commit 0bc0f831ea2f64cce5c08333f1d054f647cee166)
…isk and correct its premise Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhZZyCWnhiNQfwRkX6CNWL (cherry picked from commit 525ec56a6f750b9361e9d15f84a838a1f12d0546)
…es no longer gate --strict Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhZZyCWnhiNQfwRkX6CNWL (cherry picked from commit 8ce8799c1e0c7a7c0f9256f4acace9d9f2bf278d)
…st it Also adds the skill content lifecycle section (Task 8 Step 3 of the plan, folded in here because it shares the same anchor). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhZZyCWnhiNQfwRkX6CNWL (cherry picked from commit 80f9aff6110f296ce2606b4b5a6640e8bf0b3713)
…l source Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhZZyCWnhiNQfwRkX6CNWL (cherry picked from commit ae28263d5a5ff9eadc38d1a27dd4e7dd3d523a30)
…commit delivery, drop the link advice Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhZZyCWnhiNQfwRkX6CNWL (cherry picked from commit 4748e1c2e475f8c8d844264c673b81fc999e6c26)
… to claude-opus-5 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhZZyCWnhiNQfwRkX6CNWL (cherry picked from commit a66fcce68577af10b736325b769ad9f986ec9094)
…ound:false SKILL.md measures 490 lines / 39,525 chars / ~9,881 tokens against the 5,000-token per-skill re-attach cap this commit documents; the cut falls at line 255. Recorded, not addressed — deferred to a separate restructuring pass with its own eval run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhZZyCWnhiNQfwRkX6CNWL (cherry picked from commit a75fd30c51ff9310ed4b31716731edc7a486ed9e)
Re-verified every Claude-runtime claim against Claude Code 2.1.222, the Desktop archive, 712 real skill listings, and two live Cowork probes. Four claims were wrong; each correction states its evidence in the CHANGELOG entry. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhZZyCWnhiNQfwRkX6CNWL (cherry picked from commit 7db800cb9df2bc1fdea4936e96d3942a2a4680e5)
…arratives The 0.9.0 corrections left behind archaeology in forward-facing docs — what the doc used to claim, when it was disproved, and why. That is changelog material; the docs should just state the current rule. Trimmed from harness/README.md, environments.md (three places), create-skill.yaml, and frontmatter.py; the CHANGELOG keeps the full history. environments.md drops 874 chars, which matters because it is agent-loaded reference text. Two forward-facing notes are kept deliberately: frontmatter.py still warns against re-introducing PyYAML, and create-skill.yaml still explains why its assertion stays now that the premise behind it changed. Both state a rule, not a correction. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhZZyCWnhiNQfwRkX6CNWL (cherry picked from commit 1caaa1c7ce0b94713389ab3b258423590075b133)
Records the full rule list, the exit-code contract, and that --strict gates on warnings and errors only while advisories report without gating (--strict-advisories opts in). Also notes this repo's own linter baseline, so a non-empty finding list is not mistaken for a regression - a new rule id is the signal. Kept in sync with the CLAUDE.md mirror. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhZZyCWnhiNQfwRkX6CNWL
…name main is protected but enforce_admins is off, so a maintainer push succeeds and only prints 'Bypassed rule violations' — the protection cannot stop an accidental release, which makes the approval the real gate. Says so, and calls out automated agents explicitly: committing locally is not approval to push. Also corrects the recipe: release.yml triggers on 'push: tags: v*', so pushing the tag by name is sufficient and a release never needs a direct push to main. The old 'git push origin main --tags' both bypassed the PR flow and pushed more than needed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhZZyCWnhiNQfwRkX6CNWL (cherry picked from commit 53f910d5015dfb4f5cede8b03fba78af21f0c659)
After auto-compaction Claude re-attaches each invoked skill truncated to 19,900 characters. The cap is documented as "5,000 tokens" but the runtime sizes skill content by character count rather than tokenizing it, so characters are the unit that matters and wc -m is the way to measure. A tokenizer reading answers a different question and, on technical markdown, overstates the overage. Also records two behaviours that are easy to lose content to: truncation is written back, so a second compaction cannot recover the tail, and combined-cap overflow drops a skill's stored content entirely for the rest of the session. Verified against the shipping Claude Code 2.1.222 binary; the per-skill and combined caps are fixed literals with no context-window scaling. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhZZyCWnhiNQfwRkX6CNWL
SKILL.md told the agent to put <skill-name>-workspace/ "as a sibling to the skill directory". On a plugin or marketplace install the skill lives in a read-only cache, so that path is unwritable — and the agent silently falls back to the session scratchpad, which no user can see. On a remote Cowork session the scratchpad is reclaimed when the session ends, so the generated skill, its scripts, evals.json, the fixtures and every eval output are DESTROYED. Measured with cowork-harness at container fidelity, 2026-08-06, on the full create -> test -> eval -> review loop. Reproduced in both arms, so it is not a compaction artifact: full SKILL.md 41 files undelivered (scratchpad/skills/...) truncated SKILL.md 26 files undelivered (scratchpad/...) Both runs otherwise succeeded (68 and 62 tools, 6 sub-agents each) and both correctly paused for human review before packaging — the loss is purely the workspace location. The instruction now requires a user-visible, writable location and explains the failure mode, phrased by outcome rather than naming a lane-specific path. references/environments.md carries the Cowork-specific detail with the measured figures. Note this lands at SKILL.md:234, inside the 19,900-char surviving window, so it is present after compaction. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhZZyCWnhiNQfwRkX6CNWL (cherry picked from commit 9987b8e9e5039e8a67f83758e7966d9c2c080412)
… size guard Nothing measured the post-compaction budget, which is why this repo's own SKILL.md sat at ~2x it for nine releases without anyone noticing. The check is exact rather than heuristic. The runtime's documented '5,000 token' per-skill cap is computed as Math.round(chars / 4) against a hardcoded literal and sliced to 5000*4 minus a 98-char marker, so the real limit is 19,900 CHARACTERS and the check is a length comparison — no tokenizer, no estimate, no divisor to tune, no false-positive rate to argue about. The finding names the approximate line where the cut falls and states the unit explicitly, because both common proxies are wrong here: wc -c counts bytes and a tokenizer reads ~26% low on technical markdown. Advisory severity, so it reports without gating --strict. Scoped to claude-code + cowork: the mechanic lives in the Claude Code binary, and Claude.ai's behaviour is unverified. Adds 3 tests including the exact boundary. This skill's documented linter baseline goes 3 findings -> 4; DEVELOPMENT.md and its CLAUDE.md mirror updated and re-verified against real output. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhZZyCWnhiNQfwRkX6CNWL (cherry picked from commit c117824a34262f4f89f5411a41f6cb1369951cf2)
Bumps the pin from 1.16.0 across CI, harness/README.md, docs/DEVELOPMENT.md,
the scenario headers and the shipped references/environments.md install floor.
Two behavioural changes in the 1.17-1.19 range apply here:
- The CI lint step now runs --strict --min-severity WARN. Without both flags
it cannot fail on a WARN-class rule, so the gate was inert.
- verify-cassettes takes --allow-empty, replacing a hand-rolled ls guard. A
missing path still exits 2, so it cannot green a typo.
1.18.0's host-inventory finding class and its refusal to record into a
repo-visible path are tier-gated to protocol/hostloop and do not affect this
suite, where every scenario is fidelity: container. Both are documented in
harness/README.md for anyone adding such a scenario later, since
harness/cassettes/ is repo-visible here.
The scenarios pin no baseline, so the agent moved 2.1.219 -> 2.1.221 with this
upgrade. That also flipped proactiveSkillSuggestEnabled on, changing the surface
the no-trigger negative control asserts against; recorded in that scenario.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KhZZyCWnhiNQfwRkX6CNWL
…gest flip
cowork-harness 1.18.0's baseline flipped proactiveSkillSuggestEnabled from
{on:false,defaultValue} to {on:true,force}, changing the surface no-trigger.yaml
asserts against. The previous commit documented that as an open question.
Ran it live at container fidelity (2026-08-06, $0.2036, 1 turn):
no_skill_triggered: "skill-creator-plus" PASS
result: success PASS
mcp__skills__suggest_skills served
skillActivity []
toolCounts {} (agent just answered "Paris")
The served-tool line is the one that matters — it shows the run exercised the
post-flip surface rather than passing because the surface was absent. The
control holds, so the gate stays unpinned: production is ON and the harness now
models ON, making the unpinned run the faithful test.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KhZZyCWnhiNQfwRkX6CNWL
(cherry picked from commit 85eee1a6e78040c25272818872607d4e3ce00670)
The entry had grown to 1,909 words across 15 bullets — three times the largest prior release (0.8.0 at 641) and roughly fifteen times typical, with one bullet at 240 words, longer than three earlier releases combined. It read as an investigation log rather than release notes. Rewritten to 762 words. Removed: internal runtime symbol names, the measurement narratives behind each finding (probe counts, arm-by-arm figures, fidelity tiers), and self-critical asides about how long defects went unnoticed. Kept every change and every user-visible consequence. Section order corrected to Added / Changed / Fixed, matching 0.8.0; the entry had been Fixed / Changed / Added. Both breaking changes remain explicit: the listing-collapse-risk -> listing-desc-drop-risk rule rename, and advisories no longer gating --strict. Coverage re-checked against the full origin/main..HEAD diff rather than the commit log; the CI-only changes (lint severity flags, verify-cassettes --allow-empty) are folded into the harness-pin bullet where a contributor copying the recipe will see them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhZZyCWnhiNQfwRkX6CNWL (cherry picked from commit b868f608660e39edb7f1339db221343431fb868c)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every Claude-runtime claim in this repo was re-verified against the shipping Claude Code 2.1.222 binary. Four were wrong. Two real defects were found and fixed along the way, one of them a data-loss bug.
Highlights
Two defects, not just documentation
VIEWER_PID=$!andkill $VIEWER_PIDsat in separate shell invocations, so the variable was unset by the time it was read.Four corrected claims
contextWindow × 4 × skillListingBudgetFraction, not a fixed ~8 KB.allowed-toolsgrants permission rather than requesting it; the real gate is workspace trust.thirdparty-importwas a false positive onimport pandas.New
compaction-truncation-risklint rule — flags aSKILL.mdover the 19,900-character post-compaction limit. Exact rather than heuristic, because the cap is a fixed character count in the runtime.Breaking changes
listing-collapse-risk→listing-desc-drop-risk. Update any tooling that keys on the old name.check_portability.py --strict. Warnings and errors gate as before;--strict-advisoriesrestores the old behaviour.Verification
Tests (95),
quick_validate,check_portability,package_skill --dry-run, and the full cowork-harness static lane (lint-skill --strict,analyze-skill --strict, gated scenariolint,record --dry-run) all pass. The negative-control scenario was additionally run live to confirm it survives cowork-harness 1.18.0 flipping proactive skill-suggest on.Full detail in
CHANGELOG.md.After merge
Tag the merge commit to cut the release —
release.ymltriggers onpush: tags: 'v*', so the tag alone is what publishes: