@evomap/evolver-core 2.0.0-beta.19 → 2.0.0-beta.22

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 (160) hide show
  1. package/assets/gep/genes.jsonl +5 -5
  2. package/dist/algo/bans.d.ts +10 -1
  3. package/dist/algo/bans.js +56 -6
  4. package/dist/algo/candidateAssembly.d.ts +25 -2
  5. package/dist/algo/candidateAssembly.js +143 -20
  6. package/dist/algo/capabilityCandidates.js +10 -0
  7. package/dist/algo/cycleEngine.d.ts +40 -5
  8. package/dist/algo/cycleEngine.js +277 -37
  9. package/dist/algo/evolutionEvent.d.ts +26 -0
  10. package/dist/algo/evolutionEvent.js +32 -0
  11. package/dist/algo/exploration.d.ts +7 -0
  12. package/dist/algo/exploration.js +16 -3
  13. package/dist/algo/geneHealth.d.ts +34 -1
  14. package/dist/algo/geneHealth.js +42 -0
  15. package/dist/algo/geneIntake.d.ts +46 -1
  16. package/dist/algo/geneIntake.js +121 -10
  17. package/dist/algo/geneSelection.d.ts +115 -6
  18. package/dist/algo/geneSelection.js +459 -32
  19. package/dist/algo/index.d.ts +4 -1
  20. package/dist/algo/index.js +4 -1
  21. package/dist/algo/kautoProjection.d.ts +41 -0
  22. package/dist/algo/kautoProjection.js +95 -0
  23. package/dist/algo/kautoValidator.d.ts +68 -0
  24. package/dist/algo/kautoValidator.js +256 -0
  25. package/dist/algo/orchestrator.d.ts +14 -1
  26. package/dist/algo/orchestrator.js +9 -2
  27. package/dist/algo/solidify.d.ts +11 -2
  28. package/dist/algo/solidify.js +37 -7
  29. package/dist/algo/ucb1.d.ts +53 -0
  30. package/dist/algo/ucb1.js +156 -0
  31. package/dist/assetrepair/hubRejection.d.ts +12 -0
  32. package/dist/assetrepair/hubRejection.js +109 -0
  33. package/dist/assetrepair/index.d.ts +2 -0
  34. package/dist/assetrepair/index.js +2 -0
  35. package/dist/assetrepair/repair.d.ts +33 -0
  36. package/dist/assetrepair/repair.js +155 -0
  37. package/dist/assetstore/assetSidecarRecords.js +5 -1
  38. package/dist/assetstore/assetStoreHealth.d.ts +2 -3
  39. package/dist/assetstore/assetStoreHealth.js +4 -10
  40. package/dist/assetstore/foreignJsonlSource.d.ts +48 -0
  41. package/dist/assetstore/foreignJsonlSource.js +150 -0
  42. package/dist/assetstore/index.d.ts +3 -0
  43. package/dist/assetstore/index.js +3 -0
  44. package/dist/assetstore/learningHistory.js +3 -3
  45. package/dist/assetstore/localAssetStoreSnapshot.d.ts +51 -0
  46. package/dist/assetstore/localAssetStoreSnapshot.js +329 -0
  47. package/dist/assetstore/localJsonl.d.ts +8 -0
  48. package/dist/assetstore/localJsonl.js +128 -3
  49. package/dist/assetstore/provenance.d.ts +38 -3
  50. package/dist/assetstore/provenance.js +103 -45
  51. package/dist/assetstore/provider.d.ts +4 -0
  52. package/dist/assetstore/reviewFilter.d.ts +19 -1
  53. package/dist/assetstore/reviewFilter.js +36 -0
  54. package/dist/assetstore/unionReadStore.d.ts +25 -0
  55. package/dist/assetstore/unionReadStore.js +119 -0
  56. package/dist/benchmark/antiGeneBenchmark.d.ts +2 -0
  57. package/dist/benchmark/antiGeneBenchmark.js +4 -3
  58. package/dist/benchmark/antiGeneRollout.d.ts +2 -0
  59. package/dist/benchmark/antiGeneRollout.js +4 -3
  60. package/dist/benchmark/index.d.ts +2 -1
  61. package/dist/benchmark/index.js +2 -1
  62. package/dist/benchmark/selectionFlatAbstention.d.ts +152 -0
  63. package/dist/benchmark/selectionFlatAbstention.js +481 -0
  64. package/dist/bootstrap/envFingerprint.d.ts +9 -0
  65. package/dist/bootstrap/envFingerprint.js +5 -0
  66. package/dist/bootstrap/index.d.ts +2 -1
  67. package/dist/bootstrap/index.js +2 -1
  68. package/dist/bootstrap/lifecycleBootstrap.d.ts +111 -0
  69. package/dist/bootstrap/lifecycleBootstrap.js +433 -0
  70. package/dist/bootstrap/v1EnvCompat.d.ts +3 -0
  71. package/dist/bootstrap/v1EnvCompat.js +48 -1
  72. package/dist/events/eventArchive.d.ts +2 -0
  73. package/dist/events/eventArchive.js +13 -3
  74. package/dist/events/eventSchema.d.ts +7 -7
  75. package/dist/events/eventStore.d.ts +2 -0
  76. package/dist/events/eventStore.js +5 -1
  77. package/dist/events/ingest.d.ts +2 -1
  78. package/dist/events/ingest.js +6 -0
  79. package/dist/exec/autoExec.d.ts +30 -3
  80. package/dist/exec/autoExec.js +294 -29
  81. package/dist/exec/autonomousCycle.d.ts +7 -0
  82. package/dist/exec/autonomousCycle.js +2 -0
  83. package/dist/exec/claudeBridge.d.ts +28 -6
  84. package/dist/exec/claudeBridge.js +411 -258
  85. package/dist/exec/executionBinding.d.ts +414 -0
  86. package/dist/exec/executionBinding.js +588 -0
  87. package/dist/exec/index.d.ts +1 -0
  88. package/dist/exec/index.js +1 -0
  89. package/dist/exec/proofOfWork.d.ts +1 -1
  90. package/dist/exec/proofOfWork.js +2 -2
  91. package/dist/exec/runnerRegistry.d.ts +5 -0
  92. package/dist/exec/runnerRegistry.js +54 -14
  93. package/dist/hub/capability.d.ts +40 -1
  94. package/dist/hub/conversationDistiller.d.ts +19 -0
  95. package/dist/hub/conversationDistiller.js +115 -37
  96. package/dist/hub/fake.d.ts +1 -0
  97. package/dist/hub/fake.js +1 -0
  98. package/dist/hub/index.d.ts +1 -0
  99. package/dist/hub/index.js +1 -0
  100. package/dist/hub/recipeCompose.d.ts +27 -0
  101. package/dist/hub/recipeCompose.js +90 -0
  102. package/dist/hub/sanitize.js +119 -5
  103. package/dist/index.d.ts +2 -0
  104. package/dist/index.js +2 -0
  105. package/dist/mailbox/ipcServer.d.ts +2 -0
  106. package/dist/mailbox/ipcServer.js +20 -0
  107. package/dist/mailbox/store.d.ts +52 -2
  108. package/dist/mailbox/store.js +546 -81
  109. package/dist/modelCompatibility.d.ts +164 -0
  110. package/dist/modelCompatibility.js +309 -0
  111. package/dist/observers/valueDigestObserver.d.ts +9 -0
  112. package/dist/observers/valueDigestObserver.js +35 -2
  113. package/dist/ops/cleanup.js +1 -1
  114. package/dist/ops/evolutionGraphProjection.d.ts +20 -0
  115. package/dist/ops/evolutionGraphProjection.js +315 -0
  116. package/dist/ops/index.d.ts +2 -1
  117. package/dist/ops/index.js +2 -1
  118. package/dist/ops/selfUpdate.d.ts +8 -0
  119. package/dist/ops/selfUpdate.js +24 -8
  120. package/dist/ops/valueOutreach.d.ts +3 -1
  121. package/dist/ops/valueOutreach.js +5 -1
  122. package/dist/personality/schema.d.ts +18 -18
  123. package/dist/schema/evolutionGraph.d.ts +784 -0
  124. package/dist/schema/evolutionGraph.js +187 -0
  125. package/dist/schema/index.d.ts +1 -0
  126. package/dist/schema/index.js +1 -0
  127. package/dist/schema/proofOfWork.d.ts +125 -6
  128. package/dist/schema/proofOfWork.js +102 -4
  129. package/dist/shadow/shadowHub.js +1 -0
  130. package/dist/signals/expand.d.ts +15 -1
  131. package/dist/signals/expand.js +148 -0
  132. package/dist/signals/index.d.ts +3 -1
  133. package/dist/signals/index.js +3 -1
  134. package/dist/signals/scopeVocabulary.d.ts +75 -0
  135. package/dist/signals/scopeVocabulary.js +91 -0
  136. package/dist/signals/taskDomain.d.ts +22 -0
  137. package/dist/signals/taskDomain.js +43 -0
  138. package/dist/trace/learningTrace.d.ts +7 -0
  139. package/dist/trace/learningTrace.js +22 -0
  140. package/dist/trace/trajectory.d.ts +8 -0
  141. package/dist/trace/trajectory.js +14 -2
  142. package/dist/util/fileLock.d.ts +92 -5
  143. package/dist/util/fileLock.js +809 -70
  144. package/dist/util/index.d.ts +2 -1
  145. package/dist/util/index.js +1 -1
  146. package/dist/verify/index.d.ts +2 -1
  147. package/dist/verify/index.js +1 -1
  148. package/dist/verify/sandboxRunner.d.ts +2 -0
  149. package/dist/verify/sandboxRunner.js +154 -10
  150. package/dist/verify/sandboxedValidation.d.ts +7 -2
  151. package/dist/verify/sandboxedValidation.js +102 -24
  152. package/dist/verify/validation.d.ts +24 -3
  153. package/dist/verify/validation.js +141 -24
  154. package/dist/wire/geneHints.d.ts +88 -16
  155. package/dist/wire/geneHints.js +124 -15
  156. package/dist/wire/index.d.ts +8 -3
  157. package/dist/wire/index.js +2 -2
  158. package/dist/wire/schemaGate.d.ts +21 -0
  159. package/dist/wire/schemaGate.js +119 -10
  160. package/package.json +5 -4
@@ -0,0 +1,315 @@
1
+ // Read-only Evolution Graph projection over already-emitted root_events.
2
+ //
3
+ // PURE: a function over a root-event snapshot. It never appends events, writes assets, or mutates selection —
4
+ // projecting is strictly an observability concern (same posture as ops/reuseOutcomes.ts). The graph it returns is
5
+ // evidence for "which variant was selected on what basis, and was that later contradicted", not a new actuator.
6
+ //
7
+ // Every edge carries provenance back to the root_event seq that justified it, so a dashboard card can always be
8
+ // traced to a specific emitted event instead of a narrative summary.
9
+ import { deriveEvolutionGraphDashboardSummary, EVOLUTION_GRAPH_SCHEMA_VERSION, } from '../schema/evolutionGraph.js';
10
+ import { HOST_SUPPRESS_CLASSES } from '../algo/cycleFailureClassifier.js';
11
+ const DEFAULT_MAX_EVENTS = 5_000;
12
+ const MAX_LABEL = 120;
13
+ const RESOLUTION_STATUSES = new Set([
14
+ 'pending',
15
+ 'suppressed_observationally',
16
+ 'resolved_by_evidence',
17
+ 'regressed',
18
+ 'inconclusive',
19
+ ]);
20
+ export function projectEvolutionGraph(events, options = {}) {
21
+ const maxEvents = boundedLimit(options.maxEvents, DEFAULT_MAX_EVENTS);
22
+ const window = events.length > maxEvents ? events.slice(events.length - maxEvents) : events;
23
+ const builder = new GraphBuilder();
24
+ for (const event of window)
25
+ builder.absorb(event);
26
+ const nodes = builder.nodes();
27
+ const edges = builder.edges();
28
+ const newestTs = window.length > 0 ? text(window[window.length - 1]?.ts) : '';
29
+ return {
30
+ schemaVersion: EVOLUTION_GRAPH_SCHEMA_VERSION,
31
+ graphId: options.graphId ?? 'graph:evolution:root-events',
32
+ generatedAt: options.generatedAt ?? (isoTimestamp(newestTs) ?? '1970-01-01T00:00:00.000Z'),
33
+ nodes,
34
+ edges,
35
+ dashboard: deriveEvolutionGraphDashboardSummary({ nodes, edges }),
36
+ extensions: {},
37
+ };
38
+ }
39
+ class GraphBuilder {
40
+ nodesById = new Map();
41
+ edgesById = new Map();
42
+ variantByLifecycle = new Map();
43
+ /** cycleId can be reused; only events in the current lifecycle may share evidence or graph nodes. */
44
+ lifecycleByCycle = new Map();
45
+ nodes() {
46
+ return [...this.nodesById.values()].sort((left, right) => left.id.localeCompare(right.id));
47
+ }
48
+ edges() {
49
+ return [...this.edgesById.values()].sort((left, right) => left.id.localeCompare(right.id));
50
+ }
51
+ absorb(event) {
52
+ const at = isoTimestamp(text(event.ts));
53
+ if (!at)
54
+ return;
55
+ const payload = event.payload ?? {};
56
+ const cycleId = opaqueId(payload['cycleId']);
57
+ switch (event.type) {
58
+ case 'cycle.started': {
59
+ if (cycleId)
60
+ this.beginLifecycle(cycleId);
61
+ return;
62
+ }
63
+ case 'capsule.produced': {
64
+ if (!cycleId)
65
+ return;
66
+ const capsuleId = opaqueId(payload['capsuleId']);
67
+ const status = resolutionStatus(payload['resolutionStatus']);
68
+ if (!capsuleId || !status)
69
+ return;
70
+ const lifecycle = this.activeLifecycle(cycleId);
71
+ lifecycle.capsule = {
72
+ capsuleId,
73
+ resolutionStatus: status,
74
+ producedValue: payload['producedValue'] === true,
75
+ event,
76
+ };
77
+ return;
78
+ }
79
+ case 'decision.gene_selected': {
80
+ if (!cycleId)
81
+ return;
82
+ const lifecycle = this.decisionLifecycle(cycleId, event);
83
+ const variant = this.variant(lifecycle, at);
84
+ const gene = opaqueId(payload['selectedAssetId']) ?? opaqueId(payload['selectedGeneId']);
85
+ if (gene) {
86
+ const spec = this.node(`spec:${gene}`, 'spec', `gene ${gene}`, at);
87
+ this.edge('derivation', spec, variant, at, event, 'variant derived from the selected gene');
88
+ }
89
+ const selection = this.node(`selection:${lifecycle.key}`, 'selection', `selection for cycle ${cycleId}`, at);
90
+ const reason = text(payload['selectedReason']) || text(event.human?.title) || 'gene selected by cycle engine';
91
+ this.edge('selected', variant, selection, at, event, reason);
92
+ return;
93
+ }
94
+ case 'mutation.built': {
95
+ if (!cycleId)
96
+ return;
97
+ const lifecycle = this.activeLifecycle(cycleId);
98
+ if (!lifecycle.key)
99
+ return;
100
+ const variant = this.variant(lifecycle, at);
101
+ const mutationId = opaqueId(payload['mutationId']);
102
+ if (!mutationId)
103
+ return;
104
+ const code = this.node(`code:${mutationId}`, 'code', `mutation ${mutationId}`, at);
105
+ this.edge('derivation', variant, code, at, event, 'variant produced a mutation');
106
+ return;
107
+ }
108
+ case 'cycle.solidified': {
109
+ if (!cycleId)
110
+ return;
111
+ const lifecycle = this.activeLifecycle(cycleId);
112
+ lifecycle.terminal = true;
113
+ if (!lifecycle.key)
114
+ return;
115
+ const score = terminalOutcomeScore(payload['outcome'], 'success');
116
+ if (score === null)
117
+ return;
118
+ const variant = this.variant(lifecycle, at);
119
+ const run = this.node(`run:${lifecycle.key}`, 'run', `cycle ${cycleId}`, at);
120
+ this.edge('evaluated_by', variant, run, at, event, 'cycle completed with a measured outcome');
121
+ const evidence = this.matchingCapsuleEvidence(lifecycle, payload, true);
122
+ if (evidence?.resolutionStatus === 'resolved_by_evidence'
123
+ && evidence.producedValue
124
+ && payload['producedValue'] === true) {
125
+ this.edge('fixed', variant, run, at, event, 'cycle resolved by output-backed validation evidence', {
126
+ metric: 'cycle_outcome_score',
127
+ after: score,
128
+ direction: 'improved',
129
+ }, [evidence.event]);
130
+ }
131
+ return;
132
+ }
133
+ case 'cycle.failed': {
134
+ if (!cycleId)
135
+ return;
136
+ const lifecycle = this.activeLifecycle(cycleId);
137
+ lifecycle.terminal = true;
138
+ if (!lifecycle.key)
139
+ return;
140
+ const score = terminalOutcomeScore(payload['outcome'], 'failed');
141
+ const failureClass = text(payload['failure_class']);
142
+ if (score === null || text(payload['failureKind']) || suppressesFailure(failureClass))
143
+ return;
144
+ const variant = this.variant(lifecycle, at);
145
+ const run = this.node(`run:${lifecycle.key}`, 'run', `cycle ${cycleId}`, at);
146
+ this.edge('evaluated_by', variant, run, at, event, 'cycle completed with a measured failed outcome');
147
+ const capsule = this.matchingCapsuleEvidence(lifecycle, payload);
148
+ const inlineStatus = resolutionStatus(payload['resolutionStatus']);
149
+ if (hasOwn(payload, 'resolutionStatus') && !inlineStatus)
150
+ return;
151
+ const status = inlineStatus ?? capsule?.resolutionStatus ?? null;
152
+ if (inlineStatus && capsule && inlineStatus !== capsule.resolutionStatus)
153
+ return;
154
+ if (status === 'regressed') {
155
+ this.edge('regressed', variant, run, at, event, failureClass || 'measured cycle regression', {
156
+ metric: 'cycle_outcome_score',
157
+ after: score,
158
+ direction: 'regressed',
159
+ }, capsule ? [capsule.event] : []);
160
+ }
161
+ return;
162
+ }
163
+ case 'cycle.aborted': {
164
+ if (cycleId)
165
+ this.activeLifecycle(cycleId).terminal = true;
166
+ return;
167
+ }
168
+ case 'value.reuse_outcome': {
169
+ const assetId = opaqueId(payload['assetId']);
170
+ if (!assetId)
171
+ return;
172
+ const spec = this.node(`spec:${assetId}`, 'spec', `gene ${assetId}`, at);
173
+ const feedback = this.node(`feedback:${assetId}:${event.seq}`, 'feedback', `reuse outcome ${text(payload['outcome']) || 'negative'}`, at);
174
+ this.edge('derivation', feedback, spec, at, event, 'reuse feedback recorded against the gene');
175
+ return;
176
+ }
177
+ case 'anti_gene.rollout_result': {
178
+ const suite = opaqueId(payload['suite']) ?? `seq-${event.seq}`;
179
+ const test = this.node(`test:${suite}`, 'test', `anti-gene rollout ${suite}`, at);
180
+ const verdict = text(payload['verdict']);
181
+ const variant = this.node(`variant:rollout:${suite}`, 'variant', `anti-gene arm ${suite}`, at);
182
+ this.edge('evaluated_by', variant, test, at, event, verdict || 'anti-gene rollout evaluated');
183
+ return;
184
+ }
185
+ default:
186
+ return;
187
+ }
188
+ }
189
+ beginLifecycle(cycleId) {
190
+ const lifecycle = {
191
+ cycleId,
192
+ key: '',
193
+ decisionSeen: false,
194
+ capsule: null,
195
+ terminal: false,
196
+ };
197
+ this.lifecycleByCycle.set(cycleId, lifecycle);
198
+ return lifecycle;
199
+ }
200
+ activeLifecycle(cycleId) {
201
+ const current = this.lifecycleByCycle.get(cycleId);
202
+ return !current || current.terminal ? this.beginLifecycle(cycleId) : current;
203
+ }
204
+ decisionLifecycle(cycleId, event) {
205
+ let lifecycle = this.lifecycleByCycle.get(cycleId);
206
+ if (!lifecycle || lifecycle.decisionSeen || lifecycle.capsule || lifecycle.terminal) {
207
+ lifecycle = this.beginLifecycle(cycleId);
208
+ }
209
+ lifecycle.key = `${cycleId}:seq:${event.seq}`;
210
+ lifecycle.decisionSeen = true;
211
+ lifecycle.capsule = null;
212
+ return lifecycle;
213
+ }
214
+ variant(lifecycle, at) {
215
+ const existing = this.variantByLifecycle.get(lifecycle.key);
216
+ if (existing)
217
+ return this.nodesById.get(existing);
218
+ const node = this.node(`variant:${lifecycle.key}`, 'variant', `variant from cycle ${lifecycle.cycleId}`, at);
219
+ this.variantByLifecycle.set(lifecycle.key, node.id);
220
+ return node;
221
+ }
222
+ matchingCapsuleEvidence(lifecycle, payload, requireCapsuleId = false) {
223
+ const evidence = lifecycle.capsule;
224
+ if (!evidence)
225
+ return null;
226
+ if (!hasOwn(payload, 'capsuleId'))
227
+ return requireCapsuleId ? null : evidence;
228
+ const capsuleId = opaqueId(payload['capsuleId']);
229
+ return !capsuleId || capsuleId !== evidence.capsuleId ? null : evidence;
230
+ }
231
+ node(id, kind, label, at) {
232
+ const existing = this.nodesById.get(id);
233
+ if (existing)
234
+ return existing;
235
+ const node = {
236
+ id,
237
+ kind,
238
+ label: label.slice(0, MAX_LABEL) || id,
239
+ createdAt: at,
240
+ metrics: [],
241
+ tags: [],
242
+ extensions: {},
243
+ };
244
+ this.nodesById.set(id, node);
245
+ return node;
246
+ }
247
+ edge(kind, from, to, at, event, reason, metricDelta, supportingEvents = []) {
248
+ const id = `edge:${kind}:${from.id}->${to.id}:${event.seq}`;
249
+ if (this.edgesById.has(id))
250
+ return;
251
+ this.edgesById.set(id, {
252
+ id,
253
+ kind,
254
+ from: from.id,
255
+ to: to.id,
256
+ createdAt: at,
257
+ provenance: provenanceFor([...supportingEvents, event]),
258
+ ...(metricDelta ? { metricDelta } : {}),
259
+ reason: reason.slice(0, MAX_LABEL),
260
+ extensions: {},
261
+ });
262
+ }
263
+ }
264
+ function boundedLimit(value, fallback) {
265
+ if (!Number.isFinite(value) || value === undefined || value <= 0)
266
+ return fallback;
267
+ return Math.min(fallback, Math.floor(value));
268
+ }
269
+ function text(value) {
270
+ return typeof value === 'string' ? value.replace(/[\r\n\t]+/g, ' ').trim() : '';
271
+ }
272
+ /** Opaque local identifiers only: no control characters, bounded, so a graph id cannot smuggle payload text. */
273
+ function opaqueId(value) {
274
+ const candidate = text(value);
275
+ if (!candidate || candidate.length > 160)
276
+ return null;
277
+ return /^[A-Za-z0-9][A-Za-z0-9:._-]*$/.test(candidate) ? candidate : null;
278
+ }
279
+ function isoTimestamp(value) {
280
+ if (!value)
281
+ return null;
282
+ const parsed = Date.parse(value);
283
+ return Number.isFinite(parsed) ? new Date(parsed).toISOString() : null;
284
+ }
285
+ function terminalOutcomeScore(value, expectedStatus) {
286
+ if (!value || typeof value !== 'object' || Array.isArray(value))
287
+ return null;
288
+ const outcome = value;
289
+ if (outcome['status'] !== expectedStatus)
290
+ return null;
291
+ const score = outcome['score'];
292
+ return typeof score === 'number' && Number.isFinite(score) ? score : null;
293
+ }
294
+ function resolutionStatus(value) {
295
+ return typeof value === 'string' && RESOLUTION_STATUSES.has(value)
296
+ ? value
297
+ : null;
298
+ }
299
+ function suppressesFailure(value) {
300
+ return value !== '' && HOST_SUPPRESS_CLASSES.has(value);
301
+ }
302
+ function hasOwn(value, key) {
303
+ return Object.prototype.hasOwnProperty.call(value, key);
304
+ }
305
+ function provenanceFor(events) {
306
+ const seen = new Set();
307
+ return events.flatMap((event) => {
308
+ const capturedAt = isoTimestamp(text(event.ts));
309
+ const ref = `seq:${event.seq}`;
310
+ if (!capturedAt || seen.has(ref))
311
+ return [];
312
+ seen.add(ref);
313
+ return [{ kind: 'root_event', ref, capturedAt, summary: event.type }];
314
+ });
315
+ }
@@ -4,4 +4,5 @@ export * from './selfUpdate.js';
4
4
  export * from './valueLedger.js';
5
5
  export * from './valueOutreach.js';
6
6
  export * from './recall.js';
7
- export * from './reuseOutcomes.js';
7
+ export * from './reuseOutcomes.js';
8
+ export * from './evolutionGraphProjection.js';
package/dist/ops/index.js CHANGED
@@ -4,4 +4,5 @@ export * from './selfUpdate.js';
4
4
  export * from './valueLedger.js';
5
5
  export * from './valueOutreach.js';
6
6
  export * from './recall.js';
7
- export * from './reuseOutcomes.js';
7
+ export * from './reuseOutcomes.js';
8
+ export * from './evolutionGraphProjection.js';
@@ -91,6 +91,14 @@ export interface DownloadedArtifact {
91
91
  /** Or a precomputed lowercase-hex sha256, if the caller hashed during streaming (avoids buffering). */
92
92
  sha256?: string;
93
93
  }
94
+ /**
95
+ * Parse a configured public key (PEM, raw 32-byte base64, SPKI DER base64, or a KeyObject) into a node KeyObject.
96
+ *
97
+ * The base64 forms mirror scripts/release-update-manifest.mjs parsePublicKey exactly: the release pipeline and the
98
+ * built-in channel key ship the full SPKI DER blob (44 bytes for Ed25519), while operator overrides may supply the
99
+ * bare 32-byte raw key. Anything that does not decode to a valid Ed25519 SPKI key throws (fail-closed).
100
+ */
101
+ export declare function toPublicKey(publicKey: string | KeyObject): KeyObject;
94
102
  /**
95
103
  * Verify downloaded artifacts against the manifest. PURE + deterministic (takes already-read bytes/hashes; does
96
104
  * NO I/O). Two layers:
@@ -224,19 +224,35 @@ export function canonicalManifestBytes(manifest) {
224
224
  };
225
225
  return new TextEncoder().encode(JSON.stringify(canonical));
226
226
  }
227
- /** Parse a configured public key (PEM, raw 32-byte base64, or a KeyObject) into a node KeyObject. */
228
- function toPublicKey(publicKey) {
227
+ /**
228
+ * Parse a configured public key (PEM, raw 32-byte base64, SPKI DER base64, or a KeyObject) into a node KeyObject.
229
+ *
230
+ * The base64 forms mirror scripts/release-update-manifest.mjs parsePublicKey exactly: the release pipeline and the
231
+ * built-in channel key ship the full SPKI DER blob (44 bytes for Ed25519), while operator overrides may supply the
232
+ * bare 32-byte raw key. Anything that does not decode to a valid Ed25519 SPKI key throws (fail-closed).
233
+ */
234
+ export function toPublicKey(publicKey) {
229
235
  if (typeof publicKey !== 'string')
230
236
  return publicKey;
231
237
  const trimmed = publicKey.trim();
232
238
  if (trimmed.includes('BEGIN PUBLIC KEY'))
233
239
  return createPublicKey(trimmed);
234
- // Raw 32-byte Ed25519 key, base64 → wrap in DER SPKI so createPublicKey accepts it.
235
- const raw = Buffer.from(trimmed, 'base64');
236
- if (raw.length !== 32)
237
- throw new Error('ed25519 raw key must be 32 bytes');
238
- const der = Buffer.concat([Buffer.from('302a300506032b6570032100', 'hex'), raw]);
239
- return createPublicKey({ key: der, format: 'der', type: 'spki' });
240
+ const decoded = Buffer.from(trimmed, 'base64');
241
+ // Raw 32-byte Ed25519 key, base64 → wrap in DER SPKI so createPublicKey accepts it;
242
+ // any other length is assumed to already be a full SPKI DER blob.
243
+ const der = decoded.length === 32
244
+ ? Buffer.concat([Buffer.from('302a300506032b6570032100', 'hex'), decoded])
245
+ : decoded;
246
+ let key;
247
+ try {
248
+ key = createPublicKey({ key: der, format: 'der', type: 'spki' });
249
+ }
250
+ catch {
251
+ throw new Error('ed25519 public key must be a raw 32-byte or SPKI DER base64 key');
252
+ }
253
+ if (key.asymmetricKeyType !== 'ed25519')
254
+ throw new Error('ed25519 public key must be an Ed25519 key');
255
+ return key;
240
256
  }
241
257
  /** Verify the signature over the complete canonical manifest when a public key is configured. */
242
258
  function verifyConfiguredManifestSignature(manifest, publicKey) {
@@ -67,4 +67,6 @@ export declare function digestShouldSend(summary: ValueSummary): boolean;
67
67
  * caller then delivers nothing — no empty digest, ever). measured and estimated stay on separate lines. Pure:
68
68
  * the window label + the period string are passed in so the digest is deterministic.
69
69
  */
70
- export declare function buildValueDigest(summary: ValueSummary, period: string): string | null;
70
+ export declare function buildValueDigest(summary: ValueSummary, period: string, extras?: {
71
+ pendingReviewCount?: number;
72
+ }): string | null;
@@ -221,7 +221,7 @@ export function digestShouldSend(summary) {
221
221
  * caller then delivers nothing — no empty digest, ever). measured and estimated stay on separate lines. Pure:
222
222
  * the window label + the period string are passed in so the digest is deterministic.
223
223
  */
224
- export function buildValueDigest(summary, period) {
224
+ export function buildValueDigest(summary, period, extras = {}) {
225
225
  if (!digestShouldSend(summary))
226
226
  return null;
227
227
  const L = [];
@@ -238,6 +238,10 @@ export function buildValueDigest(summary, period) {
238
238
  for (const g of summary.topGenes.slice(0, 5))
239
239
  L.push(`- ${g.assetId} — reused ×${g.reuses}`);
240
240
  }
241
+ if ((extras.pendingReviewCount ?? 0) > 0) {
242
+ L.push('');
243
+ L.push(`${extras.pendingReviewCount} gene(s) still awaiting review — run \`evolver review\` so they can enter SessionStart.`);
244
+ }
241
245
  L.push('');
242
246
  L.push('_Run `evolver value` any time for the full breakdown. Turn this digest off with `EVOLVER_VALUE_DIGEST=0`._');
243
247
  return L.join('\n');
@@ -65,15 +65,15 @@ export declare const personalityStats: z.ZodObject<{
65
65
  n: z.ZodDefault<z.ZodNumber>;
66
66
  updatedAt: z.ZodDefault<z.ZodNullable<z.ZodString>>;
67
67
  }, "strip", z.ZodTypeAny, {
68
+ fail: number;
68
69
  success: number;
69
70
  updatedAt: string | null;
70
- fail: number;
71
71
  n: number;
72
72
  avgScore: number;
73
73
  }, {
74
+ fail?: number | undefined;
74
75
  success?: number | undefined;
75
76
  updatedAt?: string | null | undefined;
76
- fail?: number | undefined;
77
77
  n?: number | undefined;
78
78
  avgScore?: number | undefined;
79
79
  }>;
@@ -88,13 +88,13 @@ export declare const personalityHistoryEntry: z.ZodObject<{
88
88
  }, "strip", z.ZodTypeAny, {
89
89
  at: string;
90
90
  score: number | null;
91
- outcome: string;
92
91
  key: string;
92
+ outcome: string;
93
93
  notes: string | null;
94
94
  }, {
95
95
  at: string;
96
- outcome: string;
97
96
  key: string;
97
+ outcome: string;
98
98
  score?: number | null | undefined;
99
99
  notes?: string | null | undefined;
100
100
  }>;
@@ -132,15 +132,15 @@ export declare const personalityModel: z.ZodObject<{
132
132
  n: z.ZodDefault<z.ZodNumber>;
133
133
  updatedAt: z.ZodDefault<z.ZodNullable<z.ZodString>>;
134
134
  }, "strip", z.ZodTypeAny, {
135
+ fail: number;
135
136
  success: number;
136
137
  updatedAt: string | null;
137
- fail: number;
138
138
  n: number;
139
139
  avgScore: number;
140
140
  }, {
141
+ fail?: number | undefined;
141
142
  success?: number | undefined;
142
143
  updatedAt?: string | null | undefined;
143
- fail?: number | undefined;
144
144
  n?: number | undefined;
145
145
  avgScore?: number | undefined;
146
146
  }>>>;
@@ -153,13 +153,13 @@ export declare const personalityModel: z.ZodObject<{
153
153
  }, "strip", z.ZodTypeAny, {
154
154
  at: string;
155
155
  score: number | null;
156
- outcome: string;
157
156
  key: string;
157
+ outcome: string;
158
158
  notes: string | null;
159
159
  }, {
160
160
  at: string;
161
- outcome: string;
162
161
  key: string;
162
+ outcome: string;
163
163
  score?: number | null | undefined;
164
164
  notes?: string | null | undefined;
165
165
  }>, "many">>;
@@ -167,8 +167,6 @@ export declare const personalityModel: z.ZodObject<{
167
167
  extensions: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
168
168
  }, "strip", z.ZodTypeAny, {
169
169
  extensions: Record<string, unknown>;
170
- updatedAt: string | null;
171
- version: 1;
172
170
  current: {
173
171
  type: "PersonalityState";
174
172
  rigor: number;
@@ -177,24 +175,24 @@ export declare const personalityModel: z.ZodObject<{
177
175
  risk_tolerance: number;
178
176
  obedience: number;
179
177
  };
178
+ updatedAt: string | null;
179
+ version: 1;
180
180
  stats: Record<string, {
181
+ fail: number;
181
182
  success: number;
182
183
  updatedAt: string | null;
183
- fail: number;
184
184
  n: number;
185
185
  avgScore: number;
186
186
  }>;
187
187
  history: {
188
188
  at: string;
189
189
  score: number | null;
190
- outcome: string;
191
190
  key: string;
191
+ outcome: string;
192
192
  notes: string | null;
193
193
  }[];
194
194
  }, {
195
195
  extensions?: Record<string, unknown> | undefined;
196
- updatedAt?: string | null | undefined;
197
- version?: 1 | undefined;
198
196
  current?: {
199
197
  type?: "PersonalityState" | undefined;
200
198
  rigor?: number | undefined;
@@ -203,17 +201,19 @@ export declare const personalityModel: z.ZodObject<{
203
201
  risk_tolerance?: number | undefined;
204
202
  obedience?: number | undefined;
205
203
  } | undefined;
204
+ updatedAt?: string | null | undefined;
205
+ version?: 1 | undefined;
206
206
  stats?: Record<string, {
207
+ fail?: number | undefined;
207
208
  success?: number | undefined;
208
209
  updatedAt?: string | null | undefined;
209
- fail?: number | undefined;
210
210
  n?: number | undefined;
211
211
  avgScore?: number | undefined;
212
212
  }> | undefined;
213
213
  history?: {
214
214
  at: string;
215
- outcome: string;
216
215
  key: string;
216
+ outcome: string;
217
217
  score?: number | null | undefined;
218
218
  notes?: string | null | undefined;
219
219
  }[] | undefined;
@@ -227,12 +227,12 @@ export declare const personalityMutation: z.ZodObject<{
227
227
  reason: z.ZodDefault<z.ZodString>;
228
228
  }, "strip", z.ZodTypeAny, {
229
229
  type: "PersonalityMutation";
230
+ delta: number;
230
231
  reason: string;
231
232
  param: "rigor" | "creativity" | "verbosity" | "risk_tolerance" | "obedience";
232
- delta: number;
233
233
  }, {
234
- param: "rigor" | "creativity" | "verbosity" | "risk_tolerance" | "obedience";
235
234
  delta: number;
235
+ param: "rigor" | "creativity" | "verbosity" | "risk_tolerance" | "obedience";
236
236
  type?: "PersonalityMutation" | undefined;
237
237
  reason?: string | undefined;
238
238
  }>;