Skip to content

Commit 62e49f9

Browse files
author
Tehan
committed
refactor(migrations): renumber external-recall migration v37→v38 (skill_memory takes v37)
1 parent 358629e commit 62e49f9

7 files changed

Lines changed: 18 additions & 17 deletions

File tree

ARCHITECTURE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ Magic Context runs in three effective modes depending on `ctx_reduce_enabled` an
431431

432432
**Storage:** Use the SQLite database created by `src/features/magic-context/storage-db.ts` under the cortexkit data directory resolved by `src/shared/data-path.ts` (`~/.local/share/cortexkit/magic-context/context.db` on Linux/macOS, XDG-equivalent on Windows). Legacy OpenCode-plugin-folder DBs are migrated forward on first boot. The same DB is shared cross-harness between OpenCode and Pi; session-scoped tables include a `harness` discriminator (`'opencode'` / `'pi'`) while project-scoped tables (memories, git commits) are shared.
433433

434-
**Schema migrations:** `src/features/magic-context/migrations.ts` declares versioned migrations v1–v37 (`LATEST_SUPPORTED_VERSION = 37` in `storage-db.ts` is the schema-fence ceiling and MUST be bumped with every new migration; a unit test — `schema-version-fence.test.ts` — asserts `LATEST_SUPPORTED_VERSION === LATEST_MIGRATION_VERSION` so the two can't drift). Notable: v10 `tool_owner_message_id` (composite tool-tag identity); v11 `todo_synthetic_*` (synthetic-todowrite); v12 orphan `memory_embeddings` cleanup; v13 `pending_compaction_marker_state` (deferred-marker drain); v14 project-scoped key files + version counter; v15 `deferred_execute_state` (boundary execution); v16 context-limit cache sentinels; v17 multi-anchor note-nudge/auto-search JSON storage; v18 `pending_pi_compaction_marker_state`; v19 compartment-state lease table; v20 subagent invocation token accounting; v21 session lifetime work metrics; **v22 the v2.0 cache-architecture foundation (m[0]/m[1] split tables, `project_state` epoch counter, plus per-compartment `p1`–`p4` tier columns, `importance`, `episode_type`, `p1_embedding`, and `legacy` flag); v23 `compartment_events` (historian-extracted causal_incident / trajectory_correction, stored-not-rendered in v2.0); v24 `historian_runs` telemetry (per-run chunk range, compartment/fact/event counts, importance min/max/avg, status + failure reason, FK to `subagent_invocations`); v25 `pi_stable_id_scheme` (Pi stable-id cutover watermark); v26 `memory_mutation_log` + `cached_m1_bytes` (memory supersede-delta — non-additive in-session memory mutations render as an m[1] `<memory-updates>` delta instead of bumping the project epoch, plus the frozen-m[1]-bytes cache column); v27 `tags.entry_fingerprint` (Pi fallback-tag adoption); v28 `git_sweep_coordinator` (lease/cooldown for cross-process git-commit sweeps); v29 `notes.anchor_ordinal` (note→conversation-tail traceback); v30 `cached_m0_system_hash` / `cached_m0_tool_set_hash` / `cached_m0_model_key` (HARD-bust m[0] markers — provider-side cache-eviction detection for the materialization taxonomy; the migration clears the m[0]/m[1] cache once so pre-v30 rows re-materialize cleanly); v31 ctx_reduce-nudge state (`last_nudge_undropped`, `channel2_nudge_state`, `last_emergency_input_sample` + startup heal zeroing legacy sticky/anchor nudge state); v32 protected-tail v3 boundary state + per-tag cached token counts (`tags.token_count` / `input_token_count` / `reasoning_token_count` — computed once on tag insert, summed for sidebar/boundary/nudge math); v33 `compartment_chunk_embeddings` table for cross-session semantic search across compartment windows; v34 `workspaces` / `workspace_members` tables plus `cached_m0_workspace_fingerprint` m[0] marker (with a one-shot m[0]/m[1] cache reset so pre-v34 rows re-materialize cleanly); v35 `workspaces.share_categories` default + epoch refresh for existing members; v36 `session_projects` ownership map + seed for pre-v36 embedded sessions; **v37 the external-memory v2 unified-read foundation: per-session `external_recall_json` / `external_recall_state` / `external_recall_at` columns on `session_meta` (the frozen post-dedup, post-trim snapshot every render replays for byte stability) and the `cached_m0_external_recall_hash` m[0] marker (a carried marker that drives the m[1] `<external-memory>` delta comparison only — deliberately NOT a `mustMaterialize` trigger; the migration is `ensureColumn`-idempotent so a dev DB that ran it under the pre-rename v31 number re-applies harmlessly).** Migration runner uses `schema_migrations` table with version-ordered execution and sibling-startup race protection (duplicate-insert is tolerated).
434+
**Schema migrations:** `src/features/magic-context/migrations.ts` declares versioned migrations v1–v38 (`LATEST_SUPPORTED_VERSION = 38` in `storage-db.ts` is the schema-fence ceiling and MUST be bumped with every new migration; a unit test — `schema-version-fence.test.ts` — asserts `LATEST_SUPPORTED_VERSION === LATEST_MIGRATION_VERSION` so the two can't drift). Notable: v10 `tool_owner_message_id` (composite tool-tag identity); v11 `todo_synthetic_*` (synthetic-todowrite); v12 orphan `memory_embeddings` cleanup; v13 `pending_compaction_marker_state` (deferred-marker drain); v14 project-scoped key files + version counter; v15 `deferred_execute_state` (boundary execution); v16 context-limit cache sentinels; v17 multi-anchor note-nudge/auto-search JSON storage; v18 `pending_pi_compaction_marker_state`; v19 compartment-state lease table; v20 subagent invocation token accounting; v21 session lifetime work metrics; **v22 the v2.0 cache-architecture foundation (m[0]/m[1] split tables, `project_state` epoch counter, plus per-compartment `p1`–`p4` tier columns, `importance`, `episode_type`, `p1_embedding`, and `legacy` flag); v23 `compartment_events` (historian-extracted causal_incident / trajectory_correction, stored-not-rendered in v2.0); v24 `historian_runs` telemetry (per-run chunk range, compartment/fact/event counts, importance min/max/avg, status + failure reason, FK to `subagent_invocations`); v25 `pi_stable_id_scheme` (Pi stable-id cutover watermark); v26 `memory_mutation_log` + `cached_m1_bytes` (memory supersede-delta — non-additive in-session memory mutations render as an m[1] `<memory-updates>` delta instead of bumping the project epoch, plus the frozen-m[1]-bytes cache column); v27 `tags.entry_fingerprint` (Pi fallback-tag adoption); v28 `git_sweep_coordinator` (lease/cooldown for cross-process git-commit sweeps); v29 `notes.anchor_ordinal` (note→conversation-tail traceback); v30 `cached_m0_system_hash` / `cached_m0_tool_set_hash` / `cached_m0_model_key` (HARD-bust m[0] markers — provider-side cache-eviction detection for the materialization taxonomy; the migration clears the m[0]/m[1] cache once so pre-v30 rows re-materialize cleanly); v31 ctx_reduce-nudge state (`last_nudge_undropped`, `channel2_nudge_state`, `last_emergency_input_sample` + startup heal zeroing legacy sticky/anchor nudge state); v32 protected-tail v3 boundary state + per-tag cached token counts (`tags.token_count` / `input_token_count` / `reasoning_token_count` — computed once on tag insert, summed for sidebar/boundary/nudge math); v33 `compartment_chunk_embeddings` table for cross-session semantic search across compartment windows; v34 `workspaces` / `workspace_members` tables plus `cached_m0_workspace_fingerprint` m[0] marker (with a one-shot m[0]/m[1] cache reset so pre-v34 rows re-materialize cleanly); v35 `workspaces.share_categories` default + epoch refresh for existing members; v36 `session_projects` ownership map + seed for pre-v36 embedded sessions; **v38 the external-memory v2 unified-read foundation: per-session `external_recall_json` / `external_recall_state` / `external_recall_at` columns on `session_meta` (the frozen post-dedup, post-trim snapshot every render replays for byte stability) and the `cached_m0_external_recall_hash` m[0] marker (a carried marker that drives the m[1] `<external-memory>` delta comparison only — deliberately NOT a `mustMaterialize` trigger; the migration is `ensureColumn`-idempotent so a dev DB that ran it under the pre-rename v31 number re-applies harmlessly).** Migration runner uses `schema_migrations` table with version-ordered execution and sibling-startup race protection (duplicate-insert is tolerated).
435435

436436
**Harness-aware behavior:** `src/shared/harness.ts` exposes `setHarness()`/`getHarness()` for the runtime to identify itself; production INSERTs into session-scoped tables tag rows with the current harness. Pi-specific session-resolution paths are skipped on OpenCode and vice versa.
437437

STRUCTURE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@
124124
- `src/features/magic-context/memory/external-recall-read.ts`: `readExternalRecallSnapshot` (sanitizeSlice validates per-item to fail safe on corrupted rows), `readExternalRecallHash`, `computeRecallSnapshotHash` (deterministic 16-char SHA-256 prefix of the JSON-serialized snapshot).
125125
- `src/features/magic-context/storage-db.ts`: Create durable storage; run versioned migrations; resolve runtime SQLite backend.
126126
- `src/features/magic-context/storage-meta-persisted.ts`: Read and write per-session persisted scalars and JSON blobs.
127-
- `src/features/magic-context/migrations.ts`: Versioned schema migrations v1–v37 (`LATEST_SUPPORTED_VERSION` in `storage-db.ts` must track the highest; `schema-version-fence.test.ts` asserts they stay in lockstep). v37 adds `external_recall_json` / `external_recall_state` / `external_recall_at` and the `cached_m0_external_recall_hash` m[0] marker.
127+
- `src/features/magic-context/migrations.ts`: Versioned schema migrations v1–v38 (`LATEST_SUPPORTED_VERSION` in `storage-db.ts` must track the highest; `schema-version-fence.test.ts` asserts they stay in lockstep). v38 adds `external_recall_json` / `external_recall_state` / `external_recall_at` and the `cached_m0_external_recall_hash` m[0] marker.
128128
- `src/features/magic-context/message-index.ts`: FTS-backed raw-message index for `ctx_search`.
129129
- `src/features/magic-context/search.ts`: Unified retrieval over memories, raw messages, git commits, and (explicit-only) the external long-term memory backend (`SearchSource += "external"`; `searchExternal` runs project + main bank in parallel, content-hash-dedups, drops hits already in the session's `<external-memory>` block, respects a 5s `AbortSignal`).
130130
- `src/tools/ctx-memory/tools.ts`: W2 correctives (Pi mirror: `packages/pi-plugin/src/tools/ctx-memory.ts`) — `write` tees to external, `update` remove-then-tee cascade, `archive` batched remove, `merge` no-op, `verify` (dreamer-only) verbatim re-upsert. Also adds `scope: "global"` which routes ONLY to the external main bank with origin provenance and no local row.

packages/plugin/src/features/magic-context/migrations-v34.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,13 @@ describe("migration v34/v35 — workspaces", () => {
7878
expect(
7979
db.prepare("SELECT share_categories FROM workspaces WHERE name = 'fresh'").get(),
8080
).toEqual({ share_categories: '["CONSTRAINTS"]' });
81-
expect(LATEST_SUPPORTED_VERSION).toBe(37);
82-
expect(LATEST_MIGRATION_VERSION).toBe(37);
81+
expect(LATEST_SUPPORTED_VERSION).toBe(38);
82+
expect(LATEST_MIGRATION_VERSION).toBe(38);
8383
expect(
8484
db
8585
.prepare("SELECT version FROM schema_migrations ORDER BY version DESC LIMIT 1")
8686
.get(),
87-
).toEqual({ version: 37 });
87+
).toEqual({ version: 38 });
8888
} finally {
8989
closeQuietly(db);
9090
}
@@ -215,7 +215,7 @@ describe("migration v34/v35 — workspaces", () => {
215215
db
216216
.prepare("SELECT version FROM schema_migrations ORDER BY version DESC LIMIT 1")
217217
.get(),
218-
).toEqual({ version: 37 });
218+
).toEqual({ version: 38 });
219219
} finally {
220220
closeQuietly(db);
221221
}

packages/plugin/src/features/magic-context/migrations-v36.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ describe("migration v36 — session project ownership", () => {
2929
expect.arrayContaining(["session_id", "harness", "project_path", "updated_at"]),
3030
);
3131
expect(indexNames(db)).toContain("idx_session_projects_project");
32-
expect(LATEST_SUPPORTED_VERSION).toBe(37);
33-
expect(LATEST_MIGRATION_VERSION).toBe(37);
32+
expect(LATEST_SUPPORTED_VERSION).toBe(38);
33+
expect(LATEST_MIGRATION_VERSION).toBe(38);
3434
expect(
3535
db
3636
.prepare("SELECT version FROM schema_migrations ORDER BY version DESC LIMIT 1")
3737
.get(),
38-
).toEqual({ version: 37 });
38+
).toEqual({ version: 38 });
3939
} finally {
4040
closeQuietly(db);
4141
}
@@ -58,7 +58,7 @@ describe("migration v36 — session project ownership", () => {
5858
db
5959
.prepare("SELECT version FROM schema_migrations ORDER BY version DESC LIMIT 1")
6060
.get(),
61-
).toEqual({ version: 37 });
61+
).toEqual({ version: 38 });
6262
} finally {
6363
closeQuietly(db);
6464
}

packages/plugin/src/features/magic-context/migrations-v37.test.ts renamed to packages/plugin/src/features/magic-context/migrations-v38.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ function columnNames(db: Database, table: string): string[] {
1010
);
1111
}
1212

13-
describe("migration v37 — external recall snapshot + m[0] marker", () => {
13+
describe("migration v38 — external recall snapshot + m[0] marker", () => {
1414
test("adds external recall columns to session_meta on a fresh DB, idempotently", () => {
1515
const db = new Database(":memory:");
1616
try {
@@ -40,14 +40,14 @@ describe("migration v37 — external recall snapshot + m[0] marker", () => {
4040
runMigrations(db);
4141

4242
db.prepare("INSERT INTO session_meta (session_id, harness) VALUES (?, ?)").run(
43-
"ses_v37",
43+
"ses_v38",
4444
"test-harness",
4545
);
4646
const row = db
4747
.prepare(
4848
"SELECT external_recall_json, external_recall_state, external_recall_at, cached_m0_external_recall_hash FROM session_meta WHERE session_id = ?",
4949
)
50-
.get("ses_v37") as Record<string, unknown>;
50+
.get("ses_v38") as Record<string, unknown>;
5151

5252
expect(row.external_recall_json).toBeNull();
5353
expect(row.external_recall_state).toBeNull();

packages/plugin/src/features/magic-context/migrations.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1439,9 +1439,10 @@ const MIGRATIONS: Migration[] = [
14391439
{
14401440
// Was v31 on the pre-v0.23 external-memory-backend branch; renumbered
14411441
// to v33 pre-v0.24-rebase, then to v37 when upstream v0.24 shipped its
1442-
// own v33/34/35/36. The body is ensureColumn-idempotent, so a dev DB
1443-
// that already ran it under an old number re-applies harmlessly.
1444-
version: 37,
1442+
// own v33/34/35/36, then to v38 when skill_memory took v37.
1443+
// The body is ensureColumn-idempotent, so a dev DB that already ran it
1444+
// under an old number re-applies harmlessly.
1445+
version: 38,
14451446
description: "External memory v2: session recall snapshot + m[0] recall marker",
14461447
up: (db: Database) => {
14471448
// session_meta existence guard — see v30's comment (partial test fixtures).

packages/plugin/src/features/magic-context/storage-db.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export function getSchemaFenceRejection(): {
3636
return lastSchemaFenceRejection;
3737
}
3838

39-
export const LATEST_SUPPORTED_VERSION = 37;
39+
export const LATEST_SUPPORTED_VERSION = 38;
4040

4141
export interface OpenDatabaseOptions {
4242
dbPath?: string;

0 commit comments

Comments
 (0)