@evomap/evolver-core 2.0.0-beta.9 → 2.0.0

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 (142) hide show
  1. package/dist/algo/candidateAssembly.d.ts +7 -2
  2. package/dist/algo/candidateAssembly.js +81 -13
  3. package/dist/algo/capabilityCandidates.js +10 -0
  4. package/dist/algo/cycleEngine.d.ts +23 -2
  5. package/dist/algo/cycleEngine.js +236 -36
  6. package/dist/algo/exploration.d.ts +7 -0
  7. package/dist/algo/exploration.js +16 -3
  8. package/dist/algo/geneHealth.d.ts +2 -2
  9. package/dist/algo/geneHealth.js +5 -4
  10. package/dist/algo/geneSelection.d.ts +63 -5
  11. package/dist/algo/geneSelection.js +330 -30
  12. package/dist/algo/index.d.ts +2 -0
  13. package/dist/algo/index.js +2 -0
  14. package/dist/algo/orchestrator.d.ts +8 -1
  15. package/dist/algo/orchestrator.js +15 -3
  16. package/dist/algo/publishEligibility.d.ts +34 -0
  17. package/dist/algo/publishEligibility.js +52 -0
  18. package/dist/algo/ucb1.d.ts +53 -0
  19. package/dist/algo/ucb1.js +156 -0
  20. package/dist/assetstore/assetSidecarRecords.d.ts +7 -2
  21. package/dist/assetstore/assetSidecarRecords.js +238 -0
  22. package/dist/assetstore/assetSidecarRecovery.js +2 -2
  23. package/dist/assetstore/assetStoreHealth.d.ts +6 -0
  24. package/dist/assetstore/assetStoreHealth.js +56 -14
  25. package/dist/assetstore/assetStoreStorage.d.ts +1 -1
  26. package/dist/assetstore/assetStoreStorage.js +27 -9
  27. package/dist/assetstore/assetSyncLedger.d.ts +86 -0
  28. package/dist/assetstore/assetSyncLedger.js +683 -4
  29. package/dist/assetstore/index.d.ts +1 -0
  30. package/dist/assetstore/index.js +1 -0
  31. package/dist/assetstore/localAssetStoreSnapshot.d.ts +51 -0
  32. package/dist/assetstore/localAssetStoreSnapshot.js +329 -0
  33. package/dist/assetstore/localJsonl.d.ts +4 -2
  34. package/dist/assetstore/localJsonl.js +89 -9
  35. package/dist/assetstore/provenance.d.ts +80 -4
  36. package/dist/assetstore/provenance.js +313 -5
  37. package/dist/assetstore/provider.d.ts +58 -1
  38. package/dist/assetstore/provider.js +97 -6
  39. package/dist/benchmark/antiGeneBenchmark.d.ts +2 -0
  40. package/dist/benchmark/antiGeneBenchmark.js +4 -3
  41. package/dist/benchmark/antiGeneRollout.d.ts +2 -0
  42. package/dist/benchmark/antiGeneRollout.js +4 -3
  43. package/dist/benchmark/index.d.ts +2 -1
  44. package/dist/benchmark/index.js +2 -1
  45. package/dist/benchmark/selectionFlatAbstention.d.ts +152 -0
  46. package/dist/benchmark/selectionFlatAbstention.js +481 -0
  47. package/dist/bootstrap/envFingerprint.d.ts +9 -0
  48. package/dist/bootstrap/envFingerprint.js +5 -0
  49. package/dist/bootstrap/index.d.ts +2 -1
  50. package/dist/bootstrap/index.js +2 -1
  51. package/dist/bootstrap/v1EnvCompat.d.ts +111 -0
  52. package/dist/bootstrap/v1EnvCompat.js +280 -0
  53. package/dist/events/eventArchive.d.ts +2 -0
  54. package/dist/events/eventArchive.js +13 -3
  55. package/dist/events/eventSchema.d.ts +7 -7
  56. package/dist/events/eventStore.d.ts +2 -0
  57. package/dist/events/eventStore.js +5 -1
  58. package/dist/events/ingest.d.ts +1 -0
  59. package/dist/events/ingest.js +1 -0
  60. package/dist/events/paths.d.ts +3 -1
  61. package/dist/events/paths.js +4 -0
  62. package/dist/events/public.d.ts +2 -2
  63. package/dist/events/public.js +2 -2
  64. package/dist/events/reports.d.ts +2 -0
  65. package/dist/events/reports.js +4 -0
  66. package/dist/exec/autoExec.d.ts +43 -2
  67. package/dist/exec/autoExec.js +76 -9
  68. package/dist/exec/autonomousCycle.d.ts +22 -4
  69. package/dist/exec/autonomousCycle.js +64 -13
  70. package/dist/exec/claudeBridge.d.ts +32 -7
  71. package/dist/exec/claudeBridge.js +281 -29
  72. package/dist/exec/prompt.js +5 -1
  73. package/dist/exec/runnerRegistry.d.ts +68 -26
  74. package/dist/exec/runnerRegistry.js +307 -72
  75. package/dist/exec/selfPr.js +1 -7
  76. package/dist/feedback/envelope.d.ts +61 -0
  77. package/dist/feedback/envelope.js +168 -0
  78. package/dist/feedback/index.d.ts +1 -0
  79. package/dist/feedback/index.js +1 -0
  80. package/dist/hooks/hooks.js +1 -0
  81. package/dist/hub/assetCallLog.d.ts +35 -1
  82. package/dist/hub/assetCallLog.js +124 -1
  83. package/dist/hub/bindings.d.ts +8 -1
  84. package/dist/hub/bindings.js +17 -6
  85. package/dist/hub/capability.d.ts +90 -3
  86. package/dist/hub/fake.d.ts +2 -2
  87. package/dist/hub/fake.js +1 -1
  88. package/dist/hub/questionGenerator.d.ts +5 -1
  89. package/dist/hub/questionGenerator.js +8 -6
  90. package/dist/index.d.ts +3 -1
  91. package/dist/index.js +4 -1
  92. package/dist/mailbox/dispatch.d.ts +1 -1
  93. package/dist/mailbox/dispatch.js +22 -6
  94. package/dist/mailbox/envelope.d.ts +7 -1
  95. package/dist/mailbox/envelope.js +9 -2
  96. package/dist/mailbox/ipcServer.d.ts +10 -2
  97. package/dist/mailbox/ipcServer.js +163 -13
  98. package/dist/mailbox/store.d.ts +89 -3
  99. package/dist/mailbox/store.js +895 -41
  100. package/dist/ops/evolutionGraphProjection.d.ts +20 -0
  101. package/dist/ops/evolutionGraphProjection.js +315 -0
  102. package/dist/ops/index.d.ts +2 -1
  103. package/dist/ops/index.js +2 -1
  104. package/dist/ops/selfUpdate.d.ts +8 -0
  105. package/dist/ops/selfUpdate.js +24 -8
  106. package/dist/personality/schema.d.ts +16 -16
  107. package/dist/schema/evolutionGraph.d.ts +784 -0
  108. package/dist/schema/evolutionGraph.js +187 -0
  109. package/dist/schema/index.d.ts +1 -0
  110. package/dist/schema/index.js +1 -0
  111. package/dist/schema/signal.d.ts +3 -3
  112. package/dist/schema/signal.js +1 -1
  113. package/dist/signals/curriculum.d.ts +55 -0
  114. package/dist/signals/curriculum.js +202 -0
  115. package/dist/signals/cycleHistoryFromEvents.js +17 -8
  116. package/dist/signals/expand.d.ts +15 -1
  117. package/dist/signals/expand.js +169 -1
  118. package/dist/signals/extractor.d.ts +2 -2
  119. package/dist/signals/extractor.js +31 -6
  120. package/dist/signals/index.d.ts +3 -1
  121. package/dist/signals/index.js +3 -1
  122. package/dist/signals/metaSignals.d.ts +4 -0
  123. package/dist/signals/metaSignals.js +42 -0
  124. package/dist/signals/signalGate.js +1 -1
  125. package/dist/signals/taskDomain.d.ts +22 -0
  126. package/dist/signals/taskDomain.js +43 -0
  127. package/dist/strategy/constraintAblation.js +115 -369
  128. package/dist/strategy/constraintAblationPredicates.d.ts +31 -0
  129. package/dist/strategy/constraintAblationPredicates.js +339 -0
  130. package/dist/trace/index.d.ts +3 -1
  131. package/dist/trace/index.js +3 -1
  132. package/dist/trace/learningTrace.d.ts +209 -0
  133. package/dist/trace/learningTrace.js +276 -0
  134. package/dist/trace/proxyTurns.d.ts +31 -0
  135. package/dist/trace/proxyTurns.js +137 -0
  136. package/dist/verify/sandboxRunner.d.ts +28 -0
  137. package/dist/verify/sandboxRunner.js +218 -19
  138. package/dist/verify/sandboxedValidation.d.ts +9 -0
  139. package/dist/verify/sandboxedValidation.js +113 -13
  140. package/dist/verify/validation.d.ts +11 -1
  141. package/dist/verify/validation.js +31 -0
  142. package/package.json +5 -2
@@ -0,0 +1,20 @@
1
+ import { type EvolutionGraph } from '../schema/evolutionGraph.js';
2
+ /** The minimal root_event view this projector reads (structurally matches events' ReportEvent). */
3
+ export interface EvolutionGraphSourceEvent {
4
+ type: string;
5
+ seq: number;
6
+ ts: string;
7
+ payload?: Record<string, unknown> | undefined;
8
+ human?: {
9
+ title?: string | undefined;
10
+ } | undefined;
11
+ }
12
+ export interface ProjectEvolutionGraphOptions {
13
+ /** Stable identifier for the produced snapshot. */
14
+ graphId?: string;
15
+ /** Snapshot timestamp; defaults to the newest projected event so the projection stays deterministic. */
16
+ generatedAt?: string;
17
+ /** Bound on scanned events (newest window wins) so a long history cannot make the projection unbounded. */
18
+ maxEvents?: number;
19
+ }
20
+ export declare function projectEvolutionGraph(events: readonly EvolutionGraphSourceEvent[], options?: ProjectEvolutionGraphOptions): EvolutionGraph;
@@ -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) {
@@ -169,6 +169,13 @@ export declare const personalityModel: z.ZodObject<{
169
169
  extensions: Record<string, unknown>;
170
170
  updatedAt: string | null;
171
171
  version: 1;
172
+ stats: Record<string, {
173
+ success: number;
174
+ updatedAt: string | null;
175
+ fail: number;
176
+ n: number;
177
+ avgScore: number;
178
+ }>;
172
179
  current: {
173
180
  type: "PersonalityState";
174
181
  rigor: number;
@@ -177,13 +184,6 @@ export declare const personalityModel: z.ZodObject<{
177
184
  risk_tolerance: number;
178
185
  obedience: number;
179
186
  };
180
- stats: Record<string, {
181
- success: number;
182
- updatedAt: string | null;
183
- fail: number;
184
- n: number;
185
- avgScore: number;
186
- }>;
187
187
  history: {
188
188
  at: string;
189
189
  score: number | null;
@@ -195,6 +195,13 @@ export declare const personalityModel: z.ZodObject<{
195
195
  extensions?: Record<string, unknown> | undefined;
196
196
  updatedAt?: string | null | undefined;
197
197
  version?: 1 | undefined;
198
+ stats?: Record<string, {
199
+ success?: number | undefined;
200
+ updatedAt?: string | null | undefined;
201
+ fail?: number | undefined;
202
+ n?: number | undefined;
203
+ avgScore?: number | undefined;
204
+ }> | undefined;
198
205
  current?: {
199
206
  type?: "PersonalityState" | undefined;
200
207
  rigor?: number | undefined;
@@ -203,13 +210,6 @@ export declare const personalityModel: z.ZodObject<{
203
210
  risk_tolerance?: number | undefined;
204
211
  obedience?: number | undefined;
205
212
  } | undefined;
206
- stats?: Record<string, {
207
- success?: number | undefined;
208
- updatedAt?: string | null | undefined;
209
- fail?: number | undefined;
210
- n?: number | undefined;
211
- avgScore?: number | undefined;
212
- }> | undefined;
213
213
  history?: {
214
214
  at: string;
215
215
  outcome: string;
@@ -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
  }>;