@lmzhen/dsh-evolution-state-domain 0.3.63 → 0.3.65

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.
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { DomainError, defineDomain, domainTable } from "@deepseek-ai/dsh-storage-domain";
3
- import { CURATOR_STATE_KEY, CURATOR_STATE_TABLE, PENDING_RESOLVED_CAP, PENDING_TABLE, PROVIDER_DOMAIN, REVIEW_STATE_TABLE, canClaimPending, canResolvePending, releasedStatus } from "@lmzhen/dsh-evolution-state-storage";
3
+ import { CURATOR_STATE_KEY, CURATOR_STATE_TABLE, PENDING_RESOLVED_CAP, PENDING_TABLE, PROVIDER_DOMAIN, REVIEW_STATE_TABLE, assertCloneable, canClaimPending, canResolvePending, cloneRecord, recordIssue, releasedStatus } from "@lmzhen/dsh-evolution-state-storage";
4
4
  //#region lib/types/index.js
5
5
  /**
6
6
  * storage-domain provider for evolution state.
@@ -23,7 +23,7 @@ const reviewStateSchema = z.object({
23
23
  turnsSinceMemory: z.number().int().nonnegative(),
24
24
  turnsSinceSkill: z.number().int().nonnegative(),
25
25
  lastTurn: z.number().int().nonnegative()
26
- });
26
+ }).loose();
27
27
  /**
28
28
  * Curator-state record schema of the storage-domain table.
29
29
  * @internal Referenced only by this package's own tests and EVOLUTION_DOMAIN
@@ -36,7 +36,7 @@ const curatorStateSchema = z.object({
36
36
  runCount: z.number().int().nonnegative(),
37
37
  lastSummary: z.string(),
38
38
  paused: z.boolean()
39
- });
39
+ }).loose();
40
40
  /**
41
41
  * Pending record schema of the storage-domain table.
42
42
  * @internal Referenced only by this package's own tests and EVOLUTION_DOMAIN
@@ -63,7 +63,7 @@ const pendingSchema = z.object({
63
63
  claimedAt: z.string().optional(),
64
64
  origin: z.string().optional(),
65
65
  sessionId: z.string().optional()
66
- });
66
+ }).loose();
67
67
  /**
68
68
  * The evolution storage-domain spec: three schema-validated KV tables.
69
69
  * @internal Referenced only by this package's own tests and `open()` — not
@@ -116,40 +116,64 @@ function apply(ctx) {
116
116
  const provider = {
117
117
  name: PROVIDER_DOMAIN,
118
118
  async loadReviewState(sessionId) {
119
- return (await ensure()).table(REVIEW_STATE_TABLE).get(sessionId) ?? null;
119
+ const record = (await ensure()).table(REVIEW_STATE_TABLE).get(sessionId);
120
+ return record === void 0 ? null : structuredClone(record);
120
121
  },
121
122
  async saveReviewState(sessionId, record) {
122
- await (await ensure()).table(REVIEW_STATE_TABLE).put(sessionId, record);
123
+ const issue = recordIssue(REVIEW_STATE_TABLE, record) ?? assertCloneable(record);
124
+ if (issue !== null) throw new Error(`evolution-state-domain: refusing to persist an invalid review-state record: ${issue}`);
125
+ const parsed = reviewStateSchema.safeParse(record);
126
+ if (!parsed.success) throw new Error(`evolution-state-domain: refusing to persist an invalid review-state record: ${parsed.error.issues[0]?.message ?? "schema mismatch"}`);
127
+ await (await ensure()).table(REVIEW_STATE_TABLE).put(sessionId, cloneRecord(parsed.data));
123
128
  },
124
129
  async loadCuratorState() {
125
- return (await ensure()).table(CURATOR_STATE_TABLE).get(CURATOR_STATE_KEY) ?? null;
130
+ const record = (await ensure()).table(CURATOR_STATE_TABLE).get(CURATOR_STATE_KEY);
131
+ return record === void 0 ? null : structuredClone(record);
126
132
  },
127
133
  async saveCuratorState(record) {
128
- await (await ensure()).table(CURATOR_STATE_TABLE).put(CURATOR_STATE_KEY, record);
134
+ const issue = recordIssue(CURATOR_STATE_TABLE, record) ?? assertCloneable(record);
135
+ if (issue !== null) throw new Error(`evolution-state-domain: refusing to persist an invalid curator-state record: ${issue}`);
136
+ const parsed = curatorStateSchema.safeParse(record);
137
+ if (!parsed.success) throw new Error(`evolution-state-domain: refusing to persist an invalid curator-state record: ${parsed.error.issues[0]?.message ?? "schema mismatch"}`);
138
+ await (await ensure()).table(CURATOR_STATE_TABLE).put(CURATOR_STATE_KEY, cloneRecord(parsed.data));
129
139
  },
130
140
  async transactCuratorState(task) {
131
141
  const table = (await ensure()).table(CURATOR_STATE_TABLE);
142
+ const guarded = (current) => {
143
+ const next = task(current);
144
+ if (next === null) return null;
145
+ const issue = recordIssue(CURATOR_STATE_TABLE, next) ?? assertCloneable(next);
146
+ if (issue !== null) throw new Error(`evolution-state-domain: refusing to persist an invalid curator-state record: ${issue}`);
147
+ return cloneRecord(next);
148
+ };
132
149
  try {
133
- await table.update(CURATOR_STATE_KEY, (current) => task(current) ?? current);
150
+ await table.update(CURATOR_STATE_KEY, (current) => guarded(current) ?? current);
134
151
  return;
135
152
  } catch (error) {
136
153
  if (!(error instanceof DomainError && error.code === "missing-key")) throw error;
137
154
  }
138
155
  try {
139
- await table.update(CURATOR_STATE_KEY, (current) => task(current) ?? current);
156
+ await table.update(CURATOR_STATE_KEY, (current) => guarded(current) ?? current);
140
157
  return;
141
158
  } catch (error) {
142
159
  if (!(error instanceof DomainError && error.code === "missing-key")) throw error;
143
160
  }
144
- const next = task(null);
161
+ const next = guarded(null);
145
162
  if (next !== null) await table.put(CURATOR_STATE_KEY, next);
146
163
  else await table.delete(CURATOR_STATE_KEY);
147
164
  },
148
165
  async listPending(status = "pending") {
149
- return [...(await ensure()).table(PENDING_TABLE).entries()].map(([, value]) => value).filter((record) => record.status === status);
166
+ return [...(await ensure()).table(PENDING_TABLE).entries()].filter(([, value]) => value.status === status).map(([, value]) => structuredClone(value));
150
167
  },
151
168
  async savePending(record) {
152
- await (await ensure()).table(PENDING_TABLE).put(record.id, record);
169
+ const issue = recordIssue(PENDING_TABLE, record) ?? assertCloneable(record);
170
+ if (issue !== null) throw new Error(`evolution-state-domain: refusing to persist an invalid pending record: ${issue}`);
171
+ const parsed = pendingSchema.safeParse({
172
+ ...record,
173
+ args: record.args
174
+ });
175
+ if (!parsed.success) throw new Error(`evolution-state-domain: refusing to persist an invalid pending record: ${parsed.error.issues[0]?.message ?? "schema mismatch"}`);
176
+ await (await ensure()).table(PENDING_TABLE).put(record.id, cloneRecord(parsed.data));
153
177
  },
154
178
  async claimPending(id, claimId) {
155
179
  const table = (await ensure()).table(PENDING_TABLE);
@@ -166,7 +190,7 @@ function apply(ctx) {
166
190
  };
167
191
  return slot.record;
168
192
  });
169
- return slot.record === null ? null : { ...slot.record };
193
+ return slot.record === null ? null : structuredClone(slot.record);
170
194
  } catch (error) {
171
195
  if (error instanceof DomainError && error.code === "missing-key") return null;
172
196
  throw error;
@@ -216,17 +240,21 @@ function apply(ctx) {
216
240
  };
217
241
  resolvedEntries.sort((a, b) => resolvedAtMs(a.record) - resolvedAtMs(b.record));
218
242
  const evicted = resolvedEntries.slice(0, Math.max(0, resolvedEntries.length - PENDING_RESOLVED_CAP));
219
- for (const entry of evicted) await table.delete(entry.key).catch((error) => {
220
- ctx.logger.warn(`evolution-state-domain: pending-cap eviction for "${entry.key}" failed (will retry on the next resolve): ${error instanceof Error ? error.message : String(error)}`);
221
- });
243
+ for (const entry of evicted) {
244
+ const current = table.get(entry.key);
245
+ if (!(current !== void 0 && (current.status === "approved" || current.status === "rejected") && current.resolvedAt === entry.record.resolvedAt)) continue;
246
+ await table.delete(entry.key).catch((error) => {
247
+ ctx.logger.warn(`evolution-state-domain: pending-cap eviction for "${entry.key}" failed (will retry on the next resolve): ${error instanceof Error ? error.message : String(error)}`);
248
+ });
249
+ }
222
250
  }
223
251
  const rawRecord = record;
224
252
  if (resolved.record === null) return {
225
- record: rawRecord === null ? null : { ...rawRecord },
253
+ record: rawRecord === null ? null : structuredClone(rawRecord),
226
254
  applied: false
227
255
  };
228
256
  return {
229
- record: { ...resolved.record },
257
+ record: structuredClone(resolved.record),
230
258
  applied: true
231
259
  };
232
260
  } catch (error) {
@@ -22,7 +22,7 @@ export declare const reviewStateSchema: z.ZodObject<{
22
22
  turnsSinceMemory: z.ZodNumber;
23
23
  turnsSinceSkill: z.ZodNumber;
24
24
  lastTurn: z.ZodNumber;
25
- }, z.core.$strip>;
25
+ }, z.core.$loose>;
26
26
  /**
27
27
  * Curator-state record schema of the storage-domain table.
28
28
  * @internal Referenced only by this package's own tests and EVOLUTION_DOMAIN
@@ -34,7 +34,7 @@ export declare const curatorStateSchema: z.ZodObject<{
34
34
  runCount: z.ZodNumber;
35
35
  lastSummary: z.ZodString;
36
36
  paused: z.ZodBoolean;
37
- }, z.core.$strip>;
37
+ }, z.core.$loose>;
38
38
  /**
39
39
  * Pending record schema of the storage-domain table.
40
40
  * @internal Referenced only by this package's own tests and EVOLUTION_DOMAIN
@@ -52,7 +52,7 @@ export declare const pendingSchema: z.ZodObject<{
52
52
  claimedAt: z.ZodOptional<z.ZodString>;
53
53
  origin: z.ZodOptional<z.ZodString>;
54
54
  sessionId: z.ZodOptional<z.ZodString>;
55
- }, z.core.$strip>;
55
+ }, z.core.$loose>;
56
56
  /**
57
57
  * The evolution storage-domain spec: three schema-validated KV tables.
58
58
  * @internal Referenced only by this package's own tests and `open()` — not
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lmzhen/dsh-evolution-state-domain",
3
3
  "description": "storage-domain provider for evolution state (community build)",
4
- "version": "0.3.63",
4
+ "version": "0.3.65",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -36,13 +36,13 @@
36
36
  "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
37
37
  "@deepseek-ai/cordis": "^4.0.1",
38
38
  "@deepseek-ai/dsh-storage-domain": "^0.1.1-rc.2",
39
- "@lmzhen/dsh-evolution-state-storage": "^0.3.63"
39
+ "@lmzhen/dsh-evolution-state-storage": "^0.3.65"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
43
43
  "@deepseek-ai/dsh-storage-domain": "^0.1.1-rc.2",
44
44
  "@deepseek-ai/dsh-storage": "^0.1.1-rc.2",
45
45
  "@deepseek-ai/dsh-storage-json": "^0.1.1-rc.2",
46
- "@lmzhen/dsh-evolution-state-storage": "^0.3.63"
46
+ "@lmzhen/dsh-evolution-state-storage": "^0.3.65"
47
47
  }
48
48
  }