The registrar gate resolves a revision. A sixth rule: a commit-shaped revision on an event must name a commit that holds the concept’s local resource, so the skills pin with the full hash; the validate job checks out the full history, and a shallow clone is reported rather than passed. Check 11 proves both outcomes in a throwaway repository.
Portability pages for the curator and the librarian, and the sidecar’s rewritten as a host matrix. What works, what is lost and the substitute on GitHub, GitLab, Forgejo, no forge, no git, Windows and PowerShell, macOS, synced folders and an Obsidian vault.
Every skill declares what it needs in the Agent Skills compatibility field; check 3b holds it to the spec’s 500 characters.
A forge-free provenance gate.knowledge-provenance.sh verifies each confirmation’s commit signature against the curator’s public key on file under .lokf/curators/, GPG with its subkeys or SSH, with plain git and gpg or ssh-keygen; check 13 proves each outcome with throwaway keys.
A prerequisites page gives each preflight line its plain meaning, who fixes it and what to send them, for a person who cannot act on it themselves; check 12 holds it to every line the preflight can print.
A preflight every skill runs first.knowledge-preflight.sh prints what this machine can do, from shell and git to identity, signing, keys on file and toolkit, and ends by naming what is missing and which steps that disables; check 12 exercises it.
The sidecar lays down .lokf/.gitattributes, keeping the bundle on LF so a Windows checkout gives CI’s verdict.
Three more conventions the gate checks: one file per id, lowercase paths, and a closed frontmatter block with no byte order mark; check 11 proves each.
Changed
The skills use lokf 0.9.0+’s revision. The curator writes it on a confirmation, the librarian on generated, and the docent quotes it beside the date. An older toolkit leaves it out. The librarian’s tables also name a source’s excerpt.
The sidecar’s toolkit floor is lokf 0.8.0, here and in the lokf-sidecar template. The librarian’s field tables now state its constraints: sources[].author is an actor string, http_method is one of seven uppercase verbs, and every timestamp including stale_after is a datetime, a bare date meaning midnight UTC.
The curator says what it can record before offering a session, from a Ready to record line with three identity routes - gh, glab, the signing key the forge lists - and a rule for a host with no forge. The librarian names files in lowercase and hands off on a host without git; the docent’s feedback attribution names the same routes.
Six of the conventions script’s ten checks now parse YAML for real.knowledge-conventions.py, run through uv run, replaces grep and awk where they missed flow-style events. The other four stay shell, and without uv the script says which rules it skipped. The preflight reports a host holding one half without the other, and check 11 proves each rule.
Fixed
The librarian’s version check names a command that exists: uvx --from pip pip index versions lokf, since uv pip index is not a subcommand.
A Windows checkout no longer blinds the conventions script. It reads files with CRLF and a byte order mark stripped, and check 11 holds a CRLF bundle to the same verdict as LF.
A bundle reached through a link is read, not passed unread.find never entered a linked .lokf/knowledge, so the conventions script and the preflight saw zero files; checks 11 and 12 plant one.
The preflight reads commit.gpgsign as git does, taking yes and 1 as on and no user.signingkey as git’s default key; all three scripts stop on one line under sh.
The gate refuses a human: id it cannot look up. The schema accepts human:-x, and both the GitHub job and the forge-free script skipped such ids as unparsable, so an unsigned confirmation under one passed unseen.
The gate reads a confirmation whole, not its by: line. Re-dating an existing event, moving its revision, or writing it in flow style left no added by: human: line and passed both gates; events are now compared whole between base and head, keyed by the concept’s id, so a renamed concept keeps its confirmations and a copied one does not. Check 13 proves each.
The conventions script no longer aborts on a runner that ignores SIGPIPE. GitHub Actions starts every step that way, so an awk that closed the frontmatter pipe early turned into a tr: write error that pipefail made fatal on the first long concept; the script now reads each file whole, and the contract’s own job installs uv so the parser’s half runs there too.
A confirmation spelt with a YAML tag, anchor, alias or quoted key was invisible to both gates while lokf validate accepted it. Conventions rule 10 now holds id, by, at and revision to spellings a line reader and a parser agree on, so the validate check fails such a concept before the provenance check could miss it; check 11 proves it.
Both gates read merges, generated, and only the frontmatter. Events are now read against every parent of a commit, from verified and generated and nowhere else, so a merge can no longer slip one in and an example in a body code fence no longer counts. Check 13 proves each.
A push to main between releases no longer promotes ## [Unreleased] a second time. When the top released version has no tag yet, changelog-release.mjs promote folds new entries into it by subsection instead of writing a second heading. The plan job also runs check directly, because semantic-release skips its plugin hooks on a pull request. Check 14 proves it.
publish.yml installs uv, so a release can pass the contract it runs. Six conventions rules run through uv run, and without it no release could reach the tag. The contract now names that cause in one line up front.