@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.
- package/assets/gep/genes.jsonl +5 -5
- package/dist/algo/bans.d.ts +10 -1
- package/dist/algo/bans.js +56 -6
- package/dist/algo/candidateAssembly.d.ts +25 -2
- package/dist/algo/candidateAssembly.js +143 -20
- package/dist/algo/capabilityCandidates.js +10 -0
- package/dist/algo/cycleEngine.d.ts +40 -5
- package/dist/algo/cycleEngine.js +277 -37
- package/dist/algo/evolutionEvent.d.ts +26 -0
- package/dist/algo/evolutionEvent.js +32 -0
- package/dist/algo/exploration.d.ts +7 -0
- package/dist/algo/exploration.js +16 -3
- package/dist/algo/geneHealth.d.ts +34 -1
- package/dist/algo/geneHealth.js +42 -0
- package/dist/algo/geneIntake.d.ts +46 -1
- package/dist/algo/geneIntake.js +121 -10
- package/dist/algo/geneSelection.d.ts +115 -6
- package/dist/algo/geneSelection.js +459 -32
- package/dist/algo/index.d.ts +4 -1
- package/dist/algo/index.js +4 -1
- package/dist/algo/kautoProjection.d.ts +41 -0
- package/dist/algo/kautoProjection.js +95 -0
- package/dist/algo/kautoValidator.d.ts +68 -0
- package/dist/algo/kautoValidator.js +256 -0
- package/dist/algo/orchestrator.d.ts +14 -1
- package/dist/algo/orchestrator.js +9 -2
- package/dist/algo/solidify.d.ts +11 -2
- package/dist/algo/solidify.js +37 -7
- package/dist/algo/ucb1.d.ts +53 -0
- package/dist/algo/ucb1.js +156 -0
- package/dist/assetrepair/hubRejection.d.ts +12 -0
- package/dist/assetrepair/hubRejection.js +109 -0
- package/dist/assetrepair/index.d.ts +2 -0
- package/dist/assetrepair/index.js +2 -0
- package/dist/assetrepair/repair.d.ts +33 -0
- package/dist/assetrepair/repair.js +155 -0
- package/dist/assetstore/assetSidecarRecords.js +5 -1
- package/dist/assetstore/assetStoreHealth.d.ts +2 -3
- package/dist/assetstore/assetStoreHealth.js +4 -10
- package/dist/assetstore/foreignJsonlSource.d.ts +48 -0
- package/dist/assetstore/foreignJsonlSource.js +150 -0
- package/dist/assetstore/index.d.ts +3 -0
- package/dist/assetstore/index.js +3 -0
- package/dist/assetstore/learningHistory.js +3 -3
- package/dist/assetstore/localAssetStoreSnapshot.d.ts +51 -0
- package/dist/assetstore/localAssetStoreSnapshot.js +329 -0
- package/dist/assetstore/localJsonl.d.ts +8 -0
- package/dist/assetstore/localJsonl.js +128 -3
- package/dist/assetstore/provenance.d.ts +38 -3
- package/dist/assetstore/provenance.js +103 -45
- package/dist/assetstore/provider.d.ts +4 -0
- package/dist/assetstore/reviewFilter.d.ts +19 -1
- package/dist/assetstore/reviewFilter.js +36 -0
- package/dist/assetstore/unionReadStore.d.ts +25 -0
- package/dist/assetstore/unionReadStore.js +119 -0
- package/dist/benchmark/antiGeneBenchmark.d.ts +2 -0
- package/dist/benchmark/antiGeneBenchmark.js +4 -3
- package/dist/benchmark/antiGeneRollout.d.ts +2 -0
- package/dist/benchmark/antiGeneRollout.js +4 -3
- package/dist/benchmark/index.d.ts +2 -1
- package/dist/benchmark/index.js +2 -1
- package/dist/benchmark/selectionFlatAbstention.d.ts +152 -0
- package/dist/benchmark/selectionFlatAbstention.js +481 -0
- package/dist/bootstrap/envFingerprint.d.ts +9 -0
- package/dist/bootstrap/envFingerprint.js +5 -0
- package/dist/bootstrap/index.d.ts +2 -1
- package/dist/bootstrap/index.js +2 -1
- package/dist/bootstrap/lifecycleBootstrap.d.ts +111 -0
- package/dist/bootstrap/lifecycleBootstrap.js +433 -0
- package/dist/bootstrap/v1EnvCompat.d.ts +3 -0
- package/dist/bootstrap/v1EnvCompat.js +48 -1
- package/dist/events/eventArchive.d.ts +2 -0
- package/dist/events/eventArchive.js +13 -3
- package/dist/events/eventSchema.d.ts +7 -7
- package/dist/events/eventStore.d.ts +2 -0
- package/dist/events/eventStore.js +5 -1
- package/dist/events/ingest.d.ts +2 -1
- package/dist/events/ingest.js +6 -0
- package/dist/exec/autoExec.d.ts +30 -3
- package/dist/exec/autoExec.js +294 -29
- package/dist/exec/autonomousCycle.d.ts +7 -0
- package/dist/exec/autonomousCycle.js +2 -0
- package/dist/exec/claudeBridge.d.ts +28 -6
- package/dist/exec/claudeBridge.js +411 -258
- package/dist/exec/executionBinding.d.ts +414 -0
- package/dist/exec/executionBinding.js +588 -0
- package/dist/exec/index.d.ts +1 -0
- package/dist/exec/index.js +1 -0
- package/dist/exec/proofOfWork.d.ts +1 -1
- package/dist/exec/proofOfWork.js +2 -2
- package/dist/exec/runnerRegistry.d.ts +5 -0
- package/dist/exec/runnerRegistry.js +54 -14
- package/dist/hub/capability.d.ts +40 -1
- package/dist/hub/conversationDistiller.d.ts +19 -0
- package/dist/hub/conversationDistiller.js +115 -37
- package/dist/hub/fake.d.ts +1 -0
- package/dist/hub/fake.js +1 -0
- package/dist/hub/index.d.ts +1 -0
- package/dist/hub/index.js +1 -0
- package/dist/hub/recipeCompose.d.ts +27 -0
- package/dist/hub/recipeCompose.js +90 -0
- package/dist/hub/sanitize.js +119 -5
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/mailbox/ipcServer.d.ts +2 -0
- package/dist/mailbox/ipcServer.js +20 -0
- package/dist/mailbox/store.d.ts +52 -2
- package/dist/mailbox/store.js +546 -81
- package/dist/modelCompatibility.d.ts +164 -0
- package/dist/modelCompatibility.js +309 -0
- package/dist/observers/valueDigestObserver.d.ts +9 -0
- package/dist/observers/valueDigestObserver.js +35 -2
- package/dist/ops/cleanup.js +1 -1
- package/dist/ops/evolutionGraphProjection.d.ts +20 -0
- package/dist/ops/evolutionGraphProjection.js +315 -0
- package/dist/ops/index.d.ts +2 -1
- package/dist/ops/index.js +2 -1
- package/dist/ops/selfUpdate.d.ts +8 -0
- package/dist/ops/selfUpdate.js +24 -8
- package/dist/ops/valueOutreach.d.ts +3 -1
- package/dist/ops/valueOutreach.js +5 -1
- package/dist/personality/schema.d.ts +18 -18
- package/dist/schema/evolutionGraph.d.ts +784 -0
- package/dist/schema/evolutionGraph.js +187 -0
- package/dist/schema/index.d.ts +1 -0
- package/dist/schema/index.js +1 -0
- package/dist/schema/proofOfWork.d.ts +125 -6
- package/dist/schema/proofOfWork.js +102 -4
- package/dist/shadow/shadowHub.js +1 -0
- package/dist/signals/expand.d.ts +15 -1
- package/dist/signals/expand.js +148 -0
- package/dist/signals/index.d.ts +3 -1
- package/dist/signals/index.js +3 -1
- package/dist/signals/scopeVocabulary.d.ts +75 -0
- package/dist/signals/scopeVocabulary.js +91 -0
- package/dist/signals/taskDomain.d.ts +22 -0
- package/dist/signals/taskDomain.js +43 -0
- package/dist/trace/learningTrace.d.ts +7 -0
- package/dist/trace/learningTrace.js +22 -0
- package/dist/trace/trajectory.d.ts +8 -0
- package/dist/trace/trajectory.js +14 -2
- package/dist/util/fileLock.d.ts +92 -5
- package/dist/util/fileLock.js +809 -70
- package/dist/util/index.d.ts +2 -1
- package/dist/util/index.js +1 -1
- package/dist/verify/index.d.ts +2 -1
- package/dist/verify/index.js +1 -1
- package/dist/verify/sandboxRunner.d.ts +2 -0
- package/dist/verify/sandboxRunner.js +154 -10
- package/dist/verify/sandboxedValidation.d.ts +7 -2
- package/dist/verify/sandboxedValidation.js +102 -24
- package/dist/verify/validation.d.ts +24 -3
- package/dist/verify/validation.js +141 -24
- package/dist/wire/geneHints.d.ts +88 -16
- package/dist/wire/geneHints.js +124 -15
- package/dist/wire/index.d.ts +8 -3
- package/dist/wire/index.js +2 -2
- package/dist/wire/schemaGate.d.ts +21 -0
- package/dist/wire/schemaGate.js +119 -10
- 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
|
+
}
|
package/dist/ops/index.d.ts
CHANGED
package/dist/ops/index.js
CHANGED
package/dist/ops/selfUpdate.d.ts
CHANGED
|
@@ -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:
|
package/dist/ops/selfUpdate.js
CHANGED
|
@@ -224,19 +224,35 @@ export function canonicalManifestBytes(manifest) {
|
|
|
224
224
|
};
|
|
225
225
|
return new TextEncoder().encode(JSON.stringify(canonical));
|
|
226
226
|
}
|
|
227
|
-
/**
|
|
228
|
-
|
|
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
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
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
|
|
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
|
}>;
|