refactor(review): simplify pass over E (reuse, simplification, efficiency)

Quality only, no behaviour change (four cleanup reviewers, one implementer;
npm test 2480/0 on the working tree):

- threat-model.mjs splitBacked(): the one known_outside backing check of
  plan-gate (record and bare gate), verdict-gate and review-finalize, with
  one why-text; the engines' security keys derived from ENGINES; isSecurity.
- coordinator-contract: "not a security engine" read from ENGINES (a string
  engine only), not the code-review literal.
- review-rounds owns trailingBlock, findingsBlockSha, isMajor, isBlocker;
  review-answers imports them (review-rounds still imports nothing from it).
  prepare keeps the archive bytes it read instead of reading the previous
  archive again.
- engine-compare exports rowIn and payloadEngine; finalize uses them.
- plan-gate: one accepted_open builder; the stop-rule check hoisted; one
  top-level lookup for --record --brief.
- security-engine: notFullShas(), runCli's usage flag, readScopeList shared
  with engine-findings; findReport and reviewRoundSummary module-private;
  two dead defaults gone.
- tests: shared plan-gate harness and threat-model brief helpers; the [CNV]
  table cases call convertReport in-process, one CLI case per exit path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-11-08 21:27:59 +01:00
commit f820081bdc
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
18 changed files with 332 additions and 373 deletions

View file

@ -12,6 +12,7 @@ import { strict as assert } from 'node:assert';
import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { TM, briefWith } from '../helpers/threat-model-brief.mjs';
const HERE = dirname(fileURLToPath(import.meta.url));
const ROOT = join(HERE, '..', '..');
@ -19,43 +20,7 @@ const validator = () => import(join(ROOT, 'lib', 'validators', 'brief-validator.
const approval = () => import(join(ROOT, 'lib', 'validators', 'intent-approval.mjs'));
const read = (rel) => readFileSync(join(ROOT, rel), 'utf8');
const TM = `## Threat Model
- Inside: a crafted file name in a pull request reaches the shell
- Outside: a local user who can already edit the repo's hooks
`;
const brief = (threat = '') => `---
type: trekbrief
brief_version: "2.2"
created: 2026-11-08
task: "Add an upload hook"
slug: upload-hook
project_dir: .claude/projects/2026-11-08-upload-hook/
research_topics: 0
research_status: complete
framing: new-direction
---
# Task
## TL;DR
An upload hook.
## Intent
Uploads arrive from strangers.
## Goal
A hook that checks each upload.
${threat}
## Success Criteria
- It checks.
`;
const brief = (threat = '') => briefWith(threat);
const codes = (r) => r.errors.map((e) => e.code);
const STAMP_AT = new Date('2026-11-08T08:00:00Z');