@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,137 @@
|
|
|
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 { GeneCandidateInput } from '../algo/geneSelection.js';
|
|
5
|
+
import type { CycleEngine, SolidifyPermitGate } from '../algo/cycleEngine.js';
|
|
6
|
+
import { type AutonomousSafety } from './autonomousCycle.js';
|
|
7
|
+
import type { GitRunner, ValidateHook } from './claudeBridge.js';
|
|
8
|
+
import type { AgentRunner } from './runnerRegistry.js';
|
|
9
|
+
import { type OpenPrLister } from './openPrRegistry.js';
|
|
10
|
+
import type { ReuseOutcomeSummary, ReuseOutcomeEvent } from '../ops/reuseOutcomes.js';
|
|
11
|
+
import type { PersonalityStore } from '../personality/store.js';
|
|
12
|
+
export interface AutoExecTask {
|
|
13
|
+
id: string;
|
|
14
|
+
repo: string;
|
|
15
|
+
target: string;
|
|
16
|
+
expectedEffect: string;
|
|
17
|
+
/** Explicit opt-in public context safe to send to the public Hub question generator. */
|
|
18
|
+
publicQuestionContext?: string;
|
|
19
|
+
signals: readonly string[];
|
|
20
|
+
/** Optional learned strategy to seed as a local (trusted) gene for this task. */
|
|
21
|
+
strategy?: readonly string[];
|
|
22
|
+
/** Optional explicit gene id/asset id selected by GEP or the task source. */
|
|
23
|
+
forcedGeneId?: string;
|
|
24
|
+
/** Legacy/GEP aliases accepted at the autoexec boundary and normalized into forcedGeneId. */
|
|
25
|
+
preferredGeneId?: string;
|
|
26
|
+
selected_gene_id?: string;
|
|
27
|
+
selectedGeneId?: string;
|
|
28
|
+
/** Optional explicit strategy preset name for this task; wins over daemon default and meta-signal auto-detection. */
|
|
29
|
+
strategyName?: string;
|
|
30
|
+
validationCmds?: readonly string[];
|
|
31
|
+
}
|
|
32
|
+
export interface AutoExecVerdict {
|
|
33
|
+
taskId: string;
|
|
34
|
+
status: 'refused' | 'skipped' | 'solidified' | 'failed' | 'innovated';
|
|
35
|
+
reason?: string;
|
|
36
|
+
finalStage?: string;
|
|
37
|
+
outcome?: {
|
|
38
|
+
status: string;
|
|
39
|
+
score: number;
|
|
40
|
+
};
|
|
41
|
+
proofOfWork?: unknown;
|
|
42
|
+
usedAssetIds?: readonly string[];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Reuse-before-solve seam (#110): given the task's signals, resolve hub candidates worth competing in the
|
|
46
|
+
* selection pool. This is a pure FUNCTION SIGNATURE — core deliberately does NOT import the adapter's
|
|
47
|
+
* `reuseBeforeSolve` (that would breach the core-can't-import-adapter boundary). The real implementation
|
|
48
|
+
* (free hub search → pure score → paid fetch → cache) is injected at the composition layer that already owns
|
|
49
|
+
* the hub capability (the CLI/daemon), mirroring how the exec bridge's `agent` seam is injected. The seam is
|
|
50
|
+
* optional: when absent, no hub candidates flow and the cycle behaves exactly as today (and makes ZERO hub
|
|
51
|
+
* calls). It must never throw — reuse is an optimization, so a hub failure degrades to solving fresh.
|
|
52
|
+
*/
|
|
53
|
+
export interface HubReuseContext {
|
|
54
|
+
/** The cycle this reuse resolution feeds — carried so the composition layer can emit a reuse event whose
|
|
55
|
+
* refs point at the SAME cycleId the cycle records (value-ledger audit anchor, #112). */
|
|
56
|
+
cycleId: string;
|
|
57
|
+
}
|
|
58
|
+
export type HubReuseSeam = (signals: readonly string[], ctx?: HubReuseContext) => Promise<readonly GeneCandidateInput[]>;
|
|
59
|
+
export interface AutoExecDeps {
|
|
60
|
+
engine: CycleEngine;
|
|
61
|
+
store: AssetStoreProvider;
|
|
62
|
+
provenance?: ProvenanceStore;
|
|
63
|
+
/** Optional review-state gate: withhold an unreviewed (auto-distilled) gene's strategy from the agent prompt. */
|
|
64
|
+
review?: ReviewLedger;
|
|
65
|
+
/**
|
|
66
|
+
* Probation (#306, gated): when set, a quarantined auto-distilled gene is BOTH selectable and embeddable, so it
|
|
67
|
+
* is tried with its own strategy and its outcome becomes real evidence for auto-promote. Forwarded to selection
|
|
68
|
+
* (includeProbation) AND to makeSafeExecute (the resolver embeds the probation strategy). Omit (default) → today's
|
|
69
|
+
* behavior: quarantined drafts wait for human approval. Bad probation strategies are contained by the exec gates.
|
|
70
|
+
*/
|
|
71
|
+
includeProbation?: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Optional reuse-before-solve seam (#110): when set, it is called before the cycle to pull hub candidates
|
|
74
|
+
* that compete in the SAME pool as local genes (trust-first — a trusted local gene wins on a geneId
|
|
75
|
+
* collision). Omit to disable (zero hub calls, exactly today's behavior). Injected by the composition layer
|
|
76
|
+
* that owns the hub capability so core stays hub-agnostic (the signature, not the adapter, lives here).
|
|
77
|
+
*/
|
|
78
|
+
hubReuse?: HubReuseSeam;
|
|
79
|
+
/** Build a validation hook for a task (e.g. run its validationCmds in the worktree). Deployment-specific. */
|
|
80
|
+
validate?: (task: AutoExecTask) => ValidateHook;
|
|
81
|
+
/** Optional adapter/runtime permit gate. Core owns only the seam; adapters own the verification policy. */
|
|
82
|
+
solidifyPermit?: SolidifyPermitGate;
|
|
83
|
+
/**
|
|
84
|
+
* Optional open-PR dedup: when set, before spawning an agent the task's signals are compared against open PR
|
|
85
|
+
* titles/branches; a strong overlap yields a 'skipped' verdict so the daemon never re-implements work that is
|
|
86
|
+
* already in flight. Opt-in — omit to disable. Wrap with makeCachedPrLister for a polling daemon.
|
|
87
|
+
*/
|
|
88
|
+
prLister?: OpenPrLister;
|
|
89
|
+
/** Min token-overlap for a PR to count as a duplicate (default 0.5). */
|
|
90
|
+
dedupThreshold?: number;
|
|
91
|
+
/**
|
|
92
|
+
* Cross-runtime reuse-outcome summary (#268 phase 1 on-switch): when set, it SOFTLY re-orders gene selection by
|
|
93
|
+
* how MCP-native agents fared reusing each gene (forwarded to runEvolutionCycle). Omit (the default) → no reuse
|
|
94
|
+
* re-order → exactly today's behavior. The composition layer computes it from reuse-outcome events behind a flag.
|
|
95
|
+
*/
|
|
96
|
+
reuseOutcomes?: ReuseOutcomeSummary;
|
|
97
|
+
/** Observed `value.recall` events (#274 slice 3): folded into the same soft re-order as reuseOutcomes (lower
|
|
98
|
+
* weight) so transcript-observed recall influences selection. Forwarded to runEvolutionCycle. Omit → none. */
|
|
99
|
+
recallEvents?: readonly ReuseOutcomeEvent[];
|
|
100
|
+
/** Optional daemon-level explicit strategy preset name, e.g. EVOLVE_STRATEGY. */
|
|
101
|
+
strategyName?: string;
|
|
102
|
+
/** Optional evolvable personality store shared with CycleEngine and the exec prompt. */
|
|
103
|
+
personality?: PersonalityStore;
|
|
104
|
+
/** Test/custom seam: inject a runner instead of spawning a real agent. */
|
|
105
|
+
agent?: AgentRunner;
|
|
106
|
+
/** Test/custom seam: inject git instead of spawning git. */
|
|
107
|
+
git?: GitRunner;
|
|
108
|
+
}
|
|
109
|
+
export interface ForcedGeneFields {
|
|
110
|
+
forcedGeneId?: unknown;
|
|
111
|
+
preferredGeneId?: unknown;
|
|
112
|
+
selected_gene_id?: unknown;
|
|
113
|
+
selectedGeneId?: unknown;
|
|
114
|
+
}
|
|
115
|
+
export declare function canonicalForcedGeneId(task: ForcedGeneFields): string | undefined;
|
|
116
|
+
export declare function normalizeAutoExecTask(task: AutoExecTask): AutoExecTask;
|
|
117
|
+
/**
|
|
118
|
+
* Run one autonomous task end to end with every safety control composed (makeSafeExecute). Deny-by-default:
|
|
119
|
+
* if task.repo is not within safety.allowedRoots, returns a 'refused' verdict and runs nothing. Otherwise seeds
|
|
120
|
+
* the task's strategy as a local (trusted) gene, then drives a real evolution cycle and maps the result.
|
|
121
|
+
*/
|
|
122
|
+
export declare function runAutoExecTask(deps: AutoExecDeps, rawTask: AutoExecTask, safety: AutonomousSafety): Promise<AutoExecVerdict>;
|
|
123
|
+
/**
|
|
124
|
+
* Single-flight re-entrancy guard for a poll-driven resident loop. A resident autoexec daemon polls on an
|
|
125
|
+
* interval; if a pass outlives the poll period (a hung/slow agent), the next tick must NOT start a second
|
|
126
|
+
* overlapping pass — that piled up runaway nested agents in an early scratch run. Wrap the pass: while one is
|
|
127
|
+
* in flight, subsequent calls return { skipped: true } immediately instead of starting another.
|
|
128
|
+
*/
|
|
129
|
+
export declare function singleFlight<T>(fn: () => Promise<T>): () => Promise<T | {
|
|
130
|
+
skipped: true;
|
|
131
|
+
}>;
|
|
132
|
+
/**
|
|
133
|
+
* Process tasks strictly SEQUENTIALLY (one at a time, never overlapping) through `runOne`, collecting verdicts.
|
|
134
|
+
* Sequential by construction — an autonomous agent edits a worktree and runs tools; concurrent passes would
|
|
135
|
+
* contend. Combine with {@link singleFlight} so a poll tick that fires mid-drain is skipped, not stacked.
|
|
136
|
+
*/
|
|
137
|
+
export declare function drainTasks<T, V>(tasks: readonly T[], runOne: (task: T) => Promise<V>): Promise<V[]>;
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
// Autonomous-exec task runner — the productized per-task kernel a resident daemon polls (the deployment form
|
|
2
|
+
// of the scratch autoexec daemon). One task → one fully-hardened evolution cycle, with a deny-by-default
|
|
3
|
+
// allowlist pre-check that yields a clean "refused" verdict WITHOUT running anything when the repo is not
|
|
4
|
+
// allowlisted. Secure by construction: the execute is built by makeSafeExecute (all six controls); callers
|
|
5
|
+
// cannot bypass the safety composition.
|
|
6
|
+
import { resolve as resolvePath, sep } from 'node:path';
|
|
7
|
+
import { normalizeForPut } from '../assetstore/provider.js';
|
|
8
|
+
import { ingestUntrusted } from '../assetstore/provenance.js';
|
|
9
|
+
import { mergePendingSignalsForStore } from '../assetstore/pendingSignals.js';
|
|
10
|
+
import { intakeGene } from '../algo/geneIntake.js';
|
|
11
|
+
import { runEvolutionCycle } from '../algo/orchestrator.js';
|
|
12
|
+
import { makeSafeExecute, makeTrustedGeneResolver } from './autonomousCycle.js';
|
|
13
|
+
import { findSignalHints } from './openPrRegistry.js';
|
|
14
|
+
/** Same path-containment as the bridge guard — used here to refuse before running anything (clean verdict). */
|
|
15
|
+
function withinAllowlist(repo, roots) {
|
|
16
|
+
const c = resolvePath(repo);
|
|
17
|
+
return roots.some((root) => { const r = resolvePath(root); return c === r || c.startsWith(r.endsWith(sep) ? r : r + sep); });
|
|
18
|
+
}
|
|
19
|
+
function cleanForcedGeneId(value) {
|
|
20
|
+
if (typeof value !== 'string')
|
|
21
|
+
return undefined;
|
|
22
|
+
const trimmed = value.trim();
|
|
23
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
24
|
+
}
|
|
25
|
+
export function canonicalForcedGeneId(task) {
|
|
26
|
+
return cleanForcedGeneId(task.forcedGeneId)
|
|
27
|
+
?? cleanForcedGeneId(task.preferredGeneId)
|
|
28
|
+
?? cleanForcedGeneId(task.selected_gene_id)
|
|
29
|
+
?? cleanForcedGeneId(task.selectedGeneId);
|
|
30
|
+
}
|
|
31
|
+
export function normalizeAutoExecTask(task) {
|
|
32
|
+
const forcedGeneId = canonicalForcedGeneId(task);
|
|
33
|
+
const normalized = { ...task };
|
|
34
|
+
if (forcedGeneId === undefined)
|
|
35
|
+
delete normalized.forcedGeneId;
|
|
36
|
+
else
|
|
37
|
+
normalized.forcedGeneId = forcedGeneId;
|
|
38
|
+
return normalized;
|
|
39
|
+
}
|
|
40
|
+
async function landHubAssetIfPresent(deps, candidate) {
|
|
41
|
+
if (!candidate.hubAsset)
|
|
42
|
+
return candidate;
|
|
43
|
+
if (!deps.provenance)
|
|
44
|
+
return null;
|
|
45
|
+
let normalized;
|
|
46
|
+
try {
|
|
47
|
+
normalized = normalizeForPut(candidate.hubAsset).record;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
const existing = await deps.store.get(normalized.asset_id);
|
|
53
|
+
if (!existing) {
|
|
54
|
+
try {
|
|
55
|
+
await ingestUntrusted(deps.store, deps.provenance, normalized, 'hub');
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return candidate.assetId === normalized.asset_id ? candidate : { ...candidate, assetId: normalized.asset_id };
|
|
62
|
+
}
|
|
63
|
+
async function hasTrustedResolvedStrategy(deps, candidate) {
|
|
64
|
+
if (!deps.provenance)
|
|
65
|
+
return false;
|
|
66
|
+
const resolveGene = makeTrustedGeneResolver(deps.store, deps.provenance, deps.review);
|
|
67
|
+
const ids = candidate.hubAsset
|
|
68
|
+
? [candidate.assetId].filter((id) => typeof id === 'string' && id.length > 0)
|
|
69
|
+
: [candidate.geneId, candidate.assetId].filter((id) => typeof id === 'string' && id.length > 0);
|
|
70
|
+
const uniqueIds = [...new Set(ids)];
|
|
71
|
+
for (const id of uniqueIds) {
|
|
72
|
+
const info = await resolveGene(id);
|
|
73
|
+
if (info?.trusted === true && (info.strategy?.length ?? 0) > 0)
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
async function executableHubCandidates(deps, candidates) {
|
|
79
|
+
const out = [];
|
|
80
|
+
for (const candidate of candidates) {
|
|
81
|
+
const landed = await landHubAssetIfPresent(deps, candidate);
|
|
82
|
+
if (!landed)
|
|
83
|
+
continue;
|
|
84
|
+
if (await hasTrustedResolvedStrategy(deps, landed))
|
|
85
|
+
out.push(landed);
|
|
86
|
+
}
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Run one autonomous task end to end with every safety control composed (makeSafeExecute). Deny-by-default:
|
|
91
|
+
* if task.repo is not within safety.allowedRoots, returns a 'refused' verdict and runs nothing. Otherwise seeds
|
|
92
|
+
* the task's strategy as a local (trusted) gene, then drives a real evolution cycle and maps the result.
|
|
93
|
+
*/
|
|
94
|
+
export async function runAutoExecTask(deps, rawTask, safety) {
|
|
95
|
+
const task = normalizeAutoExecTask(rawTask);
|
|
96
|
+
if (!withinAllowlist(task.repo, safety.allowedRoots)) {
|
|
97
|
+
return { taskId: task.id, status: 'refused', reason: `repo not in allowlist: ${task.repo}` };
|
|
98
|
+
}
|
|
99
|
+
// Open-PR dedup (opt-in): if an open PR already covers this task's signals, skip before spawning an agent
|
|
100
|
+
// so the daemon doesn't re-implement in-flight work. Graceful — a lister that returns [] is a no-op.
|
|
101
|
+
if (deps.prLister) {
|
|
102
|
+
const hints = findSignalHints(task.signals, await deps.prLister(task.repo), { threshold: deps.dedupThreshold ?? 0.5 });
|
|
103
|
+
const top = hints[0];
|
|
104
|
+
if (top) {
|
|
105
|
+
return { taskId: task.id, status: 'skipped', reason: `open-pr-dedup: signals overlap PR #${top.number} (${top.headRefName}) @ ${top.tokenOverlap.toFixed(2)}` };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
let cycleSignals = [...task.signals];
|
|
109
|
+
try {
|
|
110
|
+
const explicit = mergePendingSignalsForStore(deps.store, task.signals, { repoRoot: task.repo });
|
|
111
|
+
cycleSignals = explicit.signals;
|
|
112
|
+
if (explicit.injected > 0) {
|
|
113
|
+
console.log(`[ExplicitSignals] Injected ${explicit.injected} user-declared signal(s) from pending_signals.json.`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
118
|
+
console.warn(`[ExplicitSignals] Failed to consume pending signals (non-fatal): ${message}`);
|
|
119
|
+
}
|
|
120
|
+
let seededStrategyGeneId;
|
|
121
|
+
if (task.strategy && task.strategy.length > 0) {
|
|
122
|
+
const gi = intakeGene({
|
|
123
|
+
category: 'repair', signals_match: cycleSignals, strategy: [...task.strategy],
|
|
124
|
+
summary: task.expectedEffect.slice(0, 80), ...(task.validationCmds ? { validation: [...task.validationCmds] } : {}),
|
|
125
|
+
});
|
|
126
|
+
if (gi.ok && gi.gene) {
|
|
127
|
+
await deps.store.put(gi.gene);
|
|
128
|
+
seededStrategyGeneId = cleanForcedGeneId(gi.gene.id);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Reuse-before-solve (#110): if the seam is wired, resolve hub candidates BEFORE the cycle so they compete
|
|
132
|
+
// in the same selection pool as local genes. Reuse is an optimization, never a hard dependency — a seam
|
|
133
|
+
// that throws degrades to solving fresh (no hub candidates) rather than failing the task.
|
|
134
|
+
let hubCandidates = [];
|
|
135
|
+
const cycleId = `autoexec-${task.id}`;
|
|
136
|
+
if (deps.hubReuse) {
|
|
137
|
+
try {
|
|
138
|
+
hubCandidates = await executableHubCandidates(deps, await deps.hubReuse(cycleSignals, { cycleId }));
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
hubCandidates = [];
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const execute = makeSafeExecute(task.repo, deps.store, safety, {
|
|
145
|
+
...(deps.provenance ? { provenance: deps.provenance } : {}),
|
|
146
|
+
...(deps.review ? { review: deps.review } : {}),
|
|
147
|
+
...(deps.includeProbation ? { includeProbation: true } : {}),
|
|
148
|
+
...(task.validationCmds ? { validationCmds: task.validationCmds } : {}),
|
|
149
|
+
...(deps.validate ? { validate: deps.validate(task) } : {}),
|
|
150
|
+
...(deps.personality ? { personality: deps.personality } : {}),
|
|
151
|
+
...(deps.agent ? { agent: deps.agent } : {}),
|
|
152
|
+
...(deps.git ? { git: deps.git } : {}),
|
|
153
|
+
});
|
|
154
|
+
const strategyName = task.strategyName ?? deps.strategyName;
|
|
155
|
+
// Intentional semantics (see #308 review M1): a task carrying `strategy` — even without an
|
|
156
|
+
// explicit forcedGeneId — force-selects the gene seeded from that strategy above, rather than
|
|
157
|
+
// letting it compete in normal ranking. Supplying a strategy is treated as "use this strategy".
|
|
158
|
+
// The forced pick still passes every hard gate downstream (candidate pool, ban, epigenetic
|
|
159
|
+
// suppression), so this never bypasses trust/review/inert filtering.
|
|
160
|
+
const cycleForcedGeneId = task.forcedGeneId ?? seededStrategyGeneId;
|
|
161
|
+
const res = await runEvolutionCycle(deps.engine, deps.store, {
|
|
162
|
+
...(deps.provenance ? { provenance: deps.provenance } : {}),
|
|
163
|
+
...(deps.review ? { review: deps.review } : {}),
|
|
164
|
+
...(deps.includeProbation ? { includeProbation: true } : {}),
|
|
165
|
+
...(hubCandidates.length > 0 ? { hubCandidates } : {}),
|
|
166
|
+
...(deps.solidifyPermit ? { solidifyPermit: deps.solidifyPermit } : {}),
|
|
167
|
+
...(deps.reuseOutcomes ? { reuseOutcomes: deps.reuseOutcomes } : {}),
|
|
168
|
+
...(deps.recallEvents ? { recallEvents: deps.recallEvents } : {}),
|
|
169
|
+
...(strategyName !== undefined ? { strategyName } : {}),
|
|
170
|
+
...(cycleForcedGeneId !== undefined ? { forcedGeneId: cycleForcedGeneId } : {}),
|
|
171
|
+
cycleId,
|
|
172
|
+
problem: {
|
|
173
|
+
id: task.id, signature: `sig:${task.id}`, signatureV: 1,
|
|
174
|
+
firstSeenAt: new Date(0).toISOString(), lastSeenAt: new Date(0).toISOString(),
|
|
175
|
+
occurrences: 1, linkedSignals: cycleSignals, resolvedBy: null, status: 'open',
|
|
176
|
+
value: { severity: 0.7, reach: 1, strategicFit: 0.9, novelty: 0, costEst: 0.2 },
|
|
177
|
+
consecutiveFailures: 0, cooldownUntil: null, extensions: {},
|
|
178
|
+
},
|
|
179
|
+
signals: cycleSignals, category: 'repair', target: task.target, expectedEffect: task.expectedEffect,
|
|
180
|
+
summary: `autonomous: ${task.id}`, confidence: 0.85, execute, consumePendingSignals: false,
|
|
181
|
+
});
|
|
182
|
+
const status = res.finalStage === 'solidified' ? 'solidified' : res.finalStage === 'failed' ? 'failed' : 'innovated';
|
|
183
|
+
const cap = res.capsule;
|
|
184
|
+
const hubAssetIds = new Set(hubCandidates.map((c) => c.assetId).filter((id) => typeof id === 'string' && id.length > 0));
|
|
185
|
+
const selectedAssetId = res.decision?.selectedAssetId;
|
|
186
|
+
const usedAssetIds = selectedAssetId && hubAssetIds.has(selectedAssetId) ? [selectedAssetId] : [];
|
|
187
|
+
return {
|
|
188
|
+
taskId: task.id, status, finalStage: res.finalStage,
|
|
189
|
+
...(res.reasons.length > 0 && status !== 'solidified' ? { reason: res.reasons.join('; ') } : {}),
|
|
190
|
+
...(cap?.outcome ? { outcome: cap.outcome } : {}),
|
|
191
|
+
...(cap?.proof_of_work ? { proofOfWork: cap.proof_of_work } : {}),
|
|
192
|
+
...(usedAssetIds.length > 0 ? { usedAssetIds } : {}),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Single-flight re-entrancy guard for a poll-driven resident loop. A resident autoexec daemon polls on an
|
|
197
|
+
* interval; if a pass outlives the poll period (a hung/slow agent), the next tick must NOT start a second
|
|
198
|
+
* overlapping pass — that piled up runaway nested agents in an early scratch run. Wrap the pass: while one is
|
|
199
|
+
* in flight, subsequent calls return { skipped: true } immediately instead of starting another.
|
|
200
|
+
*/
|
|
201
|
+
export function singleFlight(fn) {
|
|
202
|
+
let inFlight = null;
|
|
203
|
+
return () => {
|
|
204
|
+
if (inFlight)
|
|
205
|
+
return Promise.resolve({ skipped: true });
|
|
206
|
+
const p = fn().finally(() => { inFlight = null; });
|
|
207
|
+
inFlight = p;
|
|
208
|
+
return p;
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Process tasks strictly SEQUENTIALLY (one at a time, never overlapping) through `runOne`, collecting verdicts.
|
|
213
|
+
* Sequential by construction — an autonomous agent edits a worktree and runs tools; concurrent passes would
|
|
214
|
+
* contend. Combine with {@link singleFlight} so a poll tick that fires mid-drain is skipped, not stacked.
|
|
215
|
+
*/
|
|
216
|
+
export async function drainTasks(tasks, runOne) {
|
|
217
|
+
const out = [];
|
|
218
|
+
for (const t of tasks)
|
|
219
|
+
out.push(await runOne(t));
|
|
220
|
+
return out;
|
|
221
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
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 { Mutation } from '../wire/index.js';
|
|
5
|
+
import type { GeneDecision } from '../algo/geneSelection.js';
|
|
6
|
+
import type { ExecutionResult } from '../algo/cycleEngine.js';
|
|
7
|
+
import { type GeneResolver, type ValidateHook, type AgentRunnerOptions, type RunnerName, type AgentRunner, type GitRunner } from './claudeBridge.js';
|
|
8
|
+
import type { PersonalityStore } from '../personality/store.js';
|
|
9
|
+
/**
|
|
10
|
+
* Resolve a gene's strategy from the store and whether it is safe to EMBED into an autonomous agent's prompt —
|
|
11
|
+
* the exec-side link from #30 (provenance ledger) and the review-state gate to #45 (requireTrustedGene gate). A
|
|
12
|
+
* gene is embeddable only when BOTH axes pass: trusted ORIGIN (no provenance record → local/trusted; a hub one
|
|
13
|
+
* is untrusted until promoted) AND review-APPROVED content (no review record → eligible; an auto-distilled draft
|
|
14
|
+
* is quarantined until a human approves). Both default-open, so cycle-self-produced/local genes are unaffected;
|
|
15
|
+
* only hub-ingested (untrusted) and auto-distilled (unreviewed) drafts are withheld. Looks up by id or asset_id.
|
|
16
|
+
*/
|
|
17
|
+
export declare function makeTrustedGeneResolver(store: AssetStoreProvider, provenance?: ProvenanceStore, review?: ReviewLedger, includeProbation?: boolean): GeneResolver;
|
|
18
|
+
export interface AutonomousSafety {
|
|
19
|
+
/** Deny-by-default repo allowlist (#41). Required — an empty array refuses everything. */
|
|
20
|
+
allowedRoots: readonly string[];
|
|
21
|
+
/** Which built-in runner (#66). Default 'claude'. The same safety controls wrap whichever runner. cursor is a scaffold (unverified). */
|
|
22
|
+
runner?: RunnerName;
|
|
23
|
+
/** Agent runner options (#38/#40). Default: bounded skip-permissions (Read/Edit/Write). */
|
|
24
|
+
agentOptions?: AgentRunnerOptions;
|
|
25
|
+
/** Strip evolver/hub secrets from the agent env (#42). Default true. */
|
|
26
|
+
scrubEnv?: boolean;
|
|
27
|
+
/** Run in a throwaway git worktree (#43). Default 'worktree'. */
|
|
28
|
+
isolation?: 'worktree' | 'none';
|
|
29
|
+
/** Only embed trusted gene strategies (#45). Default true. */
|
|
30
|
+
requireTrustedGene?: boolean;
|
|
31
|
+
timeoutMs?: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Build the fully-hardened `execute` for an autonomous run against `repo`. Composes every exec-bridge control
|
|
35
|
+
* with secure defaults so they can't be forgotten piecemeal: deny-by-default allowedRoots (#41) + worktree
|
|
36
|
+
* isolation (#43) + env scrub (#42) + bounded skip-permissions agent (#38/#40) + trusted-gene gate fed by
|
|
37
|
+
* provenance (#45/#30). Pass the result as runEvolutionCycle's `execute`.
|
|
38
|
+
*/
|
|
39
|
+
export declare function makeSafeExecute(repo: string, store: AssetStoreProvider, safety: AutonomousSafety, opts?: {
|
|
40
|
+
provenance?: ProvenanceStore;
|
|
41
|
+
review?: ReviewLedger;
|
|
42
|
+
validate?: ValidateHook;
|
|
43
|
+
validationCmds?: readonly string[];
|
|
44
|
+
includeProbation?: boolean;
|
|
45
|
+
personality?: PersonalityStore;
|
|
46
|
+
agent?: AgentRunner;
|
|
47
|
+
git?: GitRunner;
|
|
48
|
+
}): (mutation: Mutation, decision: GeneDecision) => Promise<ExecutionResult>;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { makeClaudeExecBridge } from './claudeBridge.js';
|
|
2
|
+
const asStrings = (v) => (Array.isArray(v) ? v.filter((x) => typeof x === 'string') : []);
|
|
3
|
+
/**
|
|
4
|
+
* Resolve a gene's strategy from the store and whether it is safe to EMBED into an autonomous agent's prompt —
|
|
5
|
+
* the exec-side link from #30 (provenance ledger) and the review-state gate to #45 (requireTrustedGene gate). A
|
|
6
|
+
* gene is embeddable only when BOTH axes pass: trusted ORIGIN (no provenance record → local/trusted; a hub one
|
|
7
|
+
* is untrusted until promoted) AND review-APPROVED content (no review record → eligible; an auto-distilled draft
|
|
8
|
+
* is quarantined until a human approves). Both default-open, so cycle-self-produced/local genes are unaffected;
|
|
9
|
+
* only hub-ingested (untrusted) and auto-distilled (unreviewed) drafts are withheld. Looks up by id or asset_id.
|
|
10
|
+
*/
|
|
11
|
+
export function makeTrustedGeneResolver(store, provenance, review, includeProbation = false) {
|
|
12
|
+
return async (geneId) => {
|
|
13
|
+
const genes = await store.list('Gene', 1000);
|
|
14
|
+
const g = genes.find((x) => String(x['id']) === geneId || String(x.asset_id) === geneId);
|
|
15
|
+
if (!g)
|
|
16
|
+
return null;
|
|
17
|
+
const summary = g['summary'];
|
|
18
|
+
const trustedOrigin = provenance ? provenance.isTrusted(String(g.asset_id)) : true;
|
|
19
|
+
const reviewApproved = review ? review.isApproved(String(g.asset_id)) : true;
|
|
20
|
+
// Probation (#306): when enabled, a QUARANTINED (auto-distilled, not yet approved — but not rejected) draft IS
|
|
21
|
+
// embeddable, so its strategy actually drives the trial. That is what makes the trial's outcome real evidence
|
|
22
|
+
// for auto-promote (without embedding, the gene would be selected but run as innovate — hollow evidence). The
|
|
23
|
+
// strategy is unreviewed, so its containment rests on the proven exec gates: sanitizeInjection neutralizes
|
|
24
|
+
// injected directives in the prompt, and the always-on hard gates + worktree isolation contain the agent's
|
|
25
|
+
// ACTIONS regardless of the prompt (#309). A REJECTED draft and an untrusted-origin (hub) gene stay withheld.
|
|
26
|
+
const probationOk = includeProbation && review?.get(String(g.asset_id))?.state === 'quarantined';
|
|
27
|
+
const info = {
|
|
28
|
+
strategy: asStrings(g['strategy']),
|
|
29
|
+
preconditions: asStrings(g['preconditions']),
|
|
30
|
+
...(typeof summary === 'string' ? { summary } : {}),
|
|
31
|
+
trusted: trustedOrigin && (reviewApproved || probationOk), // trusted ORIGIN + (approved OR on probation)
|
|
32
|
+
};
|
|
33
|
+
return info;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
// Claude's safe default: bypass the permission prompts but BOUND the agent to file edits (#38/#40).
|
|
37
|
+
const CLAUDE_DEFAULT_AGENT_OPTIONS = { skipPermissions: true, allowedTools: ['Read', 'Edit', 'Write'] };
|
|
38
|
+
// Codex's safe default is SANDBOXED (no skip): the autonomous-bypass flag is gated until verified (#66), so
|
|
39
|
+
// skipPermissions would throw at construction. `codex exec` still runs non-interactively under its own sandbox.
|
|
40
|
+
const CODEX_DEFAULT_AGENT_OPTIONS = {};
|
|
41
|
+
// Cursor's safe default keeps skip OFF (#66 SCAFFOLD). The runner is flag-confirmed via `cursor-agent --help`
|
|
42
|
+
// but not yet run-verified end to end (needs an authed cursor-agent). The `-p --force --trust` bypass would
|
|
43
|
+
// auto-approve shell+write, but Cursor has no verified per-run allowlist/sandbox mapping yet, so skipPermissions
|
|
44
|
+
// is refused outright. Use default cursor with worktree isolation until the CLI is run-verified.
|
|
45
|
+
const CURSOR_DEFAULT_AGENT_OPTIONS = {};
|
|
46
|
+
/** Per-runner safe default agent options — claude bypasses-with-bounds; codex + cursor stay non-bypassing (codex sandboxed; cursor skip refused, #66). */
|
|
47
|
+
function defaultAgentOptions(runner) {
|
|
48
|
+
if (runner === 'codex')
|
|
49
|
+
return CODEX_DEFAULT_AGENT_OPTIONS;
|
|
50
|
+
if (runner === 'cursor')
|
|
51
|
+
return CURSOR_DEFAULT_AGENT_OPTIONS;
|
|
52
|
+
return CLAUDE_DEFAULT_AGENT_OPTIONS;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Build the fully-hardened `execute` for an autonomous run against `repo`. Composes every exec-bridge control
|
|
56
|
+
* with secure defaults so they can't be forgotten piecemeal: deny-by-default allowedRoots (#41) + worktree
|
|
57
|
+
* isolation (#43) + env scrub (#42) + bounded skip-permissions agent (#38/#40) + trusted-gene gate fed by
|
|
58
|
+
* provenance (#45/#30). Pass the result as runEvolutionCycle's `execute`.
|
|
59
|
+
*/
|
|
60
|
+
export function makeSafeExecute(repo, store, safety, opts = {}) {
|
|
61
|
+
return makeClaudeExecBridge({
|
|
62
|
+
cwd: repo,
|
|
63
|
+
enabled: true,
|
|
64
|
+
...(opts.agent ? { agent: opts.agent } : {}),
|
|
65
|
+
...(opts.git ? { git: opts.git } : {}),
|
|
66
|
+
allowedRoots: safety.allowedRoots,
|
|
67
|
+
...(safety.runner ? { runner: safety.runner } : {}),
|
|
68
|
+
...(safety.isolation === 'none' ? {} : { isolation: 'worktree' }),
|
|
69
|
+
scrubEnv: safety.scrubEnv ?? true,
|
|
70
|
+
requireTrustedGene: safety.requireTrustedGene ?? true,
|
|
71
|
+
agentOptions: safety.agentOptions ?? defaultAgentOptions(safety.runner),
|
|
72
|
+
...(safety.timeoutMs !== undefined ? { timeoutMs: safety.timeoutMs } : {}),
|
|
73
|
+
resolveGene: makeTrustedGeneResolver(store, opts.provenance, opts.review, opts.includeProbation ?? false),
|
|
74
|
+
...(opts.validate ? { validate: opts.validate } : {}),
|
|
75
|
+
...(opts.validationCmds ? { validationCmds: opts.validationCmds } : {}),
|
|
76
|
+
...(opts.personality ? { personality: opts.personality } : {}),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { Mutation } from '../wire/index.js';
|
|
2
|
+
import type { GeneDecision } from '../algo/geneSelection.js';
|
|
3
|
+
import type { ExecutionResult } from '../algo/cycleEngine.js';
|
|
4
|
+
import { type GeneStrategyInfo } from './prompt.js';
|
|
5
|
+
import type { PersonalityStore } from '../personality/store.js';
|
|
6
|
+
import { type AgentRunner, type AgentRunnerOptions, type RunnerName } from './runnerRegistry.js';
|
|
7
|
+
export { resolveSpawnCommand, spawnCapture, UnboundedSkipPermissionsError, UnsupportedCursorSkipPermissionsError, claudeRunnerArgs, makeClaudeHeadlessRunner, claudeHeadlessRunner, codexRunnerArgs, makeCodexHeadlessRunner, cursorRunnerArgs, makeCursorHeadlessRunner, getRunnerSpec, } from './runnerRegistry.js';
|
|
8
|
+
export type { AgentRunContext, AgentRunResult, AgentRunner, RunnerName, AgentRunnerOptions, ClaudeRunnerOptions, CodexRunnerOptions, AgentRunnerSpec, } from './runnerRegistry.js';
|
|
9
|
+
/** Run a git subcommand in cwd and return its stdout. */
|
|
10
|
+
export type GitRunner = (args: readonly string[], cwd: string) => Promise<string>;
|
|
11
|
+
/** Resolve the selected gene's learned strategy (for prompt enrichment). */
|
|
12
|
+
export type GeneResolver = (geneId: string) => Promise<GeneStrategyInfo | null> | GeneStrategyInfo | null;
|
|
13
|
+
/** Decide success from the post-run working tree (e.g. run the gene's validation plan). */
|
|
14
|
+
export type ValidateHook = (mutation: Mutation, decision: GeneDecision, cwd: string) => Promise<{
|
|
15
|
+
passed: boolean;
|
|
16
|
+
score?: number;
|
|
17
|
+
}> | {
|
|
18
|
+
passed: boolean;
|
|
19
|
+
score?: number;
|
|
20
|
+
};
|
|
21
|
+
export interface ExecBridgeOptions {
|
|
22
|
+
/** Working directory the agent edits and git is measured in. */
|
|
23
|
+
cwd: string;
|
|
24
|
+
/** Default: headless `claude` runner. Inject a fake in tests. */
|
|
25
|
+
agent?: AgentRunner;
|
|
26
|
+
/** Which built-in runner to use when `agent` is not injected (#66). Default 'claude' (byte-identical). cursor is a scaffold (unverified runner). */
|
|
27
|
+
runner?: RunnerName;
|
|
28
|
+
/** When `agent` is not injected, options for the built-in headless runner (permission bypass / allowed tools / model). */
|
|
29
|
+
agentOptions?: AgentRunnerOptions;
|
|
30
|
+
/** Default: spawns `git`. Inject a fake in tests. */
|
|
31
|
+
git?: GitRunner;
|
|
32
|
+
/** Default: EVOLVE_EXEC_BRIDGE === '1'. Set true to force-enable (e.g. integration tests). */
|
|
33
|
+
enabled?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Deny-by-default repo guardrail for autonomous use: when set, the agent may only run in a `cwd` that is
|
|
36
|
+
* within one of these roots. An empty array denies everything (the safe default for a resident loop until
|
|
37
|
+
* repos are explicitly allowlisted). When undefined, no path restriction (caller's responsibility — e.g.
|
|
38
|
+
* tests with fake agents). Autonomous deployments MUST set this.
|
|
39
|
+
*/
|
|
40
|
+
allowedRoots?: readonly string[];
|
|
41
|
+
/** Strip evolver/hub/cloud secrets from the agent's environment before spawning (finding #39.2). Default true
|
|
42
|
+
* (secure by default); the agent keeps ONLY its own runner's auth (claude: ANTHROPIC_/CLAUDE_, codex: OPENAI_/
|
|
43
|
+
* CODEX_ — #66). Set false only to inherit the full env. */
|
|
44
|
+
scrubEnv?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Run the agent in a throwaway git worktree of `cwd` instead of the repo's real working tree (finding #39.4):
|
|
47
|
+
* the agent's edits land in an isolated checkout, never touching the user's working tree. The diff is measured
|
|
48
|
+
* there, captured as a patch (proof.gitDiff.patchRef), and the worktree is removed. `cwd` must be a git repo.
|
|
49
|
+
*/
|
|
50
|
+
isolation?: 'worktree';
|
|
51
|
+
/**
|
|
52
|
+
* Only embed a selected gene's strategy into the agent prompt when it is trusted (gene.trusted === true)
|
|
53
|
+
* (finding #39.3): a poisoned/hub-ingested gene's strategy is the injection blast end for an autonomous agent.
|
|
54
|
+
* When true, an untrusted gene is dropped (the run proceeds as innovate, without its strategy). Recommended
|
|
55
|
+
* for unattended runs. Default false (back-compat; local genes are trusted by their author).
|
|
56
|
+
*/
|
|
57
|
+
requireTrustedGene?: boolean;
|
|
58
|
+
/** Per-run agent timeout. Default 600_000ms (10 min). */
|
|
59
|
+
timeoutMs?: number;
|
|
60
|
+
/** Optional: enrich the prompt with the selected gene's strategy. */
|
|
61
|
+
resolveGene?: GeneResolver;
|
|
62
|
+
/** Optional: validation commands surfaced in the prompt's done-criteria. */
|
|
63
|
+
validationCmds?: readonly string[];
|
|
64
|
+
/** Optional: authoritative success decision after the agent runs. Falls back to "agent ok + produced a diff". */
|
|
65
|
+
validate?: ValidateHook;
|
|
66
|
+
/**
|
|
67
|
+
* Optional evolvable personality (use-case ①): when set, the agent prompt gets a behavioral-style block
|
|
68
|
+
* rendered from the store's CURRENT persisted state. CycleEngine's applySelectForRun has already run and
|
|
69
|
+
* saved the per-run state to this same store before execute() is invoked, so reading currentState() here
|
|
70
|
+
* injects exactly the personality this cycle selected. Pass the SAME PersonalityStore given to CycleEngine.
|
|
71
|
+
* Absent ⇒ no style block (byte-identical to today). Reading is best-effort — a load failure falls back to
|
|
72
|
+
* the store's default state (store.load never throws), it never fails the run.
|
|
73
|
+
*/
|
|
74
|
+
personality?: PersonalityStore;
|
|
75
|
+
}
|
|
76
|
+
export declare class ExecBridgeDisabledError extends Error {
|
|
77
|
+
constructor();
|
|
78
|
+
}
|
|
79
|
+
/** Thrown when the agent's working directory is outside the configured allowedRoots (deny-by-default guardrail). */
|
|
80
|
+
export declare class ExecBridgeForbiddenError extends Error {
|
|
81
|
+
constructor(cwd: string);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Thrown when a FULL-ACCESS (or unverified) agent run is requested without worktree isolation. The throwaway
|
|
85
|
+
* worktree is the containment WE control — allowedRoots gates the cwd but cannot stop an auto-approved or
|
|
86
|
+
* unsandboxed process writing/running outside it. Gated runners:
|
|
87
|
+
* - codex with skipPermissions → `--sandbox danger-full-access` (no inner OS sandbox). Without skip it stays
|
|
88
|
+
* workspace-write, so only the skip path is gated.
|
|
89
|
+
* - cursor default → gated UNCONDITIONALLY. cursor-agent base `-p` already documents write+shell access, cursor
|
|
90
|
+
* skipPermissions is rejected by the runner layer, and the scaffold remains unverified (#66/#181) — so default
|
|
91
|
+
* cursor still needs the wrapper worktree rather than risk mutating the real tree.
|
|
92
|
+
* claude is exempt: its skip is bounded by --allowedTools (finding #80).
|
|
93
|
+
*/
|
|
94
|
+
export declare class UnsandboxedFullAccessRequiresIsolationError extends Error {
|
|
95
|
+
constructor();
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Whitelist-filter `env` for a spawned agent/tool: keep ONLY the minimal runtime env + the caller-declared
|
|
99
|
+
* extras (the runner's own auth via allowPrefixes/allowKeys); drop everything else. Fail-safe by construction —
|
|
100
|
+
* an unlisted var never leaks.
|
|
101
|
+
*/
|
|
102
|
+
export declare function scrubAgentEnv(env: NodeJS.ProcessEnv, opts?: {
|
|
103
|
+
allowKeys?: readonly string[];
|
|
104
|
+
allowPrefixes?: readonly string[];
|
|
105
|
+
}): NodeJS.ProcessEnv;
|
|
106
|
+
/** Default git runner: spawn `git <args>` in cwd, return stdout (empty string on error). Env scrubbed — git never needs evolver/hub secrets. */
|
|
107
|
+
export declare const defaultGitRunner: GitRunner;
|
|
108
|
+
/**
|
|
109
|
+
* Build the `execute` function CycleEngine/runEvolutionCycle consume. Default-off: throws
|
|
110
|
+
* ExecBridgeDisabledError on first call unless enabled.
|
|
111
|
+
*/
|
|
112
|
+
export declare function makeClaudeExecBridge(opts: ExecBridgeOptions): (mutation: Mutation, decision: GeneDecision) => Promise<ExecutionResult>;
|