dsh-continual-evolve 0.10.6 → 0.12.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/README.md +35 -122
- package/README.zh.md +26 -97
- package/cordis.patch.yml +2 -2
- package/lib/index.d.ts +44 -241
- package/lib/index.js +30 -253
- package/lib/memory-guide.d.ts +13 -14
- package/lib/memory-guide.js +32 -21
- package/lib/memory-section.d.ts +77 -0
- package/lib/memory-section.js +189 -0
- package/package.json +2 -17
- package/lib/apply.d.ts +0 -22
- package/lib/apply.js +0 -157
- package/lib/approval.d.ts +0 -72
- package/lib/approval.js +0 -127
- package/lib/auto.d.ts +0 -236
- package/lib/auto.js +0 -773
- package/lib/autocase.d.ts +0 -38
- package/lib/autocase.js +0 -76
- package/lib/benchmark-command.d.ts +0 -9
- package/lib/benchmark-command.js +0 -357
- package/lib/benchmark.d.ts +0 -151
- package/lib/benchmark.js +0 -250
- package/lib/command.d.ts +0 -49
- package/lib/command.js +0 -568
- package/lib/consolidate.d.ts +0 -90
- package/lib/consolidate.js +0 -180
- package/lib/copy.d.ts +0 -74
- package/lib/copy.js +0 -160
- package/lib/declines.d.ts +0 -101
- package/lib/declines.js +0 -175
- package/lib/evaluate.d.ts +0 -74
- package/lib/evaluate.js +0 -271
- package/lib/evolve-event.d.ts +0 -40
- package/lib/evolve-event.js +0 -59
- package/lib/failures.d.ts +0 -42
- package/lib/failures.js +0 -171
- package/lib/fate.d.ts +0 -130
- package/lib/fate.js +0 -350
- package/lib/goal-command.d.ts +0 -7
- package/lib/goal-command.js +0 -37
- package/lib/goal.d.ts +0 -72
- package/lib/goal.js +0 -72
- package/lib/inject.d.ts +0 -196
- package/lib/inject.js +0 -412
- package/lib/llm-text.d.ts +0 -104
- package/lib/llm-text.js +0 -140
- package/lib/logfile.d.ts +0 -71
- package/lib/logfile.js +0 -159
- package/lib/memory-agent.d.ts +0 -129
- package/lib/memory-agent.js +0 -568
- package/lib/memory-benchmark.d.ts +0 -76
- package/lib/memory-benchmark.js +0 -170
- package/lib/memory-index.d.ts +0 -114
- package/lib/memory-index.js +0 -197
- package/lib/message-source.d.ts +0 -23
- package/lib/message-source.js +0 -12
- package/lib/mount-command.d.ts +0 -10
- package/lib/mount-command.js +0 -48
- package/lib/mount.d.ts +0 -42
- package/lib/mount.js +0 -212
- package/lib/notify.d.ts +0 -59
- package/lib/notify.js +0 -97
- package/lib/plan.d.ts +0 -16
- package/lib/plan.js +0 -126
- package/lib/planner.d.ts +0 -61
- package/lib/planner.js +0 -144
- package/lib/pool.d.ts +0 -7
- package/lib/pool.js +0 -25
- package/lib/prefix-cache.d.ts +0 -78
- package/lib/prefix-cache.js +0 -168
- package/lib/project.d.ts +0 -28
- package/lib/project.js +0 -66
- package/lib/projection.d.ts +0 -22
- package/lib/projection.js +0 -112
- package/lib/promotion.d.ts +0 -94
- package/lib/promotion.js +0 -171
- package/lib/recall.d.ts +0 -85
- package/lib/recall.js +0 -142
- package/lib/record-language.d.ts +0 -85
- package/lib/record-language.js +0 -152
- package/lib/render.d.ts +0 -13
- package/lib/render.js +0 -80
- package/lib/review-scheduler.d.ts +0 -38
- package/lib/review-scheduler.js +0 -191
- package/lib/review.d.ts +0 -60
- package/lib/review.js +0 -145
- package/lib/rollback.d.ts +0 -9
- package/lib/rollback.js +0 -68
- package/lib/rubric.d.ts +0 -29
- package/lib/rubric.js +0 -119
- package/lib/runtime.d.ts +0 -24
- package/lib/runtime.js +0 -87
- package/lib/score.d.ts +0 -64
- package/lib/score.js +0 -191
- package/lib/search.d.ts +0 -83
- package/lib/search.js +0 -136
- package/lib/service.d.ts +0 -49
- package/lib/service.js +0 -180
- package/lib/skill-render.d.ts +0 -23
- package/lib/skill-render.js +0 -69
- package/lib/skill.d.ts +0 -15
- package/lib/skill.js +0 -80
- package/lib/skillquality.d.ts +0 -85
- package/lib/skillquality.js +0 -320
- package/lib/source.d.ts +0 -30
- package/lib/source.js +0 -43
- package/lib/state.d.ts +0 -26
- package/lib/state.js +0 -151
- package/lib/store.d.ts +0 -62
- package/lib/store.js +0 -164
- package/lib/token-usage.d.ts +0 -68
- package/lib/token-usage.js +0 -211
- package/lib/tool.d.ts +0 -34
- package/lib/tool.js +0 -320
- package/lib/turn-snapshot.d.ts +0 -72
- package/lib/turn-snapshot.js +0 -238
- package/lib/types.d.ts +0 -208
- package/lib/types.js +0 -127
- package/lib/usage.d.ts +0 -36
- package/lib/usage.js +0 -98
- package/lib/validate.d.ts +0 -28
- package/lib/validate.js +0 -181
- package/lib/wrapup-command.d.ts +0 -10
- package/lib/wrapup-command.js +0 -243
- package/lib/wrapup.d.ts +0 -260
- package/lib/wrapup.js +0 -539
package/lib/benchmark.js
DELETED
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Benchmark store: file-backed case definitions and scoreboards under
|
|
3
|
-
* `<baseDir>/evolve/benchmarks/<bid>/`.
|
|
4
|
-
*
|
|
5
|
-
* Layout:
|
|
6
|
-
* benchmark.json title, runs (repeats per case), passThreshold
|
|
7
|
-
* cases/<cid>/statement.md public task text
|
|
8
|
-
* cases/<cid>/rubric.json encrypted scoring criteria (AES-256-GCM, see src/rubric.ts)
|
|
9
|
-
* scoreboard.json code-owned aggregates + acceptance history
|
|
10
|
-
*
|
|
11
|
-
* Rubric isolation is code-enforced: rubric plaintext never reaches the
|
|
12
|
-
* disk. Only the evaluation runner decrypts (into the child prompt); the
|
|
13
|
-
* optimizer can read the file and sees ciphertext only. Legacy files that
|
|
14
|
-
* predate encryption carry plaintext and are still readable.
|
|
15
|
-
*/
|
|
16
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
17
|
-
import { join } from "node:path";
|
|
18
|
-
import { encryptRubric, DEV_RUBRIC_KEY, deriveKey } from "./rubric.js";
|
|
19
|
-
/**
|
|
20
|
-
* Close the acceptance loop: when the code-owned decision rejects a
|
|
21
|
-
* candidate refinement, revert it deterministically. The rollback is the
|
|
22
|
-
* same engine path as `/evolve rollback` (inverse edits rebuilt from the
|
|
23
|
-
* applied result — no LLM re-guessing), so it snapshots, versions, and
|
|
24
|
-
* audits like any other mutation. Failures (e.g. the refinement belongs to
|
|
25
|
-
* another session's history) are reported, never thrown: the command shows
|
|
26
|
-
* the manual fallback instead.
|
|
27
|
-
*/
|
|
28
|
-
export function rollbackRejectedCandidate(engine, sessionId, candidateId) {
|
|
29
|
-
try {
|
|
30
|
-
const result = engine.rollback("local", sessionId, candidateId);
|
|
31
|
-
const applied = result.appliedEdits.filter((edit) => edit.applied).length;
|
|
32
|
-
return {
|
|
33
|
-
rolledBack: true,
|
|
34
|
-
message: `auto-rollback: reverted refinement ${candidateId} — ${applied} edits restored to the pre-refinement snapshot`,
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
catch (cause) {
|
|
38
|
-
return {
|
|
39
|
-
rolledBack: false,
|
|
40
|
-
message: `auto-rollback failed: ${cause instanceof Error ? cause.message : String(cause)} — roll back manually with /evolve rollback <${candidateId}>`,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
export function benchmarkDir(baseDir, bid) {
|
|
45
|
-
return join(baseDir, "evolve", "benchmarks", bid);
|
|
46
|
-
}
|
|
47
|
-
export function sanitizeId(raw) {
|
|
48
|
-
const id = raw.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 40);
|
|
49
|
-
if (!id) {
|
|
50
|
-
throw new Error("benchmark id must be a non-empty slug");
|
|
51
|
-
}
|
|
52
|
-
return id;
|
|
53
|
-
}
|
|
54
|
-
export function createBenchmark(baseDir, opts) {
|
|
55
|
-
const id = sanitizeId(opts.title);
|
|
56
|
-
const dir = benchmarkDir(baseDir, id);
|
|
57
|
-
if (existsSync(dir)) {
|
|
58
|
-
throw new Error(`benchmark ${id} already exists`);
|
|
59
|
-
}
|
|
60
|
-
const definition = {
|
|
61
|
-
id,
|
|
62
|
-
title: opts.title.trim(),
|
|
63
|
-
description: opts.description?.trim() ?? "",
|
|
64
|
-
runs: opts.runs ?? 1,
|
|
65
|
-
passThreshold: opts.passThreshold ?? 60,
|
|
66
|
-
createdAt: new Date().toISOString(),
|
|
67
|
-
};
|
|
68
|
-
mkdirSync(dir, { recursive: true });
|
|
69
|
-
writeFileSync(join(dir, "benchmark.json"), `${JSON.stringify(definition, null, 2)}\n`, "utf8");
|
|
70
|
-
writeFileSync(join(dir, "scoreboard.json"), `${JSON.stringify({ candidates: [], decisions: [] }, null, 2)}\n`, "utf8");
|
|
71
|
-
return definition;
|
|
72
|
-
}
|
|
73
|
-
export function listBenchmarks(baseDir) {
|
|
74
|
-
const root = join(baseDir, "evolve", "benchmarks");
|
|
75
|
-
if (!existsSync(root))
|
|
76
|
-
return [];
|
|
77
|
-
return readdirSafe(root)
|
|
78
|
-
.map((id) => loadBenchmark(baseDir, id))
|
|
79
|
-
.filter((b) => b !== undefined);
|
|
80
|
-
}
|
|
81
|
-
export function loadBenchmark(baseDir, bid) {
|
|
82
|
-
const path = join(benchmarkDir(baseDir, bid), "benchmark.json");
|
|
83
|
-
if (!existsSync(path))
|
|
84
|
-
return undefined;
|
|
85
|
-
try {
|
|
86
|
-
return JSON.parse(readFileSync(path, "utf8"));
|
|
87
|
-
}
|
|
88
|
-
catch {
|
|
89
|
-
return undefined;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
export function addCase(baseDir, bid, title, statement, rubric, rubricKey) {
|
|
93
|
-
const definition = loadBenchmark(baseDir, bid);
|
|
94
|
-
if (!definition) {
|
|
95
|
-
throw new Error(`benchmark ${bid} not found`);
|
|
96
|
-
}
|
|
97
|
-
const id = sanitizeId(title);
|
|
98
|
-
const caseDir = join(benchmarkDir(baseDir, bid), "cases", id);
|
|
99
|
-
if (existsSync(caseDir)) {
|
|
100
|
-
throw new Error(`case ${id} already exists in ${bid}`);
|
|
101
|
-
}
|
|
102
|
-
mkdirSync(caseDir, { recursive: true });
|
|
103
|
-
writeFileSync(join(caseDir, "statement.md"), statement, "utf8");
|
|
104
|
-
// Rubric plaintext never touches the disk; callers pass a resolved key
|
|
105
|
-
// (config → env → per-installation key file → dev fallback, see
|
|
106
|
-
// resolveRubricKey) and the dev key here is only a defensive last resort.
|
|
107
|
-
const stored = rubricKey ? encryptRubric(rubric, rubricKey) : encryptRubric(rubric, deriveKey(DEV_RUBRIC_KEY));
|
|
108
|
-
writeFileSync(join(caseDir, "rubric.json"), `${JSON.stringify(stored, null, 2)}\n`, "utf8");
|
|
109
|
-
// A5: initialize case metadata for quality gate.
|
|
110
|
-
saveCaseMeta(baseDir, bid, id, defaultCaseMeta());
|
|
111
|
-
return { id, title: title.trim(), statement, rubric };
|
|
112
|
-
}
|
|
113
|
-
export function listCases(baseDir, bid) {
|
|
114
|
-
const casesDir = join(benchmarkDir(baseDir, bid), "cases");
|
|
115
|
-
if (!existsSync(casesDir))
|
|
116
|
-
return [];
|
|
117
|
-
return readdirSafe(casesDir)
|
|
118
|
-
.map((id) => {
|
|
119
|
-
const statementPath = join(casesDir, id, "statement.md");
|
|
120
|
-
const rubricPath = join(casesDir, id, "rubric.json");
|
|
121
|
-
if (!existsSync(statementPath) || !existsSync(rubricPath))
|
|
122
|
-
return undefined;
|
|
123
|
-
try {
|
|
124
|
-
const statement = readFileSync(statementPath, "utf8");
|
|
125
|
-
const rubric = JSON.parse(readFileSync(rubricPath, "utf8"));
|
|
126
|
-
const meta = loadCaseMeta(baseDir, bid, id);
|
|
127
|
-
return { id, title: id, statement, rubric, ...(meta ? { status: meta.status } : {}) };
|
|
128
|
-
}
|
|
129
|
-
catch {
|
|
130
|
-
return undefined;
|
|
131
|
-
}
|
|
132
|
-
})
|
|
133
|
-
.filter((c) => c !== undefined);
|
|
134
|
-
}
|
|
135
|
-
export function loadScoreboard(baseDir, bid) {
|
|
136
|
-
const path = join(benchmarkDir(baseDir, bid), "scoreboard.json");
|
|
137
|
-
if (!existsSync(path)) {
|
|
138
|
-
return { candidates: [], decisions: [] };
|
|
139
|
-
}
|
|
140
|
-
try {
|
|
141
|
-
const raw = JSON.parse(readFileSync(path, "utf8"));
|
|
142
|
-
return {
|
|
143
|
-
...(raw.reference ? { reference: raw.reference } : {}),
|
|
144
|
-
candidates: raw.candidates ?? [],
|
|
145
|
-
decisions: raw.decisions ?? [],
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
catch {
|
|
149
|
-
return { candidates: [], decisions: [] };
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
export function saveScoreboard(baseDir, bid, board) {
|
|
153
|
-
writeFileSync(join(benchmarkDir(baseDir, bid), "scoreboard.json"), `${JSON.stringify(board, null, 2)}\n`, "utf8");
|
|
154
|
-
}
|
|
155
|
-
// ── Case meta (gap A5: quality gate + calibration history) ────────────
|
|
156
|
-
export function loadCaseMeta(baseDir, bid, cid) {
|
|
157
|
-
const path = join(benchmarkDir(baseDir, bid), "cases", cid, "meta.json");
|
|
158
|
-
if (!existsSync(path))
|
|
159
|
-
return undefined;
|
|
160
|
-
try {
|
|
161
|
-
return JSON.parse(readFileSync(path, "utf8"));
|
|
162
|
-
}
|
|
163
|
-
catch {
|
|
164
|
-
return undefined;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
export function saveCaseMeta(baseDir, bid, cid, meta) {
|
|
168
|
-
const metaDir = join(benchmarkDir(baseDir, bid), "cases", cid);
|
|
169
|
-
mkdirSync(metaDir, { recursive: true });
|
|
170
|
-
writeFileSync(join(metaDir, "meta.json"), `${JSON.stringify(meta, null, 2)}\n`, "utf8");
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Transition a case's lifecycle state. Throws on illegal transitions.
|
|
174
|
-
* draft → calibrating (start pilot)
|
|
175
|
-
* calibrating → draft (abandon calibration)
|
|
176
|
-
* calibrating → frozen (lock baseline)
|
|
177
|
-
*/
|
|
178
|
-
export function transitionCaseStatus(baseDir, bid, cid, to) {
|
|
179
|
-
const meta = loadCaseMeta(baseDir, bid, cid) ?? defaultCaseMeta();
|
|
180
|
-
const from = meta.status;
|
|
181
|
-
const valid = (from === "draft" && to === "calibrating") ||
|
|
182
|
-
(from === "calibrating" && to === "draft") ||
|
|
183
|
-
(from === "calibrating" && to === "frozen");
|
|
184
|
-
if (!valid) {
|
|
185
|
-
throw new Error(`illegal case status transition: ${from} → ${to}`);
|
|
186
|
-
}
|
|
187
|
-
meta.status = to;
|
|
188
|
-
saveCaseMeta(baseDir, bid, cid, meta);
|
|
189
|
-
return meta;
|
|
190
|
-
}
|
|
191
|
-
function defaultCaseMeta() {
|
|
192
|
-
return {
|
|
193
|
-
status: "draft",
|
|
194
|
-
capability: "",
|
|
195
|
-
distinguisher: "",
|
|
196
|
-
shortcuts: "",
|
|
197
|
-
calibrationHistory: [],
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* Quality-check a case: mechanical validation without LLM calls.
|
|
202
|
-
* Returns human-readable problems; empty array means the case passes.
|
|
203
|
-
*/
|
|
204
|
-
export function caseCheckProblems(baseDir, bid, cid) {
|
|
205
|
-
const problems = [];
|
|
206
|
-
const statementPath = join(benchmarkDir(baseDir, bid), "cases", cid, "statement.md");
|
|
207
|
-
if (!existsSync(statementPath)) {
|
|
208
|
-
problems.push("statement.md missing");
|
|
209
|
-
return problems;
|
|
210
|
-
}
|
|
211
|
-
const statement = readFileSync(statementPath, "utf8").trim();
|
|
212
|
-
if (statement.length < 20) {
|
|
213
|
-
problems.push(`statement too short (${statement.length} chars, minimum 20)`);
|
|
214
|
-
}
|
|
215
|
-
const rubricPath = join(benchmarkDir(baseDir, bid), "cases", cid, "rubric.json");
|
|
216
|
-
if (!existsSync(rubricPath)) {
|
|
217
|
-
problems.push("rubric.json missing");
|
|
218
|
-
return problems;
|
|
219
|
-
}
|
|
220
|
-
try {
|
|
221
|
-
const raw = readFileSync(rubricPath, "utf8");
|
|
222
|
-
JSON.parse(raw);
|
|
223
|
-
}
|
|
224
|
-
catch {
|
|
225
|
-
problems.push("rubric.json is not valid JSON");
|
|
226
|
-
}
|
|
227
|
-
const meta = loadCaseMeta(baseDir, bid, cid);
|
|
228
|
-
if (!meta) {
|
|
229
|
-
problems.push("meta.json missing (run /evolve benchmark casecheck to initialize)");
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
if (!meta.capability)
|
|
233
|
-
problems.push("capability contract is empty");
|
|
234
|
-
if (!meta.distinguisher)
|
|
235
|
-
problems.push("distinguisher is empty");
|
|
236
|
-
if (!meta.shortcuts)
|
|
237
|
-
problems.push("shortcuts annotation is empty");
|
|
238
|
-
}
|
|
239
|
-
return problems;
|
|
240
|
-
}
|
|
241
|
-
import { readdirSync } from "node:fs";
|
|
242
|
-
function readdirSafe(dir) {
|
|
243
|
-
try {
|
|
244
|
-
return readdirSync(dir);
|
|
245
|
-
}
|
|
246
|
-
catch {
|
|
247
|
-
return [];
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
//# sourceMappingURL=benchmark.js.map
|
package/lib/command.d.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The human-facing `/evolve` command: inspect and drive the continual
|
|
3
|
-
* harness from the chat UI without the model in between.
|
|
4
|
-
*/
|
|
5
|
-
import type { Context } from "@deepseek-ai/cordis";
|
|
6
|
-
import type { HarnessEntry, HarnessState, RefinementKind } from "./types.js";
|
|
7
|
-
import type { EvolutionEngine } from "./service.js";
|
|
8
|
-
import type { PromotionPolicy } from "./promotion.js";
|
|
9
|
-
import type { RecordLanguagePreference } from "./record-language.js";
|
|
10
|
-
export interface CommandGateOptions {
|
|
11
|
-
requireGlobalApproval: boolean;
|
|
12
|
-
}
|
|
13
|
-
export interface CommandRuntimeOptions {
|
|
14
|
-
rubricKey: Buffer;
|
|
15
|
-
/** When a benchmark decision rejects a candidate, roll the refinement back automatically. */
|
|
16
|
-
autoRollbackOnReject: boolean;
|
|
17
|
-
/** P1: capture failed evolution attempts as draft cases in the auto-regression benchmark. */
|
|
18
|
-
autoCase: boolean;
|
|
19
|
-
/** Mechanical promotion guards for wrapup/fate (2026-08-22 policy). */
|
|
20
|
-
promotionPolicy: PromotionPolicy;
|
|
21
|
-
/**
|
|
22
|
-
* Initial Memory Agent default from plugin config. The listener is always
|
|
23
|
-
* registered; this is not a registration gate.
|
|
24
|
-
*/
|
|
25
|
-
autoReview?: boolean;
|
|
26
|
-
/** Plugin `recordLanguage` preference for dialog copy (see `approval.ts`). */
|
|
27
|
-
recordLanguage?: RecordLanguagePreference;
|
|
28
|
-
}
|
|
29
|
-
export declare function registerEvolveCommand(ctx: Context, engine: EvolutionEngine, opts: CommandGateOptions, runtime: CommandRuntimeOptions): void;
|
|
30
|
-
/**
|
|
31
|
-
* Tokenize a command's raw input with shell-like quoting:
|
|
32
|
-
* - a `#` outside quotes starts a comment (rest of the line is dropped);
|
|
33
|
-
* - whitespace separates tokens;
|
|
34
|
-
* - double or single quotes group words into one token and are stripped.
|
|
35
|
-
*
|
|
36
|
-
* This lets users paste help-text examples verbatim, e.g.
|
|
37
|
-
* `/evolve benchmark add-case <bid> "<title>" "<statement>" "<rubric>"`.
|
|
38
|
-
*/
|
|
39
|
-
export declare function tokenizeEvolveInput(rawInput: string): string[];
|
|
40
|
-
/** Accept both `<id>` (help-text placeholder form) and bare `id`. */
|
|
41
|
-
export declare function stripAngleBrackets(value: string): string;
|
|
42
|
-
/**
|
|
43
|
-
* Locate an entry by id across every kind of a store. Ids are only unique
|
|
44
|
-
* within a kind, so the lookup scans all four and returns the first match
|
|
45
|
-
* (kind + entry) or undefined. Used by archive/unarchive, which take a bare
|
|
46
|
-
* id from the user.
|
|
47
|
-
*/
|
|
48
|
-
export declare function findEntryById(state: HarnessState, id: string): [RefinementKind, HarnessEntry] | undefined;
|
|
49
|
-
//# sourceMappingURL=command.d.ts.map
|