@lmzhen/dsh-evolution-plan-validator 0.3.62 → 0.3.63
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 +29 -1
- package/package.json +2 -2
package/lib/index.js
CHANGED
|
@@ -144,6 +144,13 @@ function validateEvolutionPlan(plan, context) {
|
|
|
144
144
|
};
|
|
145
145
|
}
|
|
146
146
|
function validateMemoryOp(op, context, index) {
|
|
147
|
+
const badField = malformedStringField(op, [
|
|
148
|
+
"facts",
|
|
149
|
+
"content",
|
|
150
|
+
"old_text",
|
|
151
|
+
"target"
|
|
152
|
+
]);
|
|
153
|
+
if (badField) return `memory op ${index}: field ${badField} must be a string`;
|
|
147
154
|
if (!hasValidEvidence(op.evidence, context.sessionSeq)) return `memory op ${index}: evidence is required and must reference a valid session seq`;
|
|
148
155
|
for (const key of FORBIDDEN_KEYS) if (key in op) return `memory op ${index}: forbidden field ${key}`;
|
|
149
156
|
if (op.target !== "memory" && op.target !== "user") return `memory op ${index}: target must be memory or user`;
|
|
@@ -156,7 +163,28 @@ function validateMemoryOp(op, context, index) {
|
|
|
156
163
|
if (text.length > budget) return `memory op ${index}: content exceeds ${op.target === "user" ? "user" : "memory"} budget`;
|
|
157
164
|
return null;
|
|
158
165
|
}
|
|
166
|
+
/** P2-1 (v15): the string-typed fields the executors dereference with
|
|
167
|
+
* `.trim()`/`.length`. `target` is included for memory ops because the
|
|
168
|
+
* engine compares it against literals. */
|
|
169
|
+
function malformedStringField(op, fields) {
|
|
170
|
+
const record = op;
|
|
171
|
+
for (const field of fields) {
|
|
172
|
+
const value = record[field];
|
|
173
|
+
if (value !== void 0 && value !== null && typeof value !== "string") return field;
|
|
174
|
+
}
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
159
177
|
function validateSkillOp(op, context, index) {
|
|
178
|
+
const badField = malformedStringField(op, [
|
|
179
|
+
"name",
|
|
180
|
+
"content",
|
|
181
|
+
"old_string",
|
|
182
|
+
"new_string",
|
|
183
|
+
"file_path",
|
|
184
|
+
"file_content",
|
|
185
|
+
"absorbed_into"
|
|
186
|
+
]);
|
|
187
|
+
if (badField) return `skill op ${index}: field ${badField} must be a string`;
|
|
160
188
|
for (const key of FORBIDDEN_KEYS) if (key in op) return `skill op ${index}: forbidden field ${key}`;
|
|
161
189
|
const name = (op.name ?? "").trim();
|
|
162
190
|
if (!name) return `skill op ${index}: name is required`;
|
|
@@ -172,7 +200,7 @@ function validateSkillOp(op, context, index) {
|
|
|
172
200
|
op.content ?? "",
|
|
173
201
|
op.new_string ?? ""
|
|
174
202
|
].reduce((max, value) => Math.max(max, value.length), 0);
|
|
175
|
-
if (action === "write_file" && !(op.file_content ??
|
|
203
|
+
if (action === "write_file" && !(op.file_content ?? "").trim()) return `skill op ${index}: write_file requires file_content`;
|
|
176
204
|
if (writeBytes > (context.maxSkillContentChars ?? DEFAULT_SKILL_CONTENT_CHARS)) return `skill op ${index}: content exceeds skill budget`;
|
|
177
205
|
if (action === "restructure") {
|
|
178
206
|
if (!Array.isArray(op.restructure) || op.restructure.length === 0) return `skill op ${index}: restructure requires a non-empty restructure list`;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-plan-validator",
|
|
3
3
|
"description": "Deterministic validator for model-produced evolution plans (community build)",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.63",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
],
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@lmzhen/dsh-evolution-core": "^0.3.
|
|
33
|
+
"@lmzhen/dsh-evolution-core": "^0.3.63"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
|