From 67f636a4d3a850970fcac8b5e7f74406e0aa6cd7 Mon Sep 17 00:00:00 2001 From: garrytan Date: Fri, 16 Oct 2026 23:51:20 +0000 Subject: [PATCH] test(ship-queue): receipt digest contract names lib/ship-queue.ts for its pregate lane Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> (cherry picked from commit 501637c2585b2903aa27b879857f3df8b69777c1) --- test/gstack-ship-queue.test.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/gstack-ship-queue.test.ts b/test/gstack-ship-queue.test.ts index 96b302788..92a59a864 100644 --- a/test/gstack-ship-queue.test.ts +++ b/test/gstack-ship-queue.test.ts @@ -15,7 +15,9 @@ import * as fs from 'node:fs'; import * as path from 'node:path'; import { EXIT } from '../lib/headless-artifacts'; import { SHIP_QUEUE_KEYS_VERSION } from '../lib/ship-policy'; +import { receiptDigest } from '../lib/ship-queue'; import { applyStampPatch } from '../lib/ship-queue-gate'; +import type { TreeReceipt } from '../lib/tree-receipt'; import { BASE_POLICY, BIN, cleanup, makeFixtureRepo, makePr, mergeMain, mergeToMain, restamp, runBin, type FixtureRepo } from './helpers/restamp-fixture'; import { coordinatorClone, ghQueueShim } from './helpers/ship-queue-fixture'; @@ -280,3 +282,20 @@ describe('ready', () => { expect(queue(repo, ['ready', '--pr', '1'], shim(moved, green)).err).toMatch(/uncommitted tracked changes: pr-a\.txt.*\(QUEUE_NOT_READY\)/); }, 180_000); }); + +describe('receipt digest', () => { + const receipt = (files: Array<{ path: string; rule: string; verdict: string }>, extra: Partial = {}) => ({ + gated_tree: 'a'.repeat(40), current_tree: 'b'.repeat(40), old_version: '1.2.3.0', new_version: '1.2.4.0', + files, tree: 'same-modulo-stamps', stamp_diff: '-1.2.3.0\n+1.2.4.0', ...extra, + }) as unknown as TreeReceipt; + const files = [{ path: 'VERSION', rule: 'version', verdict: 'stamp-only' }, { path: 'CHANGELOG.md', rule: 'changelog', verdict: 'stamp-only' }]; + + test('binds the proof fields and ignores file order, so verify compares the same receipt from any clone', () => { + const d = receiptDigest(receipt(files)); + expect(d).toMatch(/^[0-9a-f]{64}$/); + expect(receiptDigest(receipt([...files].reverse()))).toBe(d); + expect(receiptDigest(receipt([files[0], { ...files[1], verdict: 'changed' }]))).not.toBe(d); + expect(receiptDigest(receipt(files, { current_tree: 'c'.repeat(40) }))).not.toBe(d); + expect(receiptDigest(receipt(files, { new_version: '1.2.5.0' }))).not.toBe(d); + }); +});