@entrorove/skill 0.1.22 → 0.1.24

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.
Files changed (155) hide show
  1. package/AGREEMENT.md +6 -6
  2. package/CHANGELOG.md +10 -0
  3. package/SKILL.md +12 -4
  4. package/archguard-runtime-build.mjs +15 -0
  5. package/blueprint-criterion-runner.mjs +110 -0
  6. package/blueprint-criterion-wire.mjs +78 -0
  7. package/calctool-runtime-build.mjs +59 -0
  8. package/calctool-runtime-entry.mjs +92 -0
  9. package/cli.mjs +18 -83
  10. package/local-approved-plan.mjs +74 -15
  11. package/local-archguard-ast.mjs +371 -0
  12. package/local-archguard-checkpoint.mjs +123 -0
  13. package/local-archguard-components.mjs +177 -0
  14. package/local-archguard-contract.mjs +109 -0
  15. package/local-archguard-contracts.mjs +42 -0
  16. package/local-archguard-evaluate.mjs +120 -0
  17. package/local-archguard-language-ast.mjs +165 -0
  18. package/local-archguard-mutation-fence.mjs +28 -0
  19. package/local-archguard-operations.mjs +25 -0
  20. package/local-archguard-scope.mjs +64 -0
  21. package/local-archguard-signing.mjs +52 -0
  22. package/local-archguard-snapshot.mjs +126 -0
  23. package/local-archguard-state.mjs +200 -0
  24. package/local-archguard.mjs +74 -0
  25. package/local-budget-git-attributes.mjs +49 -0
  26. package/local-budget-git-loader.mjs +61 -0
  27. package/local-budget-git-native-attributes.mjs +81 -0
  28. package/local-budget-git-native-darwin.mjs +104 -0
  29. package/local-budget-git-native-linux.mjs +93 -0
  30. package/local-budget-git-native-reads.mjs +88 -0
  31. package/local-budget-git-native-request.mjs +53 -0
  32. package/local-budget-git-native-runtime.mjs +18 -0
  33. package/local-budget-git-native.c +313 -0
  34. package/local-budget-git-native.mjs +109 -0
  35. package/local-budget-git-outcome.mjs +33 -0
  36. package/local-budget-git-scratch-loader.mjs +158 -0
  37. package/local-budget-git-scratch.mjs +112 -0
  38. package/local-budget-git-system-attributes.mjs +44 -0
  39. package/local-budget-git.mjs +92 -0
  40. package/local-budget-grants.mjs +82 -0
  41. package/local-budget-handoff-completion.mjs +70 -0
  42. package/local-budget-handoff-contracts.mjs +53 -0
  43. package/local-budget-handoff.mjs +229 -0
  44. package/local-budget-lock.mjs +55 -0
  45. package/local-budget-reads.mjs +135 -0
  46. package/local-budget-renewal.mjs +86 -34
  47. package/local-budget-source-bindings.mjs +51 -0
  48. package/local-budget-store.mjs +131 -0
  49. package/local-budget-transition.mjs +46 -0
  50. package/local-budget.mjs +185 -0
  51. package/local-calctool-cli.mjs +22 -0
  52. package/local-calctool-contracts.mjs +42 -0
  53. package/local-calctool-runtime.mjs +10 -0
  54. package/local-calctool-storage.mjs +101 -0
  55. package/local-calctool.mjs +103 -0
  56. package/local-cli.mjs +49 -16
  57. package/local-contract-types.mjs +46 -0
  58. package/local-contracts.mjs +124 -0
  59. package/local-credential.mjs +101 -0
  60. package/local-decimal.mjs +85 -0
  61. package/local-evidence-verification.mjs +199 -0
  62. package/local-execution.mjs +115 -304
  63. package/local-final-gate16-bundle.mjs +21 -0
  64. package/local-final-gate16-checks.mjs +88 -0
  65. package/local-final-gate16-contract.mjs +15 -0
  66. package/local-final-gate16-plan.mjs +66 -0
  67. package/local-final-gate16-proof.mjs +75 -0
  68. package/local-final-gate16-release.mjs +17 -0
  69. package/local-final-gate16-state.mjs +70 -0
  70. package/local-final-gate16-worker.mjs +19 -0
  71. package/local-final-gate16.mjs +137 -0
  72. package/local-formula-ast.mjs +97 -0
  73. package/local-formula-engine.mjs +111 -0
  74. package/local-formula-tests.mjs +61 -0
  75. package/local-formula.mjs +25 -125
  76. package/local-integrity.mjs +22 -41
  77. package/local-invocations.mjs +107 -0
  78. package/local-ledger.mjs +2 -7
  79. package/local-merge-archguard-verification.d.mts +44 -0
  80. package/local-merge-archguard-verification.mjs +240 -0
  81. package/local-merge-archguard.mjs +138 -0
  82. package/local-merge-artifacts.mjs +86 -0
  83. package/local-merge-authority.mjs +89 -0
  84. package/local-merge-contracts.mjs +56 -0
  85. package/local-merge-controller.mjs +170 -0
  86. package/local-merge-head.mjs +56 -0
  87. package/local-merge-journal.mjs +77 -0
  88. package/local-merge-mutation.mjs +97 -0
  89. package/local-merge-rollback.mjs +126 -0
  90. package/local-merge-snapshot-rollback.mjs +26 -0
  91. package/local-merge-storage.mjs +103 -0
  92. package/local-merge-targets.mjs +47 -0
  93. package/local-merge-transaction.mjs +133 -0
  94. package/local-mutation-audit.mjs +34 -0
  95. package/local-mutation-authority.mjs +96 -0
  96. package/local-mutation-batch-receipt.mjs +84 -0
  97. package/local-mutation-batch.mjs +143 -0
  98. package/local-mutation-binding.mjs +86 -0
  99. package/local-mutation-files.mjs +245 -0
  100. package/local-mutation-pass-store.mjs +63 -0
  101. package/local-mutation-snapshot.mjs +200 -0
  102. package/local-mutation-wire.mjs +89 -0
  103. package/local-probe.mjs +133 -11
  104. package/local-scope-candidate.mjs +28 -0
  105. package/local-scope-context.mjs +28 -0
  106. package/local-scope-files.mjs +106 -0
  107. package/local-scope-git-attributes.mjs +200 -0
  108. package/local-scope-git-comparison.mjs +8 -0
  109. package/local-scope-git-history.mjs +72 -0
  110. package/local-scope-git-reads.mjs +66 -0
  111. package/local-scope-git.mjs +124 -0
  112. package/local-scope-repository.mjs +249 -0
  113. package/local-scope-signature.mjs +70 -0
  114. package/local-scope-snapshot.mjs +39 -0
  115. package/local-scope-state.mjs +204 -0
  116. package/local-scope-workspaces.mjs +83 -0
  117. package/local-swarm-authority.mjs +143 -0
  118. package/local-swarm-baseline.mjs +32 -0
  119. package/local-swarm-completion.mjs +102 -0
  120. package/local-swarm-contracts.mjs +47 -0
  121. package/local-swarm-mutation.mjs +142 -0
  122. package/local-swarm-priority.mjs +237 -0
  123. package/local-swarm-state.mjs +102 -0
  124. package/local-swarm-storage.mjs +135 -0
  125. package/local-swarm.mjs +179 -0
  126. package/local-task-handoff-completion-wire.mjs +71 -0
  127. package/local-task-handoff-contracts.mjs +66 -0
  128. package/local-task-handoff-fence.mjs +478 -0
  129. package/local-task-handoff-observation.mjs +38 -0
  130. package/local-task-handoff-overlay-wire.mjs +94 -0
  131. package/local-task-handoff-read-authority.mjs +236 -0
  132. package/local-task-handoff-storage.mjs +73 -0
  133. package/local-task-handoff-write-archive.mjs +80 -0
  134. package/local-task-handoff-write-constraints.mjs +66 -0
  135. package/local-task-handoff-write-receipts.mjs +99 -0
  136. package/local-task-handoff-write-wire.mjs +99 -0
  137. package/local-task-routing.mjs +202 -22
  138. package/manifest.json +1 -1
  139. package/package.json +153 -3
  140. package/release-state.json +153 -17
  141. package/release.mjs +238 -4
  142. package/releases.json +12 -0
  143. package/remote-client.mjs +127 -36
  144. package/remote-transport.mjs +80 -0
  145. package/review-client.mjs +38 -0
  146. package/runtime/archguard-runtime-v7.0.44.mjs +314 -0
  147. package/runtime/calctool-runtime-v7.0.43.mjs +1887 -0
  148. package/runtime/git-native-darwin-v1.mjs +5 -0
  149. package/runtime/git-native-linux-v1.mjs +5 -0
  150. package/task-message-cli.mjs +47 -0
  151. package/task-message-entry.mjs +159 -0
  152. package/workflow-local-client.mjs +35 -0
  153. package/workflow-local-contracts.mjs +58 -0
  154. package/workflow-local-request.mjs +53 -0
  155. package/workflow-local-runner.mjs +350 -0
@@ -0,0 +1,199 @@
1
+ import { createHash, createPublicKey, verify } from 'node:crypto';
2
+
3
+ const EVIDENCE_SCHEMA = 'entrorove.test-evidence/2.0';
4
+ const EXECUTION_SCHEMA = 'validator.execution-receipt/1.0';
5
+ const GENERIC_SCHEMA = 'entrorove.runner-receipt/1.0';
6
+ const KINDS = new Set(['test', 'build', 'lint', 'security', 'benchmark']);
7
+ const RUNNERS = new Set(['local', 'trusted-runner', 'sandbox']);
8
+ const SHA = /^[0-9a-f]{64}$/;
9
+ const ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
10
+ const FIELDS = new Set(['schemaVersion', 'evidenceId', 'kind', 'runner', 'command', 'exitCode', 'durationMs',
11
+ 'summary', 'artifactSha256', 'subject', 'subjectDigest', 'receipt', 'flowId', 'stepId']);
12
+ const object = value => value !== null && typeof value === 'object' && !Array.isArray(value);
13
+ const digest = value => createHash('sha256').update(value).digest('hex');
14
+ const text = (value, max) => typeof value === 'string' && value.trim().length > 0 && value.length <= max;
15
+ function fail(code, message) { throw Object.assign(new Error(message), { code }); }
16
+
17
+ function canonical(value) {
18
+ if (value === null || typeof value === 'boolean' || typeof value === 'string') return JSON.stringify(value);
19
+ if (typeof value === 'number' && Number.isFinite(value)) return JSON.stringify(value);
20
+ if (Array.isArray(value)) return `[${value.map(canonical).join(',')}]`;
21
+ if (!object(value)) fail('ENTROROVE_EVIDENCE_JSON', 'Evidence must contain finite JSON values');
22
+ return `{${Object.keys(value).sort().map(key => `${JSON.stringify(key)}:${canonical(value[key])}`).join(',')}}`;
23
+ }
24
+
25
+ function state(status, details = {}) {
26
+ return { verified: false, authentic: false, successful: false, status, evidenceState: status, ...details };
27
+ }
28
+
29
+ function validateEvidence(evidence) {
30
+ if (!object(evidence) || Object.keys(evidence).some(key => !FIELDS.has(key)) || evidence.schemaVersion !== EVIDENCE_SCHEMA
31
+ || !text(evidence.evidenceId, 200) || !KINDS.has(evidence.kind) || !RUNNERS.has(evidence.runner)
32
+ || !text(evidence.command, 2000) || !Number.isInteger(evidence.exitCode) || evidence.exitCode < -128 || evidence.exitCode > 255
33
+ || !Number.isSafeInteger(evidence.durationMs) || evidence.durationMs < 0 || evidence.durationMs > 86_400_000
34
+ || !text(evidence.summary, 4000) || !SHA.test(String(evidence.artifactSha256 ?? ''))) {
35
+ fail('ENTROROVE_EVIDENCE_SCHEMA', 'Evidence schema is invalid');
36
+ }
37
+ canonical(evidence);
38
+ }
39
+
40
+ function publicKey(encoded) {
41
+ if (typeof encoded !== 'string' || !/^[A-Za-z0-9+/]+={0,2}$/.test(encoded)) fail('ENTROROVE_EVIDENCE_KEY', 'Independent receipt public key encoding is invalid');
42
+ const bytes = Buffer.from(encoded, 'base64');
43
+ if (bytes.toString('base64') !== encoded) fail('ENTROROVE_EVIDENCE_KEY', 'Receipt public key must use canonical base64');
44
+ let key; try { key = createPublicKey({ key: bytes, format: 'der', type: 'spki' }); }
45
+ catch { fail('ENTROROVE_EVIDENCE_KEY', 'Receipt public key is invalid'); }
46
+ if (key.asymmetricKeyType !== 'ed25519' || !key.export({ format: 'der', type: 'spki' }).equals(bytes)) {
47
+ fail('ENTROROVE_EVIDENCE_KEY', 'Receipt public key must be canonical Ed25519 SPKI');
48
+ }
49
+ return { key, keyId: digest(bytes) };
50
+ }
51
+
52
+ function verifySignature(receipt, payload, encoded) {
53
+ if (!object(receipt) || !SHA.test(String(receipt.keyId ?? '')) || typeof receipt.signature !== 'string'
54
+ || !/^[A-Za-z0-9_-]{86}$/.test(receipt.signature)) fail('ENTROROVE_EVIDENCE_SIGNATURE', 'Receipt signature fields are invalid');
55
+ const trusted = publicKey(encoded); const signature = Buffer.from(receipt.signature, 'base64url');
56
+ if (signature.length !== 64 || signature.toString('base64url') !== receipt.signature || trusted.keyId !== receipt.keyId
57
+ || (receipt.publicKey !== undefined && receipt.publicKey !== encoded)
58
+ || !verify(null, Buffer.from(canonical(payload)), trusted.key, signature)) {
59
+ fail('ENTROROVE_EVIDENCE_SIGNATURE', 'Receipt key identity or signature is invalid');
60
+ }
61
+ return trusted.keyId;
62
+ }
63
+
64
+ function receiptPayload(evidence) {
65
+ const receipt = evidence.receipt;
66
+ if (receipt?.schemaVersion === GENERIC_SCHEMA) return Object.fromEntries(Object.entries(evidence).filter(([key]) => key !== 'receipt'));
67
+ if (receipt?.schemaVersion !== EXECUTION_SCHEMA) fail('ENTROROVE_EVIDENCE_RECEIPT', 'Signed receipt schema is invalid');
68
+ if (!object(evidence.subject) || evidence.subjectDigest !== digest(canonical(evidence.subject))
69
+ || receipt.subjectDigest !== evidence.subjectDigest) fail('ENTROROVE_EVIDENCE_SUBJECT', 'Execution receipt subject digest is not bound');
70
+ return Object.fromEntries(Object.entries(receipt).filter(([key]) => key !== 'signature'));
71
+ }
72
+
73
+ function manifest(subject) {
74
+ if (!Array.isArray(subject.files) || !subject.files.length || subject.files.length > 512) fail('ENTROROVE_EVIDENCE_MANIFEST', 'Subject requires a nonempty bounded file manifest');
75
+ for (const [index, file] of subject.files.entries()) {
76
+ if (!object(file) || Object.keys(file).sort().join('|') !== 'path|sha256' || !text(file.path, 4096)
77
+ || file.path !== file.path.normalize('NFC') || file.path.startsWith('/') || /^[A-Za-z]:/.test(file.path)
78
+ || /[\\\u0000-\u001f\u007f]/.test(file.path) || file.path.split('/').some(part => !part || part === '.' || part === '..')
79
+ || !SHA.test(String(file.sha256 ?? '')) || (index > 0 && subject.files[index - 1].path >= file.path)) {
80
+ fail('ENTROROVE_EVIDENCE_MANIFEST', 'Subject manifest paths must be normalized, sorted and unique');
81
+ }
82
+ }
83
+ const actual = digest(`validator.file-manifest/1.0\n${subject.files.map(file => `${file.path}\0${file.sha256}`).join('\n')}`);
84
+ if (subject.artifactSha256 !== actual) fail('ENTROROVE_EVIDENCE_ARTIFACT', 'Subject artifact does not match its actual file manifest');
85
+ }
86
+
87
+ function validateSubject(evidence, options) {
88
+ const subject = evidence.subject; const policy = subject?.policy;
89
+ if (!object(subject) || subject.schemaVersion !== 'validator.validation-subject/1.0' || !object(policy)
90
+ || !ID.test(String(subject.planId ?? '')) || !ID.test(String(subject.validationRunId ?? ''))
91
+ || !text(subject.memberId, 128) || !ID.test(String(subject.chainId ?? '')) || !Number.isFinite(Date.parse(subject.executedAt))
92
+ || !SHA.test(String(evidence.subjectDigest ?? '')) || evidence.subjectDigest !== digest(canonical(subject))
93
+ || policy.command !== evidence.command || policy.requiredExitCode !== 0 || subject.artifactSha256 !== evidence.artifactSha256) {
94
+ fail('ENTROROVE_EVIDENCE_SUBJECT', 'Evidence command, artifact or validation subject is not bound');
95
+ }
96
+ manifest(subject);
97
+ const kind = policy.evidenceKind ?? 'test'; const runner = policy.evidenceRunner ?? 'trusted-runner';
98
+ if (!KINDS.has(kind) || !RUNNERS.has(runner) || evidence.kind !== kind || evidence.runner !== runner) {
99
+ fail('ENTROROVE_EVIDENCE_SEMANTICS', 'Evidence kind and runner must match signed policy');
100
+ }
101
+ if (!Array.isArray(subject.tests) || !subject.tests.length || subject.tests.some(item => !object(item)
102
+ || !ID.test(String(item.testId ?? '')) || !subject.files.some(file => file.path === item.path))) {
103
+ fail('ENTROROVE_EVIDENCE_TESTS', 'Subject tests must be bound to manifest files');
104
+ }
105
+ validateBaseline(subject);
106
+ validateBinding(evidence, subject, options);
107
+ if (options.expectedSubject !== undefined && canonical(options.expectedSubject) !== canonical(subject)) {
108
+ fail('ENTROROVE_EVIDENCE_SUBJECT', 'Evidence belongs to a different expected subject');
109
+ }
110
+ return subject;
111
+ }
112
+
113
+ function validateBaseline(subject) {
114
+ const baseline = subject.goldenBaseline; const source = baseline?.source;
115
+ if (!object(baseline) || baseline.schemaVersion !== 'validator.golden-baseline/1.0' || baseline.frozen !== true
116
+ || !ID.test(String(baseline.baselineId ?? '')) || !ID.test(String(baseline.version ?? ''))
117
+ || !ID.test(String(baseline.frozenBy ?? '')) || !Number.isFinite(Date.parse(baseline.frozenAt))
118
+ || !object(source) || !['repository-commit', 'artifact', 'approved-record'].includes(source.kind)
119
+ || !text(source.locator, 4096) || !SHA.test(String(source.digestSha256 ?? ''))
120
+ || baseline.testsSha256 !== digest(canonical(subject.tests))) fail('ENTROROVE_EVIDENCE_BASELINE', 'A frozen traceable baseline must bind the actual subject tests');
121
+ }
122
+
123
+ function validateBinding(evidence, subject, options) {
124
+ const workflow = subject.policy.workflowBinding;
125
+ if (workflow !== undefined && !object(workflow)) fail('ENTROROVE_EVIDENCE_BINDING', 'Signed workflow binding is invalid');
126
+ const values = { flowId: workflow?.flowId ?? subject.chainId, stepId: workflow?.stepId ?? subject.validationRunId,
127
+ snapshotDigest: subject.contracts?.aimlock?.snapshotSha256 ?? subject.snapshotDigest,
128
+ contractDigest: subject.contracts?.archguard?.contractSha256 ?? subject.contractDigest };
129
+ if (!ID.test(String(values.flowId ?? '')) || !ID.test(String(values.stepId ?? ''))) fail('ENTROROVE_EVIDENCE_BINDING', 'Signed flow and step are required');
130
+ for (const field of ['flowId', 'stepId']) {
131
+ if (evidence[field] !== undefined && evidence[field] !== values[field]) fail('ENTROROVE_EVIDENCE_BINDING', 'Outer evidence flow or step differs from signed subject');
132
+ }
133
+ for (const field of ['snapshotDigest', 'contractDigest']) {
134
+ if (subject[field] !== undefined && subject[field] !== values[field]) fail('ENTROROVE_EVIDENCE_BINDING', 'Subject has conflicting contract digest bindings');
135
+ }
136
+ const binding = options.binding ?? {};
137
+ for (const field of ['flowId', 'stepId', 'snapshotDigest', 'contractDigest']) {
138
+ if ((options.requireBinding || binding[field] !== undefined) && (binding[field] === undefined || values[field] !== binding[field]
139
+ || (field.endsWith('Digest') && !SHA.test(String(values[field] ?? ''))))) {
140
+ fail('ENTROROVE_EVIDENCE_BINDING', `Evidence is not bound to requested ${field}`);
141
+ }
142
+ }
143
+ for (const field of ['artifactSha256', 'subjectDigest']) {
144
+ if (binding[field] !== undefined && evidence[field] !== binding[field]) fail('ENTROROVE_EVIDENCE_BINDING', `Evidence ${field} does not match requested subject`);
145
+ }
146
+ }
147
+
148
+ function executionResult(evidence, subject, now) {
149
+ const receipt = evidence.receipt; const result = receipt.result;
150
+ const issued = Date.parse(receipt.issuedAt); const expires = Date.parse(receipt.expiresAt);
151
+ if (!ID.test(String(receipt.nonce ?? '')) || !Number.isFinite(issued) || !Number.isFinite(expires)
152
+ || issued > now + 60_000 || expires <= now || expires <= issued || expires - issued > 600_000) {
153
+ fail('ENTROROVE_EVIDENCE_LIFETIME', 'Execution receipt lifetime or nonce is invalid');
154
+ }
155
+ if (!object(result) || result.runner !== 'trusted-runner' || typeof result.passed !== 'boolean'
156
+ || result.exitCode !== evidence.exitCode || result.durationMs !== evidence.durationMs || result.summary !== evidence.summary) {
157
+ fail('ENTROROVE_EVIDENCE_RESULT', 'Execution receipt result is not bound to evidence');
158
+ }
159
+ if (subject.execution !== undefined) {
160
+ const execution = subject.execution;
161
+ if (!object(execution) || (execution.exitCode === null ? 1 : execution.exitCode) !== evidence.exitCode || typeof execution.timedOut !== 'boolean'
162
+ || typeof execution.outputLimitExceeded !== 'boolean' || (execution.signal !== null && !text(execution.signal, 64))) {
163
+ fail('ENTROROVE_EVIDENCE_RESULT', 'Signed process result is invalid');
164
+ }
165
+ const passed = execution.exitCode === 0 && execution.signal === null && !execution.timedOut && !execution.outputLimitExceeded;
166
+ if (passed !== result.passed) fail('ENTROROVE_EVIDENCE_RESULT', 'Receipt passed flag differs from signed process result');
167
+ }
168
+ if (result.passed && evidence.exitCode !== 0) fail('ENTROROVE_EVIDENCE_RESULT', 'Successful receipt must exit zero');
169
+ return result.passed && evidence.exitCode === 0;
170
+ }
171
+
172
+ export function verifyEvidenceIntegrity(evidence, options = {}) {
173
+ try {
174
+ validateEvidence(evidence); const receipt = evidence.receipt; const payload = receiptPayload(evidence);
175
+ const keyId = verifySignature(receipt, payload, options.publicKey ?? receipt?.publicKey);
176
+ if (receipt.schemaVersion === EXECUTION_SCHEMA) {
177
+ const subject = validateSubject(evidence, options);
178
+ executionResult(evidence, subject, options.now ?? Date.now());
179
+ }
180
+ return state('incomplete', { authentic: true, integrity: 'verified', keyId, evidence,
181
+ reason: 'Signature integrity alone does not establish independent successful execution' });
182
+ } catch (error) { return state('blocked', { integrity: 'invalid', code: error.code ?? 'ENTROROVE_EVIDENCE_INVALID', reason: error.message }); }
183
+ }
184
+
185
+ export function verifyTestEvidence(evidence, options = {}) {
186
+ try {
187
+ validateEvidence(evidence);
188
+ if (evidence.runner === 'local' || !options.publicKey) return state('incomplete', { evidence,
189
+ reason: 'Local evidence or an unconfigured independent verifier cannot establish trusted execution' });
190
+ const now = options.now ?? Date.now();
191
+ if (!Number.isSafeInteger(now) || now < 0) fail('ENTROROVE_EVIDENCE_TIME', 'Trusted verification time is invalid');
192
+ const payload = receiptPayload(evidence); const keyId = verifySignature(evidence.receipt, payload, options.publicKey);
193
+ if (evidence.receipt.schemaVersion === GENERIC_SCHEMA) return state('incomplete', { authentic: true, integrity: 'verified', keyId, evidence,
194
+ reason: 'Generic signatures have no signed execution lifetime or result authority' });
195
+ const subject = validateSubject(evidence, options); const successful = executionResult(evidence, subject, now);
196
+ return state(successful ? 'verified' : 'blocked', { verified: true, authentic: true, successful, keyId, evidence,
197
+ integrity: 'verified', reason: successful ? 'Independent signed execution passed' : 'Independent signed execution failed' });
198
+ } catch (error) { return state('blocked', { code: error.code ?? 'ENTROROVE_EVIDENCE_INVALID', reason: error.message }); }
199
+ }