@evomap/evolver-core 2.0.0-beta.1 → 2.0.0-beta.3
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 +132 -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 +23 -0
- package/dist/assetstore/assetSidecarRecords.js +142 -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 +318 -0
- package/dist/assetstore/assetSyncLedger.d.ts +32 -0
- package/dist/assetstore/assetSyncLedger.js +66 -0
- package/dist/assetstore/index.d.ts +5 -1
- package/dist/assetstore/index.js +5 -1
- package/dist/assetstore/localJsonl.d.ts +10 -2
- package/dist/assetstore/localJsonl.js +93 -37
- package/dist/assetstore/pendingSignals.js +3 -1
- package/dist/assetstore/provenance.d.ts +20 -2
- package/dist/assetstore/provenance.js +92 -56
- package/dist/assetstore/provider.d.ts +2 -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 +2 -0
- package/dist/events/paths.d.ts +1 -1
- package/dist/events/paths.js +2 -2
- 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 +7 -2
- package/dist/exec/claudeBridge.js +115 -14
- package/dist/exec/prompt.js +9 -0
- package/dist/exec/runnerRegistry.d.ts +64 -18
- package/dist/exec/runnerRegistry.js +341 -38
- 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/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 +44 -2
- 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/schema/common.d.ts +1 -1
- package/dist/schema/common.js +1 -1
- package/dist/schema/material.d.ts +5 -5
- package/dist/trace/trajectoryExport.js +2 -2
- package/dist/util/fileLock.d.ts +19 -2
- package/dist/util/fileLock.js +166 -31
- 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/package.json +6 -1
|
@@ -21,7 +21,7 @@ export type Watermark = z.infer<typeof watermark>;
|
|
|
21
21
|
export declare const material: z.ZodEffects<z.ZodObject<{
|
|
22
22
|
materialId: z.ZodString;
|
|
23
23
|
/** Runtime agent that produced a session/tool source. Absent for agent-agnostic origins (proxy trace), #95. */
|
|
24
|
-
sourceAgent: z.ZodOptional<z.ZodEnum<["claude-code", "codex", "cursor", "gemini", "kimi", "kiro", "opencode", "generic-chat"]>>;
|
|
24
|
+
sourceAgent: z.ZodOptional<z.ZodEnum<["claude-code", "codex", "cursor", "gemini", "antigravity", "kimi", "kiro", "opencode", "generic-chat"]>>;
|
|
25
25
|
/** Origin class: a runtime agent session, or the proxy gateway's LLM trace (agent-agnostic), #95.
|
|
26
26
|
* Defaults to runtime_session so pre-#95 records (which only ever held sessions) parse unchanged. */
|
|
27
27
|
sourceKind: z.ZodDefault<z.ZodEnum<["runtime_session", "proxy_trace"]>>;
|
|
@@ -76,7 +76,7 @@ export declare const material: z.ZodEffects<z.ZodObject<{
|
|
|
76
76
|
consumerGroup: string;
|
|
77
77
|
feedsMaterial: boolean;
|
|
78
78
|
extensions: Record<string, unknown>;
|
|
79
|
-
sourceAgent?: "claude-code" | "codex" | "cursor" | "gemini" | "kimi" | "kiro" | "opencode" | "generic-chat" | undefined;
|
|
79
|
+
sourceAgent?: "claude-code" | "codex" | "cursor" | "gemini" | "antigravity" | "kimi" | "kiro" | "opencode" | "generic-chat" | undefined;
|
|
80
80
|
payloadRef?: {
|
|
81
81
|
path: string;
|
|
82
82
|
sha256: string;
|
|
@@ -95,7 +95,7 @@ export declare const material: z.ZodEffects<z.ZodObject<{
|
|
|
95
95
|
};
|
|
96
96
|
capturedAt: string;
|
|
97
97
|
consumerGroup: string;
|
|
98
|
-
sourceAgent?: "claude-code" | "codex" | "cursor" | "gemini" | "kimi" | "kiro" | "opencode" | "generic-chat" | undefined;
|
|
98
|
+
sourceAgent?: "claude-code" | "codex" | "cursor" | "gemini" | "antigravity" | "kimi" | "kiro" | "opencode" | "generic-chat" | undefined;
|
|
99
99
|
sourceKind?: "runtime_session" | "proxy_trace" | undefined;
|
|
100
100
|
payloadRef?: {
|
|
101
101
|
path: string;
|
|
@@ -120,7 +120,7 @@ export declare const material: z.ZodEffects<z.ZodObject<{
|
|
|
120
120
|
consumerGroup: string;
|
|
121
121
|
feedsMaterial: boolean;
|
|
122
122
|
extensions: Record<string, unknown>;
|
|
123
|
-
sourceAgent?: "claude-code" | "codex" | "cursor" | "gemini" | "kimi" | "kiro" | "opencode" | "generic-chat" | undefined;
|
|
123
|
+
sourceAgent?: "claude-code" | "codex" | "cursor" | "gemini" | "antigravity" | "kimi" | "kiro" | "opencode" | "generic-chat" | undefined;
|
|
124
124
|
payloadRef?: {
|
|
125
125
|
path: string;
|
|
126
126
|
sha256: string;
|
|
@@ -139,7 +139,7 @@ export declare const material: z.ZodEffects<z.ZodObject<{
|
|
|
139
139
|
};
|
|
140
140
|
capturedAt: string;
|
|
141
141
|
consumerGroup: string;
|
|
142
|
-
sourceAgent?: "claude-code" | "codex" | "cursor" | "gemini" | "kimi" | "kiro" | "opencode" | "generic-chat" | undefined;
|
|
142
|
+
sourceAgent?: "claude-code" | "codex" | "cursor" | "gemini" | "antigravity" | "kimi" | "kiro" | "opencode" | "generic-chat" | undefined;
|
|
143
143
|
sourceKind?: "runtime_session" | "proxy_trace" | undefined;
|
|
144
144
|
payloadRef?: {
|
|
145
145
|
path: string;
|
|
@@ -1558,7 +1558,7 @@ function runtimeSessionId(input) {
|
|
|
1558
1558
|
return explicit;
|
|
1559
1559
|
const sourcePath = stringValue(input.sourcePath);
|
|
1560
1560
|
const base = sourcePath.split(/[\\/]/).filter(Boolean).pop() ?? '';
|
|
1561
|
-
return base.replace(/\.jsonl?$/i, '') || 'unknown';
|
|
1561
|
+
return redactString(base.replace(/\.jsonl?$/i, '')) || 'unknown';
|
|
1562
1562
|
}
|
|
1563
1563
|
function nativeCallHasField(call, key) {
|
|
1564
1564
|
return Object.prototype.hasOwnProperty.call(call, key);
|
|
@@ -1704,7 +1704,7 @@ export function buildCodingTrajectoryFromSessionLog(input) {
|
|
|
1704
1704
|
session_id: sessionId,
|
|
1705
1705
|
source_kind: 'runtime_session',
|
|
1706
1706
|
source_agent: sourceAgent,
|
|
1707
|
-
source_path: sourcePath,
|
|
1707
|
+
source_path: redactString(sourcePath),
|
|
1708
1708
|
...(sessionModel ? { session_model: sessionModel } : {}),
|
|
1709
1709
|
...(provider !== sourceAgent ? { session_provider: provider } : {}),
|
|
1710
1710
|
...(sessionTools !== undefined ? { session_tools: redactRuntimeStructuredValue(sessionTools) } : {}),
|
package/dist/util/fileLock.d.ts
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
export declare function syncSleep(ms: number): void;
|
|
2
2
|
export declare class LockTimeoutError extends Error {
|
|
3
3
|
readonly code = "LOCK_TIMEOUT";
|
|
4
|
-
constructor(
|
|
4
|
+
constructor(_lockPath?: string);
|
|
5
5
|
}
|
|
6
|
+
export type UnsafeLockPathReason = 'symlink' | 'not_regular_file' | 'owner_too_large' | 'path_changed' | 'permission_denied' | 'invalid_owner';
|
|
7
|
+
export declare class UnsafeLockPathError extends Error {
|
|
8
|
+
readonly reason: UnsafeLockPathReason;
|
|
9
|
+
readonly code = "UNSAFE_LOCK_PATH";
|
|
10
|
+
constructor(reason: UnsafeLockPathReason);
|
|
11
|
+
}
|
|
12
|
+
export declare const MAX_LOCK_OWNER_BYTES = 4096;
|
|
6
13
|
export interface AcquireLockOptions {
|
|
7
14
|
maxTries?: number;
|
|
8
15
|
waitMs?: number;
|
|
@@ -21,4 +28,14 @@ export interface AcquireLockOptions {
|
|
|
21
28
|
* synchronous critical sections (append-only writes).
|
|
22
29
|
*/
|
|
23
30
|
export declare function acquireLock(lockPath: string, opts?: AcquireLockOptions): void;
|
|
24
|
-
export
|
|
31
|
+
export type ReleaseLockReason = 'released' | 'missing' | 'ownership_changed' | 'not_owned' | 'released_with_cleanup_error' | UnsafeLockPathReason | 'release_failed';
|
|
32
|
+
export interface ReleaseLockResult {
|
|
33
|
+
released: boolean;
|
|
34
|
+
reason: ReleaseLockReason;
|
|
35
|
+
}
|
|
36
|
+
export declare function releaseLock(lockPath: string): ReleaseLockResult;
|
|
37
|
+
export declare class LockReleaseError extends Error {
|
|
38
|
+
readonly reason: ReleaseLockReason;
|
|
39
|
+
readonly code = "LOCK_RELEASE_FAILED";
|
|
40
|
+
constructor(reason: ReleaseLockReason);
|
|
41
|
+
}
|
package/dist/util/fileLock.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import {
|
|
2
|
+
import { closeSync, constants, fstatSync, lstatSync, openSync, readSync, renameSync, unlinkSync, writeFileSync, } from 'node:fs';
|
|
3
3
|
import { basename, dirname, join, resolve } from 'node:path';
|
|
4
4
|
export function syncSleep(ms) {
|
|
5
5
|
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
@@ -7,11 +7,21 @@ export function syncSleep(ms) {
|
|
|
7
7
|
const ownedLocks = new Map();
|
|
8
8
|
export class LockTimeoutError extends Error {
|
|
9
9
|
code = 'LOCK_TIMEOUT';
|
|
10
|
-
constructor(
|
|
11
|
-
super(
|
|
10
|
+
constructor(_lockPath) {
|
|
11
|
+
super('获取文件锁超时');
|
|
12
12
|
this.name = 'LockTimeoutError';
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
+
export class UnsafeLockPathError extends Error {
|
|
16
|
+
reason;
|
|
17
|
+
code = 'UNSAFE_LOCK_PATH';
|
|
18
|
+
constructor(reason) {
|
|
19
|
+
super(`不安全的文件锁路径: ${reason}`);
|
|
20
|
+
this.reason = reason;
|
|
21
|
+
this.name = 'UnsafeLockPathError';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export const MAX_LOCK_OWNER_BYTES = 4096;
|
|
15
25
|
function lockKey(lockPath) {
|
|
16
26
|
return resolve(lockPath);
|
|
17
27
|
}
|
|
@@ -24,6 +34,73 @@ function serializeOwner(owner) {
|
|
|
24
34
|
function isErrno(error, code) {
|
|
25
35
|
return typeof error === 'object' && error !== null && error.code === code;
|
|
26
36
|
}
|
|
37
|
+
function noFollowFlag() {
|
|
38
|
+
return constants['O_NOFOLLOW'] ?? 0;
|
|
39
|
+
}
|
|
40
|
+
function assertRegularOwnerStat(stat) {
|
|
41
|
+
if (stat.isSymbolicLink())
|
|
42
|
+
throw new UnsafeLockPathError('symlink');
|
|
43
|
+
if (!stat.isFile())
|
|
44
|
+
throw new UnsafeLockPathError('not_regular_file');
|
|
45
|
+
if (stat.size > BigInt(MAX_LOCK_OWNER_BYTES))
|
|
46
|
+
throw new UnsafeLockPathError('owner_too_large');
|
|
47
|
+
}
|
|
48
|
+
function currentOwnerStat(path) {
|
|
49
|
+
try {
|
|
50
|
+
const stat = lstatSync(path, { bigint: true });
|
|
51
|
+
assertRegularOwnerStat(stat);
|
|
52
|
+
return stat;
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
if (isErrno(error, 'ENOENT'))
|
|
56
|
+
return null;
|
|
57
|
+
if (isErrno(error, 'EACCES') || isErrno(error, 'EPERM')) {
|
|
58
|
+
throw new UnsafeLockPathError('permission_denied');
|
|
59
|
+
}
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function readOwnerBounded(path) {
|
|
64
|
+
const before = currentOwnerStat(path);
|
|
65
|
+
if (before === null)
|
|
66
|
+
return null;
|
|
67
|
+
let fd;
|
|
68
|
+
try {
|
|
69
|
+
fd = openSync(path, constants.O_RDONLY | noFollowFlag());
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
if (isErrno(error, 'ENOENT'))
|
|
73
|
+
return null;
|
|
74
|
+
if (isErrno(error, 'ELOOP'))
|
|
75
|
+
throw new UnsafeLockPathError('symlink');
|
|
76
|
+
if (isErrno(error, 'EACCES') || isErrno(error, 'EPERM')) {
|
|
77
|
+
throw new UnsafeLockPathError('permission_denied');
|
|
78
|
+
}
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
const opened = fstatSync(fd, { bigint: true });
|
|
83
|
+
assertRegularOwnerStat(opened);
|
|
84
|
+
const current = currentOwnerStat(path);
|
|
85
|
+
if (current === null || current.dev !== opened.dev || current.ino !== opened.ino) {
|
|
86
|
+
throw new UnsafeLockPathError('path_changed');
|
|
87
|
+
}
|
|
88
|
+
const buffer = Buffer.alloc(MAX_LOCK_OWNER_BYTES + 1);
|
|
89
|
+
let total = 0;
|
|
90
|
+
while (total < buffer.length) {
|
|
91
|
+
const read = readSync(fd, buffer, total, buffer.length - total, total);
|
|
92
|
+
if (read === 0)
|
|
93
|
+
break;
|
|
94
|
+
total += read;
|
|
95
|
+
}
|
|
96
|
+
if (total > MAX_LOCK_OWNER_BYTES)
|
|
97
|
+
throw new UnsafeLockPathError('owner_too_large');
|
|
98
|
+
return buffer.subarray(0, total).toString('utf8');
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
closeSync(fd);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
27
104
|
/** True if pid is a live process (cross-platform via signal 0; EPERM = exists but owned by another user). */
|
|
28
105
|
function pidAlive(pid) {
|
|
29
106
|
if (!Number.isInteger(pid) || pid <= 0)
|
|
@@ -73,10 +150,13 @@ function parseOwner(raw) {
|
|
|
73
150
|
/** Owner recorded in the lock file; null if missing/unparseable. */
|
|
74
151
|
function lockOwner(lockPath) {
|
|
75
152
|
try {
|
|
76
|
-
|
|
153
|
+
const raw = readOwnerBounded(lockPath);
|
|
154
|
+
return raw === null ? null : parseOwner(raw);
|
|
77
155
|
}
|
|
78
156
|
catch (error) {
|
|
79
|
-
|
|
157
|
+
// A valid owner can release and another waiter can acquire between lstat/open/fstat. Treat that snapshot as
|
|
158
|
+
// transiently unavailable: callers remain conservative (no steal/delete) and the acquire loop retries.
|
|
159
|
+
if (error instanceof UnsafeLockPathError && error.reason === 'path_changed')
|
|
80
160
|
return null;
|
|
81
161
|
throw error;
|
|
82
162
|
}
|
|
@@ -100,17 +180,30 @@ function removeFileIfExists(path) {
|
|
|
100
180
|
}
|
|
101
181
|
}
|
|
102
182
|
function createLockFile(lockPath, owner, trackOwnership) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
183
|
+
for (let permissionAttempt = 0; permissionAttempt < 2; permissionAttempt++) {
|
|
184
|
+
try {
|
|
185
|
+
writeFileSync(lockPath, serializeOwner(owner), { flag: 'wx', mode: 0o600 });
|
|
186
|
+
if (trackOwnership)
|
|
187
|
+
ownedLocks.set(lockKey(lockPath), { owner, releasePending: false });
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
if (isErrno(error, 'EEXIST'))
|
|
192
|
+
return false;
|
|
193
|
+
if (isErrno(error, 'EACCES') || isErrno(error, 'EPERM')) {
|
|
194
|
+
// Windows can report EPERM instead of EEXIST during contention. A regular owner is busy; if the owner
|
|
195
|
+
// disappeared before lstat, retry create once to distinguish that release race from a persistent ACL
|
|
196
|
+
// failure. Unsafe/inaccessible paths still throw from currentOwnerStat and remain fail closed.
|
|
197
|
+
if (currentOwnerStat(lockPath) !== null)
|
|
198
|
+
return false;
|
|
199
|
+
if (permissionAttempt === 0)
|
|
200
|
+
continue;
|
|
201
|
+
throw new UnsafeLockPathError('permission_denied');
|
|
202
|
+
}
|
|
203
|
+
throw error;
|
|
204
|
+
}
|
|
113
205
|
}
|
|
206
|
+
throw new UnsafeLockPathError('permission_denied');
|
|
114
207
|
}
|
|
115
208
|
function tryAcquireMutationGuard(lockPath) {
|
|
116
209
|
const guardPath = mutationGuardPath(lockPath);
|
|
@@ -185,6 +278,12 @@ function reclaimStaleLock(lockPath) {
|
|
|
185
278
|
* synchronous critical sections (append-only writes).
|
|
186
279
|
*/
|
|
187
280
|
export function acquireLock(lockPath, opts = {}) {
|
|
281
|
+
const pending = ownedLocks.get(lockKey(lockPath));
|
|
282
|
+
if (pending?.releasePending) {
|
|
283
|
+
const released = releaseLock(lockPath);
|
|
284
|
+
if (!released.released)
|
|
285
|
+
throw new LockReleaseError(released.reason);
|
|
286
|
+
}
|
|
188
287
|
const maxTries = opts.maxTries ?? 300;
|
|
189
288
|
const waitMs = opts.waitMs ?? 10;
|
|
190
289
|
for (let i = 0; i < maxTries; i++) {
|
|
@@ -200,28 +299,64 @@ export function acquireLock(lockPath, opts = {}) {
|
|
|
200
299
|
}
|
|
201
300
|
syncSleep(waitMs);
|
|
202
301
|
}
|
|
203
|
-
throw new LockTimeoutError(
|
|
302
|
+
throw new LockTimeoutError();
|
|
204
303
|
}
|
|
205
304
|
export function releaseLock(lockPath) {
|
|
206
305
|
const key = lockKey(lockPath);
|
|
207
|
-
const
|
|
208
|
-
if (
|
|
209
|
-
return;
|
|
306
|
+
const owned = ownedLocks.get(key);
|
|
307
|
+
if (owned === undefined)
|
|
308
|
+
return { released: true, reason: 'not_owned' };
|
|
309
|
+
const failed = (reason) => {
|
|
310
|
+
owned.releasePending = true;
|
|
311
|
+
return { released: false, reason };
|
|
312
|
+
};
|
|
313
|
+
// Release must not use lockOwner(): that helper intentionally folds path_changed into a conservative null
|
|
314
|
+
// for acquire retries. Here, an inconclusive read marks a pending release so the next acquire can retry or
|
|
315
|
+
// surface LOCK_RELEASE_FAILED instead of silently timing out behind this process's own PID.
|
|
316
|
+
let raw;
|
|
210
317
|
try {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
318
|
+
raw = readOwnerBounded(lockPath);
|
|
319
|
+
}
|
|
320
|
+
catch (error) {
|
|
321
|
+
return failed(error instanceof UnsafeLockPathError ? error.reason : 'release_failed');
|
|
322
|
+
}
|
|
323
|
+
if (raw === null) {
|
|
324
|
+
ownedLocks.delete(key);
|
|
325
|
+
return { released: true, reason: 'missing' };
|
|
326
|
+
}
|
|
327
|
+
const current = parseOwner(raw);
|
|
328
|
+
if (current === null)
|
|
329
|
+
return failed('invalid_owner');
|
|
330
|
+
if (!sameOwner(current, owned.owner)) {
|
|
331
|
+
ownedLocks.delete(key);
|
|
332
|
+
return { released: true, reason: 'ownership_changed' };
|
|
333
|
+
}
|
|
334
|
+
const releasedPath = sidecarPath(lockPath, 'released');
|
|
335
|
+
try {
|
|
336
|
+
renameSync(lockPath, releasedPath);
|
|
337
|
+
}
|
|
338
|
+
catch (error) {
|
|
339
|
+
if (isErrno(error, 'ENOENT')) {
|
|
340
|
+
ownedLocks.delete(key);
|
|
341
|
+
return { released: true, reason: 'missing' };
|
|
221
342
|
}
|
|
343
|
+
return failed('release_failed');
|
|
344
|
+
}
|
|
345
|
+
ownedLocks.delete(key);
|
|
346
|
+
try {
|
|
222
347
|
removeFileIfExists(releasedPath);
|
|
223
348
|
}
|
|
224
|
-
|
|
225
|
-
|
|
349
|
+
catch {
|
|
350
|
+
return { released: true, reason: 'released_with_cleanup_error' };
|
|
351
|
+
}
|
|
352
|
+
return { released: true, reason: 'released' };
|
|
353
|
+
}
|
|
354
|
+
export class LockReleaseError extends Error {
|
|
355
|
+
reason;
|
|
356
|
+
code = 'LOCK_RELEASE_FAILED';
|
|
357
|
+
constructor(reason) {
|
|
358
|
+
super(`文件锁释放未完成: ${reason}`);
|
|
359
|
+
this.reason = reason;
|
|
360
|
+
this.name = 'LockReleaseError';
|
|
226
361
|
}
|
|
227
362
|
}
|
package/dist/wire/geneHints.d.ts
CHANGED
|
@@ -34,13 +34,45 @@ export interface GeneToolPolicy {
|
|
|
34
34
|
deny?: string[];
|
|
35
35
|
severity?: ToolPolicySeverity;
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Provenance classification (V1 #302 classifyProvenance, aligned with TaskGenome Bench §3.1): a Gene's value
|
|
39
|
+
* depends on WHERE it came from, not on being short. The three tiers:
|
|
40
|
+
* evolved -- distilled from a real solve -> fail -> mutate -> pass trajectory; beats Skills (+8.7..+15.5pp)
|
|
41
|
+
* distilled -- transcribed from reference/teacher text with no real failing trajectory; WORSE than Skills (-3.2..-11.2pp)
|
|
42
|
+
* manual -- pure human transcription, no execution evidence at all
|
|
43
|
+
* The high-value payload of an evolved Gene is the corrective_insight that flipped the outcome.
|
|
44
|
+
*/
|
|
45
|
+
export declare const GENERATION_SOURCES: readonly ["evolved", "distilled", "manual"];
|
|
46
|
+
export type GenerationSource = (typeof GENERATION_SOURCES)[number];
|
|
47
|
+
export interface GeneGenerationHeuristics {
|
|
48
|
+
strategy_steps?: number;
|
|
49
|
+
avoid_count?: number;
|
|
50
|
+
validation_declared_count?: number;
|
|
51
|
+
validation_runnable_count?: number;
|
|
52
|
+
signals_extracted?: number;
|
|
53
|
+
preconditions_extracted?: number;
|
|
54
|
+
trajectory_depth?: number;
|
|
55
|
+
has_corrective_insight?: boolean;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The full provenance + quality metadata block (V1 `gene._source`). Lives on Gene as the v2-delta field
|
|
59
|
+
* `generation_meta`. `source` is the only required key; the rest is descriptive for reviewers / future
|
|
60
|
+
* governance. `quality_score` is a coarse [0,1] tier-anchored score (evolved 0.7 / distilled 0.4 / manual 0.3
|
|
61
|
+
* baseline + bonuses); `overcame_errors` is the mutation_log copy that the trajectory overcame.
|
|
62
|
+
*/
|
|
63
|
+
export interface GenerationMeta {
|
|
64
|
+
source: GenerationSource;
|
|
65
|
+
quality_score?: number;
|
|
66
|
+
quality_heuristics?: GeneGenerationHeuristics;
|
|
67
|
+
overcame_errors?: string[];
|
|
68
|
+
}
|
|
37
69
|
/**
|
|
38
70
|
* The v2-delta hint field names, in one place — the intake gate strips these before the gep-sdk schema check.
|
|
39
71
|
* IMPORTANT: when a gep-sdk gene-schema bump makes one of these first-class, REMOVE it from this list in the
|
|
40
72
|
* same change. Otherwise intakeGene keeps stripping a now-validated field before validateWire (fail-open — the
|
|
41
73
|
* field's new schema constraints go unchecked at intake) while asset_id still commits it.
|
|
42
74
|
*/
|
|
43
|
-
export declare const GENE_HINT_FIELDS: readonly ["routing_hint", "tool_policy"];
|
|
75
|
+
export declare const GENE_HINT_FIELDS: readonly ["routing_hint", "tool_policy", "generation_meta"];
|
|
44
76
|
/**
|
|
45
77
|
* Normalize an arbitrary routing_hint fragment to a strict { tier?, reasoning_level? } object, or null.
|
|
46
78
|
* Unknown enum values are dropped (a stray tier would fail the consumer's exhaustive match and route as if
|
|
@@ -60,5 +92,14 @@ export declare function normalizeRoutingHint(raw: unknown): GeneRoutingHint | nu
|
|
|
60
92
|
* defaults to 'warn' when a list is present; the whole object collapses to null when neither list survives.
|
|
61
93
|
*/
|
|
62
94
|
export declare function normalizeToolPolicy(raw: unknown): GeneToolPolicy | null;
|
|
95
|
+
/**
|
|
96
|
+
* Normalize an arbitrary generation_meta fragment to a strict { source, quality_score?, quality_heuristics?,
|
|
97
|
+
* overcame_errors? } object, or null. Lossy (mirrors normalizeRoutingHint / normalizeToolPolicy): unknown source
|
|
98
|
+
* values are dropped (the whole block collapses to null — a generation_meta with no recognized source carries no
|
|
99
|
+
* usable provenance signal); quality_score is clamped to [0,1]; heuristics keeps only its numeric/boolean fields;
|
|
100
|
+
* overcame_errors keeps only non-empty strings. A block with a valid source but all-else-empty still survives (source
|
|
101
|
+
* alone is a meaningful provenance tag); only a missing/unknown source yields null.
|
|
102
|
+
*/
|
|
103
|
+
export declare function normalizeGenerationMeta(raw: unknown): GenerationMeta | null;
|
|
63
104
|
/** Strip the v2-delta hint fields from a gene-shaped object (used to validate the gep-sdk-known core). */
|
|
64
105
|
export declare function stripGeneHints(gene: Record<string, unknown>): Record<string, unknown>;
|
package/dist/wire/geneHints.js
CHANGED
|
@@ -22,13 +22,22 @@
|
|
|
22
22
|
export const ROUTING_TIERS = ['cheap', 'mid', 'expensive'];
|
|
23
23
|
export const REASONING_LEVELS = ['off', 'low', 'medium', 'high'];
|
|
24
24
|
export const TOOL_POLICY_SEVERITIES = ['warn', 'block'];
|
|
25
|
+
/**
|
|
26
|
+
* Provenance classification (V1 #302 classifyProvenance, aligned with TaskGenome Bench §3.1): a Gene's value
|
|
27
|
+
* depends on WHERE it came from, not on being short. The three tiers:
|
|
28
|
+
* evolved -- distilled from a real solve -> fail -> mutate -> pass trajectory; beats Skills (+8.7..+15.5pp)
|
|
29
|
+
* distilled -- transcribed from reference/teacher text with no real failing trajectory; WORSE than Skills (-3.2..-11.2pp)
|
|
30
|
+
* manual -- pure human transcription, no execution evidence at all
|
|
31
|
+
* The high-value payload of an evolved Gene is the corrective_insight that flipped the outcome.
|
|
32
|
+
*/
|
|
33
|
+
export const GENERATION_SOURCES = ['evolved', 'distilled', 'manual'];
|
|
25
34
|
/**
|
|
26
35
|
* The v2-delta hint field names, in one place — the intake gate strips these before the gep-sdk schema check.
|
|
27
36
|
* IMPORTANT: when a gep-sdk gene-schema bump makes one of these first-class, REMOVE it from this list in the
|
|
28
37
|
* same change. Otherwise intakeGene keeps stripping a now-validated field before validateWire (fail-open — the
|
|
29
38
|
* field's new schema constraints go unchecked at intake) while asset_id still commits it.
|
|
30
39
|
*/
|
|
31
|
-
export const GENE_HINT_FIELDS = ['routing_hint', 'tool_policy'];
|
|
40
|
+
export const GENE_HINT_FIELDS = ['routing_hint', 'tool_policy', 'generation_meta'];
|
|
32
41
|
function includesEnum(set, v) {
|
|
33
42
|
return typeof v === 'string' && set.includes(v);
|
|
34
43
|
}
|
|
@@ -89,6 +98,48 @@ function cleanToolList(raw) {
|
|
|
89
98
|
const cleaned = raw.filter((x) => typeof x === 'string' && x.length > 0);
|
|
90
99
|
return cleaned.length > 0 ? cleaned : undefined;
|
|
91
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Normalize an arbitrary generation_meta fragment to a strict { source, quality_score?, quality_heuristics?,
|
|
103
|
+
* overcame_errors? } object, or null. Lossy (mirrors normalizeRoutingHint / normalizeToolPolicy): unknown source
|
|
104
|
+
* values are dropped (the whole block collapses to null — a generation_meta with no recognized source carries no
|
|
105
|
+
* usable provenance signal); quality_score is clamped to [0,1]; heuristics keeps only its numeric/boolean fields;
|
|
106
|
+
* overcame_errors keeps only non-empty strings. A block with a valid source but all-else-empty still survives (source
|
|
107
|
+
* alone is a meaningful provenance tag); only a missing/unknown source yields null.
|
|
108
|
+
*/
|
|
109
|
+
export function normalizeGenerationMeta(raw) {
|
|
110
|
+
if (!raw || typeof raw !== 'object')
|
|
111
|
+
return null;
|
|
112
|
+
const r = raw;
|
|
113
|
+
const source = r['source'];
|
|
114
|
+
if (!includesEnum(GENERATION_SOURCES, source))
|
|
115
|
+
return null;
|
|
116
|
+
const out = { source };
|
|
117
|
+
const qs = r['quality_score'];
|
|
118
|
+
if (typeof qs === 'number' && Number.isFinite(qs))
|
|
119
|
+
out.quality_score = Math.max(0, Math.min(1, qs));
|
|
120
|
+
const eh = r['quality_heuristics'];
|
|
121
|
+
if (eh && typeof eh === 'object') {
|
|
122
|
+
const h = eh;
|
|
123
|
+
const heuristics = {};
|
|
124
|
+
const numFields = [
|
|
125
|
+
'strategy_steps', 'avoid_count', 'validation_declared_count', 'validation_runnable_count',
|
|
126
|
+
'signals_extracted', 'preconditions_extracted', 'trajectory_depth',
|
|
127
|
+
];
|
|
128
|
+
for (const k of numFields) {
|
|
129
|
+
const v = h[k];
|
|
130
|
+
if (typeof v === 'number' && Number.isFinite(v))
|
|
131
|
+
heuristics[k] = v;
|
|
132
|
+
}
|
|
133
|
+
if (typeof h['has_corrective_insight'] === 'boolean')
|
|
134
|
+
heuristics.has_corrective_insight = h['has_corrective_insight'];
|
|
135
|
+
if (Object.keys(heuristics).length > 0)
|
|
136
|
+
out.quality_heuristics = heuristics;
|
|
137
|
+
}
|
|
138
|
+
const errs = cleanToolList(r['overcame_errors']);
|
|
139
|
+
if (errs)
|
|
140
|
+
out.overcame_errors = errs;
|
|
141
|
+
return out;
|
|
142
|
+
}
|
|
92
143
|
/** Strip the v2-delta hint fields from a gene-shaped object (used to validate the gep-sdk-known core). */
|
|
93
144
|
export function stripGeneHints(gene) {
|
|
94
145
|
const hidden = GENE_HINT_FIELDS;
|
package/dist/wire/index.d.ts
CHANGED
|
@@ -2,12 +2,18 @@
|
|
|
2
2
|
* 资产 wire 层. SSOT = @evomap/gep-sdk/schemas/*.schema.json (D19).
|
|
3
3
|
* 字段一律 snake_case 锁定 (asset_id 跨实现契约); 本仓不发明 wire 字段, 只镜像 + 重导出工具.
|
|
4
4
|
*/
|
|
5
|
-
import type { GeneRoutingHint, GeneToolPolicy } from './geneHints.js';
|
|
5
|
+
import type { GeneRoutingHint, GeneToolPolicy, GenerationMeta } from './geneHints.js';
|
|
6
6
|
export { SCHEMA_VERSION, canonicalize, computeAssetId, verifyAssetId } from '@evomap/gep-sdk';
|
|
7
7
|
export type GepCategory = typeof import('@evomap/gep-sdk').GEP_GENE_CATEGORIES[number];
|
|
8
8
|
export type OutcomeStatus = typeof import('@evomap/gep-sdk').GEP_OUTCOME_STATUSES[number];
|
|
9
9
|
export type SourceType = typeof import('@evomap/gep-sdk').GEP_SOURCE_TYPES[number];
|
|
10
10
|
export type RiskLevel = typeof import('@evomap/gep-sdk').GEP_RISK_LEVELS[number];
|
|
11
|
+
export type CapsuleVisibility = typeof import('@evomap/gep-sdk').GEP_CAPSULE_VISIBILITIES[number];
|
|
12
|
+
export type CapsuleCostTier = typeof import('@evomap/gep-sdk').GEP_CAPSULE_COST_TIERS[number];
|
|
13
|
+
export interface CapsuleAuthor {
|
|
14
|
+
handle: string;
|
|
15
|
+
evox_install_id: string;
|
|
16
|
+
}
|
|
11
17
|
/** Gene = 基因型/方法论 (gene.schema.json). */
|
|
12
18
|
export interface Gene {
|
|
13
19
|
type: 'Gene';
|
|
@@ -28,6 +34,7 @@ export interface Gene {
|
|
|
28
34
|
anti_patterns?: unknown[];
|
|
29
35
|
routing_hint?: GeneRoutingHint | null;
|
|
30
36
|
tool_policy?: GeneToolPolicy | null;
|
|
37
|
+
generation_meta?: GenerationMeta | null;
|
|
31
38
|
asset_id: string;
|
|
32
39
|
}
|
|
33
40
|
/** Capsule = 表现型/纯进化产物 (capsule.schema.json). */
|
|
@@ -49,6 +56,11 @@ export interface Capsule {
|
|
|
49
56
|
};
|
|
50
57
|
resolution_status?: 'pending' | 'suppressed_observationally' | 'resolved_by_evidence' | 'regressed' | 'inconclusive';
|
|
51
58
|
proof_of_work?: unknown;
|
|
59
|
+
visibility?: CapsuleVisibility | null;
|
|
60
|
+
scope?: string[] | null;
|
|
61
|
+
cost_tier?: CapsuleCostTier | null;
|
|
62
|
+
pack_of?: string[] | null;
|
|
63
|
+
author?: CapsuleAuthor | null;
|
|
52
64
|
execution_trace?: unknown[];
|
|
53
65
|
trigger_context?: unknown;
|
|
54
66
|
asset_id: string;
|
|
@@ -88,4 +100,4 @@ export interface Mutation {
|
|
|
88
100
|
risk_level: RiskLevel;
|
|
89
101
|
}
|
|
90
102
|
export { validateWire, schemaProperties, type WireValidation } from './schemaGate.js';
|
|
91
|
-
export { ROUTING_TIERS, REASONING_LEVELS, TOOL_POLICY_SEVERITIES, GENE_HINT_FIELDS, normalizeRoutingHint, normalizeToolPolicy, stripGeneHints, type RoutingTier, type ReasoningLevel, type ToolPolicySeverity, type GeneRoutingHint, type GeneToolPolicy, } from './geneHints.js';
|
|
103
|
+
export { ROUTING_TIERS, REASONING_LEVELS, TOOL_POLICY_SEVERITIES, GENERATION_SOURCES, GENE_HINT_FIELDS, normalizeRoutingHint, normalizeToolPolicy, normalizeGenerationMeta, stripGeneHints, type RoutingTier, type ReasoningLevel, type ToolPolicySeverity, type GenerationSource, type GeneRoutingHint, type GeneToolPolicy, type GeneGenerationHeuristics, type GenerationMeta, } from './geneHints.js';
|
package/dist/wire/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { SCHEMA_VERSION, canonicalize, computeAssetId, verifyAssetId } from '@evomap/gep-sdk';
|
|
2
2
|
export { validateWire, schemaProperties } from './schemaGate.js';
|
|
3
|
-
export { ROUTING_TIERS, REASONING_LEVELS, TOOL_POLICY_SEVERITIES, GENE_HINT_FIELDS, normalizeRoutingHint, normalizeToolPolicy, stripGeneHints, } from './geneHints.js';
|
|
3
|
+
export { ROUTING_TIERS, REASONING_LEVELS, TOOL_POLICY_SEVERITIES, GENERATION_SOURCES, GENE_HINT_FIELDS, normalizeRoutingHint, normalizeToolPolicy, normalizeGenerationMeta, stripGeneHints, } from './geneHints.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evomap/evolver-core",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "hub-无关核心: 算法引擎/原材料/mailbox/资产库/workflow",
|
|
@@ -17,12 +17,17 @@
|
|
|
17
17
|
"zod": "^3.24.1",
|
|
18
18
|
"ulid": "^2.3.0"
|
|
19
19
|
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/EvoMap/evolver.git"
|
|
23
|
+
},
|
|
20
24
|
"publishConfig": {
|
|
21
25
|
"access": "public",
|
|
22
26
|
"tag": "v2-beta"
|
|
23
27
|
},
|
|
24
28
|
"files": [
|
|
25
29
|
"dist/",
|
|
30
|
+
"assets/",
|
|
26
31
|
"README.md",
|
|
27
32
|
"package.json"
|
|
28
33
|
]
|