feat(reparenting): supersede di un record ri-parenta automaticamente i figli attivi
- gateway: nel blocco supersede, i figli attivi (parent_id == vecchio UUID, superseded_by vuoto) vengono ri-parentati al nuovo UUID; audit action 'reparent'; risposta con campo 'reparented'. Un solo livello: i nipoti puntano agli UUID dei figli, invariati. I figli superseduti restano storici ancorati alla vecchia lineage. - estensione: qmem_tree con fallback lineage (cerca figli anche per supersedes_id del root) per gli orfani pre-fix; qmem_correct riporta il numero di figli ri-parentati. - test: 2 nuovi (ri-parenta figli attivi; ri-parenta solo attivi con figlio già superseduto). 34 pass. - deploy su brain (10.8.0.3): main.py aggiornato, container ricreato, smoke test end-to-end OK (reparented=1).
This commit is contained in:
+25
-11
@@ -568,10 +568,10 @@ export default function qmemExtension(pi: ExtensionAPI) {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Correzione applicata: nuovo record ${data.memory_id} supersede ${memoryId}${p.reason ? ` (motivo: ${p.reason})` : ""}. Il vecchio record resta in archivio marcato superseded.`,
|
||||
text: `Correzione applicata: nuovo record ${data.memory_id} supersede ${memoryId}${p.reason ? ` (motivo: ${p.reason})` : ""}. Il vecchio record resta in archivio marcato superseded.${data.reparented ? ` ${data.reparented} figli ri-parentati al nuovo UUID.` : ""}`,
|
||||
},
|
||||
],
|
||||
details: { new_id: data.memory_id, superseded_id: memoryId },
|
||||
details: { new_id: data.memory_id, superseded_id: memoryId, reparented: data.reparented ?? 0 },
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -774,15 +774,29 @@ export default function qmemExtension(pi: ExtensionAPI) {
|
||||
}
|
||||
}
|
||||
|
||||
// Recupera tutti i figli associati a parent_id == rootId
|
||||
const childRes = await gatewayRequest(
|
||||
cfg,
|
||||
"POST",
|
||||
"/v1/memories:search",
|
||||
{ query: "*", parent_id: rootId, top_k: 20, include_superseded: false, min_score: 0.0 },
|
||||
signal,
|
||||
);
|
||||
const children = childRes.ok ? (childRes.data.results ?? []) : [];
|
||||
// Recupera tutti i figli associati a parent_id == rootId.
|
||||
// Fallback lineage: se il root è stato superseduto, i figli storici
|
||||
// puntano ancora al vecchio UUID (supersedes_id) — li includiamo per
|
||||
// garantire la navigabilità dell'albero anche per gli orfani pre-fix.
|
||||
const parentIds = [rootId];
|
||||
if (rootData.supersedes_id) parentIds.push(rootData.supersedes_id);
|
||||
const children: any[] = [];
|
||||
const seen = new Set<string>();
|
||||
for (const pid of parentIds) {
|
||||
const childRes = await gatewayRequest(
|
||||
cfg,
|
||||
"POST",
|
||||
"/v1/memories:search",
|
||||
{ query: "*", parent_id: pid, top_k: 20, include_superseded: false, min_score: 0.0 },
|
||||
signal,
|
||||
);
|
||||
for (const c of childRes.ok ? (childRes.data.results ?? []) : []) {
|
||||
if (!seen.has(c.memory_id)) {
|
||||
seen.add(c.memory_id);
|
||||
children.push(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const out: string[] = [];
|
||||
out.push(`🌳 ALBERO GERARCHICO: ${rootData.topic ?? "ROOT"} [${rootData.level ?? "L1_ROOT"}]`);
|
||||
|
||||
Reference in New Issue
Block a user