pi-mega-compact 0.11.0 → 0.11.1

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.
@@ -105,10 +105,6 @@ export function initSchema(db) {
105
105
  );
106
106
  CREATE INDEX IF NOT EXISTS idx_raptor_session ON raptor_nodes(session_id);
107
107
  CREATE INDEX IF NOT EXISTS idx_raptor_parent ON raptor_nodes(parent_id);
108
- -- S42D/QA perf: session-scoped built_at ordering so the per-search cache
109
- -- invalidation MAX(built_at) is index-satisfied.
110
- CREATE INDEX IF NOT EXISTS idx_raptor_session_built
111
- ON raptor_nodes(session_id, built_at DESC);
112
108
 
113
109
  -- S42D: structured RAPTOR build history. One row per tree build; the
114
110
  -- freshness check (buildHistory.ts) uses completed_at + leaf_count to skip
@@ -375,6 +371,11 @@ export function initSchema(db) {
375
371
  // S25: RAPTOR freshness-guard timestamp. Additive; old DBs have NULL → 0 →
376
372
  // treated as stale → flat fallback (safe).
377
373
  ensureColumn(db, "raptor_nodes", "built_at", "INTEGER");
374
+ // S42D/QA perf: session-scoped built_at ordering. Must follow ensureColumn
375
+ // above — old DBs already have raptor_nodes without built_at, so CREATE TABLE
376
+ // IF NOT EXISTS is a no-op that doesn't add the column, and moving this index
377
+ // inside the DDL block caused "no such column: built_at" on upgrade.
378
+ db.exec("CREATE INDEX IF NOT EXISTS idx_raptor_session_built ON raptor_nodes(session_id, built_at DESC)");
378
379
  // S43: turn_index on raw_transcript so a message points directly at its
379
380
  // conversation turn (otherwise it must be inferred from seq ordering). NULL
380
381
  // for legacy rows — turns written before S43 have no turn link.
@@ -390,7 +391,9 @@ export function initSchema(db) {
390
391
  for (const d of ACHIEVEMENT_DEFS) {
391
392
  seedAch.run(d.id, d.title, d.description, d.hidden ? 1 : 0, d.icon);
392
393
  }
393
- const v = db.prepare("SELECT value FROM meta WHERE key='schema_version'").get();
394
+ const v = db
395
+ .prepare("SELECT value FROM meta WHERE key='schema_version'")
396
+ .get();
394
397
  if (!v) {
395
398
  db.prepare("INSERT INTO meta(key, value) VALUES(?, ?)").run("schema_version", String(SCHEMA_VERSION));
396
399
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-mega-compact",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "Layered, local, vector-backed context compressor for pi — supersede/collapse/cluster compaction with deduped inline recall.",
5
5
  "type": "module",
6
6
  "license": "BSD-3-Clause",
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * schema.ts — table creation, migrations, `ensureColumn`, PRAGMA setup.
3
3
  */
4
- import { DatabaseSync } from "node:sqlite";
4
+ import type { DatabaseSync } from "node:sqlite";
5
5
  import { ACHIEVEMENT_DEFS } from "../../game/scoring.js";
6
6
 
7
7
  const SCHEMA_VERSION = 2;
@@ -13,14 +13,21 @@ const SCHEMA_VERSION = 2;
13
13
  * input), so the unavoidable identifier interpolation here does not violate
14
14
  * PREVENT-002 (no external data reaches this SQL).
15
15
  */
16
- export function ensureColumn(db: DatabaseSync, table: string, column: string, decl: string): void {
17
- const cols = db.prepare(`PRAGMA table_info(${table})`).all() as Array<{ name: string }>;
18
- if (cols.some((c) => c.name === column)) return;
19
- db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${decl}`);
16
+ export function ensureColumn(
17
+ db: DatabaseSync,
18
+ table: string,
19
+ column: string,
20
+ decl: string,
21
+ ): void {
22
+ const cols = db.prepare(`PRAGMA table_info(${table})`).all() as Array<{
23
+ name: string;
24
+ }>;
25
+ if (cols.some((c) => c.name === column)) return;
26
+ db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${decl}`);
20
27
  }
21
28
 
22
29
  export function initSchema(db: DatabaseSync): void {
23
- db.exec(`
30
+ db.exec(`
24
31
  CREATE TABLE IF NOT EXISTS context_chunks (
25
32
  id TEXT NOT NULL,
26
33
  session_id TEXT NOT NULL,
@@ -111,10 +118,6 @@ export function initSchema(db: DatabaseSync): void {
111
118
  );
112
119
  CREATE INDEX IF NOT EXISTS idx_raptor_session ON raptor_nodes(session_id);
113
120
  CREATE INDEX IF NOT EXISTS idx_raptor_parent ON raptor_nodes(parent_id);
114
- -- S42D/QA perf: session-scoped built_at ordering so the per-search cache
115
- -- invalidation MAX(built_at) is index-satisfied.
116
- CREATE INDEX IF NOT EXISTS idx_raptor_session_built
117
- ON raptor_nodes(session_id, built_at DESC);
118
121
 
119
122
  -- S42D: structured RAPTOR build history. One row per tree build; the
120
123
  -- freshness check (buildHistory.ts) uses completed_at + leaf_count to skip
@@ -364,45 +367,55 @@ export function initSchema(db: DatabaseSync): void {
364
367
  CREATE INDEX IF NOT EXISTS idx_perf_samples_ts ON perf_samples(ts);
365
368
  CREATE INDEX IF NOT EXISTS idx_perf_samples_kind_ts ON perf_samples(kind, ts);
366
369
  `);
367
- // Idempotent column migrations. `CREATE TABLE IF NOT EXISTS` is a no-op on a
368
- // pre-existing table, so new columns added to context_chunks after a store was
369
- // first created (e.g. original_token_estimate in v0.4.2) must be ALTERed in for
370
- // databases created by an older version — otherwise repoStats()/upsert crash
371
- // with "no such column" and the extension fails to load. Additive only.
372
- ensureColumn(db, "context_chunks", "original_token_estimate", "INTEGER");
373
- // S27 Task 6: content_ref column in raw_transcript for dedup_mirror references.
374
- ensureColumn(db, "raw_transcript", "content_ref", "TEXT");
375
- // S20 memory-RAG extension: additive columns for auto-review ops. Idempotent —
376
- // only alters DBs created by an older version that lack these columns.
377
- ensureColumn(db, "memories", "category", "TEXT");
378
- ensureColumn(db, "memories", "target", "TEXT");
379
- ensureColumn(db, "memories", "last_referenced", "INTEGER");
380
- ensureColumn(db, "memories", "source_turn", "INTEGER");
381
- // S25: RAPTOR freshness-guard timestamp. Additive; old DBs have NULL → 0 →
382
- // treated as stale → flat fallback (safe).
383
- ensureColumn(db, "raptor_nodes", "built_at", "INTEGER");
384
- // S43: turn_index on raw_transcript so a message points directly at its
385
- // conversation turn (otherwise it must be inferred from seq ordering). NULL
386
- // for legacy rows turns written before S43 have no turn link.
387
- ensureColumn(db, "raw_transcript", "turn_index", "INTEGER");
388
- // S43: conversation_id + last_turn_id on session_state (legacy DBs have NULL).
389
- ensureColumn(db, "session_state", "conversation_id", "TEXT");
390
- ensureColumn(db, "session_state", "last_turn_id", "INTEGER");
391
- // S35: idempotent seed of the 9 achievement rows. ON CONFLICT(id) DO
392
- // NOTHING so a re-open never clobbers an already-unlocked row's
393
- // unlocked_at. No user input reaches this SQL (PREVENT-002 safe).
394
- const seedAch = db.prepare(
395
- `INSERT INTO game_achievements (id, title, description, hidden, icon)
370
+ // Idempotent column migrations. `CREATE TABLE IF NOT EXISTS` is a no-op on a
371
+ // pre-existing table, so new columns added to context_chunks after a store was
372
+ // first created (e.g. original_token_estimate in v0.4.2) must be ALTERed in for
373
+ // databases created by an older version — otherwise repoStats()/upsert crash
374
+ // with "no such column" and the extension fails to load. Additive only.
375
+ ensureColumn(db, "context_chunks", "original_token_estimate", "INTEGER");
376
+ // S27 Task 6: content_ref column in raw_transcript for dedup_mirror references.
377
+ ensureColumn(db, "raw_transcript", "content_ref", "TEXT");
378
+ // S20 memory-RAG extension: additive columns for auto-review ops. Idempotent —
379
+ // only alters DBs created by an older version that lack these columns.
380
+ ensureColumn(db, "memories", "category", "TEXT");
381
+ ensureColumn(db, "memories", "target", "TEXT");
382
+ ensureColumn(db, "memories", "last_referenced", "INTEGER");
383
+ ensureColumn(db, "memories", "source_turn", "INTEGER");
384
+ // S25: RAPTOR freshness-guard timestamp. Additive; old DBs have NULL → 0 →
385
+ // treated as stale → flat fallback (safe).
386
+ ensureColumn(db, "raptor_nodes", "built_at", "INTEGER");
387
+ // S42D/QA perf: session-scoped built_at ordering. Must follow ensureColumn
388
+ // above old DBs already have raptor_nodes without built_at, so CREATE TABLE
389
+ // IF NOT EXISTS is a no-op that doesn't add the column, and moving this index
390
+ // inside the DDL block caused "no such column: built_at" on upgrade.
391
+ db.exec(
392
+ "CREATE INDEX IF NOT EXISTS idx_raptor_session_built ON raptor_nodes(session_id, built_at DESC)",
393
+ );
394
+ // S43: turn_index on raw_transcript so a message points directly at its
395
+ // conversation turn (otherwise it must be inferred from seq ordering). NULL
396
+ // for legacy rows turns written before S43 have no turn link.
397
+ ensureColumn(db, "raw_transcript", "turn_index", "INTEGER");
398
+ // S43: conversation_id + last_turn_id on session_state (legacy DBs have NULL).
399
+ ensureColumn(db, "session_state", "conversation_id", "TEXT");
400
+ ensureColumn(db, "session_state", "last_turn_id", "INTEGER");
401
+ // S35: idempotent seed of the 9 achievement rows. ON CONFLICT(id) DO
402
+ // NOTHING so a re-open never clobbers an already-unlocked row's
403
+ // unlocked_at. No user input reaches this SQL (PREVENT-002 safe).
404
+ const seedAch = db.prepare(
405
+ `INSERT INTO game_achievements (id, title, description, hidden, icon)
396
406
  VALUES (?, ?, ?, ?, ?) ON CONFLICT(id) DO NOTHING`,
397
- );
398
- for (const d of ACHIEVEMENT_DEFS) {
399
- seedAch.run(d.id, d.title, d.description, d.hidden ? 1 : 0, d.icon);
400
- }
407
+ );
408
+ for (const d of ACHIEVEMENT_DEFS) {
409
+ seedAch.run(d.id, d.title, d.description, d.hidden ? 1 : 0, d.icon);
410
+ }
401
411
 
402
- const v = db.prepare("SELECT value FROM meta WHERE key='schema_version'").get() as
403
- | { value: string }
404
- | undefined;
405
- if (!v) {
406
- db.prepare("INSERT INTO meta(key, value) VALUES(?, ?)").run("schema_version", String(SCHEMA_VERSION));
407
- }
412
+ const v = db
413
+ .prepare("SELECT value FROM meta WHERE key='schema_version'")
414
+ .get() as { value: string } | undefined;
415
+ if (!v) {
416
+ db.prepare("INSERT INTO meta(key, value) VALUES(?, ?)").run(
417
+ "schema_version",
418
+ String(SCHEMA_VERSION),
419
+ );
420
+ }
408
421
  }