@gamaze/hicortex 0.17.5 → 0.17.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.
@@ -15,16 +15,20 @@
15
15
  * ------------
16
16
  * Walks memories ordered by rowid in batches (default 200). Default scope =
17
17
  * episodes only (`memory_type = 'episode'`); `--all` reclassifies every memory
18
- * regardless of current type. For each memory, ONE constrained LLM call asks
19
- * the model to classify the content as episode / fact / decision. The reply is
20
- * parsed + validated, and `UPDATE memories SET memory_type = ? WHERE id = ?`
21
- * runs inside a per-batch transaction. The cursor (`typeCursor` in state.json)
22
- * advances to the last committed rowid after each batch — crash-safe and
23
- * infra-abort-safe (same discipline as classify-domains).
18
+ * regardless of current type **except lessons** (see below). For each memory,
19
+ * ONE constrained LLM call asks the model to classify the content as
20
+ * episode / fact / decision. The reply is parsed + validated, and
21
+ * `UPDATE memories SET memory_type = ? WHERE id = ?` runs inside a per-batch
22
+ * transaction. The cursor (`typeCursor` in state.json) advances to the last
23
+ * committed rowid after each batch — crash-safe and infra-abort-safe (same
24
+ * discipline as classify-domains).
24
25
  *
25
- * Lessons are NEVER produced here: the reflection stage owns them. A model that
26
- * replies "lesson" is treated as unparseable (the memory keeps its current type
27
- * and is retried next run via the cursor).
26
+ * Lessons are NEVER touched here: the reflection stage owns them. The `--all`
27
+ * scope explicitly excludes `memory_type = 'lesson'` this is the primary
28
+ * defence. (The prompt asks only for episode/fact/decision, so a lesson that
29
+ * DID enter scope would be overwritten to E/F/D — the model never replies
30
+ * "lesson". `parseTypeReply`'s rejection of a "lesson" reply is a backstop, not
31
+ * the main guard.)
28
32
  *
29
33
  * This command does NOT use the consolidation budget — it is a standalone CLI,
30
34
  * not a nightly stage.
@@ -16,16 +16,20 @@
16
16
  * ------------
17
17
  * Walks memories ordered by rowid in batches (default 200). Default scope =
18
18
  * episodes only (`memory_type = 'episode'`); `--all` reclassifies every memory
19
- * regardless of current type. For each memory, ONE constrained LLM call asks
20
- * the model to classify the content as episode / fact / decision. The reply is
21
- * parsed + validated, and `UPDATE memories SET memory_type = ? WHERE id = ?`
22
- * runs inside a per-batch transaction. The cursor (`typeCursor` in state.json)
23
- * advances to the last committed rowid after each batch — crash-safe and
24
- * infra-abort-safe (same discipline as classify-domains).
19
+ * regardless of current type **except lessons** (see below). For each memory,
20
+ * ONE constrained LLM call asks the model to classify the content as
21
+ * episode / fact / decision. The reply is parsed + validated, and
22
+ * `UPDATE memories SET memory_type = ? WHERE id = ?` runs inside a per-batch
23
+ * transaction. The cursor (`typeCursor` in state.json) advances to the last
24
+ * committed rowid after each batch — crash-safe and infra-abort-safe (same
25
+ * discipline as classify-domains).
25
26
  *
26
- * Lessons are NEVER produced here: the reflection stage owns them. A model that
27
- * replies "lesson" is treated as unparseable (the memory keeps its current type
28
- * and is retried next run via the cursor).
27
+ * Lessons are NEVER touched here: the reflection stage owns them. The `--all`
28
+ * scope explicitly excludes `memory_type = 'lesson'` this is the primary
29
+ * defence. (The prompt asks only for episode/fact/decision, so a lesson that
30
+ * DID enter scope would be overwritten to E/F/D — the model never replies
31
+ * "lesson". `parseTypeReply`'s rejection of a "lesson" reply is a backstop, not
32
+ * the main guard.)
29
33
  *
30
34
  * This command does NOT use the consolidation budget — it is a standalone CLI,
31
35
  * not a nightly stage.
@@ -205,8 +209,15 @@ async function runClassifyTypes(options = {}) {
205
209
  report.cursor = cursor;
206
210
  console.log(`[hicortex] classify-types starting: scope ${all ? "ALL" : "episodes only"}, ` +
207
211
  `batch ${batchSize}, cursor ${cursor}${options.reset ? " (reset)" : ""}`);
208
- // Scope filter: default = episodes only; --all = everything.
209
- const scopeSql = all ? "rowid > ?" : "rowid > ? AND memory_type = 'episode'";
212
+ // Scope filter: default = episodes only; --all = everything EXCEPT lessons.
213
+ // Lessons are owned by the reflection stage they must never be
214
+ // reclassified here. (The prompt asks only for episode/fact/decision, so a
215
+ // lesson row in scope gets overwritten: the model never replies "lesson".
216
+ // The scope exclusion is therefore the real guard; parseTypeReply's
217
+ // "lesson" rejection is a backstop, not the primary defence.)
218
+ const scopeSql = all
219
+ ? "rowid > ? AND (memory_type IS NULL OR memory_type != 'lesson')"
220
+ : "rowid > ? AND memory_type = 'episode'";
210
221
  const batchStmt = db.prepare(`SELECT rowid AS __rowid, id, content, memory_type FROM memories
211
222
  WHERE ${scopeSql} ORDER BY rowid ASC LIMIT ?`);
212
223
  // Set true when the classifier returns null (infra error): finish the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gamaze/hicortex",
3
- "version": "0.17.5",
3
+ "version": "0.17.6",
4
4
  "description": "Self-learning memory for AI agents — experience captured automatically, distilled into lessons overnight, shared across your whole fleet. Works with Hermes, OpenClaw, Claude Code, and Pi.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {