import { describe, expect, test } from 'bun:test' import { readFileSync } from 'node:fs' import { join } from 'node:path' import { PACK_BLOB_VERSION, decodePackBlob, isV2Envelope } from './pack-blob' /** * BACKWARD-COMPAT FREEZE TESTS for the memory pack-blob envelope. * * Reads FROZEN envelope bytes committed under test/fixtures/compat/ and decodes * them with the CURRENT code. The pack-blob is the on-chain memory partition * (iNFT slot 0 / slot 3, pre-encryption plaintext). A non-additive change to * the envelope format would brick every existing agent's memory on the next * reprovision/restore, and no other test catches it because they all generate * their input with the current encoder. * * Fixtures produced once by test/fixtures/compat/__generate.ts; bytes immutable. * NEW envelope versions add a NEW fixture; never edit a frozen one. */ const FIXTURES = join(import.meta.dir, '../../../../test/fixtures/compat') function fixture(name: string): Uint8Array { return new Uint8Array(readFileSync(join(FIXTURES, name))) } describe('pack-blob backward-compat (frozen fixtures)', () => { test('FROZEN v2 envelope is sniffed as v2 and decodes to the same files', () => { const bytes = fixture('pack-blob-v2.json') expect(isV2Envelope(bytes)).toBe(true) const blob = decodePackBlob(bytes) expect(blob.v).toBe(PACK_BLOB_VERSION) expect(blob.root).toContain('# MEMORY.md') expect(blob.root).toContain('frozen compat index') expect(blob.files['learned-frozen.md']).toContain('frozen for compat') expect(blob.files['operator-preferences.md']).toContain('dark mode') expect(Object.keys(blob.files).sort()).toEqual(['learned-frozen.md', 'operator-preferences.md']) }) test('FROZEN legacy v1 markdown blob is NOT a v2 envelope (v1 fallthrough path stays live)', () => { const bytes = fixture('pack-blob-v1-legacy.md') // Pre-v0.24.0 stored slot 0/3 as raw markdown text. isV2Envelope must keep // returning false so callers fall through to the legacy single-file decode // instead of trying (and failing) to parse it as a JSON envelope. expect(isV2Envelope(bytes)).toBe(false) // And the raw text is recoverable verbatim (the v1 "decode" is identity). expect(new TextDecoder().decode(bytes)).toContain('legacy single-file markdown body') }) test('FROZEN legacy v1 markdown blob throws if force-decoded as v2 (no silent corruption)', () => { const bytes = fixture('pack-blob-v1-legacy.md') expect(() => decodePackBlob(bytes)).toThrow() }) })