Files
gstack/test/takes-fence-fallback.test.ts
T
Garry Tan e884617b7c test(brain): schema migration + fence-block fallback + preflight budget (T19+T21)
3 new gate-tier test files closing the most important coverage gaps in
the brain-aware planning layer:

test/schema-version-migration.test.ts (D4 A4):
  - Cache file with mismatched schema_version triggers wipe-and-rebuild
  - Matching version + fresh TTL stays warm-hit (no unnecessary rebuild)
  - Rebuild wipes ALL files in scope, not just the one being read

test/takes-fence-fallback.test.ts:
  - Every preflight skill mentions both takes_add (preferred) and
    put_page fence-block (fallback for pre-T8 gbrain versions)
  - All 5 skills gate on BRAIN_CALIBRATION_WRITEBACK flag + personal
    trust policy
  - Per-skill weight matches SKILL_CALIBRATION_WEIGHTS (E5)
  - Write-back emits the kind=bet frontmatter shape and invalidates
    affected cache digests

test/skill-preflight-budget.test.ts (T21 / D7):
  - Per-skill BRAIN_* instruction bytes stay under 3x the runtime
    digest budget (resolver bloat catch)
  - Autoplan total instruction bytes stay under 75 KB (3x of 25 KB
    runtime cap)
  - Non-preflight skills emit zero brain bytes
  - Per-skill subset references are present in the preflight bash

Note on the 3x multiplier: SKILL_PREFLIGHT_BUDGET_BYTES governs runtime
digest data (enforced by cache CLI truncateToBudget). Instruction text
emitted by the resolver gets a separate 3x headroom — anything beyond
that signals the instructions themselves are bloated and need a trim.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 23:14:16 -07:00

88 lines
3.3 KiB
TypeScript

/**
* Phase 2 calibration write-back fence-block fallback (T19).
*
* The BRAIN_WRITE_BACK resolver output describes two paths:
* 1. Preferred: mcp__gbrain__takes_add op (upstream gbrain v0.42+, T8)
* 2. Fallback: mcp__gbrain__put_page with a gstack:takes fence block
*
* Until T8 ships, the fallback is the only path. Verify the resolver output
* mentions the fence-block fallback explicitly so the agent knows what to
* do when takes_add returns MCPMethodNotFound.
*
* Gate-tier, free, pure import + render.
*/
import { describe, test, expect } from 'bun:test';
import { generateBrainWriteBack } from '../scripts/resolvers/gbrain';
import { SKILL_DIGEST_SUBSETS, SKILL_CALIBRATION_WEIGHTS } from '../scripts/brain-cache-spec';
import { HOST_PATHS } from '../scripts/resolvers/types';
import type { TemplateContext } from '../scripts/resolvers/types';
function buildCtx(skillName: string): TemplateContext {
return {
skillName,
tmplPath: `/tmp/${skillName}/SKILL.md.tmpl`,
host: 'claude',
paths: HOST_PATHS.claude,
};
}
describe('Phase 2 write-back fence-block fallback', () => {
test('every preflight skill emits write-back with fallback path documented', () => {
for (const skill of Object.keys(SKILL_DIGEST_SUBSETS)) {
const out = generateBrainWriteBack(buildCtx(skill));
// Mentions takes_add (preferred)
expect(out).toContain('takes_add');
// Mentions put_page fallback
expect(out).toContain('put_page');
// Mentions the takes fence-block syntax
expect(out).toContain('takes');
}
});
test('write-back guidance gates on BRAIN_CALIBRATION_WRITEBACK feature flag', () => {
for (const skill of Object.keys(SKILL_DIGEST_SUBSETS)) {
const out = generateBrainWriteBack(buildCtx(skill));
expect(out).toContain('BRAIN_CALIBRATION_WRITEBACK');
}
});
test('write-back guidance gates on brain_trust_policy == personal', () => {
for (const skill of Object.keys(SKILL_DIGEST_SUBSETS)) {
const out = generateBrainWriteBack(buildCtx(skill));
expect(out).toContain('personal');
expect(out).toContain('brain_trust_policy');
}
});
test('write-back emits the kind=bet take frontmatter shape', () => {
const out = generateBrainWriteBack(buildCtx('plan-ceo-review'));
expect(out).toContain('kind: bet');
expect(out).toContain('holder:');
expect(out).toContain('claim:');
expect(out).toContain('weight:');
expect(out).toContain('since_date:');
expect(out).toContain('expected_resolution:');
expect(out).toContain('source_skill:');
});
test('per-skill weight matches SKILL_CALIBRATION_WEIGHTS', () => {
for (const skill of Object.keys(SKILL_DIGEST_SUBSETS)) {
const weight = SKILL_CALIBRATION_WEIGHTS[skill];
if (weight == null) continue;
const out = generateBrainWriteBack(buildCtx(skill));
expect(out).toContain(`weight: ${weight}`);
}
});
test('write-back invalidates affected cache digests after write', () => {
const out = generateBrainWriteBack(buildCtx('plan-ceo-review'));
expect(out).toContain('gstack-brain-cache invalidate');
});
test('non-preflight skill gets empty write-back (no Phase 2 path)', () => {
expect(generateBrainWriteBack(buildCtx('ship'))).toBe('');
expect(generateBrainWriteBack(buildCtx('qa'))).toBe('');
});
});