v0.27.0
Added
-
The documentation site lists every skill, under Skills.
Sixteen of them across three trees, and which tree a skill lives in decides who can read it and what moving it
costs. The three tables are generated from the files that already decide the split:plugin.jsonfor what travels
inside a plugin,manifest.yamlfor what travels into a corpus, and the.claude/skills/directory for what stays
here.SkillReferenceTestsfails a stale table, so the page cannot drift from the manifests the way a hand-written
one would. Nothing aboutkacchanged. -
kac newandkac updatesend a corpus thewriting-a-reportskill. It joinstechnical-writingand
writing-a-recordin the overlay, under one rule: a writing skill travels where it governs a surface a corpus
holds. A corpus can adoptreports, so the skill that says how to fill a report's judgement cells travels with it.
writing-in-the-toolandwriting-the-docsdescribe C# and a documentation site no corpus has, andi-want-to
routes to this repository's own processes where a corpus reads its own throughprocess-lookup, so all three stay
behind.reports/_template.mdgains the four verdicts as well, for an author who opens the template and loads no
skill. Before this the wordsCovered,Covered by its pair,GapandOut of scopewere stated in one file that
never left this repository, so a corpus adoptingreportswas told to answer the judgement cells and nowhere told
with what.manifest.yamlmoves to 15, andkac updatestampsupstream.template-version. -
kac newandkac updatesend a corpus theharvest-findingsskill, which triages filed findings and drafts the
record one asks for.raise-findingfiles an observation as an issue and stops, so nothing moves it afterwards.
triagereads every finding without akac:triagedlabel, sorts each into one of five routes, shows a person the
table and writes nothing until they agree.draft <issue>takes akac:route-recordfinding and opens a pull
request carrying the record. Both invocations write: to the tracker, and to the records themselves. So the reader is
the corpus's own maintainer, and the skill lands in the corpus's working tree under.claude/skills/, beside the
writing skills. No plugin ships it, because a consumer holds a frozen export and not the source. It reads the
tracker,frameworkandpublishingblocks of.corpus.yamlfor the backlog, for where the tool is reported and
for where the record lives. A framework finding filed on a tracker other than the framework's own is drafted as a
comment and copied by hand, because an Azure DevOps user has no GitHub account.manifest.yamlmoves to 16, and
kac updatestampsupstream.template-version. -
kac validaterefuses a target the descriptor names and the tool cannot act on, under a new
descriptor-targetcheck.publishing-targettakes the five values the link rules are written for.tracker.target
andframework.targettakegithub,azure-devopsornone, because a wiki and a documentation site publish
records and hold no backlog. The message names the key, the value and the list it takes. Onlykac newheld its
flags to these lists before, and every one of the keys is written by hand after that, so a misspelling read as a
corpus that publishes nowhere and files nowhere. -
.corpus.yamlstates where work about its records is filed, under a newtracker:key. It takes atargetand
abase, the same pairframework:takes. A corpus that states no block gets the tracker itspublishing:block
implies, so a corpus on GitHub configures nothing: a repository there has an issue list of its own. State the block
where the backlog and the published form are two places. One Azure DevOps project holds one backlog and many
repositories, so a repository URL does not address the backlog, andkac exportderives the project from it.
manifest.jsonstates a tracker three times: for the corpus, for the framework, and for every entry insources.
Each one gains anid, which is the target and the base normalised, so a caller comparing two of them compares two
strings and never parses a URL.baseandidare bothnullwherever a block addresses no backlog, so a base is
never written beside a target that cannot use it.descriptor-versionmoves to 4, andkac updatestamps it. No
skill reads the key yet. -
.corpus.yamlstates where to report a problem with the framework, under a newframework:key. It takes a
targetand abase, the same pairpublishing-targetandpublishing.basetake.kac exportwrites the block
intomanifest.json, beside theidevery tracker there gains, so the address travels to whoever installs the
corpus as a plugin. Itsbaseis written the way every tracker's is, so an Azure DevOps base is the project holding
the backlog. Before this, the only address an export carried was the corpus's ownpublishing.base.
upstream.urlwas never one: it says where the template was copied from, and that is often a folder.kac new
writes the block, taking the base from--fromwhere that names a repository and from the framework's own
repository where it names a folder.descriptor-versionmoves to 3, andkac updatestamps it. No skill reads the
key yet. -
A
fixtakesstatus: draft, and a draft states no verification.verifiedis required of every other
status, so a session can write a fix from an observation nobody has checked andkac validatepasses. The type's
export shape moves tofixes@2, becauseverifiedarrives as null on a draft. A corpus listingdraftunder
export.exclude:in.corpus.yamlwithholds a draft, which is how an unchecked resolution stays out of
fix-lookup. -
fix-lookup, the skill that says whether a problem has already been solved here. It searches
symptom-keywords, which a fix over-fills with error text and the words somebody arrives with, then reports the
Symptom, Cause and Resolution the corpus settled. It states the record's derivedtruston every answer, so a
caller can tell a resolution a person checked from one an agent ran. A fix declares no part, so the skill searches
corpus/fixes/and the record is the unit. It ships in every corpus'splugin.jsonand leaves the bundle wherever
the export carries no fix. Take it withkac update --from <template>. -
raise-findingsearches the fixes before it files anything about a problem. Seven sessions meeting the same
problem should not open seven issues. Where the plugin has nofix-lookup, the corpus declined thefixestype and
the finding is the only route. Take it withkac update --from <template>.
Changed
-
A verification taken before
generated.atreaches no trust tier.kac exportderivedtrustfromverified
alone, so a report somebody read in March still shipped ashuman-reviewedafter an agent rewrote its verdicts in
September. Authorship now passes to whoever answers those cells, which movesgenerated.atpast every reading of
the words before them, so the exporter leaves an older entry out. A moment that will not parse still counts, because
timestamp-formatalready reports it against the record. -
A report's
generatedsays who wrote the content, and authorship passes to whoever edits it.kac reportwrote
itself intogenerated.byand left it there, so a report an agent finished credited the tool with the agent's
verdicts.bynow names whoever wrote the content a reader meets, which the Open Knowledge Format defines it as and
illustrates with a person. Two keys survive the handover:reportstates the report the run used, ascoverage, so
a record says whichkac reportname regenerates it, andtoolkeeps the version that wrote the mechanical half.
Both are optional, and a report nobody produced with the tool states neither.generated-by-a-produceris renamed
generated-by-a-known-actorand admits all three actor forms, sohuman:alex.doeis now a legal author. -
A report states no verification until somebody reads it.
verifiedwas required with at least one entry, so an
agent finishing a report had to name a verifier to get pastkac validate, and the two worked corpora each named an
agent that does not exist. The field now followsfixes: a draft states none, and every other status states one.
A report with no entry is the Open Knowledge Format's unverified tier, whichkac exportalready ships astrust. -
An accepted ADR is edited in place, and only a changed decision needs a superseding ADR.
immutable-after-acceptedallowed a typo fix, a link correction and a status transition, and nothing else. That
list left out an edit changing no decision. A sentence that no longer matched the decision the ADR already stated
read as forbidden. The rule now asks whether the decision changed, andadrs.mdsays to name the edit in the commit
message.immutable-after-publishedtakes the same shape for a postmortem, where a new understanding is a new
postmortem. Both are still declared and do not run, because telling a changed decision from a correction needs git
history. The Decided tier note in_tiers.yamldrops "never rewritten" for the same reason, so a corpus's
knowledge-as-code/taxonomy.mdchanges when you regenerate it.kac update --from <template>takes all three, and
kac generaterewrites the blocks under them.adrs.mdandpostmortems.mdseed a corpus, so the Immutability
paragraph on each stays that corpus's own to reword. -
kac exportreports every reason it refuses in one run. A type the corpus has not adopted, anexport-exclude
key it cannot act on, a consumed corpus nothing is restored for, a consumed corpus at another export format and two
corpora disagreeing about a type are each one line, and all of them print before the run stops. A shape or fidelity
line now ends with what to do about it. Before, the first of them stopped the run on its own. -
A finding
raise-findingfiles is the observation, and proposes no record. Itskac-findingblock dropsid
andexpires, which were a proposed discovery's own fields, and gainslooks-like. That key takes the type the
observation resembles,frameworkwhere what was noticed is the tool, the schema or a skill, ornone. Whoever
triages the issue gets the hint and keeps the decision.corpus,source,confidence,provenance,
applies-toandtagsare unchanged, and so are the body's three headings. Take it with
kac update --from <template>.
Removed
- The
discoveriestype and theobservedtier. A corpus no longer keeps an unverified observation. One goes
into whatever tracker that corpus already uses, and what the corpus keeps is the answer somebody settled and
verified.kac newwrites one type fewer, andkac validatecounts one template fewer.fixesandstandards
droppromoted-from, so a record that still has that key failsunknown-key;sourcesstates where the content
came from instead. Aschema-shapemessage naming the tiers now offers four. Take it with
kac update --from <template>, which deletesdiscoveries.md, the folder and the schema file.
Fixed
-
kac exportpublishes a grandparent's record files down a chain three corpora deep. A consumer read only the
record files sitting directly in an imported type's directory. The records its producer had inherited were dropped,
and their part lines reached the next corpus naming files that never arrived.kacnow reads the folders a producer
filed those records in, and files each record under the corpus that wrote it. A corpus consuming both a producer and
that producer's own producer meets one record twice, and writes and counts it once.sourcesalready listed the
grandparent, and still does. -
kac validateresolves a citation into a corpus reached through another.gp:pol-OLDwas reported as a
shortcode this corpus consumes nothing under. The reader behindvalidateskipped the folders an export files an
inherited record in, and filed what it did read under the corpus it arrived through. A record is now found by the
shortcode of the corpus that wrote it, whether this corpus declared that corpus inconsumes:or not.
eng:pol-OLDcorrespondingly stops resolving, which is whatref-resolvesalready says about a record eng does not
have. While a declared import is unrestored, a shortcode nothing here knows is left toimport-restoredinstead of
drawing a second finding telling the reader to declare it. -
kac report coveragecredits a grandparent's standard against the clause it implements. A record file keeps the
ids its own corpus wrote, and the edge was scoped to the corpus the record arrived through. The clause read as a gap
and the standard covered nothing, because the clause lines are scoped to the corpus that wrote them.