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,238 +0,0 @@
1
- import { sessionEventsOf } from "./inject.js";
2
- import { projectKeyOf } from "./project.js";
3
- /** ZCode's minimum user-prose threshold, counted as lexical words. */
4
- export const MEMORY_MIN_USER_WORDS = 3;
5
- const WORD_SEGMENTER = new Intl.Segmenter("und", { granularity: "word" });
6
- function countUserWords(text) {
7
- return [...WORD_SEGMENTER.segment(text)].filter((segment) => segment.isWordLike).length;
8
- }
9
- function containsEligibleUserProse(events, minUserWords) {
10
- return events.some((event) => {
11
- if (!isDirectUserEvent(event))
12
- return false;
13
- const row = event;
14
- return countUserWords(contentText(row.data?.content)) >= minUserWords;
15
- });
16
- }
17
- /**
18
- * Capture the current durable surface and select only rows after `cursor`.
19
- * A seq-bearing session uses `seq:<n>`; older/test surfaces fall back to an
20
- * event-count cursor so the scheduler still has a deterministic boundary.
21
- */
22
- export async function captureTurnSnapshot(ctx, agent, opts) {
23
- const allEvents = await readSurface(ctx, agent);
24
- const cursor = boundaryCursor(allEvents);
25
- const events = eventsAfterCursor(allEvents, opts.cursor);
26
- const minUserWords = opts.minUserWords ?? MEMORY_MIN_USER_WORDS;
27
- const eligibility = evaluateSnapshotEligibility(events, isInternalAgent(agent), minUserWords);
28
- const projectKey = projectKeyOf(agent);
29
- return {
30
- sessionId: agent.id,
31
- ...(projectKey ? { projectKey } : {}),
32
- turn: opts.turn,
33
- reason: opts.reason,
34
- cursor,
35
- events,
36
- trajectory: eligibility.eligible ? serializeSnapshotEvents(events, opts.maxChars) : "",
37
- userText: eligibility.userText,
38
- sourceSeqs: directUserSeqs(events),
39
- maxChars: opts.maxChars,
40
- minUserWords,
41
- ...(opts.cursor === undefined ? {} : { capturedAfterCursor: opts.cursor }),
42
- eligible: eligibility.eligible,
43
- ...(eligibility.reason ? { skipReason: eligibility.reason } : {}),
44
- };
45
- }
46
- /**
47
- * Rebase one captured snapshot onto a phase-specific cursor while preserving
48
- * its outer boundary. The memory phase uses this after a downstream review or
49
- * fate failure: already-processed evidence is removed, but newly captured rows
50
- * remain available without moving the shared scheduler cursor backwards.
51
- */
52
- export function sliceTurnSnapshot(snapshot, cursor) {
53
- const events = sliceSnapshotEvents(snapshot, cursor);
54
- const eligibility = evaluateSnapshotEligibility(events, false, snapshot.minUserWords);
55
- return {
56
- ...snapshot,
57
- events,
58
- trajectory: eligibility.eligible ? serializeSnapshotEvents(events, snapshot.maxChars) : "",
59
- userText: eligibility.userText,
60
- sourceSeqs: directUserSeqs(events),
61
- eligible: eligibility.eligible,
62
- ...(eligibility.reason ? { skipReason: eligibility.reason } : {}),
63
- };
64
- }
65
- /**
66
- * Decide whether the incremental rows deserve a model call. This intentionally
67
- * does not decide whether a fact is valuable; that remains the review model's
68
- * job. It only removes mechanical noise before the scheduler spends tokens.
69
- */
70
- export function evaluateSnapshotEligibility(events, internalAgent = false, minUserWords = MEMORY_MIN_USER_WORDS) {
71
- if (internalAgent)
72
- return { eligible: false, reason: "internal-agent", userText: "" };
73
- if (events.length === 0)
74
- return { eligible: false, reason: "no-new-events", userText: "" };
75
- if (containsDirectMemoryWrite(events))
76
- return { eligible: false, reason: "direct-memory-write", userText: "" };
77
- const userText = directUserText(events);
78
- if (!containsEligibleUserProse(events, minUserWords))
79
- return { eligible: false, reason: "no-user-prose", userText };
80
- return { eligible: true, userText };
81
- }
82
- /** True when an assistant row records an explicit evolve memory mutation. */
83
- export function containsDirectMemoryWrite(events) {
84
- for (const event of events) {
85
- if (!event || typeof event !== "object")
86
- continue;
87
- const row = event;
88
- if (row.type === "tool/call" || row.type === "tool-call") {
89
- if (isMemoryMutationName(readNestedString(row.data, ["name", "tool", "toolName"])))
90
- return true;
91
- }
92
- if (row.type === "assistant/message" && containsMemoryMutationName(row.data))
93
- return true;
94
- }
95
- return false;
96
- }
97
- /** Serialize only user/assistant text, retaining the bounded tail. */
98
- export function serializeSnapshotEvents(events, maxChars) {
99
- const lines = [];
100
- for (const raw of events) {
101
- if (!raw || typeof raw !== "object")
102
- continue;
103
- const event = raw;
104
- if (event.type === "user/message" && !isDirectUserEvent(raw))
105
- continue;
106
- const role = event.type === "user/message" ? "user" : event.type === "assistant/message" ? "assistant" : null;
107
- if (role === null)
108
- continue;
109
- const text = contentText(event.data?.content).trim();
110
- if (text.length > 0)
111
- lines.push(`${role}: ${text}`);
112
- }
113
- const joined = lines.join("\n");
114
- return joined.length <= maxChars ? joined : joined.slice(-maxChars);
115
- }
116
- /** A DSH subagent header is an internal source when its origin says so. */
117
- export function isInternalAgent(agent) {
118
- const header = agent?.session?.header;
119
- return header?.origin === "subagent" || header?.origin === "internal" || header?.isSubagent === true;
120
- }
121
- async function readSurface(ctx, agent) {
122
- const reader = ctx.sessionQuery;
123
- if (reader) {
124
- const snapshot = await reader.readSurface(agent.id);
125
- return Array.isArray(snapshot.events) ? snapshot.events : [];
126
- }
127
- return sessionEventsOf(agent);
128
- }
129
- function boundaryCursor(events) {
130
- const seqs = events.map(eventSeq).filter((seq) => seq !== undefined);
131
- return seqs.length > 0 ? `seq:${Math.max(...seqs)}` : `index:${events.length}`;
132
- }
133
- function sliceSnapshotEvents(snapshot, cursor) {
134
- if (snapshot.cursor.startsWith("index:") && cursor.startsWith("index:") && snapshot.capturedAfterCursor?.startsWith("index:")) {
135
- const start = Number(snapshot.capturedAfterCursor.slice("index:".length));
136
- const phaseBoundary = Number(cursor.slice("index:".length));
137
- if (!Number.isInteger(start) || !Number.isInteger(phaseBoundary))
138
- return snapshot.events;
139
- const relative = phaseBoundary - start;
140
- if (relative <= 0)
141
- return snapshot.events;
142
- return relative >= snapshot.events.length ? [] : snapshot.events.slice(relative);
143
- }
144
- return eventsAfterCursor(snapshot.events, cursor);
145
- }
146
- function eventsAfterCursor(events, cursor) {
147
- if (cursor === undefined)
148
- return events;
149
- if (cursor.startsWith("seq:")) {
150
- const boundary = Number(cursor.slice(4));
151
- if (!Number.isFinite(boundary))
152
- return events;
153
- return events.filter((event) => {
154
- const seq = eventSeq(event);
155
- return seq === undefined || seq > boundary;
156
- });
157
- }
158
- if (cursor.startsWith("index:")) {
159
- const boundary = Number(cursor.slice(6));
160
- return Number.isInteger(boundary) && boundary >= 0 ? events.slice(boundary) : events;
161
- }
162
- return events;
163
- }
164
- function directUserText(events) {
165
- return events
166
- .filter(isDirectUserEvent)
167
- .map((event) => contentText(event.data?.content).trim())
168
- .filter(Boolean)
169
- .join("\n");
170
- }
171
- function directUserSeqs(events) {
172
- return events
173
- .filter(isDirectUserEvent)
174
- .map(eventSeq)
175
- .filter((seq) => seq !== undefined);
176
- }
177
- function isDirectUserEvent(event) {
178
- if (!event || typeof event !== "object")
179
- return false;
180
- const row = event;
181
- if (row.type !== "user/message")
182
- return false;
183
- if (row.data?.visibility === "model-only")
184
- return false;
185
- if (row.data?.source?.synthetic === true)
186
- return false;
187
- if (row.data?.source?.kind !== undefined && row.data.source.kind !== "user")
188
- return false;
189
- return contentText(row.data?.content).trim().length > 0;
190
- }
191
- function contentText(content) {
192
- if (typeof content === "string")
193
- return content;
194
- if (!Array.isArray(content))
195
- return "";
196
- return content
197
- .map((block) => {
198
- if (typeof block === "string")
199
- return block;
200
- if (!block || typeof block !== "object")
201
- return "";
202
- const value = block;
203
- if (value.synthetic === true || value.ignored === true || (value.type !== undefined && value.type !== "text"))
204
- return "";
205
- return typeof value.text === "string" ? value.text : "";
206
- })
207
- .filter(Boolean)
208
- .join(" ");
209
- }
210
- function eventSeq(event) {
211
- if (!event || typeof event !== "object")
212
- return undefined;
213
- const seq = event.seq;
214
- return typeof seq === "number" && Number.isInteger(seq) ? seq : undefined;
215
- }
216
- function containsMemoryMutationName(value) {
217
- if (typeof value === "string")
218
- return isMemoryMutationName(value);
219
- if (Array.isArray(value))
220
- return value.some(containsMemoryMutationName);
221
- if (!value || typeof value !== "object")
222
- return false;
223
- return Object.values(value).some(containsMemoryMutationName);
224
- }
225
- function isMemoryMutationName(value) {
226
- return value === "evolve_add" || value === "evolve_update" || value === "evolve_delete";
227
- }
228
- function readNestedString(value, keys) {
229
- if (!value || typeof value !== "object")
230
- return undefined;
231
- const row = value;
232
- for (const key of keys) {
233
- if (typeof row[key] === "string")
234
- return row[key];
235
- }
236
- return undefined;
237
- }
238
- //# sourceMappingURL=turn-snapshot.js.map
package/lib/types.d.ts DELETED
@@ -1,208 +0,0 @@
1
- /** What a harness entry can be. */
2
- export type RefinementKind = "prompt" | "memory" | "skill" | "subagent";
3
- /**
4
- * Skill-entry form: `executable` skills carry a python reference contract
5
- * and can be hot-mounted as tools; `guidance` skills are SKILL.md documents
6
- * (no python reference) that materialize as discoverable skills for the
7
- * `skill` tool — the form for recurring multi-step workflows. Absent means
8
- * `executable` (backwards compatible with pre-guidance stores).
9
- */
10
- export type SkillKind = "executable" | "guidance";
11
- /** How an entry changes. */
12
- export type RefinementAction = "create" | "update" | "delete" | "archive";
13
- /** Where an entry lives: session staging, one project, or cross-project. */
14
- export type HarnessScope = "local" | "project" | "global";
15
- /**
16
- * Memory-entry shape discipline (one fact per entry, typed like ZCode's
17
- * memory frontmatter): every `memory` create must stamp one of these in
18
- * `metadata[MEMORY_TYPE_KEY]` — the recall hook the directory shows.
19
- */
20
- export declare const MEMORY_TYPE_KEY = "memoryType";
21
- /** Closed memory-type set: user | feedback | project | reference. */
22
- export declare const MEMORY_TYPES: readonly ["user", "feedback", "project", "reference"];
23
- /** One of {@link MEMORY_TYPES}. */
24
- export type MemoryRecallType = (typeof MEMORY_TYPES)[number];
25
- /** True when the value is a closed-set memory type. */
26
- export declare function isMemoryType(value: unknown): value is MemoryRecallType;
27
- /**
28
- * Metadata key recording which session an entry's content was distilled from
29
- * (trajectory citation; see {@link EntrySource}).
30
- */
31
- export declare const SOURCE_SESSION_KEY = "sourceSession";
32
- /**
33
- * Metadata key recording the session-log event seqs (of the direct user
34
- * messages) the entry cites as its source (trajectory citation).
35
- */
36
- export declare const SOURCE_SEQS_KEY = "sourceSeqs";
37
- /**
38
- * Metadata key recording when an entry was archived. Archived entries are
39
- * hidden from injection but never deleted — the data stays in the store and
40
- * the entry can be restored (unarchive) or rolled back like any other edit.
41
- */
42
- export declare const ARCHIVED_AT_KEY = "archivedAt";
43
- /**
44
- * Metadata key stamped on a LOCAL entry that was promoted to the global
45
- * store by a session wrap-up: the id of the global entry it became. Present
46
- * means the entry's lifecycle is finished — it must not be offered for
47
- * promotion again (the global copy is the live one, the local copy is a
48
- * restorable trace).
49
- */
50
- export declare const PROMOTED_TO_KEY = "promotedTo";
51
- /**
52
- * Metadata key recording when a local entry was promoted to the global
53
- * store (companion of {@link PROMOTED_TO_KEY}).
54
- */
55
- export declare const PROMOTED_AT_KEY = "promotedAt";
56
- /**
57
- * Metadata key stamped on a GLOBAL entry created by a session wrap-up
58
- * promotion: `<sessionId>:<localEntryId>` — the反向 provenance link from the
59
- * cross-session copy back to the session it was distilled from.
60
- */
61
- export declare const SOURCED_FROM_KEY = "sourcedFromLocal";
62
- /**
63
- * Metadata key stamped on a GLOBAL entry that was created despite a
64
- * moderate-similarity overlap with an existing entry (write-time conflict
65
- * guard, warn tier): `<kind>:<id>:<score>` — points at the entry it may
66
- * duplicate so wrapup/fate can consolidate later. Creates at/above the block
67
- * threshold never reach this stamp; they are rejected outright.
68
- */
69
- export declare const CONFLICT_HINT_KEY = "conflictHint";
70
- /**
71
- * Negative-valence counter (P1 效价反馈): how many times an assessment marked
72
- * this entry contradicted by newer evidence (user correction, overridden
73
- * fact). Injection ranking demotes entries with a positive counter and the
74
- * wrapup/fate assessors see the count so they prefer archiving the entry.
75
- */
76
- export declare const VALENCE_NEGATIVE_KEY = "valenceNegative";
77
- /**
78
- * Provenance of entries merged INTO this one by the consolidation command
79
- * (P1 反膨胀): array of `<kind>:<id>` — the near-duplicate sources whose
80
- * content was appended before they archived. The trail keeps an unarchive of
81
- * the source explainable and lets audits find the merge provenance.
82
- */
83
- export declare const MERGED_FROM_KEY = "mergedFrom";
84
- /**
85
- * True when the entry is archived (hidden from injection, restorable).
86
- * Absent or empty archivedAt means the entry is active.
87
- */
88
- export declare function isArchived(entry: HarnessEntry): boolean;
89
- /**
90
- * Trajectory citation attached to newly created entries: the session the
91
- * content came from and the seqs of the direct user messages it was
92
- * distilled from. Both fields are optional — when they cannot be determined
93
- * the citation is simply omitted (never an error).
94
- */
95
- export interface EntrySource {
96
- sessionId?: string;
97
- /** Event seqs of the source user messages, in log order. */
98
- seqs?: number[];
99
- }
100
- /** A single persisted harness entry. */
101
- export interface HarnessEntry {
102
- id: string;
103
- kind: RefinementKind;
104
- title: string;
105
- content: string;
106
- path: string;
107
- scope: HarnessScope;
108
- /** Skill entries carry an executable contract; see {@link PythonReference}. */
109
- reference: Record<string, unknown>;
110
- /** Skill entries declare their accepted inputs here. */
111
- arguments: Record<string, unknown>;
112
- /** Skill form: "executable" (default) or "guidance" (SKILL.md document). */
113
- skill_kind?: SkillKind;
114
- metadata: Record<string, unknown>;
115
- source: "evolve";
116
- created_at: string;
117
- updated_at: string;
118
- version: number;
119
- }
120
- /** One entry of the append-only refinement history (the evidence trail). */
121
- export interface HarnessRefinementEvent {
122
- id: string;
123
- trigger: string;
124
- changes: string[];
125
- /** Where the trajectory evidence for this refinement lives (e.g. seq ranges). */
126
- evidence: string;
127
- /** The falsifiable expectation recorded with the edit. */
128
- outcome: string;
129
- created_at: string;
130
- }
131
- /** The whole harness state file. */
132
- export interface HarnessState {
133
- schema: number;
134
- entries: Record<RefinementKind, Record<string, HarnessEntry>>;
135
- refinements: HarnessRefinementEvent[];
136
- }
137
- /** A model-proposed edit, before validation and application. */
138
- export interface RefinementEdit {
139
- action: RefinementAction;
140
- kind: RefinementKind;
141
- id?: string;
142
- title?: string;
143
- content?: string;
144
- path?: string;
145
- reference?: Record<string, unknown>;
146
- arguments?: Record<string, unknown>;
147
- /** Skill form: "guidance" for SKILL.md document skills; absent = executable. */
148
- skill_kind?: SkillKind;
149
- metadata?: Record<string, unknown>;
150
- reason?: string;
151
- /**
152
- * Gap C2: blast-radius annotation — how broadly this edit applies.
153
- * Values: "general" (cross-project tactical), "project" (single project),
154
- * "session" (one-off session-specific). The review gate checks that
155
- * local-scope edits are "session" or "project" and global-scope edits
156
- * are "general" or "project".
157
- */
158
- blastRadius?: "general" | "project" | "session";
159
- }
160
- /** The structured output of a planning pass. */
161
- export interface RefinementProposal {
162
- summary: string;
163
- rationale: string;
164
- edits: RefinementEdit[];
165
- expectedOutcome: string;
166
- }
167
- /** An edit after the apply pass: before/after snapshots and outcome per edit. */
168
- export interface AppliedRefinementEdit extends RefinementEdit {
169
- id: string;
170
- before?: HarnessEntry;
171
- after?: HarnessEntry;
172
- applied: boolean;
173
- error?: string;
174
- }
175
- /** The result of applying one refinement. */
176
- export interface RefinementResult {
177
- id: string;
178
- summary: string;
179
- rationale: string;
180
- expectedOutcome: string;
181
- appliedEdits: AppliedRefinementEdit[];
182
- harnessStatePath: string;
183
- rollbackOf?: string;
184
- scope?: HarnessScope;
185
- }
186
- /** The executable contract a skill entry must carry (python REPL skills). */
187
- export interface PythonReference {
188
- type: "python";
189
- import?: string;
190
- python_import?: string;
191
- callable?: string;
192
- call_pattern?: string;
193
- }
194
- /**
195
- * A stable id derived from a title: ASCII runs become snake_case (unchanged
196
- * legacy behavior). Titles with no ASCII content at all (e.g. pure Chinese)
197
- * used to collapse onto the bare fallback, so distinct memories shared one
198
- * id and every later create failed as "already exists". They now take
199
- * `<fallback>_<sha256-8>` instead: distinct titles get distinct ids while
200
- * identical titles still dedupe onto the same id. The fallback itself is
201
- * assumed id-safe (callers pass entry kinds).
202
- */
203
- export declare function slug(raw: string, fallback: string): string;
204
- /** Fresh empty state with the current schema version. */
205
- export declare function emptyHarnessState(): HarnessState;
206
- /** Deep clone helper (state is plain JSON data). */
207
- export declare function cloneEntry(entry: HarnessEntry | undefined): HarnessEntry | undefined;
208
- //# sourceMappingURL=types.d.ts.map
package/lib/types.js DELETED
@@ -1,127 +0,0 @@
1
- /**
2
- * Type model for the continual-evolution harness state.
3
- *
4
- * Design provenance: the state model follows the continual-harness design
5
- * validated in prime-agent's `/refine` subsystem (MIT): versioned entries
6
- * keyed by kind, an append-only refinement history carrying an evidence
7
- * trail, atomic persistence, and deterministic inverse-op rollback. The
8
- * code here is an original implementation, written for the DeepSeek Harness
9
- * plugin surface.
10
- */
11
- import { createHash } from "node:crypto";
12
- /**
13
- * Memory-entry shape discipline (one fact per entry, typed like ZCode's
14
- * memory frontmatter): every `memory` create must stamp one of these in
15
- * `metadata[MEMORY_TYPE_KEY]` — the recall hook the directory shows.
16
- */
17
- export const MEMORY_TYPE_KEY = "memoryType";
18
- /** Closed memory-type set: user | feedback | project | reference. */
19
- export const MEMORY_TYPES = ["user", "feedback", "project", "reference"];
20
- /** True when the value is a closed-set memory type. */
21
- export function isMemoryType(value) {
22
- return typeof value === "string" && MEMORY_TYPES.includes(value);
23
- }
24
- /**
25
- * Metadata key recording which session an entry's content was distilled from
26
- * (trajectory citation; see {@link EntrySource}).
27
- */
28
- export const SOURCE_SESSION_KEY = "sourceSession";
29
- /**
30
- * Metadata key recording the session-log event seqs (of the direct user
31
- * messages) the entry cites as its source (trajectory citation).
32
- */
33
- export const SOURCE_SEQS_KEY = "sourceSeqs";
34
- /**
35
- * Metadata key recording when an entry was archived. Archived entries are
36
- * hidden from injection but never deleted — the data stays in the store and
37
- * the entry can be restored (unarchive) or rolled back like any other edit.
38
- */
39
- export const ARCHIVED_AT_KEY = "archivedAt";
40
- /**
41
- * Metadata key stamped on a LOCAL entry that was promoted to the global
42
- * store by a session wrap-up: the id of the global entry it became. Present
43
- * means the entry's lifecycle is finished — it must not be offered for
44
- * promotion again (the global copy is the live one, the local copy is a
45
- * restorable trace).
46
- */
47
- export const PROMOTED_TO_KEY = "promotedTo";
48
- /**
49
- * Metadata key recording when a local entry was promoted to the global
50
- * store (companion of {@link PROMOTED_TO_KEY}).
51
- */
52
- export const PROMOTED_AT_KEY = "promotedAt";
53
- /**
54
- * Metadata key stamped on a GLOBAL entry created by a session wrap-up
55
- * promotion: `<sessionId>:<localEntryId>` — the反向 provenance link from the
56
- * cross-session copy back to the session it was distilled from.
57
- */
58
- export const SOURCED_FROM_KEY = "sourcedFromLocal";
59
- /**
60
- * Metadata key stamped on a GLOBAL entry that was created despite a
61
- * moderate-similarity overlap with an existing entry (write-time conflict
62
- * guard, warn tier): `<kind>:<id>:<score>` — points at the entry it may
63
- * duplicate so wrapup/fate can consolidate later. Creates at/above the block
64
- * threshold never reach this stamp; they are rejected outright.
65
- */
66
- export const CONFLICT_HINT_KEY = "conflictHint";
67
- /**
68
- * Negative-valence counter (P1 效价反馈): how many times an assessment marked
69
- * this entry contradicted by newer evidence (user correction, overridden
70
- * fact). Injection ranking demotes entries with a positive counter and the
71
- * wrapup/fate assessors see the count so they prefer archiving the entry.
72
- */
73
- export const VALENCE_NEGATIVE_KEY = "valenceNegative";
74
- /**
75
- * Provenance of entries merged INTO this one by the consolidation command
76
- * (P1 反膨胀): array of `<kind>:<id>` — the near-duplicate sources whose
77
- * content was appended before they archived. The trail keeps an unarchive of
78
- * the source explainable and lets audits find the merge provenance.
79
- */
80
- export const MERGED_FROM_KEY = "mergedFrom";
81
- /**
82
- * True when the entry is archived (hidden from injection, restorable).
83
- * Absent or empty archivedAt means the entry is active.
84
- */
85
- export function isArchived(entry) {
86
- const value = entry.metadata[ARCHIVED_AT_KEY];
87
- return typeof value === "string" && value.length > 0;
88
- }
89
- /**
90
- * A stable id derived from a title: ASCII runs become snake_case (unchanged
91
- * legacy behavior). Titles with no ASCII content at all (e.g. pure Chinese)
92
- * used to collapse onto the bare fallback, so distinct memories shared one
93
- * id and every later create failed as "already exists". They now take
94
- * `<fallback>_<sha256-8>` instead: distinct titles get distinct ids while
95
- * identical titles still dedupe onto the same id. The fallback itself is
96
- * assumed id-safe (callers pass entry kinds).
97
- */
98
- export function slug(raw, fallback) {
99
- const normalized = raw
100
- .trim()
101
- .toLowerCase()
102
- .replace(/[^a-z0-9]+/g, "_")
103
- .replace(/^_+|_+$/g, "")
104
- .slice(0, 80);
105
- if (normalized)
106
- return normalized;
107
- const digest = createHash("sha256").update(raw, "utf8").digest("hex").slice(0, 8);
108
- return `${fallback}_${digest}`;
109
- }
110
- /** Fresh empty state with the current schema version. */
111
- export function emptyHarnessState() {
112
- return {
113
- schema: 1,
114
- entries: {
115
- prompt: {},
116
- memory: {},
117
- skill: {},
118
- subagent: {},
119
- },
120
- refinements: [],
121
- };
122
- }
123
- /** Deep clone helper (state is plain JSON data). */
124
- export function cloneEntry(entry) {
125
- return entry ? JSON.parse(JSON.stringify(entry)) : undefined;
126
- }
127
- //# sourceMappingURL=types.js.map
package/lib/usage.d.ts DELETED
@@ -1,36 +0,0 @@
1
- import type { RefinementKind } from "./types.js";
2
- export interface UsageStore {
3
- /** Injection count per entry key (`kind:id`). */
4
- counts: Record<string, number>;
5
- /** Session dedup marker: the last session id each key was counted in (v2). */
6
- lastSession?: Record<string, string>;
7
- }
8
- /**
9
- * Load the usage store from disk; returns an empty store when absent or
10
- * corrupt. Accepts BOTH on-disk shapes:
11
- * - legacy (≤0.3.x): a flat `{ "kind:id": count }` map,
12
- * - v2: `{ version: 2, counts, lastSession }` with per-session dedup.
13
- */
14
- export declare function loadUsage(baseDir: string): UsageStore;
15
- /** Persist the usage store atomically (always the v2 shape). */
16
- export declare function saveUsage(baseDir: string, store: UsageStore): void;
17
- /** Build the usage key for an entry. */
18
- export declare function usageKey(kind: RefinementKind, id: string): string;
19
- /**
20
- * Increment injection counts for the entries that were actually injected.
21
- * Called after `entriesSectionText` renders the injected block. Keys not
22
- * present in the store are initialized to 1.
23
- *
24
- * Session dedup (2026-08-22): with a sessionId, each key counts AT MOST
25
- * ONCE per session — the old per-build counting produced meaningless
26
- * numbers (one entry hit 2311× in a week) and hid the real "how many
27
- * sessions found this useful" signal that staleness decay needs. Without
28
- * a sessionId the call degrades to legacy always-increment behavior.
29
- */
30
- export declare function recordInjection(baseDir: string, injectedKeys: readonly string[], sessionId?: string): void;
31
- /**
32
- * Get the injection count for a specific entry. Returns 0 when the entry
33
- * has never been injected (absent from the store).
34
- */
35
- export declare function getUsageCount(store: UsageStore, kind: RefinementKind, id: string): number;
36
- //# sourceMappingURL=usage.d.ts.map