Consistency audit compliance¶
Prompt¶
Before responding to questions or discussion points in this
document, explore the kerbside codebase thoroughly. Read
relevant source files, understand existing patterns (the CI
workflows under .github/workflows/, the pre-commit
configuration in .pre-commit-config.yaml, the review
tracking tooling in tools/review-tracking.sh and
REVIEWS.md, the vendored sfui copy under
kerbside/api/static/sfui/, and the shared blocks embedded
in PLAN-TEMPLATE.md and PUSH-AUDIT.md). Ground your
answers in what the code actually does today. Do not
speculate about the codebase when you could read it instead.
Flag any uncertainty explicitly rather than guessing.
All planning documents should go into docs/plans/.
Consult ARCHITECTURE.md for the overall proxy architecture
and AGENTS.md for build commands, project conventions, and
code organisation. This plan is unusual in that most of its
authority lives in another repository -- read the audit
specification before implementing any phase, because the
issue text is a generated summary of it and has already been
shown to be stale or wrong:
shakenfist/development-- the canonical audit specifications underdocs/audits/, the canonical shared blocks undertemplates/shared-blocks/, and the checker itself inscripts/audit-check.py. A finding is only as good as the check that produced it, and one of the six findings this plan opens with turned out to be a defect in the checker rather than in kerbside.shakenfist/sfui-- the canonical design system, vendored intokerbside/api/static/sfui/by that repository'stools/vendor.sh.shakenfist/actions-- the shared Claude Code review automation that supersedes the retired comment addresser.
When we get to detailed planning, I prefer a separate plan
file per detailed phase. These separate files should be
named for the master plan, in the same directory as the
master plan, and simply have -phase-NN-descriptive
appended before the .md file extension.
I prefer one commit per logical change, and at minimum one commit per phase. Do not batch unrelated changes into a single commit. Each commit should be self-contained: it should build, pass tests, and have a clear commit message explaining what changed and why.
Situation¶
A daily consistency audit runs in shakenfist/development
against every repository in the ecosystem, checking each
against a set of specifications under that repository's
docs/audits/. Where a repository fails a check, the audit
files a GitHub issue labelled consistency naming the
audit, linking its specification, and quoting the automated
check's own description of what is missing.
Kerbside carries six such open issues, filed between 2026-08-03 and 2026-08-28:
| Issue | Audit | Finding as filed |
|---|---|---|
| #227 | Human review coverage | 0 of 152 in-scope files reviewed at HEAD; 152 need review (threshold 5) |
| #359 | LLM context linting in pre-commit and CI | skillsaw does not run from a CI workflow |
| #360 | CI review automation | the retired comment addresser is still deployed |
| #368 | Plan template | missing shared block plan-push-audit-phase |
| #370 | Pre-push audit file | missing shared blocks path-traversal-review, python-version-discipline, functional-test-coverage |
| #373 | sfui vendored copy | 2 commit(s) behind canonical |
This plan file previously existed under a different remit.
From 2026-07-16 it was a standalone plan called Consistency
audit deferred work, tracking five checkboxes for GitHub
settings that could only be changed through the web
interface. Three were completed and verified in July; two
remained. That plan never grew to cover the audit findings
themselves, so the six issues above accumulated with no
planning document tracking them, while a document named for
the consistency audit sat at In progress describing
something much narrower. This rewrite promotes the file to a
master plan covering the whole compliance backlog, and folds
the two surviving checkboxes into phase 1 as the residue
they are.
What the survey found¶
Every finding above was checked against the tree on 2026-08-29 before this plan was written, rather than being taken from the issue text. Four of the six survived intact. Two did not, and both corrections change what the work is.
#359 is a defect in the checker, not in kerbside.
Kerbside runs skillsaw in CI.
.github/workflows/functional-tests.yml lines 267-272
install skillsaw==0.18.0 into the test venv and run
skillsaw --no-custom-rules . in the sanity_checks job,
and .pre-commit-config.yaml lines 54-57 carry the hook at
the matching rev. The audit's own specification says
outright that "how skillsaw is invoked is deliberately not
pinned", but check_llm_context_lint_ci() in
scripts/audit-check.py (lines 5571-5626) passes the CI
half only if a workflow mentions the literal string
stbenjam/skillsaw outside a comment, or runs pre-commit
run. Kerbside does neither: it installs from PyPI, and the
one mention of stbenjam/skillsaw@v0 in the workflow is
inside a comment, which file_mentions() deliberately
excludes. The checker already carries an escape hatch for
exactly this shape -- its comment at lines 5396-5402 notes
that development's own consistency-audit.yml "installs
skillsaw from PyPI and so never names the upstream
repository either" -- but that hatch is spelled as
pre-commit run, which kerbside does not use. Kerbside's
workflow explains at length (lines 249-255) why it cannot
use the composite action: stbenjam/skillsaw@v0 opens with
actions/setup-python pinned to 3.11, actions/python-versions
publishes no Debian 12 build, and these runners carry no
tool cache, so the action fails before it lints anything.
That reason is real and is not kerbside's to fix. The remedy
is upstream, in development, and phase 3 carries it.
#227 is badly out of date, in kerbside's favour. The
issue was filed on 2026-08-03 and says 0 of 152 in-scope
files reviewed. tools/review-tracking.sh status at HEAD
reports 124 of 194 in-scope files reviewed, 70 needing
review. The backlog is real -- the threshold is 5 -- but
it is a third of what the issue claims, and the issue's list
of missing files names paths that no longer exist
(.claude/skills/add-database-migration.md is now
.claude/skills/add-database-migration/SKILL.md, and
alembic/versions/ moved into the package during
demo-install phase 1). Nothing needs correcting at the
source here: the audit recomputes coverage against HEAD on
every run and re-states the issue body, so the staleness is
in the rendered issue text rather than in any file this
repository owns. It is recorded here so that a reader sizing
phase 4 does not budget for 152 files.
The other four held, with two details worth carrying into the phases:
- #373 is a provenance stamp bump and nothing else.
kerbside/api/static/sfui/.sfui-commitrecords190383aecb31; sfui's default branch (develop, notmain) is atc3f65ae0aa0d. The diff between them touches exactly one file,.github/workflows/renovate.yml, whichtools/vendor.shdoes not distribute. Re-vendoring will therefore change the stamp and no asset. That makes the phase cheap, but it also means the usual justification for re-vendoring -- propagating an improvement -- does not apply, and the change must be defended on provenance grounds alone. - #360's deletion is wider than the four files it
names. Beyond
.github/workflows/pr-address-comments.yml,tools/address-comments-with-claude.sh,tools/render-review.pyandtools/review-schema.json, the tree also carrieskerbside/tests/unit/test_render_review.py, which importstools/render-review.pyby path and would fail at collection the moment the script goes; a row in.claude/CLAUDE.md(line 139) listing the workflow; three cross-references in.github/workflows/pr-re-review.yml(lines 10, 34 and 106); one intools/shellcheck-wrap.sh(line 7); and four review marks plus their weaudit entries. Deleting only the four named files leaves a repository whose unit tests do not run.
Corrected during phase 2 planning: this bullet
originally named one pr-re-review.yml reference and no
shellcheck-wrap.sh reference. The line 34 one is the
awkward case -- it is the stated reason for a live
if: guard that must outlive the workflow it cites.
The two surviving GitHub-settings checkboxes were also re-checked against the API rather than the web interface:
- Delete branch on merge -- already enabled
(
delete_branch_on_merge: true). The checkbox was simply never ticked. - Allow auto-merge -- genuinely disabled
(
allow_auto_merge: false). Decided against in this plan rather than left open; see decision 1.
Mission and problem statement¶
Bring kerbside into compliance with every consistency audit it currently fails, and leave behind a planning document that tracks the audit backlog as a whole rather than a subset of it.
One audit is an exception, deliberately. review-coverage
is not failing because anything in the repository is
missing; it is failing because a hundred files have not yet
been read by a person, and no amount of planning shortens
that. This plan builds what the reading needs and leaves the
reading to #227. Decision 5 sets out why.
The problem is not any individual finding -- five of the six are small, and one of those is not kerbside's bug at all. The problem is that the backlog has no owner. Issues arrive daily from another repository, land in a label, and are worked on when somebody notices them; the two oldest have been open since early August. A repository whose compliance drifts silently is exactly the failure mode the audit exists to prevent, so the audit's own findings deserve the same treatment as any other planned work.
A second, narrower problem: the audits delegate real content
to shared blocks, and kerbside is missing four of them.
PUSH-AUDIT.md is the checklist run over every plan's
accumulated diff before it is pushed, so three missing
blocks there mean three criteria -- path traversal review,
Python version discipline, functional test coverage -- are
not being applied to any of this repository's work.
PLAN-TEMPLATE.md is missing plan-push-audit-phase, which
is the block that makes the push audit phase mandatory and
defines the Merged column that records what to audit.
Those are not cosmetic gaps.
Open questions¶
None outstanding. The two that existed when this file was a standalone plan -- whether to enable auto-merge, and whether the settings work was worth tracking at all -- are settled by decision 1 and by this rewrite respectively.
The question phase 3 turns on is not open so much as
unanswerable from inside this repository: whether
development would rather widen the skillsaw check or have
kerbside change its invocation. Phase 3 proposes the former
and says why, but the decision belongs to that repository's
maintainer and the phase is scoped to making the case, not
to forcing it.
Execution¶
| Phase | Plan | Status | Merged |
|---|---|---|---|
| 1. Shared blocks, vendor stamp and settings closeout | PLAN-consistency-audit-phase-01-blocks-and-stamp.md | Complete | cbca9b1 |
| 2. Retire the comment addresser | PLAN-consistency-audit-phase-02-retire-addresser.md | Complete | 5f3c80c |
| 3. Skillsaw CI detection, upstream | PLAN-consistency-audit-phase-03-skillsaw-detection.md | Complete | 16e6173 |
| 4. Review scope and session scaffolding | PLAN-consistency-audit-phase-04-review-coverage.md | Complete | ade2788 |
| 5. Diagram discipline and mermaid linting | PLAN-consistency-audit-phase-05-diagram-discipline.md | In progress | |
| 6. Push audit | PLAN-consistency-audit-phase-06-push-audit.md | Not started |
Phase sketches (to be expanded into per-phase plans):
Phase 1 -- shared blocks, vendor stamp and settings
closeout. Resolves #368, #370 and #373. Copy the four
missing shared blocks verbatim from
shakenfist/development's templates/shared-blocks/:
plan-push-audit-phase into PLAN-TEMPLATE.md, and
path-traversal-review, python-version-discipline and
functional-test-coverage into PUSH-AUDIT.md. Re-vendor
sfui from a current checkout so .sfui-commit names
canonical HEAD. Tick the delete branch on merge checkbox
against the API evidence and record allow auto-merge as
decided against. Docs and static assets only; no Python
changes and no behaviour change.
Phase 2 -- retire the comment addresser. Resolves #360.
Delete .github/workflows/pr-address-comments.yml,
tools/address-comments-with-claude.sh,
tools/render-review.py and tools/review-schema.json in
one commit, as the audit requires, along with
kerbside/tests/unit/test_render_review.py which cannot
survive them. Remove the .claude/CLAUDE.md row and repair
the three pr-re-review.yml cross-references and the one in
tools/shellcheck-wrap.sh, keeping the bot-comment guard
whose justification one of them is. Prune the four review
marks. The security argument is the point of the phase and
belongs in the commit message: the workflow holds
contents: write on the pull request branch, for automation
that has been superseded by
shakenfist/actions/review-pr-with-claude@main and is no
longer used.
Phase 3 -- skillsaw CI detection, upstream. Addresses
359, but the change lands in shakenfist/development, not¶
here. Widen check_llm_context_lint_ci() so a workflow that
demonstrably runs the linter satisfies the CI half however
it installs it, matching the specification's own stated
intent. Add a test to scripts/test_audit_check.py covering
kerbside's shape -- PyPI install, no pre-commit run, the
upstream name appearing only in a comment. Kerbside's own
issue closes when the next audit run passes; nothing in this
repository changes. If development declines, the fallback
is to record the divergence here and ask for a
REPO_OVERRIDES exemption rather than to break a CI step
that works.
Phase 4 -- review scope and session scaffolding.
Resolves the review-scope-completeness check and builds
the scaffolding the human review runs on: a scope
configuration that names every tracked file, a session
recipe in docs/development.md that a reader can follow
without opening the upstream document, and a tranche order
that front-loads the files where a review is most likely to
find something (kerbside/api.py,
kerbside/proxy_supervisor.py, kerbside/sf_token.py,
kerbside/sources/ovirt.py, and the Jinja templates that
render the endpoints the open security issues concern).
Every mark is a signed commit, so the phase settles where
the signing configuration lives before any reading starts.
The reading itself is out of scope, and #227 is not this plan's to close. See decision 5. The phase delivers the scaffolding and stops; the 104 files are read in separate sessions on their own clock, tracked by the issue alone.
Corrected during phase 4 planning: three of this sketch's claims did not survive contact with the tree.
- The backlog is 77 files, not 70 -- the 70 was measured on 2026-08-29, before phases 2 and 3 and the renovate merges landed.
- The bulk is not
docs/spice/. Those 9 files are the smallest group of the six. The distribution iskerbside/25,tools/17,docs/17, and 7 repository-root files includingAGENTS.mdandPUSH-AUDIT.md. - The signing prerequisite passes. This bullet
originally said the opposite, and was corrected on
2026-09-02. The survey read
Nfromgit log --format='%h %G? %s'as "unsigned", but%G?verifies against the current clone'sgpg.format, and a development clone with none set cannot parse gitsign's x509 signature and reportsNfor a valid one. Testing the commit object instead (git cat-file commit <sha> | grep '^gpgsig') finds 29 signed mark-adding commits, continuously since 2026-08-14, alongside 46 unsigned commits touching the same files -- 38 bot prunes, which are correctly unsigned, and eight others. Three marks from before that date are unsigned. The count read 30 until 2026-09-03; the extra was37c11de, a merge carrying GitHub's web-flow PGP signature rather than a gitsign attestation, which is why the command excludes merges. The real question the phase had to settle was which clone holds the configuration, not whether anyone had ever run it.
The phase also absorbs a check that did not exist when this
sketch was written. review-scope-completeness landed
upstream on 2026-08-30 and fails with 44 orphaned files; it
is folded in here rather than given a phase, because
narrowing scope is the cheapest way to close a
review-coverage issue and settling scope after the grind
would mean redoing part of it. Fixing scope moves the
in-scope count from 192 to 227 and the backlog from 77 to
112, which is the honest number and a worse-looking one.
Phase 5 -- diagram discipline and mermaid linting.
Resolves #370 and #381. The dates in this sketch were
wrong and were corrected on 2026-09-03: #370 was filed
2026-08-26 and is not a new issue at all, but the
pre-push audit issue phase 1 already worked on, refiled
against a criterion that has since grown a block; #381 was
filed 2026-08-30. Both follow shakenfist/development
adding a diagram-discipline shared block and an
accompanying mermaid-lint-ci audit. Copy the diagram-discipline block
verbatim into PUSH-AUDIT.md, and copy
templates/mermaid-lint/ to give the repository a
tools/mermaid-lint.sh and a workflow that runs it. Note that
370's issue body is stale: it still lists the three shared¶
blocks phase 1 added, all of which are present on develop, and
the audit does not refresh an open issue's body. Its only live
finding is the missing diagram-discipline block. These two
issues are one upstream change and are deliberately kept in one
phase rather than split to clear a failure count sooner.
Surveyed 2026-09-03. The sketch is right in substance and
the phase is a pure adoption: all nine diagram-bearing files
already render, measured by running the upstream linter
against develop, so nothing has to be converted or fixed
behind the new lane. diagram-format already passes for the
same reason. Two facts the sketch does not mention decide how
the phase is built. The lane needs a docker daemon, and
kerbside's only lint job runs on a static runner that has
none, so the shipped path-filtered workflow is taken rather
than folded into the gate -- and it stays advisory, because a
path-filtered workflow that a ruleset requires never reports
on a pull request it skips and blocks it forever. The new
debian-12-docker runner label must also be added to
.github/actionlint.yaml, which otherwise fails on the
workflow.
Phase 6 -- push audit. Work through PUSH-AUDIT.md over
the accumulated diff of phases 1, 2 and 4 against develop
-- phase 3 lands in another repository and is audited there,
as part of the pull request that lands it. Name the commit
range explicitly, from the Merged column above, and
substitute it wherever PUSH-AUDIT.md says git diff
develop...HEAD. Note the ordering hazard: phase 1 adds
three criteria to PUSH-AUDIT.md, so this phase runs a
checklist that phase 1 changed, and must be run from the
version of the file that phase 1 produced.
Phase status¶
Plan status vocabulary (shared block; do not edit -- the canonical
copy lives in shakenfist/development at
templates/shared-blocks/plan-status-vocabulary.md):
A status cell -- in the master plan's own Execution phase table, and
in the row docs/plans/index.md carries for the plan -- holds
exactly one of these terms and nothing else:
Proposed-- written down as a concept, not yet scheduled.Not started-- scheduled, but no work has begun.In progress-- work has begun and has not finished.Blocked-- cannot proceed until something outside the plan changes. Say what, in the plan.Complete-- the work is done.Abandoned-- deliberately dropped without being done.Superseded-- replaced by another plan, which the plan names.
The term is the whole cell. No dates, no phase arithmetic, no parenthetical qualifiers, no summary of what happened: a status is read to decide whether a plan still wants attention, and prose in that column has repeatedly grown until it could no longer be read either by a person scanning the table or by tooling. Detail belongs in the plan file, and a one-line summary belongs in the index's own Intent column.
Matching is case-insensitive, so In Progress is accepted, but the
spelling above is the one to write.
Decisions¶
Decision 1 -- auto-merge stays disabled. The standalone
plan's checkbox asked us to confirm Allow auto-merge was
enabled; the API says it is not. Rather than enable it to
satisfy a checkbox written before the merge queue existed,
this plan records it as decided against. Auto-merge lands a
pull request the moment its required checks pass; the merge
queue, live since 2026-08-09, exists precisely so that
nothing lands without being retested against the develop tip
it will actually sit on, and two-tier CI puts the oVirt and
OpenStack lanes only in the queue. Enabling auto-merge
alongside it adds a second landing path that skips the merge
tier's entire point. No consistency audit asks for it --
there is a delete-branch-on-merge audit and a
merge-queue-config audit, and neither mentions auto-merge.
The checkbox is retired, not ticked.
Decision 2 -- #359 is fixed upstream, not worked around.
The tempting cheap fix is to make kerbside's CI step name
stbenjam/skillsaw so the checker's string match succeeds --
a uses: line, or even editing the comment. Both are
refused. The composite action genuinely does not work on
these runners for a documented reason, so switching to it
would trade a green audit for a red CI lane; and satisfying
a substring check by rewording a comment is precisely the
kind of compliance theatre that makes an audit worthless.
The check is wrong against its own specification, so the
check is what changes. This is the decision most likely to
be argued with, because it makes kerbside's issue depend on
another repository's maintainer accepting a patch, and
leaves #359 open in the meantime. The alternative is worse:
a repository that games the audit teaches every other
repository to do the same.
Decision 3 -- phase 1 is grouped by risk, not by issue
age. The natural grouping would put all five small
findings in one phase. Instead #360 is split out, because
deleting a workflow that holds contents: write, four
tools, and a unit test is a different kind of change from
copying a documentation block, and it deserves its own
commit message making the security argument and its own
review. Phase 1 is the changes where the diff can be
verified by comparison against a canonical source; phase 2
is the change where something has to be reasoned about.
Decision 4 -- the master plan is rewritten in place rather
than superseded. PLAN-consistency-audit.md keeps its
filename, its 2026-07-16 date and its index row, moving from
the Standalone plans table to Master plans. Superseding
it with a new file would strand the three completed security
checkboxes and lose the history of why they were tracked.
The old remit survives as phase 1's settings closeout.
Decision 5 -- the human reading is out of scope; this
plan builds the scaffolding for it. Phase 4 was originally
written to run until the review backlog dropped below five,
which would have kept this plan In progress for as long as
it takes one person to read a hundred files -- weeks, at a
rate nobody had measured. That is the wrong instrument. A
plan tracks work that planning makes go faster, and reading
source code is not that: the sequencing is worth deciding
once, but after that the plan has nothing left to contribute
and only reports a number the audit already reports better.
So the boundary is drawn at the scaffolding. In scope: a scope configuration that names every tracked file, a documented session recipe, a tranche order, and the settled question of where signing configuration lives. Out of scope: the reading. #227 stays open and is sufficient on its own -- it is recomputed against HEAD daily, it names exactly which files remain, and it closes itself when a passing audit run says so. Duplicating that into a status column adds a second place to be stale.
Two consequences a reader should not be surprised by. This
plan can reach Complete while review-coverage is still
failing, which looks wrong against the mission statement and
is why the mission now states the exception outright. And
the tranche table in the phase 4 plan becomes a reference
document rather than a progress tracker -- nothing updates
it as tranches are worked, and nothing should.
This is the decision most likely to be argued with, because the plan opens by complaining that the audit backlog has no owner and this hands the oldest issue in it back to the label. The distinction is that #227 does have an owner and a next action; what it lacked was scope that made the work possible to start, and that is what phase 4 delivered.
Agent guidance¶
Execution model¶
All implementation work is done by sub-agents, never in the management session. The management session is reserved for planning, review, and decision-making.
The workflow is:
- Plan at high effort in the management session.
- Spawn a sub-agent for each implementation step with the brief from the plan, at the recommended effort level and model.
- Review the sub-agent's output in the management session. Check the actual files -- the sub-agent's summary describes what it intended, not necessarily what it did.
- Fix or retry if the output is wrong. Diagnose whether the brief was insufficient (improve it) or the model was too light (upgrade it), then re-run.
- Commit once the management session is satisfied.
This plan has an unusual verification property that the
review step should lean on: for every shared block and for
the vendored sfui copy, a canonical source exists and the
correct answer is a byte-for-byte comparison against it.
Where that is true, review by diff, not by reading.
Planning effort¶
The master plan was created at high effort. Phase 1 is
mechanical and can be planned at medium effort -- its
difficulty is entirely in getting the block boundaries and
the vendoring procedure exactly right, which is a matter of
care rather than judgment. Phase 2 should be planned at
medium effort, with attention to the full reference set the
survey found rather than the four files the issue names.
Phase 3 should be planned at high effort: it changes another
repository's checker, and a widened check that accidentally
passes a repository running no linter at all is worse than
the false negative it fixes. Phase 4 was planned at high effort,
because the scope configuration it writes is load-bearing
for an audit and expensive to redo once reading has started
against it. Phase 5 follows PUSH-AUDIT.md.
Step-level guidance¶
Each phase plan includes the step table described in
PLAN-TEMPLATE.md (step, effort, model, isolation, brief),
with briefs written so a colleague who has never seen the
codebase could execute them. Front-load the research from
this master plan into the briefs -- a brief for phase 2
should name kerbside/tests/unit/test_render_review.py and
.claude/CLAUDE.md line 139 outright, rather than leaving
the implementing agent to rediscover that the four files the
issue names are not the whole deletion.
For every phase in this plan, read the audit specification
in shakenfist/development/docs/audits/ before starting.
The issue body is a generated summary and has already been
wrong twice.
Management session review checklist¶
After a sub-agent completes, the management session verifies:
- The files that were supposed to change actually changed -- read them, do not trust the summary.
- No unrelated files were modified.
- Shared blocks are byte-identical to their canonical
copies, including the version number in the opening
marker; verified with
diff, not by eye. - The code passes
tox -eflake8andtox -epy3. -
pre-commit run --all-filespasses. - Workflow changes pass actionlint.
- The commit message follows project conventions,
including the
Co-Authored-Byline recording model, context window and effort level.
Administration and logistics¶
Success criteria¶
We will know when this plan has been successfully implemented because the following statements will be true:
- Issues #360, #368, #370 and #373 are closed, each by a consistency audit run that passes rather than by hand. #227 is deliberately absent: see decision 5.
-
359 is closed, or -- if
upstream change -- kerbside carries a recorded exemption and this plan says so in writing.developmentdeclines the¶ PUSH-AUDIT.mdcarries thepath-traversal-review,python-version-disciplineandfunctional-test-coverageshared blocks, byte-identical to their canonical copies.PLAN-TEMPLATE.mdcarries theplan-push-audit-phaseshared block, byte-identical to its canonical copy.kerbside/api/static/sfui/.sfui-commitnames the commit at sfui'sdevelopHEAD, andtools/vendor.sh --checkfrom a checkout at that commit reports no difference.- No file matching
pr-address-comments.yml,address-comments-with-claude.sh,render-review.pyorreview-schema.jsonexists anywhere in the tree, andtox -epy3still passes. ./tools/review-tracking.sh scope-orphansexits zero, and thereview-scope-completenessaudit passes: every tracked file is either in review scope or explicitly excluded, with a stated reason for each exclusion.docs/development.mddocuments the review session recipe, and the command it gives for listing a tranche's outstanding files runs and produces file paths.- The code passes
tox -eflake8andtox -epy3, andpre-commit run --all-filesis clean. - The
PUSH-AUDIT.mdaudit has been run over the plan's accumulated diff, and every finding it raised has been fixed or declined in writing in this plan.
Documentation index maintenance¶
docs/plans/index.md carries this plan's row. The rewrite
moves it from the Standalone plans table to the Master
plans table, keeping the 2026-07-16 date, and adds the
phase links. When all phases are complete, set the status to
Complete.
Future work¶
- The audit backlog is a standing queue, not a one-off. When
this plan completes, new
consistency-labelled issues will keep arriving. Consider whether the right end state is a further phase, a recurring session, or simply closing this plan and treating each new issue on its merits. - The
review-coverageaudit runsreview-tracking.py status, which reads the sidecar and never checks whether the commit carrying a mark was signed. A repository can therefore pass the audit with no attestation at all. Kerbside signs anyway, by convention rather than because anything enforces it, so the gap here is latent rather than live -- but the signature is the attestation in this scheme, and an audit that ignores it measures bookkeeping rather than review. Worth raising as an issue onshakenfist/development, alongside the twogithub-securitydefects below. -
227's underlying problem is that review coverage decays¶
with every merge -- theprune-reviewsworkflow invalidates a mark whenever its file changes. Neither this plan nor the reading sessions that follow it stop the backlog regrowing; they only empty it once. A standing review budget, of the kindshakenfist/actions's reviewer-budget work explores, would be the durable fix and is out of scope here. -
The three GitHub security settings ticked in July (Dependabot security updates, secret scanning, push protection) were verified once, by hand, on 2026-07-18. This rewrite drops the checkboxes that recorded them, on the assumption that the
github-securityaudit indevelopmentre-checks all three continuously. Phase 1 step 1d checked that assumption and it is wrong in both directions, so the settings are still uncovered:- Dependabot security updates is not checked at all.
docs/audits/github-security.mdline 12 lists it as required, butdependabotappears nowhere inscripts/audit-check.py. The specification and the implementation disagree. - The check silently passes when it cannot reach the
GitHub API.
check_github_security()guards onif result.returncode == 0 and result.stdout.strip():and appends nothing when that fails, sosecuritystaysNone, theif security:block is skipped, and the function returnspass. Only a timeout or a missingghbinary is reported; an auth failure, a rate limit or a 404 reads as compliant.
- Dependabot security updates is not checked at all.
Both belong upstream, alongside phase 3's fix, and both
should be raised as issues on shakenfist/development
rather than worked around here. Until they are, secret
scanning and push protection are covered only when the
audit's API call happens to succeed, and Dependabot is not
covered at all.
Bugs fixed during this work¶
Three defects so far, all of them in the audit tooling in
shakenfist/development/scripts/audit-check.py rather than
in kerbside, and all of the same family -- a check that does
not do what its specification says:
check_llm_context_lint_ci()contradicts its own specification by requiring skillsaw to be invoked in one of two specific ways, which is what #359 reports against kerbside. Found by the survey; phase 3 fixes it.check_github_security()does not check Dependabot security updates, which its specification requires. Found by phase 1 step 1d.check_github_security()returnspasswhen itsgh apicall fails with a non-zero exit status, so an auth failure or a rate limit reads as compliant. Found by phase 1 step 1d.
Only the first is in this plan's scope, because only the
first is why kerbside carries an open issue. Defects 2 and 3
should be filed against shakenfist/development; phase 3
already goes there and is the natural place to raise them.
227's stale issue body is not a bug: it is a rendering¶
artifact of an old run. The live checker agreed with the tree at 124 of 194 when this was written, and at 123 of 227 once phase 4 widened the scope.
Back brief¶
Before executing any step of this plan, please back brief the operator as to your understanding of the plan and how the work you intend to do aligns with that plan.