Stable release. The release branch ran as a pre-release candidate on the maintainer's own setup for a full week (2026-08-21 → 2026-08-28) before merging: every session wrote to the new per-file log, two scheduled reviews ran against the new format, and no id collisions occurred across parallel sessions.
The breaking change
The observation log is now a directory, not a file: skill-observations/observation-log/, one small Markdown file per observation with a YAML frontmatter header, and resolved observations under observation-log/archive/. Creating an observation never touches another entry's bytes, so the numbering ritual, the bounded-mutation rules, the invariant check and the survival check of the single-file log are gone rather than relocated — about a hundred lines of SKILL.md deleted by making them unnecessary. Scans read only the frontmatter, so the always-on session-start pass stays cheap as the backlog grows.
Upgrading: the first session with 3.0 installed finds your old log.md, runs scripts/migrate-log.py (check-only first, then convert, flagging anything it is not sure about instead of guessing) and keeps the old file as log.md.migrated. references/migration.md has the procedure and the rollback. Fresh installs never see any of this.
Thanks to @ebertti, whose pull request #35 is the basis for this. Two things differ from the PR as submitted and are declared in the merge commit: skill: is always a list and a separate proposes_skill: list replaces the new-skill sentinel; and the migration is a script.
Added since the release candidate
A week of running the candidate produced its own round of improvements, plus contributions that arrived during the trial:
- Enforcement triggers must hang on events visible in the tool record (PR #56 — @notbucki): the capture checkpoint bound to todo completions is inert in sessions that never use todos; project-completing commands (deploy, release, publish, push) are now flush points too, and "is this a major deliverable?" is named for what it is — a self-assessment that fails under load.
- A deferral needs a nameable criterion, not a plausible reason (PR #57 — @notbucki): "let's wait for a few days of real use" reads as diligence, which is why nobody challenges it; before writing any "later", name which observation would change the decision and when it could realistically arrive.
- The pre-delivery gate resolves its path (#61 — fix designed by @leobaray): running the gate script from inside a bundle directory (
.or./) false-failed a correct bundle becausePath('.').nameis the empty string. - Load is not activation (thanks to a detailed field report from @kai-tecweb): the recommended activation block now demands the Session Start Protocol by name, not just the skill load, and adds a post-task backstop — check the session's observation records and report a one-line summary — so a session that silently skipped the protocol is discovered at the first task boundary instead of never.
- Sibling propagation: observations carry a mandatory
siblings_checkedfield resolved against a skill-family registry at write time, so an insight found in one member of a skill family reaches its siblings instead of silently diverging. - A
parkedstatus: decided-but-blocked observations leave the work queue without pretending to be resolved;parked_untilnames the condition that unparks them. - Loud-on-failure scans: the session-start scan and id derivation distinguish "the log is empty" from "my command is broken", with independent existence checks and hard stops.
- Configuration vs process — the three-container rule (skill-authoring): a skill needing person- or installation-specific values reads them from a private config file, keeping the skill generic and the invoking prompt a thin trigger; safety duplication in prompts becomes a stop condition rather than a copy, because a copy can drift out of agreement with its source and a refusal to proceed without the source cannot.
- Verify subagent judgements, not just their values (weekly review): a delegated agent's reported conflict, defect or readiness verdict must be spot-checked against the source before it reaches the user as a finding — a wrong value fails loudly downstream; a wrong characterisation is consumed by being agreed with.
Also in this release (unchanged from the candidate)
- Activation, honestly documented (#20, #21, #22, #34 — @scorpiomic, @michaelkariuki): three tiers, only the hook is enforced, trigger worded as "before the first tool call", fires before planning; a sample
SessionStarthook injects the open count and review staleness. - Workspace anchoring that survives a by-the-book setup (#18, #19, #41, PR #51 — @scorpiomic, @duran14, @notbucki): the activation block pins an absolute path and carries the constraints; search before creating a log.
- Environment-agnostic procedures (#17, #23, #32, #45, #47, #52, PR #37 — @monroyd, @seqorasecurity, @supervixens, @aritamoseti59-dev, @itsdaniik, @daddison1981-droid, @justonesec): one environment table, write targets classified by durability, the read-only guard named as Cowork-only with cp+diff as the opening move, retries before declaring a log unwritable, priced writes in shared document stores, offline policy for scheduled runs.
- A delivery gate that asserts (#26, #28, #43, PR #27 — @bapinoko-sudo, @14maxwjo, @aritamoseti59-dev):
scripts/validate-skill-bundle.pychecks what the installer enforces — description cap, name/directory match, forward-slash member paths on raw bytes — and packs a well-formed bundle on any platform. - Portable snippets and version control as a mutation surface (#16, #24, #25, #31, #36 — @monroyd, @jazorro11, @rlucho, @14maxwjo, @thanhvu-create). #40 is dissolved: there are no backups to prune.
- Observation quality gates (#30, #33, #38, #39, #42, #44, #53 — @14maxwjo, @dubes394, @minorum, @aritamoseti59-dev, @waylooking-hub): generalisability test, targets validated at write time, candidates deduplicated, status set in the same turn you act, presence check and classify-before-ask in the review, a
supersededstatus. - First-run backfill (#29 — @14maxwjo) and a staging manifest (
skill-updates/PENDING.md) with git as an optional staging medium (proposed by @Sloppy0726 after PR #7). - Review approval (PR #48, PR #49, PR #50 — @notbucki): a declined prompt is a stop signal; direct-apply means now, never in place; a feedback pre-flight before drafting any issue or PR.
- Progressive disclosure: SKILL.md is reorganised around the rules that matter on every turn;
references/observation-log.mdandreferences/signals.mdare new, and every pointer names its load trigger. - CONTRIBUTING.md, written from how these changes were actually handled.
Still open: #46 (bounding root-cause investigation — discussed in the issue), and the issues filed during and after the trial week, which are queued for the next cycle — activation verification, platform portability beyond POSIX shells, and review/install drift are the three big themes.