/**
 * Structural-equivalence tests for the BRAIN memory wire-shape contracts.
 *
 * These tests pin the field shapes of the 15 types promoted from
 * `packages/core/src/memory/brain-retrieval.ts` in Phase 0e of
 * SG-ARCH-SOLID (E-CONTRACTS-FOUNDATION). Accidental narrowing or
 * widening triggers a compile-time failure during `tsc -b` in the CI gate.
 *
 * The compile-time assertions use the conditional-equality trick
 * (`Equals<A, B>`) so any structural drift produces a TS2322 or TS2344
 * at build time. The runtime `expect` smoke verifies that constructible
 * literals satisfy each interface — these are pure type contracts with
 * no runtime, so this is a thin satisfies check rather than a behavior
 * test.
 *
 * @since SG-ARCH-SOLID Saga T9831 · E-CONTRACTS-FOUNDATION T9832 · T9956 (Phase 0e)
 */
import { describe, expect, it } from 'vitest';
import { BRAIN_OBSERVATION_SOURCE_TYPES, } from '../memory/observe.js';
// ─── Runtime constructibility smoke ─────────────────────────────────
describe('memory wire-shape contracts (T9956)', () => {
    it('BrainCompactHit is constructible with the canonical shape', () => {
        const hit = {
            id: 'O-abc123',
            type: 'observation',
            title: 'sample',
            date: '2026-05-21T00:00:00Z',
        };
        expect(hit.id).toBe('O-abc123');
        expect(hit.type).toBe('observation');
    });
    it('SearchBrainCompactResult composes BrainCompactHit and token accounting', () => {
        const result = {
            results: [{ id: 'O-1', type: 'observation', title: 't', date: '2026-05-21' }],
            total: 1,
            tokensEstimated: 50,
        };
        expect(result.results).toHaveLength(1);
        expect(result.tokensEstimated).toBe(50);
    });
    it('BrainAnchor and TimelineBrainResult compose correctly', () => {
        const anchor = { id: 'O-anchor', type: 'observation', data: { x: 1 } };
        const result = {
            anchor,
            before: [{ id: 'O-prev', type: 'observation', date: '2026-05-20' }],
            after: [{ id: 'O-next', type: 'observation', date: '2026-05-22' }],
        };
        expect(result.anchor?.id).toBe('O-anchor');
        expect(result.before).toHaveLength(1);
        expect(result.after).toHaveLength(1);
    });
    it('TimelineBrainResult accepts null anchor for unresolved IDs', () => {
        const result = { anchor: null, before: [], after: [] };
        expect(result.anchor).toBeNull();
    });
    it('FetchBrainEntriesResult tracks notFound IDs alongside resolved entries', () => {
        const result = {
            results: [{ id: 'O-1', type: 'observation', data: null }],
            notFound: ['O-missing'],
            tokensEstimated: 100,
        };
        expect(result.results).toHaveLength(1);
        expect(result.notFound).toContain('O-missing');
    });
    it('BRAIN_OBSERVATION_SOURCE_TYPES is the runtime tuple backing BrainObservationSourceType', () => {
        expect(BRAIN_OBSERVATION_SOURCE_TYPES).toEqual([
            'agent',
            'session-debrief',
            'claude-mem',
            'manual',
        ]);
        // The derived type must include every const member.
        const sample = [...BRAIN_OBSERVATION_SOURCE_TYPES];
        expect(sample).toHaveLength(4);
    });
    it('ObserveBrainParams accepts the minimal required shape (text only)', () => {
        const params = { text: 'hello world' };
        expect(params.text).toBe('hello world');
    });
    it('ObserveBrainResult mirrors the persisted row identity tuple', () => {
        const result = {
            id: 'O-new',
            type: 'observation',
            createdAt: '2026-05-21T12:00:00Z',
        };
        expect(result.id).toBe('O-new');
        expect(result.type).toBe('observation');
    });
    it('BudgetedRetrievalOptions composes all three optional filter axes', () => {
        const opts = {
            types: ['semantic', 'procedural'],
            tiers: ['medium', 'long'],
            verified: true,
        };
        expect(opts.types).toHaveLength(2);
        expect(opts.tiers).toHaveLength(2);
        expect(opts.verified).toBe(true);
    });
    it('BudgetedResult tracks token usage, remaining budget, and exclusion count', () => {
        const result = {
            entries: [
                {
                    id: 'L-1',
                    type: 'learning',
                    title: 'insight',
                    text: 'body',
                    score: 0.42,
                    tokensEstimated: 32,
                },
            ],
            tokensUsed: 32,
            tokensRemaining: 468,
            excluded: 0,
        };
        expect(result.entries).toHaveLength(1);
        expect(result.tokensUsed + result.tokensRemaining).toBe(500);
    });
});
//# sourceMappingURL=memory-wire-shapes.test.js.map