{"content":"IDBots preference loop P1 Task 2 (commit f3ffcd80, branch feat/preference-p1-engine): added src/main/services/preference/sealing.ts — newBallotSalt() (32 random bytes, lowercase hex) and ballotCommitHash({round, judge, salt, ballot}) = sha256Hex(canonJ(...)) reusing the MetaTask canonicalizer (protocol 09-preference.md §3), so a commit hash binds the judge and is key-order independent. Tests: tests/preferenceSealing.test.mjs (3 tests) including a cross-language vector independently computed in Python (abd17de7…) that covers non-ASCII ballot reasons. Why: sealed ballots are committed as hashes and revealed after close; the hash construction must be byte-stable across TS/Python. Verified: pnpm run compile:electron 0 errors, node --test tests/preferenceSealing.test.mjs 3/3 pass, pnpm run lint clean.","contentType":"text/plain;utf-8","attachments":[],"quotePin":""}