@evomap/evolver-core 2.0.0-beta.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.
- package/dist/algo/antiDistill.d.ts +35 -0
- package/dist/algo/antiDistill.js +167 -0
- package/dist/algo/bans.d.ts +6 -0
- package/dist/algo/bans.js +33 -0
- package/dist/algo/candidateAssembly.d.ts +65 -0
- package/dist/algo/candidateAssembly.js +196 -0
- package/dist/algo/capabilityCandidates.d.ts +38 -0
- package/dist/algo/capabilityCandidates.js +131 -0
- package/dist/algo/confidence.d.ts +106 -0
- package/dist/algo/confidence.js +196 -0
- package/dist/algo/cycleEngine.d.ts +143 -0
- package/dist/algo/cycleEngine.js +417 -0
- package/dist/algo/cycleFailureClassifier.d.ts +52 -0
- package/dist/algo/cycleFailureClassifier.js +104 -0
- package/dist/algo/epigenetics.d.ts +14 -0
- package/dist/algo/epigenetics.js +41 -0
- package/dist/algo/evolutionEvent.d.ts +23 -0
- package/dist/algo/evolutionEvent.js +24 -0
- package/dist/algo/exploration.d.ts +34 -0
- package/dist/algo/exploration.js +55 -0
- package/dist/algo/geneHealth.d.ts +24 -0
- package/dist/algo/geneHealth.js +16 -0
- package/dist/algo/geneIntake.d.ts +37 -0
- package/dist/algo/geneIntake.js +100 -0
- package/dist/algo/genePromotion.d.ts +48 -0
- package/dist/algo/genePromotion.js +53 -0
- package/dist/algo/geneSelection.d.ts +128 -0
- package/dist/algo/geneSelection.js +222 -0
- package/dist/algo/index.d.ts +18 -0
- package/dist/algo/index.js +18 -0
- package/dist/algo/mutation.d.ts +12 -0
- package/dist/algo/mutation.js +22 -0
- package/dist/algo/orchestrator.d.ts +65 -0
- package/dist/algo/orchestrator.js +63 -0
- package/dist/algo/solidify.d.ts +43 -0
- package/dist/algo/solidify.js +63 -0
- package/dist/algo/strategyPresets.d.ts +32 -0
- package/dist/algo/strategyPresets.js +61 -0
- package/dist/assetstore/index.d.ts +8 -0
- package/dist/assetstore/index.js +8 -0
- package/dist/assetstore/learningHistory.d.ts +25 -0
- package/dist/assetstore/learningHistory.js +38 -0
- package/dist/assetstore/localJsonl.d.ts +34 -0
- package/dist/assetstore/localJsonl.js +182 -0
- package/dist/assetstore/pendingSignals.d.ts +22 -0
- package/dist/assetstore/pendingSignals.js +171 -0
- package/dist/assetstore/provenance.d.ts +39 -0
- package/dist/assetstore/provenance.js +109 -0
- package/dist/assetstore/provider.d.ts +48 -0
- package/dist/assetstore/provider.js +36 -0
- package/dist/assetstore/remoteStub.d.ts +32 -0
- package/dist/assetstore/remoteStub.js +36 -0
- package/dist/assetstore/reviewFilter.d.ts +20 -0
- package/dist/assetstore/reviewFilter.js +44 -0
- package/dist/assetstore/reviewLedger.d.ts +55 -0
- package/dist/assetstore/reviewLedger.js +121 -0
- package/dist/benchmark/antiGeneBenchmark.d.ts +79 -0
- package/dist/benchmark/antiGeneBenchmark.js +241 -0
- package/dist/benchmark/antiGeneRollout.d.ts +80 -0
- package/dist/benchmark/antiGeneRollout.js +256 -0
- package/dist/benchmark/benchmark.d.ts +32 -0
- package/dist/benchmark/benchmark.js +26 -0
- package/dist/benchmark/evolutionThesisSolver.d.ts +25 -0
- package/dist/benchmark/evolutionThesisSolver.js +41 -0
- package/dist/benchmark/index.d.ts +5 -0
- package/dist/benchmark/index.js +5 -0
- package/dist/benchmark/thesis.d.ts +85 -0
- package/dist/benchmark/thesis.js +150 -0
- package/dist/bootstrap/envFingerprint.d.ts +45 -0
- package/dist/bootstrap/envFingerprint.js +72 -0
- package/dist/bootstrap/index.d.ts +2 -0
- package/dist/bootstrap/index.js +2 -0
- package/dist/bootstrap/selfEvolve.d.ts +36 -0
- package/dist/bootstrap/selfEvolve.js +26 -0
- package/dist/cycle/cycleTimeline.d.ts +35 -0
- package/dist/cycle/cycleTimeline.js +74 -0
- package/dist/cycle/index.d.ts +2 -0
- package/dist/cycle/index.js +2 -0
- package/dist/cycle/stateMachine.d.ts +6 -0
- package/dist/cycle/stateMachine.js +25 -0
- package/dist/daemon/cycleContext.d.ts +12 -0
- package/dist/daemon/cycleContext.js +13 -0
- package/dist/daemon/drain.d.ts +11 -0
- package/dist/daemon/drain.js +16 -0
- package/dist/daemon/guards.d.ts +87 -0
- package/dist/daemon/guards.js +142 -0
- package/dist/daemon/idempotency.d.ts +11 -0
- package/dist/daemon/idempotency.js +36 -0
- package/dist/daemon/idleScheduler.d.ts +55 -0
- package/dist/daemon/idleScheduler.js +181 -0
- package/dist/daemon/index.d.ts +8 -0
- package/dist/daemon/index.js +8 -0
- package/dist/daemon/stepRunner.d.ts +12 -0
- package/dist/daemon/stepRunner.js +31 -0
- package/dist/daemon/unhandledRejectionWindow.d.ts +21 -0
- package/dist/daemon/unhandledRejectionWindow.js +52 -0
- package/dist/daemon/watchdog.d.ts +11 -0
- package/dist/daemon/watchdog.js +14 -0
- package/dist/events/eventSchema.d.ts +132 -0
- package/dist/events/eventSchema.js +30 -0
- package/dist/events/eventStore.d.ts +32 -0
- package/dist/events/eventStore.js +137 -0
- package/dist/events/ingest.d.ts +34 -0
- package/dist/events/ingest.js +61 -0
- package/dist/events/paths.d.ts +22 -0
- package/dist/events/paths.js +44 -0
- package/dist/events/projectors.d.ts +9 -0
- package/dist/events/projectors.js +11 -0
- package/dist/events/public.d.ts +14 -0
- package/dist/events/public.js +8 -0
- package/dist/events/replayer.d.ts +26 -0
- package/dist/events/replayer.js +67 -0
- package/dist/events/reports.d.ts +90 -0
- package/dist/events/reports.js +244 -0
- package/dist/events/retention.d.ts +70 -0
- package/dist/events/retention.js +177 -0
- package/dist/events/sink.d.ts +5 -0
- package/dist/events/sink.js +1 -0
- package/dist/exec/autoExec.d.ts +137 -0
- package/dist/exec/autoExec.js +221 -0
- package/dist/exec/autonomousCycle.d.ts +48 -0
- package/dist/exec/autonomousCycle.js +78 -0
- package/dist/exec/claudeBridge.d.ts +112 -0
- package/dist/exec/claudeBridge.js +219 -0
- package/dist/exec/index.d.ts +9 -0
- package/dist/exec/index.js +11 -0
- package/dist/exec/openPrRegistry.d.ts +60 -0
- package/dist/exec/openPrRegistry.js +130 -0
- package/dist/exec/policy/blastRadius.d.ts +31 -0
- package/dist/exec/policy/blastRadius.js +67 -0
- package/dist/exec/policy/constraints.d.ts +26 -0
- package/dist/exec/policy/constraints.js +62 -0
- package/dist/exec/policy/destructive.d.ts +45 -0
- package/dist/exec/policy/destructive.js +108 -0
- package/dist/exec/policy/failureMode.d.ts +33 -0
- package/dist/exec/policy/failureMode.js +49 -0
- package/dist/exec/policy/index.d.ts +24 -0
- package/dist/exec/policy/index.js +30 -0
- package/dist/exec/policy/protectedPaths.d.ts +17 -0
- package/dist/exec/policy/protectedPaths.js +65 -0
- package/dist/exec/policyCheck.d.ts +2 -0
- package/dist/exec/policyCheck.js +7 -0
- package/dist/exec/prompt.d.ts +34 -0
- package/dist/exec/prompt.js +108 -0
- package/dist/exec/proofOfWork.d.ts +9 -0
- package/dist/exec/proofOfWork.js +11 -0
- package/dist/exec/runnerRegistry.d.ts +123 -0
- package/dist/exec/runnerRegistry.js +237 -0
- package/dist/exec/selfPr.d.ts +83 -0
- package/dist/exec/selfPr.js +104 -0
- package/dist/exec/selfPrObfuscation.d.ts +21 -0
- package/dist/exec/selfPrObfuscation.js +85 -0
- package/dist/hooks/hooks.d.ts +117 -0
- package/dist/hooks/hooks.js +89 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hub/assetCallLog.d.ts +43 -0
- package/dist/hub/assetCallLog.js +72 -0
- package/dist/hub/bindings.d.ts +28 -0
- package/dist/hub/bindings.js +90 -0
- package/dist/hub/capability.d.ts +278 -0
- package/dist/hub/capability.js +1 -0
- package/dist/hub/conversationDistiller.d.ts +88 -0
- package/dist/hub/conversationDistiller.js +264 -0
- package/dist/hub/fake.d.ts +45 -0
- package/dist/hub/fake.js +69 -0
- package/dist/hub/hubReview.d.ts +91 -0
- package/dist/hub/hubReview.js +106 -0
- package/dist/hub/index.d.ts +10 -0
- package/dist/hub/index.js +10 -0
- package/dist/hub/ingest.d.ts +15 -0
- package/dist/hub/ingest.js +15 -0
- package/dist/hub/questionGenerator.d.ts +59 -0
- package/dist/hub/questionGenerator.js +406 -0
- package/dist/hub/reuseDecision.d.ts +87 -0
- package/dist/hub/reuseDecision.js +127 -0
- package/dist/hub/sanitize.d.ts +52 -0
- package/dist/hub/sanitize.js +321 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +27 -0
- package/dist/mailbox/catalog.d.ts +17 -0
- package/dist/mailbox/catalog.js +53 -0
- package/dist/mailbox/daemon.d.ts +48 -0
- package/dist/mailbox/daemon.js +61 -0
- package/dist/mailbox/dispatch.d.ts +46 -0
- package/dist/mailbox/dispatch.js +62 -0
- package/dist/mailbox/envelope.d.ts +43 -0
- package/dist/mailbox/envelope.js +52 -0
- package/dist/mailbox/index.d.ts +8 -0
- package/dist/mailbox/index.js +8 -0
- package/dist/mailbox/ipcServer.d.ts +46 -0
- package/dist/mailbox/ipcServer.js +168 -0
- package/dist/mailbox/requestReply.d.ts +40 -0
- package/dist/mailbox/requestReply.js +77 -0
- package/dist/mailbox/store.d.ts +74 -0
- package/dist/mailbox/store.js +308 -0
- package/dist/mailbox/wake.d.ts +45 -0
- package/dist/mailbox/wake.js +60 -0
- package/dist/material/boundary.d.ts +7 -0
- package/dist/material/boundary.js +14 -0
- package/dist/material/consumer.d.ts +21 -0
- package/dist/material/consumer.js +52 -0
- package/dist/material/emit.d.ts +55 -0
- package/dist/material/emit.js +52 -0
- package/dist/material/factory.d.ts +27 -0
- package/dist/material/factory.js +25 -0
- package/dist/material/index.d.ts +8 -0
- package/dist/material/index.js +8 -0
- package/dist/material/materialStore.d.ts +24 -0
- package/dist/material/materialStore.js +76 -0
- package/dist/material/sampling.d.ts +21 -0
- package/dist/material/sampling.js +39 -0
- package/dist/material/sources.d.ts +25 -0
- package/dist/material/sources.js +33 -0
- package/dist/material/watermark.d.ts +21 -0
- package/dist/material/watermark.js +76 -0
- package/dist/observers/cursorRewriteObserver.d.ts +46 -0
- package/dist/observers/cursorRewriteObserver.js +103 -0
- package/dist/observers/distillObserver.d.ts +31 -0
- package/dist/observers/distillObserver.js +93 -0
- package/dist/observers/index.d.ts +5 -0
- package/dist/observers/index.js +5 -0
- package/dist/observers/observerBus.d.ts +44 -0
- package/dist/observers/observerBus.js +73 -0
- package/dist/observers/reflectionObserver.d.ts +31 -0
- package/dist/observers/reflectionObserver.js +124 -0
- package/dist/observers/valueDigestObserver.d.ts +50 -0
- package/dist/observers/valueDigestObserver.js +70 -0
- package/dist/ops/cleanup.d.ts +23 -0
- package/dist/ops/cleanup.js +68 -0
- package/dist/ops/health.d.ts +37 -0
- package/dist/ops/health.js +96 -0
- package/dist/ops/index.d.ts +7 -0
- package/dist/ops/index.js +7 -0
- package/dist/ops/recall.d.ts +65 -0
- package/dist/ops/recall.js +152 -0
- package/dist/ops/reuseOutcomes.d.ts +68 -0
- package/dist/ops/reuseOutcomes.js +126 -0
- package/dist/ops/savingsCore.d.ts +47 -0
- package/dist/ops/savingsCore.js +112 -0
- package/dist/ops/selfUpdate.d.ts +106 -0
- package/dist/ops/selfUpdate.js +294 -0
- package/dist/ops/valueLedger.d.ts +205 -0
- package/dist/ops/valueLedger.js +238 -0
- package/dist/ops/valueOutreach.d.ts +70 -0
- package/dist/ops/valueOutreach.js +244 -0
- package/dist/personality/drift.d.ts +45 -0
- package/dist/personality/drift.js +106 -0
- package/dist/personality/events.d.ts +25 -0
- package/dist/personality/events.js +37 -0
- package/dist/personality/evolveOps.d.ts +20 -0
- package/dist/personality/evolveOps.js +93 -0
- package/dist/personality/index.d.ts +11 -0
- package/dist/personality/index.js +11 -0
- package/dist/personality/mutate.d.ts +21 -0
- package/dist/personality/mutate.js +39 -0
- package/dist/personality/pivot.d.ts +23 -0
- package/dist/personality/pivot.js +22 -0
- package/dist/personality/prompt.d.ts +6 -0
- package/dist/personality/prompt.js +62 -0
- package/dist/personality/riskGate.d.ts +42 -0
- package/dist/personality/riskGate.js +80 -0
- package/dist/personality/schema.d.ts +255 -0
- package/dist/personality/schema.js +119 -0
- package/dist/personality/select.d.ts +46 -0
- package/dist/personality/select.js +71 -0
- package/dist/personality/stats.d.ts +46 -0
- package/dist/personality/stats.js +82 -0
- package/dist/personality/store.d.ts +35 -0
- package/dist/personality/store.js +92 -0
- package/dist/schema/common.d.ts +28 -0
- package/dist/schema/common.js +17 -0
- package/dist/schema/index.d.ts +5 -0
- package/dist/schema/index.js +5 -0
- package/dist/schema/material.d.ts +201 -0
- package/dist/schema/material.js +50 -0
- package/dist/schema/problem.d.ts +160 -0
- package/dist/schema/problem.js +45 -0
- package/dist/schema/proofOfWork.d.ts +97 -0
- package/dist/schema/proofOfWork.js +9 -0
- package/dist/schema/signal.d.ts +41 -0
- package/dist/schema/signal.js +19 -0
- package/dist/shadow/index.d.ts +6 -0
- package/dist/shadow/index.js +6 -0
- package/dist/shadow/jsonlSink.d.ts +17 -0
- package/dist/shadow/jsonlSink.js +27 -0
- package/dist/shadow/redact.d.ts +11 -0
- package/dist/shadow/redact.js +18 -0
- package/dist/shadow/shadowHub.d.ts +12 -0
- package/dist/shadow/shadowHub.js +42 -0
- package/dist/shadow/shadowMailbox.d.ts +17 -0
- package/dist/shadow/shadowMailbox.js +25 -0
- package/dist/shadow/shadowStore.d.ts +18 -0
- package/dist/shadow/shadowStore.js +55 -0
- package/dist/shadow/sink.d.ts +37 -0
- package/dist/shadow/sink.js +18 -0
- package/dist/signals/cycleHistoryFromEvents.d.ts +11 -0
- package/dist/signals/cycleHistoryFromEvents.js +96 -0
- package/dist/signals/expand.d.ts +34 -0
- package/dist/signals/expand.js +125 -0
- package/dist/signals/extractor.d.ts +25 -0
- package/dist/signals/extractor.js +57 -0
- package/dist/signals/index.d.ts +6 -0
- package/dist/signals/index.js +6 -0
- package/dist/signals/metaSignals.d.ts +57 -0
- package/dist/signals/metaSignals.js +158 -0
- package/dist/signals/signalGate.d.ts +15 -0
- package/dist/signals/signalGate.js +40 -0
- package/dist/signals/traceSignals.d.ts +44 -0
- package/dist/signals/traceSignals.js +123 -0
- package/dist/signatures/classifier.d.ts +16 -0
- package/dist/signatures/classifier.js +29 -0
- package/dist/signatures/index.d.ts +2 -0
- package/dist/signatures/index.js +2 -0
- package/dist/signatures/signatures.d.ts +22 -0
- package/dist/signatures/signatures.js +42 -0
- package/dist/strategy/experiment.d.ts +48 -0
- package/dist/strategy/experiment.js +63 -0
- package/dist/strategy/index.d.ts +2 -0
- package/dist/strategy/index.js +2 -0
- package/dist/strategy/strategyPoint.d.ts +30 -0
- package/dist/strategy/strategyPoint.js +23 -0
- package/dist/trace/index.d.ts +2 -0
- package/dist/trace/index.js +2 -0
- package/dist/trace/trajectory.d.ts +82 -0
- package/dist/trace/trajectory.js +117 -0
- package/dist/trace/trajectoryExport.d.ts +237 -0
- package/dist/trace/trajectoryExport.js +1818 -0
- package/dist/trigger/budget.d.ts +16 -0
- package/dist/trigger/budget.js +20 -0
- package/dist/trigger/engine.d.ts +12 -0
- package/dist/trigger/engine.js +23 -0
- package/dist/trigger/index.d.ts +6 -0
- package/dist/trigger/index.js +6 -0
- package/dist/trigger/problemBuilder.d.ts +24 -0
- package/dist/trigger/problemBuilder.js +32 -0
- package/dist/trigger/trigger.d.ts +22 -0
- package/dist/trigger/trigger.js +27 -0
- package/dist/trigger/valueModel.d.ts +26 -0
- package/dist/trigger/valueModel.js +25 -0
- package/dist/trigger/wfq.d.ts +13 -0
- package/dist/trigger/wfq.js +25 -0
- package/dist/util/fileLock.d.ts +24 -0
- package/dist/util/fileLock.js +227 -0
- package/dist/util/index.d.ts +2 -0
- package/dist/util/index.js +2 -0
- package/dist/util/version.d.ts +12 -0
- package/dist/util/version.js +51 -0
- package/dist/verify/index.d.ts +4 -0
- package/dist/verify/index.js +4 -0
- package/dist/verify/rollback.d.ts +22 -0
- package/dist/verify/rollback.js +33 -0
- package/dist/verify/sandboxRunner.d.ts +39 -0
- package/dist/verify/sandboxRunner.js +116 -0
- package/dist/verify/sandboxedValidation.d.ts +35 -0
- package/dist/verify/sandboxedValidation.js +56 -0
- package/dist/verify/validation.d.ts +41 -0
- package/dist/verify/validation.js +85 -0
- package/dist/wire/canonicalize.golden.d.ts +23 -0
- package/dist/wire/canonicalize.golden.js +46 -0
- package/dist/wire/geneHints.d.ts +64 -0
- package/dist/wire/geneHints.js +100 -0
- package/dist/wire/index.d.ts +91 -0
- package/dist/wire/index.js +3 -0
- package/dist/wire/schemaGate.d.ts +11 -0
- package/dist/wire/schemaGate.js +49 -0
- package/dist/workflow/dsl.d.ts +54 -0
- package/dist/workflow/dsl.js +15 -0
- package/dist/workflow/engine.d.ts +30 -0
- package/dist/workflow/engine.js +94 -0
- package/dist/workflow/index.d.ts +2 -0
- package/dist/workflow/index.js +2 -0
- package/package.json +29 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { StrategyPoint } from '../strategy/strategyPoint.js';
|
|
2
|
+
import { geneHealthScore, HEALTH_WEIGHTS_VERSION } from './geneHealth.js';
|
|
3
|
+
import { tagOverlapScore, bagCosine } from '../signals/expand.js';
|
|
4
|
+
import { driftSelect } from './exploration.js';
|
|
5
|
+
import { isDistilledGeneId } from './geneIntake.js';
|
|
6
|
+
function decisionWithWarnings(input, decision) {
|
|
7
|
+
return input.antiWarnings && input.antiWarnings.length > 0
|
|
8
|
+
? { ...decision, antiWarnings: [...input.antiWarnings] }
|
|
9
|
+
: decision;
|
|
10
|
+
}
|
|
11
|
+
function signalMatchScore(signals, match) {
|
|
12
|
+
if (signals.length === 0 || match.length === 0)
|
|
13
|
+
return 0;
|
|
14
|
+
const set = new Set(signals);
|
|
15
|
+
const hit = match.filter((m) => set.has(m)).length;
|
|
16
|
+
return hit / match.length; // 覆盖率
|
|
17
|
+
}
|
|
18
|
+
// Weight of the bag-of-words cosine path when it fills the recall gap left by literal + tag overlap.
|
|
19
|
+
const SEMANTIC_WEIGHT = 0.5;
|
|
20
|
+
/**
|
|
21
|
+
* Weight of the preferred-gene confidence factor (fourth factor, positive cross-cycle learning). Kept small so
|
|
22
|
+
* it only re-orders near-ties between already-eligible candidates rather than overriding health / signal match.
|
|
23
|
+
*/
|
|
24
|
+
export const CONFIDENCE_WEIGHT = 0.15;
|
|
25
|
+
/**
|
|
26
|
+
* Weight of the cross-runtime reuse-sentiment factor (#268 phase 1). Deliberately SMALLER than CONFIDENCE_WEIGHT:
|
|
27
|
+
* a self-reported reuse outcome is weaker evidence than the confidence sidecar (which is built from verified cycle
|
|
28
|
+
* history), so it only re-orders near-ties. Clamped to a [-1,1] sentiment, so its contribution is bounded to
|
|
29
|
+
* ±REUSE_WEIGHT and can never dominate health/signal-match.
|
|
30
|
+
*/
|
|
31
|
+
export const REUSE_WEIGHT = 0.1;
|
|
32
|
+
/**
|
|
33
|
+
* Version of the full engine-health weight vector (health 0.6 + signal-match 0.4 − epigenetic penalty
|
|
34
|
+
* + CONFIDENCE_WEIGHT × confidence + REUSE_WEIGHT × reuse-sentiment). Bumped whenever a factor is added so golden
|
|
35
|
+
* weight snapshots track the change. Composed from the health-weights version so a change to either layer shows.
|
|
36
|
+
*/
|
|
37
|
+
export const SELECTION_WEIGHTS_VERSION = `sel-3(${HEALTH_WEIGHTS_VERSION},conf=${CONFIDENCE_WEIGHT},reuse=${REUSE_WEIGHT})`;
|
|
38
|
+
/**
|
|
39
|
+
* Match score with semantic signal expansion (ported from v1): literal coverage first, then fill the
|
|
40
|
+
* recall gap with semantic tag overlap, then with bag-of-words cosine similarity. A perfect literal match
|
|
41
|
+
* short-circuits to 1; otherwise tag overlap adds partial credit (so a '429' signal can reach a gene tagged
|
|
42
|
+
* for 'repair'), and cosine catches lexical similarity the curated tags miss (e.g. a 'timeout_slow' signal
|
|
43
|
+
* vs a gene summarized "fix the slow timeout"). Each layer only fills the gap the previous one left.
|
|
44
|
+
*/
|
|
45
|
+
function expandedMatchScore(signals, c) {
|
|
46
|
+
const literal = signalMatchScore(signals, c.signalsMatch);
|
|
47
|
+
if (literal >= 1)
|
|
48
|
+
return { score: 1, literal, tag: 0, cos: 0 };
|
|
49
|
+
const tag = tagOverlapScore(signals, { signalsMatch: c.signalsMatch, geneId: c.geneId, category: c.category, summary: c.summary });
|
|
50
|
+
const base = Math.min(1, literal + (1 - literal) * tag);
|
|
51
|
+
if (base >= 1)
|
|
52
|
+
return { score: 1, literal, tag, cos: 0 };
|
|
53
|
+
const geneText = [...c.signalsMatch, c.category ?? '', c.summary ?? ''].join(' ');
|
|
54
|
+
const cos = bagCosine(signals.join(' '), geneText);
|
|
55
|
+
return { score: Math.min(1, base + (1 - base) * cos * SEMANTIC_WEIGHT), literal, tag, cos };
|
|
56
|
+
}
|
|
57
|
+
/** Score one candidate under the engine-health weight vector (health 0.6 + 信号匹配 0.4 − epigenetic + confidence). */
|
|
58
|
+
function scoreCandidate(signals, c) {
|
|
59
|
+
const health = geneHealthScore(c.view, { reuseCount: c.reuseCount, antiPatternCount: c.antiPatternCount });
|
|
60
|
+
const m = expandedMatchScore(signals, c);
|
|
61
|
+
const epi = c.epigeneticPenalty ?? 0;
|
|
62
|
+
// Confidence is the fourth (positive) factor: a [0,1] preferred-gene edge for this signal fingerprint.
|
|
63
|
+
// Clamped defensively so an upstream bug cannot turn the soft nudge into a dominant term.
|
|
64
|
+
const conf = Math.max(0, Math.min(1, c.confidence ?? 0));
|
|
65
|
+
// Cross-runtime reuse sentiment (#268 phase 1): clamped to [-1,1] so an upstream bug cannot turn the soft nudge
|
|
66
|
+
// into a dominant (or unbounded) term. Absent → 0 → no effect (default-off until a caller injects it).
|
|
67
|
+
const reuse = Math.max(-1, Math.min(1, c.reuseAdjust ?? 0));
|
|
68
|
+
const score = 0.6 * health.score + 0.4 * m.score - epi + CONFIDENCE_WEIGHT * conf + REUSE_WEIGHT * reuse;
|
|
69
|
+
const breakdown = m.tag > 0 || m.cos > 0 ? `(literal=${m.literal.toFixed(2)}+tag=${m.tag.toFixed(2)}+cos=${m.cos.toFixed(2)})` : '';
|
|
70
|
+
const reasons = [`health=${health.score.toFixed(3)}(succ=${health.successRate.toFixed(2)},reuse=${health.reuseCount})`, `信号匹配=${m.score.toFixed(2)}${breakdown}`];
|
|
71
|
+
if (epi > 0)
|
|
72
|
+
reasons.push(`epigenetic 环境抑制 -${epi.toFixed(2)}`);
|
|
73
|
+
if (conf > 0)
|
|
74
|
+
reasons.push(`preferred-gene confidence +${(CONFIDENCE_WEIGHT * conf).toFixed(3)} (conf=${conf.toFixed(2)})`);
|
|
75
|
+
if (reuse !== 0)
|
|
76
|
+
reasons.push(`cross-runtime reuse ${reuse >= 0 ? '+' : ''}${(REUSE_WEIGHT * reuse).toFixed(3)} (sentiment=${reuse.toFixed(2)})`);
|
|
77
|
+
return { geneId: c.geneId, ...(c.assetId ? { assetId: c.assetId } : {}), score, health, reasons };
|
|
78
|
+
}
|
|
79
|
+
function matchesForcedGeneId(c, forcedGeneId) {
|
|
80
|
+
return c.geneId === forcedGeneId || c.assetId === forcedGeneId;
|
|
81
|
+
}
|
|
82
|
+
function matchesCandidateIdentity(s, c) {
|
|
83
|
+
return c.assetId ? s.assetId === c.assetId : s.geneId === c.geneId;
|
|
84
|
+
}
|
|
85
|
+
function matchesScoredIdentity(a, b) {
|
|
86
|
+
return b.assetId ? a.assetId === b.assetId : a.geneId === b.geneId;
|
|
87
|
+
}
|
|
88
|
+
function withoutCandidateIdentity(scored, c) {
|
|
89
|
+
return scored.filter((s) => !matchesCandidateIdentity(s, c));
|
|
90
|
+
}
|
|
91
|
+
function forcedSelection(input, scored, scoreForcedFallback, floor) {
|
|
92
|
+
const forcedGeneId = input.forcedGeneId?.trim();
|
|
93
|
+
if (!forcedGeneId)
|
|
94
|
+
return { scoredForChoice: scored };
|
|
95
|
+
const source = input.candidates.find((c) => matchesForcedGeneId(c, forcedGeneId));
|
|
96
|
+
if (source) {
|
|
97
|
+
const forced = scored.find((s) => matchesCandidateIdentity(s, source));
|
|
98
|
+
if (!forced)
|
|
99
|
+
return { scoredForChoice: scored };
|
|
100
|
+
if ((source.epigeneticPenalty ?? 0) > 0) {
|
|
101
|
+
forced.reasons.push('forced gene rejected: epigenetic suppression');
|
|
102
|
+
return { scoredForChoice: withoutCandidateIdentity(scored, source), forceRejected: true };
|
|
103
|
+
}
|
|
104
|
+
forced.reasons.push(`forced gene selected: explicit forcedGeneId matched assembled candidate (${forcedGeneId})`);
|
|
105
|
+
if (floor !== undefined && forced.score <= floor)
|
|
106
|
+
forced.reasons.push(`forced gene selected despite floor ${floor}`);
|
|
107
|
+
return { selectedGeneId: source.geneId, ...(source.assetId ? { selectedAssetId: source.assetId } : {}), scoredForChoice: scored };
|
|
108
|
+
}
|
|
109
|
+
const fallback = (input.distilledFallback ?? []).find((c) => matchesForcedGeneId(c, forcedGeneId));
|
|
110
|
+
if (!fallback)
|
|
111
|
+
return { scoredForChoice: scored };
|
|
112
|
+
const scoredCandidatesOnly = scored.slice();
|
|
113
|
+
const forcedFallback = scoreForcedFallback(fallback);
|
|
114
|
+
scored.push(forcedFallback);
|
|
115
|
+
if ((fallback.epigeneticPenalty ?? 0) > 0) {
|
|
116
|
+
forcedFallback.reasons.push('forced gene rejected: epigenetic suppression');
|
|
117
|
+
return { scoredForChoice: scoredCandidatesOnly, forceRejected: true };
|
|
118
|
+
}
|
|
119
|
+
if (!isDistilledGeneId(fallback.geneId)) {
|
|
120
|
+
forcedFallback.reasons.push('forced gene rejected: suppressed fallback');
|
|
121
|
+
return { scoredForChoice: scoredCandidatesOnly, forceRejected: true };
|
|
122
|
+
}
|
|
123
|
+
forcedFallback.reasons.push(`forced gene selected: explicit forcedGeneId matched assembled distilled fallback (${forcedGeneId})`);
|
|
124
|
+
if (floor !== undefined && forcedFallback.score <= floor)
|
|
125
|
+
forcedFallback.reasons.push(`forced gene selected despite floor ${floor}`);
|
|
126
|
+
return { selectedGeneId: fallback.geneId, ...(fallback.assetId ? { selectedAssetId: fallback.assetId } : {}), scoredForChoice: scoredCandidatesOnly };
|
|
127
|
+
}
|
|
128
|
+
/** 实现1: engine 健康分主导(health 0.6 + 信号匹配 0.4). */
|
|
129
|
+
export const engineHealthSelection = {
|
|
130
|
+
name: 'engine-health',
|
|
131
|
+
version: '1',
|
|
132
|
+
run(input, ctx) {
|
|
133
|
+
const scored = input.candidates.map((c) => scoreCandidate(input.signals, c)).sort((a, b) => b.score - a.score);
|
|
134
|
+
const floor = input.floor ?? 0;
|
|
135
|
+
const forced = forcedSelection(input, scored, (c) => scoreCandidate(input.signals, c), floor);
|
|
136
|
+
const eligible = forced.scoredForChoice.filter((s) => s.score > floor);
|
|
137
|
+
// Deterministic top by default; exploration drift picks from the top-N to escape local optima.
|
|
138
|
+
const drift = driftSelect(eligible.length, input.exploration, ctx?.rng ?? Math.random);
|
|
139
|
+
const chosen = eligible[drift.index] ?? eligible[0];
|
|
140
|
+
let selectedGeneId = forced.selectedGeneId ?? (chosen ? chosen.geneId : null);
|
|
141
|
+
let selectedAssetId = forced.selectedAssetId ?? chosen?.assetId;
|
|
142
|
+
if (!selectedGeneId) {
|
|
143
|
+
// Issue #97 (ported from v1 selector.js): no candidate matched any live signal (every gene scored <= 0). Rather
|
|
144
|
+
// than fall straight through to a blind innovate, reuse a *distilled* gene if one is available. NB the prefix
|
|
145
|
+
// does NOT mean "skill-derived" in v2 the way it did in v1: v1 tagged only skill genes gene_distilled_ (auto-
|
|
146
|
+
// evolved genes were gene_auto_), but v2's intakeGene tags EVERY intaken gene gene_distilled_ (autoExec even
|
|
147
|
+
// intakes task strategies that way) and has no gene_auto_. So this pool is "any trusted/approved/non-suppressed
|
|
148
|
+
// pooled gene that does not match", not specifically skill-derived — the safety rests on the upstream gates
|
|
149
|
+
// (trust #30 / review #89-91 / signal-ban / inert-ban #195) plus the epigenetic skip below, not on a skill-
|
|
150
|
+
// provenance low-blast-radius assumption. We skip any distilled fallback epigenetically suppressed in this env;
|
|
151
|
+
// v2's event-log-derived epigeneticPenalty is the analog of v1's asset-mark hard suppression (related band, not
|
|
152
|
+
// the identical predicate). No usable distilled fallback → stay null so the caller still innovates (the contract).
|
|
153
|
+
//
|
|
154
|
+
// v1 #97 parity: the distilled fallback is a *no-signal-match* last resort — it must fire only when NOTHING
|
|
155
|
+
// scored above zero, NOT merely when nothing cleared a positive `floor`. Otherwise a real but weak signal match
|
|
156
|
+
// (0 < score <= floor) would be preempted by an unrelated zero-evidence distilled gene; V1 (which has no floor)
|
|
157
|
+
// keeps such a match. When candidates scored > 0 but below floor, defer to V2's floor policy (innovate).
|
|
158
|
+
const noSignalMatch = !forced.forceRejected && forced.scoredForChoice.every((s) => s.score <= 0);
|
|
159
|
+
const fb = noSignalMatch
|
|
160
|
+
? (input.distilledFallback ?? []).find((c) => isDistilledGeneId(c.geneId) && (c.epigeneticPenalty ?? 0) === 0)
|
|
161
|
+
: undefined;
|
|
162
|
+
if (fb) {
|
|
163
|
+
const fbScored = scoreCandidate(input.signals, fb);
|
|
164
|
+
fbScored.reasons.push('distilled_fallback(#97): 无信号匹配, 低置信度复用蒸馏 gene');
|
|
165
|
+
scored.push(fbScored);
|
|
166
|
+
selectedGeneId = fb.geneId;
|
|
167
|
+
selectedAssetId = fb.assetId;
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
forced.scoredForChoice.forEach((s) => s.reasons.push(`< floor ${floor} → innovate`));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
else if (forced.selectedGeneId === undefined && drift.driftMode !== 'deterministic') {
|
|
174
|
+
scored.find((s) => s.geneId === selectedGeneId)?.reasons.push(`drift(${drift.driftMode},intensity=${drift.intensity.toFixed(2)})`);
|
|
175
|
+
}
|
|
176
|
+
return decisionWithWarnings(input, { selectedGeneId, ...(selectedAssetId ? { selectedAssetId } : {}), candidates: scored, weightsVersion: SELECTION_WEIGHTS_VERSION, strategyName: 'engine-health' });
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
/** 实现2: 纯信号匹配采样(忽略 health, 对照基线 — 经验主义要可对比). */
|
|
180
|
+
export const signalMatchSelection = {
|
|
181
|
+
name: 'signal-match',
|
|
182
|
+
version: '1',
|
|
183
|
+
run(input) {
|
|
184
|
+
const scoreSignalCandidate = (c) => ({
|
|
185
|
+
geneId: c.geneId, ...(c.assetId ? { assetId: c.assetId } : {}), score: signalMatchScore(input.signals, c.signalsMatch),
|
|
186
|
+
reasons: [`纯信号匹配=${signalMatchScore(input.signals, c.signalsMatch).toFixed(2)}`],
|
|
187
|
+
});
|
|
188
|
+
const scored = input.candidates.map((c) => scoreSignalCandidate(c)).sort((a, b) => b.score - a.score);
|
|
189
|
+
const forced = forcedSelection(input, scored, scoreSignalCandidate, input.floor ?? 0);
|
|
190
|
+
const top = forced.scoredForChoice[0];
|
|
191
|
+
const selectedGeneId = forced.selectedGeneId ?? (top && top.score > (input.floor ?? 0) ? top.geneId : null);
|
|
192
|
+
const selectedAssetId = forced.selectedAssetId ?? (selectedGeneId === top?.geneId ? top.assetId : undefined);
|
|
193
|
+
return decisionWithWarnings(input, {
|
|
194
|
+
selectedGeneId,
|
|
195
|
+
...(selectedAssetId ? { selectedAssetId } : {}),
|
|
196
|
+
candidates: scored, weightsVersion: 'none', strategyName: 'signal-match',
|
|
197
|
+
});
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
/** 实现3: agent 主导(注入决策回调; engine 只给候选+分, agent 拍板, D26 agent 一等公民). */
|
|
201
|
+
export function agentLedSelection(pick) {
|
|
202
|
+
return {
|
|
203
|
+
name: 'agent-led',
|
|
204
|
+
version: '1',
|
|
205
|
+
run(input, ctx) {
|
|
206
|
+
const baseDecision = engineHealthSelection.run(input, ctx);
|
|
207
|
+
const base = baseDecision.candidates;
|
|
208
|
+
const forced = input.forcedGeneId ? base.find((s) => s.reasons.some((r) => r.includes('forced gene'))) : undefined;
|
|
209
|
+
if (forced?.reasons.some((r) => r.includes('forced gene selected'))) {
|
|
210
|
+
return decisionWithWarnings(input, { selectedGeneId: forced.geneId, ...(forced.assetId ? { selectedAssetId: forced.assetId } : {}), candidates: base, weightsVersion: SELECTION_WEIGHTS_VERSION, strategyName: 'agent-led' });
|
|
211
|
+
}
|
|
212
|
+
const candidatesForPick = forced?.reasons.some((r) => r.includes('forced gene rejected')) ? base.filter((s) => !matchesScoredIdentity(s, forced)) : base;
|
|
213
|
+
const choice = pick(candidatesForPick, input);
|
|
214
|
+
const selected = candidatesForPick.find((s) => s.geneId === choice) ?? base.find((s) => s.geneId === choice);
|
|
215
|
+
return decisionWithWarnings(input, { selectedGeneId: choice, ...(selected?.assetId ? { selectedAssetId: selected.assetId } : {}), candidates: base, weightsVersion: SELECTION_WEIGHTS_VERSION, strategyName: 'agent-led' });
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
/** 选 gene StrategyPoint: 默认 engine-health, 备选 signal-match(+ 可注册 agent-led). */
|
|
220
|
+
export function makeGeneSelectionPoint() {
|
|
221
|
+
return new StrategyPoint('gene-selection', engineHealthSelection).register(signalMatchSelection);
|
|
222
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export * from './geneHealth.js';
|
|
2
|
+
export * from './exploration.js';
|
|
3
|
+
export * from './epigenetics.js';
|
|
4
|
+
export * from './confidence.js';
|
|
5
|
+
export * from './capabilityCandidates.js';
|
|
6
|
+
export * from './geneIntake.js';
|
|
7
|
+
export * from './candidateAssembly.js';
|
|
8
|
+
export * from './genePromotion.js';
|
|
9
|
+
export * from './bans.js';
|
|
10
|
+
export * from './antiDistill.js';
|
|
11
|
+
export * from './orchestrator.js';
|
|
12
|
+
export * from './geneSelection.js';
|
|
13
|
+
export * from './mutation.js';
|
|
14
|
+
export * from './solidify.js';
|
|
15
|
+
export * from './evolutionEvent.js';
|
|
16
|
+
export * from './cycleEngine.js';
|
|
17
|
+
export * from './strategyPresets.js';
|
|
18
|
+
export * from './cycleFailureClassifier.js';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export * from './geneHealth.js';
|
|
2
|
+
export * from './exploration.js';
|
|
3
|
+
export * from './epigenetics.js';
|
|
4
|
+
export * from './confidence.js';
|
|
5
|
+
export * from './capabilityCandidates.js';
|
|
6
|
+
export * from './geneIntake.js';
|
|
7
|
+
export * from './candidateAssembly.js';
|
|
8
|
+
export * from './genePromotion.js';
|
|
9
|
+
export * from './bans.js';
|
|
10
|
+
export * from './antiDistill.js';
|
|
11
|
+
export * from './orchestrator.js';
|
|
12
|
+
export * from './geneSelection.js';
|
|
13
|
+
export * from './mutation.js';
|
|
14
|
+
export * from './solidify.js';
|
|
15
|
+
export * from './evolutionEvent.js';
|
|
16
|
+
export * from './cycleEngine.js';
|
|
17
|
+
export * from './strategyPresets.js';
|
|
18
|
+
export * from './cycleFailureClassifier.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { GepCategory, Mutation } from '../wire/index.js';
|
|
2
|
+
import type { GeneDecision } from './geneSelection.js';
|
|
3
|
+
export interface BuildMutationInput {
|
|
4
|
+
decision: GeneDecision;
|
|
5
|
+
category: GepCategory;
|
|
6
|
+
signals: readonly string[];
|
|
7
|
+
target: string;
|
|
8
|
+
expectedEffect: string;
|
|
9
|
+
riskOverride?: Mutation['risk_level'];
|
|
10
|
+
}
|
|
11
|
+
/** 由选择决策构造 Mutation(瞬态, 不落资产库; 进 root_events). */
|
|
12
|
+
export declare function buildMutation(input: BuildMutationInput): Mutation;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ulid as makeUlid } from 'ulid';
|
|
2
|
+
/** category → 基线风险(innovate/explore 改动开放面大, repair 收敛). 选不到 gene(innovate)再升一档. */
|
|
3
|
+
function baselineRisk(category, noGene) {
|
|
4
|
+
if (category === 'innovate' || category === 'explore')
|
|
5
|
+
return 'high';
|
|
6
|
+
if (noGene)
|
|
7
|
+
return 'medium'; // 无现成 gene = 新路径
|
|
8
|
+
return category === 'repair' ? 'low' : 'medium';
|
|
9
|
+
}
|
|
10
|
+
/** 由选择决策构造 Mutation(瞬态, 不落资产库; 进 root_events). */
|
|
11
|
+
export function buildMutation(input) {
|
|
12
|
+
const noGene = input.decision.selectedGeneId === null;
|
|
13
|
+
return {
|
|
14
|
+
type: 'Mutation',
|
|
15
|
+
id: makeUlid(),
|
|
16
|
+
category: input.category,
|
|
17
|
+
trigger_signals: [...input.signals],
|
|
18
|
+
target: input.target,
|
|
19
|
+
expected_effect: input.expectedEffect,
|
|
20
|
+
risk_level: input.riskOverride ?? baselineRisk(input.category, noGene),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { AssetStoreProvider } from '../assetstore/provider.js';
|
|
2
|
+
import type { ProvenanceStore } from '../assetstore/provenance.js';
|
|
3
|
+
import type { ReviewLedger } from '../assetstore/reviewLedger.js';
|
|
4
|
+
import type { GepCategory } from '../wire/index.js';
|
|
5
|
+
import type { ProblemPattern } from '../schema/problem.js';
|
|
6
|
+
import type { GeneCandidateInput } from './geneSelection.js';
|
|
7
|
+
import { CycleEngine, type CycleInput, type CycleResult, type SolidifyPermitGate } from './cycleEngine.js';
|
|
8
|
+
import { type PendingSignalsContext } from '../assetstore/pendingSignals.js';
|
|
9
|
+
import { type ReuseOutcomeSummary, type ReuseOutcomeEvent } from '../ops/reuseOutcomes.js';
|
|
10
|
+
export interface RunCycleOptions {
|
|
11
|
+
cycleId: string;
|
|
12
|
+
problem: ProblemPattern;
|
|
13
|
+
signals: readonly string[];
|
|
14
|
+
category: GepCategory;
|
|
15
|
+
/** Optional explicit strategy preset name forwarded to CycleEngine. */
|
|
16
|
+
strategyName?: string;
|
|
17
|
+
target: string;
|
|
18
|
+
expectedEffect: string;
|
|
19
|
+
summary: string;
|
|
20
|
+
confidence: number;
|
|
21
|
+
selectionFloor?: number;
|
|
22
|
+
/** Optional explicit gene chosen by GEP / an external runtime; forwarded to CycleEngine after assembly. */
|
|
23
|
+
forcedGeneId?: string;
|
|
24
|
+
/** The agent runtime's work: run the mutation, return the outcome. */
|
|
25
|
+
execute: CycleInput['execute'];
|
|
26
|
+
/** Optional triage context forwarded to CycleEngine for cycle.failed classification. */
|
|
27
|
+
failureContext?: CycleInput['failureContext'];
|
|
28
|
+
/** Optional adapter/runtime permit gate. Runs after execute succeeds and before solidify writes assets. */
|
|
29
|
+
solidifyPermit?: SolidifyPermitGate;
|
|
30
|
+
/** Cap on how many genes are pulled from the store as candidates. */
|
|
31
|
+
candidateLimit?: number;
|
|
32
|
+
/** Trust-first selection (#30): exclude hub-ingested genes unless promoted. */
|
|
33
|
+
provenance?: ProvenanceStore;
|
|
34
|
+
/** Review-first selection (#89/#91): exclude quarantined/rejected auto-distilled drafts. */
|
|
35
|
+
review?: ReviewLedger;
|
|
36
|
+
/** Probation (#306, gated): let a quarantined draft be TRIED to earn evidence (rejected stays out). Default off. */
|
|
37
|
+
includeProbation?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Reuse-before-solve hub candidates (#110): already-resolved hub assets (the adapter's free search →
|
|
40
|
+
* pure score → paid fetch flow) injected to compete in the SAME selection pool as local genes. Core stays
|
|
41
|
+
* hub-agnostic — it only forwards these into assembleCandidates, which merges them trust-first (a geneId
|
|
42
|
+
* colliding with a trusted local gene keeps the local one). Omit (the default) → no hub candidates → exactly
|
|
43
|
+
* today's behavior. The hub call/billing/cache all live in the adapter; this is the in-cycle injection point.
|
|
44
|
+
*/
|
|
45
|
+
hubCandidates?: readonly GeneCandidateInput[];
|
|
46
|
+
/** Optional v1-compatible pending_signals.json path context. */
|
|
47
|
+
pendingSignalsContext?: PendingSignalsContext;
|
|
48
|
+
/** Disable only when the caller already consumed pending_signals.json before invoking this cycle. */
|
|
49
|
+
consumePendingSignals?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Cross-runtime reuse-outcome summary (#268 phase 1): when provided, it is mapped to a per-gene sentiment that
|
|
52
|
+
* SOFTLY re-orders selection (down-rank genes foreign agents keep finding unhelpful, up-rank ones they reuse
|
|
53
|
+
* successfully). Omit (the default) → no reuse re-order → exactly today's behavior. The signal is computed by
|
|
54
|
+
* the composition layer from reuse-outcome events; core just folds it into the selection pool here.
|
|
55
|
+
*/
|
|
56
|
+
reuseOutcomes?: ReuseOutcomeSummary;
|
|
57
|
+
/**
|
|
58
|
+
* Observed `value.recall` events (#274 slice 3): folded into the same soft re-order as reuse outcomes, at a lower
|
|
59
|
+
* weight (RECALL_WEIGHT) — `used` nudges up, `unused` nudges down. This is how transcript-OBSERVED recall (not
|
|
60
|
+
* agent self-report) gains teeth on selection. Omit → no recall contribution. Never feeds quarantine.
|
|
61
|
+
*/
|
|
62
|
+
recallEvents?: readonly ReuseOutcomeEvent[];
|
|
63
|
+
}
|
|
64
|
+
/** Drive one full evolution cycle end-to-end: assemble candidates from the store, then run the cycle. */
|
|
65
|
+
export declare function runEvolutionCycle(engine: CycleEngine, store: AssetStoreProvider, opts: RunCycleOptions): Promise<CycleResult>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { CycleEngine } from './cycleEngine.js';
|
|
2
|
+
import { assembleSelectionPool } from './candidateAssembly.js';
|
|
3
|
+
import { mergePendingSignalsForStore } from '../assetstore/pendingSignals.js';
|
|
4
|
+
import { reuseCountsFromSummary, recallCountsFromEvents } from '../ops/reuseOutcomes.js';
|
|
5
|
+
/** Drive one full evolution cycle end-to-end: assemble candidates from the store, then run the cycle. */
|
|
6
|
+
export async function runEvolutionCycle(engine, store, opts) {
|
|
7
|
+
let signals = [...opts.signals];
|
|
8
|
+
if (opts.consumePendingSignals !== false) {
|
|
9
|
+
try {
|
|
10
|
+
const explicit = mergePendingSignalsForStore(store, opts.signals, opts.pendingSignalsContext);
|
|
11
|
+
signals = explicit.signals;
|
|
12
|
+
if (explicit.injected > 0) {
|
|
13
|
+
console.log(`[ExplicitSignals] Injected ${explicit.injected} user-declared signal(s) from pending_signals.json.`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
18
|
+
console.warn(`[ExplicitSignals] Failed to consume pending signals (non-fatal): ${message}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// #268 phase 1 + #274 slice 3: fold cross-runtime reuse counts AND observed recall into the pool (soft re-order).
|
|
22
|
+
// Absent both → no map → default-off. Recall is folded at a lower weight (RECALL_WEIGHT). Assembly sums a gene's
|
|
23
|
+
// ids → sentiment; bounded + clamped in geneSelection; the hard trust/review/ban gates in assembly run first.
|
|
24
|
+
const reuseCounts = opts.reuseOutcomes ? reuseCountsFromSummary(opts.reuseOutcomes) : new Map();
|
|
25
|
+
if (opts.recallEvents && opts.recallEvents.length > 0) {
|
|
26
|
+
for (const [id, rc] of recallCountsFromEvents(opts.recallEvents)) {
|
|
27
|
+
const c = reuseCounts.get(id) ?? { success: 0, negative: 0 };
|
|
28
|
+
c.success += rc.success;
|
|
29
|
+
c.negative += rc.negative;
|
|
30
|
+
reuseCounts.set(id, c);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const asmOpts = {
|
|
34
|
+
...(opts.candidateLimit ? { limit: opts.candidateLimit } : {}),
|
|
35
|
+
...(opts.provenance ? { provenance: opts.provenance } : {}),
|
|
36
|
+
...(opts.review ? { review: opts.review } : {}),
|
|
37
|
+
...(opts.includeProbation ? { includeProbation: true } : {}),
|
|
38
|
+
...(opts.hubCandidates && opts.hubCandidates.length > 0 ? { hubCandidates: opts.hubCandidates } : {}),
|
|
39
|
+
...(reuseCounts.size > 0 ? { reuseCounts } : {}),
|
|
40
|
+
};
|
|
41
|
+
const { candidates, distilledFallback, antiWarnings } = await assembleSelectionPool(store, signals, asmOpts);
|
|
42
|
+
return engine.runCycle({
|
|
43
|
+
cycleId: opts.cycleId,
|
|
44
|
+
problem: opts.problem,
|
|
45
|
+
signals,
|
|
46
|
+
category: opts.category,
|
|
47
|
+
...(opts.strategyName !== undefined ? { strategyName: opts.strategyName } : {}),
|
|
48
|
+
candidates,
|
|
49
|
+
target: opts.target,
|
|
50
|
+
expectedEffect: opts.expectedEffect,
|
|
51
|
+
summary: opts.summary,
|
|
52
|
+
confidence: opts.confidence,
|
|
53
|
+
...(opts.selectionFloor !== undefined ? { selectionFloor: opts.selectionFloor } : {}),
|
|
54
|
+
...(opts.forcedGeneId !== undefined ? { forcedGeneId: opts.forcedGeneId } : {}),
|
|
55
|
+
execute: opts.execute,
|
|
56
|
+
...(opts.failureContext !== undefined ? { failureContext: opts.failureContext } : {}),
|
|
57
|
+
...(opts.solidifyPermit ? { solidifyPermit: opts.solidifyPermit } : {}),
|
|
58
|
+
// #97: forward the distilled-gene fallback pool so a no-signal-match cycle reuses a distilled strategy
|
|
59
|
+
// (instead of a blind innovate) when nothing clears the floor.
|
|
60
|
+
...(distilledFallback.length > 0 ? { distilledFallback } : {}),
|
|
61
|
+
...(antiWarnings.length > 0 ? { antiWarnings } : {}),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type Capsule } from '../wire/index.js';
|
|
2
|
+
import type { ProofOfWork } from '../schema/proofOfWork.js';
|
|
3
|
+
export type ResolutionStatus = 'pending' | 'suppressed_observationally' | 'resolved_by_evidence' | 'regressed' | 'inconclusive';
|
|
4
|
+
export interface SolidifyInput {
|
|
5
|
+
geneId: string;
|
|
6
|
+
trigger: readonly string[];
|
|
7
|
+
summary: string;
|
|
8
|
+
confidence: number;
|
|
9
|
+
outcome: {
|
|
10
|
+
status: 'success' | 'failed';
|
|
11
|
+
score: number;
|
|
12
|
+
};
|
|
13
|
+
proofOfWork?: ProofOfWork;
|
|
14
|
+
/** 是否有强证据(validation/测试在证据下通过). 默认 false → 不自动升级到 resolved. */
|
|
15
|
+
strongEvidence?: boolean;
|
|
16
|
+
/** regressed 判定阈: 失败且分低于此 → regressed, 否则 inconclusive. 默认 0.3. */
|
|
17
|
+
regressThreshold?: number;
|
|
18
|
+
}
|
|
19
|
+
export interface SolidifyResult {
|
|
20
|
+
capsule: Capsule;
|
|
21
|
+
resolutionStatus: ResolutionStatus;
|
|
22
|
+
producedValue: boolean;
|
|
23
|
+
reasons: string[];
|
|
24
|
+
}
|
|
25
|
+
/** ProofOfWork 是否表明有实际产出(解锁非 coding agent, 批注#17/#19). */
|
|
26
|
+
export declare function proofIndicatesOutput(p?: ProofOfWork): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* 两级 resolution(M4A-8) + ProofOfWork 判价值(M4A-5):
|
|
29
|
+
* - 失败: 分 < 阈 → regressed, 否则 inconclusive.
|
|
30
|
+
* - 成功 + 强证据(proofOfWork 有产出 ∧ strongEvidence) → resolved_by_evidence.
|
|
31
|
+
* - 成功但仅观测(无证据) → suppressed_observationally.
|
|
32
|
+
* 默认**不自动**从 suppressed 升级到 resolved(军杰§6).
|
|
33
|
+
*/
|
|
34
|
+
export declare function decideResolution(input: SolidifyInput): {
|
|
35
|
+
status: ResolutionStatus;
|
|
36
|
+
producedValue: boolean;
|
|
37
|
+
reasons: string[];
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* solidify: 把执行结果固化成 Capsule(表现型/纯产物). resolution_status/proof_of_work 是 v2-delta
|
|
41
|
+
* (本地存得下; 发 hub 须先 gep-sdk bump, 由 wire/schemaGate 把关).
|
|
42
|
+
*/
|
|
43
|
+
export declare function solidify(input: SolidifyInput): SolidifyResult;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { ulid as makeUlid } from 'ulid';
|
|
2
|
+
import { computeAssetId, SCHEMA_VERSION } from '../wire/index.js';
|
|
3
|
+
/** ProofOfWork 是否表明有实际产出(解锁非 coding agent, 批注#17/#19). */
|
|
4
|
+
export function proofIndicatesOutput(p) {
|
|
5
|
+
if (!p)
|
|
6
|
+
return false;
|
|
7
|
+
switch (p.kind) {
|
|
8
|
+
case 'git_diff': return (p.gitDiff?.files ?? 0) > 0 || (p.gitDiff?.lines ?? 0) > 0;
|
|
9
|
+
case 'artifact_hash': return Boolean(p.artifactHash?.sha256);
|
|
10
|
+
case 'external_receipt': return Boolean(p.externalReceipt?.receiptId);
|
|
11
|
+
case 'tool_call_trace': return (p.toolCallTrace?.calls ?? 0) > 0;
|
|
12
|
+
default: return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 两级 resolution(M4A-8) + ProofOfWork 判价值(M4A-5):
|
|
17
|
+
* - 失败: 分 < 阈 → regressed, 否则 inconclusive.
|
|
18
|
+
* - 成功 + 强证据(proofOfWork 有产出 ∧ strongEvidence) → resolved_by_evidence.
|
|
19
|
+
* - 成功但仅观测(无证据) → suppressed_observationally.
|
|
20
|
+
* 默认**不自动**从 suppressed 升级到 resolved(军杰§6).
|
|
21
|
+
*/
|
|
22
|
+
export function decideResolution(input) {
|
|
23
|
+
const reasons = [];
|
|
24
|
+
const producedValue = proofIndicatesOutput(input.proofOfWork);
|
|
25
|
+
if (input.outcome.status === 'failed') {
|
|
26
|
+
const status = input.outcome.score < (input.regressThreshold ?? 0.3) ? 'regressed' : 'inconclusive';
|
|
27
|
+
reasons.push(`失败 score=${input.outcome.score} → ${status}`);
|
|
28
|
+
return { status, producedValue, reasons };
|
|
29
|
+
}
|
|
30
|
+
if (producedValue && input.strongEvidence) {
|
|
31
|
+
reasons.push('成功 + ProofOfWork 有产出 + 强证据 → resolved_by_evidence');
|
|
32
|
+
return { status: 'resolved_by_evidence', producedValue, reasons };
|
|
33
|
+
}
|
|
34
|
+
reasons.push(producedValue ? '成功 + 有产出但无强证据 → suppressed_observationally(不自动升级)' : '成功但无 ProofOfWork 产出证据 → suppressed_observationally');
|
|
35
|
+
return { status: 'suppressed_observationally', producedValue, reasons };
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* solidify: 把执行结果固化成 Capsule(表现型/纯产物). resolution_status/proof_of_work 是 v2-delta
|
|
39
|
+
* (本地存得下; 发 hub 须先 gep-sdk bump, 由 wire/schemaGate 把关).
|
|
40
|
+
*/
|
|
41
|
+
export function solidify(input) {
|
|
42
|
+
const { status, producedValue, reasons } = decideResolution(input);
|
|
43
|
+
// blast_radius is only a real measurement for git_diff proofs. For non-git_diff proofs
|
|
44
|
+
// (artifact_hash/external_receipt/tool_call_trace) gd is undefined and blast falls back to {0,0} — which here
|
|
45
|
+
// means "blast unknown", NOT "no change". Consumers that read blast=0 as a no-op signal (e.g. cycleFailure's
|
|
46
|
+
// local_gene_no_blast bucket) MUST first confirm the proof kind is git_diff; the cycleEngine guard does this.
|
|
47
|
+
const gd = input.proofOfWork?.kind === 'git_diff' ? input.proofOfWork.gitDiff : undefined;
|
|
48
|
+
const base = {
|
|
49
|
+
type: 'Capsule',
|
|
50
|
+
schema_version: SCHEMA_VERSION,
|
|
51
|
+
id: makeUlid(),
|
|
52
|
+
trigger: [...input.trigger],
|
|
53
|
+
gene: input.geneId,
|
|
54
|
+
summary: input.summary,
|
|
55
|
+
confidence: input.confidence,
|
|
56
|
+
blast_radius: { files: gd?.files ?? 0, lines: gd?.lines ?? 0 },
|
|
57
|
+
outcome: input.outcome,
|
|
58
|
+
resolution_status: status,
|
|
59
|
+
...(input.proofOfWork ? { proof_of_work: input.proofOfWork } : {}),
|
|
60
|
+
};
|
|
61
|
+
const asset_id = computeAssetId(base);
|
|
62
|
+
return { capsule: { ...base, asset_id }, resolutionStatus: status, producedValue, reasons };
|
|
63
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface StrategyPreset {
|
|
2
|
+
name: string;
|
|
3
|
+
label: string;
|
|
4
|
+
description: string;
|
|
5
|
+
/** Target allocation ratios that inform the cycle's intent mix (sum ≈ 1). */
|
|
6
|
+
repair: number;
|
|
7
|
+
optimize: number;
|
|
8
|
+
innovate: number;
|
|
9
|
+
explore: number;
|
|
10
|
+
/** Repair ratio over recent cycles that should force innovation to break a repair loop. */
|
|
11
|
+
repairLoopThreshold: number;
|
|
12
|
+
}
|
|
13
|
+
export declare const STRATEGY_PRESETS: Record<string, StrategyPreset>;
|
|
14
|
+
export declare function strategyNames(): string[];
|
|
15
|
+
export interface ResolveStrategyInput {
|
|
16
|
+
/** Explicit strategy (e.g. EVOLVE_STRATEGY). Undefined / 'balanced' / 'auto' enable auto-detection. */
|
|
17
|
+
name?: string;
|
|
18
|
+
/** Recent signal kinds (for saturation detection). */
|
|
19
|
+
signals?: readonly string[];
|
|
20
|
+
/** Current evolution cycle count (for the early-stabilize heuristic). */
|
|
21
|
+
cycleCount?: number;
|
|
22
|
+
/** Back-compat: forces 'innovate' when no explicit name is set. */
|
|
23
|
+
forceInnovation?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Resolve the active strategy preset. Explicit name wins (unknown → balanced). Otherwise auto-detect:
|
|
27
|
+
* first 1-5 cycles → early-stabilize; an innovate-pivot meta-signal (repair loop / high failure ratio) →
|
|
28
|
+
* innovate; a saturation signal → steady-state (overrides both); forceInnovation → innovate. This is where
|
|
29
|
+
* the history-derived meta-signals (see signals/metaSignals.ts) actually drive strategy adaptation.
|
|
30
|
+
* Pure — no env/fs reads (the caller supplies the inputs).
|
|
31
|
+
*/
|
|
32
|
+
export declare function resolveStrategy(input?: ResolveStrategyInput): StrategyPreset;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Evolution strategy presets (ported from v1 gep/strategy.js). An operator-selectable POSTURE that biases the
|
|
2
|
+
// repair/optimize/innovate/explore mix for a cycle — "harden after a big change", "repair-only emergency",
|
|
3
|
+
// "innovate when stable" — plus a repair-loop threshold. resolveStrategy is pure + fully input-driven (the
|
|
4
|
+
// caller supplies the chosen name, recent signals, and cycle count from env/state); auto-detection picks
|
|
5
|
+
// early-stabilize for the first few cycles and steady-state when saturation signals appear.
|
|
6
|
+
export const STRATEGY_PRESETS = {
|
|
7
|
+
balanced: { name: 'balanced', label: 'Balanced', description: 'Normal operation. Steady growth with stability.', repair: 0.2, optimize: 0.2, innovate: 0.5, explore: 0.1, repairLoopThreshold: 0.5 },
|
|
8
|
+
innovate: { name: 'innovate', label: 'Innovation Focus', description: 'System is stable. Maximize new features and capabilities.', repair: 0.05, optimize: 0.1, innovate: 0.8, explore: 0.05, repairLoopThreshold: 0.3 },
|
|
9
|
+
harden: { name: 'harden', label: 'Hardening', description: 'After a big change. Focus on stability and robustness.', repair: 0.4, optimize: 0.35, innovate: 0.2, explore: 0.05, repairLoopThreshold: 0.7 },
|
|
10
|
+
'repair-only': { name: 'repair-only', label: 'Repair Only', description: 'Emergency. Fix everything before doing anything else.', repair: 0.8, optimize: 0.18, innovate: 0.0, explore: 0.02, repairLoopThreshold: 1.0 },
|
|
11
|
+
'early-stabilize': { name: 'early-stabilize', label: 'Early Stabilization', description: 'First cycles. Prioritize fixing existing issues before innovating.', repair: 0.6, optimize: 0.22, innovate: 0.15, explore: 0.03, repairLoopThreshold: 0.8 },
|
|
12
|
+
'steady-state': { name: 'steady-state', label: 'Steady State', description: 'Evolution saturated. Maintain existing capabilities. Explore for new directions.', repair: 0.55, optimize: 0.25, innovate: 0.05, explore: 0.15, repairLoopThreshold: 0.9 },
|
|
13
|
+
};
|
|
14
|
+
export function strategyNames() {
|
|
15
|
+
return Object.keys(STRATEGY_PRESETS);
|
|
16
|
+
}
|
|
17
|
+
/** Saturation meta-signals that switch auto-detection to steady-state (graceful degradation). */
|
|
18
|
+
const SATURATION_SIGNALS = new Set(['force_steady_state', 'evolution_saturation']);
|
|
19
|
+
/**
|
|
20
|
+
* Meta-signals that mean "stuck repairing / failing — break out by innovating" (ported from v1 strategy.js
|
|
21
|
+
* intent: a repair loop or a high failure ratio should pivot the posture off repair toward new directions).
|
|
22
|
+
* Saturation takes precedence (it wins when both are present, matching v1's steady-state-on-saturation rule).
|
|
23
|
+
*/
|
|
24
|
+
const INNOVATE_PIVOT_SIGNALS = new Set([
|
|
25
|
+
'repair_loop_detected',
|
|
26
|
+
'force_innovation_after_repair_loop',
|
|
27
|
+
'high_failure_ratio',
|
|
28
|
+
]);
|
|
29
|
+
/**
|
|
30
|
+
* Resolve the active strategy preset. Explicit name wins (unknown → balanced). Otherwise auto-detect:
|
|
31
|
+
* first 1-5 cycles → early-stabilize; an innovate-pivot meta-signal (repair loop / high failure ratio) →
|
|
32
|
+
* innovate; a saturation signal → steady-state (overrides both); forceInnovation → innovate. This is where
|
|
33
|
+
* the history-derived meta-signals (see signals/metaSignals.ts) actually drive strategy adaptation.
|
|
34
|
+
* Pure — no env/fs reads (the caller supplies the inputs).
|
|
35
|
+
*/
|
|
36
|
+
export function resolveStrategy(input = {}) {
|
|
37
|
+
const explicit = typeof input.name === 'string' && input.name.trim() !== '';
|
|
38
|
+
let name = (explicit ? input.name : 'balanced').toLowerCase().trim();
|
|
39
|
+
let forceInnovation = false;
|
|
40
|
+
if (!explicit && input.forceInnovation) {
|
|
41
|
+
name = 'innovate';
|
|
42
|
+
forceInnovation = true;
|
|
43
|
+
}
|
|
44
|
+
const isDefault = !explicit || name === 'balanced' || name === 'auto';
|
|
45
|
+
if (isDefault && !forceInnovation) {
|
|
46
|
+
const signals = input.signals ?? [];
|
|
47
|
+
const cycleCount = input.cycleCount ?? 0;
|
|
48
|
+
if (cycleCount > 0 && cycleCount <= 5)
|
|
49
|
+
name = 'early-stabilize';
|
|
50
|
+
// Stuck repairing / failing → pivot to innovate to break the loop (v1 strategy.js intent).
|
|
51
|
+
if (signals.some((s) => INNOVATE_PIVOT_SIGNALS.has(s)))
|
|
52
|
+
name = 'innovate';
|
|
53
|
+
// Saturation → steady-state. Last so it overrides early-stabilize AND the innovate pivot:
|
|
54
|
+
// when the loop has exhausted its innovation space, hardening/maintenance beats more innovation.
|
|
55
|
+
if (signals.some((s) => SATURATION_SIGNALS.has(s)))
|
|
56
|
+
name = 'steady-state';
|
|
57
|
+
}
|
|
58
|
+
if (name === 'auto')
|
|
59
|
+
name = 'balanced';
|
|
60
|
+
return STRATEGY_PRESETS[name] ?? STRATEGY_PRESETS['balanced'];
|
|
61
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './provider.js';
|
|
2
|
+
export * from './localJsonl.js';
|
|
3
|
+
export * from './remoteStub.js';
|
|
4
|
+
export * from './learningHistory.js';
|
|
5
|
+
export * from './provenance.js';
|
|
6
|
+
export * from './reviewLedger.js';
|
|
7
|
+
export * from './reviewFilter.js';
|
|
8
|
+
export * from './pendingSignals.js';
|