You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
Added
kac validate reports its findings on the pull request under CI. Under GitHub Actions each error and warning
is also a ::error or ::warning annotation, and under Azure Pipelines a ##vso[task.logissue] line. On a pull
request with findings, validate posts one comment per corpus listing them, and later runs update it. It posts
only where the step has GITHUB_TOKEN with pull-requests: write, or SYSTEM_ACCESSTOKEN, and a failed post
leaves the exit code alone. Without the token, a run with findings prints a note and a clean run prints nothing. An
info finding and --json write neither, and a local run is unchanged.
kac new pins itself in .config/dotnet-tools.json. The tool manifest names the release of the kac that ran new, and kac update never compares, writes or reports it. Both starter pipelines install .NET SDK 10.0.402, run dotnet tool restore and then dotnet tool run kac, so each can take the token validate posts with. The GitHub
starter grants pull-requests: write and passes GITHUB_TOKEN to the validate step, and the Azure starter passes SYSTEM_ACCESSTOKEN. The starter's dependabot.yml gains a nuget entry, which proposes each new kac.
A record accepts a warning, with a reason.accepts: is a universal field listing a check and a reason for
each warning a record keeps. kac validate reports each accepted warning as info, reading accepted: and the reason,
so CI neither annotates nor comments on it. An entry naming an error, an info or an unknown check is the error acceptance-check, and one matching no warning is the warning acceptance-stale. The field never travels in an
export.
kac validate --since <ref> compares each record with its state at that revision. Records pair by id, so a
moved file still compares. immutable-after-accepted and immutable-after-published are errors on a change in
substance to a decided ADR or a published postmortem. A reflow, a link target, a typo or a move of status, superseded-by, review-by or accepts passes. retire-not-delete warns on a record deleted while in force. A ref
git cannot resolve exits 1. Without the flag, one line names the checks skipped. Both starter pipelines fetch the
full history and pass --since on a pull request.
kac validate --since <ref> keeps clause ids and rule ids.clause-id-kept is an error where a policy was active at the revision and a clause id it had there has gone, and rule-id-kept is the same for a standard's rule
ids. The message names the id and says to restore it or replace the record with a new one. A part added or reworded
passes, and so does a new title. A part whose id no longer parses is left to the id-format checks. A record that was
not active at the revision changes freely, and that includes a draft made active in the same change.
Changed
A required key in an entry needs a value.kac validate reports entry-key where a record's object entry
writes a required key with no value, such as reason: in accepts: or resource: in sources:. A template's
entries are exempt.
A tool can replace several others.replaces in tools takes a list of tool ids, one per line, so one tool can
take over from several. Each tool it lists names it as successor, and kac validate reports reciprocal where one
does not. A single id written on the line itself is now a list error. version: under export: in .schema/tools.yaml moves to 4.
A standard's rule is cited by its id, and a control names the rules it checks. Each rule heading opens with an id,
as ### PERMS: A job declares the permission it needs, and kac validate reports part-id-format on one without.
The export's part is that id and title drops it, while anchor stays the slug of the whole heading. verifies in controls takes rule ids, as std-CI.PERMS, and a bare standard id is a ref-resolves error. reciprocal folds a rule id to its standard. version: under export: moves to 3 in .schema/standards.yaml and
to 2 in .schema/controls.yaml.
kac report coverage names the rule.Covered by lists the rules whose Covers line cites the clause, and Controls lists the controls naming one of them. The review view kac bundle writes lists each control under the
rule it names.
A runbook, a process and a manual control say who did it.last-rehearsed and last-verified take the last
run, as { at: "2026-10-20", by: human:alex.doe }, or never. A runbook states method, live or tabletop, in
place of rehearsal-method, and kac validate reports walk-method-stated on a walk without one. by names a
person or an agent, never a process. A rule expression reads one key of an object field by a dotted path, as days_since('last-rehearsed.at'). version: under export: moves to 3 in .schema/runbooks.yaml and .schema/controls.yaml, and to 2 in .schema/processes.yaml.
Removed
changelog-begins-at-active and changelog-on-material-change leave the standards schema. Neither ran, and
a standard's type page no longer lists them as declared and not yet enforced.
Fixed
kac export, kac bundle, kac report --out and kac validate --json write the same bytes on Windows as on
Linux. Indented JSON and the body of a report ended their lines with CRLF on Windows, mixed with the LF written
around them. Each line now ends with LF on every platform.
A path kac reports uses / on Windows.kac report --out reports\clause-coverage.md printed the backslashes
and lost the grey folder prefix. Every wrote line, and each refusal of report --out, now prints /.
kac new and kac update delete their template clone on Windows. Git marks the files under .git/objects
read-only, and Windows refused to delete them, so each run left its clone in the temp folder.