@lmzhen/dsh-evolution-approval 0.3.62 → 0.3.64

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
@@ -12,7 +12,8 @@ replayable only when the corresponding tool package is composed.
12
12
  Run the companion invariant and tests:
13
13
 
14
14
  ```sh
15
- node node_modules/vitest/vitest.mjs run packages/evolution/evolution-approval/tests
15
+ node node_modules/vitest/vitest.mjs run packages/evolution/evolution-approval/tests # overlay layout
16
+ # flat mirror: node node_modules/vitest/vitest.mjs run packages/evolution-approval/tests
16
17
  ```
17
18
 
18
19
  ## Model Experience
package/lib/index.js CHANGED
@@ -31,13 +31,19 @@ var EvolutionApproval = class extends Service {
31
31
  stageForeground: z.boolean().default(true)
32
32
  });
33
33
  enabled;
34
- stageForeground;
34
+ stageForegroundConfig;
35
+ /** P3 (v16): public read for staging pre-checks (learning-graph refuses a
36
+ * stage that no runner could replay only when foreground writes stage at
37
+ * all). Mirrors `this.stageForeground`. */
38
+ get stageForeground() {
39
+ return this.stageForegroundConfig;
40
+ }
35
41
  runners = /* @__PURE__ */ new Map();
36
42
  inFlight = /* @__PURE__ */ new Map();
37
43
  constructor(ctx, config = {}) {
38
44
  super(ctx, "evolutionApproval");
39
45
  this.enabled = config.enabled ?? false;
40
- this.stageForeground = config.stageForeground ?? true;
46
+ this.stageForegroundConfig = config.stageForeground ?? true;
41
47
  }
42
48
  state() {
43
49
  return this.ctx.evolutionState;
@@ -139,7 +145,7 @@ var EvolutionApproval = class extends Service {
139
145
  message: `Pending write "${id}" is not in the pending window (rotated or resolved).`
140
146
  };
141
147
  }
142
- const resolution = await this.state().tryResolvePending(id, "rejected");
148
+ const resolution = await this.state().tryResolvePending(id, "rejected", claimId);
143
149
  if (!resolution.applied || !resolution.record) {
144
150
  await this.state().releasePendingClaim(id, claimId);
145
151
  return {
@@ -195,10 +201,16 @@ var EvolutionApproval = class extends Service {
195
201
  const runner = this.runners.get(record.kind);
196
202
  if (!runner) {
197
203
  if (record.kind === "capability") {
198
- if (!(await this.state().tryResolvePending(id, "approved")).applied) return {
199
- ok: false,
200
- message: `Pending write "${id}" was already resolved.`
201
- };
204
+ if (!(await this.state().tryResolvePending(id, "approved", claimId)).applied) {
205
+ if ((await this.state().listPending("rejected")).find((item) => item.id === id)) return {
206
+ ok: false,
207
+ message: `Capability "${id}" was approved, but the record was resolved to "rejected" concurrently — no code ran and nothing needs replaying; verify before re-submitting.`
208
+ };
209
+ return {
210
+ ok: false,
211
+ message: `Pending write "${id}" was already resolved by another writer.`
212
+ };
213
+ }
202
214
  return {
203
215
  ok: true,
204
216
  message: "Capability approved for manual activation in Creator mode (no code was executed)."
@@ -253,7 +265,7 @@ function normalizeSummary(input) {
253
265
  return `memory ${targetLabel === "memory" ? "" : `${targetLabel} `}batch of ${candidate.operations.length} operations`;
254
266
  }
255
267
  }
256
- if (input.kind === "skill" && /(?:^|\s)delete\s/.test(trimmed)) return `${trimmed} (warning: archive)`;
268
+ if (input.kind === "skill" && /^(?:skill|graph)\s+delete\s/.test(trimmed)) return `${trimmed} (warning: archive)`;
257
269
  return trimmed;
258
270
  }
259
271
  //#endregion
@@ -66,6 +66,11 @@ export type ApprovalLike = {
66
66
  }>;
67
67
  hasRunner(kind: PendingKind): boolean;
68
68
  isEnabled?: boolean;
69
+ /** P3 (v16): whether foreground-origin writes stage (learning-graph's
70
+ * hasRunner pre-check reads it so it only refuses writes that would
71
+ * actually be staged). Optional: absent means "unknown" and callers must
72
+ * not pre-refuse on it. */
73
+ stageForeground?: boolean;
69
74
  registerRunner(kind: PendingKind, runner: WriteRunner): () => void;
70
75
  list(status?: PendingStatus): Promise<PendingRecord[]>;
71
76
  approve(id: string): Promise<{
@@ -106,7 +111,11 @@ export declare class EvolutionApproval extends Service {
106
111
  static inject: string[];
107
112
  static Config: Schema<Config>;
108
113
  private readonly enabled;
109
- private readonly stageForeground;
114
+ private readonly stageForegroundConfig;
115
+ /** P3 (v16): public read for staging pre-checks (learning-graph refuses a
116
+ * stage that no runner could replay only when foreground writes stage at
117
+ * all). Mirrors `this.stageForeground`. */
118
+ get stageForeground(): boolean;
110
119
  private readonly runners;
111
120
  private readonly inFlight;
112
121
  constructor(ctx: Context, config?: Config);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lmzhen/dsh-evolution-approval",
3
3
  "description": "Stage/pending approval service for Hermes-style self-evolution writes (community build)",
4
- "version": "0.3.62",
4
+ "version": "0.3.64",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -35,15 +35,15 @@
35
35
  "peerDependencies": {
36
36
  "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
37
37
  "@deepseek-ai/cordis": "^4.0.1",
38
- "@lmzhen/dsh-evolution-state-storage": "^0.3.62",
39
- "@lmzhen/dsh-evolution-state": "^0.3.62"
38
+ "@lmzhen/dsh-evolution-state-storage": "^0.3.64",
39
+ "@lmzhen/dsh-evolution-state": "^0.3.64"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
43
- "@lmzhen/dsh-evolution-state-storage": "^0.3.62",
44
- "@lmzhen/dsh-evolution-state": "^0.3.62",
45
- "@lmzhen/dsh-evolution-io": "^0.3.62",
46
- "@lmzhen/dsh-evolution-io-node": "^0.3.62",
47
- "@lmzhen/dsh-evolution-state-json": "^0.3.62"
43
+ "@lmzhen/dsh-evolution-state-storage": "^0.3.64",
44
+ "@lmzhen/dsh-evolution-state": "^0.3.64",
45
+ "@lmzhen/dsh-evolution-io": "^0.3.64",
46
+ "@lmzhen/dsh-evolution-io-node": "^0.3.64",
47
+ "@lmzhen/dsh-evolution-state-json": "^0.3.64"
48
48
  }
49
49
  }