feat(gate): session-gate.sh - R3/R4/R6 checks before a session starts
Order 20260926T070037Z-680859139 (.claude). A read-only, zero-model-call check any session starter can call first: exit 0 allows, exit 2 denies with one stderr line naming the rule and what is missing. - R4: PLAN.md holds exactly one gate line, <!-- gate: gjenfortelling=<time>; dekning=komplett; r1-proeve=<time|->; foerste-maaling=<time|->; retning=<name> --> - R3: the Logg table's Bevegelse (ja|nei) and Kvote (N%) columns. Deny at >= 10% of the weekly quota without movement since the last row that moved. - R6: cap 1 live session per repo (claude agents --json --cwd <repo>) until r1-proeve and foerste-maaling are both times, then 2. Night 23:00-07:00 or --night needs r1-proeve. Fail-closed: unmeasured rows, a missing claude binary, a non-JSON listing, duplicate or unknown keys and usage errors all deny. Measured: claude agents --cwd matches the directory a session was STARTED in, not its printed cwd, so --repo must be the main checkout root. Chose NOT to call it from board.sh --dispatch, because a dispatch line is generated before the start (a live count would be stale), and live-session reading is the process axis board.sh refuses by design. session-gate-selftest.sh: 0 -> 97 checks. It was red 91 of 95 before the script existed, then 97/97 green. Ten mutants all die. It is wired into npm test as the sixth suite, and the README badge goes from 1006 to 1103. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
6c9b17277c
commit
02d4df2dfb
5 changed files with 794 additions and 10 deletions
|
|
@ -74,6 +74,13 @@ test('orders bash selftest passes', () => {
|
|||
runSuite('orders');
|
||||
});
|
||||
|
||||
// session-gate.sh is the check a session starter calls before it starts one.
|
||||
// Its suite feeds live sessions from a fake `claude` on PATH, so it proves the
|
||||
// gate without depending on what happens to be running on this machine.
|
||||
test('session-gate bash selftest passes', () => {
|
||||
runSuite('session-gate');
|
||||
});
|
||||
|
||||
// The engine refuses to invent an identity from the cwd, but the hook is the
|
||||
// FOURTH place repo identity is derived, and a rule enforced in three of four
|
||||
// places is not a rule: as long as the hook resolved the name itself and passed
|
||||
|
|
@ -255,7 +262,7 @@ function suiteTotal(name) {
|
|||
|
||||
test('README states the selftest counts the suites actually reported', () => {
|
||||
const readme = readFileSync(join(root, 'README.md'), 'utf8');
|
||||
const suites = ['coord', 'board', 'route', 'orders', 'state-line-guard'];
|
||||
const suites = ['coord', 'board', 'route', 'orders', 'state-line-guard', 'session-gate'];
|
||||
|
||||
let sum = 0;
|
||||
for (const name of suites) {
|
||||
|
|
@ -275,5 +282,5 @@ test('README states the selftest counts the suites actually reported', () => {
|
|||
const badge = readme.match(/badge\/selftest_checks-(\d+)-/);
|
||||
assert.ok(badge, 'README has no selftest_checks badge to check');
|
||||
assert.equal(Number(badge[1]), sum,
|
||||
`README's badge says ${badge[1]} selftest checks; the five suites reported ${sum}`);
|
||||
`README's badge says ${badge[1]} selftest checks; the ${suites.length} suites reported ${sum}`);
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue