@orquentra/codebuddy 2.15.0 → 2.15.3
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/ARCHITECTURE.md +12 -7
- package/README.md +2 -2
- package/dist/{chunk-YMXFSHXT.js → chunk-3L5IR6OW.js} +2 -2
- package/dist/{chunk-YMXFSHXT.js.map → chunk-3L5IR6OW.js.map} +1 -1
- package/dist/{chunk-JJQDVGF7.js → chunk-3TZNQJTH.js} +3 -3
- package/dist/{chunk-4BSO3HST.js → chunk-4LMBZWIF.js} +48 -13
- package/dist/chunk-4LMBZWIF.js.map +1 -0
- package/dist/{chunk-WHKXUXHE.js → chunk-4TKKLQLH.js} +5 -5
- package/dist/chunk-4TKKLQLH.js.map +1 -0
- package/dist/{chunk-KQCP3ZYH.js → chunk-5ZLNHYJH.js} +31 -15
- package/dist/chunk-5ZLNHYJH.js.map +1 -0
- package/dist/{chunk-U7KDM62P.js → chunk-6KSSJJZO.js} +17 -9
- package/dist/chunk-6KSSJJZO.js.map +1 -0
- package/dist/{chunk-6YI2D5F5.js → chunk-7IXPARDM.js} +3 -3
- package/dist/{chunk-UTPC66MV.js → chunk-FEFOZ2ZW.js} +23 -4
- package/dist/chunk-FEFOZ2ZW.js.map +1 -0
- package/dist/{chunk-ITXE27SZ.js → chunk-FGJ2KPPN.js} +104 -22
- package/dist/chunk-FGJ2KPPN.js.map +1 -0
- package/dist/{chunk-D5E7SGI5.js → chunk-KGDRGA2L.js} +14 -14
- package/dist/{chunk-D5E7SGI5.js.map → chunk-KGDRGA2L.js.map} +1 -1
- package/dist/{chunk-UR3DF74I.js → chunk-LZTYPJ5I.js} +36 -18
- package/dist/chunk-LZTYPJ5I.js.map +1 -0
- package/dist/{chunk-UATJCD2T.js → chunk-R5E2YGLE.js} +14 -8
- package/dist/chunk-R5E2YGLE.js.map +1 -0
- package/dist/chunk-R5JRKMEP.js +55 -0
- package/dist/chunk-R5JRKMEP.js.map +1 -0
- package/dist/{chunk-RZ266NHE.js → chunk-SPQU2422.js} +5 -5
- package/dist/{chunk-RZ266NHE.js.map → chunk-SPQU2422.js.map} +1 -1
- package/dist/{chunk-BTTQWSDS.js → chunk-SXVH74NE.js} +36 -6
- package/dist/chunk-SXVH74NE.js.map +1 -0
- package/dist/{chunk-KYRM3HPP.js → chunk-TIMS3PB7.js} +3 -3
- package/dist/{chunk-M75SN4D4.js → chunk-Y4QQML24.js} +3 -3
- package/dist/{chunk-M75SN4D4.js.map → chunk-Y4QQML24.js.map} +1 -1
- package/dist/cli/index.js +4 -4
- package/dist/{config-TXQJCCVI.js → config-32X53LWY.js} +4 -4
- package/dist/{expand-KWYGNCKZ.js → expand-VFYOWNZS.js} +5 -5
- package/dist/{file-vectors-MKXTSGGH.js → file-vectors-UBOKGYXX.js} +4 -3
- package/dist/{index-facts-4MTEHKMN.js → index-facts-ZTUANWBF.js} +7 -7
- package/dist/index-pass-S6NC25P5.js +15 -0
- package/dist/index.js +9 -8
- package/dist/{install-E3JWINTN.js → install-ZTE3H7QM.js} +8 -7
- package/dist/{lean-MLTAFS5L.js → lean-5N6BOONS.js} +5 -4
- package/dist/{local-75DJECVR.js → local-5EYLEBEP.js} +4 -2
- package/dist/{local-llm-MECVJTVU.js → local-llm-ESMVP5LE.js} +4 -4
- package/dist/{main-RLMKQZW4.js → main-B3HZCGVE.js} +61 -50
- package/dist/main-B3HZCGVE.js.map +1 -0
- package/dist/{memory-PFFVMTCH.js → memory-CI7HIGHN.js} +5 -5
- package/dist/{operations-STR7S5UO.js → operations-MW52HIQ3.js} +4 -4
- package/dist/{rerank-XXKWDI5Q.js → rerank-O4S5BC45.js} +5 -5
- package/dist/{runtime-SWFWGTQ4.js → runtime-SZAWIXEB.js} +6 -5
- package/dist/{summaries-QXWFFDUZ.js → summaries-GCHZGIIA.js} +11 -8
- package/dist/{zvec-F73IBWO5.js → zvec-V34P24WF.js} +11 -6
- package/package.json +1 -1
- package/dist/chunk-4BSO3HST.js.map +0 -1
- package/dist/chunk-BTTQWSDS.js.map +0 -1
- package/dist/chunk-ITXE27SZ.js.map +0 -1
- package/dist/chunk-KQCP3ZYH.js.map +0 -1
- package/dist/chunk-U7KDM62P.js.map +0 -1
- package/dist/chunk-UATJCD2T.js.map +0 -1
- package/dist/chunk-UR3DF74I.js.map +0 -1
- package/dist/chunk-UTPC66MV.js.map +0 -1
- package/dist/chunk-WHKXUXHE.js.map +0 -1
- package/dist/index-pass-TBDUEZCB.js +0 -14
- package/dist/main-RLMKQZW4.js.map +0 -1
- /package/dist/{chunk-JJQDVGF7.js.map → chunk-3TZNQJTH.js.map} +0 -0
- /package/dist/{chunk-6YI2D5F5.js.map → chunk-7IXPARDM.js.map} +0 -0
- /package/dist/{chunk-KYRM3HPP.js.map → chunk-TIMS3PB7.js.map} +0 -0
- /package/dist/{config-TXQJCCVI.js.map → config-32X53LWY.js.map} +0 -0
- /package/dist/{expand-KWYGNCKZ.js.map → expand-VFYOWNZS.js.map} +0 -0
- /package/dist/{file-vectors-MKXTSGGH.js.map → file-vectors-UBOKGYXX.js.map} +0 -0
- /package/dist/{index-facts-4MTEHKMN.js.map → index-facts-ZTUANWBF.js.map} +0 -0
- /package/dist/{index-pass-TBDUEZCB.js.map → index-pass-S6NC25P5.js.map} +0 -0
- /package/dist/{install-E3JWINTN.js.map → install-ZTE3H7QM.js.map} +0 -0
- /package/dist/{lean-MLTAFS5L.js.map → lean-5N6BOONS.js.map} +0 -0
- /package/dist/{local-75DJECVR.js.map → local-5EYLEBEP.js.map} +0 -0
- /package/dist/{local-llm-MECVJTVU.js.map → local-llm-ESMVP5LE.js.map} +0 -0
- /package/dist/{memory-PFFVMTCH.js.map → memory-CI7HIGHN.js.map} +0 -0
- /package/dist/{operations-STR7S5UO.js.map → operations-MW52HIQ3.js.map} +0 -0
- /package/dist/{rerank-XXKWDI5Q.js.map → rerank-O4S5BC45.js.map} +0 -0
- /package/dist/{runtime-SWFWGTQ4.js.map → runtime-SZAWIXEB.js.map} +0 -0
- /package/dist/{summaries-QXWFFDUZ.js.map → summaries-GCHZGIIA.js.map} +0 -0
- /package/dist/{zvec-F73IBWO5.js.map → zvec-V34P24WF.js.map} +0 -0
package/ARCHITECTURE.md
CHANGED
|
@@ -130,7 +130,7 @@ four criteria in the 2.15 brief:
|
|
|
130
130
|
Cactus has no maintained Node.js binding for a desktop/server process, and its
|
|
131
131
|
Node package hosts only the Needle tool-calling model, which the brief excludes
|
|
132
132
|
(the job is plain English → code vocabulary, not tool selection). So
|
|
133
|
-
node-llama-cpp. It is not a package dependency: `codebuddy
|
|
133
|
+
node-llama-cpp. It is not a package dependency: `codebuddy` (or
|
|
134
134
|
`codebuddy models add local-llm`) installs it with `npm -g` and downloads the pinned GGUF into
|
|
135
135
|
`~/.cache/codebuddy/models/gguf/`, checking size and sha256 before moving it
|
|
136
136
|
into place. Forcing `gpu: false` on macOS makes node-llama-cpp compile llama.cpp
|
|
@@ -168,12 +168,17 @@ setup only when a provider key is already in the environment.
|
|
|
168
168
|
**Cards** extend the existing `llm-summaries.json` store (prompt version 2), so
|
|
169
169
|
the BYOK and local backends fill the same cache. Each card is used three ways:
|
|
170
170
|
a card vector per file in `file-vectors.json` (granite, next to the chunk
|
|
171
|
-
vectors), one Markdown file per source file in
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
171
|
+
vectors), one Markdown file per source file in its own zvec-grep workspace
|
|
172
|
+
(English model `local/bge-small-en-v1.5`, `--no-ignore`), and card terms and
|
|
173
|
+
symptoms in the content index at half weight. Since 2.15.2 the card workspace is
|
|
174
|
+
`~/.cache/codebuddy/cards/<sha256(repo root), 16 hex>/` (`CODEBUDDY_CARD_CACHE`
|
|
175
|
+
overrides the base): zg resolves any folder under an indexed repository to the
|
|
176
|
+
repository's workspace, so the earlier in-repo `.codebuddy/cache/cards/` could
|
|
177
|
+
never get its own index (model mismatch) and indexing it re-pointed the code
|
|
178
|
+
index's roots.
|
|
179
|
+
|
|
180
|
+
**Agreement rule** (`context/discovery.ts`; floors re-calibrated in 2.15.2 on
|
|
181
|
+
`evals/agreement-calibration-litestar.json`, see the `AGREEMENT` comment). 2.14 dropped every vector hit
|
|
177
182
|
outside the keyword set unless it shared task terms with the source and cleared
|
|
178
183
|
`zvec.minScore`. That deleted exactly the hits a reworded task needs. In 2.15 a
|
|
179
184
|
candidate is admitted when at least two signals put it in their top k (default
|
package/README.md
CHANGED
|
@@ -79,7 +79,7 @@ installation fails, include the exact npm error and requested version in a
|
|
|
79
79
|
A small local model can write a plain-English **intent card** for every source
|
|
80
80
|
file, so a task worded nothing like the code (for example "the browser forgets
|
|
81
81
|
how long to wait before reconnecting") still finds the right file. `codebuddy`
|
|
82
|
-
/ `codebuddy
|
|
82
|
+
/ `codebuddy` installs it as part of setup (Qwen3-0.6B Q4_K_M, ~400 MB,
|
|
83
83
|
checksum-verified; skip with `--no-local-llm` or `CODEBUDDY_LOCAL_LLM=0`), and it
|
|
84
84
|
runs offline after that. To manage it by hand:
|
|
85
85
|
|
|
@@ -127,7 +127,7 @@ the 2.14 behaviour.
|
|
|
127
127
|
shows them and `codebuddy memory prune --origin index` removes them. Facts a
|
|
128
128
|
person or agent wrote are never replaced.
|
|
129
129
|
|
|
130
|
-
`codebuddy
|
|
130
|
+
`codebuddy` also builds the zvec-grep index and enables it when `zg` 0.2.x
|
|
131
131
|
is installed, and `codebuddy serve` keeps a `zg server` running so the prompt
|
|
132
132
|
hook gets vector candidates within its deadline.
|
|
133
133
|
|
|
@@ -497,7 +497,7 @@ var MEMORY_CONCEPT_SCORE = 0.5;
|
|
|
497
497
|
// package.json
|
|
498
498
|
var package_default = {
|
|
499
499
|
name: "@orquentra/codebuddy",
|
|
500
|
-
version: "2.15.
|
|
500
|
+
version: "2.15.3",
|
|
501
501
|
description: "CodeBuddy by Orquentra: local-first MCP server and CLI for project context and durable memory in Claude Code, Codex, and other AI coding agents.",
|
|
502
502
|
type: "module",
|
|
503
503
|
license: "MIT",
|
|
@@ -1039,4 +1039,4 @@ export {
|
|
|
1039
1039
|
INCIDENT_SEVERITIES,
|
|
1040
1040
|
MemoryFileStore
|
|
1041
1041
|
};
|
|
1042
|
-
//# sourceMappingURL=chunk-
|
|
1042
|
+
//# sourceMappingURL=chunk-3L5IR6OW.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/db/schema.ts","../src/core/memory-search.ts","../package.json","../src/version.ts","../src/core/memory-file-store.ts","../src/core/memory-lifecycle.ts"],"sourcesContent":["import { sql } from \"drizzle-orm\";\nimport {\n boolean,\n customType,\n index,\n integer,\n jsonb,\n numeric,\n pgEnum,\n pgTable,\n text,\n timestamp,\n uniqueIndex,\n} from \"drizzle-orm/pg-core\";\n\nexport const VECTOR_DIMENSIONS = 384;\nexport const HNSW_M = 16;\nexport const HNSW_EF_CONSTRUCTION = 64;\n\nconst vector = customType<{ data: string; driverData: string }>({\n dataType() {\n return `vector(${VECTOR_DIMENSIONS})`;\n },\n});\n\nexport const memoryTypeEnum = pgEnum(\"memory_type\", [\"interaction\", \"fact\", \"summary\"]);\nexport const interactionRoleEnum = pgEnum(\"interaction_role\", [\"user\", \"assistant\", \"system\"]);\nexport const embeddingOwnerTypeEnum = pgEnum(\"embedding_owner_type\", [\n \"interaction\",\n \"fact\",\n \"summary\",\n]);\nexport const embeddingStatusEnum = pgEnum(\"embedding_status\", [\n \"pending\",\n \"processing\",\n \"ready\",\n \"failed\",\n]);\nexport const shareModeEnum = pgEnum(\"share_mode\", [\"reference\", \"snapshot\"]);\nexport const modelCallTypeEnum = pgEnum(\"model_call_type\", [\"embedding\", \"llm\"]);\nexport const modelCallStatusEnum = pgEnum(\"model_call_status\", [\n \"success\",\n \"failed\",\n \"timeout\",\n \"rate_limited\",\n \"gated\",\n \"fallback\",\n]);\nexport const auditActionEnum = pgEnum(\"audit_action\", [\n \"remember\",\n \"remember_batch\",\n \"share\",\n \"forget\",\n \"config\",\n]);\n\nconst createdAt = timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow();\nconst updatedAt = timestamp(\"updated_at\", { withTimezone: true }).notNull().defaultNow();\n\nexport const namespaces = pgTable(\n \"namespaces\",\n {\n id: text(\"id\").primaryKey(),\n name: text(\"name\").notNull(),\n createdAt,\n updatedAt,\n },\n (table) => ({\n nameUnique: uniqueIndex(\"namespaces_name_unique\").on(table.name),\n }),\n);\n\nexport const interactions = pgTable(\n \"interactions\",\n {\n id: text(\"id\").primaryKey(),\n namespaceId: text(\"namespace_id\")\n .notNull()\n .references(() => namespaces.id, { onDelete: \"cascade\" }),\n sessionId: text(\"session_id\").notNull(),\n role: interactionRoleEnum(\"role\").notNull().default(\"user\"),\n content: text(\"content\").notNull(),\n contentHash: text(\"content_hash\").notNull(),\n tokenCount: integer(\"token_count\").notNull().default(0),\n createdByAgent: text(\"created_by_agent\"),\n createdAt,\n },\n (table) => ({\n namespaceContentHashUnique: uniqueIndex(\"interactions_namespace_content_hash_unique\").on(\n table.namespaceId,\n table.contentHash,\n ),\n namespaceSessionCreatedIdx: index(\"interactions_namespace_session_created_idx\").on(\n table.namespaceId,\n table.sessionId,\n table.createdAt,\n ),\n }),\n);\n\nexport const sessionSummaries = pgTable(\n \"session_summaries\",\n {\n id: text(\"id\").primaryKey(),\n namespaceId: text(\"namespace_id\")\n .notNull()\n .references(() => namespaces.id, { onDelete: \"cascade\" }),\n sessionId: text(\"session_id\").notNull(),\n content: text(\"content\").notNull(),\n version: integer(\"version\").notNull().default(1),\n tokenCount: integer(\"token_count\").notNull().default(0),\n createdByAgent: text(\"created_by_agent\"),\n /** See facts.fileBacked. */\n fileBacked: boolean(\"file_backed\").notNull().default(false),\n createdAt,\n },\n (table) => ({\n namespaceSessionVersionIdx: index(\"session_summaries_namespace_session_version_idx\").on(\n table.namespaceId,\n table.sessionId,\n table.version,\n ),\n }),\n);\n\nexport const facts = pgTable(\n \"facts\",\n {\n id: text(\"id\").primaryKey(),\n namespaceId: text(\"namespace_id\")\n .notNull()\n .references(() => namespaces.id, { onDelete: \"cascade\" }),\n subject: text(\"subject\").notNull(),\n predicate: text(\"predicate\").notNull(),\n object: text(\"object\").notNull(),\n propositionKey: text(\"proposition_key\"),\n /** Kept apart from content_hash so a reindex (which recomputes the hash) keeps it. */\n idempotencyKey: text(\"idempotency_key\"),\n content: text(\"content\").notNull(),\n contentHash: text(\"content_hash\").notNull(),\n confidence: numeric(\"confidence\", { precision: 5, scale: 4 }).notNull().default(\"1\"),\n /**\n * Historical provenance only — deliberately not a foreign key. Interactions\n * are ephemeral DB rows; Markdown facts must re-import after a rebuild that\n * lost them, and the ID must survive so `sourceDeleted` can be tracked.\n */\n sourceInteractionId: text(\"source_interaction_id\"),\n sourceDeleted: boolean(\"source_deleted\").notNull().default(false),\n supersededBy: text(\"superseded_by\"),\n /**\n * True once a reindex imported this row from its Markdown file. Only such\n * rows are deleted when the file disappears; DB-only legacy rows are kept.\n */\n fileBacked: boolean(\"file_backed\").notNull().default(false),\n embeddingModel: text(\"embedding_model\"),\n createdByAgent: text(\"created_by_agent\"),\n createdAt,\n updatedAt,\n },\n (table) => ({\n namespaceContentHashUnique: uniqueIndex(\"facts_namespace_content_hash_unique\").on(\n table.namespaceId,\n table.contentHash,\n ),\n namespaceSubjectIdx: index(\"facts_namespace_subject_idx\").on(table.namespaceId, table.subject),\n namespaceIdempotencyIdx: index(\"facts_namespace_idempotency_idx\").on(\n table.namespaceId,\n table.idempotencyKey,\n ),\n sourceInteractionIdx: index(\"facts_source_interaction_idx\").on(table.sourceInteractionId),\n }),\n);\n\nexport const embeddings = pgTable(\n \"embeddings\",\n {\n id: text(\"id\").primaryKey(),\n namespaceId: text(\"namespace_id\")\n .notNull()\n .references(() => namespaces.id, { onDelete: \"cascade\" }),\n ownerType: embeddingOwnerTypeEnum(\"owner_type\").notNull(),\n ownerId: text(\"owner_id\").notNull(),\n vector: vector(\"vector\").notNull(),\n embeddingModel: text(\"embedding_model\").notNull(),\n embeddingSpace: text(\"embedding_space\"),\n status: embeddingStatusEnum(\"status\").notNull().default(\"pending\"),\n attempts: integer(\"attempts\").notNull().default(0),\n lastError: text(\"last_error\"),\n /** Lease deadline while status='processing'; null otherwise. */\n leaseUntil: timestamp(\"lease_until\", { withTimezone: true }),\n leaseToken: text(\"lease_token\"),\n createdAt,\n updatedAt,\n },\n (table) => ({\n ownerUnique: uniqueIndex(\"embeddings_owner_unique\").on(table.ownerType, table.ownerId),\n namespaceModelStatusIdx: index(\"embeddings_namespace_model_status_idx\").on(\n table.namespaceId,\n table.embeddingModel,\n table.status,\n ),\n namespaceSpaceStatusIdx: index(\"embeddings_namespace_space_status_idx\").on(\n table.namespaceId,\n table.embeddingSpace,\n table.status,\n ),\n vectorHnswIdx: index(\"embeddings_vector_hnsw_idx\").using(\n \"hnsw\",\n sql`${table.vector} vector_cosine_ops`,\n ),\n }),\n);\n\nexport const shares = pgTable(\n \"shares\",\n {\n id: text(\"id\").primaryKey(),\n fromNamespaceId: text(\"from_namespace_id\")\n .notNull()\n .references(() => namespaces.id, { onDelete: \"cascade\" }),\n toNamespaceId: text(\"to_namespace_id\")\n .notNull()\n .references(() => namespaces.id, { onDelete: \"cascade\" }),\n sourceFactId: text(\"source_fact_id\")\n .notNull()\n .references(() => facts.id, { onDelete: \"cascade\" }),\n snapshotFactId: text(\"snapshot_fact_id\").references(() => facts.id, { onDelete: \"set null\" }),\n mode: shareModeEnum(\"mode\").notNull().default(\"reference\"),\n tombstoned: boolean(\"tombstoned\").notNull().default(false),\n createdByAgent: text(\"created_by_agent\"),\n createdAt,\n },\n (table) => ({\n shareUnique: uniqueIndex(\"shares_target_source_unique\").on(\n table.toNamespaceId,\n table.sourceFactId,\n table.mode,\n ),\n fromNamespaceIdx: index(\"shares_from_namespace_idx\").on(table.fromNamespaceId),\n }),\n);\n\nexport const checkpoints = pgTable(\n \"checkpoints\",\n {\n id: text(\"id\").primaryKey(),\n namespaceId: text(\"namespace_id\")\n .notNull()\n .references(() => namespaces.id, { onDelete: \"cascade\" }),\n threadId: text(\"thread_id\").notNull(),\n checkpointId: text(\"checkpoint_id\").notNull(),\n parentId: text(\"parent_id\"),\n channelValues: jsonb(\"channel_values\").notNull().default(sql`'{}'::jsonb`),\n metadata: jsonb(\"metadata\").notNull().default(sql`'{}'::jsonb`),\n createdAt,\n },\n (table) => ({\n checkpointUnique: uniqueIndex(\"checkpoints_thread_checkpoint_unique\").on(\n table.namespaceId,\n table.threadId,\n table.checkpointId,\n ),\n }),\n);\n\nexport const modelCalls = pgTable(\n \"model_calls\",\n {\n id: text(\"id\").primaryKey(),\n namespaceId: text(\"namespace_id\").references(() => namespaces.id, { onDelete: \"set null\" }),\n model: text(\"model\").notNull(),\n type: modelCallTypeEnum(\"type\").notNull(),\n latencyMs: integer(\"latency_ms\"),\n tokens: integer(\"tokens\"),\n status: modelCallStatusEnum(\"status\").notNull(),\n error: text(\"error\"),\n metadata: jsonb(\"metadata\").notNull().default(sql`'{}'::jsonb`),\n createdAt,\n },\n (table) => ({\n modelCreatedIdx: index(\"model_calls_model_created_idx\").on(table.model, table.createdAt),\n namespaceCreatedIdx: index(\"model_calls_namespace_created_idx\").on(\n table.namespaceId,\n table.createdAt,\n ),\n }),\n);\n\nexport const auditLog = pgTable(\n \"audit_log\",\n {\n id: text(\"id\").primaryKey(),\n namespaceId: text(\"namespace_id\").references(() => namespaces.id, { onDelete: \"set null\" }),\n action: auditActionEnum(\"action\").notNull(),\n entityType: text(\"entity_type\").notNull(),\n entityId: text(\"entity_id\"),\n createdByAgent: text(\"created_by_agent\"),\n metadata: jsonb(\"metadata\").notNull().default(sql`'{}'::jsonb`),\n createdAt,\n },\n (table) => ({\n namespaceActionCreatedIdx: index(\"audit_log_namespace_action_created_idx\").on(\n table.namespaceId,\n table.action,\n table.createdAt,\n ),\n }),\n);\n","import { VECTOR_DIMENSIONS } from \"../db/schema.js\";\n\n/** Bound both DB hydration and the lexical query work independently of caller input. */\nexport function candidateLimit(limit: number): number {\n if (!Number.isFinite(limit)) return 256;\n return Math.max(1, Math.min(1024, Math.trunc(limit)));\n}\n\n/** pgvector stores float4, so values must stay finite after float4 rounding. */\nexport function validSearchVector(vector: number[]): boolean {\n return (\n vector.length === VECTOR_DIMENSIONS &&\n vector.every((value) => Number.isFinite(Math.fround(value))) &&\n vector.some((value) => value !== 0)\n );\n}\n\n/** Common prompt scaffolding should not make unrelated facts look relevant. */\nconst QUERY_STOPWORDS = new Set([\n \"a\",\n \"about\",\n \"after\",\n \"again\",\n \"all\",\n \"also\",\n \"always\",\n \"an\",\n \"and\",\n \"any\",\n \"are\",\n \"as\",\n \"at\",\n \"back\",\n \"be\",\n \"been\",\n \"before\",\n \"being\",\n \"but\",\n \"by\",\n \"can\",\n \"could\",\n \"did\",\n \"do\",\n \"does\",\n \"done\",\n \"each\",\n \"even\",\n \"ever\",\n \"for\",\n \"from\",\n \"get\",\n \"gets\",\n \"got\",\n \"had\",\n \"has\",\n \"have\",\n \"here\",\n \"how\",\n \"i\",\n \"if\",\n \"in\",\n \"into\",\n \"is\",\n \"it\",\n \"its\",\n \"just\",\n \"like\",\n \"make\",\n \"me\",\n \"more\",\n \"most\",\n \"my\",\n \"never\",\n \"no\",\n \"not\",\n \"now\",\n \"of\",\n \"on\",\n \"only\",\n \"or\",\n \"other\",\n \"our\",\n \"out\",\n \"over\",\n \"please\",\n \"really\",\n \"same\",\n \"should\",\n \"so\",\n \"some\",\n \"sometimes\",\n \"still\",\n \"such\",\n \"than\",\n \"that\",\n \"the\",\n \"their\",\n \"them\",\n \"then\",\n \"there\",\n \"these\",\n \"they\",\n \"this\",\n \"those\",\n \"through\",\n \"to\",\n \"too\",\n \"under\",\n \"up\",\n \"us\",\n \"very\",\n \"was\",\n \"we\",\n \"were\",\n \"what\",\n \"when\",\n \"where\",\n \"which\",\n \"while\",\n \"who\",\n \"why\",\n \"will\",\n \"with\",\n \"would\",\n \"yet\",\n \"you\",\n \"your\",\n]);\n\n/** Literal, case-insensitive terms; no SQL wildcard or query-language syntax. */\nexport function lexicalTerms(query: string): string[] {\n return [\n ...new Set(\n query\n .slice(0, 4096)\n .toLowerCase()\n .match(/[\\p{L}\\p{N}_]+/gu) ?? [],\n ),\n ]\n .filter((term) => !QUERY_STOPWORDS.has(term))\n .slice(0, 32)\n .map((term) => term.slice(0, 64));\n}\n\n/**\n * Everyday coding words. Shared alone they do not say which fact a prompt is\n * about; in a small fact corpus they would otherwise look rare.\n */\nconst GENERIC_TERMS = new Set(\n (\n \"add added adding bug build call change changed changes check code config configure configuration \" +\n \"create data default delete error errors feature file files fix fixed handle issue line load logic \" +\n \"new option options problem project read remove result return run running save set setting settings \" +\n \"show step support test tests thing time update updated use used value values version want way work \" +\n \"works write\"\n ).split(\" \"),\n);\n/** A lone shared term admits a fact only if at most this share of the facts hold it… */\nconst RARE_TERM_SHARE = 0.005;\n/** …or at most this many (so small corpora are not held to a fraction of one fact). */\nconst RARE_TERM_MIN_DF = 2;\n\n/**\n * Lexical admission for per-prompt fact recall (#9): at least two distinct\n * non-generic shared terms, or one that is rare across the fact corpus\n * (document frequency ≤ max(2, 0.5% of facts)) and not generic. One common\n * word in common (\"session\" in an unrelated deploy prompt) is a coincidence.\n */\nexport function admitsLexically(\n shared: string[],\n documentFrequency: Map<string, number>,\n corpusSize: number,\n): boolean {\n const specific = shared.filter((term) => !GENERIC_TERMS.has(term));\n if (specific.length >= 2) return true;\n const rare = Math.max(RARE_TERM_MIN_DF, Math.floor(RARE_TERM_SHARE * corpusSize));\n return specific.some((term) => (documentFrequency.get(term) ?? 0) <= rare);\n}\n\n/** Words every captured decision shares (\"we decided to use …\"); they carry no claim. */\nconst CLAIM_BOILERPLATE = new Set([\n \"decided\",\n \"decide\",\n \"decision\",\n \"made\",\n \"use\",\n \"uses\",\n \"used\",\n \"using\",\n \"now\",\n \"going\",\n \"will\",\n]);\n\n/**\n * Jaccard overlap of two texts' content words (stopwords dropped), 0..1.\n * Used to spot near-duplicate facts: at capture (so a reworded decision is not\n * saved twice) and at recall (so two copies never take two of the few slots).\n */\nexport function termOverlap(a: string, b: string): number {\n const terms = (text: string) =>\n new Set(\n (text.toLowerCase().match(/[\\p{L}\\p{N}_]+/gu) ?? []).filter(\n (term) => !QUERY_STOPWORDS.has(term) && !CLAIM_BOILERPLATE.has(term),\n ),\n );\n const left = terms(a);\n const right = terms(b);\n if (left.size === 0 || right.size === 0) return 0;\n let shared = 0;\n for (const term of left) if (right.has(term)) shared += 1;\n return shared / (left.size + right.size - shared);\n}\n\n/** Score complete-word evidence, favoring explicit fact fields over free text. */\nexport function lexicalFactScore(\n fact: { subject: string; object: string; content: string },\n terms: string[],\n): number {\n if (terms.length === 0) return 0;\n const structured = new Set(\n `${fact.subject} ${fact.object}`.toLowerCase().match(/[\\p{L}\\p{N}_]+/gu) ?? [],\n );\n const prose = new Set(fact.content.toLowerCase().match(/[\\p{L}\\p{N}_]+/gu) ?? []);\n const points = terms.reduce(\n (total, term) => total + (structured.has(term) ? 2 : 0) + (prose.has(term) ? 1 : 0),\n 0,\n );\n return points / (3 * terms.length);\n}\n\nexport function cosine(a: number[], b: number[]): number {\n if (a.length !== b.length) return 0;\n let dot = 0;\n let na = 0;\n let nb = 0;\n for (let i = 0; i < a.length; i++) {\n const av = a[i] ?? 0;\n const bv = b[i] ?? 0;\n dot += av * bv;\n na += av * av;\n nb += bv * bv;\n }\n const denom = Math.sqrt(na) * Math.sqrt(nb);\n return denom === 0 ? 0 : dot / denom;\n}\n\n/** Narrow convention intents, shared by PG and the in-memory repository. These\n * admit existing evidence, never synthesize a language, version or numeric value.\n * Patterns deliberately avoid broad aliases such as \"requires\" on its own. */\nexport function memoryConceptPatterns(query: string): string[] {\n const text = query.slice(0, 4096).toLowerCase();\n const patterns: string[] = [];\n if (\n /\\b(?:lines?|formatter|formatting)\\b/.test(text) &&\n /\\b(?:wide|width|length|long|characters?|columns?)\\b/.test(text)\n ) {\n patterns.push(\"line[_ -]?(length|width)|max[_ -]?line[_ -]?(length|width)|print[_ -]?width\");\n }\n if (\n /\\b(?:interpreter|runtime|language|python|node|ruby|php|java|jdk|dotnet|rust|golang)\\b/.test(\n text,\n ) &&\n /\\b(?:oldest|earliest|minimum|min|version|release|supports?)\\b/.test(text)\n ) {\n patterns.push(\n \"requires[-_ ]?(python|node(js)?|ruby|php|java|jdk|dotnet|rust|golang)|\" +\n \"(python|node(js)?|ruby|php|java|jdk|dotnet|rust|golang|interpreter|runtime)[^.!?]{0,40}(>=|minimum|newer)|\" +\n \"minimum[^.!?]{0,40}(python|node(js)?|ruby|php|java|jdk|dotnet|rust|golang|interpreter|runtime)\",\n );\n }\n return patterns;\n}\n\n/** Supporting lexical evidence, not a semantic probability. */\nexport const MEMORY_CONCEPT_SCORE = 0.5;\nexport function memoryConceptScore(text: string, patterns: string[]): number {\n return patterns.some((pattern) => new RegExp(pattern, \"i\").test(text)) ? MEMORY_CONCEPT_SCORE : 0;\n}\n","{\n \"name\": \"@orquentra/codebuddy\",\n \"version\": \"2.15.0\",\n \"description\": \"CodeBuddy by Orquentra: local-first MCP server and CLI for project context and durable memory in Claude Code, Codex, and other AI coding agents.\",\n \"type\": \"module\",\n \"license\": \"MIT\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"author\": \"Orquentra Inc\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/Orquentra-Inc/CodeBuddy\"\n },\n \"engines\": {\n \"node\": \">=20\"\n },\n \"bin\": {\n \"codebuddy\": \"./dist/cli/index.js\"\n },\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n },\n \"./langgraph\": {\n \"types\": \"./dist/langgraph/index.d.ts\",\n \"import\": \"./dist/langgraph/index.js\"\n }\n },\n \"files\": [\n \"dist\",\n \"src/db/migrations\",\n \"README.md\",\n \"CLAUDE_CODEX.md\",\n \"ARCHITECTURE.md\",\n \"WORKFLOW.md\",\n \"LICENSE\",\n \"docker-compose.yml\",\n \"examples\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsx src/cli/index.ts\",\n \"db:generate\": \"drizzle-kit generate\",\n \"db:migrate\": \"drizzle-kit migrate\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run --passWithNoTests\",\n \"test:pg\": \"bash scripts/test-pg-recovery.sh\",\n \"eval:agent-ab\": \"tsx scripts/eval-agent-ab.mts\",\n \"eval:memory-ab\": \"tsx scripts/eval-memory-ab.mts\",\n \"eval:retrieval\": \"tsx scripts/eval-retrieval.mts\",\n \"eval:savings\": \"tsx scripts/eval-task-savings.mts\",\n \"branches:prune\": \"bash scripts/prune-merged-branches.sh\",\n \"lint\": \"biome check .\",\n \"format\": \"biome format --write .\",\n \"prepublishOnly\": \"node scripts/check-release.mjs && npm run typecheck && npm test && npm run build\",\n \"eval:semantic\": \"tsx scripts/eval-semantic.mts\"\n },\n \"keywords\": [\n \"codebuddy\",\n \"orquentra\",\n \"mcp\",\n \"mcp-server\",\n \"model-context-protocol\",\n \"claude-code\",\n \"codex\",\n \"opencode\",\n \"ai-agent\",\n \"coding-agent\",\n \"context-engine\",\n \"memory\",\n \"agent\",\n \"multi-agent\",\n \"pgvector\",\n \"postgres\",\n \"huggingface\",\n \"langgraph\",\n \"claude\"\n ],\n \"homepage\": \"https://github.com/Orquentra-Inc/CodeBuddy\",\n \"bugs\": {\n \"url\": \"https://github.com/Orquentra-Inc/CodeBuddy/issues\"\n },\n \"dependencies\": {\n \"@clack/prompts\": \"^1.8.1\",\n \"@huggingface/inference\": \"^4.13.19\",\n \"@modelcontextprotocol/sdk\": \"^1.17.5\",\n \"commander\": \"^14.0.0\",\n \"drizzle-orm\": \"^0.45.2\",\n \"js-tiktoken\": \"^1.0.21\",\n \"p-queue\": \"^10.0.0\",\n \"p-retry\": \"^8.0.1\",\n \"p-timeout\": \"^8.1.0\",\n \"picocolors\": \"^1.1.1\",\n \"pino\": \"^10.4.0\",\n \"postgres\": \"^3.4.7\",\n \"yaml\": \"^2.9.0\",\n \"zod\": \"^4.6.7\"\n },\n \"peerDependencies\": {\n \"@langchain/langgraph\": \"^0.2.0 || ^0.3.0\"\n },\n \"peerDependenciesMeta\": {\n \"@langchain/langgraph\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^2.5.0\",\n \"@types/node\": \"^24.3.0\",\n \"drizzle-kit\": \"^0.31.10\",\n \"tsup\": \"^8.5.0\",\n \"tsx\": \"^4.20.5\",\n \"typescript\": \"^5.9.2\",\n \"vitest\": \"^4.1.12\"\n },\n \"optionalDependencies\": {\n \"@huggingface/transformers\": \"^4.3.2\"\n }\n}\n","import pkg from \"../package.json\" with { type: \"json\" };\n\n/**\n * The single source of truth for the product version. `package.json` is the\n * canonical value (npm reads it for the published package); the CLI `--version`\n * flag and the MCP server handshake both import it from here so a version bump\n * only ever touches `package.json`. The bundler inlines this at build time, so\n * there is no runtime file read.\n */\nexport const VERSION: string = pkg.version;\n","import { mkdir, readdir, readFile, rm, stat } from \"node:fs/promises\";\nimport { dirname, join, relative, resolve, sep } from \"node:path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { z } from \"zod\";\nimport { redactPersisted } from \"../core/sensitive.js\";\nimport { VERSION } from \"../version.js\";\nimport {\n assertNoSymlinkBetween,\n composeMarkdown,\n parseFrontMatter,\n writeAtomic,\n} from \"./markdown-store-fs.js\";\nimport { isEligibleMemory } from \"./memory-lifecycle.js\";\n\nexport const FACT_CATEGORIES = [\"general\", \"incident\"] as const;\nexport type FactCategory = (typeof FACT_CATEGORIES)[number];\nexport const INCIDENT_SEVERITIES = [\"low\", \"medium\", \"high\", \"critical\"] as const;\nexport type IncidentSeverity = (typeof INCIDENT_SEVERITIES)[number];\n\nconst factFrontMatterSchema = z.object({\n schemaVersion: z.literal(1),\n id: z.string().regex(/^fact_[a-z0-9]+$/),\n namespace: z.string().min(1),\n type: z.literal(\"fact\"),\n subject: z.string(),\n predicate: z.string(),\n object: z.string(),\n /** Explicit single-valued claim identity; facts sharing it are rival assertions. */\n propositionKey: z.string().min(1).nullable().default(null),\n /** The caller's `remember` idempotency key, so a retry after reindex dedupes. */\n idempotencyKey: z.string().min(1).max(200).nullable().default(null),\n confidence: z.number().min(0).max(1),\n createdAt: z.preprocess(\n (value) => (value instanceof Date ? value.toISOString() : value),\n z.string().datetime(),\n ),\n createdByAgent: z.string().nullable(),\n sourceInteractionId: z.string().nullable(),\n sourceDeleted: z.boolean(),\n category: z.enum(FACT_CATEGORIES).default(\"general\"),\n paths: z.array(z.string().min(1)).default([]),\n severity: z.enum(INCIDENT_SEVERITIES).nullable().default(null),\n introducedBy: z.string().nullable().default(null),\n resolvedBy: z.string().nullable().default(null),\n fingerprint: z\n .string()\n .regex(/^[a-f0-9]{64}$/)\n .nullable()\n .default(null),\n sourcePlanId: z.string().nullable().default(null),\n sourceSessionId: z.string().nullable().default(null),\n verification: z.array(z.string()).default([]),\n supersededBy: z.string().nullable().default(null),\n /** Namespaces granted a live reference to this fact (durable form of reference shares). */\n sharedWith: z.array(z.string().min(1)).default([]),\n});\n\nconst summaryFrontMatterSchema = z.object({\n schemaVersion: z.literal(1),\n id: z.string().regex(/^sum_[a-z0-9]+$/),\n namespace: z.string().min(1),\n type: z.literal(\"summary\"),\n sessionId: z.string().min(1),\n version: z.number().int().positive(),\n tokenCount: z.number().int().nonnegative(),\n createdAt: z.preprocess(\n (value) => (value instanceof Date ? value.toISOString() : value),\n z.string().datetime(),\n ),\n createdByAgent: z.string().nullable(),\n});\n\nexport type FactFile = z.infer<typeof factFrontMatterSchema> & {\n content: string;\n path: string;\n};\n\nexport type FactFileWrite = Omit<\n FactFile,\n | \"path\"\n | \"schemaVersion\"\n | \"type\"\n | \"category\"\n | \"paths\"\n | \"severity\"\n | \"introducedBy\"\n | \"resolvedBy\"\n | \"fingerprint\"\n | \"sourcePlanId\"\n | \"sourceSessionId\"\n | \"verification\"\n | \"supersededBy\"\n | \"sharedWith\"\n | \"propositionKey\"\n | \"idempotencyKey\"\n> &\n Partial<\n Pick<\n FactFile,\n | \"category\"\n | \"paths\"\n | \"severity\"\n | \"introducedBy\"\n | \"resolvedBy\"\n | \"fingerprint\"\n | \"sourcePlanId\"\n | \"sourceSessionId\"\n | \"verification\"\n | \"supersededBy\"\n | \"sharedWith\"\n | \"propositionKey\"\n | \"idempotencyKey\"\n >\n >;\nexport type IncidentFactFile = FactFile & {\n category: \"incident\";\n severity: IncidentSeverity;\n};\nexport type SummaryFile = z.infer<typeof summaryFrontMatterSchema> & {\n content: string;\n path: string;\n};\nexport type SummaryFileWrite = Omit<SummaryFile, \"path\" | \"schemaVersion\" | \"type\">;\n/** A managed memory file that exists on disk but could not be parsed. */\nexport type InvalidMemoryFile = { id: string; path: string; error: string };\n\n/** Files read concurrently while scanning. */\nconst SCAN_BATCH = 64;\n\n/** Parsed memory files by absolute path, valid while mtime and size match. */\nconst parsedFiles = new Map<string, { mtimeMs: number; size: number; item: { id: string } }>();\nconst loadedCaches = new Set<string>();\n\n/**\n * The parse cache also lives on disk (`.codebuddy/cache/parsed-<dir>.json`,\n * gitignored and rebuildable like the index manifest), so each short-lived\n * hook process re-parses only files that changed since any earlier process.\n * Entries are still checked against each file's mtime and size, the cache is\n * discarded when the CodeBuddy version changes (the parsed shape may differ),\n * and a missing or corrupt cache only costs a full parse.\n */\nfunction parseCachePath(root: string, directory: string): string {\n return join(\n root,\n \".codebuddy\",\n \"cache\",\n `parsed-${directory.split(sep).at(-1) ?? \"memory\"}.json`,\n );\n}\n\nasync function loadParseCache(root: string, directory: string): Promise<void> {\n if (loadedCaches.has(directory)) return;\n loadedCaches.add(directory);\n try {\n const raw = JSON.parse(await readFile(parseCachePath(root, directory), \"utf8\")) as {\n version: string;\n files: Record<string, { mtimeMs: number; size: number; item: { id: string } }>;\n };\n if (raw.version !== VERSION) return;\n for (const [name, entry] of Object.entries(raw.files)) {\n const path = join(directory, name);\n if (!parsedFiles.has(path)) parsedFiles.set(path, entry);\n }\n } catch {\n // No cache yet, or unreadable: parse from the files.\n }\n}\n\nasync function saveParseCache(root: string, directory: string): Promise<void> {\n const files: Record<string, unknown> = {};\n for (const [path, entry] of parsedFiles) {\n if (dirname(path) === directory) files[relative(directory, path)] = entry;\n }\n try {\n const path = parseCachePath(root, directory);\n await mkdir(dirname(path), { recursive: true });\n await writeAtomic(path, JSON.stringify({ version: VERSION, files }));\n } catch {\n // A cache that cannot be written only costs a re-parse next time.\n }\n}\n\nexport class MemoryFileStore {\n readonly repositoryRoot: string;\n readonly factsDirectory: string;\n readonly summariesDirectory: string;\n\n constructor(repositoryRoot = process.cwd()) {\n this.repositoryRoot = resolve(repositoryRoot);\n this.factsDirectory = join(this.repositoryRoot, \".codebuddy\", \"memory\", \"facts\");\n this.summariesDirectory = join(this.repositoryRoot, \".codebuddy\", \"memory\", \"summaries\");\n }\n\n async writeFact(raw: FactFileWrite): Promise<string> {\n // Persistence boundary: every fact writer (capture, remember, outcomes,\n // migration, resolve/supersede rewrites) is redacted here.\n const input = redactPersisted(raw);\n const path = this.factPath(input.id);\n await this.prepareDirectory(this.factsDirectory);\n await assertNoSymlinkBetween(this.repositoryRoot, dirname(path));\n\n const metadata = {\n schemaVersion: 1,\n id: input.id,\n namespace: input.namespace,\n type: \"fact\",\n subject: input.subject,\n predicate: input.predicate,\n object: input.object,\n propositionKey: input.propositionKey,\n idempotencyKey: input.idempotencyKey,\n confidence: input.confidence,\n createdAt: input.createdAt,\n createdByAgent: input.createdByAgent,\n sourceInteractionId: input.sourceInteractionId,\n sourceDeleted: input.sourceDeleted,\n category: input.category,\n paths: input.paths,\n severity: input.severity,\n introducedBy: input.introducedBy,\n resolvedBy: input.resolvedBy,\n fingerprint: input.fingerprint,\n sourcePlanId: input.sourcePlanId,\n sourceSessionId: input.sourceSessionId,\n verification: input.verification,\n supersededBy: input.supersededBy,\n sharedWith: input.sharedWith,\n };\n const frontMatter = stringifyYaml(stripUndefinedAndDefaultIncidentFields(metadata));\n\n await writeAtomic(path, composeMarkdown(frontMatter, input.content));\n return path;\n }\n\n async writeSummary(input: SummaryFileWrite): Promise<string> {\n const path = this.summaryPath(input.id);\n await this.prepareDirectory(this.summariesDirectory);\n await assertNoSymlinkBetween(this.repositoryRoot, dirname(path));\n const metadata = stringifyYaml({\n schemaVersion: 1,\n id: input.id,\n namespace: input.namespace,\n type: \"summary\",\n sessionId: input.sessionId,\n version: input.version,\n tokenCount: input.tokenCount,\n createdAt: input.createdAt,\n createdByAgent: input.createdByAgent,\n });\n await writeAtomic(path, composeMarkdown(metadata, input.content));\n return path;\n }\n\n async readFact(pathOrId: string): Promise<FactFile> {\n return this.readFactFile(pathOrId, false);\n }\n\n /** `trusted`: the caller (scan) already proved the path is a regular file in a checked directory. */\n private async readFactFile(pathOrId: string, trusted: boolean): Promise<FactFile> {\n const path = pathOrId.endsWith(\".md\") ? this.safePath(pathOrId) : this.factPath(pathOrId);\n if (!trusted) await assertNoSymlinkBetween(this.repositoryRoot, path);\n const parsed = parseFrontMatter(await readFile(path, \"utf8\"));\n const metadata = factFrontMatterSchema.parse(parseYaml(parsed.frontMatter));\n return {\n ...metadata,\n content: parsed.content.trim(),\n path,\n };\n }\n\n async listFacts(): Promise<FactFile[]> {\n return (await this.scanFacts()).facts;\n }\n\n /**\n * Parse every managed fact file. Hand-written markdown is ignored, and a\n * schema-invalid/corrupt fact is reported in `invalid` (not thrown) so one\n * bad file can't break recall, capture or reindexing for the whole project.\n * Invalid files stay on disk for manual repair.\n */\n async scanFacts(): Promise<{ facts: FactFile[]; invalid: InvalidMemoryFile[] }> {\n const scan = await this.scan(this.factsDirectory, /^fact_[a-z0-9]+\\.md$/, (path, trusted) =>\n this.readFactFile(path, trusted),\n );\n return { facts: scan.items, invalid: scan.invalid };\n }\n\n /**\n * List incident facts for the namespace, ranked by severity then recency.\n * Unlike {@link findIncidentFactsForPaths} this does not filter by path, so\n * callers (e.g. the context engine's project bootstrap) can surface the\n * repository's incident hotspots before any specific edit target is known.\n */\n async listIncidentFacts(\n input: { namespace?: string; includeResolved?: boolean } = {},\n ): Promise<IncidentFactFile[]> {\n const incidents = (await this.listFacts()).filter(\n (fact): fact is IncidentFactFile =>\n fact.category === \"incident\" && Boolean(fact.severity) && isEligibleMemory(fact, input),\n );\n\n return incidents.sort((left, right) => {\n const severity = severityRank(right.severity) - severityRank(left.severity);\n if (severity !== 0) return severity;\n return right.createdAt.localeCompare(left.createdAt);\n });\n }\n\n async findIncidentFactsForPaths(input: {\n namespace?: string;\n paths: string[];\n includeResolved?: boolean;\n }): Promise<IncidentFactFile[]> {\n const wanted = new Set(input.paths.map(normalizeMemoryPath));\n if (wanted.size === 0) return [];\n\n return (\n await this.listIncidentFacts({\n ...(input.namespace !== undefined ? { namespace: input.namespace } : {}),\n ...(input.includeResolved !== undefined ? { includeResolved: input.includeResolved } : {}),\n })\n ).filter((fact) => fact.paths.map(normalizeMemoryPath).some((path) => wanted.has(path)));\n }\n\n async readSummary(pathOrId: string): Promise<SummaryFile> {\n const path = pathOrId.endsWith(\".md\") ? this.safePath(pathOrId) : this.summaryPath(pathOrId);\n await assertNoSymlinkBetween(this.repositoryRoot, path);\n const parsed = parseFrontMatter(await readFile(path, \"utf8\"));\n return {\n ...summaryFrontMatterSchema.parse(parseYaml(parsed.frontMatter)),\n content: parsed.content.trim(),\n path,\n };\n }\n\n async listSummaries(): Promise<SummaryFile[]> {\n return (await this.scanSummaries()).summaries;\n }\n\n async scanSummaries(): Promise<{ summaries: SummaryFile[]; invalid: InvalidMemoryFile[] }> {\n const scan = await this.scan(this.summariesDirectory, /^sum_[a-z0-9]+\\.md$/, (path) =>\n this.readSummary(path),\n );\n return { summaries: scan.items, invalid: scan.invalid };\n }\n\n /**\n * Parse every managed file in `directory`. Hot path: the prompt hook and\n * capture scan facts several times per process, and the MCP server for its\n * lifetime, so each parsed file is cached by path, mtime and size (a changed\n * file is re-read, from any process) and files are read in parallel batches.\n * The directory chain is checked for symlinks once; a `withFileTypes` entry\n * that is a symlink is never `isFile()`, so no file escapes through one.\n */\n private async scan<T extends { id: string }>(\n directory: string,\n managedName: RegExp,\n read: (path: string, trusted: boolean) => Promise<T>,\n ): Promise<{ items: T[]; invalid: InvalidMemoryFile[] }> {\n try {\n await this.prepareDirectory(directory);\n await assertNoSymlinkBetween(this.repositoryRoot, directory);\n await loadParseCache(this.repositoryRoot, directory);\n let reparsed = false;\n const entries = (await readdir(directory, { withFileTypes: true }))\n .filter((entry) => entry.isFile() && managedName.test(entry.name))\n .sort((left, right) => left.name.localeCompare(right.name));\n // Forget files that were deleted, so the cache never outgrows the directory.\n const live = new Set(entries.map((entry) => join(directory, entry.name)));\n for (const path of [...parsedFiles.keys()]) {\n if (dirname(path) === directory && !live.has(path)) {\n parsedFiles.delete(path);\n reparsed = true;\n }\n }\n const outcomes: Array<{ item: T } | { invalid: InvalidMemoryFile }> = [];\n for (let start = 0; start < entries.length; start += SCAN_BATCH) {\n const batch = entries.slice(start, start + SCAN_BATCH);\n outcomes.push(\n ...(await Promise.all(\n batch.map(async (entry) => {\n const path = join(directory, entry.name);\n const id = entry.name.slice(0, -\".md\".length);\n try {\n const info = await stat(path);\n const cached = parsedFiles.get(path);\n const fresh =\n cached !== undefined &&\n cached.mtimeMs === info.mtimeMs &&\n cached.size === info.size;\n const item = fresh ? (cached.item as T) : await read(path, true);\n if (!fresh) reparsed = true;\n if (item.id !== id) {\n throw new Error(`file ID ${id} differs from front matter ID ${item.id}`);\n }\n parsedFiles.set(path, { mtimeMs: info.mtimeMs, size: info.size, item });\n return { item: { ...item } };\n } catch (error) {\n parsedFiles.delete(path);\n return {\n invalid: {\n id,\n path,\n error: (error as Error).message.split(\"\\n\")[0]?.slice(0, 300) ?? \"unreadable\",\n },\n };\n }\n }),\n )),\n );\n }\n if (reparsed) await saveParseCache(this.repositoryRoot, directory);\n const result: { items: T[]; invalid: InvalidMemoryFile[] } = { items: [], invalid: [] };\n for (const outcome of outcomes) {\n if (\"item\" in outcome) result.items.push(outcome.item);\n else result.invalid.push(outcome.invalid);\n }\n return result;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return { items: [], invalid: [] };\n throw error;\n }\n }\n\n async deleteFact(id: string): Promise<void> {\n await rm(this.factPath(id), { force: true });\n }\n\n async markIncidentResolved(id: string, resolvedBy: string): Promise<void> {\n const fact = await this.readFact(id);\n await this.writeFact(copyFact(fact, { resolvedBy }));\n }\n\n async markFactSuperseded(id: string, supersededBy: string): Promise<void> {\n const fact = await this.readFact(id);\n await this.writeFact(copyFact(fact, { supersededBy }));\n }\n\n async setFactSharedWith(id: string, sharedWith: string[]): Promise<void> {\n const fact = await this.readFact(id);\n await this.writeFact(copyFact(fact, { sharedWith: [...new Set(sharedWith)].sort() }));\n }\n\n /** Persist interaction deletion in Markdown before the derived DB is updated. */\n async markSourceInteractionDeleted(\n namespace: string,\n sourceInteractionId: string,\n ): Promise<void> {\n const { facts } = await this.scanFacts();\n for (const fact of facts) {\n if (fact.namespace !== namespace || fact.sourceInteractionId !== sourceInteractionId)\n continue;\n if (fact.sourceDeleted) continue;\n await this.writeFact(copyFact(fact, { sourceDeleted: true }));\n }\n }\n\n /** Persist that a fact's source interaction was forgotten, keeping its provenance id. */\n async markFactSourceDeleted(id: string): Promise<void> {\n const fact = await this.readFact(id);\n await this.writeFact(copyFact(fact, { sourceDeleted: true }));\n }\n\n private factPath(id: string): string {\n if (!/^fact_[a-z0-9]+$/.test(id)) {\n throw new Error(`Invalid fact id: ${id}`);\n }\n return this.safePath(join(this.factsDirectory, `${id}.md`));\n }\n\n private summaryPath(id: string): string {\n if (!/^sum_[a-z0-9]+$/.test(id)) throw new Error(`Invalid summary id: ${id}`);\n return this.safePath(join(this.summariesDirectory, `${id}.md`));\n }\n\n private safePath(path: string): string {\n const absolute = resolve(path);\n const relativePath = relative(this.repositoryRoot, absolute);\n if (relativePath === \"..\" || relativePath.startsWith(`..${sep}`) || relativePath === \"\") {\n throw new Error(`Memory path escapes repository root: ${path}`);\n }\n return absolute;\n }\n\n private async prepareDirectory(directory: string): Promise<void> {\n await assertNoSymlinkBetween(this.repositoryRoot, dirname(directory));\n await mkdir(directory, { recursive: true, mode: 0o700 });\n }\n}\n\nfunction copyFact(\n fact: FactFile,\n patch: Partial<Pick<FactFile, \"resolvedBy\" | \"supersededBy\" | \"sourceDeleted\" | \"sharedWith\">>,\n): FactFileWrite {\n const { path: _path, schemaVersion: _schemaVersion, type: _type, ...write } = fact;\n return { ...write, ...patch };\n}\n\nfunction stripUndefinedAndDefaultIncidentFields(\n metadata: Record<string, unknown>,\n): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(metadata).filter(([key, value]) => {\n if (value === undefined) return false;\n if (key === \"category\" && value === \"general\") return false;\n if ((key === \"paths\" || key === \"sharedWith\") && Array.isArray(value) && value.length === 0)\n return false;\n if (\n [\"severity\", \"introducedBy\", \"resolvedBy\", \"propositionKey\", \"idempotencyKey\"].includes(\n key,\n ) &&\n (value === null || value === undefined)\n ) {\n return false;\n }\n return true;\n }),\n );\n}\n\nfunction normalizeMemoryPath(path: string): string {\n return path.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n}\n\nfunction severityRank(severity: IncidentSeverity): number {\n switch (severity) {\n case \"critical\":\n return 4;\n case \"high\":\n return 3;\n case \"medium\":\n return 2;\n case \"low\":\n return 1;\n }\n}\n","/** Lifecycle fields shared by Markdown facts and indexed (database) fact rows. */\nexport type MemoryLifecycle = {\n namespace?: string;\n sourceDeleted: boolean;\n supersededBy?: string | null;\n category?: string;\n resolvedBy?: string | null;\n};\n\n/**\n * The single eligibility rule for durable memory evidence. A fact is eligible\n * when it belongs to the requested namespace, its source was not deleted, and\n * it was not superseded. A resolved incident is eligible only for historical\n * inspection (`includeResolved`). File context, risk signals, and database\n * recall apply this before ranking or deduplication, so ineligible evidence\n * can never displace or suppress eligible evidence.\n */\nexport function isEligibleMemory(\n fact: MemoryLifecycle,\n options: { namespace?: string; includeResolved?: boolean } = {},\n): boolean {\n if (options.namespace && fact.namespace !== options.namespace) return false;\n if (fact.sourceDeleted || fact.supersededBy) return false;\n if (fact.category === \"incident\" && fact.resolvedBy && !options.includeResolved) return false;\n return true;\n}\n"],"mappings":"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","names":["vector","text","text","facts"]}
|
|
1
|
+
{"version":3,"sources":["../src/db/schema.ts","../src/core/memory-search.ts","../package.json","../src/version.ts","../src/core/memory-file-store.ts","../src/core/memory-lifecycle.ts"],"sourcesContent":["import { sql } from \"drizzle-orm\";\nimport {\n boolean,\n customType,\n index,\n integer,\n jsonb,\n numeric,\n pgEnum,\n pgTable,\n text,\n timestamp,\n uniqueIndex,\n} from \"drizzle-orm/pg-core\";\n\nexport const VECTOR_DIMENSIONS = 384;\nexport const HNSW_M = 16;\nexport const HNSW_EF_CONSTRUCTION = 64;\n\nconst vector = customType<{ data: string; driverData: string }>({\n dataType() {\n return `vector(${VECTOR_DIMENSIONS})`;\n },\n});\n\nexport const memoryTypeEnum = pgEnum(\"memory_type\", [\"interaction\", \"fact\", \"summary\"]);\nexport const interactionRoleEnum = pgEnum(\"interaction_role\", [\"user\", \"assistant\", \"system\"]);\nexport const embeddingOwnerTypeEnum = pgEnum(\"embedding_owner_type\", [\n \"interaction\",\n \"fact\",\n \"summary\",\n]);\nexport const embeddingStatusEnum = pgEnum(\"embedding_status\", [\n \"pending\",\n \"processing\",\n \"ready\",\n \"failed\",\n]);\nexport const shareModeEnum = pgEnum(\"share_mode\", [\"reference\", \"snapshot\"]);\nexport const modelCallTypeEnum = pgEnum(\"model_call_type\", [\"embedding\", \"llm\"]);\nexport const modelCallStatusEnum = pgEnum(\"model_call_status\", [\n \"success\",\n \"failed\",\n \"timeout\",\n \"rate_limited\",\n \"gated\",\n \"fallback\",\n]);\nexport const auditActionEnum = pgEnum(\"audit_action\", [\n \"remember\",\n \"remember_batch\",\n \"share\",\n \"forget\",\n \"config\",\n]);\n\nconst createdAt = timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow();\nconst updatedAt = timestamp(\"updated_at\", { withTimezone: true }).notNull().defaultNow();\n\nexport const namespaces = pgTable(\n \"namespaces\",\n {\n id: text(\"id\").primaryKey(),\n name: text(\"name\").notNull(),\n createdAt,\n updatedAt,\n },\n (table) => ({\n nameUnique: uniqueIndex(\"namespaces_name_unique\").on(table.name),\n }),\n);\n\nexport const interactions = pgTable(\n \"interactions\",\n {\n id: text(\"id\").primaryKey(),\n namespaceId: text(\"namespace_id\")\n .notNull()\n .references(() => namespaces.id, { onDelete: \"cascade\" }),\n sessionId: text(\"session_id\").notNull(),\n role: interactionRoleEnum(\"role\").notNull().default(\"user\"),\n content: text(\"content\").notNull(),\n contentHash: text(\"content_hash\").notNull(),\n tokenCount: integer(\"token_count\").notNull().default(0),\n createdByAgent: text(\"created_by_agent\"),\n createdAt,\n },\n (table) => ({\n namespaceContentHashUnique: uniqueIndex(\"interactions_namespace_content_hash_unique\").on(\n table.namespaceId,\n table.contentHash,\n ),\n namespaceSessionCreatedIdx: index(\"interactions_namespace_session_created_idx\").on(\n table.namespaceId,\n table.sessionId,\n table.createdAt,\n ),\n }),\n);\n\nexport const sessionSummaries = pgTable(\n \"session_summaries\",\n {\n id: text(\"id\").primaryKey(),\n namespaceId: text(\"namespace_id\")\n .notNull()\n .references(() => namespaces.id, { onDelete: \"cascade\" }),\n sessionId: text(\"session_id\").notNull(),\n content: text(\"content\").notNull(),\n version: integer(\"version\").notNull().default(1),\n tokenCount: integer(\"token_count\").notNull().default(0),\n createdByAgent: text(\"created_by_agent\"),\n /** See facts.fileBacked. */\n fileBacked: boolean(\"file_backed\").notNull().default(false),\n createdAt,\n },\n (table) => ({\n namespaceSessionVersionIdx: index(\"session_summaries_namespace_session_version_idx\").on(\n table.namespaceId,\n table.sessionId,\n table.version,\n ),\n }),\n);\n\nexport const facts = pgTable(\n \"facts\",\n {\n id: text(\"id\").primaryKey(),\n namespaceId: text(\"namespace_id\")\n .notNull()\n .references(() => namespaces.id, { onDelete: \"cascade\" }),\n subject: text(\"subject\").notNull(),\n predicate: text(\"predicate\").notNull(),\n object: text(\"object\").notNull(),\n propositionKey: text(\"proposition_key\"),\n /** Kept apart from content_hash so a reindex (which recomputes the hash) keeps it. */\n idempotencyKey: text(\"idempotency_key\"),\n content: text(\"content\").notNull(),\n contentHash: text(\"content_hash\").notNull(),\n confidence: numeric(\"confidence\", { precision: 5, scale: 4 }).notNull().default(\"1\"),\n /**\n * Historical provenance only — deliberately not a foreign key. Interactions\n * are ephemeral DB rows; Markdown facts must re-import after a rebuild that\n * lost them, and the ID must survive so `sourceDeleted` can be tracked.\n */\n sourceInteractionId: text(\"source_interaction_id\"),\n sourceDeleted: boolean(\"source_deleted\").notNull().default(false),\n supersededBy: text(\"superseded_by\"),\n /**\n * True once a reindex imported this row from its Markdown file. Only such\n * rows are deleted when the file disappears; DB-only legacy rows are kept.\n */\n fileBacked: boolean(\"file_backed\").notNull().default(false),\n embeddingModel: text(\"embedding_model\"),\n createdByAgent: text(\"created_by_agent\"),\n createdAt,\n updatedAt,\n },\n (table) => ({\n namespaceContentHashUnique: uniqueIndex(\"facts_namespace_content_hash_unique\").on(\n table.namespaceId,\n table.contentHash,\n ),\n namespaceSubjectIdx: index(\"facts_namespace_subject_idx\").on(table.namespaceId, table.subject),\n namespaceIdempotencyIdx: index(\"facts_namespace_idempotency_idx\").on(\n table.namespaceId,\n table.idempotencyKey,\n ),\n sourceInteractionIdx: index(\"facts_source_interaction_idx\").on(table.sourceInteractionId),\n }),\n);\n\nexport const embeddings = pgTable(\n \"embeddings\",\n {\n id: text(\"id\").primaryKey(),\n namespaceId: text(\"namespace_id\")\n .notNull()\n .references(() => namespaces.id, { onDelete: \"cascade\" }),\n ownerType: embeddingOwnerTypeEnum(\"owner_type\").notNull(),\n ownerId: text(\"owner_id\").notNull(),\n vector: vector(\"vector\").notNull(),\n embeddingModel: text(\"embedding_model\").notNull(),\n embeddingSpace: text(\"embedding_space\"),\n status: embeddingStatusEnum(\"status\").notNull().default(\"pending\"),\n attempts: integer(\"attempts\").notNull().default(0),\n lastError: text(\"last_error\"),\n /** Lease deadline while status='processing'; null otherwise. */\n leaseUntil: timestamp(\"lease_until\", { withTimezone: true }),\n leaseToken: text(\"lease_token\"),\n createdAt,\n updatedAt,\n },\n (table) => ({\n ownerUnique: uniqueIndex(\"embeddings_owner_unique\").on(table.ownerType, table.ownerId),\n namespaceModelStatusIdx: index(\"embeddings_namespace_model_status_idx\").on(\n table.namespaceId,\n table.embeddingModel,\n table.status,\n ),\n namespaceSpaceStatusIdx: index(\"embeddings_namespace_space_status_idx\").on(\n table.namespaceId,\n table.embeddingSpace,\n table.status,\n ),\n vectorHnswIdx: index(\"embeddings_vector_hnsw_idx\").using(\n \"hnsw\",\n sql`${table.vector} vector_cosine_ops`,\n ),\n }),\n);\n\nexport const shares = pgTable(\n \"shares\",\n {\n id: text(\"id\").primaryKey(),\n fromNamespaceId: text(\"from_namespace_id\")\n .notNull()\n .references(() => namespaces.id, { onDelete: \"cascade\" }),\n toNamespaceId: text(\"to_namespace_id\")\n .notNull()\n .references(() => namespaces.id, { onDelete: \"cascade\" }),\n sourceFactId: text(\"source_fact_id\")\n .notNull()\n .references(() => facts.id, { onDelete: \"cascade\" }),\n snapshotFactId: text(\"snapshot_fact_id\").references(() => facts.id, { onDelete: \"set null\" }),\n mode: shareModeEnum(\"mode\").notNull().default(\"reference\"),\n tombstoned: boolean(\"tombstoned\").notNull().default(false),\n createdByAgent: text(\"created_by_agent\"),\n createdAt,\n },\n (table) => ({\n shareUnique: uniqueIndex(\"shares_target_source_unique\").on(\n table.toNamespaceId,\n table.sourceFactId,\n table.mode,\n ),\n fromNamespaceIdx: index(\"shares_from_namespace_idx\").on(table.fromNamespaceId),\n }),\n);\n\nexport const checkpoints = pgTable(\n \"checkpoints\",\n {\n id: text(\"id\").primaryKey(),\n namespaceId: text(\"namespace_id\")\n .notNull()\n .references(() => namespaces.id, { onDelete: \"cascade\" }),\n threadId: text(\"thread_id\").notNull(),\n checkpointId: text(\"checkpoint_id\").notNull(),\n parentId: text(\"parent_id\"),\n channelValues: jsonb(\"channel_values\").notNull().default(sql`'{}'::jsonb`),\n metadata: jsonb(\"metadata\").notNull().default(sql`'{}'::jsonb`),\n createdAt,\n },\n (table) => ({\n checkpointUnique: uniqueIndex(\"checkpoints_thread_checkpoint_unique\").on(\n table.namespaceId,\n table.threadId,\n table.checkpointId,\n ),\n }),\n);\n\nexport const modelCalls = pgTable(\n \"model_calls\",\n {\n id: text(\"id\").primaryKey(),\n namespaceId: text(\"namespace_id\").references(() => namespaces.id, { onDelete: \"set null\" }),\n model: text(\"model\").notNull(),\n type: modelCallTypeEnum(\"type\").notNull(),\n latencyMs: integer(\"latency_ms\"),\n tokens: integer(\"tokens\"),\n status: modelCallStatusEnum(\"status\").notNull(),\n error: text(\"error\"),\n metadata: jsonb(\"metadata\").notNull().default(sql`'{}'::jsonb`),\n createdAt,\n },\n (table) => ({\n modelCreatedIdx: index(\"model_calls_model_created_idx\").on(table.model, table.createdAt),\n namespaceCreatedIdx: index(\"model_calls_namespace_created_idx\").on(\n table.namespaceId,\n table.createdAt,\n ),\n }),\n);\n\nexport const auditLog = pgTable(\n \"audit_log\",\n {\n id: text(\"id\").primaryKey(),\n namespaceId: text(\"namespace_id\").references(() => namespaces.id, { onDelete: \"set null\" }),\n action: auditActionEnum(\"action\").notNull(),\n entityType: text(\"entity_type\").notNull(),\n entityId: text(\"entity_id\"),\n createdByAgent: text(\"created_by_agent\"),\n metadata: jsonb(\"metadata\").notNull().default(sql`'{}'::jsonb`),\n createdAt,\n },\n (table) => ({\n namespaceActionCreatedIdx: index(\"audit_log_namespace_action_created_idx\").on(\n table.namespaceId,\n table.action,\n table.createdAt,\n ),\n }),\n);\n","import { VECTOR_DIMENSIONS } from \"../db/schema.js\";\n\n/** Bound both DB hydration and the lexical query work independently of caller input. */\nexport function candidateLimit(limit: number): number {\n if (!Number.isFinite(limit)) return 256;\n return Math.max(1, Math.min(1024, Math.trunc(limit)));\n}\n\n/** pgvector stores float4, so values must stay finite after float4 rounding. */\nexport function validSearchVector(vector: number[]): boolean {\n return (\n vector.length === VECTOR_DIMENSIONS &&\n vector.every((value) => Number.isFinite(Math.fround(value))) &&\n vector.some((value) => value !== 0)\n );\n}\n\n/** Common prompt scaffolding should not make unrelated facts look relevant. */\nconst QUERY_STOPWORDS = new Set([\n \"a\",\n \"about\",\n \"after\",\n \"again\",\n \"all\",\n \"also\",\n \"always\",\n \"an\",\n \"and\",\n \"any\",\n \"are\",\n \"as\",\n \"at\",\n \"back\",\n \"be\",\n \"been\",\n \"before\",\n \"being\",\n \"but\",\n \"by\",\n \"can\",\n \"could\",\n \"did\",\n \"do\",\n \"does\",\n \"done\",\n \"each\",\n \"even\",\n \"ever\",\n \"for\",\n \"from\",\n \"get\",\n \"gets\",\n \"got\",\n \"had\",\n \"has\",\n \"have\",\n \"here\",\n \"how\",\n \"i\",\n \"if\",\n \"in\",\n \"into\",\n \"is\",\n \"it\",\n \"its\",\n \"just\",\n \"like\",\n \"make\",\n \"me\",\n \"more\",\n \"most\",\n \"my\",\n \"never\",\n \"no\",\n \"not\",\n \"now\",\n \"of\",\n \"on\",\n \"only\",\n \"or\",\n \"other\",\n \"our\",\n \"out\",\n \"over\",\n \"please\",\n \"really\",\n \"same\",\n \"should\",\n \"so\",\n \"some\",\n \"sometimes\",\n \"still\",\n \"such\",\n \"than\",\n \"that\",\n \"the\",\n \"their\",\n \"them\",\n \"then\",\n \"there\",\n \"these\",\n \"they\",\n \"this\",\n \"those\",\n \"through\",\n \"to\",\n \"too\",\n \"under\",\n \"up\",\n \"us\",\n \"very\",\n \"was\",\n \"we\",\n \"were\",\n \"what\",\n \"when\",\n \"where\",\n \"which\",\n \"while\",\n \"who\",\n \"why\",\n \"will\",\n \"with\",\n \"would\",\n \"yet\",\n \"you\",\n \"your\",\n]);\n\n/** Literal, case-insensitive terms; no SQL wildcard or query-language syntax. */\nexport function lexicalTerms(query: string): string[] {\n return [\n ...new Set(\n query\n .slice(0, 4096)\n .toLowerCase()\n .match(/[\\p{L}\\p{N}_]+/gu) ?? [],\n ),\n ]\n .filter((term) => !QUERY_STOPWORDS.has(term))\n .slice(0, 32)\n .map((term) => term.slice(0, 64));\n}\n\n/**\n * Everyday coding words. Shared alone they do not say which fact a prompt is\n * about; in a small fact corpus they would otherwise look rare.\n */\nconst GENERIC_TERMS = new Set(\n (\n \"add added adding bug build call change changed changes check code config configure configuration \" +\n \"create data default delete error errors feature file files fix fixed handle issue line load logic \" +\n \"new option options problem project read remove result return run running save set setting settings \" +\n \"show step support test tests thing time update updated use used value values version want way work \" +\n \"works write\"\n ).split(\" \"),\n);\n/** A lone shared term admits a fact only if at most this share of the facts hold it… */\nconst RARE_TERM_SHARE = 0.005;\n/** …or at most this many (so small corpora are not held to a fraction of one fact). */\nconst RARE_TERM_MIN_DF = 2;\n\n/**\n * Lexical admission for per-prompt fact recall (#9): at least two distinct\n * non-generic shared terms, or one that is rare across the fact corpus\n * (document frequency ≤ max(2, 0.5% of facts)) and not generic. One common\n * word in common (\"session\" in an unrelated deploy prompt) is a coincidence.\n */\nexport function admitsLexically(\n shared: string[],\n documentFrequency: Map<string, number>,\n corpusSize: number,\n): boolean {\n const specific = shared.filter((term) => !GENERIC_TERMS.has(term));\n if (specific.length >= 2) return true;\n const rare = Math.max(RARE_TERM_MIN_DF, Math.floor(RARE_TERM_SHARE * corpusSize));\n return specific.some((term) => (documentFrequency.get(term) ?? 0) <= rare);\n}\n\n/** Words every captured decision shares (\"we decided to use …\"); they carry no claim. */\nconst CLAIM_BOILERPLATE = new Set([\n \"decided\",\n \"decide\",\n \"decision\",\n \"made\",\n \"use\",\n \"uses\",\n \"used\",\n \"using\",\n \"now\",\n \"going\",\n \"will\",\n]);\n\n/**\n * Jaccard overlap of two texts' content words (stopwords dropped), 0..1.\n * Used to spot near-duplicate facts: at capture (so a reworded decision is not\n * saved twice) and at recall (so two copies never take two of the few slots).\n */\nexport function termOverlap(a: string, b: string): number {\n const terms = (text: string) =>\n new Set(\n (text.toLowerCase().match(/[\\p{L}\\p{N}_]+/gu) ?? []).filter(\n (term) => !QUERY_STOPWORDS.has(term) && !CLAIM_BOILERPLATE.has(term),\n ),\n );\n const left = terms(a);\n const right = terms(b);\n if (left.size === 0 || right.size === 0) return 0;\n let shared = 0;\n for (const term of left) if (right.has(term)) shared += 1;\n return shared / (left.size + right.size - shared);\n}\n\n/** Score complete-word evidence, favoring explicit fact fields over free text. */\nexport function lexicalFactScore(\n fact: { subject: string; object: string; content: string },\n terms: string[],\n): number {\n if (terms.length === 0) return 0;\n const structured = new Set(\n `${fact.subject} ${fact.object}`.toLowerCase().match(/[\\p{L}\\p{N}_]+/gu) ?? [],\n );\n const prose = new Set(fact.content.toLowerCase().match(/[\\p{L}\\p{N}_]+/gu) ?? []);\n const points = terms.reduce(\n (total, term) => total + (structured.has(term) ? 2 : 0) + (prose.has(term) ? 1 : 0),\n 0,\n );\n return points / (3 * terms.length);\n}\n\nexport function cosine(a: number[], b: number[]): number {\n if (a.length !== b.length) return 0;\n let dot = 0;\n let na = 0;\n let nb = 0;\n for (let i = 0; i < a.length; i++) {\n const av = a[i] ?? 0;\n const bv = b[i] ?? 0;\n dot += av * bv;\n na += av * av;\n nb += bv * bv;\n }\n const denom = Math.sqrt(na) * Math.sqrt(nb);\n return denom === 0 ? 0 : dot / denom;\n}\n\n/** Narrow convention intents, shared by PG and the in-memory repository. These\n * admit existing evidence, never synthesize a language, version or numeric value.\n * Patterns deliberately avoid broad aliases such as \"requires\" on its own. */\nexport function memoryConceptPatterns(query: string): string[] {\n const text = query.slice(0, 4096).toLowerCase();\n const patterns: string[] = [];\n if (\n /\\b(?:lines?|formatter|formatting)\\b/.test(text) &&\n /\\b(?:wide|width|length|long|characters?|columns?)\\b/.test(text)\n ) {\n patterns.push(\"line[_ -]?(length|width)|max[_ -]?line[_ -]?(length|width)|print[_ -]?width\");\n }\n if (\n /\\b(?:interpreter|runtime|language|python|node|ruby|php|java|jdk|dotnet|rust|golang)\\b/.test(\n text,\n ) &&\n /\\b(?:oldest|earliest|minimum|min|version|release|supports?)\\b/.test(text)\n ) {\n patterns.push(\n \"requires[-_ ]?(python|node(js)?|ruby|php|java|jdk|dotnet|rust|golang)|\" +\n \"(python|node(js)?|ruby|php|java|jdk|dotnet|rust|golang|interpreter|runtime)[^.!?]{0,40}(>=|minimum|newer)|\" +\n \"minimum[^.!?]{0,40}(python|node(js)?|ruby|php|java|jdk|dotnet|rust|golang|interpreter|runtime)\",\n );\n }\n return patterns;\n}\n\n/** Supporting lexical evidence, not a semantic probability. */\nexport const MEMORY_CONCEPT_SCORE = 0.5;\nexport function memoryConceptScore(text: string, patterns: string[]): number {\n return patterns.some((pattern) => new RegExp(pattern, \"i\").test(text)) ? MEMORY_CONCEPT_SCORE : 0;\n}\n","{\n \"name\": \"@orquentra/codebuddy\",\n \"version\": \"2.15.3\",\n \"description\": \"CodeBuddy by Orquentra: local-first MCP server and CLI for project context and durable memory in Claude Code, Codex, and other AI coding agents.\",\n \"type\": \"module\",\n \"license\": \"MIT\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"author\": \"Orquentra Inc\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/Orquentra-Inc/CodeBuddy\"\n },\n \"engines\": {\n \"node\": \">=20\"\n },\n \"bin\": {\n \"codebuddy\": \"./dist/cli/index.js\"\n },\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n },\n \"./langgraph\": {\n \"types\": \"./dist/langgraph/index.d.ts\",\n \"import\": \"./dist/langgraph/index.js\"\n }\n },\n \"files\": [\n \"dist\",\n \"src/db/migrations\",\n \"README.md\",\n \"CLAUDE_CODEX.md\",\n \"ARCHITECTURE.md\",\n \"WORKFLOW.md\",\n \"LICENSE\",\n \"docker-compose.yml\",\n \"examples\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsx src/cli/index.ts\",\n \"db:generate\": \"drizzle-kit generate\",\n \"db:migrate\": \"drizzle-kit migrate\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run --passWithNoTests\",\n \"test:pg\": \"bash scripts/test-pg-recovery.sh\",\n \"eval:agent-ab\": \"tsx scripts/eval-agent-ab.mts\",\n \"eval:memory-ab\": \"tsx scripts/eval-memory-ab.mts\",\n \"eval:retrieval\": \"tsx scripts/eval-retrieval.mts\",\n \"eval:savings\": \"tsx scripts/eval-task-savings.mts\",\n \"branches:prune\": \"bash scripts/prune-merged-branches.sh\",\n \"lint\": \"biome check .\",\n \"format\": \"biome format --write .\",\n \"prepublishOnly\": \"node scripts/check-release.mjs && npm run typecheck && npm test && npm run build\",\n \"eval:semantic\": \"tsx scripts/eval-semantic.mts\"\n },\n \"keywords\": [\n \"codebuddy\",\n \"orquentra\",\n \"mcp\",\n \"mcp-server\",\n \"model-context-protocol\",\n \"claude-code\",\n \"codex\",\n \"opencode\",\n \"ai-agent\",\n \"coding-agent\",\n \"context-engine\",\n \"memory\",\n \"agent\",\n \"multi-agent\",\n \"pgvector\",\n \"postgres\",\n \"huggingface\",\n \"langgraph\",\n \"claude\"\n ],\n \"homepage\": \"https://github.com/Orquentra-Inc/CodeBuddy\",\n \"bugs\": {\n \"url\": \"https://github.com/Orquentra-Inc/CodeBuddy/issues\"\n },\n \"dependencies\": {\n \"@clack/prompts\": \"^1.8.1\",\n \"@huggingface/inference\": \"^4.13.19\",\n \"@modelcontextprotocol/sdk\": \"^1.17.5\",\n \"commander\": \"^14.0.0\",\n \"drizzle-orm\": \"^0.45.2\",\n \"js-tiktoken\": \"^1.0.21\",\n \"p-queue\": \"^10.0.0\",\n \"p-retry\": \"^8.0.1\",\n \"p-timeout\": \"^8.1.0\",\n \"picocolors\": \"^1.1.1\",\n \"pino\": \"^10.4.0\",\n \"postgres\": \"^3.4.7\",\n \"yaml\": \"^2.9.0\",\n \"zod\": \"^4.6.7\"\n },\n \"peerDependencies\": {\n \"@langchain/langgraph\": \"^0.2.0 || ^0.3.0\"\n },\n \"peerDependenciesMeta\": {\n \"@langchain/langgraph\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^2.5.0\",\n \"@types/node\": \"^24.3.0\",\n \"drizzle-kit\": \"^0.31.10\",\n \"tsup\": \"^8.5.0\",\n \"tsx\": \"^4.20.5\",\n \"typescript\": \"^5.9.2\",\n \"vitest\": \"^4.1.12\"\n },\n \"optionalDependencies\": {\n \"@huggingface/transformers\": \"^4.3.2\"\n }\n}\n","import pkg from \"../package.json\" with { type: \"json\" };\n\n/**\n * The single source of truth for the product version. `package.json` is the\n * canonical value (npm reads it for the published package); the CLI `--version`\n * flag and the MCP server handshake both import it from here so a version bump\n * only ever touches `package.json`. The bundler inlines this at build time, so\n * there is no runtime file read.\n */\nexport const VERSION: string = pkg.version;\n","import { mkdir, readdir, readFile, rm, stat } from \"node:fs/promises\";\nimport { dirname, join, relative, resolve, sep } from \"node:path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { z } from \"zod\";\nimport { redactPersisted } from \"../core/sensitive.js\";\nimport { VERSION } from \"../version.js\";\nimport {\n assertNoSymlinkBetween,\n composeMarkdown,\n parseFrontMatter,\n writeAtomic,\n} from \"./markdown-store-fs.js\";\nimport { isEligibleMemory } from \"./memory-lifecycle.js\";\n\nexport const FACT_CATEGORIES = [\"general\", \"incident\"] as const;\nexport type FactCategory = (typeof FACT_CATEGORIES)[number];\nexport const INCIDENT_SEVERITIES = [\"low\", \"medium\", \"high\", \"critical\"] as const;\nexport type IncidentSeverity = (typeof INCIDENT_SEVERITIES)[number];\n\nconst factFrontMatterSchema = z.object({\n schemaVersion: z.literal(1),\n id: z.string().regex(/^fact_[a-z0-9]+$/),\n namespace: z.string().min(1),\n type: z.literal(\"fact\"),\n subject: z.string(),\n predicate: z.string(),\n object: z.string(),\n /** Explicit single-valued claim identity; facts sharing it are rival assertions. */\n propositionKey: z.string().min(1).nullable().default(null),\n /** The caller's `remember` idempotency key, so a retry after reindex dedupes. */\n idempotencyKey: z.string().min(1).max(200).nullable().default(null),\n confidence: z.number().min(0).max(1),\n createdAt: z.preprocess(\n (value) => (value instanceof Date ? value.toISOString() : value),\n z.string().datetime(),\n ),\n createdByAgent: z.string().nullable(),\n sourceInteractionId: z.string().nullable(),\n sourceDeleted: z.boolean(),\n category: z.enum(FACT_CATEGORIES).default(\"general\"),\n paths: z.array(z.string().min(1)).default([]),\n severity: z.enum(INCIDENT_SEVERITIES).nullable().default(null),\n introducedBy: z.string().nullable().default(null),\n resolvedBy: z.string().nullable().default(null),\n fingerprint: z\n .string()\n .regex(/^[a-f0-9]{64}$/)\n .nullable()\n .default(null),\n sourcePlanId: z.string().nullable().default(null),\n sourceSessionId: z.string().nullable().default(null),\n verification: z.array(z.string()).default([]),\n supersededBy: z.string().nullable().default(null),\n /** Namespaces granted a live reference to this fact (durable form of reference shares). */\n sharedWith: z.array(z.string().min(1)).default([]),\n});\n\nconst summaryFrontMatterSchema = z.object({\n schemaVersion: z.literal(1),\n id: z.string().regex(/^sum_[a-z0-9]+$/),\n namespace: z.string().min(1),\n type: z.literal(\"summary\"),\n sessionId: z.string().min(1),\n version: z.number().int().positive(),\n tokenCount: z.number().int().nonnegative(),\n createdAt: z.preprocess(\n (value) => (value instanceof Date ? value.toISOString() : value),\n z.string().datetime(),\n ),\n createdByAgent: z.string().nullable(),\n});\n\nexport type FactFile = z.infer<typeof factFrontMatterSchema> & {\n content: string;\n path: string;\n};\n\nexport type FactFileWrite = Omit<\n FactFile,\n | \"path\"\n | \"schemaVersion\"\n | \"type\"\n | \"category\"\n | \"paths\"\n | \"severity\"\n | \"introducedBy\"\n | \"resolvedBy\"\n | \"fingerprint\"\n | \"sourcePlanId\"\n | \"sourceSessionId\"\n | \"verification\"\n | \"supersededBy\"\n | \"sharedWith\"\n | \"propositionKey\"\n | \"idempotencyKey\"\n> &\n Partial<\n Pick<\n FactFile,\n | \"category\"\n | \"paths\"\n | \"severity\"\n | \"introducedBy\"\n | \"resolvedBy\"\n | \"fingerprint\"\n | \"sourcePlanId\"\n | \"sourceSessionId\"\n | \"verification\"\n | \"supersededBy\"\n | \"sharedWith\"\n | \"propositionKey\"\n | \"idempotencyKey\"\n >\n >;\nexport type IncidentFactFile = FactFile & {\n category: \"incident\";\n severity: IncidentSeverity;\n};\nexport type SummaryFile = z.infer<typeof summaryFrontMatterSchema> & {\n content: string;\n path: string;\n};\nexport type SummaryFileWrite = Omit<SummaryFile, \"path\" | \"schemaVersion\" | \"type\">;\n/** A managed memory file that exists on disk but could not be parsed. */\nexport type InvalidMemoryFile = { id: string; path: string; error: string };\n\n/** Files read concurrently while scanning. */\nconst SCAN_BATCH = 64;\n\n/** Parsed memory files by absolute path, valid while mtime and size match. */\nconst parsedFiles = new Map<string, { mtimeMs: number; size: number; item: { id: string } }>();\nconst loadedCaches = new Set<string>();\n\n/**\n * The parse cache also lives on disk (`.codebuddy/cache/parsed-<dir>.json`,\n * gitignored and rebuildable like the index manifest), so each short-lived\n * hook process re-parses only files that changed since any earlier process.\n * Entries are still checked against each file's mtime and size, the cache is\n * discarded when the CodeBuddy version changes (the parsed shape may differ),\n * and a missing or corrupt cache only costs a full parse.\n */\nfunction parseCachePath(root: string, directory: string): string {\n return join(\n root,\n \".codebuddy\",\n \"cache\",\n `parsed-${directory.split(sep).at(-1) ?? \"memory\"}.json`,\n );\n}\n\nasync function loadParseCache(root: string, directory: string): Promise<void> {\n if (loadedCaches.has(directory)) return;\n loadedCaches.add(directory);\n try {\n const raw = JSON.parse(await readFile(parseCachePath(root, directory), \"utf8\")) as {\n version: string;\n files: Record<string, { mtimeMs: number; size: number; item: { id: string } }>;\n };\n if (raw.version !== VERSION) return;\n for (const [name, entry] of Object.entries(raw.files)) {\n const path = join(directory, name);\n if (!parsedFiles.has(path)) parsedFiles.set(path, entry);\n }\n } catch {\n // No cache yet, or unreadable: parse from the files.\n }\n}\n\nasync function saveParseCache(root: string, directory: string): Promise<void> {\n const files: Record<string, unknown> = {};\n for (const [path, entry] of parsedFiles) {\n if (dirname(path) === directory) files[relative(directory, path)] = entry;\n }\n try {\n const path = parseCachePath(root, directory);\n await mkdir(dirname(path), { recursive: true });\n await writeAtomic(path, JSON.stringify({ version: VERSION, files }));\n } catch {\n // A cache that cannot be written only costs a re-parse next time.\n }\n}\n\nexport class MemoryFileStore {\n readonly repositoryRoot: string;\n readonly factsDirectory: string;\n readonly summariesDirectory: string;\n\n constructor(repositoryRoot = process.cwd()) {\n this.repositoryRoot = resolve(repositoryRoot);\n this.factsDirectory = join(this.repositoryRoot, \".codebuddy\", \"memory\", \"facts\");\n this.summariesDirectory = join(this.repositoryRoot, \".codebuddy\", \"memory\", \"summaries\");\n }\n\n async writeFact(raw: FactFileWrite): Promise<string> {\n // Persistence boundary: every fact writer (capture, remember, outcomes,\n // migration, resolve/supersede rewrites) is redacted here.\n const input = redactPersisted(raw);\n const path = this.factPath(input.id);\n await this.prepareDirectory(this.factsDirectory);\n await assertNoSymlinkBetween(this.repositoryRoot, dirname(path));\n\n const metadata = {\n schemaVersion: 1,\n id: input.id,\n namespace: input.namespace,\n type: \"fact\",\n subject: input.subject,\n predicate: input.predicate,\n object: input.object,\n propositionKey: input.propositionKey,\n idempotencyKey: input.idempotencyKey,\n confidence: input.confidence,\n createdAt: input.createdAt,\n createdByAgent: input.createdByAgent,\n sourceInteractionId: input.sourceInteractionId,\n sourceDeleted: input.sourceDeleted,\n category: input.category,\n paths: input.paths,\n severity: input.severity,\n introducedBy: input.introducedBy,\n resolvedBy: input.resolvedBy,\n fingerprint: input.fingerprint,\n sourcePlanId: input.sourcePlanId,\n sourceSessionId: input.sourceSessionId,\n verification: input.verification,\n supersededBy: input.supersededBy,\n sharedWith: input.sharedWith,\n };\n const frontMatter = stringifyYaml(stripUndefinedAndDefaultIncidentFields(metadata));\n\n await writeAtomic(path, composeMarkdown(frontMatter, input.content));\n return path;\n }\n\n async writeSummary(input: SummaryFileWrite): Promise<string> {\n const path = this.summaryPath(input.id);\n await this.prepareDirectory(this.summariesDirectory);\n await assertNoSymlinkBetween(this.repositoryRoot, dirname(path));\n const metadata = stringifyYaml({\n schemaVersion: 1,\n id: input.id,\n namespace: input.namespace,\n type: \"summary\",\n sessionId: input.sessionId,\n version: input.version,\n tokenCount: input.tokenCount,\n createdAt: input.createdAt,\n createdByAgent: input.createdByAgent,\n });\n await writeAtomic(path, composeMarkdown(metadata, input.content));\n return path;\n }\n\n async readFact(pathOrId: string): Promise<FactFile> {\n return this.readFactFile(pathOrId, false);\n }\n\n /** `trusted`: the caller (scan) already proved the path is a regular file in a checked directory. */\n private async readFactFile(pathOrId: string, trusted: boolean): Promise<FactFile> {\n const path = pathOrId.endsWith(\".md\") ? this.safePath(pathOrId) : this.factPath(pathOrId);\n if (!trusted) await assertNoSymlinkBetween(this.repositoryRoot, path);\n const parsed = parseFrontMatter(await readFile(path, \"utf8\"));\n const metadata = factFrontMatterSchema.parse(parseYaml(parsed.frontMatter));\n return {\n ...metadata,\n content: parsed.content.trim(),\n path,\n };\n }\n\n async listFacts(): Promise<FactFile[]> {\n return (await this.scanFacts()).facts;\n }\n\n /**\n * Parse every managed fact file. Hand-written markdown is ignored, and a\n * schema-invalid/corrupt fact is reported in `invalid` (not thrown) so one\n * bad file can't break recall, capture or reindexing for the whole project.\n * Invalid files stay on disk for manual repair.\n */\n async scanFacts(): Promise<{ facts: FactFile[]; invalid: InvalidMemoryFile[] }> {\n const scan = await this.scan(this.factsDirectory, /^fact_[a-z0-9]+\\.md$/, (path, trusted) =>\n this.readFactFile(path, trusted),\n );\n return { facts: scan.items, invalid: scan.invalid };\n }\n\n /**\n * List incident facts for the namespace, ranked by severity then recency.\n * Unlike {@link findIncidentFactsForPaths} this does not filter by path, so\n * callers (e.g. the context engine's project bootstrap) can surface the\n * repository's incident hotspots before any specific edit target is known.\n */\n async listIncidentFacts(\n input: { namespace?: string; includeResolved?: boolean } = {},\n ): Promise<IncidentFactFile[]> {\n const incidents = (await this.listFacts()).filter(\n (fact): fact is IncidentFactFile =>\n fact.category === \"incident\" && Boolean(fact.severity) && isEligibleMemory(fact, input),\n );\n\n return incidents.sort((left, right) => {\n const severity = severityRank(right.severity) - severityRank(left.severity);\n if (severity !== 0) return severity;\n return right.createdAt.localeCompare(left.createdAt);\n });\n }\n\n async findIncidentFactsForPaths(input: {\n namespace?: string;\n paths: string[];\n includeResolved?: boolean;\n }): Promise<IncidentFactFile[]> {\n const wanted = new Set(input.paths.map(normalizeMemoryPath));\n if (wanted.size === 0) return [];\n\n return (\n await this.listIncidentFacts({\n ...(input.namespace !== undefined ? { namespace: input.namespace } : {}),\n ...(input.includeResolved !== undefined ? { includeResolved: input.includeResolved } : {}),\n })\n ).filter((fact) => fact.paths.map(normalizeMemoryPath).some((path) => wanted.has(path)));\n }\n\n async readSummary(pathOrId: string): Promise<SummaryFile> {\n const path = pathOrId.endsWith(\".md\") ? this.safePath(pathOrId) : this.summaryPath(pathOrId);\n await assertNoSymlinkBetween(this.repositoryRoot, path);\n const parsed = parseFrontMatter(await readFile(path, \"utf8\"));\n return {\n ...summaryFrontMatterSchema.parse(parseYaml(parsed.frontMatter)),\n content: parsed.content.trim(),\n path,\n };\n }\n\n async listSummaries(): Promise<SummaryFile[]> {\n return (await this.scanSummaries()).summaries;\n }\n\n async scanSummaries(): Promise<{ summaries: SummaryFile[]; invalid: InvalidMemoryFile[] }> {\n const scan = await this.scan(this.summariesDirectory, /^sum_[a-z0-9]+\\.md$/, (path) =>\n this.readSummary(path),\n );\n return { summaries: scan.items, invalid: scan.invalid };\n }\n\n /**\n * Parse every managed file in `directory`. Hot path: the prompt hook and\n * capture scan facts several times per process, and the MCP server for its\n * lifetime, so each parsed file is cached by path, mtime and size (a changed\n * file is re-read, from any process) and files are read in parallel batches.\n * The directory chain is checked for symlinks once; a `withFileTypes` entry\n * that is a symlink is never `isFile()`, so no file escapes through one.\n */\n private async scan<T extends { id: string }>(\n directory: string,\n managedName: RegExp,\n read: (path: string, trusted: boolean) => Promise<T>,\n ): Promise<{ items: T[]; invalid: InvalidMemoryFile[] }> {\n try {\n await this.prepareDirectory(directory);\n await assertNoSymlinkBetween(this.repositoryRoot, directory);\n await loadParseCache(this.repositoryRoot, directory);\n let reparsed = false;\n const entries = (await readdir(directory, { withFileTypes: true }))\n .filter((entry) => entry.isFile() && managedName.test(entry.name))\n .sort((left, right) => left.name.localeCompare(right.name));\n // Forget files that were deleted, so the cache never outgrows the directory.\n const live = new Set(entries.map((entry) => join(directory, entry.name)));\n for (const path of [...parsedFiles.keys()]) {\n if (dirname(path) === directory && !live.has(path)) {\n parsedFiles.delete(path);\n reparsed = true;\n }\n }\n const outcomes: Array<{ item: T } | { invalid: InvalidMemoryFile }> = [];\n for (let start = 0; start < entries.length; start += SCAN_BATCH) {\n const batch = entries.slice(start, start + SCAN_BATCH);\n outcomes.push(\n ...(await Promise.all(\n batch.map(async (entry) => {\n const path = join(directory, entry.name);\n const id = entry.name.slice(0, -\".md\".length);\n try {\n const info = await stat(path);\n const cached = parsedFiles.get(path);\n const fresh =\n cached !== undefined &&\n cached.mtimeMs === info.mtimeMs &&\n cached.size === info.size;\n const item = fresh ? (cached.item as T) : await read(path, true);\n if (!fresh) reparsed = true;\n if (item.id !== id) {\n throw new Error(`file ID ${id} differs from front matter ID ${item.id}`);\n }\n parsedFiles.set(path, { mtimeMs: info.mtimeMs, size: info.size, item });\n return { item: { ...item } };\n } catch (error) {\n parsedFiles.delete(path);\n return {\n invalid: {\n id,\n path,\n error: (error as Error).message.split(\"\\n\")[0]?.slice(0, 300) ?? \"unreadable\",\n },\n };\n }\n }),\n )),\n );\n }\n if (reparsed) await saveParseCache(this.repositoryRoot, directory);\n const result: { items: T[]; invalid: InvalidMemoryFile[] } = { items: [], invalid: [] };\n for (const outcome of outcomes) {\n if (\"item\" in outcome) result.items.push(outcome.item);\n else result.invalid.push(outcome.invalid);\n }\n return result;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return { items: [], invalid: [] };\n throw error;\n }\n }\n\n async deleteFact(id: string): Promise<void> {\n await rm(this.factPath(id), { force: true });\n }\n\n async markIncidentResolved(id: string, resolvedBy: string): Promise<void> {\n const fact = await this.readFact(id);\n await this.writeFact(copyFact(fact, { resolvedBy }));\n }\n\n async markFactSuperseded(id: string, supersededBy: string): Promise<void> {\n const fact = await this.readFact(id);\n await this.writeFact(copyFact(fact, { supersededBy }));\n }\n\n async setFactSharedWith(id: string, sharedWith: string[]): Promise<void> {\n const fact = await this.readFact(id);\n await this.writeFact(copyFact(fact, { sharedWith: [...new Set(sharedWith)].sort() }));\n }\n\n /** Persist interaction deletion in Markdown before the derived DB is updated. */\n async markSourceInteractionDeleted(\n namespace: string,\n sourceInteractionId: string,\n ): Promise<void> {\n const { facts } = await this.scanFacts();\n for (const fact of facts) {\n if (fact.namespace !== namespace || fact.sourceInteractionId !== sourceInteractionId)\n continue;\n if (fact.sourceDeleted) continue;\n await this.writeFact(copyFact(fact, { sourceDeleted: true }));\n }\n }\n\n /** Persist that a fact's source interaction was forgotten, keeping its provenance id. */\n async markFactSourceDeleted(id: string): Promise<void> {\n const fact = await this.readFact(id);\n await this.writeFact(copyFact(fact, { sourceDeleted: true }));\n }\n\n private factPath(id: string): string {\n if (!/^fact_[a-z0-9]+$/.test(id)) {\n throw new Error(`Invalid fact id: ${id}`);\n }\n return this.safePath(join(this.factsDirectory, `${id}.md`));\n }\n\n private summaryPath(id: string): string {\n if (!/^sum_[a-z0-9]+$/.test(id)) throw new Error(`Invalid summary id: ${id}`);\n return this.safePath(join(this.summariesDirectory, `${id}.md`));\n }\n\n private safePath(path: string): string {\n const absolute = resolve(path);\n const relativePath = relative(this.repositoryRoot, absolute);\n if (relativePath === \"..\" || relativePath.startsWith(`..${sep}`) || relativePath === \"\") {\n throw new Error(`Memory path escapes repository root: ${path}`);\n }\n return absolute;\n }\n\n private async prepareDirectory(directory: string): Promise<void> {\n await assertNoSymlinkBetween(this.repositoryRoot, dirname(directory));\n await mkdir(directory, { recursive: true, mode: 0o700 });\n }\n}\n\nfunction copyFact(\n fact: FactFile,\n patch: Partial<Pick<FactFile, \"resolvedBy\" | \"supersededBy\" | \"sourceDeleted\" | \"sharedWith\">>,\n): FactFileWrite {\n const { path: _path, schemaVersion: _schemaVersion, type: _type, ...write } = fact;\n return { ...write, ...patch };\n}\n\nfunction stripUndefinedAndDefaultIncidentFields(\n metadata: Record<string, unknown>,\n): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(metadata).filter(([key, value]) => {\n if (value === undefined) return false;\n if (key === \"category\" && value === \"general\") return false;\n if ((key === \"paths\" || key === \"sharedWith\") && Array.isArray(value) && value.length === 0)\n return false;\n if (\n [\"severity\", \"introducedBy\", \"resolvedBy\", \"propositionKey\", \"idempotencyKey\"].includes(\n key,\n ) &&\n (value === null || value === undefined)\n ) {\n return false;\n }\n return true;\n }),\n );\n}\n\nfunction normalizeMemoryPath(path: string): string {\n return path.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n}\n\nfunction severityRank(severity: IncidentSeverity): number {\n switch (severity) {\n case \"critical\":\n return 4;\n case \"high\":\n return 3;\n case \"medium\":\n return 2;\n case \"low\":\n return 1;\n }\n}\n","/** Lifecycle fields shared by Markdown facts and indexed (database) fact rows. */\nexport type MemoryLifecycle = {\n namespace?: string;\n sourceDeleted: boolean;\n supersededBy?: string | null;\n category?: string;\n resolvedBy?: string | null;\n};\n\n/**\n * The single eligibility rule for durable memory evidence. A fact is eligible\n * when it belongs to the requested namespace, its source was not deleted, and\n * it was not superseded. A resolved incident is eligible only for historical\n * inspection (`includeResolved`). File context, risk signals, and database\n * recall apply this before ranking or deduplication, so ineligible evidence\n * can never displace or suppress eligible evidence.\n */\nexport function isEligibleMemory(\n fact: MemoryLifecycle,\n options: { namespace?: string; includeResolved?: boolean } = {},\n): boolean {\n if (options.namespace && fact.namespace !== options.namespace) return false;\n if (fact.sourceDeleted || fact.supersededBy) return false;\n if (fact.category === \"incident\" && fact.resolvedBy && !options.includeResolved) return false;\n return true;\n}\n"],"mappings":"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","names":["vector","text","text","facts"]}
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
loadProjectArchitectureMap,
|
|
19
19
|
readBoundedSource,
|
|
20
20
|
taskTerms
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-LZTYPJ5I.js";
|
|
22
22
|
import {
|
|
23
23
|
loadKnownSecretValues,
|
|
24
24
|
redactSourceText
|
|
@@ -45,7 +45,7 @@ async function runLeanHook(input, emit, budgetMs = LEAN_HOOK_BUDGET_MS) {
|
|
|
45
45
|
if (prompt === "" || prompt.startsWith("/")) return "";
|
|
46
46
|
const sessionId = input.session_id ?? "default";
|
|
47
47
|
try {
|
|
48
|
-
void import("./local-
|
|
48
|
+
void import("./local-5EYLEBEP.js").then(({ markForeground }) => markForeground(repositoryRoot));
|
|
49
49
|
const { manifest } = await loadFreshIndex(repositoryRoot);
|
|
50
50
|
const renderBy = started + budgetMs - RENDER_RESERVE_MS;
|
|
51
51
|
const discovery = await discoverTaskPaths(
|
|
@@ -187,4 +187,4 @@ export {
|
|
|
187
187
|
renderLeanBlock,
|
|
188
188
|
isReadOnlyPrompt
|
|
189
189
|
};
|
|
190
|
-
//# sourceMappingURL=chunk-
|
|
190
|
+
//# sourceMappingURL=chunk-3TZNQJTH.js.map
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
2
|
asksForChangelog
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-LZTYPJ5I.js";
|
|
4
4
|
import {
|
|
5
5
|
readConfigFile
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-Y4QQML24.js";
|
|
7
7
|
import {
|
|
8
8
|
writeAtomic
|
|
9
9
|
} from "./chunk-CG5B3LYG.js";
|
|
10
10
|
|
|
11
11
|
// src/retrieval/zvec.ts
|
|
12
12
|
import { execFile, spawn } from "child_process";
|
|
13
|
+
import { createHash } from "crypto";
|
|
13
14
|
import { mkdir, readFile, rm, stat, writeFile } from "fs/promises";
|
|
15
|
+
import { homedir } from "os";
|
|
14
16
|
import { dirname, isAbsolute, join, relative, resolve, sep } from "path";
|
|
15
17
|
var SUPPORTED = /^0\.2\.\d+$/;
|
|
18
|
+
var ZG_MAX_LIMIT = 50;
|
|
16
19
|
var DEFAULT_TIMEOUT_MS = 1500;
|
|
17
20
|
var READY_CACHE_MS = 10 * 6e4;
|
|
18
21
|
var NOT_READY_CACHE_MS = 3e4;
|
|
@@ -35,7 +38,10 @@ var TEST_GLOBS = [
|
|
|
35
38
|
"!**/*.spec.*",
|
|
36
39
|
"!**/__tests__/**",
|
|
37
40
|
"!**/test/**",
|
|
38
|
-
"!**/tests/**"
|
|
41
|
+
"!**/tests/**",
|
|
42
|
+
"!**/test_app/**",
|
|
43
|
+
"!**/test_apps/**",
|
|
44
|
+
"!**/testdata/**"
|
|
39
45
|
];
|
|
40
46
|
var ALWAYS_EXCLUDED_GLOBS = ["!evals/**", "!scripts/**", "!.codebuddy/**", "!**/fixtures/**"];
|
|
41
47
|
function zvecExcludeGlobs(task) {
|
|
@@ -71,7 +77,7 @@ async function zvecCandidates(repositoryRoot, task, options = {}) {
|
|
|
71
77
|
return none("no-server", "no running `zg server` (this path never starts one)");
|
|
72
78
|
}
|
|
73
79
|
const limit = Math.min(20, Math.max(1, Math.floor(options.limit ?? 10)));
|
|
74
|
-
const chunkLimit = limit * 8;
|
|
80
|
+
const chunkLimit = Math.min(ZG_MAX_LIMIT, limit * 8);
|
|
75
81
|
const globs = zvecExcludeGlobs(task);
|
|
76
82
|
const query = [
|
|
77
83
|
"query",
|
|
@@ -161,10 +167,11 @@ async function refreshZvecIndex(repositoryRoot, options = {}) {
|
|
|
161
167
|
options.signal
|
|
162
168
|
);
|
|
163
169
|
if (result.error) {
|
|
164
|
-
const failure = fromError(result.error, "zvec-grep refresh");
|
|
170
|
+
const failure = fromError(result.error, "zvec-grep refresh", result.stderr);
|
|
165
171
|
return { status: failure.status, reason: failure.reason };
|
|
166
172
|
}
|
|
167
173
|
await markIndexed(root, startedAt);
|
|
174
|
+
await markReadiness(root, config.binary, null);
|
|
168
175
|
return { status: "ok", reason: "zvec-grep index refreshed" };
|
|
169
176
|
}
|
|
170
177
|
function parseHits(output) {
|
|
@@ -197,12 +204,20 @@ async function zvecStatus(repositoryRoot) {
|
|
|
197
204
|
const supported = found !== null && SUPPORTED.test(found);
|
|
198
205
|
const readiness = supported ? await checkReadiness(run) : null;
|
|
199
206
|
const server = supported ? await run(["server", "status"]) : null;
|
|
207
|
+
const cards = cardsDir(root);
|
|
208
|
+
const cardStatus = supported && await stat(join(cards, ".zvec-grep")).catch(() => null) ? await runZg(
|
|
209
|
+
config.binary,
|
|
210
|
+
["status", cards, "--check-ready", "--mode", "auto"],
|
|
211
|
+
cards,
|
|
212
|
+
5e3
|
|
213
|
+
) : null;
|
|
200
214
|
return {
|
|
201
215
|
enabled: config.enabled,
|
|
202
216
|
binary: config.binary,
|
|
203
217
|
version: found,
|
|
204
218
|
supported,
|
|
205
219
|
indexReady: supported && readiness === null,
|
|
220
|
+
cardIndex: !cardStatus ? "missing" : !cardStatus.error ? "ready" : STALE.test(cardStatus.stdout) ? "stale" : "missing",
|
|
206
221
|
server: server === null || server.error ? "unknown" : /running|ready/i.test(server.stdout) ? "running" : "stopped",
|
|
207
222
|
reason: version.error ? fromError(version.error, "zvec-grep version check").reason : !supported ? `zvec-grep ${found ?? "unknown"} is not 0.2.x` : readiness?.reason ?? "ready"
|
|
208
223
|
};
|
|
@@ -237,13 +252,28 @@ async function buildZvecIndex(repositoryRoot, options = {}) {
|
|
|
237
252
|
return code;
|
|
238
253
|
}
|
|
239
254
|
var NOT_READY = "zvec-grep index missing or not ready; run `codebuddy zvec index`";
|
|
240
|
-
|
|
255
|
+
function cardsDir(repositoryRoot) {
|
|
256
|
+
const base = process.env.CODEBUDDY_CARD_CACHE ?? join(homedir(), ".cache", "codebuddy", "cards");
|
|
257
|
+
const id = createHash("sha256").update(resolve(repositoryRoot)).digest("hex").slice(0, 16);
|
|
258
|
+
return join(base, id);
|
|
259
|
+
}
|
|
260
|
+
var LEGACY_CARDS_DIR = join(".codebuddy", "cache", "cards");
|
|
241
261
|
var DEFAULT_CARD_MODEL = "local/bge-small-en-v1.5";
|
|
242
262
|
async function queryCards(root, task, limit, run) {
|
|
243
|
-
const cards =
|
|
263
|
+
const cards = cardsDir(root);
|
|
244
264
|
if (!await stat(join(cards, ".zvec-grep")).catch(() => null)) return [];
|
|
245
265
|
const result = await run(
|
|
246
|
-
[
|
|
266
|
+
[
|
|
267
|
+
"query",
|
|
268
|
+
"--vector",
|
|
269
|
+
task,
|
|
270
|
+
"--mode",
|
|
271
|
+
"auto",
|
|
272
|
+
"--refresh",
|
|
273
|
+
"off",
|
|
274
|
+
"--limit",
|
|
275
|
+
String(Math.min(ZG_MAX_LIMIT, limit))
|
|
276
|
+
],
|
|
247
277
|
cards
|
|
248
278
|
);
|
|
249
279
|
if (result.error) return [];
|
|
@@ -262,7 +292,7 @@ async function refreshZvecCardIndex(repositoryRoot, options = {}) {
|
|
|
262
292
|
const root = resolve(repositoryRoot);
|
|
263
293
|
const config = await zvecConfig(root);
|
|
264
294
|
if (!config.enabled) return { status: "disabled", reason: "zvec-grep not enabled" };
|
|
265
|
-
const cards =
|
|
295
|
+
const cards = cardsDir(root);
|
|
266
296
|
if (!await stat(cards).catch(() => null))
|
|
267
297
|
return { status: "ok", reason: "no intent cards yet" };
|
|
268
298
|
const exists = await stat(join(cards, ".zvec-grep")).catch(() => null);
|
|
@@ -329,9 +359,10 @@ async function checkReadiness(run) {
|
|
|
329
359
|
return none("unsupported-version", `zvec-grep ${found || "unknown"} is not 0.2.x`);
|
|
330
360
|
}
|
|
331
361
|
const ready = await run(["status", "--check-ready", "--mode", "auto"]);
|
|
332
|
-
if (!ready.error) return null;
|
|
362
|
+
if (!ready.error || STALE.test(ready.stdout)) return null;
|
|
333
363
|
return ready.error.code === "ETIMEDOUT" ? none("timeout", "zvec-grep status timed out") : none("index-not-ready", NOT_READY);
|
|
334
364
|
}
|
|
365
|
+
var STALE = /Workspace index needs an update/;
|
|
335
366
|
function readyPath(root) {
|
|
336
367
|
return join(root, ".codebuddy", "cache", "zvec-ready.json");
|
|
337
368
|
}
|
|
@@ -462,7 +493,9 @@ function fromError(error, what, stderr = "") {
|
|
|
462
493
|
if (error.code === "ETIMEDOUT") return none("timeout", `${what} timed out`);
|
|
463
494
|
if (BUSY.test(stderr)) return none("busy", `${what}: index busy (a zg index refresh is running)`);
|
|
464
495
|
const code = stderr.match(/\bCode:\s*(\S+)/)?.[1];
|
|
465
|
-
|
|
496
|
+
const message = stderr.match(/^(?:Error:\s*)?(.*(?:error|mismatch|does not match|Too big).*)$/im)?.[1]?.trim().slice(0, 160);
|
|
497
|
+
const detail = [code, message].filter(Boolean).join(": ");
|
|
498
|
+
return none("failed", `${what} failed${detail ? ` (${detail})` : ""}`);
|
|
466
499
|
}
|
|
467
500
|
var BUSY = /ZVEC_GREP\.ENGINE\.LOCK\.BUSY/;
|
|
468
501
|
var BUSY_RETRY_MS = 150;
|
|
@@ -480,6 +513,7 @@ function toRepoRelative(root, path) {
|
|
|
480
513
|
}
|
|
481
514
|
|
|
482
515
|
export {
|
|
516
|
+
ZG_MAX_LIMIT,
|
|
483
517
|
DEFAULT_ZVEC_MODEL,
|
|
484
518
|
DEFAULT_ZVEC_MIN_SCORE,
|
|
485
519
|
zvecExcludeGlobs,
|
|
@@ -489,9 +523,10 @@ export {
|
|
|
489
523
|
resetZvecCache,
|
|
490
524
|
zvecStatus,
|
|
491
525
|
buildZvecIndex,
|
|
492
|
-
|
|
526
|
+
cardsDir,
|
|
527
|
+
LEGACY_CARDS_DIR,
|
|
493
528
|
DEFAULT_CARD_MODEL,
|
|
494
529
|
refreshZvecCardIndex,
|
|
495
530
|
ensureZvecServer
|
|
496
531
|
};
|
|
497
|
-
//# sourceMappingURL=chunk-
|
|
532
|
+
//# sourceMappingURL=chunk-4LMBZWIF.js.map
|