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

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/README.md CHANGED
@@ -24,4 +24,5 @@ Independent of request-prefix construction. This package does not alter the asse
24
24
 
25
25
  - Requires the host-plane `storage-domain` facility. The bundle row stays dormant when it is absent.
26
26
  - P2-4 (v15): the live pending table is BOUNDED — resolved (approved/rejected) records are kept to the most recent `PENDING_RESOLVED_CAP` (200, seam constant in `evolution-state-storage`); the oldest by `resolvedAt` are deleted on resolve. The audit ARCHIVE sidecar that the json provider maintains beyond the cap is json-specific (the domain seam has no sidecar facility) — resolved records past the cap are gone, not archived.
27
+ - V25-11 (v25): the review-state table is likewise BOUNDED — `REVIEW_STATE_SESSION_CAP` (500, seam constant) rows keyed by session; on every save the least-recently-active sessions (provider-stamped `updatedAt`) are pruned (delete failures warn and retry on the next save). The stamp is stripped on read, so the consumer-facing record shape is unchanged.
27
28
 
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, assertCloneable, canClaimPending, canResolvePending, cloneRecord, recordIssue, releasedStatus } from "@lmzhen/dsh-evolution-state-storage";
3
+ import { CURATOR_STATE_KEY, CURATOR_STATE_TABLE, PENDING_RESOLVED_CAP, PENDING_TABLE, PROVIDER_DOMAIN, REVIEW_STATE_SESSION_CAP, 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.
@@ -117,14 +117,32 @@ function apply(ctx) {
117
117
  name: PROVIDER_DOMAIN,
118
118
  async loadReviewState(sessionId) {
119
119
  const record = (await ensure()).table(REVIEW_STATE_TABLE).get(sessionId);
120
- return record === void 0 ? null : structuredClone(record);
120
+ if (record === void 0) return null;
121
+ const { updatedAt: _stamp, ...rest } = record;
122
+ return structuredClone(rest);
121
123
  },
122
124
  async saveReviewState(sessionId, record) {
123
125
  const issue = recordIssue(REVIEW_STATE_TABLE, record) ?? assertCloneable(record);
124
126
  if (issue !== null) throw new Error(`evolution-state-domain: refusing to persist an invalid review-state record: ${issue}`);
125
127
  const parsed = reviewStateSchema.safeParse(record);
126
128
  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));
129
+ const table = (await ensure()).table(REVIEW_STATE_TABLE);
130
+ const stamped = {
131
+ ...cloneRecord(parsed.data),
132
+ updatedAt: Date.now()
133
+ };
134
+ await table.put(sessionId, stamped);
135
+ const entries = [...table.entries()].map(([key, row]) => ({
136
+ key,
137
+ updatedAt: row.updatedAt ?? 0
138
+ })).filter((entry) => entry.key !== sessionId).sort((a, b) => a.updatedAt - b.updatedAt);
139
+ for (const entry of entries.slice(0, Math.max(0, entries.length - REVIEW_STATE_SESSION_CAP + 1))) {
140
+ const current = table.get(entry.key);
141
+ if (current === void 0 || (current.updatedAt ?? 0) !== entry.updatedAt) continue;
142
+ await table.delete(entry.key).catch((error) => {
143
+ ctx.logger.warn(`evolution-state-domain: review-state session-cap eviction for "${entry.key}" failed (will retry on the next save): ${error instanceof Error ? error.message : String(error)}`);
144
+ });
145
+ }
128
146
  },
129
147
  async loadCuratorState() {
130
148
  const record = (await ensure()).table(CURATOR_STATE_TABLE).get(CURATOR_STATE_KEY);
@@ -233,7 +251,7 @@ function apply(ctx) {
233
251
  const resolvedEntries = [...table.entries()].map(([key, record]) => ({
234
252
  key,
235
253
  record
236
- })).filter((entry) => entry.record.status === "approved" || entry.record.status === "rejected");
254
+ })).filter((entry) => (entry.record.status === "approved" || entry.record.status === "rejected") && entry.record.kind !== "capability");
237
255
  const resolvedAtMs = (record) => {
238
256
  const parsed = Date.parse(record.resolvedAt ?? "");
239
257
  return Number.isNaN(parsed) ? Number.MAX_SAFE_INTEGER : parsed;
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.65",
4
+ "version": "0.3.67",
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.65"
39
+ "@lmzhen/dsh-evolution-state-storage": "^0.3.67"
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.65"
46
+ "@lmzhen/dsh-evolution-state-storage": "^0.3.67"
47
47
  }
48
48
  }