dsh-continual-evolve 0.11.0 → 0.12.1

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 (161) hide show
  1. package/README.md +42 -115
  2. package/README.zh.md +33 -93
  3. package/client/client.js +253 -0
  4. package/cordis.patch.yml +2 -2
  5. package/lib/card-routes.d.ts +32 -0
  6. package/lib/card-routes.js +92 -0
  7. package/lib/index.d.ts +65 -217
  8. package/lib/index.js +74 -234
  9. package/lib/known-workspaces.d.ts +22 -0
  10. package/lib/known-workspaces.js +42 -0
  11. package/lib/memory-guide.d.ts +13 -14
  12. package/lib/memory-guide.js +34 -21
  13. package/lib/memory-section.d.ts +77 -0
  14. package/lib/memory-section.js +189 -0
  15. package/lib/memory-snapshot.d.ts +54 -0
  16. package/lib/memory-snapshot.js +125 -0
  17. package/package.json +8 -17
  18. package/lib/apply.d.ts +0 -22
  19. package/lib/apply.js +0 -157
  20. package/lib/approval.d.ts +0 -73
  21. package/lib/approval.js +0 -127
  22. package/lib/audit-log.d.ts +0 -19
  23. package/lib/audit-log.js +0 -52
  24. package/lib/auto.d.ts +0 -236
  25. package/lib/auto.js +0 -773
  26. package/lib/autocase.d.ts +0 -38
  27. package/lib/autocase.js +0 -76
  28. package/lib/benchmark-command.d.ts +0 -9
  29. package/lib/benchmark-command.js +0 -357
  30. package/lib/benchmark.d.ts +0 -151
  31. package/lib/benchmark.js +0 -250
  32. package/lib/command-util.d.ts +0 -70
  33. package/lib/command-util.js +0 -123
  34. package/lib/command.d.ts +0 -13
  35. package/lib/command.js +0 -134
  36. package/lib/consolidate.d.ts +0 -90
  37. package/lib/consolidate.js +0 -180
  38. package/lib/copy.d.ts +0 -37
  39. package/lib/copy.js +0 -58
  40. package/lib/declines.d.ts +0 -103
  41. package/lib/declines.js +0 -179
  42. package/lib/evaluate.d.ts +0 -74
  43. package/lib/evaluate.js +0 -271
  44. package/lib/evolve-event.d.ts +0 -40
  45. package/lib/evolve-event.js +0 -60
  46. package/lib/extraction-phase.d.ts +0 -132
  47. package/lib/extraction-phase.js +0 -236
  48. package/lib/failures.d.ts +0 -42
  49. package/lib/failures.js +0 -171
  50. package/lib/fate.d.ts +0 -130
  51. package/lib/fate.js +0 -350
  52. package/lib/goal-command.d.ts +0 -7
  53. package/lib/goal-command.js +0 -37
  54. package/lib/goal.d.ts +0 -72
  55. package/lib/goal.js +0 -72
  56. package/lib/inject.d.ts +0 -90
  57. package/lib/inject.js +0 -164
  58. package/lib/injection-caps.d.ts +0 -4
  59. package/lib/injection-caps.js +0 -4
  60. package/lib/injection-directory.d.ts +0 -29
  61. package/lib/injection-directory.js +0 -78
  62. package/lib/injection-rank.d.ts +0 -85
  63. package/lib/injection-rank.js +0 -161
  64. package/lib/listener.d.ts +0 -45
  65. package/lib/listener.js +0 -199
  66. package/lib/llm-text.d.ts +0 -104
  67. package/lib/llm-text.js +0 -140
  68. package/lib/logfile.d.ts +0 -71
  69. package/lib/logfile.js +0 -159
  70. package/lib/maintenance-commands.d.ts +0 -23
  71. package/lib/maintenance-commands.js +0 -136
  72. package/lib/memory-agent.d.ts +0 -93
  73. package/lib/memory-agent.js +0 -300
  74. package/lib/memory-apply.d.ts +0 -44
  75. package/lib/memory-apply.js +0 -202
  76. package/lib/memory-benchmark.d.ts +0 -76
  77. package/lib/memory-benchmark.js +0 -170
  78. package/lib/memory-index.d.ts +0 -114
  79. package/lib/memory-index.js +0 -197
  80. package/lib/memory-manifest.d.ts +0 -16
  81. package/lib/memory-manifest.js +0 -70
  82. package/lib/message-source.d.ts +0 -23
  83. package/lib/message-source.js +0 -12
  84. package/lib/mount-command.d.ts +0 -10
  85. package/lib/mount-command.js +0 -48
  86. package/lib/mount.d.ts +0 -42
  87. package/lib/mount.js +0 -212
  88. package/lib/notify.d.ts +0 -48
  89. package/lib/notify.js +0 -57
  90. package/lib/plan-command.d.ts +0 -12
  91. package/lib/plan-command.js +0 -38
  92. package/lib/plan.d.ts +0 -16
  93. package/lib/plan.js +0 -126
  94. package/lib/planner.d.ts +0 -61
  95. package/lib/planner.js +0 -144
  96. package/lib/pool.d.ts +0 -7
  97. package/lib/pool.js +0 -25
  98. package/lib/prefix-cache.d.ts +0 -79
  99. package/lib/prefix-cache.js +0 -168
  100. package/lib/project.d.ts +0 -28
  101. package/lib/project.js +0 -66
  102. package/lib/projection.d.ts +0 -22
  103. package/lib/projection.js +0 -112
  104. package/lib/promotion.d.ts +0 -94
  105. package/lib/promotion.js +0 -171
  106. package/lib/recall.d.ts +0 -85
  107. package/lib/recall.js +0 -142
  108. package/lib/record-language.d.ts +0 -85
  109. package/lib/record-language.js +0 -152
  110. package/lib/render.d.ts +0 -13
  111. package/lib/render.js +0 -80
  112. package/lib/review-scheduler.d.ts +0 -38
  113. package/lib/review-scheduler.js +0 -183
  114. package/lib/review.d.ts +0 -60
  115. package/lib/review.js +0 -145
  116. package/lib/rollback.d.ts +0 -9
  117. package/lib/rollback.js +0 -68
  118. package/lib/rubric.d.ts +0 -29
  119. package/lib/rubric.js +0 -119
  120. package/lib/runtime-commands.d.ts +0 -14
  121. package/lib/runtime-commands.js +0 -115
  122. package/lib/runtime.d.ts +0 -24
  123. package/lib/runtime.js +0 -87
  124. package/lib/score.d.ts +0 -64
  125. package/lib/score.js +0 -191
  126. package/lib/search.d.ts +0 -83
  127. package/lib/search.js +0 -136
  128. package/lib/service.d.ts +0 -63
  129. package/lib/service.js +0 -253
  130. package/lib/skill-render.d.ts +0 -23
  131. package/lib/skill-render.js +0 -69
  132. package/lib/skill.d.ts +0 -15
  133. package/lib/skill.js +0 -80
  134. package/lib/skillquality.d.ts +0 -85
  135. package/lib/skillquality.js +0 -320
  136. package/lib/source.d.ts +0 -30
  137. package/lib/source.js +0 -43
  138. package/lib/state.d.ts +0 -26
  139. package/lib/state.js +0 -151
  140. package/lib/store.d.ts +0 -61
  141. package/lib/store.js +0 -164
  142. package/lib/token-usage.d.ts +0 -68
  143. package/lib/token-usage.js +0 -211
  144. package/lib/tool.d.ts +0 -34
  145. package/lib/tool.js +0 -320
  146. package/lib/turn-snapshot.d.ts +0 -78
  147. package/lib/turn-snapshot.js +0 -252
  148. package/lib/types.d.ts +0 -218
  149. package/lib/types.js +0 -133
  150. package/lib/usage.d.ts +0 -36
  151. package/lib/usage.js +0 -98
  152. package/lib/validate.d.ts +0 -28
  153. package/lib/validate.js +0 -181
  154. package/lib/wrapup-candidates.d.ts +0 -127
  155. package/lib/wrapup-candidates.js +0 -161
  156. package/lib/wrapup-command.d.ts +0 -10
  157. package/lib/wrapup-command.js +0 -243
  158. package/lib/wrapup-proposals.d.ts +0 -101
  159. package/lib/wrapup-proposals.js +0 -281
  160. package/lib/wrapup.d.ts +0 -56
  161. package/lib/wrapup.js +0 -105
package/lib/types.d.ts DELETED
@@ -1,218 +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
- /**
209
- * Storage-hygiene defaults (#20): JSONL tail lines kept per store history
210
- * and per shared audit trail when no explicit `historyRetain` is set.
211
- */
212
- export declare const DEFAULT_REFINEMENTS_RETAIN = 500;
213
- export declare const DEFAULT_REVIEWS_RETAIN = 500;
214
- /** Prefix-cache routing modes for extractor/planner inputs (see prefix-cache.ts). */
215
- export type PlannerPrefixCacheMode = "auto" | "session" | "off";
216
- /** The only two durable outcomes a scope-approval dialog may produce. */
217
- export type ScopeApprovalDecision = "approved" | "declined";
218
- //# sourceMappingURL=types.d.ts.map
package/lib/types.js DELETED
@@ -1,133 +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
- /**
128
- * Storage-hygiene defaults (#20): JSONL tail lines kept per store history
129
- * and per shared audit trail when no explicit `historyRetain` is set.
130
- */
131
- export const DEFAULT_REFINEMENTS_RETAIN = 500;
132
- export const DEFAULT_REVIEWS_RETAIN = 500;
133
- //# 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
package/lib/usage.js DELETED
@@ -1,98 +0,0 @@
1
- /**
2
- * Entry usage tracking (gap B1): records how many times each entry has been
3
- * injected into system prompts. The counts are durable (persisted to disk)
4
- * and exposed in `evolve_list` and the gate's archive-candidate reporting,
5
- * so "zero-usage stale entries" can be surfaced for cleanup.
6
- *
7
- * Storage: `<baseDir>/evolve/usage.json` — a flat JSON object mapping
8
- * `kind:id` to an integer count. Reads are tolerant of missing/corrupt files;
9
- * writes are atomic (tmp + rename).
10
- */
11
- import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
12
- import { join } from "node:path";
13
- const USAGE_FILE = "usage.json";
14
- function usagePath(baseDir) {
15
- return join(baseDir, "evolve", USAGE_FILE);
16
- }
17
- /**
18
- * Load the usage store from disk; returns an empty store when absent or
19
- * corrupt. Accepts BOTH on-disk shapes:
20
- * - legacy (≤0.3.x): a flat `{ "kind:id": count }` map,
21
- * - v2: `{ version: 2, counts, lastSession }` with per-session dedup.
22
- */
23
- export function loadUsage(baseDir) {
24
- const path = usagePath(baseDir);
25
- try {
26
- if (!existsSync(path))
27
- return { counts: {}, lastSession: {} };
28
- const raw = JSON.parse(readFileSync(path, "utf8"));
29
- if (typeof raw === "object" && raw !== null && !Array.isArray(raw)) {
30
- const record = raw;
31
- if (record["version"] === 2 && typeof record["counts"] === "object" && record["counts"] !== null) {
32
- return {
33
- counts: record["counts"],
34
- lastSession: typeof record["lastSession"] === "object" && record["lastSession"] !== null
35
- ? record["lastSession"]
36
- : {},
37
- };
38
- }
39
- // Legacy flat map: every key is a count.
40
- return { counts: raw, lastSession: {} };
41
- }
42
- return { counts: {}, lastSession: {} };
43
- }
44
- catch {
45
- return { counts: {}, lastSession: {} };
46
- }
47
- }
48
- /** Persist the usage store atomically (always the v2 shape). */
49
- export function saveUsage(baseDir, store) {
50
- const dir = join(baseDir, "evolve");
51
- mkdirSync(dir, { recursive: true });
52
- const path = usagePath(baseDir);
53
- const tmp = `${path}.${process.pid}.tmp`;
54
- writeFileSync(tmp, `${JSON.stringify({ version: 2, counts: store.counts, lastSession: store.lastSession ?? {} }, null, 2)}\n`, "utf8");
55
- renameSync(tmp, path);
56
- }
57
- /** Build the usage key for an entry. */
58
- export function usageKey(kind, id) {
59
- return `${kind}:${id}`;
60
- }
61
- /**
62
- * Increment injection counts for the entries that were actually injected.
63
- * Called after `entriesSectionText` renders the injected block. Keys not
64
- * present in the store are initialized to 1.
65
- *
66
- * Session dedup (2026-08-22): with a sessionId, each key counts AT MOST
67
- * ONCE per session — the old per-build counting produced meaningless
68
- * numbers (one entry hit 2311× in a week) and hid the real "how many
69
- * sessions found this useful" signal that staleness decay needs. Without
70
- * a sessionId the call degrades to legacy always-increment behavior.
71
- */
72
- export function recordInjection(baseDir, injectedKeys, sessionId) {
73
- if (injectedKeys.length === 0)
74
- return;
75
- const store = loadUsage(baseDir);
76
- let dirty = false;
77
- for (const key of injectedKeys) {
78
- if (sessionId !== undefined && store.lastSession?.[key] === sessionId) {
79
- continue;
80
- }
81
- store.counts[key] = (store.counts[key] ?? 0) + 1;
82
- if (store.lastSession && sessionId !== undefined) {
83
- store.lastSession[key] = sessionId;
84
- }
85
- dirty = true;
86
- }
87
- if (dirty) {
88
- saveUsage(baseDir, store);
89
- }
90
- }
91
- /**
92
- * Get the injection count for a specific entry. Returns 0 when the entry
93
- * has never been injected (absent from the store).
94
- */
95
- export function getUsageCount(store, kind, id) {
96
- return store.counts[usageKey(kind, id)] ?? 0;
97
- }
98
- //# sourceMappingURL=usage.js.map
package/lib/validate.d.ts DELETED
@@ -1,28 +0,0 @@
1
- /**
2
- * Code-enforced validation of model-proposed edits. Every rule here exists
3
- * because the proposal is untrusted input: enum membership, immutability of
4
- * the base system prompt, required fields per action, and the executable
5
- * contract skill entries must carry.
6
- */
7
- import type { HarnessEntry, HarnessScope, RefinementEdit } from "./types.js";
8
- export declare const BASE_SYSTEM_PROMPT_ID = "base_system_prompt";
9
- /**
10
- * Gap C2: mechanical check that an edit's declared blast radius is coherent
11
- * with the scope it targets. A session-scoped edit claiming "general" would
12
- * silently read like a cross-project tactical rule; a global edit claiming
13
- * "session" would contradict its persistence. Absent blastRadius is NOT
14
- * rejected (pre-C2 data and manual edits stay compatible) — the planner is
15
- * instructed to always declare it, and this rule catches what it declares
16
- * incoherently.
17
- */
18
- export declare function validateBlastRadiusScope(scope: HarnessScope, blastRadius: "general" | "project" | "session"): string | undefined;
19
- /**
20
- * Returns a human-readable failure reason, or undefined when the edit passes.
21
- *
22
- * `before` (the entry the edit targets, absent for creates/unknown ids) lets
23
- * update rules distinguish "carrying the persisted value" from "changing it"
24
- * — e.g. a rollback inverse re-carries the stored skill_kind, which must
25
- * pass, while a genuine executable↔guidance switch must not.
26
- */
27
- export declare function validateEdit(edit: RefinementEdit, computedId: string | undefined, scope?: HarnessScope, before?: HarnessEntry): string | undefined;
28
- //# sourceMappingURL=validate.d.ts.map