@mingxy/cerebro-claude-code 0.3.5 → 0.3.6
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/.claude-plugin/plugin.json +1 -1
- package/hooks/apply-dream.mjs +24 -1
- package/package.json +1 -1
package/hooks/apply-dream.mjs
CHANGED
|
@@ -66,10 +66,28 @@ if (!archivePath && existsSync(OUT_DIR)) {
|
|
|
66
66
|
if (files.length) archivePath = join(OUT_DIR, files[files.length - 1]);
|
|
67
67
|
}
|
|
68
68
|
if (!archivePath) { console.error("apply-dream: no dream output found"); process.exit(1); }
|
|
69
|
-
|
|
69
|
+
let entries = JSON.parse(readFileSync(archivePath, "utf8")).entries || [];
|
|
70
|
+
|
|
71
|
+
// ─── dedup: the LLM occasionally emits the same name twice — once with full
|
|
72
|
+
// content, once as a bare stub (source=kept, empty body/description; the
|
|
73
|
+
// deepseek rewrite tic, cf. cc-dream-truncation-fix). The write phase is
|
|
74
|
+
// last-write-wins, so a trailing stub would clobber the real entry into a
|
|
75
|
+
// 60-byte frontmatter shell. Collapse by name BEFORE merging: longest
|
|
76
|
+
// non-empty body wins; on a tie kept wins (conservative — kept writes nothing). ──
|
|
77
|
+
{
|
|
78
|
+
const seen = new Map();
|
|
79
|
+
for (const e of entries) {
|
|
80
|
+
const cur = seen.get(e.name);
|
|
81
|
+
if (!cur || (e.body || "").length > (cur.body || "").length
|
|
82
|
+
|| ((e.body || "").length === (cur.body || "").length && e.source === "kept" && cur.source !== "kept"))
|
|
83
|
+
seen.set(e.name, e);
|
|
84
|
+
}
|
|
85
|
+
entries = [...seen.values()];
|
|
86
|
+
}
|
|
70
87
|
|
|
71
88
|
// ─── merge ────────────────────────────────────────────────────────────────────
|
|
72
89
|
const unknown = []; // kept names missing from the old archive — LLM renamed, memory at risk
|
|
90
|
+
const empty = []; // content actions with empty body+description — never written, surfaced
|
|
73
91
|
const report = { keep: 0, write: [], drop: [], dropCount: 0 };
|
|
74
92
|
for (let e of entries) {
|
|
75
93
|
// normalize BEFORE any branch: an LLM-emitted Chinese name that the MEMORY.md
|
|
@@ -83,6 +101,10 @@ for (let e of entries) {
|
|
|
83
101
|
report.drop.push(e.name);
|
|
84
102
|
report.dropCount++;
|
|
85
103
|
} else if (act === "added" || act === "merged" || act === "updated") {
|
|
104
|
+
// an empty stub must never clobber a real file: writing it would leave a
|
|
105
|
+
// 60-byte frontmatter shell. merged/updated skip = old content survives;
|
|
106
|
+
// added skip = surfaced below, not silently dropped.
|
|
107
|
+
if (!(e.body || "").trim() && !(e.description || "").trim()) { empty.push(`${e.name} (${act})`); continue; }
|
|
86
108
|
report.write.push(e); // LLM content is authoritative for these actions
|
|
87
109
|
} else {
|
|
88
110
|
unknown.push(`${e.name} (action=${act || "?"})`);
|
|
@@ -97,6 +119,7 @@ const lines = [
|
|
|
97
119
|
for (const e of report.write) lines.push(` ${e.source || e.action} ${e.name} — ${(e.description || "").slice(0, 60)}`);
|
|
98
120
|
for (const n of report.drop) lines.push(` drop ${n}`);
|
|
99
121
|
for (const n of unknown) lines.push(` ? ${n} ← surfaced, not dropped`);
|
|
122
|
+
for (const n of empty) lines.push(` ~ ${n} ← empty stub skipped, not written`);
|
|
100
123
|
if (orphanFiles.length) lines.push(` (unparsed old files left untouched: ${orphanFiles.length})`);
|
|
101
124
|
console.log(lines.join("\n"));
|
|
102
125
|
if (unknown.length) console.log("\n⚠ URGENT: unknown kept names above — surface to the user BEFORE applying; they may be renames the LLM invented.");
|
package/package.json
CHANGED