The README shows who writes the bundle and what checks it. The diagram that docs/for-the-curious.md added in 0.31.0, .assets/ktl-architecture.svg, replaces the README’s lifecycle diagram, since the opening card already shows the order the roles first run in and the loop back to the librarian. Its headings now say what happens: each in one way only and what is written, where they said each through one door and what lands.
The README says what a docent, a registrar, an accession and the sidecar are where it first names each, and links the bundle’s glossary. A docent is a museum’s name for a guide, and the README pointer that ktl-sidecar installs says so too. A registrar is the person in a museum who keeps the collection’s records, and an accession is an item added to the collection. The sidecar is .lokf/, a folder beside the code and kept out of the project’s build. The glossary now defines all four, and desk, the README’s word for the place where a role does its work.
ktl-prose keeps one topic to a paragraph, and says what happens in plain words. Rule 3 now covers the paragraph: split one that runs past 150 words where its topic turns, the limit the Federal Plain Language Guidelines give. prose-check.py reports it as paragraph, and never counts a table cell. Rule 9 now asks for the literal verb: a key is “added”, not “landed”, and an IRI is “built”, not “minted”. The script reports seven such figures under words, and the rules page lists the rest with their plain words. A word of the analogy a project names its roles by, such as the librarian’s desk, stands once the project’s glossary defines it. ktl-librarian’s rules for a concept body say the same.
prose-check.py reports a character no reader sees, as unseen. That is a control character other than a tab, or a format character such as a zero-width space, a byte order mark or the right-to-left override the “Trojan Source” attack hides code behind. An agent that types such a character’s escape into a tool call can write the character itself. The script reports each line that holds one, code and frontmatter included, and its comparison refuses a rewording that adds one. Check 18 exercises both.
Changed
In a live session, ktl-librarian opens its pull request only when the person says so. The person who started it is the change’s author and submits it, as the AI covenant says. A scheduled run’s workflow still opens its own. ktl-curator’s review session ends the same way.
The docs, the skill pages and the script comments read plainer. A third pass replaced figures of speech, such as “lands”, “mints”, “ships”, “arms”, “wires” and “lays down”, with what happens. It split every paragraph and comment block past 150 words, and took the dashes and long sentences out of the script comments, which no pass had read before. No fact changed. The captured docent answers, the released changelog entries and the messages the scripts print stay as they were.
Security
The contract fails on a character a reader cannot see in any tracked file. Check 21 searches every tracked text file for a control character other than a tab, and for a format character such as a zero-width space, a byte order mark or a right-to-left override. A diff shows none of them, and GitHub warns of only some. Typed escapes once put three of them into a sanitizer here, as the characters themselves, and only a search by hand found them. Code that needs one spells it as an escape.
A scheduled week with nothing waiting for the librarian runs no agent.knowledge-report.sh quiet exits 0 when no source moved since its concept’s stamp, no person left a note since the librarian last stamped that concept, every concept carries a stamp, and no reader feedback waits. The wrapper asks it before a scheduled run, which KNOWLEDGE_SKIP_QUIET allows, and calls no agent when the answer is quiet. A scheduled run in a month’s first seven days goes ahead regardless, since the work list never fetches a source given as a URL. So does a run a person starts. Check 20 and the layout tests exercise it.
The librarian’s hand-off reaches its pull request. The patch file may carry handoff, up to ten lines for the reviewer in the agent’s own words, such as a send-back that came up twice or a source that did not answer. The pen holds each to one line of printable text with no backtick, and writes none of it to the bundle. publish cleans the lines again and shows them under From the librarian, in a code block, where nothing renders. A scheduled run’s hand-off stayed in the job log until now.
Conventions rule 13: a confirmed concept still says what its person confirmed. After the commit that recorded the latest confirmation, a change to the concept’s body or claims must move generated.at past it, so the concept reads edited since. The pen always restamped, and the gate now fails a hand edit that does not. The rule compares parsed values, so a requoted value is no change, and it leaves out the open questions, KTL Registrar’s block and the trust fields. It can miss an edit, and never flags a concept its person saw. Check 11 exercises it.
Changed
ktl-librarian’s page is half as long, about 3,700 words where it had 7,458. The Golden Rules’ tables, the first run’s sweep and the audit’s detail moved to references/golden-rules.md, references/bootstrap.md and references/audit.md, which an agent opens when a step needs them. The by-hand fallbacks for a host without the pen are gone, and such a host runs ktl-sidecar’s repair first. A note from a person that the librarian reads now leaves its stamp on the concept, so the quiet check knows the note was read.
Security
The workflow reads the retrieval score and the hand-off only as the wrapper’s programs wrote them. The wrapper wrote the score file only when it scored, so an agent could leave its own n of m there for the pull request, or a link that sent the next write into the checkout. The wrapper now removes both files once the agent returns.
docs/for-the-curious.md shows who writes the bundle and what checks it. A new section and diagram, .assets/ktl-architecture.svg, give each writer’s one door. The librarian’s patch file goes through the pen, the curator’s verdicts through ktl-curator or the KTL Curator plugin, and a reader’s miss through the docent’s feedback recorder. Below them sit the registrar’s gate and the report script. The README now says why knowledge-apply.sh is called the pen where it first names it, and the bundle’s glossary defines the term.
Check 16b keeps KTL’s roles, skills and repositories from being named after LOKF. LOKF is the format, its schema and its toolkit. The changelog, the bundle’s log and the source map’s dated notes keep what was written at the time.
Changed
The pages name Knowledge Trust Ladder (KTL), the bundle and LOKF apart. KTL is this design, with its roles, skills, scripts and gate. The bundle is the corpus it keeps in .lokf/knowledge/, and LOKF is the format and its toolkit. docs/wikiskill.md, docs/three-lines.md and docs/three-lines-critics.md used a bundle or LOKF where they meant the design, so a reader could not tell the design from its corpus, or from the paper’s wiki. The contributing guide, the signing page, two sidecar references, the issue templates and five bundle concepts follow, and references/trust-fields.md no longer says whoever held the pen, now that the pen names a script.
Each skill’s heading is its name, such as # ktl-curator.# KTL Curator was also the Obsidian plugin’s name. Where Obsidian is the scope, the pages now say the KTL Curator plugin.
Fixed
The trust ladder’s middle rung credits the librarian’s refresh, not the schema check.Checked by automation only means a verified event with a process: actor, which a scheduled refresh writes after it reads the source again. The diagram credited lokf validate, CI and the KTL Registrar plugin, none of which writes one.
The three-lines diagram names every part of the registrar. Its second line gains the pen and the report script, which docs/three-lines.md already listed, and its title says KTL role. The two-vaults diagram shows services/, a folder the sidecar lays down, where it showed concepts/.
The preflight reports ktl-prose. Its two skill checks listed four skills, so it never reported the fifth or a stale copy of it. Its note for a host without uv now counts seven of the twelve conventions, where it said six of eleven.
docs/signing-commits.md says a signature is required to remove a confirmation, as to add one. The gate has held removals to the same evidence since 0.30.0.
scripts/sync-sidecar.sh lays down what a synced copy cannot run without. It only reported a template the sibling had never laid down. So a sync to 0.30.0 carried the new wrapper, which refuses to start without the apply script, and left the apply script and the report script out. It now lays down a template that ktl-sidecar puts on every host, and one that a copy already in the sibling cannot run without. That is a script a workflow runs, the apply script beside the wrapper, or a Python half beside its shell half. It reports any other, as before.
The pen keeps an index in the shape a person gave it.knowledge-apply.sh took any bullet that held a concept’s link for that concept’s own bullet, so a reindex, set or delete of one concept rewrote or removed a line that listed several. It looked for a folder’s section under a # heading only, so a root index with ## sections gained a second section at its end. It now rewrites every line that holds the concept’s link alone, and leaves a line that lists it among other links or names it in a sentence. It takes a deleted concept’s link out of a list of links, and refuses the delete while a sentence links it. It finds the folder’s section at any heading level, or by the section’s link to the folder’s index.md, and never under the title. Conventions rule 12 reads a line that lists two concepts the same way, as neither one’s bullet. Check 19 exercises each case. ai-linkmo’s sync to 0.30.0 found the defect, since its root index lists concepts this way.
knowledge-report.sh computes what the skills used to work out. It prints each concept’s trust label, the bundle’s health line, ktl-librarian’s work list and what a change does to the record, from frontmatter and git history, in bash and awk. ktl-curator’s Step 1 and ktl-docent’s footer quote it. The librarian workflow’s publish job fills its pull request from it, on its own checkout. A source has moved when history, not a clock, puts its last commit after the one that recorded the event. Check 20 exercises it.
A retrieval score, off unless KNOWLEDGE_RETRIEVAL is true. On a scheduled run that changes the bundle, the agent picks from index.md alone the concepts it would open for each question readers asked, and knowledge-report.sh scores the reply by program. The pull request carries the result as n of m. It reports and gates nothing.
A ledger of the questions readers asked, .lokf/questions.md.knowledge-apply.sh moves each handled feedback entry there: the day, the kind, the concept that now answers it, and the reader’s question from the operation’s asked key. It only grows, and programs read it.
The pen gains resolve and --format.resolve withdraws an open question the librarian itself asked, and never a person’s note. --format prints the patch file’s shape, which check 19 holds equal to references/patch.md.
Conventions rule 12: an index bullet carries its concept’s title and description. The pen keeps the three copies equal for a concept it writes; the gate now fails when another hand leaves one behind, and a reindex operation repairs it.
Changed
ktl-librarian starts a refresh from the work list, and reads a local source again only when it moved. It leaves a note that a later confirmation answered to the curator, withdraws its own answered questions, and keeps a reader’s words out of log.md and out of every concept. When a count or a name changes in one source, it searches the bundle for the old value, which the curation of 2026-10-03 asked for.
The health line counts a concept edited since its confirmation once, under Edited since confirmed, and no longer under Confirmed by a person as well. The person confirmed an earlier text.
ktl-curator clears answered open questions on Correct now too. Its report lists apart the questions a person’s later confirmation answered, and the confirmed concepts whose source moved after the confirmation.
The scheduled pull request is filled by the job that opens it. The health line and what the change does to the record come from knowledge-report.sh in publish, and nothing but the retrieval score’s two integers comes from the job that ran the agent.
Fixed
A sidecar laid down from 0.29.0 paired the new wrapper with a skill that predates the pen. The template pins the skills one release behind, and the wrapper’s prompt named references/patch.md, which that release lacks. The prompt now takes the format from knowledge-apply.sh --format, and the wrapper says so when the pinned skill is older. A host already laid down from 0.29.0 moves TRUST_LADDER_SKILLS_REF to v0.29.0 or syncs to this release.
docs/wikiskill.md said the paper’s ablation ran on five benchmarks. Its Table 3 has four.
A from_feedback line that feedback.md does not hold is a finding, not a traceback.
Security
A person’s record is never removed without that person. The provenance job and knowledge-provenance.sh ask the person behind a verified event that a change removes, struck out or gone with its concept, as they ask the one behind an event it adds. A person’s generated record may give way only to another person’s. Before this a pull request that deleted a confirmed concept passed the gate.
publish reads a person’s events off the patched tree.knowledge-provenance.sh --unattended refuses a person’s event added, changed or removed in any YAML layout, a person’s note added or removed, and a change to text a person wrote. The line pattern it replaces as the backstop saw a block-style by: human: line only. The wrapper runs the same check after the pen.
The pen refuses to delete a concept a person left a note on, as it refuses one a person confirmed.
A reader’s words no longer reach log.md. The librarian quoted a reader’s question there since 0.29.0, and ktl-curator opens that file to add its line. The question now stays in the ledger.
A fifth skill, ktl-prose, rewords a bundle’s agent-written concepts in plain English. It rewords only a body an agent wrote and no person confirmed, and changes no fact and no frontmatter byte, so generated keeps naming the librarian. Its prose-check.py reports dashes, long sentences and stock phrases, and proves a rewording changed only wording. Check 18 exercises it.
docs/wikiskill.md reads the WikiSkill paper (Tang et al., Google Research, 2026) against this design, part by part. The captured docent answers in docs/examples/docent.md now link the concept behind each question, so the link checker fails the build when that concept is renamed or deleted.
knowledge-apply.sh, the librarian’s only pen. ktl-librarian describes each change as one of seven operations in .lokf/patch.yaml (references/patch.md), and the script writes the files. It stamps generated, keeps each description equal to its two index bullets, files the log line, and refuses a human: actor, a rewrite of a person’s text, or the deletion of a confirmed concept. Nothing is written unless every operation passes. Check 19 exercises it.
Changed
ktl-librarian writes in plain English, and offers a plain-prose pass in a live session. A paragraph in its section 1 gives the rules for every body, description and index bullet, so a new concept needs no rewording. Before it opens its pull request in a live session it offers the ktl-prose pass, whose time is before a person confirms. An unattended run skips the offer.
ktl-librarian reads the curator’s verdicts before it derives, and closes the loop on a reader’s miss. It re-derives a sent-back concept from the source the note names. A miss that an existing concept answers is a description defect, fixed in the description and both index bullets, never with a twin. A run handles at most ten feedback entries. Rule 3 reaches a Person or Organization through author or publisher, not source.
Fixed
A concept edited after a person confirmed it is no longer read as confirmed. ktl-docent and the Copilot docent gain the label edited since a person last confirmed it, which the curator and the Obsidian plugins already show. The docent says the edit first, gives both dates, and treats the concept as unconfirmed.
ktl-curator compares the two times of “edited since” whole.references/trust-fields.md told it to cut both to the day first, so a concept confirmed in the morning and rewritten that afternoon did not count as edited. The Obsidian plugins and the SPARQL query already compared whole times.
The skills no longer claim a SHACL check that nothing runs. ktl-librarian, ktl-sidecar and docs/three-lines.md said the bundle was validated with JSON Schema and SHACL. The toolkit generates the shapes and neither ships nor runs them, so the wording now names what runs: lokf validate (JSON Schema) and --check-refs.
Security
The scheduled librarian never writes the bundle itself. The agent’s one output is .lokf/patch.yaml; knowledge-librarian.sh applies it with knowledge-apply.sh and refuses a run that touched any other file, so the refusals above hold in the unattended run and not only in prose. The threat model’s hardening list names it.
Release assets can carry a host’s published name.knowledge-release.yaml names its zips after the KNOWLEDGE_RELEASE_NAME repository variable when it is set, and after the repository otherwise, so a host whose package is published under another name, such as gist as gist-linkml, ships assets under that name.
The Snyk W011 findings on ktl-librarian and ktl-docent are acknowledged in each skill and the threat model. The librarian resolves only what a feedback entry names, and the scheduled publish job refuses any other path and any by: human: claim. The docent quotes repository text it did not author and writes only a scripted feedback entry.
atk add skill works with the released Agents Toolkit. The 1.1.17 release hides the command behind TEAMSFX_AGENT_SKILLS, not ATK_FRONTIER, which only the 1.1.18 betas read, so the documented line failed with UnknownCommandError. docs/m365.md, the sidecar’s references/m365.md and the Copilot playbook now set both.
The toolkit route in docs/m365.md runs in the agent’s project. The steps change into the folder atk new creates, pass --env dev to provision and preview, and skip atk validate, which rejects agent_skills against the v1.8 schema. Both variables are exported for the session, since provision packs the skill’s files only while one is set.
docs/m365.md says what a tenant without custom skills sees. The reader checks for the Frontier preview first. Without it, atk provision fails with Unrecognized member 'agent_skills' and Agent Builder sends the skill to Copilot Studio, which needs its own licence. The troubleshooting list quotes both.
Releases carry the docent as a Microsoft 365 Copilot skill.knowledge-release.yaml attaches ktl-docent-m365-<tag>-<repository>.zip beside the bundle zip, for upload to Agent Builder. The new .lokf/m365/ folder holds its instructions and knowledge-m365.sh, which packs a reproducible zip within Copilot’s limits. Check 17 builds it.
scripts/sync-sidecar.sh syncs a sibling repository to one release. It copies a published tag’s templates over the sibling’s copies, moves its skills pin to that tag, runs the sidecar’s checks, and leaves the diff for review. docs/releasing.md drops the hand bump of the template’s own pin, which the release commit has made since 0.23.1.
Conventions rule 11 rejects an at: later than the commit that recorded it. Local time labelled Z and round placeholders had put 28 times in this bundle ahead of their commits, so concepts read as edited after a person confirmed them. ktl-librarian and ktl-curator now take every at from date -u.