dsh-continual-evolve 0.11.0 → 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 (154) hide show
  1. package/README.md +35 -115
  2. package/README.zh.md +26 -93
  3. package/cordis.patch.yml +2 -2
  4. package/lib/index.d.ts +44 -225
  5. package/lib/index.js +30 -239
  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 -73
  14. package/lib/approval.js +0 -127
  15. package/lib/audit-log.d.ts +0 -19
  16. package/lib/audit-log.js +0 -52
  17. package/lib/auto.d.ts +0 -236
  18. package/lib/auto.js +0 -773
  19. package/lib/autocase.d.ts +0 -38
  20. package/lib/autocase.js +0 -76
  21. package/lib/benchmark-command.d.ts +0 -9
  22. package/lib/benchmark-command.js +0 -357
  23. package/lib/benchmark.d.ts +0 -151
  24. package/lib/benchmark.js +0 -250
  25. package/lib/command-util.d.ts +0 -70
  26. package/lib/command-util.js +0 -123
  27. package/lib/command.d.ts +0 -13
  28. package/lib/command.js +0 -134
  29. package/lib/consolidate.d.ts +0 -90
  30. package/lib/consolidate.js +0 -180
  31. package/lib/copy.d.ts +0 -37
  32. package/lib/copy.js +0 -58
  33. package/lib/declines.d.ts +0 -103
  34. package/lib/declines.js +0 -179
  35. package/lib/evaluate.d.ts +0 -74
  36. package/lib/evaluate.js +0 -271
  37. package/lib/evolve-event.d.ts +0 -40
  38. package/lib/evolve-event.js +0 -60
  39. package/lib/extraction-phase.d.ts +0 -132
  40. package/lib/extraction-phase.js +0 -236
  41. package/lib/failures.d.ts +0 -42
  42. package/lib/failures.js +0 -171
  43. package/lib/fate.d.ts +0 -130
  44. package/lib/fate.js +0 -350
  45. package/lib/goal-command.d.ts +0 -7
  46. package/lib/goal-command.js +0 -37
  47. package/lib/goal.d.ts +0 -72
  48. package/lib/goal.js +0 -72
  49. package/lib/inject.d.ts +0 -90
  50. package/lib/inject.js +0 -164
  51. package/lib/injection-caps.d.ts +0 -4
  52. package/lib/injection-caps.js +0 -4
  53. package/lib/injection-directory.d.ts +0 -29
  54. package/lib/injection-directory.js +0 -78
  55. package/lib/injection-rank.d.ts +0 -85
  56. package/lib/injection-rank.js +0 -161
  57. package/lib/listener.d.ts +0 -45
  58. package/lib/listener.js +0 -199
  59. package/lib/llm-text.d.ts +0 -104
  60. package/lib/llm-text.js +0 -140
  61. package/lib/logfile.d.ts +0 -71
  62. package/lib/logfile.js +0 -159
  63. package/lib/maintenance-commands.d.ts +0 -23
  64. package/lib/maintenance-commands.js +0 -136
  65. package/lib/memory-agent.d.ts +0 -93
  66. package/lib/memory-agent.js +0 -300
  67. package/lib/memory-apply.d.ts +0 -44
  68. package/lib/memory-apply.js +0 -202
  69. package/lib/memory-benchmark.d.ts +0 -76
  70. package/lib/memory-benchmark.js +0 -170
  71. package/lib/memory-index.d.ts +0 -114
  72. package/lib/memory-index.js +0 -197
  73. package/lib/memory-manifest.d.ts +0 -16
  74. package/lib/memory-manifest.js +0 -70
  75. package/lib/message-source.d.ts +0 -23
  76. package/lib/message-source.js +0 -12
  77. package/lib/mount-command.d.ts +0 -10
  78. package/lib/mount-command.js +0 -48
  79. package/lib/mount.d.ts +0 -42
  80. package/lib/mount.js +0 -212
  81. package/lib/notify.d.ts +0 -48
  82. package/lib/notify.js +0 -57
  83. package/lib/plan-command.d.ts +0 -12
  84. package/lib/plan-command.js +0 -38
  85. package/lib/plan.d.ts +0 -16
  86. package/lib/plan.js +0 -126
  87. package/lib/planner.d.ts +0 -61
  88. package/lib/planner.js +0 -144
  89. package/lib/pool.d.ts +0 -7
  90. package/lib/pool.js +0 -25
  91. package/lib/prefix-cache.d.ts +0 -79
  92. package/lib/prefix-cache.js +0 -168
  93. package/lib/project.d.ts +0 -28
  94. package/lib/project.js +0 -66
  95. package/lib/projection.d.ts +0 -22
  96. package/lib/projection.js +0 -112
  97. package/lib/promotion.d.ts +0 -94
  98. package/lib/promotion.js +0 -171
  99. package/lib/recall.d.ts +0 -85
  100. package/lib/recall.js +0 -142
  101. package/lib/record-language.d.ts +0 -85
  102. package/lib/record-language.js +0 -152
  103. package/lib/render.d.ts +0 -13
  104. package/lib/render.js +0 -80
  105. package/lib/review-scheduler.d.ts +0 -38
  106. package/lib/review-scheduler.js +0 -183
  107. package/lib/review.d.ts +0 -60
  108. package/lib/review.js +0 -145
  109. package/lib/rollback.d.ts +0 -9
  110. package/lib/rollback.js +0 -68
  111. package/lib/rubric.d.ts +0 -29
  112. package/lib/rubric.js +0 -119
  113. package/lib/runtime-commands.d.ts +0 -14
  114. package/lib/runtime-commands.js +0 -115
  115. package/lib/runtime.d.ts +0 -24
  116. package/lib/runtime.js +0 -87
  117. package/lib/score.d.ts +0 -64
  118. package/lib/score.js +0 -191
  119. package/lib/search.d.ts +0 -83
  120. package/lib/search.js +0 -136
  121. package/lib/service.d.ts +0 -63
  122. package/lib/service.js +0 -253
  123. package/lib/skill-render.d.ts +0 -23
  124. package/lib/skill-render.js +0 -69
  125. package/lib/skill.d.ts +0 -15
  126. package/lib/skill.js +0 -80
  127. package/lib/skillquality.d.ts +0 -85
  128. package/lib/skillquality.js +0 -320
  129. package/lib/source.d.ts +0 -30
  130. package/lib/source.js +0 -43
  131. package/lib/state.d.ts +0 -26
  132. package/lib/state.js +0 -151
  133. package/lib/store.d.ts +0 -61
  134. package/lib/store.js +0 -164
  135. package/lib/token-usage.d.ts +0 -68
  136. package/lib/token-usage.js +0 -211
  137. package/lib/tool.d.ts +0 -34
  138. package/lib/tool.js +0 -320
  139. package/lib/turn-snapshot.d.ts +0 -78
  140. package/lib/turn-snapshot.js +0 -252
  141. package/lib/types.d.ts +0 -218
  142. package/lib/types.js +0 -133
  143. package/lib/usage.d.ts +0 -36
  144. package/lib/usage.js +0 -98
  145. package/lib/validate.d.ts +0 -28
  146. package/lib/validate.js +0 -181
  147. package/lib/wrapup-candidates.d.ts +0 -127
  148. package/lib/wrapup-candidates.js +0 -161
  149. package/lib/wrapup-command.d.ts +0 -10
  150. package/lib/wrapup-command.js +0 -243
  151. package/lib/wrapup-proposals.d.ts +0 -101
  152. package/lib/wrapup-proposals.js +0 -281
  153. package/lib/wrapup.d.ts +0 -56
  154. package/lib/wrapup.js +0 -105
package/lib/recall.d.ts DELETED
@@ -1,85 +0,0 @@
1
- /**
2
- * Targeted memory recall (P1): the precise-reading counterpart of the cheap
3
- * directory index.
4
- *
5
- * The injected directory view (`inject.ts`) shows one line per entry and the
6
- * full `evolve_list` dumps whole stores; neither answers "give me everything
7
- * about X". Recall fills that gap: filter by query/kind/scope/memory-type,
8
- * rank with the same CJK BM25 machinery as injection, and return full
9
- * content plus source, version, and staleness signals. Read-only — it never
10
- * mutates a store.
11
- */
12
- import type { EvolutionEngine } from "./service.js";
13
- import type { HarnessScope, RefinementKind } from "./types.js";
14
- /** Memory recall types (the `memoryType` taxonomy, not entry kinds). */
15
- export declare const RECALL_MEMORY_TYPES: readonly ["user", "feedback", "project", "reference"];
16
- export type RecallMemoryType = (typeof RECALL_MEMORY_TYPES)[number];
17
- /** Default and maximum hits returned per recall call. */
18
- export declare const DEFAULT_RECALL_LIMIT = 10;
19
- export declare const MAX_RECALL_LIMIT = 50;
20
- export interface RecallFilters {
21
- /** Free-text relevance query; empty means "most recently updated first". */
22
- query?: string;
23
- /** Entry kinds to search; default is memory only. */
24
- kinds?: RefinementKind[];
25
- /** Stores to search; default is local + project + global. */
26
- scopes?: HarnessScope[];
27
- /** Memory-type filter (applies to memory entries only). */
28
- memoryTypes?: RecallMemoryType[];
29
- /** Maximum hits; clamped to 1..50, defaults to 10. */
30
- limit?: number;
31
- /** Include archived entries; default false. */
32
- includeArchived?: boolean;
33
- }
34
- /** One recalled entry with full content and provenance. */
35
- export interface RecallHit {
36
- scope: HarnessScope;
37
- kind: RefinementKind;
38
- id: string;
39
- title: string;
40
- content: string;
41
- path: string;
42
- version: number;
43
- createdAt: string;
44
- updatedAt: string;
45
- archived: boolean;
46
- /** Memory-type hook for memory entries; undefined for other kinds. */
47
- memoryType?: string;
48
- /** Conflict-hint stamp left by the promotion guard, when present. */
49
- staleHint?: string;
50
- /** Session the entry was distilled from, when recorded. */
51
- sourceSession?: string;
52
- /** Source user-message seqs, when recorded. */
53
- sourceSeqs?: number[];
54
- }
55
- export interface RecallResult {
56
- hits: RecallHit[];
57
- /** Skipped scopes with reasons (read-path honesty: never silently drop a store). */
58
- notes: string[];
59
- /** Candidates seen before ranking/truncation. */
60
- totalCandidates: number;
61
- }
62
- export interface RecallContext {
63
- /** Live session id for the local store; absent → local is skipped with a note. */
64
- sessionId?: string | undefined;
65
- /** Resolved project key; absent → project is skipped with a note. */
66
- projectKey?: string | undefined;
67
- }
68
- /**
69
- * Search the harness stores with mechanical filters and BM25 ranking.
70
- *
71
- * @param engine The evolution engine (read-only use).
72
- * @param context Store identities for the session-scoped stores.
73
- * @param filters Query/kind/scope/type/limit/archive filters.
74
- * @returns Ranked hits plus a note for every scope that could not be read.
75
- * @throws On an unknown kind, scope, or memory type — fail loud instead of
76
- * silently narrowing the search.
77
- */
78
- export declare function recallMemories(engine: EvolutionEngine, context: RecallContext, filters?: RecallFilters): RecallResult;
79
- /**
80
- * Render recall hits for a model or human reader: full content, version,
81
- * source, and staleness on every hit; skipped scopes are always shown so
82
- * "no results" can never hide an unread store.
83
- */
84
- export declare function formatRecallResult(result: RecallResult, query?: string): string;
85
- //# sourceMappingURL=recall.d.ts.map
package/lib/recall.js DELETED
@@ -1,142 +0,0 @@
1
- import { buildRelevanceIndex, relevanceScore } from "./search.js";
2
- import { CONFLICT_HINT_KEY } from "./types.js";
3
- import { isArchived, isMemoryType, ARCHIVED_AT_KEY, MEMORY_TYPE_KEY, SOURCE_SEQS_KEY, SOURCE_SESSION_KEY } from "./types.js";
4
- /** Memory recall types (the `memoryType` taxonomy, not entry kinds). */
5
- export const RECALL_MEMORY_TYPES = ["user", "feedback", "project", "reference"];
6
- /** Entry kinds recall can filter on; memory is the default. */
7
- const RECALL_KINDS = ["prompt", "memory", "skill", "subagent"];
8
- /** Default and maximum hits returned per recall call. */
9
- export const DEFAULT_RECALL_LIMIT = 10;
10
- export const MAX_RECALL_LIMIT = 50;
11
- /**
12
- * Search the harness stores with mechanical filters and BM25 ranking.
13
- *
14
- * @param engine The evolution engine (read-only use).
15
- * @param context Store identities for the session-scoped stores.
16
- * @param filters Query/kind/scope/type/limit/archive filters.
17
- * @returns Ranked hits plus a note for every scope that could not be read.
18
- * @throws On an unknown kind, scope, or memory type — fail loud instead of
19
- * silently narrowing the search.
20
- */
21
- export function recallMemories(engine, context, filters = {}) {
22
- const kinds = filters.kinds ?? ["memory"];
23
- for (const kind of kinds) {
24
- if (!RECALL_KINDS.includes(kind)) {
25
- throw new Error(`evolve_recall: unknown kind "${kind}" (expected one of ${RECALL_KINDS.join(", ")})`);
26
- }
27
- }
28
- const scopes = filters.scopes ?? ["local", "project", "global"];
29
- for (const scope of scopes) {
30
- if (scope !== "local" && scope !== "project" && scope !== "global") {
31
- throw new Error(`evolve_recall: unknown scope "${scope}" (expected local, project, or global)`);
32
- }
33
- }
34
- const memoryTypes = filters.memoryTypes ?? [];
35
- for (const memoryType of memoryTypes) {
36
- if (!RECALL_MEMORY_TYPES.includes(memoryType)) {
37
- throw new Error(`evolve_recall: unknown memoryType "${memoryType}" (expected one of ${RECALL_MEMORY_TYPES.join(", ")})`);
38
- }
39
- }
40
- const limit = typeof filters.limit === "number" && Number.isFinite(filters.limit) && filters.limit > 0
41
- ? Math.min(Math.floor(filters.limit), MAX_RECALL_LIMIT)
42
- : DEFAULT_RECALL_LIMIT;
43
- const query = filters.query?.trim() ?? "";
44
- const candidates = [];
45
- const notes = [];
46
- for (const scope of scopes) {
47
- const storeId = scope === "local" ? context.sessionId : scope === "project" ? context.projectKey : undefined;
48
- if (scope !== "global" && storeId === undefined) {
49
- notes.push(`${scope} store skipped: ${scope === "local" ? "no live session id" : "no project key for this session"}`);
50
- continue;
51
- }
52
- let state;
53
- try {
54
- state = engine.load(scope, storeId);
55
- }
56
- catch (cause) {
57
- notes.push(`${scope} store unreadable: ${cause instanceof Error ? cause.message : String(cause)}`);
58
- continue;
59
- }
60
- for (const kind of kinds) {
61
- for (const entry of Object.values(state.entries[kind])) {
62
- if (!filters.includeArchived && isArchived(entry))
63
- continue;
64
- if (kind === "memory" && memoryTypes.length > 0) {
65
- const type = entry.metadata[MEMORY_TYPE_KEY];
66
- if (typeof type !== "string" || !memoryTypes.includes(type))
67
- continue;
68
- }
69
- candidates.push(entry);
70
- }
71
- }
72
- }
73
- const ranked = query.length > 0 ? rankByRelevance(candidates, query) : [...candidates].sort((a, b) => (a.updated_at < b.updated_at ? 1 : a.updated_at > b.updated_at ? -1 : 0));
74
- return { hits: ranked.slice(0, limit).map(toRecallHit), notes, totalCandidates: candidates.length };
75
- }
76
- function rankByRelevance(candidates, query) {
77
- const index = buildRelevanceIndex(candidates);
78
- const normalized = query.trim().toLowerCase();
79
- return candidates
80
- .map((entry) => {
81
- let score = relevanceScore(index, entry, query);
82
- // Exact scope:id addressing wins over fuzzy relevance (the
83
- // memory-agent manifest search precedent).
84
- if (`${entry.scope}:${entry.id}`.toLowerCase() === normalized)
85
- score += 1000;
86
- return { entry, score };
87
- })
88
- .filter((hit) => hit.score > 0)
89
- .sort((a, b) => b.score - a.score || (a.entry.updated_at < b.entry.updated_at ? 1 : -1))
90
- .map((hit) => hit.entry);
91
- }
92
- function toRecallHit(entry) {
93
- const memoryType = entry.kind === "memory" && isMemoryType(entry.metadata[MEMORY_TYPE_KEY])
94
- ? String(entry.metadata[MEMORY_TYPE_KEY])
95
- : undefined;
96
- const staleHint = typeof entry.metadata[CONFLICT_HINT_KEY] === "string" && entry.metadata[CONFLICT_HINT_KEY].length > 0
97
- ? String(entry.metadata[CONFLICT_HINT_KEY])
98
- : undefined;
99
- const sourceSession = typeof entry.metadata[SOURCE_SESSION_KEY] === "string" ? String(entry.metadata[SOURCE_SESSION_KEY]) : undefined;
100
- const rawSeqs = entry.metadata[SOURCE_SEQS_KEY];
101
- const sourceSeqs = Array.isArray(rawSeqs) && rawSeqs.every((seq) => typeof seq === "number") ? rawSeqs : undefined;
102
- return {
103
- scope: entry.scope,
104
- kind: entry.kind,
105
- id: entry.id,
106
- title: entry.title,
107
- content: entry.content,
108
- path: entry.path,
109
- version: entry.version,
110
- createdAt: entry.created_at,
111
- updatedAt: entry.updated_at,
112
- archived: isArchived(entry),
113
- ...(memoryType !== undefined ? { memoryType } : {}),
114
- ...(staleHint !== undefined ? { staleHint } : {}),
115
- ...(sourceSession !== undefined ? { sourceSession } : {}),
116
- ...(sourceSeqs !== undefined ? { sourceSeqs } : {}),
117
- };
118
- }
119
- /**
120
- * Render recall hits for a model or human reader: full content, version,
121
- * source, and staleness on every hit; skipped scopes are always shown so
122
- * "no results" can never hide an unread store.
123
- */
124
- export function formatRecallResult(result, query) {
125
- const lines = [`recall: ${result.hits.length} hit(s)${query?.trim() ? ` for "${query.trim()}"` : ""} (${result.totalCandidates} candidate(s))`];
126
- for (const hit of result.hits) {
127
- const type = hit.memoryType !== undefined ? ` · type=${hit.memoryType}` : "";
128
- const archived = hit.archived ? " · archived" : "";
129
- const stale = hit.staleHint !== undefined ? ` · conflict-hint=${hit.staleHint}` : "";
130
- const source = hit.sourceSession !== undefined ? ` · src=${hit.sourceSession}${hit.sourceSeqs ? `:${hit.sourceSeqs.join(",")}` : ""}` : "";
131
- lines.push(`- [${hit.scope}:${hit.kind}:${hit.id}] ${hit.title} (v${hit.version}${type}${archived}${stale}${source})`);
132
- lines.push(` ${hit.content}`);
133
- }
134
- for (const note of result.notes) {
135
- lines.push(`note: ${note}`);
136
- }
137
- if (result.hits.length === 0) {
138
- lines.push(`(${ARCHIVED_AT_KEY} entries are hidden unless includeArchived is set)`);
139
- }
140
- return lines.join("\n");
141
- }
142
- //# sourceMappingURL=recall.js.map
@@ -1,85 +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
- /** Natural languages evolution records are authored in. */
19
- export type RecordLanguage = "zh" | "en";
20
- /** Plugin-facing preference: an explicit language or deferral to detection. */
21
- export type RecordLanguagePreference = "auto" | RecordLanguage;
22
- /**
23
- * Upstream durable-settings address reused verbatim
24
- * (`@deepseek-ai/dsh-client-locale`: `LOCALE_SETTINGS_NAMESPACE`,
25
- * `LOCALE_PREFERENCE_FIELD`). New keys are never invented here.
26
- */
27
- export declare const DSH_LOCALE_NAMESPACE = "locale";
28
- export declare const DSH_LOCALE_PREFERENCE_FIELD = "preference";
29
- /**
30
- * Detect Chinese from user text by Han-character density.
31
- *
32
- * @param text Arbitrary user-supplied text.
33
- * @returns `"zh"` on sufficient Han signal, otherwise `undefined` (no
34
- * signal — never a default; the resolver owns the fallback).
35
- */
36
- export declare function detectLanguageFromText(text: string): RecordLanguage | undefined;
37
- /**
38
- * Read the durable DSH client language preference through the host settings
39
- * service. Fail-open by contract: a missing service, a throwing read, an
40
- * async-shaped reply, or an unknown value all yield `undefined`.
41
- *
42
- * The service is resolved through `ctx.get("settings")` (the global registry),
43
- * which sees services provided by sibling plugin entries. A direct
44
- * `ctx.settings` walks only the caller's fiber ancestor chain and throws
45
- * "cannot get property \"settings\" without inject" — the same failure mode
46
- * documented in `goal.ts` — and a throw here would abort the whole snapshot
47
- * gate, so the property access itself is guarded. Plain-object contexts
48
- * (tests, non-Cordis hosts) fall back to the direct property.
49
- *
50
- * @param ctx Cordis context that may carry the host settings service.
51
- * @returns The stored preference (`zh`/`en`, subtag-tolerant) or `undefined`.
52
- */
53
- export declare function durableLocalePreference(ctx: unknown): string | undefined;
54
- /**
55
- * Normalize an explicit preference or durable value to a record language.
56
- *
57
- * @param value Candidate language id (config or durable preference).
58
- * @returns `"zh"`/`"en"` on a recognized id, otherwise `undefined`.
59
- */
60
- export declare function normalizeRecordLanguage(value: string | undefined): RecordLanguage | undefined;
61
- export interface ResolveRecordLanguageInput {
62
- /** Explicit plugin config; absent/`auto` defers to the chain below. */
63
- configured?: RecordLanguagePreference | undefined;
64
- /** Host context for the durable-preference read; absent skips that tier. */
65
- ctx?: unknown;
66
- /** Recent direct user text for the detection tier; absent skips it. */
67
- trajectoryText?: string;
68
- }
69
- /**
70
- * Resolve the authoring language for one evolution write.
71
- *
72
- * @param input Configured preference, host context, and trajectory sample.
73
- * @returns The winning language; always defined (`en` is the final fallback).
74
- */
75
- export declare function resolveRecordLanguage(input: ResolveRecordLanguageInput): RecordLanguage;
76
- /**
77
- * The one-line prompt addendum appended to every record-authoring system
78
- * prompt. Machine contracts (JSON keys, ids, paths, code) stay untouched —
79
- * only natural-language values follow the resolved language.
80
- *
81
- * @param lang Resolved record language.
82
- * @returns The instruction line for `lang`.
83
- */
84
- export declare function recordLanguageInstruction(lang: RecordLanguage): string;
85
- //# sourceMappingURL=record-language.d.ts.map
@@ -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
- /** Terminal state of one scheduled snapshot. */
11
- export type ReviewSchedulerStatus = "success" | "no-op" | "error" | "aborted";
12
- /** A scheduler execution receives the exact snapshot and its owner signal. */
13
- export interface ReviewSchedulerExecution<TSnapshot> {
14
- readonly snapshot: TSnapshot;
15
- readonly signal: AbortSignal;
16
- }
17
- /** Public scheduler surface used by the auto-review driver and tests. */
18
- export interface ReviewScheduler<TSnapshot> {
19
- /** Wait until the current run and all coalesced pending work settle. */
20
- drain(): Promise<void>;
21
- /** Last successfully processed or skipped snapshot boundary. */
22
- getCursor(): string | undefined;
23
- /** Whether a run or a pending acquisition exists. */
24
- hasPendingWork(): boolean;
25
- /** Submit a snapshot (or an async acquisition) without blocking the caller. */
26
- schedule(snapshot: TSnapshot | Promise<TSnapshot>): void;
27
- /** Abort the owner signal, drop pending work, and make later schedules no-ops. */
28
- shutdown(): void;
29
- }
30
- /**
31
- * Create a scheduler with ZCode-compatible serial/coalescing semantics.
32
- *
33
- * @param execute - one serial extraction/review operation
34
- * @param cursorOf - extracts the durable boundary from a snapshot
35
- */
36
- export declare function createReviewScheduler<TSnapshot>(execute: (input: ReviewSchedulerExecution<TSnapshot>) => Promise<ReviewSchedulerStatus>, cursorOf: (snapshot: TSnapshot) => string | undefined): ReviewScheduler<TSnapshot>;
37
- export { compareReviewCursors } from "./turn-snapshot.js";
38
- //# sourceMappingURL=review-scheduler.d.ts.map