Files
Garry Tanandcapy-ai[bot] 5b9b8372c4 feat: honest work and gate integrity — gate-edit detector, review/ship gate pass, zero-run green, claims-need-evidence kernel (#3114)
* docs(designs): honest work and gate integrity plan (autoplan-reviewed)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(e2e): review-gate-integrity rule case registered in touchfiles and the PR profile

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(honesty): claims-need-evidence kernel, no_claim card field, CEO value test, implementer dispatch rules, ACCEPTANCE_EDITED, Honest Work ethos

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(gate-diff): gate-edit detector lib + CLI, patch fixtures, calibration script, tests_ran in gstack-evidence

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(gate-diff): RH-15? only on CI/config floors after calibration

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(review,ship): Gate Integrity category, GATE_SCAN_BLOCK, one-way gate disposition, actor stamping, ZERO-RUN lanes, draft-while-open

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore: re-measure parity and context budgets on the integrated tree

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(touchfiles): gate-diff fixtures and helpers select review-gate-integrity

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: archaeology lint wording, paid-file census, harness-version non-behavioral record

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pin review Step 3.5 rename, plan-path placeholder, mktemp template, per-stream evidence tail

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: ACCEPTANCE_EDITED fence substitutes the <plan-path> placeholder

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(gate-diff): shallow boundary commits report no_base instead of a whole-tree inventory; recalibrate

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

---------

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
2026-10-10 22:33:01 +00:00

54 lines
2.2 KiB
TypeScript

/**
* gate-diff-repo — materialise a test/fixtures/gate-diff patch pair into a
* throwaway git repo. Fixtures are patch text only (never a nested .git):
* `<name>.base.patch` seeds the base commit on `main`, `<name>.patch` is the
* candidate change applied on a `feature` branch, committed or left in the
* working tree. Hermetic git identity and no gpg via scratch-repo.
*/
import * as fs from 'node:fs';
import * as os from 'node:os';
import * as path from 'node:path';
import { gitArgvIn } from './scratch-repo';
export const GATE_DIFF_FIXTURES = path.resolve(import.meta.dir, '..', 'fixtures', 'gate-diff');
export interface GateDiffRepoOptions {
/** Fixture stem; omit for an empty seed commit. */
fixture?: string;
/** Commit the candidate change (default: leave it staged in the working tree). */
commit?: boolean;
commitMessage?: string;
/** Extra non-ignored untracked files written after the change. */
untracked?: Record<string, string>;
}
function git(dir: string, args: string[]): string {
const r = gitArgvIn(dir, args, 10_000);
if (r.status !== 0) throw new Error(`git ${args.join(' ')} failed: ${(r.stderr ?? '').toString()}`);
return (r.stdout ?? '').toString();
}
export function buildGateDiffRepo(opts: GateDiffRepoOptions = {}): string {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-gate-diff-repo-'));
git(dir, ['init', '-q', '-b', 'main']);
if (opts.fixture) git(dir, ['apply', path.join(GATE_DIFF_FIXTURES, `${opts.fixture}.base.patch`)]);
else fs.writeFileSync(path.join(dir, 'README.md'), '# seed\n');
git(dir, ['add', '-A']);
git(dir, ['commit', '-q', '-m', 'seed']);
git(dir, ['checkout', '-q', '-b', 'feature']);
if (opts.fixture) {
git(dir, ['apply', '--index', path.join(GATE_DIFF_FIXTURES, `${opts.fixture}.patch`)]);
if (opts.commit) git(dir, ['commit', '-q', '-m', opts.commitMessage ?? `apply ${opts.fixture}`]);
}
for (const [rel, content] of Object.entries(opts.untracked ?? {})) {
const abs = path.join(dir, rel);
fs.mkdirSync(path.dirname(abs), { recursive: true });
fs.writeFileSync(abs, content);
}
return dir;
}
export function gitIn(dir: string, args: string[]): string {
return git(dir, args);
}