Hooks and the ratchet
No. 013cube check reports what is wrong with a knowledge base. The git hooks keep
it from getting worse: they run the same checks on every commit, merge and
push, and refuse a change that adds an ERROR. The hooks work the same way for
a person and for any agent that commits through git.
In the alpha, the hooks run on Linux only. On macOS and Windows they refuse every commit until a later release adds those systems’ ownership checks (see the known limits).
Install the hooks
Section titled “Install the hooks”cube adopt writes the hook scripts into .cube/hooks/. cube setup turns
them on:
cube setupIt writes the absolute paths of cube, git, gh and python3 into your global
git config, and core.hooksPath=.cube/hooks and merge.ff=false into the
repository (a fast-forward merge runs no hook). The hooks never run gh.
The programs the hooks run
Section titled “The programs the hooks run”The hooks run a program only when its file and every folder above it are
owned by root and not writable by others. A program in your home folder, such
as a cube the installer put in ~/.local/bin, passes only when you list it
yourself in cube.allowUserOwned in your global git config. cube setup says
when the hooks will refuse a program and prints the command that opts it in:
git config --global --add cube.allowUserOwned <the absolute path of the program>With the opt-in, every hook prints a warning that this is not tamper-proof
against agents that run as your account. Cube never writes the opt-in itself:
it is your decision. cube doctor shows how the hooks judge each program.
What the hooks refuse
Section titled “What the hooks refuse”- pre-commit checks the staged tree and compares its ERRORs with those of
HEAD(the ratchet, below). A refused commit prints the fix brief, whichcube check --format agentalso prints, and writes it to.cube/cache/fix-brief.md. - commit-msg checks the
Cube-*trailers of the message and writes theCube-Checkedstamp on a commit that passed. - pre-push checks every pushed commit again against its first parent.
A crashed or unreadable kit check judges nothing, so it refuses the commit
too (CHECK_FAILED).
A commit since adoption that carries no valid Cube-Checked stamp, for
example one made with git commit --no-verify, is reported as
SHORTCUT_HOOK_BYPASS. Only a person can clear it.
The ratchet
Section titled “The ratchet”The ratchet lets a knowledge base with old ERRORs move forward, but never backward:
- A commit with no ERROR passes.
- While ERRORs remain, a commit passes only when it removes at least one and adds none.
- A commit that keeps exactly the same ERRORs needs a trailer that says why (a move or a migration).
- A merge passes when it adds no ERROR that none of its parents has. ERRORs it inherits never block it.
- A commit that raises a new
SHORTCUT_*finding is refused unless it carries a rule-change act.
The ratchet compares findings by their code, the file or node they are about, and their details. Line numbers and message text do not count, so moving lines in a file does not change the count.
A kit’s own rules cannot be quietly weakened
Section titled “A kit’s own rules cannot be quietly weakened”The checks also judge the change itself. The SHORTCUT_* codes catch the
shortcuts a person or an agent might take to make a finding go away instead of
fixing it:
| Code | What it catches |
|---|---|
SHORTCUT_RULE_WEAKENED |
kit.yml judges less than it did at HEAD. |
SHORTCUT_SUPPRESS |
A suppression marker or a new allow-list entry. |
SHORTCUT_EVIDENCE_REMOVED |
A test, fixture or ledger artifact deleted, or the file a finding points at deleted with the finding. |
SHORTCUT_TEST_EDITED |
A test changed in the same commit as the code it tests. |
SHORTCUT_PLACEHOLDER |
A required field filled with TBD, TODO, n/a or another placeholder. |
SHORTCUT_GUARD_OVERRIDE |
A guard switched off, or a generated file edited by hand. |
Every SHORTCUT_* code is an ERROR from the first release. So a commit that
weakens the kit’s rules is refused, like any other commit that adds an ERROR.
Keeping such a change is a rule change. A rule change is a person’s act: a
person commits it with a Cube-Act trailer that names the rule and its old
and new severity. Removing a pack is a rule change too. The
finding codes page lists every code.
In the alpha, cube records each rule change, each cleared bypass and each
change to the code that judges commits with a HUMAN_ONLY_BY_AGENT warning.
It does not check signatures on those commits yet.
These checks guard the knowledge base, not your machine. An agent that runs as
your account can still replace a cube program your account owns, or change
your global git settings, and the checks cannot see that. Full protection
needs a cube that root owns, which a later release installs; the alpha’s
per-user install works only with the opt-in described in
the programs the hooks run, and every hook then
warns you.