From 6dc624eda6c70cb0eb1775c5386640b092601b69 Mon Sep 17 00:00:00 2001 From: garrytan Date: Tue, 29 Sep 2026 04:35:13 +0000 Subject: [PATCH] test: delete test-infrastructure dead code (G) - exit-propagation drives the runner's real strict verdict (BunTestOutputClassifier + strictTestExitCode); delete the unused shardRunLooksTruncated predicate. - delete skill-coverage-matrix registry + its gate (nothing reads it; the floor already iterates skillCensus()). - delete touchfiles-facade export-parity tests (Bun fails missing imports at link time) and the duplicated E2E_TIERS tier-value test. - delete brain-cache-spec TRANSPORT_DEFAULT_POLICY, SKILL_RUN_RETENTION_DAYS and the now-unused BrainTrustPolicy type with their literal tests. AUTOPLAN_PREFLIGHT_BUDGET_BYTES stays: skill-preflight-budget enforces it against real resolver output. - delete audit-compliance's JSDoc-comment grep. --- scripts/brain-cache-spec.ts | 26 ---- scripts/test-free-shards.ts | 17 --- test/audit-compliance.test.ts | 6 - test/brain-cache-spec.test.ts | 18 --- test/exit-propagation.test.ts | 33 +++-- test/gstack-schema-pack.test.ts | 2 +- test/skill-coverage-floor.test.ts | 30 +--- test/skill-coverage-matrix.test.ts | 78 ---------- test/skill-coverage-matrix.ts | 226 ----------------------------- test/touchfiles-facade.test.ts | 49 +------ 10 files changed, 25 insertions(+), 460 deletions(-) delete mode 100644 test/skill-coverage-matrix.test.ts delete mode 100644 test/skill-coverage-matrix.ts diff --git a/scripts/brain-cache-spec.ts b/scripts/brain-cache-spec.ts index eab2f9588..51b16988e 100644 --- a/scripts/brain-cache-spec.ts +++ b/scripts/brain-cache-spec.ts @@ -162,12 +162,6 @@ export const SKILL_CALIBRATION_WEIGHTS: Record = { */ export const CACHE_REFRESH_LOCK_TIMEOUT_MS = 5 * 60_000; -/** - * Retention policy: gstack/skill-run pages auto-archive after this many days. - * Calibration takes (kind=bet) NEVER archive (long-term scorecard needs them). - */ -export const SKILL_RUN_RETENTION_DAYS = 90; - /** * Schema pack identity. Bumped when adding/removing/renaming page types. * On mismatch with the version recorded in _meta.json, the cache layer @@ -176,26 +170,6 @@ export const SKILL_RUN_RETENTION_DAYS = 90; export const GSTACK_SCHEMA_PACK_NAME = 'gstack-core'; export const GSTACK_SCHEMA_PACK_VERSION = '1.0.0'; -/** - * Trust policy values. Drives auto-push of artifacts, calibration write-back - * eligibility, and user-namespacing strategy. - */ -export type BrainTrustPolicy = 'personal' | 'shared' | 'unset'; - -/** - * Per-transport default policy. Local engines auto-set to personal (single-tenant - * by construction). Remote endpoints are inferred based on sources_list shape: - * exactly one source + whoami matches → personal default; multiple sources or - * federation → ask the policy question. - */ -export const TRANSPORT_DEFAULT_POLICY: Record = { - 'local-pglite': 'personal', - 'local-stdio': 'personal', - 'remote-http-single-tenant': 'personal', - 'remote-http-ambiguous': 'unset', - unknown: 'unset', -}; - /** * User-slug fallback chain (D4 A3 defensive default). Resolved once per endpoint * and persisted via `gstack-config set user_slug_at_ `. diff --git a/scripts/test-free-shards.ts b/scripts/test-free-shards.ts index ca026139c..01760f1be 100755 --- a/scripts/test-free-shards.ts +++ b/scripts/test-free-shards.ts @@ -930,23 +930,6 @@ function formatShardSummary(shards: string[][]): string[] { }); } -/** - * True when a shard's output shows the run ended WITHOUT bun's final summary - * ("Ran N tests across ..."). A process.exit() fired mid-suite skips the - * summary AND hands back whatever code the caller passed — historically 0, - * which made a truncated shard indistinguishable from a green one. Exit code - * alone is therefore not evidence of completion; the summary line is. - * - * The runner itself now enforces this (and more) through - * scripts/test-strict-output.ts inside runFreeShard; this predicate remains - * the minimal documented primitive that test/exit-propagation.test.ts drives - * with genuine truncated and genuine complete bun runs. - */ -export function shardRunLooksTruncated(status: number | null, output: string): boolean { - if (status !== 0) return false; // already failing — not the silent case - return !/Ran \d+ tests? across \d+ files?/.test(output); -} - // --------------------------------------------------------------------------- // Output contract: console filtering + per-file failure attribution. // diff --git a/test/audit-compliance.test.ts b/test/audit-compliance.test.ts index 2fbdd7580..f8623ddec 100644 --- a/test/audit-compliance.test.ts +++ b/test/audit-compliance.test.ts @@ -118,12 +118,6 @@ describe('Audit compliance', () => { }); // Fix 5: Data flow documentation in review.ts - test('review.ts has data flow documentation', () => { - const review = readFileSync(join(ROOT, 'scripts/resolvers/review.ts'), 'utf-8'); - expect(review).toContain('Data sent'); - expect(review).toContain('Data NOT sent'); - }); - // Round 2 Fix 3: Extension sender validation + message type allowlist test('extension background.js validates message sender', () => { const bg = readFileSync(join(ROOT, 'extension/background.js'), 'utf-8'); diff --git a/test/brain-cache-spec.test.ts b/test/brain-cache-spec.test.ts index 05fb1fbc4..7e6c01d66 100644 --- a/test/brain-cache-spec.test.ts +++ b/test/brain-cache-spec.test.ts @@ -22,12 +22,10 @@ import { AUTOPLAN_PREFLIGHT_BUDGET_BYTES, SALIENCE_DEFAULT_ALLOWLIST, SKILL_CALIBRATION_WEIGHTS, - TRANSPORT_DEFAULT_POLICY, USER_SLUG_RESOLUTION_ORDER, GSTACK_SCHEMA_PACK_NAME, GSTACK_SCHEMA_PACK_VERSION, CACHE_REFRESH_LOCK_TIMEOUT_MS, - SKILL_RUN_RETENTION_DAYS, getCacheFile, getSkillSubset, getSkillBudget, @@ -111,18 +109,6 @@ describe('brain-cache-spec internal consistency', () => { } }); - test('transport policy defaults exist for all transport modes', () => { - const required = ['local-pglite', 'local-stdio', 'remote-http-single-tenant', 'remote-http-ambiguous']; - for (const transport of required) { - expect(TRANSPORT_DEFAULT_POLICY[transport]).toBeDefined(); - } - // Local transports must default personal (D4 / Phase 1.5 default rule) - expect(TRANSPORT_DEFAULT_POLICY['local-pglite']).toBe('personal'); - expect(TRANSPORT_DEFAULT_POLICY['local-stdio']).toBe('personal'); - // Ambiguous remote MUST require explicit ask (never silent default) - expect(TRANSPORT_DEFAULT_POLICY['remote-http-ambiguous']).toBe('unset'); - }); - test('user-slug resolution chain has 4 deterministic fallbacks ending in non-empty', () => { expect(USER_SLUG_RESOLUTION_ORDER.length).toBe(4); expect(USER_SLUG_RESOLUTION_ORDER[USER_SLUG_RESOLUTION_ORDER.length - 1]).toBe('anonymous_hostname_sha8'); @@ -137,10 +123,6 @@ describe('brain-cache-spec internal consistency', () => { expect(CACHE_REFRESH_LOCK_TIMEOUT_MS).toBe(5 * 60_000); }); - test('skill-run retention is 90 days per D10 lifecycle policy', () => { - expect(SKILL_RUN_RETENTION_DAYS).toBe(90); - }); - test('invalidation graph: every "skill-run-write" target also depends on it', () => { // recent-decisions invalidates on skill-run-write — verify the contract holds const targets = getInvalidationTargets('skill-run-write'); diff --git a/test/exit-propagation.test.ts b/test/exit-propagation.test.ts index c264d9bf0..aa53a50e7 100644 --- a/test/exit-propagation.test.ts +++ b/test/exit-propagation.test.ts @@ -3,7 +3,7 @@ import { spawnSync } from 'child_process'; import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; -import { shardRunLooksTruncated } from '../scripts/test-free-shards'; +import { BunTestOutputClassifier, strictTestExitCode } from '../scripts/test-strict-output'; // Fault-injection companion to test/no-suicide-exit.test.ts. // @@ -11,9 +11,10 @@ import { shardRunLooksTruncated } from '../scripts/test-free-shards'; // process.exit. This file proves, with real bun output, WHY that guard and // the sharded runner's summary check both exist: `bun test` itself exits 0 // when a mid-suite process.exit(0) fires — the truncated run is -// indistinguishable from a green one by exit code alone. The sharded -// runner's shardRunLooksTruncated() predicate is the detection layer; these -// tests drive it with genuine truncated and genuine complete runs. +// indistinguishable from a green one by exit code alone. The runner's strict +// verdict (BunTestOutputClassifier + strictTestExitCode, used by runFreeShard) +// is the detection layer; these tests drive it with genuine truncated and +// genuine complete runs. function runBunTest(dir: string) { return spawnSync('bun', ['test', '.'], { @@ -24,6 +25,13 @@ function runBunTest(dir: string) { }); } +function strictVerdict(r: ReturnType, expectedFiles: number): number { + const classifier = new BunTestOutputClassifier(); + classifier.write(r.stdout ?? '', 'stdout'); + classifier.write(r.stderr ?? '', 'stderr'); + return strictTestExitCode(r.status ?? 1, classifier.end(), expectedFiles); +} + function withFixtureDir(files: Record, fn: (dir: string) => void) { const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'exit-prop-')); try { @@ -46,16 +54,15 @@ const FAILING_FIXTURE = fs.readFileSync(path.join(FIXTURES, 'failing.txt'), 'utf const PASSING_FIXTURE = fs.readFileSync(path.join(FIXTURES, 'passing.txt'), 'utf8'); describe('exit-code propagation (fault injection)', () => { - test('a mid-suite process.exit(0) yields exit 0 with NO summary — and the shard predicate catches it', () => { + test('a mid-suite process.exit(0) yields exit 0 with NO summary — and the strict verdict fails it', () => { withFixtureDir( { 'a-suicide.test.ts': SUICIDE_FIXTURE, 'b-failing.test.ts': FAILING_FIXTURE }, (dir) => { const r = runBunTest(dir); - const combined = `${r.stdout ?? ''}${r.stderr ?? ''}`; if (r.status === 0) { - // The dangerous shape: green exit, truncated run. The predicate - // MUST flag it — this is the assertion that guards the suite. - expect(shardRunLooksTruncated(r.status, combined)).toBe(true); + // The dangerous shape: green exit, truncated run. The strict + // verdict MUST fail it — this is the assertion that guards the suite. + expect(strictVerdict(r, 2)).not.toBe(0); } else { // If a future bun version starts propagating the failure itself, // even better — nothing to detect. Either way, never green+silent. @@ -68,18 +75,16 @@ describe('exit-code propagation (fault injection)', () => { test('a complete green run is NOT flagged as truncated', () => { withFixtureDir({ 'ok.test.ts': PASSING_FIXTURE }, (dir) => { const r = runBunTest(dir); - const combined = `${r.stdout ?? ''}${r.stderr ?? ''}`; expect(r.status).toBe(0); - expect(shardRunLooksTruncated(r.status, combined)).toBe(false); + expect(strictVerdict(r, 1)).toBe(0); }); }); - test('a plain failing run propagates nonzero and is not the silent case', () => { + test('a plain failing run propagates nonzero through the strict verdict', () => { withFixtureDir({ 'fail.test.ts': FAILING_FIXTURE }, (dir) => { const r = runBunTest(dir); - const combined = `${r.stdout ?? ''}${r.stderr ?? ''}`; expect(r.status).not.toBe(0); - expect(shardRunLooksTruncated(r.status, combined)).toBe(false); + expect(strictVerdict(r, 1)).not.toBe(0); }); }); }); diff --git a/test/gstack-schema-pack.test.ts b/test/gstack-schema-pack.test.ts index 8d9b55e8f..ad4305a36 100644 --- a/test/gstack-schema-pack.test.ts +++ b/test/gstack-schema-pack.test.ts @@ -4,7 +4,7 @@ * Asserts the schema pack is well-formed and matches the v1.48 plan: * - Exactly 8 page types (7 entities + 1 take) * - Frontmatter shape is internally consistent - * - Retention policies match SKILL_RUN_RETENTION_DAYS spec + * - Retention policies (skill-run pages archive after 90 days) * - Link verbs only reference declared verbs * - JSON payload shape is acceptable to mcp__gbrain__schema_apply_mutations * diff --git a/test/skill-coverage-floor.test.ts b/test/skill-coverage-floor.test.ts index 4f75e370b..c3ab5f5f9 100644 --- a/test/skill-coverage-floor.test.ts +++ b/test/skill-coverage-floor.test.ts @@ -8,17 +8,14 @@ * frontmatter regressions, missing generated header, empty/trivial bodies, * and dangling SKILL.md.tmpl-without-SKILL.md mismatches. * - * Pairs with test/skill-coverage-matrix.ts (the registry) and - * test/parity-suite.test.ts (the content-invariant suite). Together, - * v1.45.0.0 ships with: floor (this file) + matrix (registry CI gate) - * + invariants (content per skill family) + size budget. That's the - * eval-first foundation the v2.0.0.0 sections/ work builds on. + * Pairs with test/parity-suite.test.ts (the content-invariant suite). + * The floor iterates every authored skill from skillCensus(), so a new + * skill is covered without registering it anywhere. */ import { describe, test, expect } from 'bun:test'; import * as fs from 'fs'; import * as path from 'path'; -import { SKILL_COVERAGE } from './skill-coverage-matrix'; import { skillCensus } from './helpers/skill-census'; const REPO_ROOT = path.resolve(import.meta.dir, '..'); @@ -32,30 +29,9 @@ function readSkillMd(skill: string): string | null { } } -// Registry-completeness assertions ("every skill on disk is registered", -// "every entry has a gate test") live in test/skill-coverage-matrix.test.ts — -// they were duplicated here with a DIFFERENT hand-rolled directory walk, which -// is the divergence class test/helpers/skill-census.ts exists to kill. This -// file owns the per-skill structural compliance checks only. - describe('skill-coverage-floor: every skill passes structural compliance', () => { const skills = skillCensus(REPO_ROOT).authoredSkills; - test('every gate-tier test path referenced in registry exists on disk', () => { - const missing: string[] = []; - for (const [skill, coverage] of Object.entries(SKILL_COVERAGE)) { - for (const testPath of [...coverage.gate, ...coverage.periodic]) { - const fullPath = path.join(REPO_ROOT, testPath); - if (!fs.existsSync(fullPath)) { - missing.push(`${skill} → ${testPath}`); - } - } - } - if (missing.length > 0) { - throw new Error(`Registry references missing test files:\n ${missing.join('\n ')}`); - } - }); - // Per-skill structural compliance (file IO only, no LLM) for (const skill of skills) { describe(`skill: ${skill}`, () => { diff --git a/test/skill-coverage-matrix.test.ts b/test/skill-coverage-matrix.test.ts deleted file mode 100644 index 30ec45c18..000000000 --- a/test/skill-coverage-matrix.test.ts +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Skill coverage matrix CI gate (v1.45.0.0 T1). - * - * Asserts every skill on disk has an entry in SKILL_COVERAGE with at - * least one gate-tier test. The detailed per-skill structural checks - * live in test/skill-coverage-floor.test.ts; this file is the matrix- - * level gate that surfaces "skill added but eval not registered" cleanly. - */ - -import { describe, test, expect } from 'bun:test'; -import * as path from 'path'; -import { SKILL_COVERAGE, type SkillCoverage } from './skill-coverage-matrix'; -import { skillCensus } from './helpers/skill-census'; - -const REPO_ROOT = path.resolve(import.meta.dir, '..'); - -// Canonical walk (skill-census.ts). This file and skill-coverage-floor -// previously hand-rolled two DIFFERENT walks (one skipped node_modules/docs/ -// test, one didn't) — exactly the divergence class the census exists to kill. -function discoverSkills(): string[] { - return skillCensus(REPO_ROOT).authoredSkills; -} - -describe('skill coverage matrix', () => { - test('SKILL_COVERAGE is exported and non-empty', () => { - expect(typeof SKILL_COVERAGE).toBe('object'); - expect(Object.keys(SKILL_COVERAGE).length).toBeGreaterThan(0); - }); - - test('every entry has the right shape', () => { - const missingGate: string[] = []; - for (const [skill, coverage] of Object.entries(SKILL_COVERAGE)) { - expect(Array.isArray(coverage.gate)).toBe(true); - expect(Array.isArray(coverage.periodic)).toBe(true); - if (!coverage.gate || coverage.gate.length === 0) missingGate.push(skill); - for (const p of [...coverage.gate, ...coverage.periodic]) { - expect(typeof p).toBe('string'); - expect(p.startsWith('test/')).toBe(true); - expect(p.endsWith('.test.ts')).toBe(true); - } - } - if (missingGate.length > 0) { - throw new Error( - `Skills with no gate-tier eval: ${missingGate.join(', ')}. ` + - `Eval-first foundation requires at least one CI-blocking check per skill.`, - ); - } - }); - - test('every skill on disk has a registry entry', () => { - const skills = discoverSkills(); - const missing: string[] = []; - for (const s of skills) { - if (!SKILL_COVERAGE[s]) missing.push(s); - } - if (missing.length > 0) { - throw new Error( - `Skills on disk missing from SKILL_COVERAGE: ${missing.join(', ')}. ` + - `Add an entry to test/skill-coverage-matrix.ts with at least ` + - `'test/skill-coverage-floor.test.ts' in gate[].`, - ); - } - }); - - test('no registry entry references a skill that does not exist on disk', () => { - const skills = new Set(discoverSkills()); - const orphans: string[] = []; - for (const skill of Object.keys(SKILL_COVERAGE)) { - if (!skills.has(skill)) orphans.push(skill); - } - if (orphans.length > 0) { - throw new Error( - `Registry references skills not on disk: ${orphans.join(', ')}. ` + - `Remove from SKILL_COVERAGE or restore the skill directory.`, - ); - } - }); -}); diff --git a/test/skill-coverage-matrix.ts b/test/skill-coverage-matrix.ts deleted file mode 100644 index 2f4c67533..000000000 --- a/test/skill-coverage-matrix.ts +++ /dev/null @@ -1,226 +0,0 @@ -/** - * Skill coverage matrix (v1.45.0.0 T1, cathedral Phase 0). - * - * Single source of truth mapping each gstack skill to its E2E test files. - * The CI gate at test/skill-coverage-matrix.test.ts fails if a skill has - * no gate-tier entry, ensuring the eval-first foundation holds: every - * skill has at least one CI-blocking check that asserts must-have - * behavior. - * - * Two tiers per entry: - * gate CI-blocking, runs on every PR, target <$0.50/test or free. - * periodic Weekly cron, deeper coverage, can cost ~$1-$3/test. - * - * The 'floor' entry refers to test/skill-coverage-floor.test.ts — - * a structural-compliance smoke test that covers every skill with - * file-IO checks (free, no LLM cost). When a skill has only 'floor' - * coverage, that's the eval-first minimum; future work can layer - * behavioral checks on top. - */ - -export interface SkillCoverage { - /** Gate-tier test file paths (relative to repo root). At least one required per skill. */ - gate: string[]; - /** Periodic-tier test file paths. Optional but recommended. */ - periodic: string[]; - /** Brief note on why this coverage is the right shape for this skill. */ - rationale?: string; -} - -/** - * Per-skill coverage. Keys MUST match the top-level skill directory name. - * The CI test asserts every skill in the repo has an entry here AND that - * gate[] is non-empty. - * - * Adding a new skill: add an entry here AND either reference an existing - * test that covers it OR add 'test/skill-coverage-floor.test.ts' as the - * minimum gate-tier check. - */ -export const SKILL_COVERAGE: Record = { - // ─── Core loop ────────────────────────────────────────────── - ship: { - gate: ['test/skill-e2e-ship-idempotency.test.ts', 'test/skill-coverage-floor.test.ts'], - periodic: ['test/skill-e2e-workflow.test.ts'], - }, - review: { - gate: ['test/skill-e2e-review.test.ts', 'test/skill-e2e-shared-libs.test.ts', 'test/skill-e2e-shared-libs-paths.test.ts', 'test/shared-libs-evidence.test.ts', 'test/shared-libs-rendering.test.ts', 'test/skill-coverage-floor.test.ts'], - periodic: ['test/skill-e2e-review-army.test.ts', 'test/regression-1539-review-self-verify.test.ts'], - }, - 'deslop-shared-libs': { - gate: ['test/shared-libs-rendering.test.ts', 'test/skill-e2e-shared-libs.test.ts', 'test/skill-coverage-floor.test.ts'], - periodic: ['test/skill-e2e-shared-libs-periodic.test.ts', 'test/codex-e2e-shared-libs.test.ts'], - rationale: 'Free host/discovery checks; native gate traces enforce read-only source access and the actual review advisory lifecycle. Periodic evaluates opportunity and PR coverage judgment.', - }, - qa: { - gate: ['test/skill-e2e-qa-workflow.test.ts', 'test/skill-coverage-floor.test.ts'], - periodic: ['test/skill-e2e-qa-workflow.test.ts', 'test/skill-e2e-qa-bugs.test.ts', 'test/skill-e2e-aside.test.ts'], - rationale: 'qa-quick / qa-only-no-fix / qa-bootstrap are gate: the skill drives Aside when it is live and the gstack browse binary otherwise, so CI runs the fallback path. The planted-bug benchmarks, the fix loop and the live-Aside run (aside-qa-quick) are periodic.', - }, - 'qa-only': { - gate: ['test/skill-coverage-floor.test.ts'], - periodic: [], - rationale: 'qa-only is qa with --report-only; behavior tested via /qa coverage.', - }, - investigate: { - gate: ['test/skill-coverage-floor.test.ts'], - periodic: [], - }, - browse: { - gate: ['test/skill-e2e-bws.test.ts', 'test/skill-coverage-floor.test.ts'], - periodic: ['test/skill-e2e-aside.test.ts'], - rationale: '/browse drives the Aside browser first (the live E2E aside-browse-basic / aside-browse-flow needs a running Aside, so it is periodic) and the gstack browse binary as fallback (browse-basic / browse-snapshot exercise it, gate; the binary has its own integration suite under browse/test/). Local-HTML rendering (lib/aside-render.ts, bin/gstack-render.ts) is a library, covered by test/aside-render.test.ts.', - }, - spec: { - gate: [ - 'test/spec-template-invariants.test.ts', - 'test/spec-template-sync.test.ts', - 'test/skill-coverage-floor.test.ts', - ], - periodic: [ - 'test/skill-e2e-spec-execute.test.ts', - 'test/skill-llm-eval-spec.test.ts', - ], - rationale: '37 deterministic invariants pin Phase 1/3 gating, --execute race/security hardening, quality-gate redaction, archive contract, plan-mode-aware Phase 5. Periodic adds full PTY pipeline + LLM-judge.', - }, - - // ─── Plan triad ───────────────────────────────────────────── - 'plan-ceo-review': { - gate: [ - 'test/skill-e2e-plan-ceo-finding-floor.test.ts', - 'test/skill-e2e-plan-ceo-plan-mode.test.ts', - 'test/skill-coverage-floor.test.ts', - ], - periodic: [ - 'test/skill-e2e-plan-ceo-finding-count.test.ts', - 'test/skill-e2e-plan-ceo-mode-routing.test.ts', - ], - }, - 'plan-eng-review': { - gate: [ - 'test/shared-libs-rendering.test.ts', - 'test/skill-e2e-plan-eng-finding-floor.test.ts', - 'test/skill-e2e-plan-eng-plan-mode.test.ts', - 'test/skill-coverage-floor.test.ts', - ], - periodic: [ - 'test/skill-e2e-shared-libs-periodic.test.ts', - 'test/skill-e2e-plan-eng-finding-count.test.ts', - 'test/skill-e2e-plan-eng-multi-finding-batching.test.ts', - ], - }, - 'plan-design-review': { - gate: [ - 'test/skill-e2e-plan-design-finding-floor.test.ts', - 'test/skill-e2e-plan-design-plan-mode.test.ts', - 'test/skill-e2e-plan-design-with-ui.test.ts', - 'test/skill-coverage-floor.test.ts', - ], - periodic: ['test/skill-e2e-plan-design-finding-count.test.ts'], - }, - 'plan-devex-review': { - gate: [ - 'test/skill-e2e-plan-devex-finding-floor.test.ts', - 'test/skill-e2e-plan-devex-plan-mode.test.ts', - 'test/skill-coverage-floor.test.ts', - ], - periodic: ['test/skill-e2e-plan-devex-finding-count.test.ts'], - }, - autoplan: { - gate: ['test/skill-coverage-floor.test.ts'], - periodic: ['test/skill-e2e-autoplan-chain.test.ts', 'test/skill-e2e-autoplan-dual-voice.test.ts'], - }, - 'office-hours': { - gate: ['test/skill-e2e-office-hours.test.ts', 'test/skill-coverage-floor.test.ts'], - periodic: ['test/skill-e2e-office-hours-auto-mode.test.ts', 'test/skill-e2e-office-hours-phase4.test.ts'], - }, - - // ─── Polish + design ──────────────────────────────────────── - 'design-review': { - gate: ['test/skill-coverage-floor.test.ts'], - periodic: ['test/skill-e2e-design.test.ts'], - rationale: 'design-review-fix drives the Aside browser (periodic; skips without one).', - }, - 'design-consultation': { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - 'design-shotgun': { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - 'design-html': { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - diagram: { - gate: ['test/skill-e2e-diagram.test.ts', 'test/skill-coverage-floor.test.ts'], - periodic: ['test/skill-e2e-diagram.test.ts'], - rationale: 'Triplet contract is gate-tier deterministic (gstack-render drives Aside when live, the browse daemon otherwise, so CI runs it); authoring-quality judge is periodic (E2E_TIERS: diagram-triplet/diagram-authoring-quality). The renderer itself is pinned free by test/aside-render.test.ts.', - }, - cso: { - gate: ['test/skill-e2e-cso.test.ts', 'test/cso-preserved.test.ts', 'test/skill-coverage-floor.test.ts'], - periodic: [], - rationale: 'cso-preserved.test.ts pins must-not-strip security guidance phrases.', - }, - 'document-release': { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - 'document-generate': { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - - // ─── Ops + integrations ───────────────────────────────────── - 'land-and-deploy': { gate: ['test/skill-e2e-deploy.test.ts', 'test/skill-coverage-floor.test.ts'], periodic: [] }, - canary: { - gate: ['test/skill-e2e-deploy.test.ts', 'test/skill-coverage-floor.test.ts'], - periodic: ['test/skill-e2e-aside.test.ts'], - rationale: 'canary-workflow (gate) runs the skill in simulation without a browser; aside-canary-quick drives Aside live (periodic).', - }, - benchmark: { - gate: ['test/skill-e2e-deploy.test.ts', 'test/skill-e2e-benchmark-providers.test.ts', 'test/skill-coverage-floor.test.ts'], - periodic: [], - rationale: 'benchmark-workflow (gate) runs the skill in simulation without a browser.', - }, - 'benchmark-models': { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - codex: { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - retro: { - gate: ['test/skill-coverage-floor.test.ts'], - periodic: ['test/regression-1624-retro-stale-base.test.ts'], - }, - 'gstack-upgrade': { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - 'context-save': { gate: ['test/skill-e2e-context-skills.test.ts', 'test/skill-coverage-floor.test.ts'], periodic: [] }, - 'context-restore': { gate: ['test/skill-e2e-context-skills.test.ts', 'test/skill-coverage-floor.test.ts'], periodic: [] }, - 'setup-deploy': { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - 'setup-browser-cookies': { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - 'setup-gbrain': { - gate: [ - 'test/skill-e2e-setup-gbrain-bad-token.test.ts', - 'test/skill-e2e-setup-gbrain-path4-local-pglite.test.ts', - 'test/skill-e2e-setup-gbrain-remote.test.ts', - 'test/skill-coverage-floor.test.ts', - ], - periodic: [], - }, - 'sync-gbrain': { - gate: ['test/skill-coverage-floor.test.ts'], - periodic: ['test/regression-1611-gbrain-sync-resume.test.ts'], - }, - 'open-gstack-browser': { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - 'pair-agent': { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - scrape: { - gate: ['test/skill-coverage-floor.test.ts'], - periodic: ['test/skill-e2e-skillify.test.ts', 'test/skill-e2e-aside.test.ts'], - rationale: '/scrape is Aside-first: aside-scrape-json drives Aside live and checks the JSON-only output discipline (periodic; skips without Aside). scrape-match-path / scrape-prototype-path assert the browser-skills `$B skill list` / `skill run` flow, which the Aside-first template no longer prescribes in its fallback — periodic until the fallback carries it again.', - }, - skillify: { gate: ['test/skill-e2e-skillify.test.ts', 'test/skill-coverage-floor.test.ts'], periodic: [] }, - learn: { gate: ['test/skill-e2e-learnings.test.ts', 'test/skill-coverage-floor.test.ts'], periodic: [] }, - 'plan-tune': { gate: ['test/skill-e2e-plan-tune.test.ts', 'test/skill-coverage-floor.test.ts'], periodic: [] }, - - // ─── iOS family ───────────────────────────────────────────── - 'ios-qa': { gate: ['test/skill-e2e-ios.test.ts', 'test/skill-coverage-floor.test.ts'], periodic: ['test/skill-e2e-ios-device.test.ts', 'test/skill-e2e-ios-swift-build.test.ts'] }, - 'ios-fix': { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - 'ios-clean': { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - 'ios-sync': { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - 'ios-design-review': { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - - // ─── Safety / housekeeping ────────────────────────────────── - careful: { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - freeze: { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - unfreeze: { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - guard: { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - 'landing-report': { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - health: { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, - 'make-pdf': { - gate: ['test/skill-coverage-floor.test.ts'], - periodic: [], - rationale: 'make-pdf is a binary with its own free suite under make-pdf/test/ (print pipeline via lib/aside-render.ts); the skill doc is structure-checked by the floor.', - }, - 'devex-review': { gate: ['test/skill-coverage-floor.test.ts'], periodic: [] }, -}; diff --git a/test/touchfiles-facade.test.ts b/test/touchfiles-facade.test.ts index 9e36c1ea2..c60ec8ecf 100644 --- a/test/touchfiles-facade.test.ts +++ b/test/touchfiles-facade.test.ts @@ -5,9 +5,8 @@ * (a) touchfiles-data.ts stays LITERALS ONLY — no imports/requires, no call * expressions, no spreads, no template literals. Map-diff selection * evaluates old git versions of that file standalone; any logic breaks it. - * (b) the ./helpers/touchfiles facade re-exports EVERY export of both halves - * by identity (===), so existing import sites see the same objects. - * (c) the data file's exports are importable and non-empty. + * (b) the data file's exports are importable and non-empty. A missing facade + * re-export needs no test: Bun fails every importer at link time. */ import { describe, test, expect } from 'bun:test'; @@ -15,8 +14,6 @@ import { readFileSync } from 'fs'; import * as path from 'path'; import * as data from './helpers/touchfiles-data'; -import * as logic from './helpers/test-selection'; -import * as facade from './helpers/touchfiles'; const DATA_PATH = path.join(import.meta.dir, 'helpers', 'touchfiles-data.ts'); @@ -124,40 +121,6 @@ describe('touchfiles-data.ts literal-only tripwire', () => { }); }); -describe('facade export parity', () => { - test('every touchfiles-data export is re-exported by identity', () => { - const dataExports = Object.keys(data); - expect(dataExports.length).toBeGreaterThan(0); - for (const name of dataExports) { - expect( - (facade as Record)[name], - `facade must re-export '${name}' from touchfiles-data by identity`, - ).toBe((data as Record)[name] as never); - } - }); - - test('every test-selection export is re-exported by identity', () => { - const logicExports = Object.keys(logic); - expect(logicExports.length).toBeGreaterThan(0); - for (const name of logicExports) { - expect( - (facade as Record)[name], - `facade must re-export '${name}' from test-selection by identity`, - ).toBe((logic as Record)[name] as never); - } - }); - - test('facade exports exactly the union of both halves', () => { - const union = new Set([...Object.keys(data), ...Object.keys(logic)]); - expect(new Set(Object.keys(facade))).toEqual(union); - }); - - test('no export name collisions between data and logic', () => { - const overlap = Object.keys(data).filter((k) => k in logic); - expect(overlap).toEqual([]); - }); -}); - describe('touchfiles-data exports are importable and non-empty', () => { test('E2E_TOUCHFILES has entries with non-empty pattern lists', () => { const keys = Object.keys(data.E2E_TOUCHFILES); @@ -167,14 +130,6 @@ describe('touchfiles-data exports are importable and non-empty', () => { } }); - test('E2E_TIERS has entries with valid tier values', () => { - const entries = Object.entries(data.E2E_TIERS); - expect(entries.length).toBeGreaterThan(0); - for (const [key, tier] of entries) { - expect(['gate', 'periodic'], `E2E_TIERS['${key}'] has invalid tier`).toContain(tier); - } - }); - test('LLM_JUDGE_TOUCHFILES has entries with non-empty pattern lists', () => { const keys = Object.keys(data.LLM_JUDGE_TOUCHFILES); expect(keys.length).toBeGreaterThan(0);