Files
gstack/test/binding-template-drift.test.ts
T
Garry TanandClaude Fable 5 2e3ba307d8 chore(binding-wave): drift tripwire, golden fixtures, TODOS follow-ups
test/binding-template-drift.test.ts pins the load-bearing prose rules in the
GENERATED templates (ship Step 16 evidence check, per-lane wrapped test lanes,
land-and-deploy wtree-first grading + UNKNOWN fallback, dashboard content-first
rule, release-body banner tripwire, greptile guard pipes) so a template
refactor can't silently drop a rule while the bins keep passing their unit
tests.

Golden ship fixtures re-pinned to the new intentional output (claude/codex/
factory variants). TODOS.md gains the five deferred follow-ups from the review
wave: eval-run evidence records, spec-spawn outcome ledger, merge-SHA custody,
default-if-silent escalations, and the paid eval case proving agents apply the
staleness grading rule.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-15 23:33:15 -07:00

62 lines
2.7 KiB
TypeScript

import { describe, test, expect } from 'bun:test';
import * as fs from 'fs';
import * as path from 'path';
/**
* Template-drift tripwire for the content-binding wave. The bins are
* code-enforced; the GRADING rules live as prose in rendered templates that
* agents follow. This test pins the load-bearing rule text in the GENERATED
* files so a template refactor can't silently drop a rule while the bins keep
* working. (Prompt-followed prose is honest tier-2 enforcement — this tripwire
* is what keeps it from being tier-3 vibes.)
*/
const ROOT = path.resolve(import.meta.dir, '..');
function rendered(rel: string): string {
return fs.readFileSync(path.join(ROOT, rel), 'utf-8');
}
describe('content-binding template drift', () => {
test('ship Step 16 carries the evidence check (mechanized IRON LAW)', () => {
const ship = rendered('ship/SKILL.md');
expect(ship).toContain('gstack-evidence check --label tests --label vitest --max-age 24 --allow-paths CHANGELOG.md,VERSION,package.json');
expect(ship).toContain('a failed CHECK never blocks');
});
test('ship Step 5 lanes run wrapped with per-lane labels', () => {
const tests = rendered('ship/sections/tests.md');
expect(tests).toContain('gstack-evidence run --label tests');
expect(tests).toContain('gstack-evidence run --label vitest');
});
test('land-and-deploy grades staleness content-first (wtree rule) and checks evidence', () => {
const land = rendered('land-and-deploy/SKILL.md');
expect(land).toContain('wtree');
expect(land).toContain('---WTREE---');
expect(land).toContain('gstack-evidence check --label tests --max-age 24');
expect(land).toContain('UNKNOWN');
});
test('the review dashboard staleness rule is wtree-first for diff-scoped rows', () => {
// The dashboard text is generated into every skill that embeds
// {{REVIEW_DASHBOARD}}; ship is the canonical carrier.
const ship = rendered('ship/SKILL.md');
expect(ship).toContain('---WTREE---');
expect(ship).toContain('diff-scoped rows only');
expect(ship).toContain('grade UNKNOWN and treat as stale');
});
test('release-body write side carries the banner tripwire', () => {
const body = rendered('document-release/sections/release-body.md');
expect(body).toContain('grep -q "UNTRUSTED TRACKER CONTENT" /tmp/gstack-pr-body-$$.md');
expect(body).toContain('banner tripwire clean');
});
test('greptile triage reads bodies through the guard (metadata/body split)', () => {
const triage = rendered('review/greptile-triage.md');
expect(triage).toContain('gstack-issue-guard --stdin --source greptile-line');
expect(triage).toContain('gstack-issue-guard --stdin --source greptile-replies');
});
});