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/index.d.ts CHANGED
@@ -1,101 +1,45 @@
1
+ /**
2
+ * dsh-continual-evolve — plugin entry.
3
+ *
4
+ * After the 2026-10-04 ZCode-alignment teardown the plugin is one thing: a
5
+ * session-start system-prompt section that injects the workspace memory
6
+ * index (`<cwd>/.evolve/memory/MEMORY.md`), hands out the store path, and
7
+ * teaches the when-to-save guide. The model reads and writes the markdown
8
+ * files with its native tools; there are no plugin tools, no commands, no
9
+ * background extraction, and no governance. See
10
+ * .agents/notes/implemented/architecture/2026-10-04-zcode-alignment-teardown.md.
11
+ *
12
+ * The host API surface is declared locally (the minimal shape this plugin
13
+ * touches) instead of importing the DSH type packages — the section call is
14
+ * the same one every prior release used, verified in production.
15
+ */
1
16
  import z from "@deepseek-ai/schemastery";
2
- import type { Context } from "@deepseek-ai/cordis";
3
- import { type EvolutionEngine } from "./service.js";
4
17
  export declare const name = "continual-evolve";
5
- /** Service key under which the evolution engine is published. */
6
- export declare const EVOLUTION_SERVICE = "evolution";
7
18
  export declare const inject: string[];
19
+ /** The minimal host surface this plugin touches. */
20
+ interface SectionContext {
21
+ agent?: unknown;
22
+ }
23
+ interface HostContext {
24
+ systemPrompt: {
25
+ section(section: {
26
+ name: string;
27
+ order: number;
28
+ text: string | ((context: SectionContext) => string);
29
+ }): void;
30
+ };
31
+ logger(name: string): {
32
+ info(message: string): void;
33
+ warn(message: string): void;
34
+ };
35
+ }
8
36
  export declare const Config: z<Schemastery.ObjectS<NoInfer<{
9
- /** Root for evolution stores; defaults to the resolved DSH home. */
10
- baseDir: z<string, string, "plain">;
11
- /** System-prompt section order for the evolution guidance. */
12
- sectionOrder: z<number, number, "defined">;
13
- /** Initial Memory Agent default when no `evolve/runtime.json` exists; not a registration gate. */
14
- autoReview: z<boolean, boolean, "defined">;
15
- /** ZCode-style minimum lexical words in one direct user text part. */
16
- memoryMinUserWords: z<number, number, "defined">;
17
- /**
18
- * Session-close bounded drain for in-flight extraction, in milliseconds.
19
- * Absent → 15s; 0 restores the legacy immediate abort on dispose.
20
- */
21
- sessionCloseDrainMs: z<number, number, "defined">;
22
- /** Trajectory slice handed to the extractor, in characters. */
23
- maxReviewInputChars: z<number, number, "defined">;
24
- /** Output budget for the cheap gate call. */
25
- reviewBudgetTokens: z<number, number, "defined">;
26
- /**
27
- * Planner prefix-cache routing for the gate and planner inputs: `auto`
28
- * prepends a session-derived message prefix when the session shows
29
- * cache-read evidence (dropping the redundant flat trajectory text),
30
- * `session` always prefixes, `off` keeps the legacy flat-text input.
31
- */
32
- plannerPrefixCache: z<"session" | "auto" | "off", "session" | "auto" | "off", "defined">;
33
- /** Session-prefix budget for Route A planning inputs, in characters. */
34
- plannerPrefixMaxChars: z<number, number, "defined">;
35
- /** After an approved gate run with applied edits, queue a visible follow-up notice. */
36
- notifyOnAutoReview: z<boolean, boolean, "defined">;
37
- /** Cross-session (global) edits require an explicit human approval. */
38
- requireGlobalApproval: z<boolean, boolean, "defined">;
39
- /**
40
- * Authoring language for evolution records (refinement summaries,
41
- * rationales, entry titles/content, review and wrap-up verdicts).
42
- * `auto` follows the DSH client language (durable `locale.preference`,
43
- * then trajectory detection, then `en`); `zh`/`en` pin it.
44
- */
45
- recordLanguage: z<"auto" | "zh" | "en", "auto" | "zh" | "en", "defined">;
46
- /** Skills root for materialized skill entries; defaults to <dshHome>/skills. */
47
- skillsDir: z<string, string, "plain">;
48
- /** Passphrase for rubric encryption; falls back to DSH_EVOLVE_RUBRIC_KEY, then a local key file. */
49
- rubricKey: z<string, string, "plain">;
50
- /** Write all cordis log messages to <baseDir>/evolve/plugin.log (JSONL). */
51
- logToFile: z<boolean, boolean, "defined">;
52
- /** File log level: 0=error, 1=info, 2=warn, 3=debug. */
53
- logLevel: z<number, number, "defined">;
54
- /** Rotate the file log when it exceeds this many bytes. */
55
- logMaxBytes: z<number, number, "defined">;
56
- /** After a benchmark decision rejects a candidate, roll the refinement back automatically. */
57
- autoRollbackOnReject: z<boolean, boolean, "defined">;
58
- /**
59
- * P1 auto-case capture: failed evolution attempts (benchmark-rejected
60
- * candidates, gate proposals without consent) land as draft cases in the
61
- * auto-regression container benchmark, seeding the regression loop.
62
- */
63
- autoCase: z<boolean, boolean, "defined">;
64
37
  /**
65
- * Optional model override for the memory extractor (cheaper model).
66
- * Format: "provider/model" or just "model" (same provider as the agent).
67
- * When absent, the extractor uses the agent's own provider/model.
68
- */
69
- reviewModel: z<string, string, "plain">;
70
- /**
71
- * Goal-blocked moment: after this many CONSECUTIVE idle probes that
72
- * observe the session goal in phase "blocked", run one memory extraction
73
- * so the stuck encounter is distilled. 0 disables.
74
- */
75
- goalBlockedWrapupTurns: z<number, number, "defined">;
76
- /**
77
- * Promotion policy (2026-08-22): regex sources whose match in a
78
- * candidate's title/content marks it project-scoped — such entries are
79
- * never promoted to the cross-session global store. Replaces the built-in
80
- * defaults when set.
81
- */
82
- /**
83
- * Promotion policy (2026-08-22): regex sources whose match in a
84
- * candidate's title/content marks it project-scoped — such entries are
85
- * never promoted to the cross-session global store. Replaces the built-in
86
- * defaults when set.
87
- */
88
- promotionBlockPatterns: z<string[], string[], "plain">;
89
- /** Whole promotions below this content length stay local (chars). */
90
- promotionMinChars: z<number, number, "defined">;
91
- /** Entry-directory lines injected per build before folding into a counter. */
92
- injectionDirectoryLines: z<number, number, "defined">;
93
- /**
94
- * evolve v2 memory index: the section that injects memory CONTENT (not just
95
- * an id/title directory) at session start, frozen per session to keep the
96
- * system prompt byte-stable (prompt cache). `enabled`/`guide`/`order`/
97
- * `maxChars` default to true/true/400/6000; with `guide` off and an empty
98
- * store the section renders to "" and costs no tokens.
38
+ * The memory section: injects the workspace memory index at session
39
+ * start, frozen per session to keep the system prompt byte-stable
40
+ * (prompt cache). `enabled`/`guide`/`order`/`maxChars` default to
41
+ * true/true/400/6000; with `guide` off and an empty store the section
42
+ * renders to "" and costs no tokens.
99
43
  */
100
44
  memoryIndex: z<Schemastery.ObjectS<NoInfer<{
101
45
  enabled: z<boolean, boolean, "plain">;
@@ -108,116 +52,13 @@ export declare const Config: z<Schemastery.ObjectS<NoInfer<{
108
52
  order: z<number, number, "plain">;
109
53
  maxChars: z<number, number, "plain">;
110
54
  }>>, "plain">;
111
- /**
112
- * Storage hygiene (#20): how much append-only past each write keeps.
113
- * `snapshots` = full-state copies per store, `refinements` = tail lines
114
- * per store history, `reviews` = tail lines of the shared audit trail,
115
- * `tokenUsage` = tail lines of the direct-call token ledger.
116
- * Absent fields fall back to the store defaults (20 / 500 / 500 / 500) —
117
- * rollback needs recent snapshots, readers need a recent window.
118
- */
119
- historyRetain: z<Schemastery.ObjectS<NoInfer<{
120
- snapshots: z<number, number, "plain">;
121
- refinements: z<number, number, "plain">;
122
- reviews: z<number, number, "plain">;
123
- tokenUsage: z<number, number, "plain">;
124
- }>>, Schemastery.ObjectT<NoInfer<{
125
- snapshots: z<number, number, "plain">;
126
- refinements: z<number, number, "plain">;
127
- reviews: z<number, number, "plain">;
128
- tokenUsage: z<number, number, "plain">;
129
- }>>, "plain">;
130
55
  }>>, Schemastery.ObjectT<NoInfer<{
131
- /** Root for evolution stores; defaults to the resolved DSH home. */
132
- baseDir: z<string, string, "plain">;
133
- /** System-prompt section order for the evolution guidance. */
134
- sectionOrder: z<number, number, "defined">;
135
- /** Initial Memory Agent default when no `evolve/runtime.json` exists; not a registration gate. */
136
- autoReview: z<boolean, boolean, "defined">;
137
- /** ZCode-style minimum lexical words in one direct user text part. */
138
- memoryMinUserWords: z<number, number, "defined">;
139
- /**
140
- * Session-close bounded drain for in-flight extraction, in milliseconds.
141
- * Absent → 15s; 0 restores the legacy immediate abort on dispose.
142
- */
143
- sessionCloseDrainMs: z<number, number, "defined">;
144
- /** Trajectory slice handed to the extractor, in characters. */
145
- maxReviewInputChars: z<number, number, "defined">;
146
- /** Output budget for the cheap gate call. */
147
- reviewBudgetTokens: z<number, number, "defined">;
148
- /**
149
- * Planner prefix-cache routing for the gate and planner inputs: `auto`
150
- * prepends a session-derived message prefix when the session shows
151
- * cache-read evidence (dropping the redundant flat trajectory text),
152
- * `session` always prefixes, `off` keeps the legacy flat-text input.
153
- */
154
- plannerPrefixCache: z<"session" | "auto" | "off", "session" | "auto" | "off", "defined">;
155
- /** Session-prefix budget for Route A planning inputs, in characters. */
156
- plannerPrefixMaxChars: z<number, number, "defined">;
157
- /** After an approved gate run with applied edits, queue a visible follow-up notice. */
158
- notifyOnAutoReview: z<boolean, boolean, "defined">;
159
- /** Cross-session (global) edits require an explicit human approval. */
160
- requireGlobalApproval: z<boolean, boolean, "defined">;
161
- /**
162
- * Authoring language for evolution records (refinement summaries,
163
- * rationales, entry titles/content, review and wrap-up verdicts).
164
- * `auto` follows the DSH client language (durable `locale.preference`,
165
- * then trajectory detection, then `en`); `zh`/`en` pin it.
166
- */
167
- recordLanguage: z<"auto" | "zh" | "en", "auto" | "zh" | "en", "defined">;
168
- /** Skills root for materialized skill entries; defaults to <dshHome>/skills. */
169
- skillsDir: z<string, string, "plain">;
170
- /** Passphrase for rubric encryption; falls back to DSH_EVOLVE_RUBRIC_KEY, then a local key file. */
171
- rubricKey: z<string, string, "plain">;
172
- /** Write all cordis log messages to <baseDir>/evolve/plugin.log (JSONL). */
173
- logToFile: z<boolean, boolean, "defined">;
174
- /** File log level: 0=error, 1=info, 2=warn, 3=debug. */
175
- logLevel: z<number, number, "defined">;
176
- /** Rotate the file log when it exceeds this many bytes. */
177
- logMaxBytes: z<number, number, "defined">;
178
- /** After a benchmark decision rejects a candidate, roll the refinement back automatically. */
179
- autoRollbackOnReject: z<boolean, boolean, "defined">;
180
- /**
181
- * P1 auto-case capture: failed evolution attempts (benchmark-rejected
182
- * candidates, gate proposals without consent) land as draft cases in the
183
- * auto-regression container benchmark, seeding the regression loop.
184
- */
185
- autoCase: z<boolean, boolean, "defined">;
186
- /**
187
- * Optional model override for the memory extractor (cheaper model).
188
- * Format: "provider/model" or just "model" (same provider as the agent).
189
- * When absent, the extractor uses the agent's own provider/model.
190
- */
191
- reviewModel: z<string, string, "plain">;
192
56
  /**
193
- * Goal-blocked moment: after this many CONSECUTIVE idle probes that
194
- * observe the session goal in phase "blocked", run one memory extraction
195
- * so the stuck encounter is distilled. 0 disables.
196
- */
197
- goalBlockedWrapupTurns: z<number, number, "defined">;
198
- /**
199
- * Promotion policy (2026-08-22): regex sources whose match in a
200
- * candidate's title/content marks it project-scoped — such entries are
201
- * never promoted to the cross-session global store. Replaces the built-in
202
- * defaults when set.
203
- */
204
- /**
205
- * Promotion policy (2026-08-22): regex sources whose match in a
206
- * candidate's title/content marks it project-scoped — such entries are
207
- * never promoted to the cross-session global store. Replaces the built-in
208
- * defaults when set.
209
- */
210
- promotionBlockPatterns: z<string[], string[], "plain">;
211
- /** Whole promotions below this content length stay local (chars). */
212
- promotionMinChars: z<number, number, "defined">;
213
- /** Entry-directory lines injected per build before folding into a counter. */
214
- injectionDirectoryLines: z<number, number, "defined">;
215
- /**
216
- * evolve v2 memory index: the section that injects memory CONTENT (not just
217
- * an id/title directory) at session start, frozen per session to keep the
218
- * system prompt byte-stable (prompt cache). `enabled`/`guide`/`order`/
219
- * `maxChars` default to true/true/400/6000; with `guide` off and an empty
220
- * store the section renders to "" and costs no tokens.
57
+ * The memory section: injects the workspace memory index at session
58
+ * start, frozen per session to keep the system prompt byte-stable
59
+ * (prompt cache). `enabled`/`guide`/`order`/`maxChars` default to
60
+ * true/true/400/6000; with `guide` off and an empty store the section
61
+ * renders to "" and costs no tokens.
221
62
  */
222
63
  memoryIndex: z<Schemastery.ObjectS<NoInfer<{
223
64
  enabled: z<boolean, boolean, "plain">;
@@ -230,34 +71,12 @@ export declare const Config: z<Schemastery.ObjectS<NoInfer<{
230
71
  order: z<number, number, "plain">;
231
72
  maxChars: z<number, number, "plain">;
232
73
  }>>, "plain">;
233
- /**
234
- * Storage hygiene (#20): how much append-only past each write keeps.
235
- * `snapshots` = full-state copies per store, `refinements` = tail lines
236
- * per store history, `reviews` = tail lines of the shared audit trail,
237
- * `tokenUsage` = tail lines of the direct-call token ledger.
238
- * Absent fields fall back to the store defaults (20 / 500 / 500 / 500) —
239
- * rollback needs recent snapshots, readers need a recent window.
240
- */
241
- historyRetain: z<Schemastery.ObjectS<NoInfer<{
242
- snapshots: z<number, number, "plain">;
243
- refinements: z<number, number, "plain">;
244
- reviews: z<number, number, "plain">;
245
- tokenUsage: z<number, number, "plain">;
246
- }>>, Schemastery.ObjectT<NoInfer<{
247
- snapshots: z<number, number, "plain">;
248
- refinements: z<number, number, "plain">;
249
- reviews: z<number, number, "plain">;
250
- tokenUsage: z<number, number, "plain">;
251
- }>>, "plain">;
252
74
  }>>, "plain">;
253
75
  /**
254
76
  * Structurally typed resolved config (loader passes the validated object).
255
77
  * Derived from the schemastery schema — single source of truth, no manual sync.
256
78
  */
257
79
  export type EvolveConfig = Partial<Schemastery.TypeT<typeof Config>>;
258
- export interface EvolutionService {
259
- readonly engine: EvolutionEngine;
260
- readonly baseDir: string;
261
- }
262
- export declare function apply(ctx: Context, config: EvolveConfig): void;
80
+ export declare function apply(host: HostContext, config: EvolveConfig): void;
81
+ export {};
263
82
  //# sourceMappingURL=index.d.ts.map
package/lib/index.js CHANGED
@@ -1,127 +1,29 @@
1
1
  /**
2
- * dsh-continual-evolve — plugin entry (Phase 2: auto review gate).
2
+ * dsh-continual-evolve — plugin entry.
3
3
  *
4
- * Mounts the evolution engine, registers the model-facing evolve_* tools,
5
- * the human-facing /evolve command, the system-prompt guidance section, and
6
- * the dedicated Memory Agent listener. The listener is always registered so
7
- * an install works without profile edits; `autoReview` only supplies the
8
- * initial default when `evolve/runtime.json` does not exist yet, and
9
- * `/evolve pause|resume` own it afterwards. Generic review/planner/fate are
10
- * not reachable from this listener.
4
+ * After the 2026-10-04 ZCode-alignment teardown the plugin is one thing: a
5
+ * session-start system-prompt section that injects the workspace memory
6
+ * index (`<cwd>/.evolve/memory/MEMORY.md`), hands out the store path, and
7
+ * teaches the when-to-save guide. The model reads and writes the markdown
8
+ * files with its native tools; there are no plugin tools, no commands, no
9
+ * background extraction, and no governance. See
10
+ * .agents/notes/implemented/architecture/2026-10-04-zcode-alignment-teardown.md.
11
11
  *
12
- * evolve v2 registers a third section (`evolve:memory-index`) that injects
13
- * memory content plus the when_to_save guide, frozen per session — see
14
- * memory-index.ts.
12
+ * The host API surface is declared locally (the minimal shape this plugin
13
+ * touches) instead of importing the DSH type packages — the section call is
14
+ * the same one every prior release used, verified in production.
15
15
  */
16
- import { join } from "node:path";
17
16
  import z from "@deepseek-ai/schemastery";
18
- import { expandHomePath, resolveDshHome } from "@deepseek-ai/dsh-home-paths";
19
- import { createEvolutionEngine } from "./service.js";
20
- import { registerEvolveTools } from "./tool.js";
21
- import { registerEvolveCommand } from "./command.js";
22
- import { registerAutoReview } from "./listener.js";
23
- import { syncSkillsFromResult } from "./skill.js";
24
- import { entriesSectionText } from "./inject.js";
25
- import { createFrozenMemorySection, DEFAULT_MEMORY_INDEX_MAX_CHARS, DEFAULT_MEMORY_SECTION_ORDER, MEMORY_SECTION_NAME, memoryIndexSectionText, } from "./memory-index.js";
26
- import { resolveRubricKey } from "./rubric.js";
27
- import { restoreMounted } from "./mount.js";
28
- import { registerFileLogger } from "./logfile.js";
29
- import { resolvePromotionPolicy } from "./promotion.js";
17
+ import { createFrozenMemorySection, DEFAULT_MAX_CHARS, DEFAULT_MEMORY_SECTION_ORDER, MEMORY_SECTION_NAME, memorySectionText, } from "./memory-section.js";
30
18
  export const name = "continual-evolve";
31
- /** Service key under which the evolution engine is published. */
32
- export const EVOLUTION_SERVICE = "evolution";
33
- export const inject = ["tools", "commands", "systemPrompt", "llm", "sessionQuery", "agents", "userQuestions", "subagents"];
19
+ export const inject = ["systemPrompt"];
34
20
  export const Config = z.object({
35
- /** Root for evolution stores; defaults to the resolved DSH home. */
36
- baseDir: z.string(),
37
- /** System-prompt section order for the evolution guidance. */
38
- sectionOrder: z.natural().default(118),
39
- /** Initial Memory Agent default when no `evolve/runtime.json` exists; not a registration gate. */
40
- autoReview: z.boolean().default(false),
41
- /** ZCode-style minimum lexical words in one direct user text part. */
42
- memoryMinUserWords: z.natural().default(3),
43
21
  /**
44
- * Session-close bounded drain for in-flight extraction, in milliseconds.
45
- * Absent → 15s; 0 restores the legacy immediate abort on dispose.
46
- */
47
- sessionCloseDrainMs: z.natural().default(15000),
48
- /** Trajectory slice handed to the extractor, in characters. */
49
- maxReviewInputChars: z.natural().default(40000),
50
- /** Output budget for the cheap gate call. */
51
- reviewBudgetTokens: z.natural().default(4096),
52
- /**
53
- * Planner prefix-cache routing for the gate and planner inputs: `auto`
54
- * prepends a session-derived message prefix when the session shows
55
- * cache-read evidence (dropping the redundant flat trajectory text),
56
- * `session` always prefixes, `off` keeps the legacy flat-text input.
57
- */
58
- plannerPrefixCache: z.union([z.const("auto"), z.const("session"), z.const("off")]).default("auto"),
59
- /** Session-prefix budget for Route A planning inputs, in characters. */
60
- plannerPrefixMaxChars: z.natural().default(12000),
61
- /** After an approved gate run with applied edits, queue a visible follow-up notice. */
62
- notifyOnAutoReview: z.boolean().default(true),
63
- /** Cross-session (global) edits require an explicit human approval. */
64
- requireGlobalApproval: z.boolean().default(true),
65
- /**
66
- * Authoring language for evolution records (refinement summaries,
67
- * rationales, entry titles/content, review and wrap-up verdicts).
68
- * `auto` follows the DSH client language (durable `locale.preference`,
69
- * then trajectory detection, then `en`); `zh`/`en` pin it.
70
- */
71
- recordLanguage: z.union([z.const("auto"), z.const("zh"), z.const("en")]).default("auto"),
72
- /** Skills root for materialized skill entries; defaults to <dshHome>/skills. */
73
- skillsDir: z.string(),
74
- /** Passphrase for rubric encryption; falls back to DSH_EVOLVE_RUBRIC_KEY, then a local key file. */
75
- rubricKey: z.string(),
76
- /** Write all cordis log messages to <baseDir>/evolve/plugin.log (JSONL). */
77
- logToFile: z.boolean().default(true),
78
- /** File log level: 0=error, 1=info, 2=warn, 3=debug. */
79
- logLevel: z.natural().default(1),
80
- /** Rotate the file log when it exceeds this many bytes. */
81
- logMaxBytes: z.natural().default(5 * 1024 * 1024),
82
- /** After a benchmark decision rejects a candidate, roll the refinement back automatically. */
83
- autoRollbackOnReject: z.boolean().default(true),
84
- /**
85
- * P1 auto-case capture: failed evolution attempts (benchmark-rejected
86
- * candidates, gate proposals without consent) land as draft cases in the
87
- * auto-regression container benchmark, seeding the regression loop.
88
- */
89
- autoCase: z.boolean().default(true),
90
- /**
91
- * Optional model override for the memory extractor (cheaper model).
92
- * Format: "provider/model" or just "model" (same provider as the agent).
93
- * When absent, the extractor uses the agent's own provider/model.
94
- */
95
- reviewModel: z.string(),
96
- /**
97
- * Goal-blocked moment: after this many CONSECUTIVE idle probes that
98
- * observe the session goal in phase "blocked", run one memory extraction
99
- * so the stuck encounter is distilled. 0 disables.
100
- */
101
- goalBlockedWrapupTurns: z.natural().min(0).default(3),
102
- /**
103
- * Promotion policy (2026-08-22): regex sources whose match in a
104
- * candidate's title/content marks it project-scoped — such entries are
105
- * never promoted to the cross-session global store. Replaces the built-in
106
- * defaults when set.
107
- */
108
- /**
109
- * Promotion policy (2026-08-22): regex sources whose match in a
110
- * candidate's title/content marks it project-scoped — such entries are
111
- * never promoted to the cross-session global store. Replaces the built-in
112
- * defaults when set.
113
- */
114
- promotionBlockPatterns: z.array(z.string()),
115
- /** Whole promotions below this content length stay local (chars). */
116
- promotionMinChars: z.natural().default(100),
117
- /** Entry-directory lines injected per build before folding into a counter. */
118
- injectionDirectoryLines: z.natural().default(15),
119
- /**
120
- * evolve v2 memory index: the section that injects memory CONTENT (not just
121
- * an id/title directory) at session start, frozen per session to keep the
122
- * system prompt byte-stable (prompt cache). `enabled`/`guide`/`order`/
123
- * `maxChars` default to true/true/400/6000; with `guide` off and an empty
124
- * store the section renders to "" and costs no tokens.
22
+ * The memory section: injects the workspace memory index at session
23
+ * start, frozen per session to keep the system prompt byte-stable
24
+ * (prompt cache). `enabled`/`guide`/`order`/`maxChars` default to
25
+ * true/true/400/6000; with `guide` off and an empty store the section
26
+ * renders to "" and costs no tokens.
125
27
  */
126
28
  memoryIndex: z.object({
127
29
  enabled: z.boolean(),
@@ -129,131 +31,20 @@ export const Config = z.object({
129
31
  order: z.natural(),
130
32
  maxChars: z.natural(),
131
33
  }),
132
- /**
133
- * Storage hygiene (#20): how much append-only past each write keeps.
134
- * `snapshots` = full-state copies per store, `refinements` = tail lines
135
- * per store history, `reviews` = tail lines of the shared audit trail,
136
- * `tokenUsage` = tail lines of the direct-call token ledger.
137
- * Absent fields fall back to the store defaults (20 / 500 / 500 / 500) —
138
- * rollback needs recent snapshots, readers need a recent window.
139
- */
140
- historyRetain: z.object({
141
- snapshots: z.natural(),
142
- refinements: z.natural(),
143
- reviews: z.natural(),
144
- tokenUsage: z.natural(),
145
- }),
146
34
  });
147
- export function apply(ctx, config) {
148
- const baseDir = resolveDshHome(config.baseDir);
149
- const skillsRoot = config.skillsDir ? expandHomePath(config.skillsDir) : join(baseDir, "skills");
150
- const engine = createEvolutionEngine(baseDir, {
151
- onApplied: (result) => {
152
- try {
153
- const warnings = syncSkillsFromResult(skillsRoot, result);
154
- for (const warning of warnings) {
155
- ctx.logger("continual-evolve").warn(warning);
156
- }
157
- }
158
- catch (cause) {
159
- ctx
160
- .logger("continual-evolve")
161
- .warn(`skill materialization failed for ${result.id}: ${cause instanceof Error ? cause.message : String(cause)}`);
162
- }
163
- },
164
- }, config.historyRetain ? { historyRetain: { ...config.historyRetain } } : {});
165
- ctx.provide(EVOLUTION_SERVICE, { engine, baseDir });
166
- ctx.systemPrompt.section({
167
- name: "tool:continual-evolve",
168
- order: config.sectionOrder ?? 118,
169
- text: "You have a continual harness: versioned, persistent prompt notes, memories, skills, and subagent specs. Memories are ONE FACT per entry, typed user/feedback/project/reference (feedback = pitfall + Why + How to apply). Stores: local (this session's staging), project (this project's cross-session store), global (cross-project). Prompt notes and delegation specs are injected below; use evolve_list for the full state. Create an entry (evolve_add) after a repeated failure, a reusable tactic, a durable fact or preference, a repeated procedure, or a repeated delegation role. Keep edits small and evidence-backed; prefer local scope, use project for repo-specific lessons, global: true only for stable cross-project lessons. Update or delete (evolve_update / evolve_delete) when an entry is wrong or obsolete; roll back faulty refinements with evolve_rollback. Every edit is snapshotted, versioned, and recorded — no edit can be silently lost.",
170
- });
171
- // Phase 2: make prompt entries real system-prompt content and subagent
172
- // entries real delegation specs. The text is a provider evaluated at every
173
- // assembly with the assembling agent; a store without prompt/subagent
174
- // entries renders to "" and the prompt renderer drops the section.
175
- //
176
- // evolve v2: when the memory index section carries memory content, the
177
- // directory stops listing memories so the same entries are never paid for
178
- // twice (one fact, one home).
179
- const memoryIndexEnabled = config.memoryIndex?.enabled ?? true;
180
- ctx.systemPrompt.section({
181
- name: "tool:continual-evolve:entries",
182
- order: (config.sectionOrder ?? 118) + 1,
183
- text: (context) => entriesSectionText(engine, context.agent, undefined, {
184
- directoryLines: config.injectionDirectoryLines ?? 15,
185
- includeMemoryDirectory: !memoryIndexEnabled,
186
- }),
187
- });
188
- // evolve v2 passive read path: memory content in the prompt at session
189
- // start, frozen per session (see memory-index.ts) so the whole system
190
- // prompt stays byte-stable within a session and prompt-cache reads keep
191
- // hitting. Registered in the empty 1–499 order slot — the two sections
192
- // above sit at 118/119, upstream's named slots start at PLAN_POLICY=500.
193
- if (memoryIndexEnabled) {
194
- const frozenMemories = createFrozenMemorySection();
195
- const memoryIndexOrder = config.memoryIndex?.order ?? DEFAULT_MEMORY_SECTION_ORDER;
196
- const memoryIndexMaxChars = config.memoryIndex?.maxChars ?? DEFAULT_MEMORY_INDEX_MAX_CHARS;
197
- const memoryIndexGuide = config.memoryIndex?.guide ?? true;
198
- ctx.systemPrompt.section({
199
- name: MEMORY_SECTION_NAME,
200
- order: memoryIndexOrder,
201
- text: (context) => frozenMemories.textFor(context.agent, (agent) => memoryIndexSectionText(engine, agent, { maxChars: memoryIndexMaxChars, guide: memoryIndexGuide })),
202
- });
203
- }
204
- const gate = {
205
- requireGlobalApproval: config.requireGlobalApproval ?? true,
206
- ...(config.recordLanguage !== undefined ? { recordLanguage: config.recordLanguage } : {}),
207
- };
208
- const promotionPolicy = resolvePromotionPolicy({
209
- blockPatterns: config.promotionBlockPatterns,
210
- minPromoteChars: config.promotionMinChars,
211
- });
212
- registerEvolveTools(ctx, engine, gate);
213
- const rubricKey = resolveRubricKey(baseDir, config.rubricKey, process.env, (m) => ctx.logger("continual-evolve").warn(m));
214
- registerEvolveCommand(ctx, engine, gate, {
215
- rubricKey,
216
- autoRollbackOnReject: config.autoRollbackOnReject ?? true,
217
- autoCase: config.autoCase ?? true,
218
- promotionPolicy,
219
- autoReview: config.autoReview ?? false,
220
- ...(config.recordLanguage !== undefined ? { recordLanguage: config.recordLanguage } : {}),
221
- });
222
- // Plugin-owned file logging: every cordis log message lands in
223
- // <baseDir>/evolve/plugin.log regardless of how dsh web was launched —
224
- // no extra component to install, no startup-script dependency.
225
- if (config.logToFile !== false) {
226
- registerFileLogger(ctx, baseDir, {
227
- logLevel: config.logLevel ?? 1,
228
- ...(config.logMaxBytes !== undefined ? { logMaxBytes: config.logMaxBytes } : {}),
229
- });
35
+ export function apply(host, config) {
36
+ if (config.memoryIndex?.enabled === false) {
37
+ return;
230
38
  }
231
- // v2 optional: restore hot-mounted skill plugins after a restart.
232
- void restoreMounted(ctx, baseDir).catch((cause) => {
233
- ctx.logger("continual-evolve").warn(`mount restore failed: ${cause instanceof Error ? cause.message : String(cause)}`);
234
- });
235
- // The memory extraction listener is always registered: an install must
236
- // work without profile edits, so `autoReview` is only the initial default
237
- // when no `evolve/runtime.json` exists yet — `/evolve pause|resume` own
238
- // the switch afterwards. Extraction is moment-driven: compaction,
239
- // goal-blocked streaks, the session-close drain, and manual
240
- // `/evolve wrapup` — successful turns never cost an LLM call.
241
- registerAutoReview(ctx, engine, {
242
- enabledByDefault: config.autoReview ?? false,
243
- memoryMinUserWords: config.memoryMinUserWords ?? 3,
244
- sessionCloseDrainMs: config.sessionCloseDrainMs ?? 15000,
245
- maxInputChars: config.maxReviewInputChars ?? 40000,
246
- budgetTokens: config.reviewBudgetTokens ?? 4096,
247
- notifyOnAutoReview: config.notifyOnAutoReview ?? true,
248
- goalBlockedWrapupTurns: config.goalBlockedWrapupTurns ?? 3,
249
- ...(config.historyRetain?.reviews !== undefined ? { reviewsRetain: config.historyRetain.reviews } : {}),
250
- ...(config.reviewModel ? { reviewModel: config.reviewModel } : {}),
251
- requireGlobalApproval: config.requireGlobalApproval ?? true,
252
- ...(config.plannerPrefixCache ? { prefixCacheMode: config.plannerPrefixCache } : {}),
253
- ...(config.plannerPrefixMaxChars !== undefined ? { prefixMaxChars: config.plannerPrefixMaxChars } : {}),
254
- ...(config.recordLanguage !== undefined ? { recordLanguage: config.recordLanguage } : {}),
39
+ const frozen = createFrozenMemorySection();
40
+ host.systemPrompt.section({
41
+ name: MEMORY_SECTION_NAME,
42
+ order: config.memoryIndex?.order ?? DEFAULT_MEMORY_SECTION_ORDER,
43
+ text: (context) => frozen.textFor(context.agent, (agent) => memorySectionText(agent, {
44
+ maxChars: config.memoryIndex?.maxChars ?? DEFAULT_MAX_CHARS,
45
+ guide: config.memoryIndex?.guide ?? true,
46
+ })),
255
47
  });
256
- ctx.logger("continual-evolve").info("continual-evolve moment-driven memory extraction listener registered (compaction / goal-blocked / session-close drain; manual wrapup via /evolve wrapup)");
257
- ctx.logger("continual-evolve").info(`continual-evolve mounted (baseDir=${baseDir})`);
48
+ host.logger("continual-evolve").info("continual-evolve memory section registered (workspace .evolve/memory, native file read/write)");
258
49
  }
259
50
  //# sourceMappingURL=index.js.map