@entrorove/skill 0.1.81 → 0.1.83

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.83 — 2026-10-23
4
+
5
+ - 补齐 Blueprint 验收申请、查询与报告的 SDK 调用入口,修复只读查询的反馈回执判定;兼容原冻结计划的时间戳格式,修正 Calctool 打包与加载的完整性绑定。
6
+ - Expose Blueprint criterion attempt, read, and report SDK operations and correct read-only feedback handling; accept original frozen-plan timestamp formats and align Calctool packaging and loader integrity pins.
7
+
8
+ ## 0.1.82 — 2026-10-23
9
+
10
+ - 修复 Calctool 原生调用的合同解析,统一标准输入声明、数值单位和精度策略必填项;补齐任务入口语言参数与云沙箱标识的依赖校验。原签名、范围、回执和合并权限检查保持。
11
+ - Fix Calctool native contract parsing and publish standard input schemas with required numeric units and decimal policy; declare the task-entry locale dependency on its cloud sandbox identifier. Existing signature, scope, receipt, and merge authority checks remain in place.
12
+
3
13
  ## 0.1.81 - 2026-10-23
4
14
 
5
15
  仓库不再保留自动化测试与调试脚本,发布内容与安装包只包含运行所需文件。八个核心技能的实现与权限边界保持不变。
package/SKILL.md CHANGED
@@ -5,7 +5,7 @@ description: Route a task selected for Entrorove among its eight skills, approve
5
5
 
6
6
  # entrorove · 熵巡
7
7
 
8
- Version: 0.1.81.
8
+ Version: 0.1.83.
9
9
 
10
10
  Entrorove applies only to the task for which it is selected; reading these instructions, discovering capabilities or installing the package never selects or governs another task. Hooks are optional. Reading this document or calling an entry once does not execute the task. On every later turn, including after compaction, continue the original task and its required next operation before dependent work. Keep the original goal, scope, account, flow, cloud task and failure records. Never describe planning, a reported step or model output as verified delivery.
11
11
 
@@ -40,6 +40,11 @@ export async function buildCalctoolRuntime({ outputPath = resolve(directory, 'ru
40
40
  const destination = resolve(outputPath);
41
41
  if (destination === resolve(directory, '../../assets/runtime-source', file) || destination === fileURLToPath(import.meta.url)) throw new Error('Calctool generator cannot overwrite its pinned source');
42
42
  const content = await sourceContent(); isolated(content);
43
+ if (destination === resolve(directory, 'runtime', file)) {
44
+ const loader = await readFile(resolve(directory, 'local-calctool-runtime.mjs'), 'utf8');
45
+ const pins = [...loader.matchAll(/\bconst expectedSha256\s*=\s*(['"])([0-9a-f]{64})\1\s*;/g)];
46
+ if (pins.length !== 1 || pins[0][2] !== sha(content)) throw new Error('Calctool loader integrity pin does not match its generated runtime');
47
+ }
43
48
  if (checkOnly) {
44
49
  const current = await readFile(destination);
45
50
  if (!current.equals(Buffer.from(content))) throw new Error('Generated Calctool runtime is stale');
@@ -1,11 +1,34 @@
1
1
  import { buildFormulaEngine, compileFormulaEngine, validateFormulaEngine, formulaDigest } from './local-formula-engine.mjs';
2
- import { formulaError } from './local-decimal.mjs';
2
+ import { formulaError, DECIMAL_POLICY } from './local-decimal.mjs';
3
3
  import { FORMULA_OPERATORS, FORMULA_ROUNDING_POLICY } from './local-formula-ast.mjs';
4
4
 
5
5
  const CLOUD_OPERATIONS = ['capabilities', 'help', 'intake', 'validate', 'compile-inline'];
6
6
  const LOCAL_OPERATIONS = ['run', 'compile', 'generate', 'verify', 'estimate', 'impact', 'status', 'inventory', 'purge',
7
7
  'brain-handshake', 'brain-invoke', 'brain-events', 'brain-cancel', 'brain-complete', 'brain-resume', 'brain-status',
8
8
  'probe-env', 'adapt-config', 'intake-round', 'compile-tool', 'blueprint-orchestrate', 'auto-pipeline', 'final-gate', 'swarm-orchestrate'];
9
+ export function calctoolOperationSchemas(schemas) {
10
+ const result = structuredClone(schemas);
11
+ for (const operation of CLOUD_OPERATIONS) {
12
+ const properties = result[operation].input;
13
+ result[operation].input = { type: 'object', properties, required: Object.keys(properties), additionalProperties: false };
14
+ }
15
+ for (const [operation, key, fields] of [['compile-inline', 'requirements', 'inputs'], ['validate', 'engine', 'fields']]) {
16
+ const schema = result[operation].input.properties[key];
17
+ if (schema.example) {
18
+ for (const field of schema.example[fields] ?? []) if (['number', 'integer', 'money', 'percent'].includes(field.type)) field.unit ??= 'count';
19
+ schema.examples = [schema.example];
20
+ delete schema.example;
21
+ }
22
+ schema.properties[fields].items.allOf = [{ if: { type: 'object', properties: { type: { enum: ['number', 'integer', 'money', 'percent'] } }, required: ['type'] },
23
+ then: { type: 'object', required: ['unit'] } }];
24
+ }
25
+ const engine = result.validate.input.properties.engine;
26
+ engine.required = [...new Set([...engine.required, 'formulas', 'importProfiles', 'decimalPolicy'])];
27
+ engine.properties.decimalPolicy = { anyOf: [{ const: 'decimal-string' }, { const: DECIMAL_POLICY }] };
28
+ engine.properties.fields.maxItems = 1000;
29
+ engine.properties.formulas.minItems = 1;
30
+ return result;
31
+ }
9
32
  function failure(request, cause) {
10
33
  return { schemaVersion: 'calctool.skill.response/1.0', requestId: request?.requestId ?? 'unknown', status: 'blocked',
11
34
  validation: { valid: false, guarantee: 'blocked', findings: [{ severity: 'P0', ruleId: cause.code ?? 'FORMULA_INVALID', entityRef: 'input', message: cause.message }] } };
@@ -31,6 +54,7 @@ export function createCalctoolEntrypoint(core) {
31
54
  return { ...output, capabilities: { ...output.capabilities, operations: CLOUD_OPERATIONS, localRunnerOperations: LOCAL_OPERATIONS,
32
55
  formulaOperators: FORMULA_OPERATORS, engineSchema: 'engine.spec/1', formulaRuntime: 'decimal28-ast/1.0',
33
56
  decimalPolicy: { precision: 28, rounding: 'half-away-from-zero', representation: 'decimal-string' }, roundingPolicy: FORMULA_ROUNDING_POLICY },
57
+ operationSchemas: calctoolOperationSchemas(output.operationSchemas),
34
58
  localRunner: { command: 'entrorove local calctool-<operation>', requiredFor: LOCAL_OPERATIONS } };
35
59
  }
36
60
  if (request.operation === 'validate') {
@@ -1,7 +1,7 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { readFile } from 'node:fs/promises';
3
3
  const runtimeUrl = new URL('./runtime/calctool-runtime-v7.0.43.mjs', import.meta.url);
4
- const expectedSha256 = '5473427c350411f62c16ac5239fa0db7b96e7b2c19458f9046768dcb4ada87d1';
4
+ const expectedSha256 = '9c17b2e1b58c2174f5ad45e30de6ef2d63f622a1588a7673b1a7e3f277527759';
5
5
  export async function calctoolRuntimeBytes() {
6
6
  const bytes = await readFile(runtimeUrl);
7
7
  if (createHash('sha256').update(bytes).digest('hex') !== expectedSha256) throw Object.assign(new Error('Calctool packaged runtime digest mismatch'), { code: 'FORMULA_RUNTIME_INTEGRITY' });
package/manifest.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": "entrorove.skill-manifest/1.0",
3
3
  "name": "entrorove",
4
- "version": "0.1.81",
4
+ "version": "0.1.83",
5
5
  "endpoint": "https://entrorove.com",
6
6
  "requestSchemaVersion": "entrorove.skill.request/2.0",
7
7
  "supportedRequestSchemaVersions": [
package/native-client.mjs CHANGED
@@ -19,14 +19,25 @@ export function buildNativeInvocation(domain, operation, input, origin = 'https:
19
19
  return { url: `${trustedOrigin(origin)}/api/skills/${domain}/invoke`, requestId, body,
20
20
  feedbackHashes: [sha256('continue' + canonical(transport)), sha256(operation + canonical(input))] };
21
21
  }
22
- function discoveredContract(output, operation) {
22
+ export function discoveredNativeContract(output, operation) {
23
23
  const payload = output.output ?? output;
24
24
  const capabilities = payload.capabilities ?? payload;
25
25
  const operations = capabilities.operations ?? capabilities.operationStatus?.implementedPure;
26
26
  const schemas = payload.operationSchemas ?? capabilities.operationSchemas;
27
27
  const schema = Array.isArray(schemas) ? schemas.find(value => value.operation === operation) : schemas?.[operation];
28
28
  if (!operations?.includes(operation) || !(schema?.input ?? schema?.inputSchema)) throw new Error(`Native capability does not support ${operation}`);
29
- return schema.input ?? schema.inputSchema;
29
+ const input = schema.input ?? schema.inputSchema;
30
+ // Older native contracts describe named fields directly. Convert only that
31
+ // typed field-map form; ordinary JSON Schemas retain strict Ajv validation.
32
+ const fields = Object.entries(input);
33
+ const schemaKeys = new Set(['$schema', '$id', '$ref', '$defs', 'definitions', 'type', 'properties', 'patternProperties',
34
+ 'additionalProperties', 'required', 'allOf', 'anyOf', 'oneOf', 'not', 'if', 'then', 'else', 'items', 'enum', 'const']);
35
+ if (fields.length && fields.every(([key, value]) => !schemaKeys.has(key) && value && typeof value === 'object'
36
+ && !Array.isArray(value) && typeof value.type === 'string')) {
37
+ return { type: 'object', properties: input, additionalProperties: false,
38
+ required: fields.filter(([, value]) => value.optional !== true).map(([key]) => key) };
39
+ }
40
+ return input;
30
41
  }
31
42
  export async function invokeNativeResult(domain, operation, input, dependencies) {
32
43
  const { home } = dependencies;
@@ -49,9 +60,10 @@ export async function invokeNativeResult(domain, operation, input, dependencies)
49
60
  // contract through Ajv's optional strictTypes authoring convention.
50
61
  const ajv = new Ajv({ strict: true, strictRequired: false, strictTypes: false, allErrors: true });
51
62
  ajv.addKeyword({ keyword: 'optional', schemaType: 'boolean', valid: true });
63
+ ajv.addKeyword({ keyword: 'example', valid: true });
52
64
  ajv.addFormat('uuid', /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i);
53
65
  ajv.addFormat('date-time', value => Number.isFinite(Date.parse(value)));
54
- const validate = ajv.compile(discoveredContract(discovery.result.output, operation));
66
+ const validate = ajv.compile(discoveredNativeContract(discovery.result.output, operation));
55
67
  if (!validate(input)) throw new Error(`Invalid native ${operation} input: ${ajv.errorsText(validate.errors)}`);
56
68
  }
57
69
  return postInvocation(call, token, home, feedbackRequired);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@entrorove/skill",
3
- "version": "0.1.81",
3
+ "version": "0.1.83",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "entrorove": "cli.mjs"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": "entrorove.release-state/1.0",
3
- "version": "0.1.81",
4
- "digest": "02c6175ebaa09bad61e9b3128bf3408561390c6d307feb31a7dd6f737f5903fe",
3
+ "version": "0.1.83",
4
+ "digest": "2a81190915dd2751aabaca0cf73018081e26a30c24d2bbacb8c6ace10968213e",
5
5
  "files": {
6
6
  "local-recovery-budget.mjs": "be3af07db8e4cc96782edb130e827039c7a99bbe8275a92f0f741533716017f3",
7
7
  "remote-capability-cache.mjs": "9c22067e1a21eb2a209747a8ab2f27c0496b14a22a7e0f5654840e2035148df0",
@@ -257,7 +257,7 @@
257
257
  "local-scope-state.mjs": "7a6d275d6267a4d0bb55582e1bcc7654c502ecba9221b84b2149a98f0ee7518f",
258
258
  "local-scope-workspaces.mjs": "8a75ce7b6639b5682370b5738c5c2a90408e3130729608e008f03053cd50351f",
259
259
  "local-task-routing.mjs": "6e2e506b2fb0e2e8d8c5147d7df32849b57a4e94a23634f01a355d45735858e4",
260
- "remote-client.mjs": "1db62896d3c0b97fdf9a4add85a34ed7de45b9399c33e482c884ed96a376c58a",
260
+ "remote-client.mjs": "218843be687c147f60b2a231f678faac66d5e675336b860873e682daf77f08d9",
261
261
  "service-prerequisite.mjs": "2361168ea12ca95faee75c79657a486af5e7edaf1ec8182f8f1afdf59f15c9a5",
262
262
  "local-source-execution.mjs": "88f6ce1ea50d0a7b92e0cb47d535f8140491c52d9c6c0dfddf91ea90397a36f5",
263
263
  "fs-request-trace.mjs": "972eacbe21537bc102047127327449a6a4b0f0c65d75e3472370de91dedf4d2f",
@@ -270,7 +270,7 @@
270
270
  "scope-amendment-observer.mjs": "9091f2e11b094b8a8cd27ad1454031d11a34ecb6923295fd6edfaa07c54899ee",
271
271
  "scope-amendment-mutation.mjs": "fa24191df290efad29d41eca3d1a081981fefde02b7dc4a11c75c6118a69106e",
272
272
  "scope-amendment-reference.mjs": "dc1768131beb7db224dd2ff8522dbf6361f73e01f466c9334cdfa24118720078",
273
- "native-client.mjs": "76f4c35cdef670f4e1cceaecde397869e8f7b4a41654ff5127345ed15d7b3888",
273
+ "native-client.mjs": "522228a97d5d7dafde18b778856b3c499b6c6f75b13eae6f57c0050521233692",
274
274
  "native-notification.mjs": "8859a26c6f13d222711f763acf49ed8546b3306cf71f990643ac31a5ccaf1ba1",
275
275
  "local-peer-status.mjs": "a971bcc69d60bb32b875ca5bb4297d948631d5d2821b812c279613ea059a8b4f",
276
276
  "cloud-watch-client.mjs": "eccce52bce1c915a71fe9a1fa3e435dba5af9a5455afdf478f04684901b6fb7b",
@@ -295,7 +295,7 @@
295
295
  "local-task-handoff-write-archive.mjs": "3668f39d8ab5664ed717994cf1b4bcc7ea23e146a0e06291f851d30337faeb77",
296
296
  "local-task-handoff-write-receipts.mjs": "e1321127bd6fcad7840e185639f81ae68a8722a0ee4264a7b504a02b27887647",
297
297
  "workflow-local-runner.mjs": "3183c15650e605cc9a8c1531cc3651f5a7d2f61b099554d334713d78a9aae62b",
298
- "workflow-local-contracts.mjs": "2ab69043b498dad007e46fa5b4cbda6bffb6720652b970c3dec7f2825175ef87",
298
+ "workflow-local-contracts.mjs": "ad208f054a7f03c790896248e735add1383775e774dce34e81b61e6f47d238c1",
299
299
  "workflow-local-client.mjs": "45c954f694d96bf0ea87ee2dc6902a6763dac2cb1df713b6a5e749632054e9af",
300
300
  "workflow-local-request.mjs": "4e24c543ce386292a87dc9cd41f90d23375f12079cacffc515c8cd01fd571780",
301
301
  "task-message-entry.mjs": "31d10056cb905237cd5649e8eb067009ff1612ec5dc1061e0373209fbc0b646a",
@@ -325,7 +325,7 @@
325
325
  "local-calctool.mjs": "9398e642250b38b2831ec58e490fbbef761455ce9ae49af033baa8c3ba8d778e",
326
326
  "local-calctool-cli.mjs": "a6b46e2aa9a91dfb73fc0dc415b2281a0343e22e317ff1bfcf58cadbb8093122",
327
327
  "local-calctool-contracts.mjs": "d8fccf662b2dd7aefd5cc6770b2473014af7a28855074fcf294937ca5a49eae8",
328
- "local-calctool-runtime.mjs": "9070b6900d1782bf77357fea1cc522bf796898d56929f96d7cb935b3036ac82f",
328
+ "local-calctool-runtime.mjs": "eccb3425ce8b71223263ddfe4b65be31468c926998646ccb4f609b554f079ffa",
329
329
  "local-calctool-storage.mjs": "4c3f352847aeb368dea1247759a1055beeab25534adf25b6e7323196d76fd684",
330
330
  "local-mutation-files.mjs": "cd27197fd25cb3ec3d0733e932c2ff2394b0665ad4afb771edc3e4a49526e428",
331
331
  "local-mutation-snapshot.mjs": "69c0ff0b67b2e6913b1d9f8247bf48c31d62f4f5ae1668c573a0ade06c01d105",
@@ -336,8 +336,8 @@
336
336
  "local-mutation-authority.mjs": "7af25eee1820d6c075bbd662b919e83436e5cbc5733e93f7f9f3b0f4ef9d37ac",
337
337
  "local-mutation-batch.mjs": "de27686b5f99a99b02f0218a3fa159e9469d6b19c595117287d6dd37a6efcb3b",
338
338
  "local-mutation-batch-receipt.mjs": "b0e6a8522867255d899e60b66677885933f6a1c4c771cbb52f84dbbbdcf5e5c2",
339
- "calctool-runtime-entry.mjs": "98d2bc8df38d16131fc56db0a3d4d260531ba4df412baa5ddc4b8b5c5ca99fe9",
340
- "calctool-runtime-build.mjs": "3c5a9bd40bc1abe02e3b6e307809eea4eaaf198e8f0db6f5d6b2583dd68a59d2",
341
- "runtime/calctool-runtime-v7.0.43.mjs": "5473427c350411f62c16ac5239fa0db7b96e7b2c19458f9046768dcb4ada87d1"
339
+ "calctool-runtime-entry.mjs": "c3a59f8984e592ceae02382061e4e890862843b26b6b219b0e37aeee56a6ac45",
340
+ "calctool-runtime-build.mjs": "29d29fa733be74a8274238eaba9431dea6cd189699b23973335ddfe644069fee",
341
+ "runtime/calctool-runtime-v7.0.43.mjs": "9c17b2e1b58c2174f5ad45e30de6ef2d63f622a1588a7673b1a7e3f277527759"
342
342
  }
343
343
  }
package/releases.json CHANGED
@@ -1,4 +1,16 @@
1
1
  [
2
+ {
3
+ "version": "0.1.83",
4
+ "date": "2026-10-23",
5
+ "zh": "补齐 Blueprint 验收申请、查询与报告的 SDK 调用入口,修复只读查询的反馈回执判定;兼容原冻结计划的时间戳格式,修正 Calctool 打包与加载的完整性绑定。",
6
+ "en": "Expose Blueprint criterion attempt, read, and report SDK operations and correct read-only feedback handling; accept original frozen-plan timestamp formats and align Calctool packaging and loader integrity pins."
7
+ },
8
+ {
9
+ "version": "0.1.82",
10
+ "date": "2026-10-23",
11
+ "zh": "修复 Calctool 原生调用的合同解析,统一标准输入声明、数值单位和精度策略必填项;补齐任务入口语言参数与云沙箱标识的依赖校验。原签名、范围、回执和合并权限检查保持。",
12
+ "en": "Fix Calctool native contract parsing and publish standard input schemas with required numeric units and decimal policy; declare the task-entry locale dependency on its cloud sandbox identifier. Existing signature, scope, receipt, and merge authority checks remain in place."
13
+ },
2
14
  {
3
15
  "version": "0.1.81",
4
16
  "date": "2026-10-23",
package/remote-client.mjs CHANGED
@@ -43,6 +43,7 @@ export function buildInvocation(operation, input) {
43
43
  'member-observation-admit', 'member-observation-report', 'member-observation-status',
44
44
  'scope-runner-prepare', 'scope-runner-register', 'scope-runner-challenge', 'scope-runner-attest', 'scope-evidence-prepare',
45
45
  'scope-runner-context-review', 'scope-runner-context-status', 'scope-runner-context-challenge', 'scope-runner-context-apply',
46
+ 'blueprint-criterion-attempt', 'blueprint-criterion-read', 'blueprint-criterion-report',
46
47
  'start', 'continue'].includes(operation)) throw new Error('Invalid entrorove operation');
47
48
  if (!input || typeof input !== 'object' || Array.isArray(input)) throw new Error('Input must be a JSON object');
48
49
  const id = requestId(operation, input);
@@ -50,6 +51,8 @@ export function buildInvocation(operation, input) {
50
51
  }
51
52
  function requiresAutomaticFeedback(operation, input, capabilities) {
52
53
  const actual = operation === 'continue' ? input.operation : operation;
54
+ // Criterion reads return stored state without creating a feedback receipt.
55
+ if (actual === 'blueprint-criterion-read') return false;
53
56
  return capabilities?.responseExtensions?.automaticFeedback === 'entrorove.automatic-feedback/1.0'
54
57
  && !capabilities.responseExtensions.automaticFeedbackObservations?.includes(actual);
55
58
  }
@@ -1817,6 +1817,29 @@ const CLOUD_OPERATIONS = ['capabilities', 'help', 'intake', 'validate', 'compile
1817
1817
  const LOCAL_OPERATIONS = ['run', 'compile', 'generate', 'verify', 'estimate', 'impact', 'status', 'inventory', 'purge',
1818
1818
  'brain-handshake', 'brain-invoke', 'brain-events', 'brain-cancel', 'brain-complete', 'brain-resume', 'brain-status',
1819
1819
  'probe-env', 'adapt-config', 'intake-round', 'compile-tool', 'blueprint-orchestrate', 'auto-pipeline', 'final-gate', 'swarm-orchestrate'];
1820
+ function calctoolOperationSchemas(schemas) {
1821
+ const result = structuredClone(schemas);
1822
+ for (const operation of CLOUD_OPERATIONS) {
1823
+ const properties = result[operation].input;
1824
+ result[operation].input = { type: 'object', properties, required: Object.keys(properties), additionalProperties: false };
1825
+ }
1826
+ for (const [operation, key, fields] of [['compile-inline', 'requirements', 'inputs'], ['validate', 'engine', 'fields']]) {
1827
+ const schema = result[operation].input.properties[key];
1828
+ if (schema.example) {
1829
+ for (const field of schema.example[fields] ?? []) if (['number', 'integer', 'money', 'percent'].includes(field.type)) field.unit ??= 'count';
1830
+ schema.examples = [schema.example];
1831
+ delete schema.example;
1832
+ }
1833
+ schema.properties[fields].items.allOf = [{ if: { type: 'object', properties: { type: { enum: ['number', 'integer', 'money', 'percent'] } }, required: ['type'] },
1834
+ then: { type: 'object', required: ['unit'] } }];
1835
+ }
1836
+ const engine = result.validate.input.properties.engine;
1837
+ engine.required = [...new Set([...engine.required, 'formulas', 'importProfiles', 'decimalPolicy'])];
1838
+ engine.properties.decimalPolicy = { anyOf: [{ const: 'decimal-string' }, { const: DECIMAL_POLICY }] };
1839
+ engine.properties.fields.maxItems = 1000;
1840
+ engine.properties.formulas.minItems = 1;
1841
+ return result;
1842
+ }
1820
1843
  function failure(request, cause) {
1821
1844
  return { schemaVersion: 'calctool.skill.response/1.0', requestId: request?.requestId ?? 'unknown', status: 'blocked',
1822
1845
  validation: { valid: false, guarantee: 'blocked', findings: [{ severity: 'P0', ruleId: cause.code ?? 'FORMULA_INVALID', entityRef: 'input', message: cause.message }] } };
@@ -1842,6 +1865,7 @@ function createCalctoolEntrypoint(core) {
1842
1865
  return { ...output, capabilities: { ...output.capabilities, operations: CLOUD_OPERATIONS, localRunnerOperations: LOCAL_OPERATIONS,
1843
1866
  formulaOperators: FORMULA_OPERATORS, engineSchema: 'engine.spec/1', formulaRuntime: 'decimal28-ast/1.0',
1844
1867
  decimalPolicy: { precision: 28, rounding: 'half-away-from-zero', representation: 'decimal-string' }, roundingPolicy: FORMULA_ROUNDING_POLICY },
1868
+ operationSchemas: calctoolOperationSchemas(output.operationSchemas),
1845
1869
  localRunner: { command: 'entrorove local calctool-<operation>', requiredFor: LOCAL_OPERATIONS } };
1846
1870
  }
1847
1871
  if (request.operation === 'validate') {
@@ -21,7 +21,8 @@ const executionPolicy = exact({ executable: absolutePath, executableSha256: sha2
21
21
  executionPolicy.properties.discipline = DISCIPLINE_POLICY_SCHEMA;
22
22
  const baseline = exact({ schemaVersion: { const: 'validator.golden-baseline/1.0' }, baselineId: id,
23
23
  source: exact({ kind: enumeration(['repository-commit', 'artifact', 'approved-record']), locator: shortText, digestSha256: sha256 }),
24
- version: id, frozen: { const: true }, frozenAt: timestamp, frozenBy: id, testsSha256: sha256,
24
+ version: id, frozen: { const: true }, frozenAt: { type: 'string',
25
+ pattern: '^\\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\\d|3[01])T(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d{1,9})?(?:Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$' }, frozenBy: id, testsSha256: sha256,
25
26
  });
26
27
  const brainFields = ['planSha256', 'reportSha256', 'checksSha256', 'scopeContractSha256', 'snapshotSha256', 'adapterSha256'];
27
28
  const contracts = object({