Files
buzz/beehive/test/handoff-selection.test.ts
2026-09-10 02:03:52 -04:00

37 lines
3.1 KiB
TypeScript

import { test } from 'node:test';
import assert from 'node:assert/strict';
import { createGenesis } from '../src/assignment.ts';
import { hash, semanticHash, sameSelection, moveSelection, validateAssignment, type Grant } from '../src/handoff.ts';
import { message, newKey, publicKey } from '../src/protocol.ts';
import { profileRevision } from '../src/profiles.ts';
const reorder = (v: any): any => Array.isArray(v) ? v.map(reorder) : v !== null && typeof v === 'object' ? Object.fromEntries(Object.entries(v).reverse().map(([k,x]) => [k,reorder(x)])) : v;
test('validated grant selections are semantic; legacy identity hashes and ordered protocol arrays remain exact', () => {
const genesis = createGenesis(publicKey(newKey()), publicKey(newKey()), 'source');
const behavior = { name: 'Source', parent: null, instructions: 'Exact source instructions', revision: profileRevision('Source', null, 'Exact source instructions') };
const requested = { model: 'fixture-model', workspace: '/fixture', profile: behavior.revision, configuration: { name: 'Destination', revision: 1 }, behavior };
const operation = message('move', 'source', genesis.agent, 2, { target: 'target', targetRevision: 1, selection: reorder(requested) });
const base: Grant = { root: hash(genesis), predecessor: hash(genesis), source: 'source', target: 'target', agent: genesis.agent, operation, prepared: 'immutable-token', selection: requested, targetRevision: 1, sourceRun: null };
const validate = (g: Grant) => validateAssignment({ genesis, assignedHost: 'target', chain: [g] });
validate(base); // Historical grants retain their existing hash and selection meaning.
const grant: Grant = { ...base, materialization: 'named-v1', selection: moveSelection(requested, 1, 'named-v1') };
validate(grant); validate({ ...grant, selection: reorder(grant.selection) });
assert.ok(sameSelection(requested, reorder(requested)));
assert.notEqual(hash(requested), hash(reorder(requested)));
assert.equal(semanticHash(requested), semanticHash(reorder(requested)));
assert.notEqual(semanticHash(['a','b']), semanticHash(['b','a']));
for (const selection of [
{ ...grant.selection, workspace: '/other' }, { ...grant.selection, extra: true },
{ ...grant.selection, behavior: { ...behavior, extra: true } },
{ ...grant.selection, configuration: { name: 'Destination', revision: 1 } },
{ ...grant.selection, profile: 'default' },
Object.fromEntries(Object.entries(grant.selection).filter(([k]) => k !== 'model')),
]) assert.throws(() => validate({ ...grant, selection } as Grant));
assert.throws(() => validate({ ...grant, extra: true } as Grant));
assert.throws(() => validate({ ...grant, materialization: 'unknown' } as any));
const missing = { ...grant } as any; delete missing.prepared; assert.throws(() => validate(missing));
const { configuration: _configuration, ...implicit } = requested;
assert.deepEqual(moveSelection(implicit, 0, 'named-v1').configuration, { name: 'default', revision: 2 });
assert.equal(moveSelection(requested, 0, 'named-v1').configuration!.revision, 2, 'initial projected @1 is never reused');
});