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.
Files changed (126) hide show
  1. package/README.md +35 -122
  2. package/README.zh.md +26 -97
  3. package/cordis.patch.yml +2 -2
  4. package/lib/index.d.ts +44 -241
  5. package/lib/index.js +30 -253
  6. package/lib/memory-guide.d.ts +13 -14
  7. package/lib/memory-guide.js +32 -21
  8. package/lib/memory-section.d.ts +77 -0
  9. package/lib/memory-section.js +189 -0
  10. package/package.json +2 -17
  11. package/lib/apply.d.ts +0 -22
  12. package/lib/apply.js +0 -157
  13. package/lib/approval.d.ts +0 -72
  14. package/lib/approval.js +0 -127
  15. package/lib/auto.d.ts +0 -236
  16. package/lib/auto.js +0 -773
  17. package/lib/autocase.d.ts +0 -38
  18. package/lib/autocase.js +0 -76
  19. package/lib/benchmark-command.d.ts +0 -9
  20. package/lib/benchmark-command.js +0 -357
  21. package/lib/benchmark.d.ts +0 -151
  22. package/lib/benchmark.js +0 -250
  23. package/lib/command.d.ts +0 -49
  24. package/lib/command.js +0 -568
  25. package/lib/consolidate.d.ts +0 -90
  26. package/lib/consolidate.js +0 -180
  27. package/lib/copy.d.ts +0 -74
  28. package/lib/copy.js +0 -160
  29. package/lib/declines.d.ts +0 -101
  30. package/lib/declines.js +0 -175
  31. package/lib/evaluate.d.ts +0 -74
  32. package/lib/evaluate.js +0 -271
  33. package/lib/evolve-event.d.ts +0 -40
  34. package/lib/evolve-event.js +0 -59
  35. package/lib/failures.d.ts +0 -42
  36. package/lib/failures.js +0 -171
  37. package/lib/fate.d.ts +0 -130
  38. package/lib/fate.js +0 -350
  39. package/lib/goal-command.d.ts +0 -7
  40. package/lib/goal-command.js +0 -37
  41. package/lib/goal.d.ts +0 -72
  42. package/lib/goal.js +0 -72
  43. package/lib/inject.d.ts +0 -196
  44. package/lib/inject.js +0 -412
  45. package/lib/llm-text.d.ts +0 -104
  46. package/lib/llm-text.js +0 -140
  47. package/lib/logfile.d.ts +0 -71
  48. package/lib/logfile.js +0 -159
  49. package/lib/memory-agent.d.ts +0 -129
  50. package/lib/memory-agent.js +0 -568
  51. package/lib/memory-benchmark.d.ts +0 -76
  52. package/lib/memory-benchmark.js +0 -170
  53. package/lib/memory-index.d.ts +0 -114
  54. package/lib/memory-index.js +0 -197
  55. package/lib/message-source.d.ts +0 -23
  56. package/lib/message-source.js +0 -12
  57. package/lib/mount-command.d.ts +0 -10
  58. package/lib/mount-command.js +0 -48
  59. package/lib/mount.d.ts +0 -42
  60. package/lib/mount.js +0 -212
  61. package/lib/notify.d.ts +0 -59
  62. package/lib/notify.js +0 -97
  63. package/lib/plan.d.ts +0 -16
  64. package/lib/plan.js +0 -126
  65. package/lib/planner.d.ts +0 -61
  66. package/lib/planner.js +0 -144
  67. package/lib/pool.d.ts +0 -7
  68. package/lib/pool.js +0 -25
  69. package/lib/prefix-cache.d.ts +0 -78
  70. package/lib/prefix-cache.js +0 -168
  71. package/lib/project.d.ts +0 -28
  72. package/lib/project.js +0 -66
  73. package/lib/projection.d.ts +0 -22
  74. package/lib/projection.js +0 -112
  75. package/lib/promotion.d.ts +0 -94
  76. package/lib/promotion.js +0 -171
  77. package/lib/recall.d.ts +0 -85
  78. package/lib/recall.js +0 -142
  79. package/lib/record-language.d.ts +0 -85
  80. package/lib/record-language.js +0 -152
  81. package/lib/render.d.ts +0 -13
  82. package/lib/render.js +0 -80
  83. package/lib/review-scheduler.d.ts +0 -38
  84. package/lib/review-scheduler.js +0 -191
  85. package/lib/review.d.ts +0 -60
  86. package/lib/review.js +0 -145
  87. package/lib/rollback.d.ts +0 -9
  88. package/lib/rollback.js +0 -68
  89. package/lib/rubric.d.ts +0 -29
  90. package/lib/rubric.js +0 -119
  91. package/lib/runtime.d.ts +0 -24
  92. package/lib/runtime.js +0 -87
  93. package/lib/score.d.ts +0 -64
  94. package/lib/score.js +0 -191
  95. package/lib/search.d.ts +0 -83
  96. package/lib/search.js +0 -136
  97. package/lib/service.d.ts +0 -49
  98. package/lib/service.js +0 -180
  99. package/lib/skill-render.d.ts +0 -23
  100. package/lib/skill-render.js +0 -69
  101. package/lib/skill.d.ts +0 -15
  102. package/lib/skill.js +0 -80
  103. package/lib/skillquality.d.ts +0 -85
  104. package/lib/skillquality.js +0 -320
  105. package/lib/source.d.ts +0 -30
  106. package/lib/source.js +0 -43
  107. package/lib/state.d.ts +0 -26
  108. package/lib/state.js +0 -151
  109. package/lib/store.d.ts +0 -62
  110. package/lib/store.js +0 -164
  111. package/lib/token-usage.d.ts +0 -68
  112. package/lib/token-usage.js +0 -211
  113. package/lib/tool.d.ts +0 -34
  114. package/lib/tool.js +0 -320
  115. package/lib/turn-snapshot.d.ts +0 -72
  116. package/lib/turn-snapshot.js +0 -238
  117. package/lib/types.d.ts +0 -208
  118. package/lib/types.js +0 -127
  119. package/lib/usage.d.ts +0 -36
  120. package/lib/usage.js +0 -98
  121. package/lib/validate.d.ts +0 -28
  122. package/lib/validate.js +0 -181
  123. package/lib/wrapup-command.d.ts +0 -10
  124. package/lib/wrapup-command.js +0 -243
  125. package/lib/wrapup.d.ts +0 -260
  126. package/lib/wrapup.js +0 -539
@@ -1,152 +0,0 @@
1
- /**
2
- * Record language resolution for evolution writes.
3
- *
4
- * Every durable record (refinement summary/rationale, entry title/content,
5
- * review and wrap-up verdicts) is generated prose. Its language is resolved
6
- * per call through one chain — never hardcoded at any single site:
7
- *
8
- * 1. explicit `recordLanguage` plugin config (`zh`|`en`; `auto` defers);
9
- * 2. the durable DSH client preference (`locale` namespace, `preference`
10
- * field — the same source the desktop shell and the web GUI follow);
11
- * 3. detection over recent direct user text (Han-character signal);
12
- * 4. `en`, matching the DSH `FALLBACK_LOCALE`.
13
- *
14
- * The durable-preference read is intentionally fail-open: the settings
15
- * service is host-owned and its shape may drift, so any mismatch yields
16
- * `undefined` and the chain moves on instead of breaking the evolution run.
17
- */
18
- /**
19
- * Upstream durable-settings address reused verbatim
20
- * (`@deepseek-ai/dsh-client-locale`: `LOCALE_SETTINGS_NAMESPACE`,
21
- * `LOCALE_PREFERENCE_FIELD`). New keys are never invented here.
22
- */
23
- export const DSH_LOCALE_NAMESPACE = "locale";
24
- export const DSH_LOCALE_PREFERENCE_FIELD = "preference";
25
- /** Han ideographs — the detection signal for Chinese user text. */
26
- const HAN_PATTERN = /[\u4e00-\u9fff]/g;
27
- /** Minimum Han hits to count as signal (stray characters must not flip). */
28
- const HAN_SIGNAL_MIN = 5;
29
- /** Detection scans a bounded prefix; trajectories are long and the signal is dense. */
30
- const DETECT_SCAN_CHARS = 4000;
31
- /**
32
- * Detect Chinese from user text by Han-character density.
33
- *
34
- * @param text Arbitrary user-supplied text.
35
- * @returns `"zh"` on sufficient Han signal, otherwise `undefined` (no
36
- * signal — never a default; the resolver owns the fallback).
37
- */
38
- export function detectLanguageFromText(text) {
39
- const hits = (text.slice(0, DETECT_SCAN_CHARS).match(HAN_PATTERN) ?? []).length;
40
- return hits >= HAN_SIGNAL_MIN ? "zh" : undefined;
41
- }
42
- /**
43
- * Read the durable DSH client language preference through the host settings
44
- * service. Fail-open by contract: a missing service, a throwing read, an
45
- * async-shaped reply, or an unknown value all yield `undefined`.
46
- *
47
- * The service is resolved through `ctx.get("settings")` (the global registry),
48
- * which sees services provided by sibling plugin entries. A direct
49
- * `ctx.settings` walks only the caller's fiber ancestor chain and throws
50
- * "cannot get property \"settings\" without inject" — the same failure mode
51
- * documented in `goal.ts` — and a throw here would abort the whole snapshot
52
- * gate, so the property access itself is guarded. Plain-object contexts
53
- * (tests, non-Cordis hosts) fall back to the direct property.
54
- *
55
- * @param ctx Cordis context that may carry the host settings service.
56
- * @returns The stored preference (`zh`/`en`, subtag-tolerant) or `undefined`.
57
- */
58
- export function durableLocalePreference(ctx) {
59
- if (typeof ctx !== "object" || ctx === null)
60
- return undefined;
61
- let settings;
62
- try {
63
- const get = ctx.get;
64
- settings = typeof get === "function" ? get.call(ctx, "settings") : undefined;
65
- if (settings === undefined)
66
- settings = ctx.settings;
67
- }
68
- catch {
69
- return undefined;
70
- }
71
- if (typeof settings !== "object" || settings === null)
72
- return undefined;
73
- const describe = settings.describe;
74
- if (typeof describe !== "function")
75
- return undefined;
76
- let rows;
77
- try {
78
- rows = describe({ redactSecrets: true });
79
- }
80
- catch {
81
- return undefined;
82
- }
83
- if (!Array.isArray(rows))
84
- return undefined;
85
- for (const row of rows) {
86
- if (typeof row !== "object" || row === null)
87
- continue;
88
- const record = row;
89
- if (record["ns"] !== DSH_LOCALE_NAMESPACE)
90
- continue;
91
- const value = record["value"];
92
- if (typeof value !== "object" || value === null)
93
- return undefined;
94
- const preference = value[DSH_LOCALE_PREFERENCE_FIELD];
95
- if (typeof preference !== "string")
96
- return undefined;
97
- const id = preference.toLowerCase();
98
- if (id === "zh" || id.startsWith("zh-"))
99
- return "zh";
100
- if (id === "en" || id.startsWith("en-"))
101
- return "en";
102
- return undefined;
103
- }
104
- return undefined;
105
- }
106
- /**
107
- * Normalize an explicit preference or durable value to a record language.
108
- *
109
- * @param value Candidate language id (config or durable preference).
110
- * @returns `"zh"`/`"en"` on a recognized id, otherwise `undefined`.
111
- */
112
- export function normalizeRecordLanguage(value) {
113
- if (value === "zh" || value === "en")
114
- return value;
115
- return undefined;
116
- }
117
- /**
118
- * Resolve the authoring language for one evolution write.
119
- *
120
- * @param input Configured preference, host context, and trajectory sample.
121
- * @returns The winning language; always defined (`en` is the final fallback).
122
- */
123
- export function resolveRecordLanguage(input) {
124
- const configured = normalizeRecordLanguage(input.configured === "auto" ? undefined : input.configured);
125
- if (configured !== undefined)
126
- return configured;
127
- if (input.ctx !== undefined) {
128
- const durable = normalizeRecordLanguage(durableLocalePreference(input.ctx));
129
- if (durable !== undefined)
130
- return durable;
131
- }
132
- if (input.trajectoryText !== undefined) {
133
- const detected = detectLanguageFromText(input.trajectoryText);
134
- if (detected !== undefined)
135
- return detected;
136
- }
137
- return "en";
138
- }
139
- /**
140
- * The one-line prompt addendum appended to every record-authoring system
141
- * prompt. Machine contracts (JSON keys, ids, paths, code) stay untouched —
142
- * only natural-language values follow the resolved language.
143
- *
144
- * @param lang Resolved record language.
145
- * @returns The instruction line for `lang`.
146
- */
147
- export function recordLanguageInstruction(lang) {
148
- return lang === "zh"
149
- ? "记录语言:用简体中文写所有的自然语言值(title、content、summary、rationale、reason、expectedOutcome)。JSON 键名、id、path 与代码片段保持原样。"
150
- : "Record language: write all natural-language values (title, content, summary, rationale, reason, expectedOutcome) in English. Keep JSON keys, ids, paths, and code snippets unchanged.";
151
- }
152
- //# sourceMappingURL=record-language.js.map
package/lib/render.d.ts DELETED
@@ -1,13 +0,0 @@
1
- /**
2
- * Prompt rendering: bounded, model-visible views of harness state and
3
- * refinement history. Every cap exists to keep token cost predictable no
4
- * matter how large the store grows.
5
- */
6
- import type { HarnessEntry, HarnessState, RefinementResult } from "./types.js";
7
- export declare function compactText(text: string, maxLength: number): string;
8
- export declare function entryLine(entry: HarnessEntry, maxContentLength: number): string;
9
- /** Render the full merged state as a bounded overview for the system prompt. */
10
- export declare function formatHarnessStateForPrompt(state: HarnessState): string;
11
- /** Render recent refinement results for the planner. */
12
- export declare function historyForPrompt(history: readonly RefinementResult[]): string;
13
- //# sourceMappingURL=render.d.ts.map
package/lib/render.js DELETED
@@ -1,80 +0,0 @@
1
- import { SOURCE_SESSION_KEY, SOURCE_SEQS_KEY, isArchived } from "./types.js";
2
- const DEFAULT_MAX_ENTRIES_PER_KIND = 6;
3
- const DEFAULT_MAX_REFINEMENTS = 5;
4
- const DEFAULT_MAX_CONTENT_LENGTH = 180;
5
- export function compactText(text, maxLength) {
6
- const normalized = text.replace(/\s+/g, " ").trim();
7
- if (normalized.length <= maxLength) {
8
- return normalized;
9
- }
10
- return `${normalized.slice(0, Math.max(0, maxLength - 3))}...`;
11
- }
12
- export function entryLine(entry, maxContentLength) {
13
- const argumentsText = entry.kind === "skill" && Object.keys(entry.arguments).length > 0
14
- ? ` args=${compactText(JSON.stringify(entry.arguments), maxContentLength)}`
15
- : "";
16
- const referenceText = entry.kind === "skill" && Object.keys(entry.reference).length > 0
17
- ? ` ref=${compactText(JSON.stringify(entry.reference), maxContentLength)}`
18
- : "";
19
- const citationText = citationSuffix(entry);
20
- const archivedText = isArchived(entry) ? " [archived]" : "";
21
- const formText = entry.kind === "skill" && entry.skill_kind === "guidance" ? " [guidance]" : "";
22
- return `- [${entry.scope}:${entry.id}] ${entry.title} (${entry.path}, v${entry.version})${archivedText}${formText}${referenceText}${argumentsText}${citationText}: ${compactText(entry.content, maxContentLength)}`;
23
- }
24
- /** Trajectory citation suffix (` src=sessionId:1,2`), empty when uncited. */
25
- function citationSuffix(entry) {
26
- const sessionId = entry.metadata[SOURCE_SESSION_KEY];
27
- if (typeof sessionId !== "string" || sessionId.length === 0) {
28
- return "";
29
- }
30
- const seqs = entry.metadata[SOURCE_SEQS_KEY];
31
- const seqText = Array.isArray(seqs) && seqs.length > 0 ? `:${seqs.join(",")}` : "";
32
- return ` src=${sessionId}${seqText}`;
33
- }
34
- /** Render the full merged state as a bounded overview for the system prompt. */
35
- export function formatHarnessStateForPrompt(state) {
36
- const lines = [
37
- "# Continual Harness State",
38
- "",
39
- "Local entries belong to this session. Global entries persist across sessions.",
40
- "The base system prompt is immutable; prompt entries are supplemental notes only.",
41
- "",
42
- ];
43
- let total = 0;
44
- for (const kind of Object.keys(state.entries)) {
45
- const entries = Object.values(state.entries[kind]).sort((a, b) => [a.path, a.title, a.id].join("\0").localeCompare([b.path, b.title, b.id].join("\0")));
46
- total += entries.length;
47
- lines.push(`${kind}: ${entries.length}`);
48
- for (const entry of entries.slice(0, DEFAULT_MAX_ENTRIES_PER_KIND)) {
49
- lines.push(entryLine(entry, DEFAULT_MAX_CONTENT_LENGTH));
50
- }
51
- const overflow = entries.length - Math.min(entries.length, DEFAULT_MAX_ENTRIES_PER_KIND);
52
- if (overflow > 0) {
53
- lines.push(`- +${overflow} more ${kind} entries`);
54
- }
55
- lines.push("");
56
- }
57
- if (total === 0) {
58
- lines.push("No saved harness entries yet.", "");
59
- }
60
- lines.push(`recent refinements: ${state.refinements.length}`);
61
- for (const event of state.refinements.slice(-DEFAULT_MAX_REFINEMENTS)) {
62
- lines.push(`- [${event.id}] ${compactText(event.trigger, DEFAULT_MAX_CONTENT_LENGTH)}: ${event.changes.join(", ") || "no applied edits"}`);
63
- }
64
- return lines.join("\n").trim();
65
- }
66
- /** Render recent refinement results for the planner. */
67
- export function historyForPrompt(history) {
68
- if (history.length === 0) {
69
- return "No prior refinement history.";
70
- }
71
- return history
72
- .slice(-20)
73
- .map((item) => {
74
- const edits = item.appliedEdits.map((e) => `${e.applied ? "applied" : "failed"} ${e.action} ${e.kind}:${e.id}`).join(", ");
75
- const rollback = item.rollbackOf ? ` rollbackOf=${item.rollbackOf}` : "";
76
- return `[${item.id}]${rollback} ${item.summary}\n${edits}\nExpected outcome: ${item.expectedOutcome}`;
77
- })
78
- .join("\n\n");
79
- }
80
- //# sourceMappingURL=render.js.map
@@ -1,38 +0,0 @@
1
- /**
2
- * Serial latest-boundary scheduler for automatic memory+review snapshots.
3
- *
4
- * One runner exists per session. A burst is coalesced by durable cursor rather
5
- * than promise arrival: once multiple pending captures settle, the highest
6
- * comparable boundary runs first. A cursor advances only after success/no-op;
7
- * errors, aborts, and stale boundaries leave it unchanged.
8
- */
9
- /** Compare two scheduler cursors; undefined means the cursor families differ. */
10
- export declare function compareReviewCursors(left: string, right: string): number | undefined;
11
- /** Terminal state of one scheduled snapshot. */
12
- export type ReviewSchedulerStatus = "success" | "no-op" | "error" | "aborted";
13
- /** A scheduler execution receives the exact snapshot and its owner signal. */
14
- export interface ReviewSchedulerExecution<TSnapshot> {
15
- readonly snapshot: TSnapshot;
16
- readonly signal: AbortSignal;
17
- }
18
- /** Public scheduler surface used by the auto-review driver and tests. */
19
- export interface ReviewScheduler<TSnapshot> {
20
- /** Wait until the current run and all coalesced pending work settle. */
21
- drain(): Promise<void>;
22
- /** Last successfully processed or skipped snapshot boundary. */
23
- getCursor(): string | undefined;
24
- /** Whether a run or a pending acquisition exists. */
25
- hasPendingWork(): boolean;
26
- /** Submit a snapshot (or an async acquisition) without blocking the caller. */
27
- schedule(snapshot: TSnapshot | Promise<TSnapshot>): void;
28
- /** Abort the owner signal, drop pending work, and make later schedules no-ops. */
29
- shutdown(): void;
30
- }
31
- /**
32
- * Create a scheduler with ZCode-compatible serial/coalescing semantics.
33
- *
34
- * @param execute - one serial extraction/review operation
35
- * @param cursorOf - extracts the durable boundary from a snapshot
36
- */
37
- export declare function createReviewScheduler<TSnapshot>(execute: (input: ReviewSchedulerExecution<TSnapshot>) => Promise<ReviewSchedulerStatus>, cursorOf: (snapshot: TSnapshot) => string | undefined): ReviewScheduler<TSnapshot>;
38
- //# sourceMappingURL=review-scheduler.d.ts.map
@@ -1,191 +0,0 @@
1
- /**
2
- * Serial latest-boundary scheduler for automatic memory+review snapshots.
3
- *
4
- * One runner exists per session. A burst is coalesced by durable cursor rather
5
- * than promise arrival: once multiple pending captures settle, the highest
6
- * comparable boundary runs first. A cursor advances only after success/no-op;
7
- * errors, aborts, and stale boundaries leave it unchanged.
8
- */
9
- /** Compare two scheduler cursors; undefined means the cursor families differ. */
10
- export function compareReviewCursors(left, right) {
11
- if (left === right)
12
- return 0;
13
- const leftMatch = /^(seq|index):(\d+)$/.exec(left);
14
- const rightMatch = /^(seq|index):(\d+)$/.exec(right);
15
- if (!leftMatch || !rightMatch || leftMatch[1] !== rightMatch[1])
16
- return undefined;
17
- return Number(leftMatch[2]) - Number(rightMatch[2]);
18
- }
19
- /** Bound unresolved acquisitions; actual auto capture is serialized per session. */
20
- const MAX_PENDING_ACQUISITIONS = 16;
21
- /**
22
- * Create a scheduler with ZCode-compatible serial/coalescing semantics.
23
- *
24
- * @param execute - one serial extraction/review operation
25
- * @param cursorOf - extracts the durable boundary from a snapshot
26
- */
27
- export function createReviewScheduler(execute, cursorOf) {
28
- let cursor;
29
- let running;
30
- let shuttingDown = false;
31
- let wakePending;
32
- const pending = [];
33
- const shutdownController = new AbortController();
34
- const signal = shutdownController.signal;
35
- const trackPending = (acquisition) => {
36
- const entry = {};
37
- entry.promise = acquisition.then((result) => {
38
- entry.result = result;
39
- wakePending?.();
40
- return result;
41
- });
42
- pending.push(entry);
43
- while (pending.length > MAX_PENDING_ACQUISITIONS)
44
- pending.shift();
45
- };
46
- const takeHighestPending = async () => {
47
- while (!signal.aborted) {
48
- for (let index = pending.length - 1; index >= 0; index -= 1) {
49
- if (pending[index]?.result?.status === "error")
50
- pending.splice(index, 1);
51
- }
52
- if (pending.length === 0)
53
- return undefined;
54
- const settled = pending.filter((entry) => entry.result !== undefined);
55
- if (settled.length > 0) {
56
- let bestIndex = -1;
57
- let bestCursor;
58
- for (let index = 0; index < settled.length; index += 1) {
59
- const entry = settled[index];
60
- if (!entry || entry.result?.status !== "acquired")
61
- continue;
62
- const candidate = cursorOf(entry.result.snapshot);
63
- const order = bestCursor === undefined || candidate === undefined
64
- ? 1
65
- : compareReviewCursors(candidate, bestCursor);
66
- if (bestIndex < 0 || order === undefined || order > 0) {
67
- bestIndex = pending.indexOf(entry);
68
- bestCursor = candidate;
69
- }
70
- }
71
- // bestIndex is always set here: the error purge above leaves only
72
- // acquired snapshots in `settled` (SnapshotAcquisition has exactly
73
- // two variants), so the first settled entry takes the slot.
74
- const chosen = pending[bestIndex];
75
- pending.splice(bestIndex, 1);
76
- for (let index = pending.length - 1; index >= 0; index -= 1) {
77
- if (pending[index]?.result !== undefined)
78
- pending.splice(index, 1);
79
- }
80
- return chosen?.result;
81
- }
82
- await new Promise((resolve) => {
83
- const cleanup = () => signal.removeEventListener("abort", onAbort);
84
- const onAbort = () => {
85
- cleanup();
86
- resolve();
87
- };
88
- wakePending = () => {
89
- cleanup();
90
- wakePending = undefined;
91
- resolve();
92
- };
93
- signal.addEventListener("abort", onAbort, { once: true });
94
- });
95
- }
96
- return undefined;
97
- };
98
- const processSnapshot = async (snapshot) => {
99
- if (shuttingDown || signal.aborted)
100
- return;
101
- const nextCursor = cursorOf(snapshot);
102
- if (cursor !== undefined && nextCursor !== undefined) {
103
- const order = compareReviewCursors(nextCursor, cursor);
104
- if (order !== undefined && order <= 0)
105
- return;
106
- }
107
- let status;
108
- try {
109
- status = await execute({ snapshot, signal });
110
- }
111
- catch {
112
- return;
113
- }
114
- if (!shuttingDown && (status === "success" || status === "no-op") && nextCursor !== undefined) {
115
- const order = cursor === undefined ? 1 : compareReviewCursors(nextCursor, cursor);
116
- if (order === undefined || order > 0)
117
- cursor = nextCursor;
118
- }
119
- };
120
- const run = async (first) => {
121
- try {
122
- let acquisition = await waitForSnapshotAcquisitionOrShutdown(first, signal);
123
- while (acquisition.status !== "shutdown" && !shuttingDown) {
124
- if (acquisition.status === "acquired")
125
- await processSnapshot(acquisition.snapshot);
126
- const next = await takeHighestPending();
127
- if (!next)
128
- break;
129
- acquisition = next;
130
- }
131
- }
132
- finally {
133
- if (shuttingDown) {
134
- pending.length = 0;
135
- wakePending?.();
136
- wakePending = undefined;
137
- }
138
- running = undefined;
139
- }
140
- };
141
- return {
142
- async drain() {
143
- while (running)
144
- await running;
145
- },
146
- getCursor() {
147
- return cursor;
148
- },
149
- hasPendingWork() {
150
- return running !== undefined || pending.length > 0;
151
- },
152
- schedule(snapshot) {
153
- if (shuttingDown)
154
- return;
155
- const acquisition = acquireSnapshot(snapshot);
156
- if (running)
157
- trackPending(acquisition);
158
- else
159
- running = run(acquisition);
160
- },
161
- shutdown() {
162
- if (shuttingDown)
163
- return;
164
- shuttingDown = true;
165
- pending.length = 0;
166
- shutdownController.abort();
167
- wakePending?.();
168
- wakePending = undefined;
169
- },
170
- };
171
- }
172
- function acquireSnapshot(snapshot) {
173
- return Promise.resolve(snapshot).then((value) => ({ status: "acquired", snapshot: value }), () => ({ status: "error" }));
174
- }
175
- function waitForSnapshotAcquisitionOrShutdown(acquisition, signal) {
176
- if (signal.aborted)
177
- return Promise.resolve({ status: "shutdown" });
178
- return new Promise((resolve) => {
179
- const cleanup = () => signal.removeEventListener("abort", onAbort);
180
- const onAbort = () => {
181
- cleanup();
182
- resolve({ status: "shutdown" });
183
- };
184
- signal.addEventListener("abort", onAbort, { once: true });
185
- void acquisition.then((result) => {
186
- cleanup();
187
- resolve(result);
188
- });
189
- });
190
- }
191
- //# sourceMappingURL=review-scheduler.js.map
package/lib/review.d.ts DELETED
@@ -1,60 +0,0 @@
1
- /**
2
- * The automatic /evolve review gate: a cheap model call that decides whether
3
- * the current trajectory justifies running the planner. Runs on a turn
4
- * interval (and, in a later step, at compaction). The gate is deliberately
5
- * small (bounded input, small output budget) — it only answers
6
- * "should we refine?", never "what should we edit?".
7
- */
8
- import type { Context } from "@deepseek-ai/cordis";
9
- import type { Agent } from "@deepseek-ai/dsh-agent";
10
- import type { HarnessState, RefinementResult } from "./types.js";
11
- import { type PrefixCacheOptions } from "./prefix-cache.js";
12
- import { type TokenUsageTarget } from "./token-usage.js";
13
- import { type RecordLanguage } from "./record-language.js";
14
- export interface AutoRefineReview {
15
- shouldRefine: boolean;
16
- rationale: string;
17
- instructions?: string;
18
- }
19
- export type AutoRefineReason = "turn_snapshot" | "turn_interval" | "compact" | "goal_blocked";
20
- export interface AutoRefineReviewContext {
21
- reason: AutoRefineReason;
22
- turnsSinceLastReview: number;
23
- }
24
- export interface ReviewOptions {
25
- agent: Agent;
26
- state: HarnessState;
27
- history: readonly RefinementResult[];
28
- context: AutoRefineReviewContext;
29
- /** Serialized trajectory text; when absent the gate is skipped by the caller. */
30
- trajectory?: string;
31
- /** Incremental surface rows captured for this turn snapshot. */
32
- trajectoryEvents?: readonly unknown[];
33
- signal?: AbortSignal;
34
- budgetTokens?: number;
35
- /** Gap C1: optional provider/model override for the review gate (cheaper model). */
36
- overrideProvider?: string;
37
- overrideModel?: string;
38
- /**
39
- * Prefix-cache routing for the gate input. Route A prepends a
40
- * session-derived message prefix and drops the flat `<conversation>`
41
- * block (same source, structured form); Route B keeps it. Absent →
42
- * auto-detect with the default budget.
43
- */
44
- prefixCache?: PrefixCacheOptions;
45
- /** Direct-call token ledger destination; the review phase is fixed by this module. */
46
- tokenUsage?: TokenUsageTarget;
47
- /**
48
- * Authoring language for the rationale. Absent → resolved per call
49
- * (explicit config upstream, else durable client preference, else
50
- * trajectory detection, else `en`).
51
- */
52
- language?: RecordLanguage;
53
- }
54
- export declare const AUTO_REVIEW_SYSTEM_PROMPT = "You are the automatic /evolve review gate.\n\nDecide whether this checkpoint should continue the non-memory /evolve path.\nA dedicated memory extraction agent has already processed the same snapshot\nwith a frozen memory manifest, so do NOT approve solely to create, update,\narchive, or delete a memory entry. Decline with a rationale that the memory\nphase owns that evidence. For the remaining kinds, approve ONLY when the\ntrajectory shows repeated evidence: the same failure, tactic, delegation\nrole, or behavioral policy recurs at least twice across turns. A single\none-off interaction defaults to decline no matter how useful it looks for\nfuture turns \u2014 one data point is never enough to generalize. When approving,\ncite the repeated spans in the instructions so the planner can ground its\nedits.\n\nThe current harness state below includes GLOBAL entries (scope=global) plus\nthis session's local entries (scope=local). When a topic is already covered\nby a global entry, do NOT approve a local duplicate of it \u2014 decline and say\nin the rationale that the topic is already covered globally.\n\nReject one-off noise, unsupported hypotheses, transient tool outputs, and\nrequests that carry no reusable content.\n\nStale local entries (superseded, long-unused, obsolete facts) are a valid\nrefine target: approve with instructions naming the entry ids, and tell the\nplanner to archive them (archive hides from injection, data stays restorable)\nrather than delete.\n\nSkill-related trajectories (the evidence concerns creating or improving a\nskill entry) are judged against the DSH skill quality standard (skill-audit\ndimensions: frontmatter routing, the 7 structural features, paragraph\nskeleton, no duplication of the official 11 skills or covered skills).\nApprove only when the trajectory shows a REAL trigger scenario and the\nresulting skill would meet the standard; otherwise decline and say in the\nrationale what must improve \u2014 drafting follows skill-creator, and the\nplanner receives the standard as its <skill_quality_standard> block.\n\nRepeated multi-step workflows (session start/end routines, recurring\nwrap-up or handoff procedures) are a valid refine target: approve with\ninstructions telling the planner to propose a guidance skill (kind=skill,\nskill_kind=guidance \u2014 a SKILL.md document, no python reference). Only\npropose when the same workflow recurs in the trajectory \u2014 never for\none-off flows. Auto-created skills are always offered to the user for a\ndecision before they land; the gate never writes a skill silently.\n\nReturn JSON only:\n{\n \"shouldRefine\": true|false,\n \"rationale\": \"short reason\",\n \"instructions\": \"optional concise instructions for /evolve if shouldRefine is true\"\n}";
55
- /** Parse the gate's JSON reply. */
56
- export declare function parseAutoRefineReview(text: string): AutoRefineReview;
57
- /** Serialize surface events to bounded role-prefixed text. */
58
- export declare function serializeSurface(events: readonly unknown[], maxChars: number): string;
59
- export declare function reviewAutoRefine(ctx: Context, options: ReviewOptions): Promise<AutoRefineReview>;
60
- //# sourceMappingURL=review.d.ts.map