@evomap/evolver-core 2.0.0-beta.2 → 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 +171 -26
- package/dist/algo/capabilityCandidates.js +10 -0
- package/dist/algo/conversationSniffer.js +25 -8
- package/dist/algo/cycleEngine.d.ts +63 -5
- package/dist/algo/cycleEngine.js +320 -42
- package/dist/algo/cycleFailureClassifier.d.ts +1 -1
- 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 +36 -3
- package/dist/algo/geneHealth.js +47 -4
- package/dist/algo/geneIntake.d.ts +46 -1
- package/dist/algo/geneIntake.js +121 -10
- package/dist/algo/geneSelection.d.ts +126 -6
- package/dist/algo/geneSelection.js +479 -36
- package/dist/algo/index.d.ts +6 -1
- package/dist/algo/index.js +6 -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/memoryGraph.d.ts +62 -0
- package/dist/algo/memoryGraph.js +86 -0
- package/dist/algo/orchestrator.d.ts +17 -1
- package/dist/algo/orchestrator.js +30 -4
- package/dist/algo/publishEligibility.d.ts +34 -0
- package/dist/algo/publishEligibility.js +52 -0
- 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.d.ts +28 -0
- package/dist/assetstore/assetSidecarRecords.js +384 -0
- package/dist/assetstore/assetSidecarRecovery.d.ts +48 -0
- package/dist/assetstore/assetSidecarRecovery.js +288 -0
- package/dist/assetstore/assetStoreHealth.d.ts +81 -0
- package/dist/assetstore/assetStoreHealth.js +319 -0
- package/dist/assetstore/assetStoreLayout.d.ts +2 -0
- package/dist/assetstore/assetStoreLayout.js +6 -0
- package/dist/assetstore/assetStoreStorage.d.ts +42 -0
- package/dist/assetstore/assetStoreStorage.js +336 -0
- package/dist/assetstore/assetSyncLedger.d.ts +91 -1
- package/dist/assetstore/assetSyncLedger.js +718 -59
- package/dist/assetstore/foreignJsonlSource.d.ts +48 -0
- package/dist/assetstore/foreignJsonlSource.js +150 -0
- package/dist/assetstore/index.d.ts +5 -0
- package/dist/assetstore/index.js +5 -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 +12 -1
- package/dist/assetstore/localJsonl.js +251 -42
- package/dist/assetstore/provenance.d.ts +93 -4
- package/dist/assetstore/provenance.js +368 -84
- package/dist/assetstore/provider.d.ts +63 -0
- package/dist/assetstore/provider.js +97 -6
- package/dist/assetstore/reviewFilter.d.ts +19 -1
- package/dist/assetstore/reviewFilter.js +39 -1
- package/dist/assetstore/reviewLedger.d.ts +8 -2
- package/dist/assetstore/reviewLedger.js +71 -45
- 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 +3 -1
- package/dist/benchmark/index.js +3 -1
- package/dist/benchmark/selectionFlatAbstention.d.ts +152 -0
- package/dist/benchmark/selectionFlatAbstention.js +481 -0
- package/dist/benchmark/triggerShift.d.ts +62 -0
- package/dist/benchmark/triggerShift.js +106 -0
- package/dist/bootstrap/envFingerprint.d.ts +9 -0
- package/dist/bootstrap/envFingerprint.js +5 -0
- package/dist/bootstrap/index.d.ts +3 -1
- package/dist/bootstrap/index.js +3 -1
- package/dist/bootstrap/lifecycleBootstrap.d.ts +111 -0
- package/dist/bootstrap/lifecycleBootstrap.js +433 -0
- package/dist/bootstrap/v1EnvCompat.d.ts +113 -0
- package/dist/bootstrap/v1EnvCompat.js +303 -0
- 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 +15 -0
- package/dist/events/paths.d.ts +12 -10
- package/dist/events/paths.js +24 -20
- package/dist/events/public.d.ts +2 -2
- package/dist/events/public.js +2 -2
- package/dist/events/reports.d.ts +2 -0
- package/dist/events/reports.js +4 -0
- package/dist/exec/autoExec.d.ts +68 -4
- package/dist/exec/autoExec.js +392 -33
- package/dist/exec/autonomousCycle.d.ts +31 -4
- package/dist/exec/autonomousCycle.js +71 -13
- package/dist/exec/claudeBridge.d.ts +80 -15
- package/dist/exec/claudeBridge.js +845 -76
- 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/openPrRegistry.d.ts +8 -2
- package/dist/exec/openPrRegistry.js +32 -22
- package/dist/exec/prompt.js +14 -1
- package/dist/exec/proofOfWork.d.ts +1 -1
- package/dist/exec/proofOfWork.js +2 -2
- package/dist/exec/runnerRegistry.d.ts +153 -36
- package/dist/exec/runnerRegistry.js +848 -65
- package/dist/exec/selfPr.js +1 -7
- package/dist/feedback/envelope.d.ts +61 -0
- package/dist/feedback/envelope.js +168 -0
- package/dist/feedback/index.d.ts +1 -0
- package/dist/feedback/index.js +1 -0
- package/dist/hooks/hooks.js +1 -0
- package/dist/hub/assetCallLog.d.ts +35 -1
- package/dist/hub/assetCallLog.js +124 -1
- package/dist/hub/bindings.d.ts +8 -1
- package/dist/hub/bindings.js +29 -8
- package/dist/hub/capability.d.ts +130 -4
- package/dist/hub/conversationDistiller.d.ts +19 -0
- package/dist/hub/conversationDistiller.js +115 -37
- package/dist/hub/fake.d.ts +3 -2
- package/dist/hub/fake.js +2 -1
- package/dist/hub/index.d.ts +1 -0
- package/dist/hub/index.js +1 -0
- package/dist/hub/questionGenerator.d.ts +5 -1
- package/dist/hub/questionGenerator.js +8 -6
- package/dist/hub/recipeCompose.d.ts +27 -0
- package/dist/hub/recipeCompose.js +90 -0
- package/dist/hub/sanitize.js +122 -7
- package/dist/index.d.ts +6 -1
- package/dist/index.js +7 -1
- package/dist/issueReporter/index.d.ts +156 -0
- package/dist/issueReporter/index.js +1688 -0
- package/dist/mailbox/dispatch.d.ts +1 -1
- package/dist/mailbox/dispatch.js +22 -6
- package/dist/mailbox/envelope.d.ts +7 -1
- package/dist/mailbox/envelope.js +9 -2
- package/dist/mailbox/ipcServer.d.ts +12 -2
- package/dist/mailbox/ipcServer.js +183 -13
- package/dist/mailbox/store.d.ts +89 -3
- package/dist/mailbox/store.js +895 -41
- 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/savingsCore.js +1 -2
- package/dist/ops/selfUpdate.d.ts +18 -1
- package/dist/ops/selfUpdate.js +88 -23
- package/dist/ops/valueOutreach.d.ts +3 -1
- package/dist/ops/valueOutreach.js +5 -1
- package/dist/personality/schema.d.ts +24 -24
- 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/schema/signal.d.ts +3 -3
- package/dist/schema/signal.js +1 -1
- package/dist/shadow/shadowHub.js +1 -0
- package/dist/signals/curriculum.d.ts +55 -0
- package/dist/signals/curriculum.js +202 -0
- package/dist/signals/cycleHistoryFromEvents.js +17 -8
- package/dist/signals/expand.d.ts +15 -1
- package/dist/signals/expand.js +169 -1
- package/dist/signals/extractor.d.ts +2 -2
- package/dist/signals/extractor.js +31 -6
- package/dist/signals/index.d.ts +4 -1
- package/dist/signals/index.js +4 -1
- package/dist/signals/metaSignals.d.ts +4 -0
- package/dist/signals/metaSignals.js +42 -0
- package/dist/signals/scopeVocabulary.d.ts +75 -0
- package/dist/signals/scopeVocabulary.js +91 -0
- package/dist/signals/signalGate.js +1 -1
- package/dist/signals/taskDomain.d.ts +22 -0
- package/dist/signals/taskDomain.js +43 -0
- package/dist/strategy/constraintAblation.d.ts +64 -0
- package/dist/strategy/constraintAblation.js +2820 -0
- package/dist/strategy/constraintAblationPredicates.d.ts +31 -0
- package/dist/strategy/constraintAblationPredicates.js +339 -0
- package/dist/strategy/index.d.ts +2 -1
- package/dist/strategy/index.js +2 -1
- package/dist/trace/index.d.ts +3 -1
- package/dist/trace/index.js +3 -1
- package/dist/trace/learningTrace.d.ts +216 -0
- package/dist/trace/learningTrace.js +298 -0
- package/dist/trace/proxyTurns.d.ts +31 -0
- package/dist/trace/proxyTurns.js +137 -0
- package/dist/trace/trajectory.d.ts +8 -0
- package/dist/trace/trajectory.js +14 -2
- package/dist/util/fetchPort.d.ts +1 -0
- package/dist/util/fetchPort.js +11 -0
- package/dist/util/fileLock.d.ts +113 -7
- package/dist/util/fileLock.js +1035 -80
- package/dist/util/index.d.ts +3 -1
- package/dist/util/index.js +2 -1
- package/dist/verify/index.d.ts +2 -1
- package/dist/verify/index.js +1 -1
- package/dist/verify/sandboxRunner.d.ts +30 -0
- package/dist/verify/sandboxRunner.js +370 -27
- package/dist/verify/sandboxedValidation.d.ts +16 -2
- package/dist/verify/sandboxedValidation.js +200 -22
- package/dist/verify/validation.d.ts +35 -4
- package/dist/verify/validation.js +164 -16
- 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/dist/workflow/dsl.d.ts +24 -3
- package/dist/workflow/dsl.js +4 -0
- package/dist/workflow/engine.d.ts +5 -1
- package/dist/workflow/engine.js +3 -0
- package/dist/workflow/index.d.ts +3 -1
- package/dist/workflow/index.js +3 -1
- package/dist/workflow/runtime.d.ts +110 -0
- package/dist/workflow/runtime.js +1298 -0
- package/dist/workflow/stateStore.d.ts +172 -0
- package/dist/workflow/stateStore.js +1044 -0
- package/package.json +12 -4
package/dist/algo/cycleEngine.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LineTooLargeError } from '../events/eventStore.js';
|
|
2
|
+
import { TERMINAL, canTransition, stageForEventType } from '../cycle/stateMachine.js';
|
|
2
3
|
import {} from './geneSelection.js';
|
|
3
4
|
import { detectPlateau } from './exploration.js';
|
|
4
5
|
import { epigeneticPenaltyForIds } from './epigenetics.js';
|
|
@@ -11,10 +12,126 @@ import { applySelectForRun, applyStatsUpdate, applyForcePivot } from '../persona
|
|
|
11
12
|
import { solidify } from './solidify.js';
|
|
12
13
|
import { buildEvolutionEvent } from './evolutionEvent.js';
|
|
13
14
|
import { cycleRecordsFromEvents } from '../signals/cycleHistoryFromEvents.js';
|
|
15
|
+
import { withoutTaskDomainSignals } from '../signals/taskDomain.js';
|
|
14
16
|
import { computeMetaSignals, deriveCycleHistory } from '../signals/metaSignals.js';
|
|
17
|
+
import { capabilityGapsFromSignals, curriculumOutcomesFromEvents, generateCurriculumSignals, normalizeCapabilityGaps, } from '../signals/curriculum.js';
|
|
15
18
|
import { resolveStrategy } from './strategyPresets.js';
|
|
16
19
|
import { classifyCycleFailure, } from './cycleFailureClassifier.js';
|
|
17
20
|
import { isDistilledGeneId } from './geneIntake.js';
|
|
21
|
+
import { deriveUcb1History } from './ucb1.js';
|
|
22
|
+
function persistedTerminalAfterLatestSelection(ingestor, cycleId, attemptStartedSeq) {
|
|
23
|
+
const events = ingestor.readAll();
|
|
24
|
+
let selectedSeq = -1;
|
|
25
|
+
for (let index = events.length - 1; index >= 0; index -= 1) {
|
|
26
|
+
const event = events[index];
|
|
27
|
+
if (event.seq <= attemptStartedSeq)
|
|
28
|
+
break;
|
|
29
|
+
if (event.type === 'decision.gene_selected' && event.payload['cycleId'] === cycleId) {
|
|
30
|
+
selectedSeq = event.seq;
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (selectedSeq < 0)
|
|
35
|
+
return null;
|
|
36
|
+
for (let index = events.length - 1; index >= 0; index -= 1) {
|
|
37
|
+
const event = events[index];
|
|
38
|
+
if (event.seq <= selectedSeq)
|
|
39
|
+
break;
|
|
40
|
+
if (event.payload['cycleId'] !== cycleId)
|
|
41
|
+
continue;
|
|
42
|
+
const terminal = stageForEventType(event.type);
|
|
43
|
+
if (terminal && TERMINAL.has(terminal))
|
|
44
|
+
return terminal;
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
function selectionPolicyEventProjection(trace) {
|
|
49
|
+
return {
|
|
50
|
+
requested: trace.requested,
|
|
51
|
+
effective: trace.effective,
|
|
52
|
+
version: trace.selectionPolicyVersion,
|
|
53
|
+
rewardVersion: trace.rewardPolicyVersion,
|
|
54
|
+
...(trace.arm ? {
|
|
55
|
+
arm: {
|
|
56
|
+
id: trace.arm.armId,
|
|
57
|
+
pulls: trace.arm.pulls,
|
|
58
|
+
completed: trace.arm.completedPulls,
|
|
59
|
+
total: trace.arm.totalPulls,
|
|
60
|
+
mean: trace.arm.meanReward,
|
|
61
|
+
index: trace.arm.index,
|
|
62
|
+
},
|
|
63
|
+
} : {}),
|
|
64
|
+
...(trace.shadowDisagrees !== undefined ? { disagrees: trace.shadowDisagrees } : {}),
|
|
65
|
+
...(trace.fallbackReason ? { fallback: trace.fallbackReason } : {}),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function minimalSelectionPolicyEventProjection(trace) {
|
|
69
|
+
return {
|
|
70
|
+
requested: trace.requested,
|
|
71
|
+
effective: trace.effective,
|
|
72
|
+
version: trace.selectionPolicyVersion,
|
|
73
|
+
rewardVersion: trace.rewardPolicyVersion,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function selectionGuardEventProjection(trace) {
|
|
77
|
+
return {
|
|
78
|
+
mode: trace.mode,
|
|
79
|
+
version: trace.version,
|
|
80
|
+
status: trace.status,
|
|
81
|
+
...(trace.reason ? { reason: trace.reason } : {}),
|
|
82
|
+
...(trace.maxMatch !== undefined ? { maxMatch: trace.maxMatch } : {}),
|
|
83
|
+
...(trace.matchSpread !== undefined ? { spread: trace.matchSpread } : {}),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function minimalSelectionGuardEventProjection(trace) {
|
|
87
|
+
return {
|
|
88
|
+
mode: trace.mode,
|
|
89
|
+
version: trace.version,
|
|
90
|
+
status: trace.status,
|
|
91
|
+
...(trace.reason ? { reason: trace.reason } : {}),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function selectionCandidateEventProjection(candidate) {
|
|
95
|
+
// matchScore and scoring diagnostics stay off decision.gene_selected payloads so
|
|
96
|
+
// UCB1/plateau telemetry retains the 4096B root-event line budget.
|
|
97
|
+
const { matchScore: _matchScore, scoreBase: _scoreBase, kautoContribution: _kautoContribution, ...persisted } = candidate;
|
|
98
|
+
return persisted;
|
|
99
|
+
}
|
|
100
|
+
async function ingestGeneSelectedWithTraceBudget(ingestor, event, policyTrace, guardTrace) {
|
|
101
|
+
const guard = guardTrace ? selectionGuardEventProjection(guardTrace) : undefined;
|
|
102
|
+
const minimalGuard = guardTrace ? minimalSelectionGuardEventProjection(guardTrace) : undefined;
|
|
103
|
+
const projections = [];
|
|
104
|
+
if (policyTrace) {
|
|
105
|
+
projections.push({ selectionPolicy: selectionPolicyEventProjection(policyTrace), ...(guard ? { selectionGuard: guard } : {}) });
|
|
106
|
+
projections.push({ selectionPolicy: minimalSelectionPolicyEventProjection(policyTrace), ...(guard ? { selectionGuard: guard } : {}) });
|
|
107
|
+
if (minimalGuard) {
|
|
108
|
+
projections.push({ selectionPolicy: minimalSelectionPolicyEventProjection(policyTrace), selectionGuard: minimalGuard });
|
|
109
|
+
projections.push({ selectionGuard: minimalGuard });
|
|
110
|
+
}
|
|
111
|
+
projections.push({ selectionPolicy: minimalSelectionPolicyEventProjection(policyTrace) });
|
|
112
|
+
}
|
|
113
|
+
else if (guard) {
|
|
114
|
+
projections.push({ selectionGuard: guard });
|
|
115
|
+
if (minimalGuard)
|
|
116
|
+
projections.push({ selectionGuard: minimalGuard });
|
|
117
|
+
}
|
|
118
|
+
projections.push({});
|
|
119
|
+
for (let index = 0; index < projections.length; index += 1) {
|
|
120
|
+
const projection = projections[index];
|
|
121
|
+
try {
|
|
122
|
+
await ingestor.ingest({
|
|
123
|
+
type: event.type,
|
|
124
|
+
human: event.human,
|
|
125
|
+
payload: { ...event.payload, ...projection },
|
|
126
|
+
});
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
if (!(error instanceof LineTooLargeError) || index === projections.length - 1)
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
18
135
|
/** Read the trailing run of cycle outcomes (newest last) from the event log, for plateau detection. */
|
|
19
136
|
function recentCycleOutcomes(ingestor, window) {
|
|
20
137
|
let events;
|
|
@@ -106,7 +223,7 @@ function categoryForStrategy(category, strategy) {
|
|
|
106
223
|
* Reading from the same append-only log makes this fully replayable. ad-hoc (innovate) cycles have no gene to
|
|
107
224
|
* credit and are skipped.
|
|
108
225
|
*/
|
|
109
|
-
function recentConfidenceObservations(ingestor, window) {
|
|
226
|
+
function recentConfidenceObservations(ingestor, window, opts = {}) {
|
|
110
227
|
let events;
|
|
111
228
|
try {
|
|
112
229
|
events = ingestor.tail(window);
|
|
@@ -146,8 +263,9 @@ function recentConfidenceObservations(ingestor, window) {
|
|
|
146
263
|
// Older events predate the producedValue tag; when it is absent we treat the cycle as a real success, so we
|
|
147
264
|
// never retroactively reclassify history into a surprise ban.
|
|
148
265
|
const status = e.type === 'cycle.failed' ? 'failed' : p?.producedValue === false ? 'inert' : 'success';
|
|
266
|
+
const fingerprintSignals = opts.ignoreTaskDomain ? withoutTaskDomainSignals(signals) : signals;
|
|
149
267
|
out.push({
|
|
150
|
-
signalFingerprint: signalFingerprint(
|
|
268
|
+
signalFingerprint: signalFingerprint(fingerprintSignals),
|
|
151
269
|
geneId: gene,
|
|
152
270
|
status,
|
|
153
271
|
at: Number.isFinite(at) ? at : 0,
|
|
@@ -164,14 +282,44 @@ export class CycleEngine {
|
|
|
164
282
|
constructor(deps) {
|
|
165
283
|
this.deps = deps;
|
|
166
284
|
}
|
|
285
|
+
/**
|
|
286
|
+
* Add V1-compatible curriculum targets from V2's replayable event history. Public so the orchestrator can run
|
|
287
|
+
* it before candidate assembly; runCycle calls it again for direct callers. Set merging makes that idempotent.
|
|
288
|
+
*/
|
|
289
|
+
prepareCurriculumSignals(signals) {
|
|
290
|
+
let externalCapabilityGaps = [];
|
|
291
|
+
try {
|
|
292
|
+
externalCapabilityGaps = normalizeCapabilityGaps(this.deps.capabilityGaps?.() ?? []);
|
|
293
|
+
}
|
|
294
|
+
catch {
|
|
295
|
+
// An optional lifecycle-state reader must never suppress local curriculum generation.
|
|
296
|
+
}
|
|
297
|
+
try {
|
|
298
|
+
const localCapabilityGaps = capabilityGapsFromSignals(signals);
|
|
299
|
+
const curriculumSignals = generateCurriculumSignals({
|
|
300
|
+
outcomes: curriculumOutcomesFromEvents(this.deps.ingestor.readAll()),
|
|
301
|
+
// Preserve existing explicit local-signal precedence; Hub gaps fill the otherwise-missing V1 source.
|
|
302
|
+
capabilityGaps: normalizeCapabilityGaps([...localCapabilityGaps, ...externalCapabilityGaps]),
|
|
303
|
+
});
|
|
304
|
+
return { signals: mergeSignals(signals, curriculumSignals), curriculumSignals };
|
|
305
|
+
}
|
|
306
|
+
catch {
|
|
307
|
+
return { signals: [...signals], curriculumSignals: [] };
|
|
308
|
+
}
|
|
309
|
+
}
|
|
167
310
|
async runCycle(input) {
|
|
168
311
|
const { ingestor, store } = this.deps;
|
|
169
312
|
const now = this.deps.now();
|
|
170
313
|
const envKey = envFingerprintKey((this.deps.envFingerprint ?? captureEnvFingerprint)());
|
|
171
314
|
const reasons = [];
|
|
172
|
-
const baseSignals = input.signals;
|
|
315
|
+
const baseSignals = [...input.signals];
|
|
316
|
+
const preparedSignals = input.curriculumSignals === undefined
|
|
317
|
+
? this.prepareCurriculumSignals(input.signals)
|
|
318
|
+
: { signals: mergeSignals(input.signals, input.curriculumSignals), curriculumSignals: [...input.curriculumSignals] };
|
|
319
|
+
const selectionSignals = preparedSignals.signals;
|
|
320
|
+
const curriculumSignals = preparedSignals.curriculumSignals;
|
|
173
321
|
const metaSignals = historyMetaSignals(ingestor, 100);
|
|
174
|
-
const cycleSignals = mergeSignals(
|
|
322
|
+
const cycleSignals = mergeSignals(selectionSignals, metaSignals);
|
|
175
323
|
// PORT v1 #279 issue-reporter: classify cycle.failed payloads when the caller supplies host context. The
|
|
176
324
|
// post-solidify failed path adds V2-local context (current gene + blast radius) so hard-filtered local no-op
|
|
177
325
|
// genes are reachable without re-emitting the old ban_gene soft signal.
|
|
@@ -200,6 +348,22 @@ export class CycleEngine {
|
|
|
200
348
|
});
|
|
201
349
|
return r.reason ? { failure_class: r.failureClass, failure_class_reason: r.reason } : { failure_class: r.failureClass };
|
|
202
350
|
};
|
|
351
|
+
const executionMetadata = (exec) => ({
|
|
352
|
+
...(exec.failureKind !== undefined ? { failureKind: exec.failureKind } : {}),
|
|
353
|
+
...(exec.exitCode !== undefined ? { exitCode: exec.exitCode } : {}),
|
|
354
|
+
...(exec.bindingCorrelation ? { bindingDigest: exec.bindingCorrelation.bindingDigest, runId: exec.bindingCorrelation.runId } : {}),
|
|
355
|
+
...(exec.executionTerminal ? { terminalDisposition: exec.executionTerminal.disposition } : {}),
|
|
356
|
+
...(exec.hubLifecycle ? { hubLifecycle: exec.hubLifecycle } : {}),
|
|
357
|
+
...(exec.provenance ? {
|
|
358
|
+
provenance: {
|
|
359
|
+
geneIds: exec.provenance.gene_ids,
|
|
360
|
+
capsuleIds: exec.provenance.capsule_ids,
|
|
361
|
+
resultAssetRefs: exec.provenance.result_asset_refs,
|
|
362
|
+
proofRefs: exec.provenance.proof_refs,
|
|
363
|
+
terminalDisposition: exec.provenance.terminal_disposition,
|
|
364
|
+
},
|
|
365
|
+
} : {}),
|
|
366
|
+
});
|
|
203
367
|
const strategy = resolveStrategy({ name: input.strategyName, signals: cycleSignals, cycleCount: historyCycleCount(ingestor, 1000, input.cycleId) });
|
|
204
368
|
const cycleCategory = categoryForStrategy(input.category, strategy);
|
|
205
369
|
let stage = 'none';
|
|
@@ -208,7 +372,7 @@ export class CycleEngine {
|
|
|
208
372
|
throw new Error(`非法 cycle 迁移 ${stage}→${to}`);
|
|
209
373
|
stage = to;
|
|
210
374
|
};
|
|
211
|
-
await ingestor.ingest({ type: 'cycle.started', human: { title: `cycle ${input.cycleId} 启动` }, payload: { cycleId: input.cycleId, problemId: input.problem.id } });
|
|
375
|
+
const cycleStarted = await ingestor.ingest({ type: 'cycle.started', human: { title: `cycle ${input.cycleId} 启动` }, payload: { cycleId: input.cycleId, problemId: input.problem.id } });
|
|
212
376
|
advance('started');
|
|
213
377
|
await ingestor.ingest({
|
|
214
378
|
type: 'cycle.signals_collected',
|
|
@@ -217,6 +381,7 @@ export class CycleEngine {
|
|
|
217
381
|
cycleId: input.cycleId,
|
|
218
382
|
signals: cycleSignals,
|
|
219
383
|
baseSignals,
|
|
384
|
+
...(curriculumSignals.length > 0 ? { curriculumSignals } : {}),
|
|
220
385
|
...(metaSignals.length > 0 ? { metaSignals, strategy: strategy.name } : {}),
|
|
221
386
|
},
|
|
222
387
|
});
|
|
@@ -226,7 +391,7 @@ export class CycleEngine {
|
|
|
226
391
|
if (!trig.trigger) {
|
|
227
392
|
await ingestor.ingest({ type: 'cycle.aborted', human: { title: `cycle ${input.cycleId} 抑制` }, payload: { cycleId: input.cycleId, reasons: trig.reasons } });
|
|
228
393
|
advance('aborted');
|
|
229
|
-
return { cycleId: input.cycleId, triggered: false, finalStage: stage, reasons: trig.reasons };
|
|
394
|
+
return { cycleId: input.cycleId, triggered: false, finalStage: stage, producedValue: false, reasons: trig.reasons };
|
|
230
395
|
}
|
|
231
396
|
// 选 gene(可解释决策). Exploration: when recent cycles plateau, enable drift to escape local optima.
|
|
232
397
|
const recentOutcomes = recentCycleOutcomes(ingestor, 100);
|
|
@@ -246,7 +411,7 @@ export class CycleEngine {
|
|
|
246
411
|
// recentEvents 由事件日志的近期 outcome 派生, 让"失败连击触发变异"在环内真正生效.
|
|
247
412
|
const sel = await applySelectForRun(personalityDeps, {
|
|
248
413
|
driftEnabled: plateau.active,
|
|
249
|
-
signals:
|
|
414
|
+
signals: selectionSignals,
|
|
250
415
|
recentEvents: recentOutcomes.map((status) => ({ outcome: { status } })),
|
|
251
416
|
});
|
|
252
417
|
personalityForRun = sel.state;
|
|
@@ -259,8 +424,24 @@ export class CycleEngine {
|
|
|
259
424
|
return;
|
|
260
425
|
await applyStatsUpdate({ store: this.deps.personality, ingestor, cycleId: input.cycleId }, { personality: personalityForRun, outcome, score });
|
|
261
426
|
};
|
|
427
|
+
let ucb1History;
|
|
428
|
+
if (plateau.active && input.selectionPolicy && input.selectionPolicy !== 'engine-health') {
|
|
429
|
+
try {
|
|
430
|
+
ucb1History = deriveUcb1History(ingestor.readAllStrict());
|
|
431
|
+
}
|
|
432
|
+
catch {
|
|
433
|
+
// Active UCB1 fails safe to legacy drift; shadow records missing_history in its compact policy trace.
|
|
434
|
+
ucb1History = undefined;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
262
437
|
const exploration = plateau.active
|
|
263
|
-
? {
|
|
438
|
+
? {
|
|
439
|
+
plateau,
|
|
440
|
+
driftEnabled: true,
|
|
441
|
+
totalAttempts: input.candidates.reduce((s, c) => s + (c.view?.total ?? 0), 0),
|
|
442
|
+
...(input.selectionPolicy ? { policy: input.selectionPolicy } : {}),
|
|
443
|
+
...(ucb1History ? { ucb1History } : {}),
|
|
444
|
+
}
|
|
264
445
|
: undefined;
|
|
265
446
|
// Epigenetic: penalize candidates that fail in THIS environment class (derived from per-env outcome history).
|
|
266
447
|
const geneOutcomes = recentGeneOutcomes(ingestor, 200);
|
|
@@ -268,7 +449,7 @@ export class CycleEngine {
|
|
|
268
449
|
// signal fingerprint. Derived from the same event log, applied as a soft fourth factor in selection.
|
|
269
450
|
const confidenceObs = recentConfidenceObservations(ingestor, 200);
|
|
270
451
|
const confidenceEdges = deriveConfidenceEdges(confidenceObs);
|
|
271
|
-
const
|
|
452
|
+
const currentConfidenceFingerprint = signalFingerprint(baseSignals);
|
|
272
453
|
// #195: drop genes stuck producing only inert (zero-work) cycles on THIS signal. A sole-matching do-nothing
|
|
273
454
|
// gene is otherwise re-selected every cycle (drift can't diversify a single candidate) and the failure-streak
|
|
274
455
|
// ban never fires because nothing "fails" — so it dominates --loop forever while producing no artifacts.
|
|
@@ -278,46 +459,85 @@ export class CycleEngine {
|
|
|
278
459
|
// cycles evict its inert run (or the earlier real success that exempts it) and the ban would flap. Recomputing
|
|
279
460
|
// it over INERT_BAN_OBSERVATION_WINDOW events (mirroring v1's memory-graph read horizon) keeps the trailing run
|
|
280
461
|
// and the successCount exemption alive across intervening cycles. tail() reads the full log either way (no I/O cost).
|
|
281
|
-
const inertBanObs = recentConfidenceObservations(ingestor, INERT_BAN_OBSERVATION_WINDOW);
|
|
282
|
-
const
|
|
462
|
+
const inertBanObs = recentConfidenceObservations(ingestor, INERT_BAN_OBSERVATION_WINDOW, { ignoreTaskDomain: true });
|
|
463
|
+
const inertBanFingerprint = signalFingerprint(withoutTaskDomainSignals(baseSignals));
|
|
464
|
+
const inertBanned = inertBannedGeneIds(deriveConfidenceEdges(inertBanObs), inertBanObs, inertBanFingerprint);
|
|
283
465
|
const candidates = input.candidates
|
|
284
466
|
.filter((c) => !isCandidateInSet(c, inertBanned))
|
|
285
467
|
.map((c) => {
|
|
286
468
|
const epi = epigeneticPenaltyForIds(candidateIds(c), envKey, geneOutcomes);
|
|
287
|
-
const conf = confidenceFor(confidenceEdges,
|
|
469
|
+
const conf = confidenceFor(confidenceEdges, currentConfidenceFingerprint, c.geneId, now);
|
|
288
470
|
const withEpi = epi > 0 ? { ...c, epigeneticPenalty: epi } : c;
|
|
289
471
|
return conf > 0 ? { ...withEpi, confidence: conf } : withEpi;
|
|
290
472
|
});
|
|
291
473
|
// #97 distilled-gene fallback pool: attach the env-scoped epigenetic penalty (so selection can hard-skip a
|
|
292
474
|
// suppressed fallback, v1 parity) and drop any inert-banned id (composes with #195). Selection uses these only
|
|
293
|
-
// when
|
|
475
|
+
// when normal selection has no reusable positive choice.
|
|
294
476
|
const distilledFallback = (input.distilledFallback ?? [])
|
|
295
477
|
.filter((c) => !isCandidateInSet(c, inertBanned))
|
|
296
478
|
.map((c) => {
|
|
297
479
|
const epi = epigeneticPenaltyForIds(candidateIds(c), envKey, geneOutcomes);
|
|
298
480
|
return epi > 0 ? { ...c, epigeneticPenalty: epi } : c;
|
|
299
481
|
});
|
|
300
|
-
const
|
|
301
|
-
await
|
|
482
|
+
const semanticCorpus = input.semanticCorpus?.filter((c) => !isCandidateInSet(c, inertBanned));
|
|
483
|
+
const decision = (await this.deps.selection.run({ signals: selectionSignals, candidates, ...(semanticCorpus ? { semanticCorpus } : {}), ...(input.disableSemanticIdf ? { disableSemanticIdf: true } : {}), floor: input.selectionFloor, ...(input.selectionGuard ? { selectionGuard: input.selectionGuard } : {}), ...(input.forcedGeneId !== undefined ? { forcedGeneId: input.forcedGeneId } : {}), ...(exploration ? { exploration } : {}), ...(distilledFallback.length > 0 ? { distilledFallback } : {}), ...(input.antiWarnings && input.antiWarnings.length > 0 ? { antiWarnings: input.antiWarnings } : {}), ...(input.memoryEvidence && input.memoryEvidence.length > 0 ? { memoryEvidence: input.memoryEvidence } : {}) }, { now, cycleId: input.cycleId, ...(this.deps.rng ? { rng: this.deps.rng } : {}) }));
|
|
484
|
+
const geneId = decision.selectedGeneId ?? 'ad-hoc';
|
|
485
|
+
const runPostSelectionStep = async (phase, step) => {
|
|
486
|
+
try {
|
|
487
|
+
return await step();
|
|
488
|
+
}
|
|
489
|
+
catch (error) {
|
|
490
|
+
let persistedTerminal = null;
|
|
491
|
+
try {
|
|
492
|
+
persistedTerminal = persistedTerminalAfterLatestSelection(ingestor, input.cycleId, cycleStarted.seq);
|
|
493
|
+
}
|
|
494
|
+
catch {
|
|
495
|
+
// Readback is best-effort; compensation below remains the fallback when the log is unavailable.
|
|
496
|
+
}
|
|
497
|
+
if (persistedTerminal && !TERMINAL.has(stage) && canTransition(stage, persistedTerminal)) {
|
|
498
|
+
advance(persistedTerminal);
|
|
499
|
+
}
|
|
500
|
+
if (!persistedTerminal && !TERMINAL.has(stage)) {
|
|
501
|
+
try {
|
|
502
|
+
await ingestor.ingest({
|
|
503
|
+
type: 'cycle.failed',
|
|
504
|
+
human: { title: `cycle ${input.cycleId} selection 后异常` },
|
|
505
|
+
payload: { cycleId: input.cycleId, reason: 'post_selection_error', phase, gene: geneId, env: envKey },
|
|
506
|
+
});
|
|
507
|
+
advance('failed');
|
|
508
|
+
try {
|
|
509
|
+
await recordPersonalityOutcome('failed', null);
|
|
510
|
+
}
|
|
511
|
+
catch {
|
|
512
|
+
// Personality is soft state; never let its writeback replace the original failure.
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
catch {
|
|
516
|
+
// The event store itself may be unavailable. Preserve and rethrow the original step failure.
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
throw error;
|
|
520
|
+
}
|
|
521
|
+
};
|
|
522
|
+
await runPostSelectionStep('decision_event', () => ingestGeneSelectedWithTraceBudget(ingestor, {
|
|
302
523
|
type: 'decision.gene_selected',
|
|
303
524
|
human: { title: `选 gene ${decision.selectedGeneId ?? '(innovate)'}`, why: decision.candidates.map((c) => `${c.geneId}:${c.score.toFixed(3)}`).join(', ') || '无候选→innovate' },
|
|
304
|
-
payload: { cycleId: input.cycleId, selectedGeneId: decision.selectedGeneId, ...(decision.selectedAssetId ? { selectedAssetId: decision.selectedAssetId } : {}), candidates: decision.candidates, ...(decision.antiWarnings && decision.antiWarnings.length > 0 ? { antiWarnings: decision.antiWarnings } : {}), weightsVersion: decision.weightsVersion, strategy: decision.strategyName, strategyPreset: strategy.name, ...(plateau.active ? { plateau } : {}), ...(inertBanned.size > 0 ? { inertBanned: [...inertBanned] } : {}) },
|
|
305
|
-
});
|
|
525
|
+
payload: { cycleId: input.cycleId, selectedGeneId: decision.selectedGeneId, ...(decision.selectedAssetId ? { selectedAssetId: decision.selectedAssetId } : {}), ...(decision.selectedReason ? { selectedReason: decision.selectedReason } : {}), candidates: decision.candidates.map(selectionCandidateEventProjection), ...(decision.antiWarnings && decision.antiWarnings.length > 0 ? { antiWarnings: decision.antiWarnings } : {}), ...(decision.memoryEvidence && decision.memoryEvidence.length > 0 ? { memoryEvidence: decision.memoryEvidence } : {}), weightsVersion: decision.weightsVersion, ...(decision.semanticProfileVersion ? { semanticProfileVersion: decision.semanticProfileVersion } : {}), ...(decision.semanticDocumentCount !== undefined ? { semanticDocumentCount: decision.semanticDocumentCount } : {}), strategy: decision.strategyName, strategyPreset: strategy.name, ...(plateau.active ? { plateau } : {}), ...(inertBanned.size > 0 ? { inertBanned: [...inertBanned] } : {}) },
|
|
526
|
+
}, decision.selectionPolicy, decision.selectionGuard));
|
|
306
527
|
advance('gene_selected');
|
|
307
|
-
const geneId = decision.selectedGeneId ?? 'ad-hoc';
|
|
308
528
|
// 变异
|
|
309
|
-
const builtMutation = buildMutation({ decision, category: cycleCategory, signals: cycleSignals, target: input.target, expectedEffect: input.expectedEffect });
|
|
529
|
+
const builtMutation = await runPostSelectionStep('mutation_build', () => buildMutation({ decision, category: cycleCategory, signals: cycleSignals, target: input.target, expectedEffect: input.expectedEffect }));
|
|
310
530
|
// 人格风险闸(用途②): 高危人格禁 innovate / 未达阈值的 high-risk 降级. 未注入人格 ⇒ 原样放行.
|
|
311
531
|
// 用本轮 applySelectForRun 选出的状态(personalityForRun), 而非再读一次 store.currentState() ——
|
|
312
532
|
// 保证"喂 prompt 的风格 / 过风险闸 / 回写统计"三者用的是同一个当轮人格.
|
|
313
533
|
let mutation = builtMutation;
|
|
314
534
|
if (this.deps.personality && personalityForRun) {
|
|
315
|
-
await emitPersonalitySelected(ingestor, { cycleId: input.cycleId, personality: personalityForRun, known: personalityKnown });
|
|
316
|
-
const gate = gatePersonalityRisk(builtMutation, personalityForRun);
|
|
535
|
+
await runPostSelectionStep('personality_selected', () => emitPersonalitySelected(ingestor, { cycleId: input.cycleId, personality: personalityForRun, known: personalityKnown }));
|
|
536
|
+
const gate = await runPostSelectionStep('personality_risk_gate', () => gatePersonalityRisk(builtMutation, personalityForRun));
|
|
317
537
|
mutation = gate.mutation;
|
|
318
|
-
await emitPersonalityRiskGated(ingestor, { cycleId: input.cycleId, personality: personalityForRun, gate });
|
|
538
|
+
await runPostSelectionStep('personality_risk_gate', () => emitPersonalityRiskGated(ingestor, { cycleId: input.cycleId, personality: personalityForRun, gate }));
|
|
319
539
|
}
|
|
320
|
-
await ingestor.ingest({ type: 'mutation.built', human: { title: `变异 ${mutation.category} → ${mutation.target}` }, payload: { cycleId: input.cycleId, mutationId: mutation.id, risk: mutation.risk_level, category: mutation.category, strategyPreset: strategy.name } });
|
|
540
|
+
await runPostSelectionStep('mutation_event', () => ingestor.ingest({ type: 'mutation.built', human: { title: `变异 ${mutation.category} → ${mutation.target}` }, payload: { cycleId: input.cycleId, mutationId: mutation.id, risk: mutation.risk_level, category: mutation.category, strategyPreset: strategy.name } }));
|
|
321
541
|
advance('mutation_built');
|
|
322
542
|
// 执行(agent/runtime)
|
|
323
543
|
let exec;
|
|
@@ -328,16 +548,19 @@ export class CycleEngine {
|
|
|
328
548
|
const msg = e instanceof Error ? e.message : String(e);
|
|
329
549
|
// execute threw before returning a transcript; the error text IS the host context (a provider error that
|
|
330
550
|
// surfaces as a thrown exception still classifies as host_provider_error). Pass it as the sessionLog.
|
|
331
|
-
await ingestor.ingest({ type: 'cycle.failed', human: { title: `cycle ${input.cycleId} 执行抛错` }, payload: { cycleId: input.cycleId, error: msg, gene: geneId, env: envKey, ...failureClassPayload({ geneId }, msg) } });
|
|
551
|
+
await runPostSelectionStep('terminal_event', () => ingestor.ingest({ type: 'cycle.failed', human: { title: `cycle ${input.cycleId} 执行抛错` }, payload: { cycleId: input.cycleId, error: msg, gene: geneId, env: envKey, ...failureClassPayload({ geneId }, msg) } }));
|
|
332
552
|
advance('failed');
|
|
333
553
|
await recordPersonalityOutcome('failed', null);
|
|
334
|
-
return { cycleId: input.cycleId, triggered: true, finalStage: stage, decision, mutation, reasons: [...reasons, `执行异常: ${msg}`] };
|
|
554
|
+
return { cycleId: input.cycleId, triggered: true, finalStage: stage, producedValue: false, decision, mutation, reasons: [...reasons, `执行异常: ${msg}`] };
|
|
335
555
|
}
|
|
336
556
|
if (input.solidifyPermit) {
|
|
337
557
|
let permit;
|
|
338
558
|
try {
|
|
339
559
|
permit = await input.solidifyPermit({
|
|
340
560
|
cycleId: input.cycleId,
|
|
561
|
+
...(input.executionBinding ? { bindingDigest: input.executionBinding.binding_digest, runId: input.executionBinding.correlation.run_id } : {}),
|
|
562
|
+
...(exec.executionTerminal ? { executionTerminal: exec.executionTerminal } : {}),
|
|
563
|
+
...(exec.provenance ? { provenance: exec.provenance } : {}),
|
|
341
564
|
geneId,
|
|
342
565
|
signals: cycleSignals,
|
|
343
566
|
mutation,
|
|
@@ -352,7 +575,15 @@ export class CycleEngine {
|
|
|
352
575
|
}
|
|
353
576
|
if (!permit.ok) {
|
|
354
577
|
const reason = `solidify permit denied: ${permit.reason}`;
|
|
355
|
-
|
|
578
|
+
exec = {
|
|
579
|
+
...exec,
|
|
580
|
+
outcome: { ...exec.outcome, status: 'failed', reason },
|
|
581
|
+
executionTerminal: { status: 'failed', disposition: 'denied' },
|
|
582
|
+
provenance: exec.provenance
|
|
583
|
+
? { ...exec.provenance, permit, terminal_disposition: 'denied' }
|
|
584
|
+
: undefined,
|
|
585
|
+
};
|
|
586
|
+
await runPostSelectionStep('terminal_event', () => ingestor.ingest({
|
|
356
587
|
type: 'cycle.failed',
|
|
357
588
|
human: { title: `cycle ${input.cycleId} permit denied` },
|
|
358
589
|
payload: {
|
|
@@ -360,32 +591,63 @@ export class CycleEngine {
|
|
|
360
591
|
reason: permit.reason,
|
|
361
592
|
gene: geneId,
|
|
362
593
|
env: envKey,
|
|
594
|
+
...executionMetadata(exec),
|
|
363
595
|
...failureClassPayload({ geneId }),
|
|
364
596
|
},
|
|
365
|
-
});
|
|
597
|
+
}));
|
|
366
598
|
advance('failed');
|
|
367
599
|
await recordPersonalityOutcome('failed', null);
|
|
368
|
-
return {
|
|
600
|
+
return {
|
|
601
|
+
cycleId: input.cycleId,
|
|
602
|
+
triggered: true,
|
|
603
|
+
finalStage: stage,
|
|
604
|
+
producedValue: false,
|
|
605
|
+
decision,
|
|
606
|
+
mutation,
|
|
607
|
+
execution: exec,
|
|
608
|
+
...(exec.bindingCorrelation ? { bindingDigest: exec.bindingCorrelation.bindingDigest, runId: exec.bindingCorrelation.runId } : {}),
|
|
609
|
+
...(exec.executionTerminal ? { terminalDisposition: exec.executionTerminal.disposition } : {}),
|
|
610
|
+
...executionMetadata(exec),
|
|
611
|
+
reasons: [...reasons, reason],
|
|
612
|
+
};
|
|
369
613
|
}
|
|
370
614
|
}
|
|
371
615
|
// solidify → Capsule
|
|
372
|
-
const sol = solidify({
|
|
616
|
+
const sol = await runPostSelectionStep('solidify', () => solidify({
|
|
373
617
|
geneId, trigger: cycleSignals, summary: input.summary, confidence: input.confidence,
|
|
374
618
|
outcome: exec.outcome, proofOfWork: exec.proofOfWork, strongEvidence: exec.strongEvidence,
|
|
375
|
-
|
|
619
|
+
...(exec.failureIdentity ? { failureIdentity: exec.failureIdentity } : {}),
|
|
620
|
+
}));
|
|
376
621
|
reasons.push(...sol.reasons);
|
|
377
|
-
await store.put(sol.capsule);
|
|
378
|
-
await ingestor.ingest({ type: 'capsule.produced', human: { title: `Capsule ${sol.resolutionStatus}` }, payload: { cycleId: input.cycleId, capsuleId: sol.capsule.asset_id, resolutionStatus: sol.resolutionStatus, producedValue: sol.producedValue, blastRadius: sol.capsule.blast_radius } });
|
|
379
|
-
// EvolutionEvent(capsule_id 引 Capsule; outcome 真值在此)
|
|
380
|
-
|
|
622
|
+
await runPostSelectionStep('capsule_store', () => store.put(sol.capsule));
|
|
623
|
+
await runPostSelectionStep('capsule_event', () => ingestor.ingest({ type: 'capsule.produced', human: { title: `Capsule ${sol.resolutionStatus}` }, payload: { cycleId: input.cycleId, capsuleId: sol.capsule.asset_id, resolutionStatus: sol.resolutionStatus, producedValue: sol.producedValue, blastRadius: sol.capsule.blast_radius } }));
|
|
624
|
+
// EvolutionEvent(capsule_id 引 Capsule; outcome 真值在此).
|
|
625
|
+
// Selection stamp: selected_asset_id / kauto_member / evolver_version / selection_stage=applied
|
|
626
|
+
// live in event.meta so production cohort collection can separate writer membership from
|
|
627
|
+
// selected/applied member share. Only true kauto membership is stamped (omit-not-null).
|
|
628
|
+
const selectedCandidate = decision.selectedGeneId
|
|
629
|
+
? input.candidates.find((c) => (c.geneId === decision.selectedGeneId
|
|
630
|
+
&& (decision.selectedAssetId === undefined || c.assetId === decision.selectedAssetId)))
|
|
631
|
+
?? input.candidates.find((c) => c.geneId === decision.selectedGeneId)
|
|
632
|
+
?? (input.distilledFallback ?? []).find((c) => (c.geneId === decision.selectedGeneId
|
|
633
|
+
&& (decision.selectedAssetId === undefined || c.assetId === decision.selectedAssetId)))
|
|
634
|
+
: undefined;
|
|
635
|
+
const envFp = (this.deps.envFingerprint ?? captureEnvFingerprint)();
|
|
636
|
+
const event = await runPostSelectionStep('evolution_event_build', () => buildEvolutionEvent({
|
|
381
637
|
intent: cycleCategory, signals: cycleSignals, genesUsed: decision.selectedGeneId ? [decision.selectedGeneId] : [],
|
|
382
638
|
mutationId: mutation.id, blastRadius: sol.capsule.blast_radius, outcome: exec.outcome,
|
|
383
639
|
capsuleId: sol.capsule.asset_id, sourceType: decision.selectedGeneId ? 'reused' : 'generated',
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
640
|
+
selection: {
|
|
641
|
+
selectionStage: 'applied',
|
|
642
|
+
...(decision.selectedAssetId ? { selectedAssetId: decision.selectedAssetId } : {}),
|
|
643
|
+
...(selectedCandidate?.kautoMember === true ? { kautoMember: true } : {}),
|
|
644
|
+
...(envFp.evolver_version ? { evolverVersion: envFp.evolver_version } : {}),
|
|
645
|
+
},
|
|
646
|
+
}));
|
|
647
|
+
await runPostSelectionStep('evolution_event_store', () => store.put(event));
|
|
648
|
+
await runPostSelectionStep('evolution_event_projection', () => ingestor.ingest({ type: 'evolution_event.projected', human: { title: `世代记录 ${exec.outcome.status}` }, payload: { cycleId: input.cycleId, eventId: event.asset_id, capsuleId: sol.capsule.asset_id, outcome: exec.outcome } }));
|
|
387
649
|
if (exec.outcome.status === 'failed') {
|
|
388
|
-
await ingestor.ingest({
|
|
650
|
+
await runPostSelectionStep('terminal_event', () => ingestor.ingest({
|
|
389
651
|
type: 'cycle.failed',
|
|
390
652
|
human: { title: `cycle ${input.cycleId} 失败` },
|
|
391
653
|
payload: {
|
|
@@ -394,6 +656,7 @@ export class CycleEngine {
|
|
|
394
656
|
outcome: exec.outcome,
|
|
395
657
|
gene: geneId,
|
|
396
658
|
env: envKey,
|
|
659
|
+
...executionMetadata(exec),
|
|
397
660
|
// Only forward blast radius as a no-op signal when it was measured from a git_diff proof. solidify.ts
|
|
398
661
|
// forces blast to {0,0} for non-git_diff proofs (artifact_hash/external_receipt/tool_call_trace),
|
|
399
662
|
// where {0,0} means "blast unknown", NOT "no change" — forwarding it would mis-classify a productive
|
|
@@ -405,15 +668,30 @@ export class CycleEngine {
|
|
|
405
668
|
: {}),
|
|
406
669
|
}, exec.sessionLog),
|
|
407
670
|
},
|
|
408
|
-
});
|
|
671
|
+
}));
|
|
409
672
|
advance('failed');
|
|
410
673
|
}
|
|
411
674
|
else {
|
|
412
|
-
await ingestor.ingest({ type: 'cycle.solidified', human: { title: `cycle ${input.cycleId} 固化` }, payload: { cycleId: input.cycleId, capsuleId: sol.capsule.asset_id, outcome: exec.outcome, gene: geneId, env: envKey, producedValue: sol.producedValue } });
|
|
675
|
+
await runPostSelectionStep('terminal_event', () => ingestor.ingest({ type: 'cycle.solidified', human: { title: `cycle ${input.cycleId} 固化` }, payload: { cycleId: input.cycleId, capsuleId: sol.capsule.asset_id, outcome: exec.outcome, gene: geneId, env: envKey, producedValue: sol.producedValue } }));
|
|
413
676
|
advance('solidified');
|
|
414
677
|
}
|
|
415
678
|
// 人格统计回写(用途②): 用本轮真实 outcome/score 回写当轮人格桶, 供下一轮自然选择靠拢. 未注入 ⇒ no-op.
|
|
416
679
|
await recordPersonalityOutcome(exec.outcome.status, exec.outcome.score);
|
|
417
|
-
return {
|
|
680
|
+
return {
|
|
681
|
+
cycleId: input.cycleId,
|
|
682
|
+
triggered: true,
|
|
683
|
+
finalStage: stage,
|
|
684
|
+
producedValue: sol.producedValue,
|
|
685
|
+
decision,
|
|
686
|
+
mutation,
|
|
687
|
+
capsule: sol.capsule,
|
|
688
|
+
event,
|
|
689
|
+
resolutionStatus: sol.resolutionStatus,
|
|
690
|
+
execution: exec,
|
|
691
|
+
...(exec.bindingCorrelation ? { bindingDigest: exec.bindingCorrelation.bindingDigest, runId: exec.bindingCorrelation.runId } : {}),
|
|
692
|
+
...(exec.executionTerminal ? { terminalDisposition: exec.executionTerminal.disposition } : {}),
|
|
693
|
+
...executionMetadata(exec),
|
|
694
|
+
reasons,
|
|
695
|
+
};
|
|
418
696
|
}
|
|
419
697
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Bucket the failure falls into. unclassified = default-open (treat as a real evolver bug worth filing).
|
|
2
|
-
* Bucket string matches V1
|
|
2
|
+
* Bucket string matches V1 byte-for-byte so wire / UI
|
|
3
3
|
* consumers can branch on the same value regardless of producer. */
|
|
4
4
|
export type CycleFailureClass = 'host_no_transcript' | 'host_provider_error' | 'local_gene_no_blast' | 'unclassified';
|
|
5
5
|
/** Shape of a recent cycle event the classifier reads. Loose so callers can pass partial DTOs. */
|
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
import { type EvolutionEvent, type GepCategory } from '../wire/index.js';
|
|
2
|
+
/** Selection-side lifecycle stamp carried in EvolutionEvent.meta (schema-allowed object). */
|
|
3
|
+
export type EvolutionSelectionStage = 'selected' | 'applied';
|
|
4
|
+
export interface EvolutionSelectionStamp {
|
|
5
|
+
/** Content asset_id of the selected Gene when known (sha256:…). */
|
|
6
|
+
selectedAssetId?: string;
|
|
7
|
+
/** True only when assembly stamped kautoMember on the selected candidate. */
|
|
8
|
+
kautoMember?: boolean;
|
|
9
|
+
/** Producer evolver version from env fingerprint, when known. */
|
|
10
|
+
evolverVersion?: string;
|
|
11
|
+
/**
|
|
12
|
+
* selected = gene was chosen for the cycle;
|
|
13
|
+
* applied = cycle produced an EvolutionEvent after execution (this builder always emits applied).
|
|
14
|
+
*/
|
|
15
|
+
selectionStage?: EvolutionSelectionStage;
|
|
16
|
+
}
|
|
2
17
|
export interface BuildEvolutionEventInput {
|
|
3
18
|
intent: GepCategory;
|
|
4
19
|
signals: readonly string[];
|
|
@@ -15,9 +30,20 @@ export interface BuildEvolutionEventInput {
|
|
|
15
30
|
capsuleId: string | null;
|
|
16
31
|
sourceType: 'generated' | 'reused' | 'reference';
|
|
17
32
|
parent?: string | null;
|
|
33
|
+
/** Optional selection lifecycle stamp; omitted keys stay absent (omit-not-null). */
|
|
34
|
+
selection?: EvolutionSelectionStamp;
|
|
18
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Build the schema-allowed `meta` object for selection telemetry.
|
|
38
|
+
* Absent optional fields are omitted so they do not enter the asset_id hash as null.
|
|
39
|
+
*/
|
|
40
|
+
export declare function buildEvolutionSelectionMeta(selection: EvolutionSelectionStamp | undefined): Record<string, unknown> | undefined;
|
|
19
41
|
/**
|
|
20
42
|
* EvolutionEvent = 世代记录(outcome 真值在此, 硬化 A4). 单向引 Capsule(capsule_id);
|
|
21
43
|
* 写入序列: capsule asset_id 先算 → 填 capsule_id → 再算 event asset_id.
|
|
44
|
+
*
|
|
45
|
+
* Optional selection stamp lands in `meta` (schema-allowed) so production cohort
|
|
46
|
+
* collection can separate writer membership from selected/applied member share
|
|
47
|
+
* without inventing a LearningAsset bridge.
|
|
22
48
|
*/
|
|
23
49
|
export declare function buildEvolutionEvent(input: BuildEvolutionEventInput): EvolutionEvent;
|
|
@@ -1,10 +1,41 @@
|
|
|
1
1
|
import { ulid as makeUlid } from 'ulid';
|
|
2
2
|
import { computeAssetId, SCHEMA_VERSION } from '../wire/index.js';
|
|
3
|
+
function nonEmptyString(value) {
|
|
4
|
+
return typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Build the schema-allowed `meta` object for selection telemetry.
|
|
8
|
+
* Absent optional fields are omitted so they do not enter the asset_id hash as null.
|
|
9
|
+
*/
|
|
10
|
+
export function buildEvolutionSelectionMeta(selection) {
|
|
11
|
+
if (!selection)
|
|
12
|
+
return undefined;
|
|
13
|
+
const selectedAssetId = nonEmptyString(selection.selectedAssetId);
|
|
14
|
+
const evolverVersion = nonEmptyString(selection.evolverVersion);
|
|
15
|
+
const selectionStage = selection.selectionStage === 'selected' || selection.selectionStage === 'applied'
|
|
16
|
+
? selection.selectionStage
|
|
17
|
+
: undefined;
|
|
18
|
+
const meta = {};
|
|
19
|
+
if (selectedAssetId)
|
|
20
|
+
meta['selected_asset_id'] = selectedAssetId;
|
|
21
|
+
if (selection.kautoMember === true)
|
|
22
|
+
meta['kauto_member'] = true;
|
|
23
|
+
if (evolverVersion)
|
|
24
|
+
meta['evolver_version'] = evolverVersion;
|
|
25
|
+
if (selectionStage)
|
|
26
|
+
meta['selection_stage'] = selectionStage;
|
|
27
|
+
return Object.keys(meta).length > 0 ? meta : undefined;
|
|
28
|
+
}
|
|
3
29
|
/**
|
|
4
30
|
* EvolutionEvent = 世代记录(outcome 真值在此, 硬化 A4). 单向引 Capsule(capsule_id);
|
|
5
31
|
* 写入序列: capsule asset_id 先算 → 填 capsule_id → 再算 event asset_id.
|
|
32
|
+
*
|
|
33
|
+
* Optional selection stamp lands in `meta` (schema-allowed) so production cohort
|
|
34
|
+
* collection can separate writer membership from selected/applied member share
|
|
35
|
+
* without inventing a LearningAsset bridge.
|
|
6
36
|
*/
|
|
7
37
|
export function buildEvolutionEvent(input) {
|
|
38
|
+
const meta = buildEvolutionSelectionMeta(input.selection);
|
|
8
39
|
const base = {
|
|
9
40
|
type: 'EvolutionEvent',
|
|
10
41
|
schema_version: SCHEMA_VERSION,
|
|
@@ -18,6 +49,7 @@ export function buildEvolutionEvent(input) {
|
|
|
18
49
|
outcome: input.outcome,
|
|
19
50
|
capsule_id: input.capsuleId,
|
|
20
51
|
source_type: input.sourceType,
|
|
52
|
+
...(meta ? { meta } : {}),
|
|
21
53
|
};
|
|
22
54
|
const asset_id = computeAssetId(base);
|
|
23
55
|
return { ...base, asset_id };
|