@evomap/evolver-core 2.0.0-beta.0 → 2.0.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/gep/genes.jsonl +5 -0
- package/dist/algo/candidateAssembly.js +23 -14
- package/dist/algo/capabilityCandidates.d.ts +2 -0
- package/dist/algo/capabilityCandidates.js +5 -0
- package/dist/algo/conversationSniffer.d.ts +18 -0
- package/dist/algo/conversationSniffer.js +149 -0
- package/dist/algo/cycleEngine.d.ts +11 -0
- package/dist/algo/cycleEngine.js +14 -6
- package/dist/algo/cycleFailureClassifier.d.ts +1 -1
- package/dist/algo/cycleFailureClassifier.js +13 -5
- package/dist/algo/geneIntake.d.ts +14 -4
- package/dist/algo/geneIntake.js +37 -9
- package/dist/algo/geneSelection.d.ts +18 -1
- package/dist/algo/geneSelection.js +42 -18
- package/dist/algo/index.d.ts +2 -0
- package/dist/algo/index.js +2 -0
- package/dist/algo/memoryGraph.d.ts +62 -0
- package/dist/algo/memoryGraph.js +86 -0
- package/dist/algo/orchestrator.d.ts +3 -0
- package/dist/algo/orchestrator.js +14 -2
- package/dist/assetstore/assetSidecarRecords.d.ts +28 -0
- package/dist/assetstore/assetSidecarRecords.js +376 -0
- package/dist/assetstore/assetSidecarRecovery.d.ts +48 -0
- package/dist/assetstore/assetSidecarRecovery.js +288 -0
- package/dist/assetstore/assetStoreHealth.d.ts +75 -0
- package/dist/assetstore/assetStoreHealth.js +277 -0
- package/dist/assetstore/assetStoreLayout.d.ts +2 -0
- package/dist/assetstore/assetStoreLayout.js +6 -0
- package/dist/assetstore/assetStoreStorage.d.ts +42 -0
- package/dist/assetstore/assetStoreStorage.js +327 -0
- package/dist/assetstore/assetSyncLedger.d.ts +118 -0
- package/dist/assetstore/assetSyncLedger.js +745 -0
- package/dist/assetstore/index.d.ts +5 -1
- package/dist/assetstore/index.js +5 -1
- package/dist/assetstore/localJsonl.d.ts +12 -3
- package/dist/assetstore/localJsonl.js +131 -39
- package/dist/assetstore/pendingSignals.js +3 -1
- package/dist/assetstore/provenance.d.ts +27 -4
- package/dist/assetstore/provenance.js +107 -56
- package/dist/assetstore/provider.d.ts +26 -0
- package/dist/assetstore/provider.js +50 -0
- package/dist/assetstore/reviewFilter.js +5 -2
- package/dist/assetstore/reviewLedger.d.ts +14 -2
- package/dist/assetstore/reviewLedger.js +78 -43
- package/dist/assetstore/seedGenes.d.ts +3 -0
- package/dist/assetstore/seedGenes.js +134 -0
- package/dist/benchmark/antiGeneBenchmark.d.ts +2 -0
- package/dist/benchmark/antiGeneBenchmark.js +11 -1
- package/dist/benchmark/antiGeneImpact.d.ts +16 -0
- package/dist/benchmark/antiGeneImpact.js +34 -0
- package/dist/benchmark/antiGeneRollout.d.ts +2 -0
- package/dist/benchmark/antiGeneRollout.js +13 -1
- package/dist/benchmark/index.d.ts +2 -1
- package/dist/benchmark/index.js +2 -1
- package/dist/benchmark/triggerShift.d.ts +62 -0
- package/dist/benchmark/triggerShift.js +106 -0
- package/dist/events/eventArchive.d.ts +65 -0
- package/dist/events/eventArchive.js +343 -0
- package/dist/events/eventStore.js +2 -12
- package/dist/events/ingest.d.ts +1 -1
- package/dist/events/ingest.js +9 -0
- package/dist/events/paths.d.ts +10 -10
- package/dist/events/paths.js +20 -20
- package/dist/events/public.d.ts +3 -1
- package/dist/events/public.js +2 -1
- package/dist/events/retention.d.ts +24 -1
- package/dist/events/retention.js +133 -37
- package/dist/exec/autoExec.d.ts +6 -1
- package/dist/exec/autoExec.js +34 -0
- package/dist/exec/autonomousCycle.d.ts +2 -0
- package/dist/exec/autonomousCycle.js +5 -0
- package/dist/exec/claudeBridge.d.ts +21 -3
- package/dist/exec/claudeBridge.js +413 -26
- package/dist/exec/openPrRegistry.d.ts +8 -2
- package/dist/exec/openPrRegistry.js +32 -22
- package/dist/exec/prompt.js +9 -0
- package/dist/exec/runnerRegistry.d.ts +90 -18
- package/dist/exec/runnerRegistry.js +603 -42
- package/dist/exec/selfPrObfuscation.d.ts +2 -1
- package/dist/exec/selfPrObfuscation.js +19 -6
- package/dist/hub/agentDirectory.d.ts +90 -0
- package/dist/hub/agentDirectory.js +104 -0
- package/dist/hub/bindings.js +23 -3
- package/dist/hub/capability.d.ts +14 -2
- package/dist/hub/fake.d.ts +4 -2
- package/dist/hub/fake.js +3 -2
- package/dist/hub/index.d.ts +1 -0
- package/dist/hub/index.js +1 -0
- package/dist/hub/sanitize.js +3 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/issueReporter/index.d.ts +156 -0
- package/dist/issueReporter/index.js +1688 -0
- package/dist/mailbox/catalog.js +3 -0
- package/dist/mailbox/ipcServer.js +2 -2
- package/dist/mailbox/store.d.ts +14 -0
- package/dist/mailbox/store.js +58 -6
- package/dist/material/consumer.js +9 -6
- package/dist/material/index.d.ts +1 -0
- package/dist/material/index.js +1 -0
- package/dist/material/materialArchive.d.ts +81 -0
- package/dist/material/materialArchive.js +466 -0
- package/dist/material/materialStore.d.ts +1 -0
- package/dist/material/materialStore.js +6 -13
- package/dist/ops/savingsCore.js +1 -2
- package/dist/ops/selfUpdate.d.ts +10 -1
- package/dist/ops/selfUpdate.js +64 -15
- package/dist/personality/schema.d.ts +12 -12
- package/dist/schema/common.d.ts +1 -1
- package/dist/schema/common.js +1 -1
- package/dist/schema/material.d.ts +5 -5
- package/dist/strategy/constraintAblation.d.ts +64 -0
- package/dist/strategy/constraintAblation.js +3074 -0
- package/dist/strategy/index.d.ts +2 -1
- package/dist/strategy/index.js +2 -1
- package/dist/trace/trajectoryExport.js +2 -2
- package/dist/util/fetchPort.d.ts +1 -0
- package/dist/util/fetchPort.js +11 -0
- package/dist/util/fileLock.d.ts +24 -5
- package/dist/util/fileLock.js +288 -72
- package/dist/util/index.d.ts +1 -0
- package/dist/util/index.js +1 -0
- package/dist/wire/geneHints.d.ts +42 -1
- package/dist/wire/geneHints.js +52 -1
- package/dist/wire/index.d.ts +14 -2
- package/dist/wire/index.js +1 -1
- package/dist/workflow/dsl.d.ts +24 -3
- package/dist/workflow/dsl.js +4 -0
- package/dist/workflow/engine.d.ts +5 -1
- package/dist/workflow/engine.js +3 -0
- package/dist/workflow/index.d.ts +3 -1
- package/dist/workflow/index.js +3 -1
- package/dist/workflow/runtime.d.ts +110 -0
- package/dist/workflow/runtime.js +1298 -0
- package/dist/workflow/stateStore.d.ts +172 -0
- package/dist/workflow/stateStore.js +1044 -0
- package/package.json +6 -1
package/dist/events/paths.js
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
import { homedir } from 'node:os';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
/** ~/.evomap, 可 EVOLVER_HOME/EVOMAP_HOME 覆盖. */
|
|
4
|
-
export function evomapHome() {
|
|
5
|
-
return
|
|
4
|
+
export function evomapHome(env = process.env) {
|
|
5
|
+
return env['EVOLVER_HOME'] ?? env['EVOMAP_HOME'] ?? join(homedir(), '.evomap');
|
|
6
6
|
}
|
|
7
|
-
export function rootEventsPath() {
|
|
8
|
-
return join(evomapHome(), 'evolution', 'root_events.jsonl');
|
|
7
|
+
export function rootEventsPath(env = process.env) {
|
|
8
|
+
return join(evomapHome(env), 'evolution', 'root_events.jsonl');
|
|
9
9
|
}
|
|
10
|
-
export function mvDir() {
|
|
11
|
-
return join(evomapHome(), 'evolution', 'mv');
|
|
10
|
+
export function mvDir(env = process.env) {
|
|
11
|
+
return join(evomapHome(env), 'evolution', 'mv');
|
|
12
12
|
}
|
|
13
13
|
/** 可进化人格模型持久化文件 (五维向量 + 各键统计 + 变更历史). v1 personality_state.json 的 v2 落点. */
|
|
14
|
-
export function personalityStatePath() {
|
|
15
|
-
return join(evomapHome(), 'evolution', 'personality_state.json');
|
|
14
|
+
export function personalityStatePath(env = process.env) {
|
|
15
|
+
return join(evomapHome(env), 'evolution', 'personality_state.json');
|
|
16
16
|
}
|
|
17
|
-
export function assetsDir() {
|
|
18
|
-
return join(evomapHome(), 'assets');
|
|
17
|
+
export function assetsDir(env = process.env) {
|
|
18
|
+
return join(evomapHome(env), 'assets');
|
|
19
19
|
}
|
|
20
20
|
/** M1 raw-material substrate (append-only jsonl consumed by the cycle). */
|
|
21
|
-
export function materialDir() {
|
|
22
|
-
return join(evomapHome(), 'evolution', 'material');
|
|
21
|
+
export function materialDir(env = process.env) {
|
|
22
|
+
return join(evomapHome(env), 'evolution', 'material');
|
|
23
23
|
}
|
|
24
24
|
/** MaterialStore backing file. */
|
|
25
|
-
export function materialStorePath() {
|
|
26
|
-
return join(materialDir(), 'material.jsonl');
|
|
25
|
+
export function materialStorePath(env = process.env) {
|
|
26
|
+
return join(materialDir(env), 'material.jsonl');
|
|
27
27
|
}
|
|
28
28
|
/** Per-source watermark cursor used to make re-ingest idempotent (file-level dedup). */
|
|
29
|
-
export function materialWatermarkPath() {
|
|
30
|
-
return join(materialDir(), 'watermark.json');
|
|
29
|
+
export function materialWatermarkPath(env = process.env) {
|
|
30
|
+
return join(materialDir(env), 'watermark.json');
|
|
31
31
|
}
|
|
32
32
|
/** Proxy LLM-trace day-files dir (`llm-trace-YYYYMMDD.jsonl`), the route-savings source for the value ledger.
|
|
33
33
|
* Mirrors the proxy's EVOLVER_LLM_TRACE_DIR default so the outreach layer reads what the proxy wrote. */
|
|
34
|
-
export function tracesDir() {
|
|
35
|
-
return
|
|
34
|
+
export function tracesDir(env = process.env) {
|
|
35
|
+
return env['EVOLVER_LLM_TRACE_DIR'] ?? join(evomapHome(env), 'proxy', 'traces');
|
|
36
36
|
}
|
|
37
37
|
/** Hub-asset audit trail (`asset_call_log.jsonl`): one JSONL line per hub-asset interaction (search hit/miss,
|
|
38
38
|
* reuse/reference, publish, review). Written best-effort by AssetCallLog; the desktop's RecallHistory / 召回历程
|
|
39
39
|
* reads it. Defaults to the evomap home root, beside assets/ + evolution/.
|
|
40
40
|
* NOTE(reuse/#234): confirm this matches where the proxy/RecallHistory reads — best-effort append, so a path
|
|
41
41
|
* mismatch degrades the audit line, never the reuse write itself. */
|
|
42
|
-
export function assetCallLogPath() {
|
|
43
|
-
return join(evomapHome(), 'asset_call_log.jsonl');
|
|
42
|
+
export function assetCallLogPath(env = process.env) {
|
|
43
|
+
return join(evomapHome(env), 'asset_call_log.jsonl');
|
|
44
44
|
}
|
package/dist/events/public.d.ts
CHANGED
|
@@ -5,10 +5,12 @@ export type { Projector } from './replayer.js';
|
|
|
5
5
|
export { eventCountsProjector, DEFAULT_PROJECTORS } from './projectors.js';
|
|
6
6
|
export type { EventCountsMV } from './projectors.js';
|
|
7
7
|
export { LineTooLargeError, MAX_LINE_BYTES } from './eventStore.js';
|
|
8
|
+
export { ArchiveSegmentConflictError, InvalidRootEventArchiveError, InvalidRootEventLogError, RootEventHistoryGapError, archiveRootEvents, inspectRootEventArchive, planRootEventArchive, readRootEventHistory, rootEventArchiveDir, rootEventArchiveSegmentName, validateRootEventHistory, ROOT_EVENT_ARCHIVE_DEFAULT_KEEP_EVENTS, } from './eventArchive.js';
|
|
9
|
+
export type { RootEventArchiveOptions, RootEventArchivePlan, RootEventArchiveResult, RootEventArchiveStats, } from './eventArchive.js';
|
|
8
10
|
export { rootEventsPath, evomapHome, mvDir, personalityStatePath, assetsDir, materialDir, materialStorePath, materialWatermarkPath, tracesDir, assetCallLogPath } from './paths.js';
|
|
9
11
|
export { EVENT_SCHEMA_VERSION } from './eventSchema.js';
|
|
10
12
|
export type { RootEvent, RawEvent, HumanNarrative, Actor, Replayability } from './eventSchema.js';
|
|
11
13
|
export { readEvents, statusReport, listCycles, showCycle, listTriggers, dailySummary, buildNarrativeSnapshot, NARRATIVE_DEFAULT_LIMIT, NARRATIVE_MAX_LIMIT, } from './reports.js';
|
|
12
|
-
export { buildRetentionReport, defaultMaterialCursorPath, RETENTION_DEFAULT_MAX_MATERIAL_BYTES, RETENTION_DEFAULT_MAX_MATERIAL_RECORDS, RETENTION_DEFAULT_MAX_ROOT_BYTES, RETENTION_DEFAULT_MAX_ROOT_EVENTS, RETENTION_DEFAULT_ROOT_TAIL_EVENTS, RETENTION_DEFAULT_WATCH_RATIO, } from './retention.js';
|
|
14
|
+
export { buildRetentionReport, defaultMaterialCursorPath, defaultMaterialCursorPaths, RETENTION_DEFAULT_MAX_MATERIAL_BYTES, RETENTION_DEFAULT_MAX_MATERIAL_RECORDS, RETENTION_DEFAULT_MAX_ROOT_BYTES, RETENTION_DEFAULT_MAX_ROOT_EVENTS, RETENTION_DEFAULT_ROOT_TAIL_EVENTS, RETENTION_DEFAULT_WATCH_RATIO, } from './retention.js';
|
|
13
15
|
export type { ReportEvent, StatusReport, CycleSummary, CycleTimeline, TriggerRow, DailySummary, NarrativeEntry, NarrativeOutcome, NarrativeSnapshot, NarrativeSnapshotOptions, } from './reports.js';
|
|
14
16
|
export type { MaterialRetentionSnapshot, RetentionReport, RetentionReportOptions, RetentionState, RetentionThresholds, RootRetentionSnapshot, } from './retention.js';
|
package/dist/events/public.js
CHANGED
|
@@ -2,7 +2,8 @@ export { Ingestor, EVENT_TYPES, registerEventType, isKnownEventType, IngestValid
|
|
|
2
2
|
export { Replayer } from './replayer.js';
|
|
3
3
|
export { eventCountsProjector, DEFAULT_PROJECTORS } from './projectors.js';
|
|
4
4
|
export { LineTooLargeError, MAX_LINE_BYTES } from './eventStore.js';
|
|
5
|
+
export { ArchiveSegmentConflictError, InvalidRootEventArchiveError, InvalidRootEventLogError, RootEventHistoryGapError, archiveRootEvents, inspectRootEventArchive, planRootEventArchive, readRootEventHistory, rootEventArchiveDir, rootEventArchiveSegmentName, validateRootEventHistory, ROOT_EVENT_ARCHIVE_DEFAULT_KEEP_EVENTS, } from './eventArchive.js';
|
|
5
6
|
export { rootEventsPath, evomapHome, mvDir, personalityStatePath, assetsDir, materialDir, materialStorePath, materialWatermarkPath, tracesDir, assetCallLogPath } from './paths.js';
|
|
6
7
|
export { EVENT_SCHEMA_VERSION } from './eventSchema.js';
|
|
7
8
|
export { readEvents, statusReport, listCycles, showCycle, listTriggers, dailySummary, buildNarrativeSnapshot, NARRATIVE_DEFAULT_LIMIT, NARRATIVE_MAX_LIMIT, } from './reports.js';
|
|
8
|
-
export { buildRetentionReport, defaultMaterialCursorPath, RETENTION_DEFAULT_MAX_MATERIAL_BYTES, RETENTION_DEFAULT_MAX_MATERIAL_RECORDS, RETENTION_DEFAULT_MAX_ROOT_BYTES, RETENTION_DEFAULT_MAX_ROOT_EVENTS, RETENTION_DEFAULT_ROOT_TAIL_EVENTS, RETENTION_DEFAULT_WATCH_RATIO, } from './retention.js';
|
|
9
|
+
export { buildRetentionReport, defaultMaterialCursorPath, defaultMaterialCursorPaths, RETENTION_DEFAULT_MAX_MATERIAL_BYTES, RETENTION_DEFAULT_MAX_MATERIAL_RECORDS, RETENTION_DEFAULT_MAX_ROOT_BYTES, RETENTION_DEFAULT_MAX_ROOT_EVENTS, RETENTION_DEFAULT_ROOT_TAIL_EVENTS, RETENTION_DEFAULT_WATCH_RATIO, } from './retention.js';
|
|
@@ -4,7 +4,7 @@ export declare const RETENTION_DEFAULT_MAX_ROOT_BYTES: number;
|
|
|
4
4
|
export declare const RETENTION_DEFAULT_MAX_MATERIAL_RECORDS = 10000;
|
|
5
5
|
export declare const RETENTION_DEFAULT_MAX_MATERIAL_BYTES: number;
|
|
6
6
|
export declare const RETENTION_DEFAULT_WATCH_RATIO = 0.8;
|
|
7
|
-
export declare const RETENTION_DEFAULT_ROOT_TAIL_EVENTS
|
|
7
|
+
export declare const RETENTION_DEFAULT_ROOT_TAIL_EVENTS = 10000;
|
|
8
8
|
export interface RetentionThresholds {
|
|
9
9
|
maxRecords: number;
|
|
10
10
|
maxBytes: number;
|
|
@@ -22,6 +22,17 @@ export interface RootRetentionSnapshot {
|
|
|
22
22
|
lastSeq: number | null;
|
|
23
23
|
firstTs: string | null;
|
|
24
24
|
lastTs: string | null;
|
|
25
|
+
archiveSegments: number;
|
|
26
|
+
archiveRecords: number;
|
|
27
|
+
archiveBytes: number;
|
|
28
|
+
archiveInvalidLines: number;
|
|
29
|
+
historyRecords: number;
|
|
30
|
+
historyBytes: number;
|
|
31
|
+
historyConflicts: number;
|
|
32
|
+
historyGaps: number;
|
|
33
|
+
historyIntegrityErrors: number;
|
|
34
|
+
archiveRotationSupported: true;
|
|
35
|
+
archiveRotationSafe: boolean;
|
|
25
36
|
protectTailEvents: number;
|
|
26
37
|
destructivePruneSafe: false;
|
|
27
38
|
reason: string;
|
|
@@ -36,12 +47,22 @@ export interface MaterialRetentionSnapshot {
|
|
|
36
47
|
thresholds: RetentionThresholds;
|
|
37
48
|
firstCapturedAt: string | null;
|
|
38
49
|
lastCapturedAt: string | null;
|
|
50
|
+
archiveSegments: number;
|
|
51
|
+
archiveRecords: number;
|
|
52
|
+
archiveBytes: number;
|
|
53
|
+
archiveInvalidLines: number;
|
|
54
|
+
historyRecords: number;
|
|
55
|
+
historyBytes: number;
|
|
56
|
+
cursorCount: number;
|
|
57
|
+
minCursor: number;
|
|
39
58
|
cursorValid: boolean;
|
|
40
59
|
cursorInRange: boolean;
|
|
41
60
|
cursor: number;
|
|
42
61
|
effectiveCursor: number;
|
|
43
62
|
consumedPrefix: number;
|
|
44
63
|
pending: number;
|
|
64
|
+
archiveRotationSupported: true;
|
|
65
|
+
archiveRotationSafe: boolean;
|
|
45
66
|
destructivePruneSafe: false;
|
|
46
67
|
reason: string;
|
|
47
68
|
}
|
|
@@ -58,6 +79,7 @@ export interface RetentionReportOptions {
|
|
|
58
79
|
rootEventsPath?: string;
|
|
59
80
|
materialStorePath?: string;
|
|
60
81
|
materialCursorPath?: string;
|
|
82
|
+
materialCursorPaths?: readonly string[];
|
|
61
83
|
now?: () => number;
|
|
62
84
|
maxRootEvents?: number;
|
|
63
85
|
maxRootBytes?: number;
|
|
@@ -67,4 +89,5 @@ export interface RetentionReportOptions {
|
|
|
67
89
|
protectRootTailEvents?: number;
|
|
68
90
|
}
|
|
69
91
|
export declare function defaultMaterialCursorPath(path?: string): string;
|
|
92
|
+
export declare function defaultMaterialCursorPaths(path?: string): string[];
|
|
70
93
|
export declare function buildRetentionReport(opts?: RetentionReportOptions): RetentionReport;
|
package/dist/events/retention.js
CHANGED
|
@@ -1,24 +1,29 @@
|
|
|
1
1
|
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
2
2
|
import { dirname, join } from 'node:path';
|
|
3
3
|
import { material } from '../schema/material.js';
|
|
4
|
+
import { inspectMaterialArchive, planMaterialArchive, readMaterialHistory, } from '../material/materialArchive.js';
|
|
4
5
|
import { rootEvent } from './eventSchema.js';
|
|
6
|
+
import { ArchiveSegmentConflictError, inspectRootEventArchive, readRootEventHistory, RootEventHistoryGapError, ROOT_EVENT_ARCHIVE_DEFAULT_KEEP_EVENTS, validateRootEventHistory, } from './eventArchive.js';
|
|
5
7
|
import { materialStorePath as defaultMaterialStorePath, rootEventsPath as defaultRootEventsPath } from './paths.js';
|
|
6
|
-
import { NARRATIVE_MAX_LIMIT } from './reports.js';
|
|
7
8
|
export const RETENTION_DEFAULT_MAX_ROOT_EVENTS = 100_000;
|
|
8
9
|
export const RETENTION_DEFAULT_MAX_ROOT_BYTES = 64 * 1024 * 1024;
|
|
9
10
|
export const RETENTION_DEFAULT_MAX_MATERIAL_RECORDS = 10_000;
|
|
10
11
|
export const RETENTION_DEFAULT_MAX_MATERIAL_BYTES = 64 * 1024 * 1024;
|
|
11
12
|
export const RETENTION_DEFAULT_WATCH_RATIO = 0.8;
|
|
12
|
-
export const RETENTION_DEFAULT_ROOT_TAIL_EVENTS =
|
|
13
|
+
export const RETENTION_DEFAULT_ROOT_TAIL_EVENTS = ROOT_EVENT_ARCHIVE_DEFAULT_KEEP_EVENTS;
|
|
13
14
|
export function defaultMaterialCursorPath(path = defaultMaterialStorePath()) {
|
|
14
15
|
return join(dirname(path), 'cycle-consumer.json');
|
|
15
16
|
}
|
|
17
|
+
export function defaultMaterialCursorPaths(path = defaultMaterialStorePath()) {
|
|
18
|
+
return [defaultMaterialCursorPath(path), join(dirname(path), 'distill-consumer.json')];
|
|
19
|
+
}
|
|
16
20
|
export function buildRetentionReport(opts = {}) {
|
|
17
21
|
const now = new Date((opts.now ?? Date.now)()).toISOString();
|
|
18
22
|
const watchRatio = ratioOf(opts.watchRatio, RETENTION_DEFAULT_WATCH_RATIO);
|
|
19
23
|
const rootPath = opts.rootEventsPath ?? defaultRootEventsPath();
|
|
20
24
|
const materialPath = opts.materialStorePath ?? defaultMaterialStorePath();
|
|
21
|
-
const
|
|
25
|
+
const cursorPaths = opts.materialCursorPaths
|
|
26
|
+
?? (opts.materialCursorPath !== undefined ? [opts.materialCursorPath] : defaultMaterialCursorPaths(materialPath));
|
|
22
27
|
const rootThresholds = {
|
|
23
28
|
maxRecords: positiveInt(opts.maxRootEvents, RETENTION_DEFAULT_MAX_ROOT_EVENTS),
|
|
24
29
|
maxBytes: positiveInt(opts.maxRootBytes, RETENTION_DEFAULT_MAX_ROOT_BYTES),
|
|
@@ -30,7 +35,7 @@ export function buildRetentionReport(opts = {}) {
|
|
|
30
35
|
watchRatio,
|
|
31
36
|
};
|
|
32
37
|
const rootEvents = rootSnapshot(rootPath, rootThresholds, positiveInt(opts.protectRootTailEvents, RETENTION_DEFAULT_ROOT_TAIL_EVENTS));
|
|
33
|
-
const material = materialSnapshot(materialPath,
|
|
38
|
+
const material = materialSnapshot(materialPath, cursorPaths, materialThresholds);
|
|
34
39
|
const warnings = buildWarnings(rootEvents, material);
|
|
35
40
|
const nextActions = buildNextActions(rootEvents, material);
|
|
36
41
|
return {
|
|
@@ -45,6 +50,22 @@ export function buildRetentionReport(opts = {}) {
|
|
|
45
50
|
}
|
|
46
51
|
function rootSnapshot(path, thresholds, protectTailEvents) {
|
|
47
52
|
const stats = readJsonl(path, (value) => rootEvent.parse(value));
|
|
53
|
+
const archive = inspectRootEventArchive(path);
|
|
54
|
+
const historyRecords = readRootEventHistory(path).length;
|
|
55
|
+
let historyConflicts = 0;
|
|
56
|
+
let historyGaps = 0;
|
|
57
|
+
let historyIntegrityErrors = 0;
|
|
58
|
+
try {
|
|
59
|
+
validateRootEventHistory(path);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
if (error instanceof ArchiveSegmentConflictError)
|
|
63
|
+
historyConflicts = 1;
|
|
64
|
+
else if (error instanceof RootEventHistoryGapError)
|
|
65
|
+
historyGaps = 1;
|
|
66
|
+
else
|
|
67
|
+
historyIntegrityErrors = 1;
|
|
68
|
+
}
|
|
48
69
|
return {
|
|
49
70
|
name: 'root_events',
|
|
50
71
|
exists: stats.exists,
|
|
@@ -57,34 +78,67 @@ function rootSnapshot(path, thresholds, protectTailEvents) {
|
|
|
57
78
|
lastSeq: stats.last?.seq ?? null,
|
|
58
79
|
firstTs: stats.first?.ts ?? null,
|
|
59
80
|
lastTs: stats.last?.ts ?? null,
|
|
81
|
+
archiveSegments: archive.segments,
|
|
82
|
+
archiveRecords: archive.records,
|
|
83
|
+
archiveBytes: archive.bytes,
|
|
84
|
+
archiveInvalidLines: archive.invalidLines,
|
|
85
|
+
historyRecords,
|
|
86
|
+
historyBytes: archive.bytes + stats.bytes,
|
|
87
|
+
historyConflicts,
|
|
88
|
+
historyGaps,
|
|
89
|
+
historyIntegrityErrors,
|
|
90
|
+
archiveRotationSupported: true,
|
|
91
|
+
archiveRotationSafe: stats.invalidLines === 0 && archive.invalidLines === 0 && historyConflicts === 0 && historyGaps === 0 && historyIntegrityErrors === 0,
|
|
60
92
|
protectTailEvents: Math.min(stats.records, protectTailEvents),
|
|
61
93
|
destructivePruneSafe: false,
|
|
62
|
-
reason: '
|
|
94
|
+
reason: 'archive rotation preserves replay history; destructive archive deletion remains disabled',
|
|
63
95
|
};
|
|
64
96
|
}
|
|
65
|
-
function materialSnapshot(path,
|
|
97
|
+
function materialSnapshot(path, cursorPaths, thresholds) {
|
|
66
98
|
const stats = readJsonl(path, (value) => material.parse(value));
|
|
67
|
-
const
|
|
68
|
-
const
|
|
69
|
-
const
|
|
99
|
+
const archive = inspectMaterialArchive(path);
|
|
100
|
+
const history = readMaterialHistory(path);
|
|
101
|
+
const historyRecords = history.length;
|
|
102
|
+
const cursors = readMaterialCursors(cursorPaths, historyRecords, archive.records);
|
|
103
|
+
const effectiveCursor = cursors.inRange ? cursors.cycle : clampCursor(cursors.cycle, historyRecords);
|
|
104
|
+
const effectiveMinimum = cursors.inRange ? cursors.min : clampCursor(cursors.min, historyRecords);
|
|
105
|
+
let archiveRotationSafe = stats.invalidLines === 0 && archive.invalidLines === 0 && cursors.valid && cursors.inRange;
|
|
106
|
+
if (archiveRotationSafe) {
|
|
107
|
+
try {
|
|
108
|
+
planMaterialArchive({ path, cursorPaths, keepRecords: 1 });
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
archiveRotationSafe = false;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
70
114
|
return {
|
|
71
115
|
name: 'material',
|
|
72
|
-
exists: stats.exists,
|
|
116
|
+
exists: stats.exists || archive.exists,
|
|
73
117
|
bytes: stats.bytes,
|
|
74
118
|
records: stats.records,
|
|
75
119
|
invalidLines: stats.invalidLines,
|
|
76
120
|
state: retentionState(stats.records, stats.bytes, thresholds),
|
|
77
121
|
thresholds,
|
|
78
|
-
firstCapturedAt:
|
|
79
|
-
lastCapturedAt:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
122
|
+
firstCapturedAt: history[0]?.capturedAt ?? null,
|
|
123
|
+
lastCapturedAt: history[history.length - 1]?.capturedAt ?? null,
|
|
124
|
+
archiveSegments: archive.segments,
|
|
125
|
+
archiveRecords: archive.records,
|
|
126
|
+
archiveBytes: archive.bytes,
|
|
127
|
+
archiveInvalidLines: archive.invalidLines,
|
|
128
|
+
historyRecords,
|
|
129
|
+
historyBytes: archive.bytes + stats.bytes,
|
|
130
|
+
cursorCount: cursors.count,
|
|
131
|
+
minCursor: effectiveMinimum,
|
|
132
|
+
cursorValid: cursors.valid,
|
|
133
|
+
cursorInRange: cursors.inRange,
|
|
134
|
+
cursor: cursors.cycle,
|
|
83
135
|
effectiveCursor,
|
|
84
|
-
consumedPrefix:
|
|
85
|
-
pending: Math.max(0,
|
|
136
|
+
consumedPrefix: effectiveMinimum,
|
|
137
|
+
pending: Math.max(0, historyRecords - effectiveCursor),
|
|
138
|
+
archiveRotationSupported: true,
|
|
139
|
+
archiveRotationSafe,
|
|
86
140
|
destructivePruneSafe: false,
|
|
87
|
-
reason: '
|
|
141
|
+
reason: 'archive rotation preserves absolute consumer cursors and full material history; destructive archive deletion remains disabled',
|
|
88
142
|
};
|
|
89
143
|
}
|
|
90
144
|
function readJsonl(path, parse) {
|
|
@@ -111,19 +165,49 @@ function readJsonl(path, parse) {
|
|
|
111
165
|
}
|
|
112
166
|
return { exists: true, bytes, records, invalidLines, first, last };
|
|
113
167
|
}
|
|
114
|
-
function
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
168
|
+
function readMaterialCursors(paths, historyRecords, archiveRecords) {
|
|
169
|
+
let valid = true;
|
|
170
|
+
let inRange = true;
|
|
171
|
+
let cycle = 0;
|
|
172
|
+
let cycleFound = false;
|
|
173
|
+
const values = [];
|
|
174
|
+
for (const path of paths) {
|
|
175
|
+
if (!existsSync(path))
|
|
176
|
+
continue;
|
|
177
|
+
let parsed;
|
|
178
|
+
try {
|
|
179
|
+
parsed = JSON.parse(readFileSync(path, 'utf8'));
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
valid = false;
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
186
|
+
valid = false;
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
for (const [group, value] of Object.entries(parsed)) {
|
|
190
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
191
|
+
valid = false;
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
const position = value;
|
|
195
|
+
values.push(position);
|
|
196
|
+
if (position > historyRecords)
|
|
197
|
+
inRange = false;
|
|
198
|
+
if (group === 'cycle' && !cycleFound) {
|
|
199
|
+
cycle = position;
|
|
200
|
+
cycleFound = true;
|
|
201
|
+
}
|
|
121
202
|
}
|
|
122
|
-
return { exists: true, valid: false, value: 0 };
|
|
123
|
-
}
|
|
124
|
-
catch {
|
|
125
|
-
return { exists: true, valid: false, value: 0 };
|
|
126
203
|
}
|
|
204
|
+
return {
|
|
205
|
+
valid,
|
|
206
|
+
inRange,
|
|
207
|
+
count: values.length,
|
|
208
|
+
cycle,
|
|
209
|
+
min: values.length === 0 ? archiveRecords : Math.min(...values),
|
|
210
|
+
};
|
|
127
211
|
}
|
|
128
212
|
function retentionState(records, bytes, thresholds) {
|
|
129
213
|
if (records > thresholds.maxRecords || bytes > thresholds.maxBytes)
|
|
@@ -136,30 +220,42 @@ function buildWarnings(root, mat) {
|
|
|
136
220
|
const out = [];
|
|
137
221
|
if (root.invalidLines > 0)
|
|
138
222
|
out.push(`root_events has ${root.invalidLines} invalid jsonl line(s); recover before rotating`);
|
|
223
|
+
if (root.archiveInvalidLines > 0)
|
|
224
|
+
out.push(`root_events archive has ${root.archiveInvalidLines} invalid jsonl line(s); repair archive integrity before rotating again`);
|
|
225
|
+
if (root.historyConflicts > 0)
|
|
226
|
+
out.push('root_events active/archive history has conflicting seq records; repair audit integrity before rotating');
|
|
227
|
+
if (root.historyGaps > 0)
|
|
228
|
+
out.push('root_events active/archive history has a seq gap; restore the missing audit segment before rotating');
|
|
229
|
+
if (root.historyIntegrityErrors > 0)
|
|
230
|
+
out.push('root_events history fails structural integrity checks; repair event ordering before rotating');
|
|
139
231
|
if (mat.invalidLines > 0)
|
|
140
232
|
out.push(`material store has ${mat.invalidLines} invalid jsonl line(s); inspect before rotating`);
|
|
141
233
|
if (!mat.cursorValid)
|
|
142
234
|
out.push('material cursor is unreadable; retention uses effectiveCursor=0 until the cursor is repaired');
|
|
143
235
|
if (mat.cursorValid && !mat.cursorInRange)
|
|
144
|
-
out.push(`material cursor ${mat.cursor} is outside material record range 0..${mat.
|
|
236
|
+
out.push(`material cursor ${mat.cursor} is outside material record range 0..${mat.historyRecords}; retention uses effectiveCursor=${mat.effectiveCursor}`);
|
|
145
237
|
if (root.state === 'over_limit')
|
|
146
|
-
out.push('root_events exceeds retention thresholds;
|
|
238
|
+
out.push('root_events exceeds retention thresholds for the active log; preview archive rotation before writing');
|
|
239
|
+
if (mat.archiveInvalidLines > 0)
|
|
240
|
+
out.push(`material archive has ${mat.archiveInvalidLines} invalid jsonl line(s); repair archive integrity before rotating again`);
|
|
241
|
+
if (!mat.archiveRotationSafe)
|
|
242
|
+
out.push('material active/archive/cursor state is not safe for rotation; run archive-material preview after repairing integrity');
|
|
147
243
|
if (mat.state === 'over_limit')
|
|
148
|
-
out.push('material store exceeds retention thresholds;
|
|
244
|
+
out.push('material active store exceeds retention thresholds; preview absolute-cursor archive rotation before writing');
|
|
149
245
|
if (mat.pending > 0)
|
|
150
246
|
out.push(`material store has ${mat.pending} pending record(s); do not prune pending material`);
|
|
151
247
|
return out;
|
|
152
248
|
}
|
|
153
249
|
function buildNextActions(root, mat) {
|
|
154
250
|
const out = [
|
|
155
|
-
'keep destructive prune disabled
|
|
251
|
+
'archive rotation is available; keep destructive prune disabled for archive deletion',
|
|
156
252
|
];
|
|
157
253
|
if (root.state !== 'ok')
|
|
158
|
-
out.push(`root_events ${root.state}: keep at least the last ${root.protectTailEvents} event(s)
|
|
254
|
+
out.push(`root_events ${root.state}: run retention archive-root preview, then keep at least the last ${root.protectTailEvents} active event(s)`);
|
|
159
255
|
if (!mat.cursorValid || !mat.cursorInRange)
|
|
160
|
-
out.push('material: repair the cycle cursor before archiving consumed material');
|
|
161
|
-
if (mat.consumedPrefix >
|
|
162
|
-
out.push(`material: ${mat.consumedPrefix} consumed prefix record(s)
|
|
256
|
+
out.push('material: repair the cycle cursor and any other durable consumer cursor before archiving consumed material');
|
|
257
|
+
if (mat.consumedPrefix > mat.archiveRecords)
|
|
258
|
+
out.push(`material: ${mat.consumedPrefix - mat.archiveRecords} consumed prefix record(s) may be archived with archive-material without rewriting cursors`);
|
|
163
259
|
if (mat.pending > 0)
|
|
164
260
|
out.push('material: process or inspect pending records before any future prune');
|
|
165
261
|
return out;
|
package/dist/exec/autoExec.d.ts
CHANGED
|
@@ -2,13 +2,14 @@ import type { AssetStoreProvider } from '../assetstore/provider.js';
|
|
|
2
2
|
import { type ProvenanceStore } from '../assetstore/provenance.js';
|
|
3
3
|
import type { ReviewLedger } from '../assetstore/reviewLedger.js';
|
|
4
4
|
import type { GeneCandidateInput } from '../algo/geneSelection.js';
|
|
5
|
-
import type { CycleEngine, SolidifyPermitGate } from '../algo/cycleEngine.js';
|
|
5
|
+
import type { CycleEngine, ExecutionFailureKind, SolidifyPermitGate } from '../algo/cycleEngine.js';
|
|
6
6
|
import { type AutonomousSafety } from './autonomousCycle.js';
|
|
7
7
|
import type { GitRunner, ValidateHook } from './claudeBridge.js';
|
|
8
8
|
import type { AgentRunner } from './runnerRegistry.js';
|
|
9
9
|
import { type OpenPrLister } from './openPrRegistry.js';
|
|
10
10
|
import type { ReuseOutcomeSummary, ReuseOutcomeEvent } from '../ops/reuseOutcomes.js';
|
|
11
11
|
import type { PersonalityStore } from '../personality/store.js';
|
|
12
|
+
import type { MemoryGraphProvider } from '../algo/memoryGraph.js';
|
|
12
13
|
export interface AutoExecTask {
|
|
13
14
|
id: string;
|
|
14
15
|
repo: string;
|
|
@@ -39,6 +40,8 @@ export interface AutoExecVerdict {
|
|
|
39
40
|
score: number;
|
|
40
41
|
};
|
|
41
42
|
proofOfWork?: unknown;
|
|
43
|
+
failureKind?: ExecutionFailureKind;
|
|
44
|
+
exitCode?: number | null;
|
|
42
45
|
usedAssetIds?: readonly string[];
|
|
43
46
|
}
|
|
44
47
|
/**
|
|
@@ -97,6 +100,8 @@ export interface AutoExecDeps {
|
|
|
97
100
|
/** Observed `value.recall` events (#274 slice 3): folded into the same soft re-order as reuseOutcomes (lower
|
|
98
101
|
* weight) so transcript-observed recall influences selection. Forwarded to runEvolutionCycle. Omit → none. */
|
|
99
102
|
recallEvents?: readonly ReuseOutcomeEvent[];
|
|
103
|
+
/** Scoped local MemoryGraph seam. Queries and records structured outcome data only. */
|
|
104
|
+
memoryGraph?: MemoryGraphProvider;
|
|
100
105
|
/** Optional daemon-level explicit strategy preset name, e.g. EVOLVE_STRATEGY. */
|
|
101
106
|
strategyName?: string;
|
|
102
107
|
/** Optional evolvable personality store shared with CycleEngine and the exec prompt. */
|
package/dist/exec/autoExec.js
CHANGED
|
@@ -122,6 +122,9 @@ export async function runAutoExecTask(deps, rawTask, safety) {
|
|
|
122
122
|
const gi = intakeGene({
|
|
123
123
|
category: 'repair', signals_match: cycleSignals, strategy: [...task.strategy],
|
|
124
124
|
summary: task.expectedEffect.slice(0, 80), ...(task.validationCmds ? { validation: [...task.validationCmds] } : {}),
|
|
125
|
+
// A task's seeded strategy is an execution-entry seed (the operator/daemon supplied a learned strategy to
|
|
126
|
+
// run/evolve), not a skill/session transcription → `evolved` per V1 #302 classifyProvenance.
|
|
127
|
+
generation_meta: { source: 'evolved' },
|
|
125
128
|
});
|
|
126
129
|
if (gi.ok && gi.gene) {
|
|
127
130
|
await deps.store.put(gi.gene);
|
|
@@ -158,6 +161,15 @@ export async function runAutoExecTask(deps, rawTask, safety) {
|
|
|
158
161
|
// The forced pick still passes every hard gate downstream (candidate pool, ban, epigenetic
|
|
159
162
|
// suppression), so this never bypasses trust/review/inert filtering.
|
|
160
163
|
const cycleForcedGeneId = task.forcedGeneId ?? seededStrategyGeneId;
|
|
164
|
+
let memoryGraphAdvice;
|
|
165
|
+
if (deps.memoryGraph) {
|
|
166
|
+
try {
|
|
167
|
+
memoryGraphAdvice = await deps.memoryGraph.query({ workspace: task.repo, signals: cycleSignals });
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
memoryGraphAdvice = undefined;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
161
173
|
const res = await runEvolutionCycle(deps.engine, deps.store, {
|
|
162
174
|
...(deps.provenance ? { provenance: deps.provenance } : {}),
|
|
163
175
|
...(deps.review ? { review: deps.review } : {}),
|
|
@@ -166,6 +178,7 @@ export async function runAutoExecTask(deps, rawTask, safety) {
|
|
|
166
178
|
...(deps.solidifyPermit ? { solidifyPermit: deps.solidifyPermit } : {}),
|
|
167
179
|
...(deps.reuseOutcomes ? { reuseOutcomes: deps.reuseOutcomes } : {}),
|
|
168
180
|
...(deps.recallEvents ? { recallEvents: deps.recallEvents } : {}),
|
|
181
|
+
...(memoryGraphAdvice ? { memoryGraphAdvice } : {}),
|
|
169
182
|
...(strategyName !== undefined ? { strategyName } : {}),
|
|
170
183
|
...(cycleForcedGeneId !== undefined ? { forcedGeneId: cycleForcedGeneId } : {}),
|
|
171
184
|
cycleId,
|
|
@@ -181,6 +194,25 @@ export async function runAutoExecTask(deps, rawTask, safety) {
|
|
|
181
194
|
});
|
|
182
195
|
const status = res.finalStage === 'solidified' ? 'solidified' : res.finalStage === 'failed' ? 'failed' : 'innovated';
|
|
183
196
|
const cap = res.capsule;
|
|
197
|
+
if (deps.memoryGraph && res.decision?.selectedGeneId && (res.finalStage === 'solidified' || res.finalStage === 'failed')) {
|
|
198
|
+
const producedSuccess = res.finalStage === 'solidified' && res.producedValue === true;
|
|
199
|
+
try {
|
|
200
|
+
await deps.memoryGraph.recordOutcome({
|
|
201
|
+
workspace: task.repo,
|
|
202
|
+
signals: cycleSignals,
|
|
203
|
+
geneId: res.decision.selectedGeneId,
|
|
204
|
+
// MemoryGraph has no inert status yet, so record a no-op as conservative failed evidence instead of reward.
|
|
205
|
+
status: producedSuccess ? 'success' : 'failed',
|
|
206
|
+
score: res.finalStage === 'solidified' && !res.producedValue
|
|
207
|
+
? 0
|
|
208
|
+
: cap?.outcome?.score ?? (producedSuccess ? 1 : 0),
|
|
209
|
+
at: new Date().toISOString(),
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
// Memory persistence is advisory and must never fail the autonomous task.
|
|
214
|
+
}
|
|
215
|
+
}
|
|
184
216
|
const hubAssetIds = new Set(hubCandidates.map((c) => c.assetId).filter((id) => typeof id === 'string' && id.length > 0));
|
|
185
217
|
const selectedAssetId = res.decision?.selectedAssetId;
|
|
186
218
|
const usedAssetIds = selectedAssetId && hubAssetIds.has(selectedAssetId) ? [selectedAssetId] : [];
|
|
@@ -189,6 +221,8 @@ export async function runAutoExecTask(deps, rawTask, safety) {
|
|
|
189
221
|
...(res.reasons.length > 0 && status !== 'solidified' ? { reason: res.reasons.join('; ') } : {}),
|
|
190
222
|
...(cap?.outcome ? { outcome: cap.outcome } : {}),
|
|
191
223
|
...(cap?.proof_of_work ? { proofOfWork: cap.proof_of_work } : {}),
|
|
224
|
+
...(res.failureKind !== undefined ? { failureKind: res.failureKind } : {}),
|
|
225
|
+
...(res.exitCode !== undefined ? { exitCode: res.exitCode } : {}),
|
|
192
226
|
...(usedAssetIds.length > 0 ? { usedAssetIds } : {}),
|
|
193
227
|
};
|
|
194
228
|
}
|
|
@@ -29,6 +29,8 @@ export interface AutonomousSafety {
|
|
|
29
29
|
/** Only embed trusted gene strategies (#45). Default true. */
|
|
30
30
|
requireTrustedGene?: boolean;
|
|
31
31
|
timeoutMs?: number;
|
|
32
|
+
/** Cooperative cancellation propagated to the spawned runner process tree. */
|
|
33
|
+
signal?: AbortSignal;
|
|
32
34
|
}
|
|
33
35
|
/**
|
|
34
36
|
* Build the fully-hardened `execute` for an autonomous run against `repo`. Composes every exec-bridge control
|
|
@@ -43,12 +43,16 @@ const CODEX_DEFAULT_AGENT_OPTIONS = {};
|
|
|
43
43
|
// auto-approve shell+write, but Cursor has no verified per-run allowlist/sandbox mapping yet, so skipPermissions
|
|
44
44
|
// is refused outright. Use default cursor with worktree isolation until the CLI is run-verified.
|
|
45
45
|
const CURSOR_DEFAULT_AGENT_OPTIONS = {};
|
|
46
|
+
// Gemini's verified safe default is `--approval-mode auto_edit`; shell remains gated and --yolo is refused.
|
|
47
|
+
const GEMINI_DEFAULT_AGENT_OPTIONS = {};
|
|
46
48
|
/** Per-runner safe default agent options — claude bypasses-with-bounds; codex + cursor stay non-bypassing (codex sandboxed; cursor skip refused, #66). */
|
|
47
49
|
function defaultAgentOptions(runner) {
|
|
48
50
|
if (runner === 'codex')
|
|
49
51
|
return CODEX_DEFAULT_AGENT_OPTIONS;
|
|
50
52
|
if (runner === 'cursor')
|
|
51
53
|
return CURSOR_DEFAULT_AGENT_OPTIONS;
|
|
54
|
+
if (runner === 'gemini')
|
|
55
|
+
return GEMINI_DEFAULT_AGENT_OPTIONS;
|
|
52
56
|
return CLAUDE_DEFAULT_AGENT_OPTIONS;
|
|
53
57
|
}
|
|
54
58
|
/**
|
|
@@ -70,6 +74,7 @@ export function makeSafeExecute(repo, store, safety, opts = {}) {
|
|
|
70
74
|
requireTrustedGene: safety.requireTrustedGene ?? true,
|
|
71
75
|
agentOptions: safety.agentOptions ?? defaultAgentOptions(safety.runner),
|
|
72
76
|
...(safety.timeoutMs !== undefined ? { timeoutMs: safety.timeoutMs } : {}),
|
|
77
|
+
...(safety.signal ? { signal: safety.signal } : {}),
|
|
73
78
|
resolveGene: makeTrustedGeneResolver(store, opts.provenance, opts.review, opts.includeProbation ?? false),
|
|
74
79
|
...(opts.validate ? { validate: opts.validate } : {}),
|
|
75
80
|
...(opts.validationCmds ? { validationCmds: opts.validationCmds } : {}),
|
|
@@ -4,10 +4,16 @@ import type { ExecutionResult } from '../algo/cycleEngine.js';
|
|
|
4
4
|
import { type GeneStrategyInfo } from './prompt.js';
|
|
5
5
|
import type { PersonalityStore } from '../personality/store.js';
|
|
6
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';
|
|
7
|
+
export { resolveSpawnCommand, spawnCapture, DEFAULT_MAX_CAPTURE_BYTES, UnboundedSkipPermissionsError, UnsupportedCursorSkipPermissionsError, UnsupportedGeminiPermissionOptionsError, claudeRunnerArgs, makeClaudeHeadlessRunner, claudeHeadlessRunner, codexRunnerArgs, makeCodexHeadlessRunner, cursorRunnerArgs, makeCursorHeadlessRunner, getRunnerSpec, geminiRunnerArgs, makeGeminiHeadlessRunner, classifyGeminiRunnerResult, } from './runnerRegistry.js';
|
|
8
8
|
export type { AgentRunContext, AgentRunResult, AgentRunner, RunnerName, AgentRunnerOptions, ClaudeRunnerOptions, CodexRunnerOptions, AgentRunnerSpec, } from './runnerRegistry.js';
|
|
9
|
+
export interface GitRunnerOptions {
|
|
10
|
+
processSignalMode?: 'cancel' | 'ignore';
|
|
11
|
+
}
|
|
9
12
|
/** Run a git subcommand in cwd and return its stdout. */
|
|
10
|
-
export type GitRunner = (args: readonly string[], cwd: string) => Promise<string>;
|
|
13
|
+
export type GitRunner = (args: readonly string[], cwd: string, signal?: AbortSignal, options?: GitRunnerOptions) => Promise<string>;
|
|
14
|
+
export type GitPatchWriter = (args: readonly string[], cwd: string, destination: string, signal?: AbortSignal,
|
|
15
|
+
/** Call immediately after this writer exclusively creates `destination`. */
|
|
16
|
+
onDestinationOpened?: () => void) => Promise<void>;
|
|
11
17
|
/** Resolve the selected gene's learned strategy (for prompt enrichment). */
|
|
12
18
|
export type GeneResolver = (geneId: string) => Promise<GeneStrategyInfo | null> | GeneStrategyInfo | null;
|
|
13
19
|
/** Decide success from the post-run working tree (e.g. run the gene's validation plan). */
|
|
@@ -29,6 +35,12 @@ export interface ExecBridgeOptions {
|
|
|
29
35
|
agentOptions?: AgentRunnerOptions;
|
|
30
36
|
/** Default: spawns `git`. Inject a fake in tests. */
|
|
31
37
|
git?: GitRunner;
|
|
38
|
+
/** Optional complete-patch sink. The default streams built-in git output directly to disk. */
|
|
39
|
+
gitPatchWriter?: GitPatchWriter;
|
|
40
|
+
/** Test seam for fallback patch persistence; production callers should use the exclusive private writer. */
|
|
41
|
+
writePatchFile?: (path: string, patch: string) => void;
|
|
42
|
+
/** Test seam for temporary patch cleanup; production callers should use the filesystem default. */
|
|
43
|
+
removePatchFile?: (path: string) => void;
|
|
32
44
|
/** Default: EVOLVE_EXEC_BRIDGE === '1'. Set true to force-enable (e.g. integration tests). */
|
|
33
45
|
enabled?: boolean;
|
|
34
46
|
/**
|
|
@@ -57,6 +69,8 @@ export interface ExecBridgeOptions {
|
|
|
57
69
|
requireTrustedGene?: boolean;
|
|
58
70
|
/** Per-run agent timeout. Default 600_000ms (10 min). */
|
|
59
71
|
timeoutMs?: number;
|
|
72
|
+
/** Cooperative cancellation propagated to the runner process tree. */
|
|
73
|
+
signal?: AbortSignal;
|
|
60
74
|
/** Optional: enrich the prompt with the selected gene's strategy. */
|
|
61
75
|
resolveGene?: GeneResolver;
|
|
62
76
|
/** Optional: validation commands surfaced in the prompt's done-criteria. */
|
|
@@ -94,6 +108,9 @@ export declare class ExecBridgeForbiddenError extends Error {
|
|
|
94
108
|
export declare class UnsandboxedFullAccessRequiresIsolationError extends Error {
|
|
95
109
|
constructor();
|
|
96
110
|
}
|
|
111
|
+
export declare class UnsafeWorktreePathError extends Error {
|
|
112
|
+
constructor(reason: string);
|
|
113
|
+
}
|
|
97
114
|
/**
|
|
98
115
|
* Whitelist-filter `env` for a spawned agent/tool: keep ONLY the minimal runtime env + the caller-declared
|
|
99
116
|
* extras (the runner's own auth via allowPrefixes/allowKeys); drop everything else. Fail-safe by construction —
|
|
@@ -103,8 +120,9 @@ export declare function scrubAgentEnv(env: NodeJS.ProcessEnv, opts?: {
|
|
|
103
120
|
allowKeys?: readonly string[];
|
|
104
121
|
allowPrefixes?: readonly string[];
|
|
105
122
|
}): NodeJS.ProcessEnv;
|
|
106
|
-
/** Default git runner:
|
|
123
|
+
/** Default git runner: every incomplete command result fails closed. */
|
|
107
124
|
export declare const defaultGitRunner: GitRunner;
|
|
125
|
+
export declare const defaultGitPatchWriter: GitPatchWriter;
|
|
108
126
|
/**
|
|
109
127
|
* Build the `execute` function CycleEngine/runEvolutionCycle consume. Default-off: throws
|
|
110
128
|
* ExecBridgeDisabledError on first call unless enabled.
|