@vaur94/agz-memory 0.4.0-beta.1 → 0.4.0

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.
@@ -1,5 +1,5 @@
1
1
  import * as z from "zod/v4";
2
- export declare const CAPTURE_SCHEMA: "opencode2-memory.capture/1";
2
+ export declare const CAPTURE_SCHEMA: "agz-memory.capture/1";
3
3
  export declare const SUPPORTED_OPENCODE_VERSION: "0.0.0-beta-18743";
4
4
  export declare const CAPTURE_EVENT_MAX_BYTES: number;
5
5
  export declare const CAPTURE_CONTENT_MAX_CHARACTERS = 4800;
@@ -34,7 +34,7 @@ declare const candidateSchema: z.ZodObject<{
34
34
  }>;
35
35
  }, z.core.$strict>;
36
36
  export declare const captureEventSchema: z.ZodObject<{
37
- schema: z.ZodLiteral<"opencode2-memory.capture/1">;
37
+ schema: z.ZodLiteral<"agz-memory.capture/1">;
38
38
  idempotencyKey: z.ZodString;
39
39
  projectID: z.ZodUUID;
40
40
  bindingKey: z.ZodString;
@@ -28,3 +28,4 @@ export * from "./retrieval/contract";
28
28
  export * from "./retrieval/formatter";
29
29
  export * from "./store/capture";
30
30
  export * from "./types";
31
+ export * from "./version";
@@ -1,5 +1,5 @@
1
1
  import { Database } from "bun:sqlite";
2
- export declare const BACKUP_FORMAT: "opencode2-memory-backup/1";
2
+ export declare const BACKUP_FORMAT: "agz-memory-backup/1";
3
3
  export interface BackupManifest {
4
4
  format: typeof BACKUP_FORMAT;
5
5
  productVersion: string;
@@ -0,0 +1,2 @@
1
+ import type { Database } from "bun:sqlite";
2
+ export declare function migrateV9ToV10(db: Database): void;
@@ -1,5 +1,6 @@
1
1
  import type { Database } from "bun:sqlite";
2
- export declare const SCHEMA_V9_TABLES = "\nCREATE TABLE IF NOT EXISTS projects (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n normalized_name TEXT NOT NULL UNIQUE,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n);\nCREATE TABLE IF NOT EXISTS notes (\n id TEXT PRIMARY KEY,\n project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,\n kind TEXT NOT NULL CHECK (kind IN ('decision','fact','procedure','context','research','preference','task')),\n title TEXT NOT NULL,\n summary TEXT NOT NULL,\n content TEXT NOT NULL,\n size_class TEXT NOT NULL CHECK (size_class IN ('inline','indexed')),\n pinned INTEGER NOT NULL DEFAULT 0 CHECK (pinned IN (0,1)),\n status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active','superseded','archived')),\n supersedes_id TEXT,\n current_revision INTEGER NOT NULL DEFAULT 1 CHECK (current_revision >= 1),\n subject_key TEXT,\n content_hash TEXT NOT NULL CHECK (length(content_hash) = 64),\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n UNIQUE(project_id, id)\n);\nCREATE INDEX IF NOT EXISTS notes_project_idx ON notes(project_id, status);\nCREATE UNIQUE INDEX IF NOT EXISTS notes_active_subject_idx\n ON notes(project_id, kind, subject_key)\n WHERE status = 'active' AND subject_key IS NOT NULL;\nCREATE TABLE IF NOT EXISTS note_edges (\n id TEXT PRIMARY KEY,\n project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,\n source_id TEXT NOT NULL,\n target_id TEXT NOT NULL,\n predicate TEXT NOT NULL CHECK (predicate IN ('SUPPORTS','DERIVED_FROM','PART_OF','ABOUT','PRECEDES','SUPERSEDES')),\n created_at INTEGER NOT NULL,\n UNIQUE(project_id, source_id, target_id, predicate),\n FOREIGN KEY (project_id, source_id) REFERENCES notes(project_id, id) ON DELETE CASCADE,\n FOREIGN KEY (project_id, target_id) REFERENCES notes(project_id, id) ON DELETE CASCADE\n);\nCREATE INDEX IF NOT EXISTS note_edges_source_idx ON note_edges(project_id, source_id);\nCREATE INDEX IF NOT EXISTS note_edges_target_idx ON note_edges(project_id, target_id);\nCREATE TABLE IF NOT EXISTS project_bindings (\n binding_key TEXT PRIMARY KEY,\n project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,\n source TEXT NOT NULL CHECK (source = 'opencode-v2'),\n source_project_id TEXT NOT NULL,\n workspace_id TEXT NOT NULL,\n canonical_path_hash TEXT NOT NULL CHECK (length(canonical_path_hash) = 64),\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n UNIQUE(source, source_project_id, workspace_id)\n);\nCREATE TABLE IF NOT EXISTS capture_checkpoints (\n session_id TEXT PRIMARY KEY,\n binding_key TEXT NOT NULL REFERENCES project_bindings(binding_key) ON DELETE CASCADE,\n project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,\n state TEXT NOT NULL CHECK (state IN ('active','idle','unavailable','closed')),\n last_message_id TEXT,\n last_reconciled_at INTEGER,\n next_reconcile_at INTEGER NOT NULL,\n failure_count INTEGER NOT NULL DEFAULT 0 CHECK (failure_count >= 0),\n lease_owner TEXT,\n lease_expires_at INTEGER,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n);\nCREATE INDEX IF NOT EXISTS capture_checkpoints_due_idx\n ON capture_checkpoints(state, next_reconcile_at);\nCREATE TABLE IF NOT EXISTS capture_events (\n idempotency_key TEXT PRIMARY KEY,\n contract TEXT NOT NULL CHECK (contract = 'opencode2-memory.capture/1'),\n project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,\n binding_key TEXT NOT NULL REFERENCES project_bindings(binding_key) ON DELETE CASCADE,\n event_kind TEXT NOT NULL CHECK (event_kind IN ('user-candidate','assistant-candidate','session-summary','tool-signal')),\n source_session_id TEXT NOT NULL,\n source_message_id TEXT,\n source_ordinal INTEGER CHECK (source_ordinal IS NULL OR source_ordinal >= 0),\n source_tool_call_id TEXT,\n payload_json TEXT CHECK (payload_json IS NULL OR json_valid(payload_json)),\n payload_hash TEXT,\n redaction_version TEXT NOT NULL,\n state TEXT NOT NULL CHECK (state IN ('pending','shadowed','review','materialized','duplicate','ignored','rejected','quarantined','failed','dead')),\n attempt_count INTEGER NOT NULL DEFAULT 0 CHECK (attempt_count >= 0),\n note_id TEXT,\n last_error_code TEXT,\n generation INTEGER NOT NULL DEFAULT 0 CHECK (generation >= 0),\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n processed_at INTEGER\n);\nCREATE INDEX IF NOT EXISTS capture_events_state_idx ON capture_events(state, updated_at);\nCREATE INDEX IF NOT EXISTS capture_events_session_idx ON capture_events(project_id, source_session_id);\nCREATE INDEX IF NOT EXISTS capture_events_note_idx ON capture_events(project_id, note_id);\nCREATE TABLE IF NOT EXISTS note_provenance (\n id TEXT PRIMARY KEY,\n project_id TEXT NOT NULL,\n note_id TEXT NOT NULL,\n source_type TEXT NOT NULL CHECK (source_type IN ('mcp-manual','opencode-capture','migration','legacy-import','admin')),\n capture_event_id TEXT,\n source_session_id TEXT,\n source_message_id TEXT,\n source_ordinal INTEGER,\n source_tool_call_id TEXT,\n redaction_version TEXT,\n extractor_version TEXT,\n confidence REAL CHECK (confidence IS NULL OR (confidence >= 0 AND confidence <= 1)),\n created_at INTEGER NOT NULL,\n UNIQUE(project_id, id),\n FOREIGN KEY (project_id, note_id) REFERENCES notes(project_id, id) ON DELETE CASCADE\n);\nCREATE TABLE IF NOT EXISTS note_revisions (\n project_id TEXT NOT NULL,\n note_id TEXT NOT NULL,\n revision INTEGER NOT NULL CHECK (revision >= 1),\n kind TEXT NOT NULL,\n title TEXT NOT NULL,\n summary TEXT NOT NULL,\n content TEXT NOT NULL,\n size_class TEXT NOT NULL,\n pinned INTEGER NOT NULL CHECK (pinned IN (0,1)),\n status TEXT NOT NULL CHECK (status IN ('active','superseded','archived')),\n supersedes_id TEXT,\n subject_key TEXT,\n content_hash TEXT NOT NULL,\n provenance_id TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n PRIMARY KEY(project_id, note_id, revision),\n FOREIGN KEY (project_id, note_id) REFERENCES notes(project_id, id) ON DELETE CASCADE,\n FOREIGN KEY (project_id, provenance_id) REFERENCES note_provenance(project_id, id)\n);\nCREATE TABLE IF NOT EXISTS index_outbox (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n backend TEXT NOT NULL,\n operation TEXT NOT NULL CHECK (operation IN ('upsert-note','delete-note','purge-project')),\n project_id TEXT NOT NULL,\n note_id TEXT,\n revision INTEGER,\n content_hash TEXT,\n state TEXT NOT NULL DEFAULT 'pending' CHECK (state IN ('pending','leased','succeeded','dead')),\n attempt_count INTEGER NOT NULL DEFAULT 0 CHECK (attempt_count >= 0),\n available_at INTEGER NOT NULL,\n lease_owner TEXT,\n lease_expires_at INTEGER,\n last_error_code TEXT,\n created_at INTEGER NOT NULL,\n completed_at INTEGER,\n UNIQUE(backend, operation, project_id, note_id, revision)\n);\nCREATE INDEX IF NOT EXISTS index_outbox_due_idx\n ON index_outbox(backend, project_id, state, available_at, id);\nCREATE TABLE IF NOT EXISTS schema_state (version INTEGER PRIMARY KEY);\n";
2
+ export declare const SCHEMA_TABLES: string;
3
3
  export declare const FTS_V9 = "\nCREATE VIRTUAL TABLE IF NOT EXISTS notes_fts USING fts5(\n title, summary, content,\n content='notes', content_rowid='rowid',\n tokenize='unicode61'\n);\nCREATE TRIGGER IF NOT EXISTS notes_fts_ai AFTER INSERT ON notes BEGIN\n INSERT INTO notes_fts(rowid, title, summary, content)\n VALUES (new.rowid, new.title, new.summary, new.content);\nEND;\nCREATE TRIGGER IF NOT EXISTS notes_fts_ad AFTER DELETE ON notes BEGIN\n INSERT INTO notes_fts(notes_fts, rowid, title, summary, content)\n VALUES ('delete', old.rowid, old.title, old.summary, old.content);\nEND;\nCREATE TRIGGER IF NOT EXISTS notes_fts_au AFTER UPDATE OF title, summary, content ON notes BEGIN\n INSERT INTO notes_fts(notes_fts, rowid, title, summary, content)\n VALUES ('delete', old.rowid, old.title, old.summary, old.content);\n INSERT INTO notes_fts(rowid, title, summary, content)\n VALUES (new.rowid, new.title, new.summary, new.content);\nEND;\n";
4
- export declare function createSchemaV9(db: Database): void;
4
+ export declare function createSchema(db: Database): void;
5
5
  export declare function rebuildFts(db: Database): void;
6
+ export declare function captureEventsTable(table?: "capture_events" | "capture_events_v10"): string;
@@ -1,5 +1,5 @@
1
1
  import { McpServer } from "@modelcontextprotocol/server";
2
2
  import type { MemoryStore } from "./store";
3
3
  export declare const SERVER_NAME = "agz-memory";
4
- export declare const SERVER_VERSION = "0.4.0-beta.1";
4
+ export declare const SERVER_VERSION: "0.4.0";
5
5
  export declare function createMemoryServer(store: MemoryStore): McpServer;
@@ -37,6 +37,11 @@ export declare class CaptureStore {
37
37
  deleted: number;
38
38
  checkpoints: number;
39
39
  };
40
+ runRetentionBacklog(now?: number, batchSize?: number, maxBatches?: number): {
41
+ summarized: number;
42
+ deleted: number;
43
+ checkpoints: number;
44
+ };
40
45
  private materialize;
41
46
  private insertCapturedNote;
42
47
  private recordRevision;
@@ -1,4 +1,4 @@
1
- export declare const SCHEMA_VERSION = 9;
1
+ export declare const SCHEMA_VERSION = 10;
2
2
  export declare const INLINE_LIMIT = 1200;
3
3
  export declare const KINDS: readonly ["decision", "fact", "procedure", "context", "research", "preference", "task"];
4
4
  export type Kind = (typeof KINDS)[number];
@@ -0,0 +1 @@
1
+ export declare const PRODUCT_VERSION: "0.4.0";
@@ -1,73 +1,149 @@
1
- # Backup And Restore Runbook
1
+ # AGZ Memory Backup And Restore Runbook
2
2
 
3
- ## Preconditions
3
+ English | [Türkçe](backup-restore-runbook.tr.md)
4
+
5
+ This runbook applies to `@vaur94/agz-memory@0.4.0` and SQLite schema v10.
4
6
 
5
- 1. Record `OPENCODE_MEMORY_DATABASE_PATH`.
6
- 2. Disable the OpenCode memory plugin or keep it in `off` mode.
7
- 3. Stop every MCP/plugin process that can write the database. Version `0.3.0`
8
- does not understand the v9 migration lock.
9
- 4. Confirm the database and backup directory are owned by the current user.
7
+ ## Preconditions
10
8
 
11
- ## Upgrade To Schema V9
9
+ 1. Export the exact production database path.
10
+ 2. Set the plugin to `mode: "off"` and `capture.enabled: false`.
11
+ 3. Stop every MCP, plugin, or admin process that can write the database.
12
+ 4. Confirm that the database directory and backup directory are owned by the
13
+ current user and are not symlinks.
14
+ 5. Keep enough free space for the database, its WAL checkpoint, one verified
15
+ backup, and one preserved restore source.
12
16
 
13
17
  ```sh
14
18
  export OPENCODE_MEMORY_DATABASE_PATH="$HOME/.local/share/opencode-memory/memory.sqlite"
19
+ ```
20
+
21
+ Do not proceed with a guessed or empty path.
22
+
23
+ ## Health Check And Upgrade
24
+
25
+ Run a read-only health report first:
26
+
27
+ ```sh
28
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin doctor
29
+ ```
30
+
31
+ `ok` must be `true`. Record `schemaVersion`, row counts, and invariant counts.
32
+ Then create a standalone verified backup and upgrade:
33
+
34
+ ```sh
35
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin backup
36
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin upgrade --to 10
37
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin doctor
38
+ ```
39
+
40
+ The upgrade itself creates another verified pre-migration backup when the
41
+ database schema is older than v10. Preserve each printed manifest path and
42
+ SHA-256. Do not start a writer if the final report has `ok: false`.
43
+
44
+ ## Verify A Backup
15
45
 
16
- bunx --package @vaur94/agz-memory@0.4.0-beta.1 agz-memory-admin doctor
17
- bunx --package @vaur94/agz-memory@0.4.0-beta.1 agz-memory-admin backup
18
- bunx --package @vaur94/agz-memory@0.4.0-beta.1 agz-memory-admin upgrade --to 9
19
- bunx --package @vaur94/agz-memory@0.4.0-beta.1 agz-memory-admin doctor
46
+ A backup pair lives under `<database>.backup/`:
47
+
48
+ ```text
49
+ schema-vN-<timestamp>-<uuid>.sqlite
50
+ schema-vN-<timestamp>-<uuid>.manifest.json
20
51
  ```
21
52
 
22
- Do not start a writer if the final doctor report has `ok: false`. Preserve the
23
- manifest path and SHA-256 printed by `backup`.
53
+ The manifest format is `agz-memory-backup/1`. `agz-memory-admin restore` verifies
54
+ that the manifest and database are regular files in the same backup directory,
55
+ then checks size, SHA-256, SQLite integrity, foreign keys, and row counts.
56
+
57
+ Final `0.4.0` does not accept prerelease manifest formats. Use the originating
58
+ prerelease to restore such a backup, run its doctor check, and only then upgrade
59
+ that restored database with `0.4.0`.
24
60
 
25
61
  ## Restore Rehearsal
26
62
 
27
- The first invocation is a dry run:
63
+ Keep all writers stopped. First request a dry run by omitting confirmation:
28
64
 
29
65
  ```sh
30
- bunx --package @vaur94/agz-memory@0.4.0-beta.1 agz-memory-admin restore \
66
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin restore \
31
67
  "$OPENCODE_MEMORY_DATABASE_PATH.backup/<backup>.manifest.json"
32
68
  ```
33
69
 
34
- Verify `targetPath`, `sourceSchema`, row counts, and `sha256`. Then run:
70
+ Compare `targetPath`, `sourceSchema`, `targetSchema`, row counts, size, and
71
+ SHA-256 with the recorded backup. Then use the exact manifest hash:
35
72
 
36
73
  ```sh
37
- bunx --package @vaur94/agz-memory@0.4.0-beta.1 agz-memory-admin restore \
74
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin restore \
38
75
  "$OPENCODE_MEMORY_DATABASE_PATH.backup/<backup>.manifest.json" \
39
76
  --sha256 <manifest-database-sha256> \
40
77
  --confirm RESTORE_DATABASE_FROM_VERIFIED_BACKUP
41
78
  ```
42
79
 
43
- The prior database is retained as `failed-restore-source-*`. Run `doctor` and a
44
- read-only MCP `project_list`/`memory_recall` smoke before enabling writers.
80
+ Restore installs a copied and verified database atomically. The replaced source
81
+ is retained as `failed-restore-source-*`; do not delete it until the restored
82
+ database passes all checks.
83
+
84
+ ## Post-Restore Validation
85
+
86
+ ```sh
87
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin doctor
88
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin capture status
89
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin outbox status
90
+ ```
91
+
92
+ Start only the MCP server and perform read-only `project_list`, `memory_recall`,
93
+ and `memory_read` smoke calls. Compare project/note counts with the manifest.
94
+ Only after those checks pass should OpenCode be restarted. Keep the plugin in
95
+ `off` until a separate rollout decision is made.
45
96
 
46
97
  ## Stale Migration Lock
47
98
 
48
- Inspect `<database>.migration.lock/owner.json`. Never break a live owner.
99
+ The lock is `<database>.migration.lock/owner.json`. Never remove it while the
100
+ recorded process is alive or any writer may still hold the database.
101
+
102
+ Inspect the owner file, verify the PID/host/start time, and request a dry-run
103
+ style error first if uncertain. Break only a proven stale lock with the exact
104
+ owner ID and confirmation:
49
105
 
50
106
  ```sh
51
- bunx --package @vaur94/agz-memory@0.4.0-beta.1 agz-memory-admin unlock \
52
- --owner <exact-owner-id> \
107
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin unlock \
108
+ --owner <owner-id> \
53
109
  --confirm BREAK_STALE_MIGRATION_LOCK
54
110
  ```
55
111
 
56
- The command refuses a live process with the same process-start marker.
57
- If `owner.json` is missing or unreadable, inspect the lock directory first and
58
- use `--owner ORPHANED` with the same confirmation phrase. Never use this while
59
- another migration process may still be starting.
112
+ Run `doctor` immediately afterward. A stale lock is evidence of an interrupted
113
+ operation; it is not permission to skip database validation.
60
114
 
61
- ## Backup Pruning
115
+ ## Prune Verified Backups
62
116
 
63
- Pruning is dry-run by default and returns a digest:
117
+ The first command is non-destructive and returns a digest over the exact backup
118
+ set:
64
119
 
65
120
  ```sh
66
- bunx --package @vaur94/agz-memory@0.4.0-beta.1 agz-memory-admin backup prune
67
- bunx --package @vaur94/agz-memory@0.4.0-beta.1 agz-memory-admin backup prune \
121
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin backup prune
122
+ ```
123
+
124
+ Review every listed manifest/database pair. Delete only that unchanged set:
125
+
126
+ ```sh
127
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin backup prune \
68
128
  --digest <dry-run-digest> \
69
129
  --confirm DELETE_VERIFIED_BACKUPS
70
130
  ```
71
131
 
72
- Do not prune the last known-good pre-upgrade backup until migration and restore
73
- rehearsals are complete.
132
+ The command refuses deletion when any manifest, database, hash, size, or set
133
+ membership changed after the dry run. Keep at least one separately protected,
134
+ recent, restore-tested backup according to your retention policy.
135
+
136
+ ## Abort Conditions
137
+
138
+ Stop and investigate if any of these occur:
139
+
140
+ - `doctor` returns `ok: false`.
141
+ - SQLite integrity or foreign-key checks fail.
142
+ - Backup row counts differ from the source.
143
+ - A migration lock owner may still be live.
144
+ - The manifest is outside the configured backup root or is a symlink.
145
+ - The restore SHA-256 differs from the dry run.
146
+ - The final project/note counts differ from the chosen backup.
147
+
148
+ Do not repair the only copy in place. Preserve the database, WAL/SHM sidecars,
149
+ lock directory, manifests, and command output before further diagnosis.
@@ -0,0 +1,148 @@
1
+ # AGZ Memory Yedekleme Ve Geri Yükleme Runbook'u
2
+
3
+ [English](backup-restore-runbook.md) | Türkçe
4
+
5
+ Bu runbook `@vaur94/agz-memory@0.4.0` ve SQLite schema v10 için geçerlidir.
6
+
7
+ ## Ön Koşullar
8
+
9
+ 1. Üretim veritabanının tam yolunu dışa aktarın.
10
+ 2. Eklentiyi `mode: "off"` ve `capture.enabled: false` durumuna getirin.
11
+ 3. Veritabanına yazabilen tüm MCP, eklenti ve yönetim süreçlerini durdurun.
12
+ 4. Veritabanı ve yedek dizinlerinin güncel kullanıcıya ait olduğunu ve sembolik
13
+ bağ olmadığını doğrulayın.
14
+ 5. Veritabanı, WAL kontrol noktası, bir doğrulanmış yedek ve bir korunmuş geri
15
+ yükleme kaynağı için yeterli boş alan bırakın.
16
+
17
+ ```sh
18
+ export OPENCODE_MEMORY_DATABASE_PATH="$HOME/.local/share/opencode-memory/memory.sqlite"
19
+ ```
20
+
21
+ Tahmin edilmiş veya boş bir yolla devam etmeyin.
22
+
23
+ ## Sağlık Kontrolü Ve Yükseltme
24
+
25
+ Önce salt-okunur sağlık raporu alın:
26
+
27
+ ```sh
28
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin doctor
29
+ ```
30
+
31
+ `ok` değeri `true` olmalıdır. `schemaVersion`, satır sayıları ve değişmez kural
32
+ sayılarını kaydedin. Sonra bağımsız doğrulanmış yedek oluşturup yükseltin:
33
+
34
+ ```sh
35
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin backup
36
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin upgrade --to 10
37
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin doctor
38
+ ```
39
+
40
+ Veritabanı v10'dan eskiyse yükseltme ayrıca değişiklikten önce doğrulanmış yedek
41
+ oluşturur. Yazdırılan her manifest yolunu ve SHA-256 değerini saklayın. Son rapor
42
+ `ok: false` ise yazıcı başlatmayın.
43
+
44
+ ## Yedeği Doğrulama
45
+
46
+ Yedek çifti `<database>.backup/` altında bulunur:
47
+
48
+ ```text
49
+ schema-vN-<timestamp>-<uuid>.sqlite
50
+ schema-vN-<timestamp>-<uuid>.manifest.json
51
+ ```
52
+
53
+ Manifest formatı `agz-memory-backup/1` olur. `agz-memory-admin restore`, manifest
54
+ ile veritabanının aynı yedek dizinindeki normal dosyalar olduğunu doğrular;
55
+ ardından boyut, SHA-256, SQLite bütünlüğü, foreign key ve satır sayılarını denetler.
56
+
57
+ Final `0.4.0` ön sürüm manifest formatlarını kabul etmez. Böyle bir yedeği onu
58
+ oluşturan ön sürümle geri yükleyin, o sürümün doctor kontrolünü çalıştırın ve
59
+ yalnız bundan sonra geri yüklenen veritabanını `0.4.0` ile yükseltin.
60
+
61
+ ## Geri Yükleme Provası
62
+
63
+ Tüm yazıcıları kapalı tutun. Önce onay vermeden deneme yapın:
64
+
65
+ ```sh
66
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin restore \
67
+ "$OPENCODE_MEMORY_DATABASE_PATH.backup/<backup>.manifest.json"
68
+ ```
69
+
70
+ `targetPath`, `sourceSchema`, `targetSchema`, satır sayıları, boyut ve SHA-256
71
+ değerlerini kaydedilen yedekle karşılaştırın. Sonra tam manifest özetini kullanın:
72
+
73
+ ```sh
74
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin restore \
75
+ "$OPENCODE_MEMORY_DATABASE_PATH.backup/<backup>.manifest.json" \
76
+ --sha256 <manifest-database-sha256> \
77
+ --confirm RESTORE_DATABASE_FROM_VERIFIED_BACKUP
78
+ ```
79
+
80
+ Geri yükleme kopyalanmış ve doğrulanmış veritabanını atomik olarak kurar.
81
+ Değiştirilen kaynak `failed-restore-source-*` adıyla korunur; geri yüklenen
82
+ veritabanı tüm kontrollerden geçmeden bunu silmeyin.
83
+
84
+ ## Geri Yükleme Sonrası Doğrulama
85
+
86
+ ```sh
87
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin doctor
88
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin capture status
89
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin outbox status
90
+ ```
91
+
92
+ Yalnız MCP sunucusunu başlatın ve salt-okunur `project_list`, `memory_recall` ve
93
+ `memory_read` denemeleri yapın. Proje/not sayılarını manifestle karşılaştırın.
94
+ OpenCode'u ancak bu kontroller geçince yeniden başlatın. Ayrı devreye alma kararı
95
+ verilene kadar eklentiyi `off` tutun.
96
+
97
+ ## Eski Geçiş Kilidi
98
+
99
+ Kilit `<database>.migration.lock/owner.json` konumundadır. Kayıtlı süreç yaşıyor
100
+ olabilirken veya bir yazıcı veritabanını tutarken kilidi kaldırmayın.
101
+
102
+ Sahip dosyasındaki PID, makine ve başlangıç zamanını doğrulayın. Yalnız eskidiği
103
+ kanıtlanan kilidi tam sahip ID'si ve onayla kırın:
104
+
105
+ ```sh
106
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin unlock \
107
+ --owner <owner-id> \
108
+ --confirm BREAK_STALE_MIGRATION_LOCK
109
+ ```
110
+
111
+ Hemen ardından `doctor` çalıştırın. Eski kilit kesintiye uğramış işlemin
112
+ kanıtıdır; veritabanı doğrulamasını atlama izni değildir.
113
+
114
+ ## Doğrulanmış Yedekleri Temizleme
115
+
116
+ İlk komut silme yapmaz ve tam yedek kümesinin özetini döndürür:
117
+
118
+ ```sh
119
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin backup prune
120
+ ```
121
+
122
+ Listelenen her manifest/veritabanı çiftini inceleyin. Yalnız değişmemiş kümeyi
123
+ silin:
124
+
125
+ ```sh
126
+ bunx --package @vaur94/agz-memory@0.4.0 agz-memory-admin backup prune \
127
+ --digest <dry-run-digest> \
128
+ --confirm DELETE_VERIFIED_BACKUPS
129
+ ```
130
+
131
+ Manifest, veritabanı, özet, boyut veya küme üyeliği denemeden sonra değişirse
132
+ komut silmeyi reddeder. Saklama politikanıza göre ayrıca korunan, yakın tarihli
133
+ ve geri yüklemesi denenmiş en az bir yedek tutun.
134
+
135
+ ## İptal Koşulları
136
+
137
+ Şunlardan biri olursa durun ve inceleyin:
138
+
139
+ - `doctor` sonucu `ok: false` olur.
140
+ - SQLite bütünlük veya foreign key kontrolü başarısız olur.
141
+ - Yedek satır sayıları kaynakla uyuşmaz.
142
+ - Geçiş kilidi sahibi hâlâ yaşıyor olabilir.
143
+ - Manifest yapılandırılan yedek kökü dışındadır veya sembolik bağdır.
144
+ - Geri yükleme SHA-256 değeri deneme çıktısından farklıdır.
145
+ - Son proje/not sayıları seçilen yedekle uyuşmaz.
146
+
147
+ Tek kopyayı yerinde onarmayın. İleri incelemeden önce veritabanını, WAL/SHM yan
148
+ dosyalarını, kilit dizinini, manifestleri ve komut çıktısını koruyun.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaur94/agz-memory",
3
- "version": "0.4.0-beta.1",
3
+ "version": "0.4.0",
4
4
  "description": "Project-scoped persistent linked memory MCP server for OpenCode V2",
5
5
  "type": "module",
6
6
  "main": "./dist/server.js",
@@ -25,6 +25,7 @@
25
25
  "ARCHITECTURE.md",
26
26
  "CHANGELOG.md",
27
27
  "docs/backup-restore-runbook.md",
28
+ "docs/backup-restore-runbook.tr.md",
28
29
  "LICENSE"
29
30
  ],
30
31
  "scripts": {
@@ -33,7 +34,8 @@
33
34
  "check": "bunx tsc --noEmit && bun run types && bun run --cwd packages/opencode-plugin check",
34
35
  "test": "bun test",
35
36
  "benchmark": "bun benchmark/run.ts",
36
- "prepack": "bun run check && bun run test && bun run build"
37
+ "release:verify": "bun scripts/verify-release.ts",
38
+ "prepack": "bun run release:verify && bun run check && bun run test && bun run build"
37
39
  },
38
40
  "engines": {
39
41
  "bun": ">=1.3.14"