memorix 1.7.3 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/cli/index.js +1488 -270
- package/dist/dashboard/static/app.js +125 -27
- package/dist/dashboard/static/index.html +11 -1
- package/dist/dashboard/static/style.css +86 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +927 -240
- package/dist/maintenance-runner.js +607 -68
- package/dist/media-audio-runner.js +602 -63
- package/dist/media-video-runner.js +607 -68
- package/dist/memcode-runtime/CHANGELOG.md +41 -0
- package/dist/sdk.js +926 -239
- package/dist/types.d.ts +8 -0
- package/dist/vector-backfill-runner.js +607 -68
- package/docs/1.2.4-PERSISTENT-MEMORY-DELIVERY.md +1 -1
- package/docs/1.8.0-RELEASE-CANDIDATE-SPEC.md +75 -0
- package/docs/API_REFERENCE.md +39 -1
- package/docs/ARCHITECTURE.md +3 -1
- package/docs/DASHBOARD.md +16 -0
- package/docs/DEVELOPMENT.md +3 -2
- package/docs/INTEGRATIONS.md +1 -1
- package/docs/README.md +15 -2
- package/package.json +1 -1
- package/plugins/antigravity/memorix/rules/memorix.md +1 -1
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/memorix/SKILL.md +1 -1
- package/plugins/claude/memorix/skills/memorix-memory/SKILL.md +2 -2
- package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
- package/plugins/codebuddy/memorix/skills/memorix-memory/SKILL.md +2 -2
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/skills/memorix-memory/SKILL.md +2 -2
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/copilot/memorix/skills/memorix-memory/SKILL.md +2 -2
- package/plugins/cursor/memorix/skills/memorix-memory/SKILL.md +2 -2
- package/plugins/gemini/memorix/GEMINI.md +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +1 -1
- package/plugins/omp/memorix/package.json +1 -1
- package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/pi/memorix/package.json +1 -1
- package/plugins/pi/memorix/skills/memorix-memory/SKILL.md +2 -2
- package/server.json +2 -2
- package/src/cli/capability-map.ts +2 -0
- package/src/cli/commands/context.ts +11 -0
- package/src/cli/commands/dashboard.ts +1 -1
- package/src/cli/commands/evidence.ts +56 -0
- package/src/cli/commands/feedback.ts +58 -0
- package/src/cli/commands/resume.ts +2 -0
- package/src/cli/commands/serve-http.ts +229 -13
- package/src/cli/fallback-budget.ts +59 -0
- package/src/cli/index.ts +5 -1
- package/src/compact/engine.ts +26 -1
- package/src/config/dotenv-loader.ts +17 -0
- package/src/dashboard/config-provenance.ts +17 -0
- package/src/dashboard/evidence.ts +63 -0
- package/src/dashboard/server.ts +178 -154
- package/src/dashboard/static/index.html +11 -1
- package/src/dashboard/static/style.css +86 -0
- package/src/hooks/installers/index.ts +1 -1
- package/src/hooks/official-skills.ts +3 -3
- package/src/hooks/rules/memorix-agent-rules.md +1 -1
- package/src/memory/feedback-model.ts +4 -0
- package/src/memory/feedback.ts +220 -0
- package/src/memory/observations.ts +19 -0
- package/src/memory/retention.ts +38 -5
- package/src/server/mcp-binding-store.ts +79 -0
- package/src/server/mcp-diagnostics.ts +40 -0
- package/src/server/tool-profile.ts +4 -0
- package/src/server.ts +125 -5
- package/src/store/evidence-store.ts +261 -0
- package/src/store/sqlite-db.ts +104 -0
- package/src/types.ts +8 -0
|
@@ -338,7 +338,7 @@ function closeAllDatabases() {
|
|
|
338
338
|
_dbCache.delete(key);
|
|
339
339
|
}
|
|
340
340
|
}
|
|
341
|
-
var BetterSqlite3, CREATE_OBSERVATIONS_TABLE, CREATE_MINI_SKILLS_TABLE, CREATE_SESSIONS_TABLE, CREATE_META_TABLE, CREATE_TEAM_AGENTS_TABLE, CREATE_TEAM_MESSAGES_TABLE, CREATE_TEAM_TASKS_TABLE, CREATE_TEAM_TASK_DEPS_TABLE, CREATE_TEAM_LOCKS_TABLE, CREATE_TEAM_ROLES_TABLE, CREATE_CHAT_TRANSCRIPT_TABLE, CREATE_GRAPH_ENTITIES_TABLE, CREATE_GRAPH_RELATIONS_TABLE, CREATE_CODE_FILES_TABLE, CREATE_CODE_SYMBOLS_TABLE, CREATE_CODE_EDGES_TABLE, CREATE_OBSERVATION_CODE_REFS_TABLE, CREATE_SCHEMA_MIGRATIONS_TABLE, CREATE_CODE_STATE_SNAPSHOTS_TABLE, CREATE_CODE_STATE_SNAPSHOT_FILES_TABLE, CREATE_KNOWLEDGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_CLAIM_EVIDENCE_TABLE, CREATE_KNOWLEDGE_CLAIM_EVENTS_TABLE, CREATE_KNOWLEDGE_WORKSPACES_TABLE, CREATE_KNOWLEDGE_PAGES_TABLE, CREATE_KNOWLEDGE_PAGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_PAGE_LINKS_TABLE, CREATE_KNOWLEDGE_PROPOSALS_TABLE, CREATE_KNOWLEDGE_WORKFLOWS_TABLE, CREATE_KNOWLEDGE_WORKFLOW_RUNS_TABLE, CREATE_LONG_TERM_MEMORIES_TABLE, CREATE_LONG_TERM_MEMORY_EVIDENCE_TABLE, CREATE_LONG_TERM_MEMORY_EVENTS_TABLE, CREATE_MEMORY_OUTCOME_SIGNALS_TABLE, CREATE_MEDIA_ASSETS_TABLE, CREATE_MEDIA_ASSET_LINKS_TABLE, CREATE_MEDIA_DERIVATIONS_TABLE, CREATE_MEDIA_EMBEDDING_PROFILES_TABLE, CREATE_MEDIA_EMBEDDINGS_TABLE, CREATE_MEDIA_JOBS_TABLE, CREATE_MAINTENANCE_JOBS_TABLE, CREATE_MAINTENANCE_TARGETS_TABLE, CREATE_COMPACTION_CHECKPOINTS_TABLE, CREATE_INDEXES, SCHEMA_MIGRATIONS, _dbCache;
|
|
341
|
+
var BetterSqlite3, CREATE_OBSERVATIONS_TABLE, CREATE_MINI_SKILLS_TABLE, CREATE_SESSIONS_TABLE, CREATE_META_TABLE, CREATE_TEAM_AGENTS_TABLE, CREATE_TEAM_MESSAGES_TABLE, CREATE_TEAM_TASKS_TABLE, CREATE_TEAM_TASK_DEPS_TABLE, CREATE_TEAM_LOCKS_TABLE, CREATE_TEAM_ROLES_TABLE, CREATE_CHAT_TRANSCRIPT_TABLE, CREATE_GRAPH_ENTITIES_TABLE, CREATE_GRAPH_RELATIONS_TABLE, CREATE_CODE_FILES_TABLE, CREATE_CODE_SYMBOLS_TABLE, CREATE_CODE_EDGES_TABLE, CREATE_OBSERVATION_CODE_REFS_TABLE, CREATE_SCHEMA_MIGRATIONS_TABLE, CREATE_CODE_STATE_SNAPSHOTS_TABLE, CREATE_CODE_STATE_SNAPSHOT_FILES_TABLE, CREATE_KNOWLEDGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_CLAIM_EVIDENCE_TABLE, CREATE_KNOWLEDGE_CLAIM_EVENTS_TABLE, CREATE_KNOWLEDGE_WORKSPACES_TABLE, CREATE_KNOWLEDGE_PAGES_TABLE, CREATE_KNOWLEDGE_PAGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_PAGE_LINKS_TABLE, CREATE_KNOWLEDGE_PROPOSALS_TABLE, CREATE_KNOWLEDGE_WORKFLOWS_TABLE, CREATE_KNOWLEDGE_WORKFLOW_RUNS_TABLE, CREATE_LONG_TERM_MEMORIES_TABLE, CREATE_LONG_TERM_MEMORY_EVIDENCE_TABLE, CREATE_LONG_TERM_MEMORY_EVENTS_TABLE, CREATE_MEMORY_OUTCOME_SIGNALS_TABLE, CREATE_MEDIA_ASSETS_TABLE, CREATE_MEDIA_ASSET_LINKS_TABLE, CREATE_MEDIA_DERIVATIONS_TABLE, CREATE_MEDIA_EMBEDDING_PROFILES_TABLE, CREATE_MEDIA_EMBEDDINGS_TABLE, CREATE_MEDIA_JOBS_TABLE, CREATE_MAINTENANCE_JOBS_TABLE, CREATE_MAINTENANCE_TARGETS_TABLE, CREATE_COMPACTION_CHECKPOINTS_TABLE, CREATE_EVIDENCE_CARDS_TABLE, CREATE_EVIDENCE_CARD_EVENTS_TABLE, CREATE_MEMORY_FEEDBACK_STATES_TABLE, CREATE_MEMORY_FEEDBACK_EVENTS_TABLE, CREATE_MCP_BINDINGS_TABLE, CREATE_INDEXES, SCHEMA_MIGRATIONS, _dbCache;
|
|
342
342
|
var init_sqlite_db = __esm({
|
|
343
343
|
"src/store/sqlite-db.ts"() {
|
|
344
344
|
"use strict";
|
|
@@ -984,6 +984,79 @@ CREATE TABLE IF NOT EXISTS compaction_checkpoints (
|
|
|
984
984
|
created_at TEXT NOT NULL,
|
|
985
985
|
updated_at TEXT NOT NULL
|
|
986
986
|
);
|
|
987
|
+
`;
|
|
988
|
+
CREATE_EVIDENCE_CARDS_TABLE = `
|
|
989
|
+
CREATE TABLE IF NOT EXISTS evidence_cards (
|
|
990
|
+
id TEXT PRIMARY KEY,
|
|
991
|
+
project_id TEXT NOT NULL,
|
|
992
|
+
candidate_kind TEXT NOT NULL,
|
|
993
|
+
candidate_id TEXT NOT NULL,
|
|
994
|
+
title TEXT NOT NULL,
|
|
995
|
+
summary TEXT NOT NULL DEFAULT '',
|
|
996
|
+
entity_name TEXT,
|
|
997
|
+
source_kind TEXT NOT NULL,
|
|
998
|
+
source_ref TEXT NOT NULL,
|
|
999
|
+
locator TEXT,
|
|
1000
|
+
captured_hash TEXT,
|
|
1001
|
+
session_id TEXT,
|
|
1002
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
1003
|
+
verification TEXT NOT NULL DEFAULT 'unverified',
|
|
1004
|
+
freshness TEXT NOT NULL DEFAULT 'current',
|
|
1005
|
+
stale_reason TEXT,
|
|
1006
|
+
files_json TEXT NOT NULL DEFAULT '[]',
|
|
1007
|
+
related_entities_json TEXT NOT NULL DEFAULT '[]',
|
|
1008
|
+
created_at TEXT NOT NULL,
|
|
1009
|
+
updated_at TEXT NOT NULL,
|
|
1010
|
+
UNIQUE(project_id, candidate_kind, candidate_id)
|
|
1011
|
+
);
|
|
1012
|
+
`;
|
|
1013
|
+
CREATE_EVIDENCE_CARD_EVENTS_TABLE = `
|
|
1014
|
+
CREATE TABLE IF NOT EXISTS evidence_card_events (
|
|
1015
|
+
id TEXT PRIMARY KEY,
|
|
1016
|
+
project_id TEXT NOT NULL,
|
|
1017
|
+
card_id TEXT NOT NULL,
|
|
1018
|
+
kind TEXT NOT NULL,
|
|
1019
|
+
detail TEXT,
|
|
1020
|
+
created_at TEXT NOT NULL,
|
|
1021
|
+
FOREIGN KEY (card_id) REFERENCES evidence_cards(id) ON DELETE CASCADE
|
|
1022
|
+
);
|
|
1023
|
+
`;
|
|
1024
|
+
CREATE_MEMORY_FEEDBACK_STATES_TABLE = `
|
|
1025
|
+
CREATE TABLE IF NOT EXISTS memory_feedback_states (
|
|
1026
|
+
project_id TEXT NOT NULL,
|
|
1027
|
+
candidate_kind TEXT NOT NULL,
|
|
1028
|
+
candidate_id TEXT NOT NULL,
|
|
1029
|
+
weight REAL NOT NULL DEFAULT 1.0,
|
|
1030
|
+
lifecycle_status TEXT NOT NULL DEFAULT 'active',
|
|
1031
|
+
updated_at TEXT NOT NULL,
|
|
1032
|
+
PRIMARY KEY (project_id, candidate_kind, candidate_id)
|
|
1033
|
+
);
|
|
1034
|
+
`;
|
|
1035
|
+
CREATE_MEMORY_FEEDBACK_EVENTS_TABLE = `
|
|
1036
|
+
CREATE TABLE IF NOT EXISTS memory_feedback_events (
|
|
1037
|
+
id TEXT PRIMARY KEY,
|
|
1038
|
+
project_id TEXT NOT NULL,
|
|
1039
|
+
candidate_kind TEXT NOT NULL,
|
|
1040
|
+
candidate_id TEXT NOT NULL,
|
|
1041
|
+
signal TEXT NOT NULL,
|
|
1042
|
+
actor TEXT,
|
|
1043
|
+
note TEXT,
|
|
1044
|
+
source_ref TEXT NOT NULL,
|
|
1045
|
+
target_event_id TEXT,
|
|
1046
|
+
delta REAL NOT NULL DEFAULT 0,
|
|
1047
|
+
observed_at TEXT NOT NULL
|
|
1048
|
+
);
|
|
1049
|
+
`;
|
|
1050
|
+
CREATE_MCP_BINDINGS_TABLE = `
|
|
1051
|
+
CREATE TABLE IF NOT EXISTS mcp_bindings (
|
|
1052
|
+
handle_id TEXT PRIMARY KEY,
|
|
1053
|
+
project_id TEXT NOT NULL,
|
|
1054
|
+
project_root TEXT NOT NULL,
|
|
1055
|
+
data_dir TEXT NOT NULL,
|
|
1056
|
+
created_at TEXT NOT NULL,
|
|
1057
|
+
last_used_at TEXT NOT NULL,
|
|
1058
|
+
expires_at TEXT
|
|
1059
|
+
);
|
|
987
1060
|
`;
|
|
988
1061
|
CREATE_INDEXES = `
|
|
989
1062
|
CREATE INDEX IF NOT EXISTS idx_observations_projectId ON observations(projectId);
|
|
@@ -1046,6 +1119,12 @@ CREATE INDEX IF NOT EXISTS idx_maintenance_targets_updated ON maintenance_target
|
|
|
1046
1119
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_project_recent ON compaction_checkpoints(project_id, status, completed_at DESC, pre_captured_at DESC);
|
|
1047
1120
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_session_pending ON compaction_checkpoints(project_id, session_id, agent, phase, status, pre_captured_at DESC);
|
|
1048
1121
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_source ON compaction_checkpoints(project_id, source_key);
|
|
1122
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_cards_project ON evidence_cards(project_id, status, updated_at DESC);
|
|
1123
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(project_id, candidate_kind, candidate_id);
|
|
1124
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at);
|
|
1125
|
+
CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC);
|
|
1126
|
+
CREATE INDEX IF NOT EXISTS idx_memory_feedback_events_candidate ON memory_feedback_events(project_id, candidate_kind, candidate_id, observed_at DESC);
|
|
1127
|
+
CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC);
|
|
1049
1128
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
1050
1129
|
ON maintenance_jobs(project_id, kind, dedupe_key)
|
|
1051
1130
|
WHERE status IN ('pending', 'running', 'retry');
|
|
@@ -1201,6 +1280,22 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
|
1201
1280
|
}
|
|
1202
1281
|
db2.exec("CREATE INDEX IF NOT EXISTS idx_media_jobs_source_asset ON media_jobs(project_id, source_asset_id, status)");
|
|
1203
1282
|
}
|
|
1283
|
+
},
|
|
1284
|
+
{
|
|
1285
|
+
id: "1.8-context-control-plane",
|
|
1286
|
+
apply: (db2) => {
|
|
1287
|
+
db2.exec(CREATE_EVIDENCE_CARDS_TABLE);
|
|
1288
|
+
db2.exec(CREATE_EVIDENCE_CARD_EVENTS_TABLE);
|
|
1289
|
+
db2.exec(CREATE_MEMORY_FEEDBACK_STATES_TABLE);
|
|
1290
|
+
db2.exec(CREATE_MEMORY_FEEDBACK_EVENTS_TABLE);
|
|
1291
|
+
db2.exec(CREATE_MCP_BINDINGS_TABLE);
|
|
1292
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_cards_project ON evidence_cards(project_id, status, updated_at DESC)");
|
|
1293
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(project_id, candidate_kind, candidate_id)");
|
|
1294
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at)");
|
|
1295
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC)");
|
|
1296
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_memory_feedback_events_candidate ON memory_feedback_events(project_id, candidate_kind, candidate_id, observed_at DESC)");
|
|
1297
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC)");
|
|
1298
|
+
}
|
|
1204
1299
|
}
|
|
1205
1300
|
];
|
|
1206
1301
|
_dbCache = /* @__PURE__ */ new Map();
|
|
@@ -1246,6 +1341,8 @@ function loadEnvFile(filePath) {
|
|
|
1246
1341
|
const parsed = parse(readFileSync2(filePath, "utf-8"));
|
|
1247
1342
|
for (const [key, value] of Object.entries(parsed)) {
|
|
1248
1343
|
if (!(key in process.env)) {
|
|
1344
|
+
loadedEnvKeys.add(key);
|
|
1345
|
+
loadedEnvValues.set(key, value);
|
|
1249
1346
|
process.env[key] = value;
|
|
1250
1347
|
injectedKeys.add(key);
|
|
1251
1348
|
}
|
|
@@ -1258,6 +1355,8 @@ function loadDotenv(projectRoot, options = {}) {
|
|
|
1258
1355
|
resetDotenv();
|
|
1259
1356
|
}
|
|
1260
1357
|
loadedEnvFiles.length = 0;
|
|
1358
|
+
loadedEnvKeys.clear();
|
|
1359
|
+
loadedEnvValues.clear();
|
|
1261
1360
|
if (projectRoot) {
|
|
1262
1361
|
loadEnvFile(getProjectDotenvPath(projectRoot));
|
|
1263
1362
|
}
|
|
@@ -1273,11 +1372,12 @@ function resetDotenv() {
|
|
|
1273
1372
|
dotenvLoaded = false;
|
|
1274
1373
|
dotenvProjectRoot = null;
|
|
1275
1374
|
loadedEnvFiles.length = 0;
|
|
1375
|
+
loadedEnvKeys.clear();
|
|
1276
1376
|
}
|
|
1277
1377
|
function getLoadedEnvFiles() {
|
|
1278
1378
|
return loadedEnvFiles;
|
|
1279
1379
|
}
|
|
1280
|
-
var dotenvLoaded, dotenvProjectRoot, loadedEnvFiles, injectedKeys;
|
|
1380
|
+
var dotenvLoaded, dotenvProjectRoot, loadedEnvFiles, loadedEnvKeys, loadedEnvValues, injectedKeys;
|
|
1281
1381
|
var init_dotenv_loader = __esm({
|
|
1282
1382
|
"src/config/dotenv-loader.ts"() {
|
|
1283
1383
|
"use strict";
|
|
@@ -1286,6 +1386,8 @@ var init_dotenv_loader = __esm({
|
|
|
1286
1386
|
dotenvLoaded = false;
|
|
1287
1387
|
dotenvProjectRoot = null;
|
|
1288
1388
|
loadedEnvFiles = [];
|
|
1389
|
+
loadedEnvKeys = /* @__PURE__ */ new Set();
|
|
1390
|
+
loadedEnvValues = /* @__PURE__ */ new Map();
|
|
1289
1391
|
injectedKeys = /* @__PURE__ */ new Set();
|
|
1290
1392
|
}
|
|
1291
1393
|
});
|
|
@@ -7981,6 +8083,226 @@ var init_lifecycle = __esm({
|
|
|
7981
8083
|
}
|
|
7982
8084
|
});
|
|
7983
8085
|
|
|
8086
|
+
// src/store/evidence-store.ts
|
|
8087
|
+
import { createHash as createHash3, randomUUID as randomUUID3 } from "crypto";
|
|
8088
|
+
function safeJson(value, fallback) {
|
|
8089
|
+
if (typeof value !== "string" || value.length === 0) return fallback;
|
|
8090
|
+
try {
|
|
8091
|
+
return JSON.parse(value);
|
|
8092
|
+
} catch {
|
|
8093
|
+
return fallback;
|
|
8094
|
+
}
|
|
8095
|
+
}
|
|
8096
|
+
function rowToCard(row) {
|
|
8097
|
+
return {
|
|
8098
|
+
id: String(row.id),
|
|
8099
|
+
projectId: String(row.project_id),
|
|
8100
|
+
candidateKind: row.candidate_kind,
|
|
8101
|
+
candidateId: String(row.candidate_id),
|
|
8102
|
+
title: String(row.title),
|
|
8103
|
+
summary: String(row.summary ?? ""),
|
|
8104
|
+
...row.entity_name ? { entityName: String(row.entity_name) } : {},
|
|
8105
|
+
sourceKind: String(row.source_kind),
|
|
8106
|
+
sourceRef: String(row.source_ref),
|
|
8107
|
+
...row.locator ? { locator: String(row.locator) } : {},
|
|
8108
|
+
...row.captured_hash ? { capturedHash: String(row.captured_hash) } : {},
|
|
8109
|
+
...row.session_id ? { sessionId: String(row.session_id) } : {},
|
|
8110
|
+
status: String(row.status ?? "active"),
|
|
8111
|
+
verification: row.verification,
|
|
8112
|
+
freshness: row.freshness,
|
|
8113
|
+
...row.stale_reason ? { staleReason: String(row.stale_reason) } : {},
|
|
8114
|
+
files: safeJson(row.files_json, []),
|
|
8115
|
+
relatedEntities: safeJson(row.related_entities_json, []),
|
|
8116
|
+
createdAt: String(row.created_at),
|
|
8117
|
+
updatedAt: String(row.updated_at)
|
|
8118
|
+
};
|
|
8119
|
+
}
|
|
8120
|
+
function observationHash(observation) {
|
|
8121
|
+
return createHash3("sha256").update(JSON.stringify({
|
|
8122
|
+
projectId: observation.projectId,
|
|
8123
|
+
id: observation.id,
|
|
8124
|
+
title: observation.title,
|
|
8125
|
+
narrative: observation.narrative,
|
|
8126
|
+
facts: observation.facts,
|
|
8127
|
+
files: observation.filesModified,
|
|
8128
|
+
relatedEntities: observation.relatedEntities
|
|
8129
|
+
})).digest("hex");
|
|
8130
|
+
}
|
|
8131
|
+
function sourceKind(observation) {
|
|
8132
|
+
if (observation.source === "git" || observation.sourceDetail === "git-ingest") return "git";
|
|
8133
|
+
if (observation.sourceDetail === "hook") return "hook";
|
|
8134
|
+
return observation.source ?? "agent";
|
|
8135
|
+
}
|
|
8136
|
+
var EvidenceCardStore;
|
|
8137
|
+
var init_evidence_store = __esm({
|
|
8138
|
+
"src/store/evidence-store.ts"() {
|
|
8139
|
+
"use strict";
|
|
8140
|
+
init_esm_shims();
|
|
8141
|
+
init_sqlite_db();
|
|
8142
|
+
EvidenceCardStore = class {
|
|
8143
|
+
db = null;
|
|
8144
|
+
async init(dataDir) {
|
|
8145
|
+
this.db = getDatabase(dataDir);
|
|
8146
|
+
}
|
|
8147
|
+
requireDb() {
|
|
8148
|
+
if (!this.db) throw new Error("EvidenceCardStore is not initialized.");
|
|
8149
|
+
return this.db;
|
|
8150
|
+
}
|
|
8151
|
+
upsertObservation(observation) {
|
|
8152
|
+
const db2 = this.requireDb();
|
|
8153
|
+
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
8154
|
+
const card = {
|
|
8155
|
+
id: `evidence:observation:${observation.projectId}:${observation.id}`,
|
|
8156
|
+
projectId: observation.projectId,
|
|
8157
|
+
candidateKind: "observation",
|
|
8158
|
+
candidateId: String(observation.id),
|
|
8159
|
+
title: observation.title,
|
|
8160
|
+
summary: observation.narrative.slice(0, 500),
|
|
8161
|
+
entityName: observation.entityName,
|
|
8162
|
+
sourceKind: sourceKind(observation),
|
|
8163
|
+
sourceRef: `observation:${observation.id}`,
|
|
8164
|
+
locator: observation.filesModified?.join(", ") || `observation:${observation.id}`,
|
|
8165
|
+
capturedHash: observationHash(observation),
|
|
8166
|
+
...observation.sessionId ? { sessionId: observation.sessionId } : {},
|
|
8167
|
+
status: observation.status ?? "active",
|
|
8168
|
+
verification: observation.status === "resolved" ? "verified" : "unverified",
|
|
8169
|
+
freshness: "current",
|
|
8170
|
+
files: observation.filesModified ?? [],
|
|
8171
|
+
relatedEntities: observation.relatedEntities ?? [],
|
|
8172
|
+
createdAt: observation.createdAt,
|
|
8173
|
+
updatedAt: now3
|
|
8174
|
+
};
|
|
8175
|
+
db2.prepare(`
|
|
8176
|
+
INSERT INTO evidence_cards (
|
|
8177
|
+
id, project_id, candidate_kind, candidate_id, title, summary, entity_name,
|
|
8178
|
+
source_kind, source_ref, locator, captured_hash, session_id, status,
|
|
8179
|
+
verification, freshness, stale_reason, files_json, related_entities_json,
|
|
8180
|
+
created_at, updated_at
|
|
8181
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?)
|
|
8182
|
+
ON CONFLICT(project_id, candidate_kind, candidate_id) DO UPDATE SET
|
|
8183
|
+
title = excluded.title,
|
|
8184
|
+
summary = excluded.summary,
|
|
8185
|
+
entity_name = excluded.entity_name,
|
|
8186
|
+
source_kind = excluded.source_kind,
|
|
8187
|
+
source_ref = excluded.source_ref,
|
|
8188
|
+
locator = excluded.locator,
|
|
8189
|
+
captured_hash = excluded.captured_hash,
|
|
8190
|
+
session_id = excluded.session_id,
|
|
8191
|
+
status = excluded.status,
|
|
8192
|
+
freshness = 'current',
|
|
8193
|
+
stale_reason = NULL,
|
|
8194
|
+
files_json = excluded.files_json,
|
|
8195
|
+
related_entities_json = excluded.related_entities_json,
|
|
8196
|
+
updated_at = excluded.updated_at
|
|
8197
|
+
`).run(
|
|
8198
|
+
card.id,
|
|
8199
|
+
card.projectId,
|
|
8200
|
+
card.candidateKind,
|
|
8201
|
+
card.candidateId,
|
|
8202
|
+
card.title,
|
|
8203
|
+
card.summary,
|
|
8204
|
+
card.entityName ?? null,
|
|
8205
|
+
card.sourceKind,
|
|
8206
|
+
card.sourceRef,
|
|
8207
|
+
card.locator ?? null,
|
|
8208
|
+
card.capturedHash ?? null,
|
|
8209
|
+
card.sessionId ?? null,
|
|
8210
|
+
card.status,
|
|
8211
|
+
card.verification,
|
|
8212
|
+
card.freshness,
|
|
8213
|
+
JSON.stringify(card.files),
|
|
8214
|
+
JSON.stringify(card.relatedEntities),
|
|
8215
|
+
card.createdAt,
|
|
8216
|
+
card.updatedAt
|
|
8217
|
+
);
|
|
8218
|
+
return this.get(card.projectId, card.candidateKind, card.candidateId) ?? card;
|
|
8219
|
+
}
|
|
8220
|
+
get(projectId, candidateKind, candidateId) {
|
|
8221
|
+
const row = this.requireDb().prepare(`
|
|
8222
|
+
SELECT * FROM evidence_cards WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
8223
|
+
`).get(projectId, candidateKind, candidateId);
|
|
8224
|
+
return row ? rowToCard(row) : void 0;
|
|
8225
|
+
}
|
|
8226
|
+
list(projectId, options = {}) {
|
|
8227
|
+
const limit2 = Math.min(100, Math.max(1, Math.floor(options.limit ?? 20)));
|
|
8228
|
+
const clauses = ["project_id = ?"];
|
|
8229
|
+
const args = [projectId];
|
|
8230
|
+
if (options.freshness) {
|
|
8231
|
+
clauses.push("freshness = ?");
|
|
8232
|
+
args.push(options.freshness);
|
|
8233
|
+
}
|
|
8234
|
+
if (options.status) {
|
|
8235
|
+
clauses.push("status = ?");
|
|
8236
|
+
args.push(options.status);
|
|
8237
|
+
}
|
|
8238
|
+
args.push(limit2);
|
|
8239
|
+
const rows = this.requireDb().prepare(`
|
|
8240
|
+
SELECT * FROM evidence_cards WHERE ${clauses.join(" AND ")} ORDER BY updated_at DESC, id DESC LIMIT ?
|
|
8241
|
+
`).all(...args);
|
|
8242
|
+
return rows.map(rowToCard);
|
|
8243
|
+
}
|
|
8244
|
+
syncObservations(observations2) {
|
|
8245
|
+
return observations2.map((observation) => this.upsertObservation(observation));
|
|
8246
|
+
}
|
|
8247
|
+
markStaleForPaths(projectId, paths, reason = "source file changed") {
|
|
8248
|
+
const normalized = new Set(paths.map((value) => value.replace(/\\/g, "/").toLowerCase()));
|
|
8249
|
+
if (normalized.size === 0) return 0;
|
|
8250
|
+
const db2 = this.requireDb();
|
|
8251
|
+
const rows = db2.prepare(`SELECT * FROM evidence_cards WHERE project_id = ? AND freshness != 'stale'`).all(projectId);
|
|
8252
|
+
const update2 = db2.prepare(`
|
|
8253
|
+
UPDATE evidence_cards SET freshness = 'stale', stale_reason = ?, updated_at = ?
|
|
8254
|
+
WHERE id = ?
|
|
8255
|
+
`);
|
|
8256
|
+
let changed = 0;
|
|
8257
|
+
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
8258
|
+
const run = db2.transaction(() => {
|
|
8259
|
+
for (const row of rows) {
|
|
8260
|
+
const files = safeJson(row.files_json, []);
|
|
8261
|
+
if (!files.some((file) => normalized.has(file.replace(/\\/g, "/").toLowerCase()))) continue;
|
|
8262
|
+
update2.run(reason, now3, row.id);
|
|
8263
|
+
changed++;
|
|
8264
|
+
}
|
|
8265
|
+
});
|
|
8266
|
+
run();
|
|
8267
|
+
return changed;
|
|
8268
|
+
}
|
|
8269
|
+
setVerification(projectId, cardId, verification) {
|
|
8270
|
+
this.requireDb().prepare(`
|
|
8271
|
+
UPDATE evidence_cards SET verification = ?, updated_at = ? WHERE project_id = ? AND id = ?
|
|
8272
|
+
`).run(verification, (/* @__PURE__ */ new Date()).toISOString(), projectId, cardId);
|
|
8273
|
+
}
|
|
8274
|
+
recordEvent(projectId, cardId, kind, detail) {
|
|
8275
|
+
const event = {
|
|
8276
|
+
id: randomUUID3(),
|
|
8277
|
+
projectId,
|
|
8278
|
+
cardId,
|
|
8279
|
+
kind,
|
|
8280
|
+
...detail ? { detail: detail.slice(0, 2e3) } : {},
|
|
8281
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8282
|
+
};
|
|
8283
|
+
this.requireDb().prepare(`
|
|
8284
|
+
INSERT INTO evidence_card_events (id, project_id, card_id, kind, detail, created_at)
|
|
8285
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
8286
|
+
`).run(event.id, event.projectId, event.cardId, event.kind, event.detail ?? null, event.createdAt);
|
|
8287
|
+
return event;
|
|
8288
|
+
}
|
|
8289
|
+
listEvents(cardId, limit2 = 50) {
|
|
8290
|
+
const rows = this.requireDb().prepare(`
|
|
8291
|
+
SELECT * FROM evidence_card_events WHERE card_id = ? ORDER BY created_at DESC LIMIT ?
|
|
8292
|
+
`).all(cardId, Math.min(200, Math.max(1, Math.floor(limit2))));
|
|
8293
|
+
return rows.map((row) => ({
|
|
8294
|
+
id: String(row.id),
|
|
8295
|
+
projectId: String(row.project_id),
|
|
8296
|
+
cardId: String(row.card_id),
|
|
8297
|
+
kind: String(row.kind),
|
|
8298
|
+
...row.detail ? { detail: String(row.detail) } : {},
|
|
8299
|
+
createdAt: String(row.created_at)
|
|
8300
|
+
}));
|
|
8301
|
+
}
|
|
8302
|
+
};
|
|
8303
|
+
}
|
|
8304
|
+
});
|
|
8305
|
+
|
|
7984
8306
|
// src/runtime/isolated-maintenance.ts
|
|
7985
8307
|
import { spawn } from "child_process";
|
|
7986
8308
|
import { existsSync as existsSync8 } from "fs";
|
|
@@ -8012,7 +8334,7 @@ var init_isolated_maintenance = __esm({
|
|
|
8012
8334
|
});
|
|
8013
8335
|
|
|
8014
8336
|
// src/knowledge/workspace-store.ts
|
|
8015
|
-
import { randomUUID as
|
|
8337
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
8016
8338
|
function arrayValue(raw) {
|
|
8017
8339
|
if (typeof raw !== "string" || !raw) return [];
|
|
8018
8340
|
try {
|
|
@@ -8153,7 +8475,7 @@ var init_workspace_store = __esm({
|
|
|
8153
8475
|
}
|
|
8154
8476
|
createProposal(input) {
|
|
8155
8477
|
const proposal = {
|
|
8156
|
-
id: input.id ??
|
|
8478
|
+
id: input.id ?? randomUUID4(),
|
|
8157
8479
|
...input,
|
|
8158
8480
|
status: input.status ?? "pending",
|
|
8159
8481
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -8206,13 +8528,13 @@ __export(workspace_exports, {
|
|
|
8206
8528
|
loadKnowledgeWorkspace: () => loadKnowledgeWorkspace,
|
|
8207
8529
|
resolveKnowledgeWorkspaceFile: () => resolveKnowledgeWorkspaceFile
|
|
8208
8530
|
});
|
|
8209
|
-
import { createHash as
|
|
8531
|
+
import { createHash as createHash4 } from "crypto";
|
|
8210
8532
|
import { execFile } from "child_process";
|
|
8211
8533
|
import { promises as fs6 } from "fs";
|
|
8212
8534
|
import path10 from "path";
|
|
8213
8535
|
import { promisify } from "util";
|
|
8214
8536
|
function hash(value) {
|
|
8215
|
-
return
|
|
8537
|
+
return createHash4("sha256").update(value).digest("hex");
|
|
8216
8538
|
}
|
|
8217
8539
|
function workspaceId(projectId, mode) {
|
|
8218
8540
|
return "workspace:" + hash(projectId + ":" + mode).slice(0, 24);
|
|
@@ -8808,7 +9130,7 @@ Respond in JSON only:
|
|
|
8808
9130
|
});
|
|
8809
9131
|
|
|
8810
9132
|
// src/media/media-store.ts
|
|
8811
|
-
import { randomUUID as
|
|
9133
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
8812
9134
|
function asOptionalText(value) {
|
|
8813
9135
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
8814
9136
|
}
|
|
@@ -8978,7 +9300,7 @@ var init_media_store = __esm({
|
|
|
8978
9300
|
return { asset: this.getAsset(input.projectId, existing.id), deduplicated: true };
|
|
8979
9301
|
}
|
|
8980
9302
|
const asset = {
|
|
8981
|
-
id:
|
|
9303
|
+
id: randomUUID5(),
|
|
8982
9304
|
...input,
|
|
8983
9305
|
createdAt: now3,
|
|
8984
9306
|
updatedAt: now3
|
|
@@ -9058,7 +9380,7 @@ var init_media_store = __esm({
|
|
|
9058
9380
|
`).get(input.assetId, input.observationId ?? null, input.role);
|
|
9059
9381
|
if (existing) return rowToLink(existing);
|
|
9060
9382
|
const link = {
|
|
9061
|
-
id:
|
|
9383
|
+
id: randomUUID5(),
|
|
9062
9384
|
assetId: input.assetId,
|
|
9063
9385
|
projectId: input.projectId,
|
|
9064
9386
|
...input.observationId !== void 0 ? { observationId: input.observationId } : {},
|
|
@@ -9097,7 +9419,7 @@ var init_media_store = __esm({
|
|
|
9097
9419
|
return rowToDerivation(this.db.prepare("SELECT * FROM media_derivations WHERE id = ?").get(existing.id));
|
|
9098
9420
|
}
|
|
9099
9421
|
const derivation = {
|
|
9100
|
-
id:
|
|
9422
|
+
id: randomUUID5(),
|
|
9101
9423
|
...input,
|
|
9102
9424
|
content,
|
|
9103
9425
|
...error ? { error } : {},
|
|
@@ -9184,7 +9506,7 @@ var init_media_store = __esm({
|
|
|
9184
9506
|
createJob(input) {
|
|
9185
9507
|
const now3 = Date.now();
|
|
9186
9508
|
const job = {
|
|
9187
|
-
id:
|
|
9509
|
+
id: randomUUID5(),
|
|
9188
9510
|
projectId: input.projectId,
|
|
9189
9511
|
kind: input.kind,
|
|
9190
9512
|
status: "queued",
|
|
@@ -9346,14 +9668,14 @@ var init_types2 = __esm({
|
|
|
9346
9668
|
});
|
|
9347
9669
|
|
|
9348
9670
|
// src/media/asset-store.ts
|
|
9349
|
-
import { createHash as
|
|
9671
|
+
import { createHash as createHash5, randomUUID as randomUUID6 } from "crypto";
|
|
9350
9672
|
import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename as rename2, rm, stat as stat2, writeFile as writeFile3 } from "fs/promises";
|
|
9351
9673
|
import path11 from "path";
|
|
9352
9674
|
function mediaRoot(dataDir) {
|
|
9353
9675
|
return path11.resolve(dataDir, "media");
|
|
9354
9676
|
}
|
|
9355
9677
|
function projectStorageKey(projectId) {
|
|
9356
|
-
return
|
|
9678
|
+
return createHash5("sha256").update(projectId).digest("hex").slice(0, 16);
|
|
9357
9679
|
}
|
|
9358
9680
|
function validateUnderRoot(root, candidate) {
|
|
9359
9681
|
const resolved = path11.resolve(candidate);
|
|
@@ -9417,7 +9739,7 @@ async function destinationExists(destination) {
|
|
|
9417
9739
|
async function persistBuffer(bytes, destination) {
|
|
9418
9740
|
await mkdir3(path11.dirname(destination), { recursive: true });
|
|
9419
9741
|
if (await destinationExists(destination)) return false;
|
|
9420
|
-
const temporary = `${destination}.${
|
|
9742
|
+
const temporary = `${destination}.${randomUUID6()}.tmp`;
|
|
9421
9743
|
try {
|
|
9422
9744
|
await writeFile3(temporary, bytes, { flag: "wx" });
|
|
9423
9745
|
await rename2(temporary, destination);
|
|
@@ -9462,7 +9784,7 @@ async function importMediaBuffer(input) {
|
|
|
9462
9784
|
if (input.bytes.length === 0) throw new Error("Media import rejects empty payloads");
|
|
9463
9785
|
if (input.bytes.length > maxBytes) throw new Error(`Media payload is too large (${input.bytes.length} bytes; limit ${maxBytes})`);
|
|
9464
9786
|
const detected = detectMedia(input.bytes.subarray(0, 32));
|
|
9465
|
-
const sha256 =
|
|
9787
|
+
const sha256 = createHash5("sha256").update(input.bytes).digest("hex");
|
|
9466
9788
|
return importKnownMedia({
|
|
9467
9789
|
dataDir: input.dataDir,
|
|
9468
9790
|
projectId: input.projectId,
|
|
@@ -9480,7 +9802,7 @@ async function readMediaAsset(dataDir, asset, maxBytes = DEFAULT_MAX_MEDIA_BYTES
|
|
|
9480
9802
|
if (asset.byteSize > maxBytes) throw new Error(`Media asset exceeds read limit (${asset.byteSize} bytes; limit ${maxBytes})`);
|
|
9481
9803
|
const bytes = await readFile3(getMediaAssetPath(dataDir, asset));
|
|
9482
9804
|
if (bytes.length !== asset.byteSize) throw new Error(`Media asset size no longer matches metadata: ${asset.id}`);
|
|
9483
|
-
const sha256 =
|
|
9805
|
+
const sha256 = createHash5("sha256").update(bytes).digest("hex");
|
|
9484
9806
|
if (sha256 !== asset.sha256) throw new Error(`Media asset hash no longer matches metadata: ${asset.id}`);
|
|
9485
9807
|
return bytes;
|
|
9486
9808
|
}
|
|
@@ -62231,7 +62553,7 @@ var require_gaxios = __commonJS({
|
|
|
62231
62553
|
var retry_js_1 = require_retry3();
|
|
62232
62554
|
var stream_1 = __require("stream");
|
|
62233
62555
|
var interceptor_js_1 = require_interceptor();
|
|
62234
|
-
var
|
|
62556
|
+
var randomUUID16 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
|
|
62235
62557
|
var HTTP_STATUS_NO_CONTENT = 204;
|
|
62236
62558
|
var Gaxios = class {
|
|
62237
62559
|
agentCache = /* @__PURE__ */ new Map();
|
|
@@ -62504,7 +62826,7 @@ var require_gaxios = __commonJS({
|
|
|
62504
62826
|
*/
|
|
62505
62827
|
["Blob", "File", "FormData"].includes(opts.data?.constructor?.name || "");
|
|
62506
62828
|
if (opts.multipart?.length) {
|
|
62507
|
-
const boundary = await
|
|
62829
|
+
const boundary = await randomUUID16();
|
|
62508
62830
|
preparedHeaders.set("content-type", `multipart/related; boundary=${boundary}`);
|
|
62509
62831
|
opts.body = stream_1.Readable.from(this.getMultipartRequest(opts.multipart, boundary));
|
|
62510
62832
|
} else if (shouldDirectlyPassData) {
|
|
@@ -74731,7 +75053,7 @@ var require_websocket = __commonJS({
|
|
|
74731
75053
|
var http3 = __require("http");
|
|
74732
75054
|
var net = __require("net");
|
|
74733
75055
|
var tls = __require("tls");
|
|
74734
|
-
var { randomBytes, createHash:
|
|
75056
|
+
var { randomBytes, createHash: createHash14 } = __require("crypto");
|
|
74735
75057
|
var { Duplex, Readable: Readable2 } = __require("stream");
|
|
74736
75058
|
var { URL: URL2 } = __require("url");
|
|
74737
75059
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -75399,7 +75721,7 @@ var require_websocket = __commonJS({
|
|
|
75399
75721
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
75400
75722
|
return;
|
|
75401
75723
|
}
|
|
75402
|
-
const digest2 =
|
|
75724
|
+
const digest2 = createHash14("sha1").update(key + GUID).digest("base64");
|
|
75403
75725
|
if (res.headers["sec-websocket-accept"] !== digest2) {
|
|
75404
75726
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
75405
75727
|
return;
|
|
@@ -75771,7 +76093,7 @@ var require_websocket_server = __commonJS({
|
|
|
75771
76093
|
var EventEmitter = __require("events");
|
|
75772
76094
|
var http3 = __require("http");
|
|
75773
76095
|
var { Duplex } = __require("stream");
|
|
75774
|
-
var { createHash:
|
|
76096
|
+
var { createHash: createHash14 } = __require("crypto");
|
|
75775
76097
|
var extension3 = require_extension();
|
|
75776
76098
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
75777
76099
|
var subprotocol2 = require_subprotocol();
|
|
@@ -76078,7 +76400,7 @@ var require_websocket_server = __commonJS({
|
|
|
76078
76400
|
);
|
|
76079
76401
|
}
|
|
76080
76402
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
76081
|
-
const digest2 =
|
|
76403
|
+
const digest2 = createHash14("sha1").update(key + GUID).digest("base64");
|
|
76082
76404
|
const headers = [
|
|
76083
76405
|
"HTTP/1.1 101 Switching Protocols",
|
|
76084
76406
|
"Upgrade: websocket",
|
|
@@ -143216,6 +143538,186 @@ var init_audio_jobs = __esm({
|
|
|
143216
143538
|
}
|
|
143217
143539
|
});
|
|
143218
143540
|
|
|
143541
|
+
// src/memory/feedback-model.ts
|
|
143542
|
+
function feedbackWeightMultiplier(weight) {
|
|
143543
|
+
return Math.max(0.35, Math.min(1.4, 0.35 + Math.max(0, Math.min(2, weight)) * 0.525));
|
|
143544
|
+
}
|
|
143545
|
+
var init_feedback_model = __esm({
|
|
143546
|
+
"src/memory/feedback-model.ts"() {
|
|
143547
|
+
"use strict";
|
|
143548
|
+
init_esm_shims();
|
|
143549
|
+
}
|
|
143550
|
+
});
|
|
143551
|
+
|
|
143552
|
+
// src/memory/feedback.ts
|
|
143553
|
+
var feedback_exports = {};
|
|
143554
|
+
__export(feedback_exports, {
|
|
143555
|
+
FEEDBACK_DELTAS: () => FEEDBACK_DELTAS,
|
|
143556
|
+
MemoryFeedbackStore: () => MemoryFeedbackStore,
|
|
143557
|
+
applyMemoryFeedback: () => applyMemoryFeedback,
|
|
143558
|
+
feedbackWeightMultiplier: () => feedbackWeightMultiplier
|
|
143559
|
+
});
|
|
143560
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
143561
|
+
function applyMemoryFeedback(current, event) {
|
|
143562
|
+
const delta = event.signal === "revoke" ? 0 : FEEDBACK_DELTAS[event.signal];
|
|
143563
|
+
const weight = Math.max(0, Math.min(2, current.weight + delta));
|
|
143564
|
+
const status = (event.signal === "code-conflict" || event.signal === "user-correction" || event.signal === "weaken") && weight < 0.5 ? "archived" : current.status;
|
|
143565
|
+
return { weight, status, audit: [...current.audit, { ...event }] };
|
|
143566
|
+
}
|
|
143567
|
+
function rowToEvent(row) {
|
|
143568
|
+
return {
|
|
143569
|
+
id: String(row.id),
|
|
143570
|
+
projectId: String(row.project_id),
|
|
143571
|
+
candidateKind: row.candidate_kind,
|
|
143572
|
+
candidateId: String(row.candidate_id),
|
|
143573
|
+
signal: row.signal,
|
|
143574
|
+
...row.observed_at ? { at: String(row.observed_at) } : { at: (/* @__PURE__ */ new Date()).toISOString() },
|
|
143575
|
+
...row.actor ? { actor: String(row.actor) } : {},
|
|
143576
|
+
...row.note ? { note: String(row.note) } : {},
|
|
143577
|
+
...row.source_ref ? { sourceRef: String(row.source_ref) } : {},
|
|
143578
|
+
...row.target_event_id ? { targetEventId: String(row.target_event_id) } : {},
|
|
143579
|
+
delta: Number(row.delta ?? 0)
|
|
143580
|
+
};
|
|
143581
|
+
}
|
|
143582
|
+
var FEEDBACK_DELTAS, MemoryFeedbackStore;
|
|
143583
|
+
var init_feedback = __esm({
|
|
143584
|
+
"src/memory/feedback.ts"() {
|
|
143585
|
+
"use strict";
|
|
143586
|
+
init_esm_shims();
|
|
143587
|
+
init_sqlite_db();
|
|
143588
|
+
init_feedback_model();
|
|
143589
|
+
FEEDBACK_DELTAS = {
|
|
143590
|
+
"user-correction": -0.35,
|
|
143591
|
+
"verification-success": 0.25,
|
|
143592
|
+
"verification-failure": -0.25,
|
|
143593
|
+
"code-change": -0.15,
|
|
143594
|
+
used: 0.1,
|
|
143595
|
+
"not-used": -0.05,
|
|
143596
|
+
"code-conflict": -0.4,
|
|
143597
|
+
strengthen: 0.2,
|
|
143598
|
+
weaken: -0.2
|
|
143599
|
+
};
|
|
143600
|
+
MemoryFeedbackStore = class {
|
|
143601
|
+
db = null;
|
|
143602
|
+
async init(dataDir) {
|
|
143603
|
+
this.db = getDatabase(dataDir);
|
|
143604
|
+
}
|
|
143605
|
+
requireDb() {
|
|
143606
|
+
if (!this.db) throw new Error("MemoryFeedbackStore is not initialized.");
|
|
143607
|
+
return this.db;
|
|
143608
|
+
}
|
|
143609
|
+
loadEvents(projectId, candidateKind, candidateId) {
|
|
143610
|
+
return this.requireDb().prepare(`
|
|
143611
|
+
SELECT * FROM memory_feedback_events
|
|
143612
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
143613
|
+
ORDER BY observed_at ASC, rowid ASC
|
|
143614
|
+
`).all(projectId, candidateKind, candidateId).map(rowToEvent);
|
|
143615
|
+
}
|
|
143616
|
+
rebuild(projectId, candidateKind, candidateId) {
|
|
143617
|
+
const events = this.loadEvents(projectId, candidateKind, candidateId);
|
|
143618
|
+
const revoked = new Set(events.filter((event) => event.signal === "revoke" && event.targetEventId).map((event) => event.targetEventId));
|
|
143619
|
+
let state = { weight: 1, status: "active", audit: [] };
|
|
143620
|
+
for (const event of events) {
|
|
143621
|
+
if (event.signal === "revoke" || revoked.has(event.id)) {
|
|
143622
|
+
state.audit.push(event);
|
|
143623
|
+
continue;
|
|
143624
|
+
}
|
|
143625
|
+
state = applyMemoryFeedback(state, event);
|
|
143626
|
+
}
|
|
143627
|
+
this.requireDb().prepare(`
|
|
143628
|
+
INSERT INTO memory_feedback_states (project_id, candidate_kind, candidate_id, weight, lifecycle_status, updated_at)
|
|
143629
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
143630
|
+
ON CONFLICT(project_id, candidate_kind, candidate_id) DO UPDATE SET
|
|
143631
|
+
weight = excluded.weight, lifecycle_status = excluded.lifecycle_status, updated_at = excluded.updated_at
|
|
143632
|
+
`).run(projectId, candidateKind, candidateId, state.weight, state.status, (/* @__PURE__ */ new Date()).toISOString());
|
|
143633
|
+
return state;
|
|
143634
|
+
}
|
|
143635
|
+
getState(projectId, candidateKind, candidateId) {
|
|
143636
|
+
const row = this.requireDb().prepare(`
|
|
143637
|
+
SELECT weight, lifecycle_status FROM memory_feedback_states
|
|
143638
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
143639
|
+
`).get(projectId, candidateKind, candidateId);
|
|
143640
|
+
if (!row) return { weight: 1, status: "active", audit: [] };
|
|
143641
|
+
return {
|
|
143642
|
+
weight: Number(row.weight ?? 1),
|
|
143643
|
+
status: row.lifecycle_status ?? "active",
|
|
143644
|
+
audit: this.loadEvents(projectId, candidateKind, candidateId)
|
|
143645
|
+
};
|
|
143646
|
+
}
|
|
143647
|
+
listStates(projectId, candidateKind = "observation") {
|
|
143648
|
+
return this.requireDb().prepare(`
|
|
143649
|
+
SELECT candidate_id, weight, lifecycle_status, updated_at
|
|
143650
|
+
FROM memory_feedback_states WHERE project_id = ? AND candidate_kind = ?
|
|
143651
|
+
ORDER BY updated_at DESC
|
|
143652
|
+
`).all(projectId, candidateKind).map((row) => ({
|
|
143653
|
+
candidateId: String(row.candidate_id),
|
|
143654
|
+
weight: Number(row.weight),
|
|
143655
|
+
status: row.lifecycle_status,
|
|
143656
|
+
updatedAt: String(row.updated_at)
|
|
143657
|
+
}));
|
|
143658
|
+
}
|
|
143659
|
+
weights(projectId, candidateKind = "observation") {
|
|
143660
|
+
const states = /* @__PURE__ */ new Map();
|
|
143661
|
+
for (const row of this.listStates(projectId, candidateKind)) {
|
|
143662
|
+
states.set(row.candidateId, this.getState(projectId, candidateKind, row.candidateId));
|
|
143663
|
+
}
|
|
143664
|
+
return states;
|
|
143665
|
+
}
|
|
143666
|
+
record(input) {
|
|
143667
|
+
if (input.signal === "revoke" && !input.targetEventId) {
|
|
143668
|
+
throw new Error("A revoke feedback event requires targetEventId.");
|
|
143669
|
+
}
|
|
143670
|
+
if (input.signal === "revoke") {
|
|
143671
|
+
const target = this.requireDb().prepare(`
|
|
143672
|
+
SELECT 1 FROM memory_feedback_events
|
|
143673
|
+
WHERE id = ? AND project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
143674
|
+
`).get(input.targetEventId, input.projectId, input.candidateKind, input.candidateId);
|
|
143675
|
+
if (!target) throw new Error("The feedback event to revoke was not found in the same candidate scope.");
|
|
143676
|
+
}
|
|
143677
|
+
const event = {
|
|
143678
|
+
id: randomUUID7(),
|
|
143679
|
+
projectId: input.projectId,
|
|
143680
|
+
candidateKind: input.candidateKind,
|
|
143681
|
+
candidateId: input.candidateId,
|
|
143682
|
+
signal: input.signal,
|
|
143683
|
+
sourceRef: input.sourceRef,
|
|
143684
|
+
...input.actor ? { actor: input.actor } : {},
|
|
143685
|
+
...input.note ? { note: input.note.slice(0, 2e3) } : {},
|
|
143686
|
+
...input.targetEventId ? { targetEventId: input.targetEventId } : {},
|
|
143687
|
+
at: input.at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
143688
|
+
delta: input.signal === "revoke" ? 0 : FEEDBACK_DELTAS[input.signal]
|
|
143689
|
+
};
|
|
143690
|
+
this.requireDb().prepare(`
|
|
143691
|
+
INSERT INTO memory_feedback_events (
|
|
143692
|
+
id, project_id, candidate_kind, candidate_id, signal, actor, note,
|
|
143693
|
+
source_ref, target_event_id, delta, observed_at
|
|
143694
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
143695
|
+
`).run(
|
|
143696
|
+
event.id,
|
|
143697
|
+
event.projectId,
|
|
143698
|
+
event.candidateKind,
|
|
143699
|
+
event.candidateId,
|
|
143700
|
+
event.signal,
|
|
143701
|
+
event.actor ?? null,
|
|
143702
|
+
event.note ?? null,
|
|
143703
|
+
event.sourceRef,
|
|
143704
|
+
event.targetEventId ?? null,
|
|
143705
|
+
event.delta,
|
|
143706
|
+
event.at
|
|
143707
|
+
);
|
|
143708
|
+
return { event, state: this.rebuild(input.projectId, input.candidateKind, input.candidateId) };
|
|
143709
|
+
}
|
|
143710
|
+
audit(projectId, candidateKind, candidateId, limit2 = 100) {
|
|
143711
|
+
return this.requireDb().prepare(`
|
|
143712
|
+
SELECT * FROM memory_feedback_events
|
|
143713
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
143714
|
+
ORDER BY observed_at DESC, rowid DESC LIMIT ?
|
|
143715
|
+
`).all(projectId, candidateKind, candidateId, Math.min(200, Math.max(1, Math.floor(limit2)))).map(rowToEvent);
|
|
143716
|
+
}
|
|
143717
|
+
};
|
|
143718
|
+
}
|
|
143719
|
+
});
|
|
143720
|
+
|
|
143219
143721
|
// src/memory/retention.ts
|
|
143220
143722
|
var retention_exports = {};
|
|
143221
143723
|
__export(retention_exports, {
|
|
@@ -143257,6 +143759,7 @@ function getEffectiveRetentionDays(doc) {
|
|
|
143257
143759
|
}
|
|
143258
143760
|
function isImmune(doc) {
|
|
143259
143761
|
if (doc.type === "probe") return false;
|
|
143762
|
+
if (doc.feedbackStatus === "archived") return false;
|
|
143260
143763
|
if (doc.admissionState === "candidate" || doc.admissionState === "ephemeral") return false;
|
|
143261
143764
|
if (doc.valueCategory === "core") return true;
|
|
143262
143765
|
const importance = getImportanceLevel(doc);
|
|
@@ -143289,7 +143792,8 @@ function calculateRelevance(doc, referenceTime) {
|
|
|
143289
143792
|
const decayFactor = Math.exp(-ageDays / retention);
|
|
143290
143793
|
const accessCount = doc.accessCount ?? 0;
|
|
143291
143794
|
const accessBoost = Math.min(2, 1 + 0.1 * accessCount);
|
|
143292
|
-
|
|
143795
|
+
const feedbackMultiplier = doc.feedbackWeight === void 0 ? 1 : feedbackWeightMultiplier(doc.feedbackWeight);
|
|
143796
|
+
let totalScore = base * decayFactor * accessBoost * feedbackMultiplier;
|
|
143293
143797
|
const immune = isImmune(doc);
|
|
143294
143798
|
if (immune) {
|
|
143295
143799
|
totalScore = Math.max(totalScore, 0.5);
|
|
@@ -143301,7 +143805,8 @@ function calculateRelevance(doc, referenceTime) {
|
|
|
143301
143805
|
decayFactor,
|
|
143302
143806
|
accessBoost,
|
|
143303
143807
|
ageDays,
|
|
143304
|
-
isImmune: immune
|
|
143808
|
+
isImmune: immune,
|
|
143809
|
+
feedbackMultiplier
|
|
143305
143810
|
};
|
|
143306
143811
|
}
|
|
143307
143812
|
function rankByRelevance(docs, referenceTime) {
|
|
@@ -143309,6 +143814,7 @@ function rankByRelevance(docs, referenceTime) {
|
|
|
143309
143814
|
}
|
|
143310
143815
|
function getRetentionZone(doc, referenceTime) {
|
|
143311
143816
|
const now3 = referenceTime ?? /* @__PURE__ */ new Date();
|
|
143817
|
+
if (doc.feedbackStatus === "archived") return "archive-candidate";
|
|
143312
143818
|
const importance = getImportanceLevel(doc);
|
|
143313
143819
|
const retention = getEffectiveRetentionDays(doc);
|
|
143314
143820
|
const createdAt = new Date(doc.createdAt);
|
|
@@ -143380,7 +143886,7 @@ function explainRetention(doc, referenceTime) {
|
|
|
143380
143886
|
summary: parts.join(" ; ")
|
|
143381
143887
|
};
|
|
143382
143888
|
}
|
|
143383
|
-
function toRetentionDocument(obs, accessMap) {
|
|
143889
|
+
function toRetentionDocument(obs, accessMap, feedback) {
|
|
143384
143890
|
const access2 = accessMap?.get(obs.id);
|
|
143385
143891
|
return {
|
|
143386
143892
|
id: `obs-${obs.id}`,
|
|
@@ -143402,11 +143908,12 @@ function toRetentionDocument(obs, accessMap) {
|
|
|
143402
143908
|
sourceDetail: obs.sourceDetail ?? "",
|
|
143403
143909
|
valueCategory: obs.valueCategory ?? "",
|
|
143404
143910
|
admissionState: obs.admissionState ?? "",
|
|
143405
|
-
admissionReason: obs.admissionReason ?? ""
|
|
143911
|
+
admissionReason: obs.admissionReason ?? "",
|
|
143912
|
+
...feedback ? { feedbackWeight: feedback.weight, feedbackStatus: feedback.status } : {}
|
|
143406
143913
|
};
|
|
143407
143914
|
}
|
|
143408
143915
|
function projectObservationRetention(observation, options = {}) {
|
|
143409
|
-
const document2 = toRetentionDocument(observation, options.accessMap);
|
|
143916
|
+
const document2 = toRetentionDocument(observation, options.accessMap, options.feedback);
|
|
143410
143917
|
const relevance = calculateRelevance(document2, options.referenceTime);
|
|
143411
143918
|
const explanation = explainRetention(document2, options.referenceTime);
|
|
143412
143919
|
return {
|
|
@@ -143431,7 +143938,17 @@ function summarizeRetentionProjections(projections) {
|
|
|
143431
143938
|
}
|
|
143432
143939
|
return { active, stale, archiveCandidates, immune };
|
|
143433
143940
|
}
|
|
143434
|
-
async function
|
|
143941
|
+
async function loadFeedbackStore(dataDir) {
|
|
143942
|
+
try {
|
|
143943
|
+
const { MemoryFeedbackStore: MemoryFeedbackStore2 } = await Promise.resolve().then(() => (init_feedback(), feedback_exports));
|
|
143944
|
+
const store = new MemoryFeedbackStore2();
|
|
143945
|
+
await store.init(dataDir);
|
|
143946
|
+
return store;
|
|
143947
|
+
} catch {
|
|
143948
|
+
return void 0;
|
|
143949
|
+
}
|
|
143950
|
+
}
|
|
143951
|
+
async function archiveExpiredBatch(projectDir2, options) {
|
|
143435
143952
|
const store = getObservationStore();
|
|
143436
143953
|
const limit2 = Math.min(500, Math.max(1, Math.floor(options.limit ?? 100)));
|
|
143437
143954
|
const afterId = Math.max(0, Math.floor(options.afterId ?? 0));
|
|
@@ -143440,11 +143957,13 @@ async function archiveExpiredBatch(_projectDir, options) {
|
|
|
143440
143957
|
afterId,
|
|
143441
143958
|
limit: limit2 + 1
|
|
143442
143959
|
});
|
|
143960
|
+
const feedback = await loadFeedbackStore(projectDir2);
|
|
143443
143961
|
const hasMore = page.length > limit2;
|
|
143444
143962
|
const scanned = hasMore ? page.slice(0, limit2) : page;
|
|
143445
143963
|
const candidateIds = scanned.filter((observation) => !options.reader || canManageObservation(observation, options.reader)).filter((observation) => projectObservationRetention(observation, {
|
|
143446
143964
|
accessMap: options.accessMap,
|
|
143447
|
-
referenceTime: options.referenceTime
|
|
143965
|
+
referenceTime: options.referenceTime,
|
|
143966
|
+
...feedback ? { feedback: feedback.getState(options.projectId, "observation", String(observation.id)) } : {}
|
|
143448
143967
|
}).zone === "archive-candidate").map((observation) => observation.id);
|
|
143449
143968
|
const archived = candidateIds.length === 0 ? 0 : await store.atomic(async (tx) => {
|
|
143450
143969
|
const updates = await Promise.all(
|
|
@@ -143475,6 +143994,7 @@ async function archiveExpired(projectDir2, referenceTime, accessMap, projectId,
|
|
|
143475
143994
|
const remaining = reader ? remainingObservations.filter((observation) => canManageObservation(observation, reader)).length : remainingObservations.length;
|
|
143476
143995
|
return { archived, remaining };
|
|
143477
143996
|
}
|
|
143997
|
+
const feedback = await loadFeedbackStore(projectDir2);
|
|
143478
143998
|
return await store.atomic(async (tx) => {
|
|
143479
143999
|
const allObs = await tx.loadAll();
|
|
143480
144000
|
const activeObs = allObs.filter(
|
|
@@ -143482,7 +144002,11 @@ async function archiveExpired(projectDir2, referenceTime, accessMap, projectId,
|
|
|
143482
144002
|
);
|
|
143483
144003
|
const archivedIds = [];
|
|
143484
144004
|
for (const obs of activeObs) {
|
|
143485
|
-
const retention = projectObservationRetention(obs, {
|
|
144005
|
+
const retention = projectObservationRetention(obs, {
|
|
144006
|
+
accessMap,
|
|
144007
|
+
referenceTime,
|
|
144008
|
+
...feedback ? { feedback: feedback.getState(obs.projectId, "observation", String(obs.id)) } : {}
|
|
144009
|
+
});
|
|
143486
144010
|
if (retention.zone === "archive-candidate") {
|
|
143487
144011
|
archivedIds.push(obs.id);
|
|
143488
144012
|
}
|
|
@@ -143502,6 +144026,7 @@ var init_retention = __esm({
|
|
|
143502
144026
|
init_esm_shims();
|
|
143503
144027
|
init_obs_store();
|
|
143504
144028
|
init_visibility();
|
|
144029
|
+
init_feedback_model();
|
|
143505
144030
|
RETENTION_DAYS = {
|
|
143506
144031
|
critical: 365,
|
|
143507
144032
|
high: 180,
|
|
@@ -143538,7 +144063,7 @@ var init_retention = __esm({
|
|
|
143538
144063
|
});
|
|
143539
144064
|
|
|
143540
144065
|
// src/memory/owner.ts
|
|
143541
|
-
import { randomUUID as
|
|
144066
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
143542
144067
|
import { promises as fs9 } from "fs";
|
|
143543
144068
|
import path17 from "path";
|
|
143544
144069
|
function ownerPath(dataDir) {
|
|
@@ -143568,7 +144093,7 @@ async function resolveLocalMemoryOwner(dataDir, options = {}) {
|
|
|
143568
144093
|
await fs9.mkdir(path17.dirname(filePath), { recursive: true });
|
|
143569
144094
|
const created = {
|
|
143570
144095
|
version: 1,
|
|
143571
|
-
id: "local-" +
|
|
144096
|
+
id: "local-" + randomUUID8(),
|
|
143572
144097
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
143573
144098
|
};
|
|
143574
144099
|
try {
|
|
@@ -143591,7 +144116,7 @@ var init_owner = __esm({
|
|
|
143591
144116
|
});
|
|
143592
144117
|
|
|
143593
144118
|
// src/memory/long-term-store.ts
|
|
143594
|
-
import { randomUUID as
|
|
144119
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
143595
144120
|
function optionalText2(value) {
|
|
143596
144121
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
143597
144122
|
}
|
|
@@ -143642,7 +144167,7 @@ function rowToEvidence(row) {
|
|
|
143642
144167
|
createdAt: row.createdAt
|
|
143643
144168
|
};
|
|
143644
144169
|
}
|
|
143645
|
-
function
|
|
144170
|
+
function rowToEvent2(row) {
|
|
143646
144171
|
return {
|
|
143647
144172
|
id: row.id,
|
|
143648
144173
|
memoryId: row.memoryId,
|
|
@@ -143751,7 +144276,7 @@ var init_long_term_store = __esm({
|
|
|
143751
144276
|
}
|
|
143752
144277
|
insertEvidence(input) {
|
|
143753
144278
|
const evidence = {
|
|
143754
|
-
id:
|
|
144279
|
+
id: randomUUID9(),
|
|
143755
144280
|
...input,
|
|
143756
144281
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
143757
144282
|
};
|
|
@@ -143778,7 +144303,7 @@ var init_long_term_store = __esm({
|
|
|
143778
144303
|
}
|
|
143779
144304
|
recordEvent(input) {
|
|
143780
144305
|
const event = {
|
|
143781
|
-
id:
|
|
144306
|
+
id: randomUUID9(),
|
|
143782
144307
|
...input,
|
|
143783
144308
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
143784
144309
|
};
|
|
@@ -143799,7 +144324,7 @@ var init_long_term_store = __esm({
|
|
|
143799
144324
|
listEvents(memoryId) {
|
|
143800
144325
|
return this.db.prepare(`
|
|
143801
144326
|
SELECT * FROM long_term_memory_events WHERE memoryId = ? ORDER BY createdAt ASC, rowid ASC
|
|
143802
|
-
`).all(memoryId).map(
|
|
144327
|
+
`).all(memoryId).map(rowToEvent2);
|
|
143803
144328
|
}
|
|
143804
144329
|
markAccess(ids, at = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
143805
144330
|
const unique = [...new Set(ids.filter(Boolean))];
|
|
@@ -143868,7 +144393,7 @@ __export(long_term_exports, {
|
|
|
143868
144393
|
selectLongTermMemoriesForTask: () => selectLongTermMemoriesForTask,
|
|
143869
144394
|
supersedeLongTermMemory: () => supersedeLongTermMemory
|
|
143870
144395
|
});
|
|
143871
|
-
import { randomUUID as
|
|
144396
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
143872
144397
|
function isOneOf(value, values) {
|
|
143873
144398
|
return typeof value === "string" && values.includes(value);
|
|
143874
144399
|
}
|
|
@@ -144050,7 +144575,7 @@ async function createManualLongTermMemory(input) {
|
|
|
144050
144575
|
const owner = await resolveLocalMemoryOwner(input.dataDir, { create: true });
|
|
144051
144576
|
if (!owner) throw new Error("Memorix could not resolve a local memory owner.");
|
|
144052
144577
|
assertScope(input.scope);
|
|
144053
|
-
const evidence = input.scope === "user" ? [{ kind: "user", referenceId: owner.id, relation: "user-confirmed" }] : [{ kind: "manual", referenceId: "manual:" +
|
|
144578
|
+
const evidence = input.scope === "user" ? [{ kind: "user", referenceId: owner.id, relation: "user-confirmed" }] : [{ kind: "manual", referenceId: "manual:" + randomUUID10(), relation: "supports" }];
|
|
144054
144579
|
return createLongTermMemoryWithDataDir({
|
|
144055
144580
|
dataDir: input.dataDir,
|
|
144056
144581
|
originProjectId: input.projectId,
|
|
@@ -144105,7 +144630,7 @@ async function createLongTermMemoryWithDataDir(input) {
|
|
|
144105
144630
|
assertPortableEvidence(input.scope, portability, evidenceInputs);
|
|
144106
144631
|
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
144107
144632
|
const memory = {
|
|
144108
|
-
id:
|
|
144633
|
+
id: randomUUID10(),
|
|
144109
144634
|
originProjectId: compactText(input.originProjectId, "origin project id", 1e3),
|
|
144110
144635
|
ownerId: compactText(input.ownerId, "owner id", 160),
|
|
144111
144636
|
scope: input.scope,
|
|
@@ -144423,9 +144948,9 @@ var init_long_term = __esm({
|
|
|
144423
144948
|
});
|
|
144424
144949
|
|
|
144425
144950
|
// src/codegraph/ids.ts
|
|
144426
|
-
import { createHash as
|
|
144951
|
+
import { createHash as createHash6 } from "crypto";
|
|
144427
144952
|
function digest(input) {
|
|
144428
|
-
return
|
|
144953
|
+
return createHash6("sha256").update(input).digest("hex").slice(0, 16);
|
|
144429
144954
|
}
|
|
144430
144955
|
function normalizeCodePath(path22) {
|
|
144431
144956
|
return path22.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/");
|
|
@@ -144460,7 +144985,7 @@ var store_exports = {};
|
|
|
144460
144985
|
__export(store_exports, {
|
|
144461
144986
|
CodeGraphStore: () => CodeGraphStore
|
|
144462
144987
|
});
|
|
144463
|
-
import { randomUUID as
|
|
144988
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
144464
144989
|
import { posix as pathPosix } from "path";
|
|
144465
144990
|
function rowToFile(row) {
|
|
144466
144991
|
return {
|
|
@@ -145177,7 +145702,7 @@ var init_store = __esm({
|
|
|
145177
145702
|
* so an interrupted scan cannot be advertised as complete.
|
|
145178
145703
|
*/
|
|
145179
145704
|
recordCodeStateSnapshot(input) {
|
|
145180
|
-
const id =
|
|
145705
|
+
const id = randomUUID11();
|
|
145181
145706
|
let snapshot;
|
|
145182
145707
|
const tx = this.db.transaction(() => {
|
|
145183
145708
|
const previous = this.db.prepare(
|
|
@@ -145255,7 +145780,7 @@ var init_store = __esm({
|
|
|
145255
145780
|
|
|
145256
145781
|
// src/codegraph/code-state.ts
|
|
145257
145782
|
import { execFile as execFile2 } from "child_process";
|
|
145258
|
-
import { createHash as
|
|
145783
|
+
import { createHash as createHash7 } from "crypto";
|
|
145259
145784
|
import { promisify as promisify3 } from "util";
|
|
145260
145785
|
async function runGit(rootPath, args) {
|
|
145261
145786
|
try {
|
|
@@ -145284,7 +145809,7 @@ function changedPathCount(status) {
|
|
|
145284
145809
|
return count2;
|
|
145285
145810
|
}
|
|
145286
145811
|
function fingerprint(baseRevision, status) {
|
|
145287
|
-
return
|
|
145812
|
+
return createHash7("sha256").update(baseRevision ?? "").update("\0").update(status).digest("hex");
|
|
145288
145813
|
}
|
|
145289
145814
|
async function collectCodeStateSnapshot(input) {
|
|
145290
145815
|
const [revision, status] = await Promise.all([
|
|
@@ -145384,11 +145909,11 @@ __export(lite_provider_exports, {
|
|
|
145384
145909
|
indexProjectLite: () => indexProjectLite,
|
|
145385
145910
|
refreshProjectLite: () => refreshProjectLite
|
|
145386
145911
|
});
|
|
145387
|
-
import { createHash as
|
|
145912
|
+
import { createHash as createHash8 } from "crypto";
|
|
145388
145913
|
import { readdirSync as readdirSync2, readFileSync as readFileSync7, statSync as statSync3 } from "fs";
|
|
145389
145914
|
import { join as join4, relative } from "path";
|
|
145390
145915
|
function hashText(text2) {
|
|
145391
|
-
return
|
|
145916
|
+
return createHash8("sha256").update(text2).digest("hex");
|
|
145392
145917
|
}
|
|
145393
145918
|
function extension2(path22) {
|
|
145394
145919
|
const index = path22.lastIndexOf(".");
|
|
@@ -145955,7 +146480,7 @@ var claim_store_exports = {};
|
|
|
145955
146480
|
__export(claim_store_exports, {
|
|
145956
146481
|
ClaimStore: () => ClaimStore
|
|
145957
146482
|
});
|
|
145958
|
-
import { createHash as
|
|
146483
|
+
import { createHash as createHash9, randomUUID as randomUUID12 } from "crypto";
|
|
145959
146484
|
function optionalText3(value) {
|
|
145960
146485
|
return typeof value === "string" && value ? value : void 0;
|
|
145961
146486
|
}
|
|
@@ -145994,7 +146519,7 @@ function rowToEvidence2(row) {
|
|
|
145994
146519
|
createdAt: row.createdAt
|
|
145995
146520
|
};
|
|
145996
146521
|
}
|
|
145997
|
-
function
|
|
146522
|
+
function rowToEvent3(row) {
|
|
145998
146523
|
return {
|
|
145999
146524
|
id: row.id,
|
|
146000
146525
|
projectId: row.projectId,
|
|
@@ -146008,7 +146533,7 @@ function rowToEvent2(row) {
|
|
|
146008
146533
|
};
|
|
146009
146534
|
}
|
|
146010
146535
|
function evidenceKey(input) {
|
|
146011
|
-
return
|
|
146536
|
+
return createHash9("sha256").update(JSON.stringify([
|
|
146012
146537
|
input.evidenceKind,
|
|
146013
146538
|
input.evidenceId,
|
|
146014
146539
|
input.relation,
|
|
@@ -146139,7 +146664,7 @@ var init_claim_store = __esm({
|
|
|
146139
146664
|
locator, capturedHash, evidenceKey, createdAt
|
|
146140
146665
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
146141
146666
|
`).run(
|
|
146142
|
-
|
|
146667
|
+
randomUUID12(),
|
|
146143
146668
|
input.claimId,
|
|
146144
146669
|
input.evidenceKind,
|
|
146145
146670
|
input.evidenceId,
|
|
@@ -146161,7 +146686,7 @@ var init_claim_store = __esm({
|
|
|
146161
146686
|
}
|
|
146162
146687
|
recordEvent(input) {
|
|
146163
146688
|
const event = {
|
|
146164
|
-
id:
|
|
146689
|
+
id: randomUUID12(),
|
|
146165
146690
|
...input,
|
|
146166
146691
|
...input.detail ? { detail: sanitizeCredentials(input.detail) } : {},
|
|
146167
146692
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -146189,7 +146714,7 @@ var init_claim_store = __esm({
|
|
|
146189
146714
|
SELECT * FROM knowledge_claim_events
|
|
146190
146715
|
WHERE claimId = ?
|
|
146191
146716
|
ORDER BY createdAt ASC, id
|
|
146192
|
-
`).all(claimId).map(
|
|
146717
|
+
`).all(claimId).map(rowToEvent3);
|
|
146193
146718
|
}
|
|
146194
146719
|
};
|
|
146195
146720
|
}
|
|
@@ -146206,7 +146731,7 @@ __export(claims_exports, {
|
|
|
146206
146731
|
supersedeClaim: () => supersedeClaim,
|
|
146207
146732
|
writeClaim: () => writeClaim
|
|
146208
146733
|
});
|
|
146209
|
-
import { createHash as
|
|
146734
|
+
import { createHash as createHash10, randomUUID as randomUUID13 } from "crypto";
|
|
146210
146735
|
function compactText2(value, field) {
|
|
146211
146736
|
if (typeof value !== "string") throw new Error("Claim " + field + " must be text");
|
|
146212
146737
|
const sanitized = sanitizeCredentials(value).trim().replace(/\s+/g, " ");
|
|
@@ -146218,7 +146743,7 @@ function normalizedTerm(value) {
|
|
|
146218
146743
|
return compactText2(value, "identity").toLocaleLowerCase("en-US");
|
|
146219
146744
|
}
|
|
146220
146745
|
function hashIdentity(parts) {
|
|
146221
|
-
return
|
|
146746
|
+
return createHash10("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
|
|
146222
146747
|
}
|
|
146223
146748
|
function buildClaimIdentity(input) {
|
|
146224
146749
|
const subject = normalizedTerm(input.subject);
|
|
@@ -146292,7 +146817,7 @@ function normalizeClaimInput(input) {
|
|
|
146292
146817
|
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
146293
146818
|
return {
|
|
146294
146819
|
claim: {
|
|
146295
|
-
id:
|
|
146820
|
+
id: randomUUID13(),
|
|
146296
146821
|
projectId,
|
|
146297
146822
|
subject,
|
|
146298
146823
|
predicate,
|
|
@@ -146459,7 +146984,7 @@ function supersedeClaim(store, input) {
|
|
|
146459
146984
|
});
|
|
146460
146985
|
}
|
|
146461
146986
|
function hashObservation(observation) {
|
|
146462
|
-
return
|
|
146987
|
+
return createHash10("sha256").update(JSON.stringify([
|
|
146463
146988
|
observation.title,
|
|
146464
146989
|
observation.narrative,
|
|
146465
146990
|
observation.facts,
|
|
@@ -146703,11 +147228,11 @@ var init_frontmatter = __esm({
|
|
|
146703
147228
|
});
|
|
146704
147229
|
|
|
146705
147230
|
// src/knowledge/markdown.ts
|
|
146706
|
-
import { createHash as
|
|
147231
|
+
import { createHash as createHash11 } from "crypto";
|
|
146707
147232
|
import { promises as fs10 } from "fs";
|
|
146708
147233
|
import path18 from "path";
|
|
146709
147234
|
function hashContent(content) {
|
|
146710
|
-
return
|
|
147235
|
+
return createHash11("sha256").update(content).digest("hex");
|
|
146711
147236
|
}
|
|
146712
147237
|
function stringField(data, key) {
|
|
146713
147238
|
const value = data[key];
|
|
@@ -146833,11 +147358,11 @@ __export(wiki_exports, {
|
|
|
146833
147358
|
lintKnowledgeWorkspace: () => lintKnowledgeWorkspace,
|
|
146834
147359
|
readKnowledgePage: () => readKnowledgePage
|
|
146835
147360
|
});
|
|
146836
|
-
import { createHash as
|
|
147361
|
+
import { createHash as createHash12 } from "crypto";
|
|
146837
147362
|
import { promises as fs11 } from "fs";
|
|
146838
147363
|
import path19 from "path";
|
|
146839
147364
|
function hash2(value) {
|
|
146840
|
-
return
|
|
147365
|
+
return createHash12("sha256").update(value).digest("hex");
|
|
146841
147366
|
}
|
|
146842
147367
|
function now() {
|
|
146843
147368
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -147377,7 +147902,7 @@ var init_workflow_sync = __esm({
|
|
|
147377
147902
|
});
|
|
147378
147903
|
|
|
147379
147904
|
// src/knowledge/workflow-store.ts
|
|
147380
|
-
import { randomUUID as
|
|
147905
|
+
import { randomUUID as randomUUID14 } from "crypto";
|
|
147381
147906
|
function parseJson(value, fallback) {
|
|
147382
147907
|
if (typeof value !== "string" || !value) return fallback;
|
|
147383
147908
|
try {
|
|
@@ -147477,7 +148002,7 @@ var init_workflow_store = __esm({
|
|
|
147477
148002
|
}
|
|
147478
148003
|
recordRun(input) {
|
|
147479
148004
|
const run = {
|
|
147480
|
-
id:
|
|
148005
|
+
id: randomUUID14(),
|
|
147481
148006
|
workflowId: input.workflowId,
|
|
147482
148007
|
projectId: input.projectId,
|
|
147483
148008
|
task: input.task.trim(),
|
|
@@ -147545,7 +148070,7 @@ var init_outcome_types = __esm({
|
|
|
147545
148070
|
});
|
|
147546
148071
|
|
|
147547
148072
|
// src/knowledge/outcome-store.ts
|
|
147548
|
-
import { randomUUID as
|
|
148073
|
+
import { randomUUID as randomUUID15 } from "crypto";
|
|
147549
148074
|
function optionalText5(value) {
|
|
147550
148075
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
147551
148076
|
}
|
|
@@ -147589,7 +148114,7 @@ var init_outcome_store = __esm({
|
|
|
147589
148114
|
}
|
|
147590
148115
|
record(input) {
|
|
147591
148116
|
const signal = {
|
|
147592
|
-
id:
|
|
148117
|
+
id: randomUUID15(),
|
|
147593
148118
|
projectId: text(input.projectId, "project id"),
|
|
147594
148119
|
candidateKind: oneOf(input.candidateKind, MEMORY_OUTCOME_CANDIDATE_KINDS, "candidate kind"),
|
|
147595
148120
|
candidateId: text(input.candidateId, "candidate id"),
|
|
@@ -147694,11 +148219,11 @@ __export(workflows_exports, {
|
|
|
147694
148219
|
syncCanonicalWorkflows: () => syncCanonicalWorkflows,
|
|
147695
148220
|
writeCanonicalWorkflow: () => writeCanonicalWorkflow
|
|
147696
148221
|
});
|
|
147697
|
-
import { createHash as
|
|
148222
|
+
import { createHash as createHash13 } from "crypto";
|
|
147698
148223
|
import { promises as fs12 } from "fs";
|
|
147699
148224
|
import path20 from "path";
|
|
147700
148225
|
function hash3(value) {
|
|
147701
|
-
return
|
|
148226
|
+
return createHash13("sha256").update(value).digest("hex");
|
|
147702
148227
|
}
|
|
147703
148228
|
function now2() {
|
|
147704
148229
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -149080,6 +149605,16 @@ async function bindObservationCodeRefsBestEffort(observation) {
|
|
|
149080
149605
|
} catch {
|
|
149081
149606
|
}
|
|
149082
149607
|
}
|
|
149608
|
+
async function persistEvidenceCard(observation) {
|
|
149609
|
+
if (!projectDir) return;
|
|
149610
|
+
try {
|
|
149611
|
+
const evidence = new EvidenceCardStore();
|
|
149612
|
+
await evidence.init(projectDir);
|
|
149613
|
+
evidence.upsertObservation(observation);
|
|
149614
|
+
} catch (error) {
|
|
149615
|
+
console.error(`[memorix] Evidence card projection failed for obs-${observation.id}: ${error instanceof Error ? error.message : String(error)}`);
|
|
149616
|
+
}
|
|
149617
|
+
}
|
|
149083
149618
|
function queueClaimDerivation(observation) {
|
|
149084
149619
|
const dataDir = projectDir;
|
|
149085
149620
|
const isExplicit = observation.sourceDetail === "explicit";
|
|
@@ -149426,6 +149961,7 @@ async function storeObservation(input) {
|
|
|
149426
149961
|
}
|
|
149427
149962
|
if (!persistedCallbackInvoked) await input.onPersisted?.(observation);
|
|
149428
149963
|
await bindObservationCodeRefsBestEffort(observation);
|
|
149964
|
+
await persistEvidenceCard(observation);
|
|
149429
149965
|
queueObservationQualification(observation);
|
|
149430
149966
|
if (resolveObservationVisibility(observation) === "project") {
|
|
149431
149967
|
queueClaimDerivation(observation);
|
|
@@ -149518,6 +150054,7 @@ async function upsertObservation(existing, input, now3) {
|
|
|
149518
150054
|
await store.update(existing);
|
|
149519
150055
|
}
|
|
149520
150056
|
await bindObservationCodeRefsBestEffort(existing);
|
|
150057
|
+
await persistEvidenceCard(existing);
|
|
149521
150058
|
queueObservationQualification(existing);
|
|
149522
150059
|
if (resolveObservationVisibility(existing) === "project") {
|
|
149523
150060
|
queueClaimDerivation(existing);
|
|
@@ -149651,6 +150188,7 @@ async function resolveObservations(ids, status = "resolved") {
|
|
|
149651
150188
|
await Promise.all(changed.map((observation) => tx.update(observation)));
|
|
149652
150189
|
});
|
|
149653
150190
|
}
|
|
150191
|
+
for (const observation of changed) await persistEvidenceCard(observation);
|
|
149654
150192
|
return { resolved, notFound };
|
|
149655
150193
|
}
|
|
149656
150194
|
function getProjectObservations(projectId) {
|
|
@@ -149988,6 +150526,7 @@ var init_observations = __esm({
|
|
|
149988
150526
|
init_secret_filter();
|
|
149989
150527
|
init_lifecycle();
|
|
149990
150528
|
init_visibility();
|
|
150529
|
+
init_evidence_store();
|
|
149991
150530
|
observations = [];
|
|
149992
150531
|
nextId = 1;
|
|
149993
150532
|
projectDir = null;
|