mirror of
https://github.com/affaan-m/ECC.git
synced 2026-09-17 23:28:04 +02:00
* feat: consolidate offline eval and operator workflows
Compose the retained framework, operator skill, roadmap and cleanup ranges on current main. Preserve current release dependencies and keep candidate execution disabled pending OS containment. Repair draft/DOCX behavior, obligation uniqueness, trusted send and audience guidance, runner provenance and eval diagnostics.
Source-PR: 2930 0abe3727d2b500c6e4830bdeb47ed67cae3f4785
Source-PR: 2931 992b49c44ed872def49675b791168b8fcd091df6
Source-PR: 2932 4a193dd13041cb7a6bebf4d2e910a0cd32bcc797
Source-PR: 2933 59cdfe500a91949ba1415f1edd7279620f21e804
Source-Base: ca185ef5f7
* fix: repair foundation CI and update js-yaml
* fix: reconcile pending-delete capsule locks after close
---------
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
53 lines
1.3 KiB
JavaScript
53 lines
1.3 KiB
JavaScript
'use strict';
|
|
|
|
/**
|
|
* Canonical JSON and hashing helpers shared by the eval-harness frameworks.
|
|
*
|
|
* Every hash in the capsule journal, the gate receipts, and the offline
|
|
* receipts is computed over canonical JSON: object keys sorted recursively,
|
|
* no whitespace, UTF-8. Two writers that agree on content therefore agree on
|
|
* bytes, which is what makes projections and receipts reproducible.
|
|
*/
|
|
|
|
const crypto = require('crypto');
|
|
|
|
function canonicalize(value) {
|
|
if (value === null || typeof value !== 'object') {
|
|
return value;
|
|
}
|
|
if (Array.isArray(value)) {
|
|
return value.map(canonicalize);
|
|
}
|
|
const out = {};
|
|
for (const key of Object.keys(value).sort()) {
|
|
const item = value[key];
|
|
if (item === undefined) {
|
|
continue;
|
|
}
|
|
// Generic JSON keys are data, including __proto__; never invoke a setter.
|
|
Object.defineProperty(out, key, {
|
|
value: canonicalize(item), enumerable: true, writable: true, configurable: true,
|
|
});
|
|
}
|
|
return out;
|
|
}
|
|
|
|
function canonicalJson(value) {
|
|
return JSON.stringify(canonicalize(value));
|
|
}
|
|
|
|
function sha256Hex(input) {
|
|
return crypto.createHash('sha256').update(input).digest('hex');
|
|
}
|
|
|
|
function hashValue(value) {
|
|
return sha256Hex(canonicalJson(value));
|
|
}
|
|
|
|
module.exports = {
|
|
canonicalize,
|
|
canonicalJson,
|
|
sha256Hex,
|
|
hashValue,
|
|
};
|