hmem-mcp 7.0.0 → 7.0.2

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.
@@ -252,10 +252,10 @@ export class HmemStore {
252
252
  const seq = this.nextSeq(prefix);
253
253
  const rootId = `${prefix}${String(seq).padStart(4, "0")}`;
254
254
  const timestamp = new Date().toISOString();
255
- const { title, level1, nodes } = this.parseTree(content, rootId);
255
+ const { title, level1, nodes: parsedNodes } = this.parseTree(content, rootId);
256
+ // nodes is mutable — E-entries may have invalid L2 nodes stripped before insert
257
+ let nodes = parsedNodes;
256
258
  // Schema validation: validate parsed section nodes, not raw content.
257
- // The parser already separates section titles from body text, so this correctly
258
- // ignores body lines that happen to be at L2 depth after a blank line.
259
259
  const schema = this.cfg.schemas?.[prefix];
260
260
  if (schema) {
261
261
  const sectionNames = new Set(schema.sections.map(s => s.name.toLowerCase()));
@@ -265,11 +265,20 @@ export class HmemStore {
265
265
  return ![...sectionNames].some(sec => firstWord.startsWith(sec));
266
266
  });
267
267
  if (invalid.length > 0) {
268
- const sectionList = schema.sections.map((s, i) => `.${i + 1} ${s.name}`).join(", ");
269
- throw new Error(`${prefix}-entry schema violation.\n` +
270
- `Valid sections: ${sectionList}\n` +
271
- `Invalid L2 nodes: ${invalid.map(n => `"${n.title.substring(0, 50)}"`).join(", ")}\n\n` +
272
- `L2 node names must match defined schema sections.`);
268
+ if (prefix === "E") {
269
+ // E-entries auto-scaffold their structure — silently drop invalid direct children.
270
+ // This handles the common case where body text is accidentally tab-indented,
271
+ // creating spurious L2 nodes that don't match schema section names.
272
+ const invalidIds = new Set(invalid.map(n => n.id));
273
+ nodes = nodes.filter(n => !invalidIds.has(n.id) && !invalidIds.has(n.parent_id));
274
+ }
275
+ else {
276
+ const sectionList = schema.sections.map((s, i) => `.${i + 1} ${s.name}`).join(", ");
277
+ throw new Error(`${prefix}-entry schema violation.\n` +
278
+ `Valid sections: ${sectionList}\n` +
279
+ `Invalid L2 nodes: ${invalid.map(n => `"${n.title.substring(0, 50)}"`).join(", ")}\n\n` +
280
+ `L2 node names must match defined schema sections.`);
281
+ }
273
282
  }
274
283
  }
275
284
  if (!level1) {