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
package/lib/index.d.ts CHANGED
@@ -1,109 +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
37
  /**
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
- /** Legacy/local-fate cadence fallback; successful-turn review is snapshot-driven. */
23
- reviewIntervalTurns: z<number, number, "defined">;
24
- /** Trajectory slice handed to the gate, in characters. */
25
- maxReviewInputChars: z<number, number, "defined">;
26
- /** Output budget for the cheap gate call. */
27
- reviewBudgetTokens: z<number, number, "defined">;
28
- /**
29
- * Planner prefix-cache routing for the gate and planner inputs: `auto`
30
- * prepends a session-derived message prefix when the session shows
31
- * cache-read evidence (dropping the redundant flat trajectory text),
32
- * `session` always prefixes, `off` keeps the legacy flat-text input.
33
- */
34
- plannerPrefixCache: z<"session" | "off" | "auto", "session" | "off" | "auto", "defined">;
35
- /** Session-prefix budget for Route A planning inputs, in characters. */
36
- plannerPrefixMaxChars: z<number, number, "defined">;
37
- /** After an approved gate run with applied edits, queue a visible follow-up notice. */
38
- notifyOnAutoReview: z<boolean, boolean, "defined">;
39
- /** Cross-session (global) edits require an explicit human approval. */
40
- requireGlobalApproval: z<boolean, boolean, "defined">;
41
- /**
42
- * Authoring language for evolution records (refinement summaries,
43
- * rationales, entry titles/content, review and wrap-up verdicts).
44
- * `auto` follows the DSH client language (durable `locale.preference`,
45
- * then trajectory detection, then `en`); `zh`/`en` pin it.
46
- */
47
- recordLanguage: z<"zh" | "en" | "auto", "zh" | "en" | "auto", "defined">;
48
- /** Skills root for materialized skill entries; defaults to <dshHome>/skills. */
49
- skillsDir: z<string, string, "plain">;
50
- /** Passphrase for rubric encryption; falls back to DSH_EVOLVE_RUBRIC_KEY, then a local key file. */
51
- rubricKey: z<string, string, "plain">;
52
- /** Write all cordis log messages to <baseDir>/evolve/plugin.log (JSONL). */
53
- logToFile: z<boolean, boolean, "defined">;
54
- /** File log level: 0=error, 1=info, 2=warn, 3=debug. */
55
- logLevel: z<number, number, "defined">;
56
- /** Rotate the file log when it exceeds this many bytes. */
57
- logMaxBytes: z<number, number, "defined">;
58
- /** After a benchmark decision rejects a candidate, roll the refinement back automatically. */
59
- autoRollbackOnReject: z<boolean, boolean, "defined">;
60
- /**
61
- * P1 auto-case capture: failed evolution attempts (benchmark-rejected
62
- * candidates, gate proposals without consent) land as draft cases in the
63
- * auto-regression container benchmark, seeding the regression loop.
64
- */
65
- autoCase: z<boolean, boolean, "defined">;
66
- /**
67
- * Gap C1: optional model override for the review gate (cheaper model).
68
- * Format: "provider/model" or just "model" (same provider as the agent).
69
- * When absent, the review gate uses the agent's own provider/model.
70
- */
71
- reviewModel: z<string, string, "plain">;
72
- /**
73
- * Gate local-fate dimension (#11 P2): the gate audits the session's local
74
- * entries on its own cadence and proposes promote/archive — consulted
75
- * first, never written silently. Only meaningful with autoReview on;
76
- * disabled by default even when the automatic pipeline is explicitly enabled.
77
- */
78
- localFate: z<boolean, boolean, "defined">;
79
- /**
80
- * Minimum turns between local-fate assessments on the turn-interval path
81
- * (compaction is unconditional). Absent → follows reviewIntervalTurns.
82
- */
83
- fateIntervalTurns: z<number, number, "plain">;
84
- /**
85
- * Goal-blocked trigger (D3): after this many CONSECUTIVE gate runs that
86
- * observe the session goal in phase "blocked", run one local-fate
87
- * assessment so the encounter is distilled. 0 disables.
88
- */
89
- goalBlockedWrapupTurns: z<number, number, "defined">;
90
- /**
91
- * Promotion policy (2026-08-22): regex sources whose match in a
92
- * candidate's title/content marks it project-scoped — such entries are
93
- * never promoted to the cross-session global store. Replaces the built-in
94
- * defaults when set.
95
- */
96
- promotionBlockPatterns: z<string[], string[], "plain">;
97
- /** Whole promotions below this content length stay local (chars). */
98
- promotionMinChars: z<number, number, "defined">;
99
- /** Entry-directory lines injected per build before folding into a counter. */
100
- injectionDirectoryLines: z<number, number, "defined">;
101
- /**
102
- * evolve v2 memory index: the section that injects memory CONTENT (not just
103
- * an id/title directory) at session start, frozen per session to keep the
104
- * system prompt byte-stable (prompt cache). `enabled`/`guide`/`order`/
105
- * `maxChars` default to true/true/400/6000; with `guide` off and an empty
106
- * 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.
107
43
  */
108
44
  memoryIndex: z<Schemastery.ObjectS<NoInfer<{
109
45
  enabled: z<boolean, boolean, "plain">;
@@ -116,124 +52,13 @@ export declare const Config: z<Schemastery.ObjectS<NoInfer<{
116
52
  order: z<number, number, "plain">;
117
53
  maxChars: z<number, number, "plain">;
118
54
  }>>, "plain">;
119
- /**
120
- * Storage hygiene (#20): how much append-only past each write keeps.
121
- * `snapshots` = full-state copies per store, `refinements` = tail lines
122
- * per store history, `reviews` = tail lines of the shared audit trail,
123
- * `tokenUsage` = tail lines of the direct-call token ledger.
124
- * Absent fields fall back to the store defaults (20 / 500 / 500 / 500) —
125
- * rollback needs recent snapshots, readers need a recent window.
126
- */
127
- historyRetain: z<Schemastery.ObjectS<NoInfer<{
128
- snapshots: z<number, number, "plain">;
129
- refinements: z<number, number, "plain">;
130
- reviews: z<number, number, "plain">;
131
- tokenUsage: z<number, number, "plain">;
132
- }>>, Schemastery.ObjectT<NoInfer<{
133
- snapshots: z<number, number, "plain">;
134
- refinements: z<number, number, "plain">;
135
- reviews: z<number, number, "plain">;
136
- tokenUsage: z<number, number, "plain">;
137
- }>>, "plain">;
138
55
  }>>, Schemastery.ObjectT<NoInfer<{
139
- /** Root for evolution stores; defaults to the resolved DSH home. */
140
- baseDir: z<string, string, "plain">;
141
- /** System-prompt section order for the evolution guidance. */
142
- sectionOrder: z<number, number, "defined">;
143
- /** Initial Memory Agent default when no `evolve/runtime.json` exists; not a registration gate. */
144
- autoReview: z<boolean, boolean, "defined">;
145
- /** ZCode-style minimum lexical words in one direct user text part. */
146
- memoryMinUserWords: z<number, number, "defined">;
147
- /**
148
- * Session-close bounded drain for in-flight extraction, in milliseconds.
149
- * Absent → 15s; 0 restores the legacy immediate abort on dispose.
150
- */
151
- sessionCloseDrainMs: z<number, number, "defined">;
152
- /** Legacy/local-fate cadence fallback; successful-turn review is snapshot-driven. */
153
- reviewIntervalTurns: z<number, number, "defined">;
154
- /** Trajectory slice handed to the gate, in characters. */
155
- maxReviewInputChars: z<number, number, "defined">;
156
- /** Output budget for the cheap gate call. */
157
- reviewBudgetTokens: z<number, number, "defined">;
158
- /**
159
- * Planner prefix-cache routing for the gate and planner inputs: `auto`
160
- * prepends a session-derived message prefix when the session shows
161
- * cache-read evidence (dropping the redundant flat trajectory text),
162
- * `session` always prefixes, `off` keeps the legacy flat-text input.
163
- */
164
- plannerPrefixCache: z<"session" | "off" | "auto", "session" | "off" | "auto", "defined">;
165
- /** Session-prefix budget for Route A planning inputs, in characters. */
166
- plannerPrefixMaxChars: z<number, number, "defined">;
167
- /** After an approved gate run with applied edits, queue a visible follow-up notice. */
168
- notifyOnAutoReview: z<boolean, boolean, "defined">;
169
- /** Cross-session (global) edits require an explicit human approval. */
170
- requireGlobalApproval: z<boolean, boolean, "defined">;
171
- /**
172
- * Authoring language for evolution records (refinement summaries,
173
- * rationales, entry titles/content, review and wrap-up verdicts).
174
- * `auto` follows the DSH client language (durable `locale.preference`,
175
- * then trajectory detection, then `en`); `zh`/`en` pin it.
176
- */
177
- recordLanguage: z<"zh" | "en" | "auto", "zh" | "en" | "auto", "defined">;
178
- /** Skills root for materialized skill entries; defaults to <dshHome>/skills. */
179
- skillsDir: z<string, string, "plain">;
180
- /** Passphrase for rubric encryption; falls back to DSH_EVOLVE_RUBRIC_KEY, then a local key file. */
181
- rubricKey: z<string, string, "plain">;
182
- /** Write all cordis log messages to <baseDir>/evolve/plugin.log (JSONL). */
183
- logToFile: z<boolean, boolean, "defined">;
184
- /** File log level: 0=error, 1=info, 2=warn, 3=debug. */
185
- logLevel: z<number, number, "defined">;
186
- /** Rotate the file log when it exceeds this many bytes. */
187
- logMaxBytes: z<number, number, "defined">;
188
- /** After a benchmark decision rejects a candidate, roll the refinement back automatically. */
189
- autoRollbackOnReject: z<boolean, boolean, "defined">;
190
- /**
191
- * P1 auto-case capture: failed evolution attempts (benchmark-rejected
192
- * candidates, gate proposals without consent) land as draft cases in the
193
- * auto-regression container benchmark, seeding the regression loop.
194
- */
195
- autoCase: z<boolean, boolean, "defined">;
196
- /**
197
- * Gap C1: optional model override for the review gate (cheaper model).
198
- * Format: "provider/model" or just "model" (same provider as the agent).
199
- * When absent, the review gate uses the agent's own provider/model.
200
- */
201
- reviewModel: z<string, string, "plain">;
202
- /**
203
- * Gate local-fate dimension (#11 P2): the gate audits the session's local
204
- * entries on its own cadence and proposes promote/archive — consulted
205
- * first, never written silently. Only meaningful with autoReview on;
206
- * disabled by default even when the automatic pipeline is explicitly enabled.
207
- */
208
- localFate: z<boolean, boolean, "defined">;
209
- /**
210
- * Minimum turns between local-fate assessments on the turn-interval path
211
- * (compaction is unconditional). Absent → follows reviewIntervalTurns.
212
- */
213
- fateIntervalTurns: z<number, number, "plain">;
214
- /**
215
- * Goal-blocked trigger (D3): after this many CONSECUTIVE gate runs that
216
- * observe the session goal in phase "blocked", run one local-fate
217
- * assessment so the encounter is distilled. 0 disables.
218
- */
219
- goalBlockedWrapupTurns: z<number, number, "defined">;
220
- /**
221
- * Promotion policy (2026-08-22): regex sources whose match in a
222
- * candidate's title/content marks it project-scoped — such entries are
223
- * never promoted to the cross-session global store. Replaces the built-in
224
- * defaults when set.
225
- */
226
- promotionBlockPatterns: z<string[], string[], "plain">;
227
- /** Whole promotions below this content length stay local (chars). */
228
- promotionMinChars: z<number, number, "defined">;
229
- /** Entry-directory lines injected per build before folding into a counter. */
230
- injectionDirectoryLines: z<number, number, "defined">;
231
56
  /**
232
- * evolve v2 memory index: the section that injects memory CONTENT (not just
233
- * an id/title directory) at session start, frozen per session to keep the
234
- * system prompt byte-stable (prompt cache). `enabled`/`guide`/`order`/
235
- * `maxChars` default to true/true/400/6000; with `guide` off and an empty
236
- * 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.
237
62
  */
238
63
  memoryIndex: z<Schemastery.ObjectS<NoInfer<{
239
64
  enabled: z<boolean, boolean, "plain">;
@@ -246,34 +71,12 @@ export declare const Config: z<Schemastery.ObjectS<NoInfer<{
246
71
  order: z<number, number, "plain">;
247
72
  maxChars: z<number, number, "plain">;
248
73
  }>>, "plain">;
249
- /**
250
- * Storage hygiene (#20): how much append-only past each write keeps.
251
- * `snapshots` = full-state copies per store, `refinements` = tail lines
252
- * per store history, `reviews` = tail lines of the shared audit trail,
253
- * `tokenUsage` = tail lines of the direct-call token ledger.
254
- * Absent fields fall back to the store defaults (20 / 500 / 500 / 500) —
255
- * rollback needs recent snapshots, readers need a recent window.
256
- */
257
- historyRetain: z<Schemastery.ObjectS<NoInfer<{
258
- snapshots: z<number, number, "plain">;
259
- refinements: z<number, number, "plain">;
260
- reviews: z<number, number, "plain">;
261
- tokenUsage: z<number, number, "plain">;
262
- }>>, Schemastery.ObjectT<NoInfer<{
263
- snapshots: z<number, number, "plain">;
264
- refinements: z<number, number, "plain">;
265
- reviews: z<number, number, "plain">;
266
- tokenUsage: z<number, number, "plain">;
267
- }>>, "plain">;
268
74
  }>>, "plain">;
269
75
  /**
270
76
  * Structurally typed resolved config (loader passes the validated object).
271
77
  * Derived from the schemastery schema — single source of truth, no manual sync.
272
78
  */
273
79
  export type EvolveConfig = Partial<Schemastery.TypeT<typeof Config>>;
274
- export interface EvolutionService {
275
- readonly engine: EvolutionEngine;
276
- readonly baseDir: string;
277
- }
278
- export declare function apply(ctx: Context, config: EvolveConfig): void;
80
+ export declare function apply(host: HostContext, config: EvolveConfig): void;
81
+ export {};
279
82
  //# sourceMappingURL=index.d.ts.map
package/lib/index.js CHANGED
@@ -1,135 +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 "./auto.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
- /** Legacy/local-fate cadence fallback; successful-turn review is snapshot-driven. */
49
- reviewIntervalTurns: z.natural().default(6),
50
- /** Trajectory slice handed to the gate, in characters. */
51
- maxReviewInputChars: z.natural().default(40000),
52
- /** Output budget for the cheap gate call. */
53
- reviewBudgetTokens: z.natural().default(4096),
54
- /**
55
- * Planner prefix-cache routing for the gate and planner inputs: `auto`
56
- * prepends a session-derived message prefix when the session shows
57
- * cache-read evidence (dropping the redundant flat trajectory text),
58
- * `session` always prefixes, `off` keeps the legacy flat-text input.
59
- */
60
- plannerPrefixCache: z.union([z.const("auto"), z.const("session"), z.const("off")]).default("auto"),
61
- /** Session-prefix budget for Route A planning inputs, in characters. */
62
- plannerPrefixMaxChars: z.natural().default(12000),
63
- /** After an approved gate run with applied edits, queue a visible follow-up notice. */
64
- notifyOnAutoReview: z.boolean().default(true),
65
- /** Cross-session (global) edits require an explicit human approval. */
66
- requireGlobalApproval: z.boolean().default(true),
67
- /**
68
- * Authoring language for evolution records (refinement summaries,
69
- * rationales, entry titles/content, review and wrap-up verdicts).
70
- * `auto` follows the DSH client language (durable `locale.preference`,
71
- * then trajectory detection, then `en`); `zh`/`en` pin it.
72
- */
73
- recordLanguage: z.union([z.const("auto"), z.const("zh"), z.const("en")]).default("auto"),
74
- /** Skills root for materialized skill entries; defaults to <dshHome>/skills. */
75
- skillsDir: z.string(),
76
- /** Passphrase for rubric encryption; falls back to DSH_EVOLVE_RUBRIC_KEY, then a local key file. */
77
- rubricKey: z.string(),
78
- /** Write all cordis log messages to <baseDir>/evolve/plugin.log (JSONL). */
79
- logToFile: z.boolean().default(true),
80
- /** File log level: 0=error, 1=info, 2=warn, 3=debug. */
81
- logLevel: z.natural().default(1),
82
- /** Rotate the file log when it exceeds this many bytes. */
83
- logMaxBytes: z.natural().default(5 * 1024 * 1024),
84
- /** After a benchmark decision rejects a candidate, roll the refinement back automatically. */
85
- autoRollbackOnReject: z.boolean().default(true),
86
- /**
87
- * P1 auto-case capture: failed evolution attempts (benchmark-rejected
88
- * candidates, gate proposals without consent) land as draft cases in the
89
- * auto-regression container benchmark, seeding the regression loop.
90
- */
91
- autoCase: z.boolean().default(true),
92
- /**
93
- * Gap C1: optional model override for the review gate (cheaper model).
94
- * Format: "provider/model" or just "model" (same provider as the agent).
95
- * When absent, the review gate uses the agent's own provider/model.
96
- */
97
- reviewModel: z.string(),
98
- /**
99
- * Gate local-fate dimension (#11 P2): the gate audits the session's local
100
- * entries on its own cadence and proposes promote/archive — consulted
101
- * first, never written silently. Only meaningful with autoReview on;
102
- * disabled by default even when the automatic pipeline is explicitly enabled.
103
- */
104
- localFate: z.boolean().default(false),
105
- /**
106
- * Minimum turns between local-fate assessments on the turn-interval path
107
- * (compaction is unconditional). Absent → follows reviewIntervalTurns.
108
- */
109
- fateIntervalTurns: z.natural(),
110
- /**
111
- * Goal-blocked trigger (D3): after this many CONSECUTIVE gate runs that
112
- * observe the session goal in phase "blocked", run one local-fate
113
- * assessment so the encounter is distilled. 0 disables.
114
- */
115
- goalBlockedWrapupTurns: z.natural().min(0).default(3),
116
- /**
117
- * Promotion policy (2026-08-22): regex sources whose match in a
118
- * candidate's title/content marks it project-scoped — such entries are
119
- * never promoted to the cross-session global store. Replaces the built-in
120
- * defaults when set.
121
- */
122
- promotionBlockPatterns: z.array(z.string()),
123
- /** Whole promotions below this content length stay local (chars). */
124
- promotionMinChars: z.natural().default(100),
125
- /** Entry-directory lines injected per build before folding into a counter. */
126
- injectionDirectoryLines: z.natural().default(15),
127
- /**
128
- * evolve v2 memory index: the section that injects memory CONTENT (not just
129
- * an id/title directory) at session start, frozen per session to keep the
130
- * system prompt byte-stable (prompt cache). `enabled`/`guide`/`order`/
131
- * `maxChars` default to true/true/400/6000; with `guide` off and an empty
132
- * 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.
133
27
  */
134
28
  memoryIndex: z.object({
135
29
  enabled: z.boolean(),
@@ -137,137 +31,20 @@ export const Config = z.object({
137
31
  order: z.natural(),
138
32
  maxChars: z.natural(),
139
33
  }),
140
- /**
141
- * Storage hygiene (#20): how much append-only past each write keeps.
142
- * `snapshots` = full-state copies per store, `refinements` = tail lines
143
- * per store history, `reviews` = tail lines of the shared audit trail,
144
- * `tokenUsage` = tail lines of the direct-call token ledger.
145
- * Absent fields fall back to the store defaults (20 / 500 / 500 / 500) —
146
- * rollback needs recent snapshots, readers need a recent window.
147
- */
148
- historyRetain: z.object({
149
- snapshots: z.natural(),
150
- refinements: z.natural(),
151
- reviews: z.natural(),
152
- tokenUsage: z.natural(),
153
- }),
154
34
  });
155
- export function apply(ctx, config) {
156
- const baseDir = resolveDshHome(config.baseDir);
157
- const skillsRoot = config.skillsDir ? expandHomePath(config.skillsDir) : join(baseDir, "skills");
158
- const engine = createEvolutionEngine(baseDir, {
159
- onApplied: (result) => {
160
- try {
161
- const warnings = syncSkillsFromResult(skillsRoot, result);
162
- for (const warning of warnings) {
163
- ctx.logger("continual-evolve").warn(warning);
164
- }
165
- }
166
- catch (cause) {
167
- ctx
168
- .logger("continual-evolve")
169
- .warn(`skill materialization failed for ${result.id}: ${cause instanceof Error ? cause.message : String(cause)}`);
170
- }
171
- },
172
- }, config.historyRetain ? { historyRetain: { ...config.historyRetain } } : {});
173
- ctx.provide(EVOLUTION_SERVICE, { engine, baseDir });
174
- ctx.systemPrompt.section({
175
- name: "tool:continual-evolve",
176
- order: config.sectionOrder ?? 118,
177
- 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.",
178
- });
179
- // Phase 2: make prompt entries real system-prompt content and subagent
180
- // entries real delegation specs. The text is a provider evaluated at every
181
- // assembly with the assembling agent; a store without prompt/subagent
182
- // entries renders to "" and the prompt renderer drops the section.
183
- //
184
- // evolve v2: when the memory index section carries memory content, the
185
- // directory stops listing memories so the same entries are never paid for
186
- // twice (one fact, one home).
187
- const memoryIndexEnabled = config.memoryIndex?.enabled ?? true;
188
- ctx.systemPrompt.section({
189
- name: "tool:continual-evolve:entries",
190
- order: (config.sectionOrder ?? 118) + 1,
191
- text: (context) => entriesSectionText(engine, context.agent, undefined, {
192
- directoryLines: config.injectionDirectoryLines ?? 15,
193
- includeMemoryDirectory: !memoryIndexEnabled,
194
- }),
195
- });
196
- // evolve v2 passive read path: memory content in the prompt at session
197
- // start, frozen per session (see memory-index.ts) so the whole system
198
- // prompt stays byte-stable within a session and prompt-cache reads keep
199
- // hitting. Registered in the empty 1–499 order slot — the two sections
200
- // above sit at 118/119, upstream's named slots start at PLAN_POLICY=500.
201
- if (memoryIndexEnabled) {
202
- const frozenMemories = createFrozenMemorySection();
203
- const memoryIndexOrder = config.memoryIndex?.order ?? DEFAULT_MEMORY_SECTION_ORDER;
204
- const memoryIndexMaxChars = config.memoryIndex?.maxChars ?? DEFAULT_MEMORY_INDEX_MAX_CHARS;
205
- const memoryIndexGuide = config.memoryIndex?.guide ?? true;
206
- ctx.systemPrompt.section({
207
- name: MEMORY_SECTION_NAME,
208
- order: memoryIndexOrder,
209
- text: (context) => frozenMemories.textFor(context.agent, (agent) => memoryIndexSectionText(engine, agent, { maxChars: memoryIndexMaxChars, guide: memoryIndexGuide })),
210
- });
211
- }
212
- const gate = {
213
- requireGlobalApproval: config.requireGlobalApproval ?? true,
214
- ...(config.recordLanguage !== undefined ? { recordLanguage: config.recordLanguage } : {}),
215
- };
216
- const promotionPolicy = resolvePromotionPolicy({
217
- blockPatterns: config.promotionBlockPatterns,
218
- minPromoteChars: config.promotionMinChars,
219
- });
220
- registerEvolveTools(ctx, engine, gate);
221
- const rubricKey = resolveRubricKey(baseDir, config.rubricKey, process.env, (m) => ctx.logger("continual-evolve").warn(m));
222
- registerEvolveCommand(ctx, engine, gate, {
223
- rubricKey,
224
- autoRollbackOnReject: config.autoRollbackOnReject ?? true,
225
- autoCase: config.autoCase ?? true,
226
- promotionPolicy,
227
- autoReview: config.autoReview ?? false,
228
- ...(config.recordLanguage !== undefined ? { recordLanguage: config.recordLanguage } : {}),
229
- });
230
- // Plugin-owned file logging: every cordis log message lands in
231
- // <baseDir>/evolve/plugin.log regardless of how dsh web was launched —
232
- // no extra component to install, no startup-script dependency.
233
- if (config.logToFile !== false) {
234
- registerFileLogger(ctx, baseDir, {
235
- logLevel: config.logLevel ?? 1,
236
- ...(config.logMaxBytes !== undefined ? { logMaxBytes: config.logMaxBytes } : {}),
237
- });
35
+ export function apply(host, config) {
36
+ if (config.memoryIndex?.enabled === false) {
37
+ return;
238
38
  }
239
- // v2 optional: restore hot-mounted skill plugins after a restart.
240
- void restoreMounted(ctx, baseDir).catch((cause) => {
241
- ctx.logger("continual-evolve").warn(`mount restore failed: ${cause instanceof Error ? cause.message : String(cause)}`);
242
- });
243
- // The Memory Agent listener is always registered: an install must work
244
- // without profile edits, so `autoReview` is only the initial default when
245
- // no `evolve/runtime.json` exists yet — `/evolve pause|resume` own the
246
- // switch afterwards. The general review/planner, prompt/skill writes, and
247
- // local-fate phases are not reachable from this listener.
248
- registerAutoReview(ctx, engine, {
249
- intervalTurns: config.reviewIntervalTurns ?? 6,
250
- enabledByDefault: config.autoReview ?? false,
251
- memoryOnly: true,
252
- memoryMinUserWords: config.memoryMinUserWords ?? 3,
253
- sessionCloseDrainMs: config.sessionCloseDrainMs ?? 15000,
254
- maxInputChars: config.maxReviewInputChars ?? 40000,
255
- budgetTokens: config.reviewBudgetTokens ?? 4096,
256
- notifyOnAutoReview: config.notifyOnAutoReview ?? true,
257
- localFate: config.localFate ?? false,
258
- fateIntervalTurns: config.fateIntervalTurns ?? config.reviewIntervalTurns ?? 6,
259
- goalBlockedWrapupTurns: config.goalBlockedWrapupTurns ?? 3,
260
- promotionPolicy,
261
- autoCase: config.autoCase ?? true,
262
- rubricKey,
263
- ...(config.historyRetain?.reviews !== undefined ? { reviewsRetain: config.historyRetain.reviews } : {}),
264
- ...(config.reviewModel ? { reviewModel: config.reviewModel } : {}),
265
- requireGlobalApproval: config.requireGlobalApproval ?? true,
266
- ...(config.plannerPrefixCache ? { prefixCacheMode: config.plannerPrefixCache } : {}),
267
- ...(config.plannerPrefixMaxChars !== undefined ? { prefixMaxChars: config.plannerPrefixMaxChars } : {}),
268
- ...(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
+ })),
269
47
  });
270
- ctx.logger("continual-evolve").info("continual-evolve automatic listener registered (Memory Agent only; generic review/planner/fate disconnected)");
271
- 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)");
272
49
  }
273
50
  //# sourceMappingURL=index.js.map