memorix 1.7.3 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/cli/index.js +1407 -192
- package/dist/dashboard/static/app.js +88 -4
- package/dist/dashboard/static/index.html +10 -0
- package/dist/dashboard/static/style.css +86 -0
- package/dist/index.js +875 -164
- 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 +32 -0
- package/dist/sdk.js +874 -163
- 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 +37 -1
- package/docs/DASHBOARD.md +10 -0
- package/docs/DEVELOPMENT.md +3 -2
- package/docs/INTEGRATIONS.md +1 -1
- package/docs/README.md +11 -1
- 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/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 +201 -12
- 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 +93 -68
- package/src/dashboard/static/index.html +10 -0
- 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 +121 -1
- package/src/store/evidence-store.ts +261 -0
- package/src/store/sqlite-db.ts +104 -0
- package/src/types.ts +8 -0
|
@@ -95,6 +95,8 @@ function loadEnvFile(filePath) {
|
|
|
95
95
|
const parsed = parse(readFileSync(filePath, "utf-8"));
|
|
96
96
|
for (const [key, value] of Object.entries(parsed)) {
|
|
97
97
|
if (!(key in process.env)) {
|
|
98
|
+
loadedEnvKeys.add(key);
|
|
99
|
+
loadedEnvValues.set(key, value);
|
|
98
100
|
process.env[key] = value;
|
|
99
101
|
injectedKeys.add(key);
|
|
100
102
|
}
|
|
@@ -107,6 +109,8 @@ function loadDotenv(projectRoot, options = {}) {
|
|
|
107
109
|
resetDotenv();
|
|
108
110
|
}
|
|
109
111
|
loadedEnvFiles.length = 0;
|
|
112
|
+
loadedEnvKeys.clear();
|
|
113
|
+
loadedEnvValues.clear();
|
|
110
114
|
if (projectRoot) {
|
|
111
115
|
loadEnvFile(getProjectDotenvPath(projectRoot));
|
|
112
116
|
}
|
|
@@ -122,11 +126,12 @@ function resetDotenv() {
|
|
|
122
126
|
dotenvLoaded = false;
|
|
123
127
|
dotenvProjectRoot = null;
|
|
124
128
|
loadedEnvFiles.length = 0;
|
|
129
|
+
loadedEnvKeys.clear();
|
|
125
130
|
}
|
|
126
131
|
function getLoadedEnvFiles() {
|
|
127
132
|
return loadedEnvFiles;
|
|
128
133
|
}
|
|
129
|
-
var dotenvLoaded, dotenvProjectRoot, loadedEnvFiles, injectedKeys;
|
|
134
|
+
var dotenvLoaded, dotenvProjectRoot, loadedEnvFiles, loadedEnvKeys, loadedEnvValues, injectedKeys;
|
|
130
135
|
var init_dotenv_loader = __esm({
|
|
131
136
|
"src/config/dotenv-loader.ts"() {
|
|
132
137
|
"use strict";
|
|
@@ -135,6 +140,8 @@ var init_dotenv_loader = __esm({
|
|
|
135
140
|
dotenvLoaded = false;
|
|
136
141
|
dotenvProjectRoot = null;
|
|
137
142
|
loadedEnvFiles = [];
|
|
143
|
+
loadedEnvKeys = /* @__PURE__ */ new Set();
|
|
144
|
+
loadedEnvValues = /* @__PURE__ */ new Map();
|
|
138
145
|
injectedKeys = /* @__PURE__ */ new Set();
|
|
139
146
|
}
|
|
140
147
|
});
|
|
@@ -518,7 +525,7 @@ function closeAllDatabases() {
|
|
|
518
525
|
_dbCache.delete(key);
|
|
519
526
|
}
|
|
520
527
|
}
|
|
521
|
-
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;
|
|
528
|
+
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;
|
|
522
529
|
var init_sqlite_db = __esm({
|
|
523
530
|
"src/store/sqlite-db.ts"() {
|
|
524
531
|
"use strict";
|
|
@@ -1164,6 +1171,79 @@ CREATE TABLE IF NOT EXISTS compaction_checkpoints (
|
|
|
1164
1171
|
created_at TEXT NOT NULL,
|
|
1165
1172
|
updated_at TEXT NOT NULL
|
|
1166
1173
|
);
|
|
1174
|
+
`;
|
|
1175
|
+
CREATE_EVIDENCE_CARDS_TABLE = `
|
|
1176
|
+
CREATE TABLE IF NOT EXISTS evidence_cards (
|
|
1177
|
+
id TEXT PRIMARY KEY,
|
|
1178
|
+
project_id TEXT NOT NULL,
|
|
1179
|
+
candidate_kind TEXT NOT NULL,
|
|
1180
|
+
candidate_id TEXT NOT NULL,
|
|
1181
|
+
title TEXT NOT NULL,
|
|
1182
|
+
summary TEXT NOT NULL DEFAULT '',
|
|
1183
|
+
entity_name TEXT,
|
|
1184
|
+
source_kind TEXT NOT NULL,
|
|
1185
|
+
source_ref TEXT NOT NULL,
|
|
1186
|
+
locator TEXT,
|
|
1187
|
+
captured_hash TEXT,
|
|
1188
|
+
session_id TEXT,
|
|
1189
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
1190
|
+
verification TEXT NOT NULL DEFAULT 'unverified',
|
|
1191
|
+
freshness TEXT NOT NULL DEFAULT 'current',
|
|
1192
|
+
stale_reason TEXT,
|
|
1193
|
+
files_json TEXT NOT NULL DEFAULT '[]',
|
|
1194
|
+
related_entities_json TEXT NOT NULL DEFAULT '[]',
|
|
1195
|
+
created_at TEXT NOT NULL,
|
|
1196
|
+
updated_at TEXT NOT NULL,
|
|
1197
|
+
UNIQUE(project_id, candidate_kind, candidate_id)
|
|
1198
|
+
);
|
|
1199
|
+
`;
|
|
1200
|
+
CREATE_EVIDENCE_CARD_EVENTS_TABLE = `
|
|
1201
|
+
CREATE TABLE IF NOT EXISTS evidence_card_events (
|
|
1202
|
+
id TEXT PRIMARY KEY,
|
|
1203
|
+
project_id TEXT NOT NULL,
|
|
1204
|
+
card_id TEXT NOT NULL,
|
|
1205
|
+
kind TEXT NOT NULL,
|
|
1206
|
+
detail TEXT,
|
|
1207
|
+
created_at TEXT NOT NULL,
|
|
1208
|
+
FOREIGN KEY (card_id) REFERENCES evidence_cards(id) ON DELETE CASCADE
|
|
1209
|
+
);
|
|
1210
|
+
`;
|
|
1211
|
+
CREATE_MEMORY_FEEDBACK_STATES_TABLE = `
|
|
1212
|
+
CREATE TABLE IF NOT EXISTS memory_feedback_states (
|
|
1213
|
+
project_id TEXT NOT NULL,
|
|
1214
|
+
candidate_kind TEXT NOT NULL,
|
|
1215
|
+
candidate_id TEXT NOT NULL,
|
|
1216
|
+
weight REAL NOT NULL DEFAULT 1.0,
|
|
1217
|
+
lifecycle_status TEXT NOT NULL DEFAULT 'active',
|
|
1218
|
+
updated_at TEXT NOT NULL,
|
|
1219
|
+
PRIMARY KEY (project_id, candidate_kind, candidate_id)
|
|
1220
|
+
);
|
|
1221
|
+
`;
|
|
1222
|
+
CREATE_MEMORY_FEEDBACK_EVENTS_TABLE = `
|
|
1223
|
+
CREATE TABLE IF NOT EXISTS memory_feedback_events (
|
|
1224
|
+
id TEXT PRIMARY KEY,
|
|
1225
|
+
project_id TEXT NOT NULL,
|
|
1226
|
+
candidate_kind TEXT NOT NULL,
|
|
1227
|
+
candidate_id TEXT NOT NULL,
|
|
1228
|
+
signal TEXT NOT NULL,
|
|
1229
|
+
actor TEXT,
|
|
1230
|
+
note TEXT,
|
|
1231
|
+
source_ref TEXT NOT NULL,
|
|
1232
|
+
target_event_id TEXT,
|
|
1233
|
+
delta REAL NOT NULL DEFAULT 0,
|
|
1234
|
+
observed_at TEXT NOT NULL
|
|
1235
|
+
);
|
|
1236
|
+
`;
|
|
1237
|
+
CREATE_MCP_BINDINGS_TABLE = `
|
|
1238
|
+
CREATE TABLE IF NOT EXISTS mcp_bindings (
|
|
1239
|
+
handle_id TEXT PRIMARY KEY,
|
|
1240
|
+
project_id TEXT NOT NULL,
|
|
1241
|
+
project_root TEXT NOT NULL,
|
|
1242
|
+
data_dir TEXT NOT NULL,
|
|
1243
|
+
created_at TEXT NOT NULL,
|
|
1244
|
+
last_used_at TEXT NOT NULL,
|
|
1245
|
+
expires_at TEXT
|
|
1246
|
+
);
|
|
1167
1247
|
`;
|
|
1168
1248
|
CREATE_INDEXES = `
|
|
1169
1249
|
CREATE INDEX IF NOT EXISTS idx_observations_projectId ON observations(projectId);
|
|
@@ -1226,6 +1306,12 @@ CREATE INDEX IF NOT EXISTS idx_maintenance_targets_updated ON maintenance_target
|
|
|
1226
1306
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_project_recent ON compaction_checkpoints(project_id, status, completed_at DESC, pre_captured_at DESC);
|
|
1227
1307
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_session_pending ON compaction_checkpoints(project_id, session_id, agent, phase, status, pre_captured_at DESC);
|
|
1228
1308
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_source ON compaction_checkpoints(project_id, source_key);
|
|
1309
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_cards_project ON evidence_cards(project_id, status, updated_at DESC);
|
|
1310
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(project_id, candidate_kind, candidate_id);
|
|
1311
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at);
|
|
1312
|
+
CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC);
|
|
1313
|
+
CREATE INDEX IF NOT EXISTS idx_memory_feedback_events_candidate ON memory_feedback_events(project_id, candidate_kind, candidate_id, observed_at DESC);
|
|
1314
|
+
CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC);
|
|
1229
1315
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
1230
1316
|
ON maintenance_jobs(project_id, kind, dedupe_key)
|
|
1231
1317
|
WHERE status IN ('pending', 'running', 'retry');
|
|
@@ -1381,6 +1467,22 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
|
1381
1467
|
}
|
|
1382
1468
|
db2.exec("CREATE INDEX IF NOT EXISTS idx_media_jobs_source_asset ON media_jobs(project_id, source_asset_id, status)");
|
|
1383
1469
|
}
|
|
1470
|
+
},
|
|
1471
|
+
{
|
|
1472
|
+
id: "1.8-context-control-plane",
|
|
1473
|
+
apply: (db2) => {
|
|
1474
|
+
db2.exec(CREATE_EVIDENCE_CARDS_TABLE);
|
|
1475
|
+
db2.exec(CREATE_EVIDENCE_CARD_EVENTS_TABLE);
|
|
1476
|
+
db2.exec(CREATE_MEMORY_FEEDBACK_STATES_TABLE);
|
|
1477
|
+
db2.exec(CREATE_MEMORY_FEEDBACK_EVENTS_TABLE);
|
|
1478
|
+
db2.exec(CREATE_MCP_BINDINGS_TABLE);
|
|
1479
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_cards_project ON evidence_cards(project_id, status, updated_at DESC)");
|
|
1480
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(project_id, candidate_kind, candidate_id)");
|
|
1481
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at)");
|
|
1482
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC)");
|
|
1483
|
+
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)");
|
|
1484
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC)");
|
|
1485
|
+
}
|
|
1384
1486
|
}
|
|
1385
1487
|
];
|
|
1386
1488
|
_dbCache = /* @__PURE__ */ new Map();
|
|
@@ -7981,8 +8083,228 @@ 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/knowledge/workspace-store.ts
|
|
7985
|
-
import { randomUUID as
|
|
8307
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
7986
8308
|
function arrayValue(raw) {
|
|
7987
8309
|
if (typeof raw !== "string" || !raw) return [];
|
|
7988
8310
|
try {
|
|
@@ -8123,7 +8445,7 @@ var init_workspace_store = __esm({
|
|
|
8123
8445
|
}
|
|
8124
8446
|
createProposal(input) {
|
|
8125
8447
|
const proposal = {
|
|
8126
|
-
id: input.id ??
|
|
8448
|
+
id: input.id ?? randomUUID4(),
|
|
8127
8449
|
...input,
|
|
8128
8450
|
status: input.status ?? "pending",
|
|
8129
8451
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -8176,13 +8498,13 @@ __export(workspace_exports, {
|
|
|
8176
8498
|
loadKnowledgeWorkspace: () => loadKnowledgeWorkspace,
|
|
8177
8499
|
resolveKnowledgeWorkspaceFile: () => resolveKnowledgeWorkspaceFile
|
|
8178
8500
|
});
|
|
8179
|
-
import { createHash as
|
|
8501
|
+
import { createHash as createHash4 } from "crypto";
|
|
8180
8502
|
import { execFile } from "child_process";
|
|
8181
8503
|
import { promises as fs6 } from "fs";
|
|
8182
8504
|
import path9 from "path";
|
|
8183
8505
|
import { promisify } from "util";
|
|
8184
8506
|
function hash(value) {
|
|
8185
|
-
return
|
|
8507
|
+
return createHash4("sha256").update(value).digest("hex");
|
|
8186
8508
|
}
|
|
8187
8509
|
function workspaceId(projectId, mode) {
|
|
8188
8510
|
return "workspace:" + hash(projectId + ":" + mode).slice(0, 24);
|
|
@@ -8778,7 +9100,7 @@ Respond in JSON only:
|
|
|
8778
9100
|
});
|
|
8779
9101
|
|
|
8780
9102
|
// src/media/media-store.ts
|
|
8781
|
-
import { randomUUID as
|
|
9103
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
8782
9104
|
function asOptionalText(value) {
|
|
8783
9105
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
8784
9106
|
}
|
|
@@ -8948,7 +9270,7 @@ var init_media_store = __esm({
|
|
|
8948
9270
|
return { asset: this.getAsset(input.projectId, existing.id), deduplicated: true };
|
|
8949
9271
|
}
|
|
8950
9272
|
const asset = {
|
|
8951
|
-
id:
|
|
9273
|
+
id: randomUUID5(),
|
|
8952
9274
|
...input,
|
|
8953
9275
|
createdAt: now3,
|
|
8954
9276
|
updatedAt: now3
|
|
@@ -9028,7 +9350,7 @@ var init_media_store = __esm({
|
|
|
9028
9350
|
`).get(input.assetId, input.observationId ?? null, input.role);
|
|
9029
9351
|
if (existing) return rowToLink(existing);
|
|
9030
9352
|
const link = {
|
|
9031
|
-
id:
|
|
9353
|
+
id: randomUUID5(),
|
|
9032
9354
|
assetId: input.assetId,
|
|
9033
9355
|
projectId: input.projectId,
|
|
9034
9356
|
...input.observationId !== void 0 ? { observationId: input.observationId } : {},
|
|
@@ -9067,7 +9389,7 @@ var init_media_store = __esm({
|
|
|
9067
9389
|
return rowToDerivation(this.db.prepare("SELECT * FROM media_derivations WHERE id = ?").get(existing.id));
|
|
9068
9390
|
}
|
|
9069
9391
|
const derivation = {
|
|
9070
|
-
id:
|
|
9392
|
+
id: randomUUID5(),
|
|
9071
9393
|
...input,
|
|
9072
9394
|
content,
|
|
9073
9395
|
...error ? { error } : {},
|
|
@@ -9154,7 +9476,7 @@ var init_media_store = __esm({
|
|
|
9154
9476
|
createJob(input) {
|
|
9155
9477
|
const now3 = Date.now();
|
|
9156
9478
|
const job = {
|
|
9157
|
-
id:
|
|
9479
|
+
id: randomUUID5(),
|
|
9158
9480
|
projectId: input.projectId,
|
|
9159
9481
|
kind: input.kind,
|
|
9160
9482
|
status: "queued",
|
|
@@ -9316,14 +9638,14 @@ var init_types2 = __esm({
|
|
|
9316
9638
|
});
|
|
9317
9639
|
|
|
9318
9640
|
// src/media/asset-store.ts
|
|
9319
|
-
import { createHash as
|
|
9641
|
+
import { createHash as createHash5, randomUUID as randomUUID6 } from "crypto";
|
|
9320
9642
|
import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename as rename2, rm, stat as stat2, writeFile as writeFile3 } from "fs/promises";
|
|
9321
9643
|
import path10 from "path";
|
|
9322
9644
|
function mediaRoot(dataDir) {
|
|
9323
9645
|
return path10.resolve(dataDir, "media");
|
|
9324
9646
|
}
|
|
9325
9647
|
function projectStorageKey(projectId) {
|
|
9326
|
-
return
|
|
9648
|
+
return createHash5("sha256").update(projectId).digest("hex").slice(0, 16);
|
|
9327
9649
|
}
|
|
9328
9650
|
function validateUnderRoot(root, candidate) {
|
|
9329
9651
|
const resolved = path10.resolve(candidate);
|
|
@@ -9387,7 +9709,7 @@ async function destinationExists(destination) {
|
|
|
9387
9709
|
async function persistBuffer(bytes, destination) {
|
|
9388
9710
|
await mkdir3(path10.dirname(destination), { recursive: true });
|
|
9389
9711
|
if (await destinationExists(destination)) return false;
|
|
9390
|
-
const temporary = `${destination}.${
|
|
9712
|
+
const temporary = `${destination}.${randomUUID6()}.tmp`;
|
|
9391
9713
|
try {
|
|
9392
9714
|
await writeFile3(temporary, bytes, { flag: "wx" });
|
|
9393
9715
|
await rename2(temporary, destination);
|
|
@@ -9432,7 +9754,7 @@ async function importMediaBuffer(input) {
|
|
|
9432
9754
|
if (input.bytes.length === 0) throw new Error("Media import rejects empty payloads");
|
|
9433
9755
|
if (input.bytes.length > maxBytes) throw new Error(`Media payload is too large (${input.bytes.length} bytes; limit ${maxBytes})`);
|
|
9434
9756
|
const detected = detectMedia(input.bytes.subarray(0, 32));
|
|
9435
|
-
const sha256 =
|
|
9757
|
+
const sha256 = createHash5("sha256").update(input.bytes).digest("hex");
|
|
9436
9758
|
return importKnownMedia({
|
|
9437
9759
|
dataDir: input.dataDir,
|
|
9438
9760
|
projectId: input.projectId,
|
|
@@ -9450,7 +9772,7 @@ async function readMediaAsset(dataDir, asset, maxBytes = DEFAULT_MAX_MEDIA_BYTES
|
|
|
9450
9772
|
if (asset.byteSize > maxBytes) throw new Error(`Media asset exceeds read limit (${asset.byteSize} bytes; limit ${maxBytes})`);
|
|
9451
9773
|
const bytes = await readFile3(getMediaAssetPath(dataDir, asset));
|
|
9452
9774
|
if (bytes.length !== asset.byteSize) throw new Error(`Media asset size no longer matches metadata: ${asset.id}`);
|
|
9453
|
-
const sha256 =
|
|
9775
|
+
const sha256 = createHash5("sha256").update(bytes).digest("hex");
|
|
9454
9776
|
if (sha256 !== asset.sha256) throw new Error(`Media asset hash no longer matches metadata: ${asset.id}`);
|
|
9455
9777
|
return bytes;
|
|
9456
9778
|
}
|
|
@@ -62201,7 +62523,7 @@ var require_gaxios = __commonJS({
|
|
|
62201
62523
|
var retry_js_1 = require_retry3();
|
|
62202
62524
|
var stream_1 = __require("stream");
|
|
62203
62525
|
var interceptor_js_1 = require_interceptor();
|
|
62204
|
-
var
|
|
62526
|
+
var randomUUID16 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
|
|
62205
62527
|
var HTTP_STATUS_NO_CONTENT = 204;
|
|
62206
62528
|
var Gaxios = class {
|
|
62207
62529
|
agentCache = /* @__PURE__ */ new Map();
|
|
@@ -62474,7 +62796,7 @@ var require_gaxios = __commonJS({
|
|
|
62474
62796
|
*/
|
|
62475
62797
|
["Blob", "File", "FormData"].includes(opts.data?.constructor?.name || "");
|
|
62476
62798
|
if (opts.multipart?.length) {
|
|
62477
|
-
const boundary = await
|
|
62799
|
+
const boundary = await randomUUID16();
|
|
62478
62800
|
preparedHeaders.set("content-type", `multipart/related; boundary=${boundary}`);
|
|
62479
62801
|
opts.body = stream_1.Readable.from(this.getMultipartRequest(opts.multipart, boundary));
|
|
62480
62802
|
} else if (shouldDirectlyPassData) {
|
|
@@ -74701,7 +75023,7 @@ var require_websocket = __commonJS({
|
|
|
74701
75023
|
var http3 = __require("http");
|
|
74702
75024
|
var net = __require("net");
|
|
74703
75025
|
var tls = __require("tls");
|
|
74704
|
-
var { randomBytes, createHash:
|
|
75026
|
+
var { randomBytes, createHash: createHash14 } = __require("crypto");
|
|
74705
75027
|
var { Duplex, Readable: Readable2 } = __require("stream");
|
|
74706
75028
|
var { URL: URL2 } = __require("url");
|
|
74707
75029
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -75369,7 +75691,7 @@ var require_websocket = __commonJS({
|
|
|
75369
75691
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
75370
75692
|
return;
|
|
75371
75693
|
}
|
|
75372
|
-
const digest2 =
|
|
75694
|
+
const digest2 = createHash14("sha1").update(key + GUID).digest("base64");
|
|
75373
75695
|
if (res.headers["sec-websocket-accept"] !== digest2) {
|
|
75374
75696
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
75375
75697
|
return;
|
|
@@ -75741,7 +76063,7 @@ var require_websocket_server = __commonJS({
|
|
|
75741
76063
|
var EventEmitter = __require("events");
|
|
75742
76064
|
var http3 = __require("http");
|
|
75743
76065
|
var { Duplex } = __require("stream");
|
|
75744
|
-
var { createHash:
|
|
76066
|
+
var { createHash: createHash14 } = __require("crypto");
|
|
75745
76067
|
var extension3 = require_extension();
|
|
75746
76068
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
75747
76069
|
var subprotocol2 = require_subprotocol();
|
|
@@ -76048,7 +76370,7 @@ var require_websocket_server = __commonJS({
|
|
|
76048
76370
|
);
|
|
76049
76371
|
}
|
|
76050
76372
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
76051
|
-
const digest2 =
|
|
76373
|
+
const digest2 = createHash14("sha1").update(key + GUID).digest("base64");
|
|
76052
76374
|
const headers = [
|
|
76053
76375
|
"HTTP/1.1 101 Switching Protocols",
|
|
76054
76376
|
"Upgrade: websocket",
|
|
@@ -143186,6 +143508,186 @@ var init_audio_jobs = __esm({
|
|
|
143186
143508
|
}
|
|
143187
143509
|
});
|
|
143188
143510
|
|
|
143511
|
+
// src/memory/feedback-model.ts
|
|
143512
|
+
function feedbackWeightMultiplier(weight) {
|
|
143513
|
+
return Math.max(0.35, Math.min(1.4, 0.35 + Math.max(0, Math.min(2, weight)) * 0.525));
|
|
143514
|
+
}
|
|
143515
|
+
var init_feedback_model = __esm({
|
|
143516
|
+
"src/memory/feedback-model.ts"() {
|
|
143517
|
+
"use strict";
|
|
143518
|
+
init_esm_shims();
|
|
143519
|
+
}
|
|
143520
|
+
});
|
|
143521
|
+
|
|
143522
|
+
// src/memory/feedback.ts
|
|
143523
|
+
var feedback_exports = {};
|
|
143524
|
+
__export(feedback_exports, {
|
|
143525
|
+
FEEDBACK_DELTAS: () => FEEDBACK_DELTAS,
|
|
143526
|
+
MemoryFeedbackStore: () => MemoryFeedbackStore,
|
|
143527
|
+
applyMemoryFeedback: () => applyMemoryFeedback,
|
|
143528
|
+
feedbackWeightMultiplier: () => feedbackWeightMultiplier
|
|
143529
|
+
});
|
|
143530
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
143531
|
+
function applyMemoryFeedback(current, event) {
|
|
143532
|
+
const delta = event.signal === "revoke" ? 0 : FEEDBACK_DELTAS[event.signal];
|
|
143533
|
+
const weight = Math.max(0, Math.min(2, current.weight + delta));
|
|
143534
|
+
const status = (event.signal === "code-conflict" || event.signal === "user-correction" || event.signal === "weaken") && weight < 0.5 ? "archived" : current.status;
|
|
143535
|
+
return { weight, status, audit: [...current.audit, { ...event }] };
|
|
143536
|
+
}
|
|
143537
|
+
function rowToEvent(row) {
|
|
143538
|
+
return {
|
|
143539
|
+
id: String(row.id),
|
|
143540
|
+
projectId: String(row.project_id),
|
|
143541
|
+
candidateKind: row.candidate_kind,
|
|
143542
|
+
candidateId: String(row.candidate_id),
|
|
143543
|
+
signal: row.signal,
|
|
143544
|
+
...row.observed_at ? { at: String(row.observed_at) } : { at: (/* @__PURE__ */ new Date()).toISOString() },
|
|
143545
|
+
...row.actor ? { actor: String(row.actor) } : {},
|
|
143546
|
+
...row.note ? { note: String(row.note) } : {},
|
|
143547
|
+
...row.source_ref ? { sourceRef: String(row.source_ref) } : {},
|
|
143548
|
+
...row.target_event_id ? { targetEventId: String(row.target_event_id) } : {},
|
|
143549
|
+
delta: Number(row.delta ?? 0)
|
|
143550
|
+
};
|
|
143551
|
+
}
|
|
143552
|
+
var FEEDBACK_DELTAS, MemoryFeedbackStore;
|
|
143553
|
+
var init_feedback = __esm({
|
|
143554
|
+
"src/memory/feedback.ts"() {
|
|
143555
|
+
"use strict";
|
|
143556
|
+
init_esm_shims();
|
|
143557
|
+
init_sqlite_db();
|
|
143558
|
+
init_feedback_model();
|
|
143559
|
+
FEEDBACK_DELTAS = {
|
|
143560
|
+
"user-correction": -0.35,
|
|
143561
|
+
"verification-success": 0.25,
|
|
143562
|
+
"verification-failure": -0.25,
|
|
143563
|
+
"code-change": -0.15,
|
|
143564
|
+
used: 0.1,
|
|
143565
|
+
"not-used": -0.05,
|
|
143566
|
+
"code-conflict": -0.4,
|
|
143567
|
+
strengthen: 0.2,
|
|
143568
|
+
weaken: -0.2
|
|
143569
|
+
};
|
|
143570
|
+
MemoryFeedbackStore = class {
|
|
143571
|
+
db = null;
|
|
143572
|
+
async init(dataDir) {
|
|
143573
|
+
this.db = getDatabase(dataDir);
|
|
143574
|
+
}
|
|
143575
|
+
requireDb() {
|
|
143576
|
+
if (!this.db) throw new Error("MemoryFeedbackStore is not initialized.");
|
|
143577
|
+
return this.db;
|
|
143578
|
+
}
|
|
143579
|
+
loadEvents(projectId, candidateKind, candidateId) {
|
|
143580
|
+
return this.requireDb().prepare(`
|
|
143581
|
+
SELECT * FROM memory_feedback_events
|
|
143582
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
143583
|
+
ORDER BY observed_at ASC, rowid ASC
|
|
143584
|
+
`).all(projectId, candidateKind, candidateId).map(rowToEvent);
|
|
143585
|
+
}
|
|
143586
|
+
rebuild(projectId, candidateKind, candidateId) {
|
|
143587
|
+
const events = this.loadEvents(projectId, candidateKind, candidateId);
|
|
143588
|
+
const revoked = new Set(events.filter((event) => event.signal === "revoke" && event.targetEventId).map((event) => event.targetEventId));
|
|
143589
|
+
let state = { weight: 1, status: "active", audit: [] };
|
|
143590
|
+
for (const event of events) {
|
|
143591
|
+
if (event.signal === "revoke" || revoked.has(event.id)) {
|
|
143592
|
+
state.audit.push(event);
|
|
143593
|
+
continue;
|
|
143594
|
+
}
|
|
143595
|
+
state = applyMemoryFeedback(state, event);
|
|
143596
|
+
}
|
|
143597
|
+
this.requireDb().prepare(`
|
|
143598
|
+
INSERT INTO memory_feedback_states (project_id, candidate_kind, candidate_id, weight, lifecycle_status, updated_at)
|
|
143599
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
143600
|
+
ON CONFLICT(project_id, candidate_kind, candidate_id) DO UPDATE SET
|
|
143601
|
+
weight = excluded.weight, lifecycle_status = excluded.lifecycle_status, updated_at = excluded.updated_at
|
|
143602
|
+
`).run(projectId, candidateKind, candidateId, state.weight, state.status, (/* @__PURE__ */ new Date()).toISOString());
|
|
143603
|
+
return state;
|
|
143604
|
+
}
|
|
143605
|
+
getState(projectId, candidateKind, candidateId) {
|
|
143606
|
+
const row = this.requireDb().prepare(`
|
|
143607
|
+
SELECT weight, lifecycle_status FROM memory_feedback_states
|
|
143608
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
143609
|
+
`).get(projectId, candidateKind, candidateId);
|
|
143610
|
+
if (!row) return { weight: 1, status: "active", audit: [] };
|
|
143611
|
+
return {
|
|
143612
|
+
weight: Number(row.weight ?? 1),
|
|
143613
|
+
status: row.lifecycle_status ?? "active",
|
|
143614
|
+
audit: this.loadEvents(projectId, candidateKind, candidateId)
|
|
143615
|
+
};
|
|
143616
|
+
}
|
|
143617
|
+
listStates(projectId, candidateKind = "observation") {
|
|
143618
|
+
return this.requireDb().prepare(`
|
|
143619
|
+
SELECT candidate_id, weight, lifecycle_status, updated_at
|
|
143620
|
+
FROM memory_feedback_states WHERE project_id = ? AND candidate_kind = ?
|
|
143621
|
+
ORDER BY updated_at DESC
|
|
143622
|
+
`).all(projectId, candidateKind).map((row) => ({
|
|
143623
|
+
candidateId: String(row.candidate_id),
|
|
143624
|
+
weight: Number(row.weight),
|
|
143625
|
+
status: row.lifecycle_status,
|
|
143626
|
+
updatedAt: String(row.updated_at)
|
|
143627
|
+
}));
|
|
143628
|
+
}
|
|
143629
|
+
weights(projectId, candidateKind = "observation") {
|
|
143630
|
+
const states = /* @__PURE__ */ new Map();
|
|
143631
|
+
for (const row of this.listStates(projectId, candidateKind)) {
|
|
143632
|
+
states.set(row.candidateId, this.getState(projectId, candidateKind, row.candidateId));
|
|
143633
|
+
}
|
|
143634
|
+
return states;
|
|
143635
|
+
}
|
|
143636
|
+
record(input) {
|
|
143637
|
+
if (input.signal === "revoke" && !input.targetEventId) {
|
|
143638
|
+
throw new Error("A revoke feedback event requires targetEventId.");
|
|
143639
|
+
}
|
|
143640
|
+
if (input.signal === "revoke") {
|
|
143641
|
+
const target = this.requireDb().prepare(`
|
|
143642
|
+
SELECT 1 FROM memory_feedback_events
|
|
143643
|
+
WHERE id = ? AND project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
143644
|
+
`).get(input.targetEventId, input.projectId, input.candidateKind, input.candidateId);
|
|
143645
|
+
if (!target) throw new Error("The feedback event to revoke was not found in the same candidate scope.");
|
|
143646
|
+
}
|
|
143647
|
+
const event = {
|
|
143648
|
+
id: randomUUID7(),
|
|
143649
|
+
projectId: input.projectId,
|
|
143650
|
+
candidateKind: input.candidateKind,
|
|
143651
|
+
candidateId: input.candidateId,
|
|
143652
|
+
signal: input.signal,
|
|
143653
|
+
sourceRef: input.sourceRef,
|
|
143654
|
+
...input.actor ? { actor: input.actor } : {},
|
|
143655
|
+
...input.note ? { note: input.note.slice(0, 2e3) } : {},
|
|
143656
|
+
...input.targetEventId ? { targetEventId: input.targetEventId } : {},
|
|
143657
|
+
at: input.at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
143658
|
+
delta: input.signal === "revoke" ? 0 : FEEDBACK_DELTAS[input.signal]
|
|
143659
|
+
};
|
|
143660
|
+
this.requireDb().prepare(`
|
|
143661
|
+
INSERT INTO memory_feedback_events (
|
|
143662
|
+
id, project_id, candidate_kind, candidate_id, signal, actor, note,
|
|
143663
|
+
source_ref, target_event_id, delta, observed_at
|
|
143664
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
143665
|
+
`).run(
|
|
143666
|
+
event.id,
|
|
143667
|
+
event.projectId,
|
|
143668
|
+
event.candidateKind,
|
|
143669
|
+
event.candidateId,
|
|
143670
|
+
event.signal,
|
|
143671
|
+
event.actor ?? null,
|
|
143672
|
+
event.note ?? null,
|
|
143673
|
+
event.sourceRef,
|
|
143674
|
+
event.targetEventId ?? null,
|
|
143675
|
+
event.delta,
|
|
143676
|
+
event.at
|
|
143677
|
+
);
|
|
143678
|
+
return { event, state: this.rebuild(input.projectId, input.candidateKind, input.candidateId) };
|
|
143679
|
+
}
|
|
143680
|
+
audit(projectId, candidateKind, candidateId, limit2 = 100) {
|
|
143681
|
+
return this.requireDb().prepare(`
|
|
143682
|
+
SELECT * FROM memory_feedback_events
|
|
143683
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
143684
|
+
ORDER BY observed_at DESC, rowid DESC LIMIT ?
|
|
143685
|
+
`).all(projectId, candidateKind, candidateId, Math.min(200, Math.max(1, Math.floor(limit2)))).map(rowToEvent);
|
|
143686
|
+
}
|
|
143687
|
+
};
|
|
143688
|
+
}
|
|
143689
|
+
});
|
|
143690
|
+
|
|
143189
143691
|
// src/memory/retention.ts
|
|
143190
143692
|
var retention_exports = {};
|
|
143191
143693
|
__export(retention_exports, {
|
|
@@ -143227,6 +143729,7 @@ function getEffectiveRetentionDays(doc) {
|
|
|
143227
143729
|
}
|
|
143228
143730
|
function isImmune(doc) {
|
|
143229
143731
|
if (doc.type === "probe") return false;
|
|
143732
|
+
if (doc.feedbackStatus === "archived") return false;
|
|
143230
143733
|
if (doc.admissionState === "candidate" || doc.admissionState === "ephemeral") return false;
|
|
143231
143734
|
if (doc.valueCategory === "core") return true;
|
|
143232
143735
|
const importance = getImportanceLevel(doc);
|
|
@@ -143259,7 +143762,8 @@ function calculateRelevance(doc, referenceTime) {
|
|
|
143259
143762
|
const decayFactor = Math.exp(-ageDays / retention);
|
|
143260
143763
|
const accessCount = doc.accessCount ?? 0;
|
|
143261
143764
|
const accessBoost = Math.min(2, 1 + 0.1 * accessCount);
|
|
143262
|
-
|
|
143765
|
+
const feedbackMultiplier = doc.feedbackWeight === void 0 ? 1 : feedbackWeightMultiplier(doc.feedbackWeight);
|
|
143766
|
+
let totalScore = base * decayFactor * accessBoost * feedbackMultiplier;
|
|
143263
143767
|
const immune = isImmune(doc);
|
|
143264
143768
|
if (immune) {
|
|
143265
143769
|
totalScore = Math.max(totalScore, 0.5);
|
|
@@ -143271,7 +143775,8 @@ function calculateRelevance(doc, referenceTime) {
|
|
|
143271
143775
|
decayFactor,
|
|
143272
143776
|
accessBoost,
|
|
143273
143777
|
ageDays,
|
|
143274
|
-
isImmune: immune
|
|
143778
|
+
isImmune: immune,
|
|
143779
|
+
feedbackMultiplier
|
|
143275
143780
|
};
|
|
143276
143781
|
}
|
|
143277
143782
|
function rankByRelevance(docs, referenceTime) {
|
|
@@ -143279,6 +143784,7 @@ function rankByRelevance(docs, referenceTime) {
|
|
|
143279
143784
|
}
|
|
143280
143785
|
function getRetentionZone(doc, referenceTime) {
|
|
143281
143786
|
const now3 = referenceTime ?? /* @__PURE__ */ new Date();
|
|
143787
|
+
if (doc.feedbackStatus === "archived") return "archive-candidate";
|
|
143282
143788
|
const importance = getImportanceLevel(doc);
|
|
143283
143789
|
const retention = getEffectiveRetentionDays(doc);
|
|
143284
143790
|
const createdAt = new Date(doc.createdAt);
|
|
@@ -143350,7 +143856,7 @@ function explainRetention(doc, referenceTime) {
|
|
|
143350
143856
|
summary: parts.join(" ; ")
|
|
143351
143857
|
};
|
|
143352
143858
|
}
|
|
143353
|
-
function toRetentionDocument(obs, accessMap) {
|
|
143859
|
+
function toRetentionDocument(obs, accessMap, feedback) {
|
|
143354
143860
|
const access2 = accessMap?.get(obs.id);
|
|
143355
143861
|
return {
|
|
143356
143862
|
id: `obs-${obs.id}`,
|
|
@@ -143372,11 +143878,12 @@ function toRetentionDocument(obs, accessMap) {
|
|
|
143372
143878
|
sourceDetail: obs.sourceDetail ?? "",
|
|
143373
143879
|
valueCategory: obs.valueCategory ?? "",
|
|
143374
143880
|
admissionState: obs.admissionState ?? "",
|
|
143375
|
-
admissionReason: obs.admissionReason ?? ""
|
|
143881
|
+
admissionReason: obs.admissionReason ?? "",
|
|
143882
|
+
...feedback ? { feedbackWeight: feedback.weight, feedbackStatus: feedback.status } : {}
|
|
143376
143883
|
};
|
|
143377
143884
|
}
|
|
143378
143885
|
function projectObservationRetention(observation, options = {}) {
|
|
143379
|
-
const document2 = toRetentionDocument(observation, options.accessMap);
|
|
143886
|
+
const document2 = toRetentionDocument(observation, options.accessMap, options.feedback);
|
|
143380
143887
|
const relevance = calculateRelevance(document2, options.referenceTime);
|
|
143381
143888
|
const explanation = explainRetention(document2, options.referenceTime);
|
|
143382
143889
|
return {
|
|
@@ -143401,7 +143908,17 @@ function summarizeRetentionProjections(projections) {
|
|
|
143401
143908
|
}
|
|
143402
143909
|
return { active, stale, archiveCandidates, immune };
|
|
143403
143910
|
}
|
|
143404
|
-
async function
|
|
143911
|
+
async function loadFeedbackStore(dataDir) {
|
|
143912
|
+
try {
|
|
143913
|
+
const { MemoryFeedbackStore: MemoryFeedbackStore2 } = await Promise.resolve().then(() => (init_feedback(), feedback_exports));
|
|
143914
|
+
const store = new MemoryFeedbackStore2();
|
|
143915
|
+
await store.init(dataDir);
|
|
143916
|
+
return store;
|
|
143917
|
+
} catch {
|
|
143918
|
+
return void 0;
|
|
143919
|
+
}
|
|
143920
|
+
}
|
|
143921
|
+
async function archiveExpiredBatch(projectDir2, options) {
|
|
143405
143922
|
const store = getObservationStore();
|
|
143406
143923
|
const limit2 = Math.min(500, Math.max(1, Math.floor(options.limit ?? 100)));
|
|
143407
143924
|
const afterId = Math.max(0, Math.floor(options.afterId ?? 0));
|
|
@@ -143410,11 +143927,13 @@ async function archiveExpiredBatch(_projectDir, options) {
|
|
|
143410
143927
|
afterId,
|
|
143411
143928
|
limit: limit2 + 1
|
|
143412
143929
|
});
|
|
143930
|
+
const feedback = await loadFeedbackStore(projectDir2);
|
|
143413
143931
|
const hasMore = page.length > limit2;
|
|
143414
143932
|
const scanned = hasMore ? page.slice(0, limit2) : page;
|
|
143415
143933
|
const candidateIds = scanned.filter((observation) => !options.reader || canManageObservation(observation, options.reader)).filter((observation) => projectObservationRetention(observation, {
|
|
143416
143934
|
accessMap: options.accessMap,
|
|
143417
|
-
referenceTime: options.referenceTime
|
|
143935
|
+
referenceTime: options.referenceTime,
|
|
143936
|
+
...feedback ? { feedback: feedback.getState(options.projectId, "observation", String(observation.id)) } : {}
|
|
143418
143937
|
}).zone === "archive-candidate").map((observation) => observation.id);
|
|
143419
143938
|
const archived = candidateIds.length === 0 ? 0 : await store.atomic(async (tx) => {
|
|
143420
143939
|
const updates = await Promise.all(
|
|
@@ -143445,6 +143964,7 @@ async function archiveExpired(projectDir2, referenceTime, accessMap, projectId,
|
|
|
143445
143964
|
const remaining = reader ? remainingObservations.filter((observation) => canManageObservation(observation, reader)).length : remainingObservations.length;
|
|
143446
143965
|
return { archived, remaining };
|
|
143447
143966
|
}
|
|
143967
|
+
const feedback = await loadFeedbackStore(projectDir2);
|
|
143448
143968
|
return await store.atomic(async (tx) => {
|
|
143449
143969
|
const allObs = await tx.loadAll();
|
|
143450
143970
|
const activeObs = allObs.filter(
|
|
@@ -143452,7 +143972,11 @@ async function archiveExpired(projectDir2, referenceTime, accessMap, projectId,
|
|
|
143452
143972
|
);
|
|
143453
143973
|
const archivedIds = [];
|
|
143454
143974
|
for (const obs of activeObs) {
|
|
143455
|
-
const retention = projectObservationRetention(obs, {
|
|
143975
|
+
const retention = projectObservationRetention(obs, {
|
|
143976
|
+
accessMap,
|
|
143977
|
+
referenceTime,
|
|
143978
|
+
...feedback ? { feedback: feedback.getState(obs.projectId, "observation", String(obs.id)) } : {}
|
|
143979
|
+
});
|
|
143456
143980
|
if (retention.zone === "archive-candidate") {
|
|
143457
143981
|
archivedIds.push(obs.id);
|
|
143458
143982
|
}
|
|
@@ -143472,6 +143996,7 @@ var init_retention = __esm({
|
|
|
143472
143996
|
init_esm_shims();
|
|
143473
143997
|
init_obs_store();
|
|
143474
143998
|
init_visibility();
|
|
143999
|
+
init_feedback_model();
|
|
143475
144000
|
RETENTION_DAYS = {
|
|
143476
144001
|
critical: 365,
|
|
143477
144002
|
high: 180,
|
|
@@ -143508,7 +144033,7 @@ var init_retention = __esm({
|
|
|
143508
144033
|
});
|
|
143509
144034
|
|
|
143510
144035
|
// src/memory/owner.ts
|
|
143511
|
-
import { randomUUID as
|
|
144036
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
143512
144037
|
import { promises as fs9 } from "fs";
|
|
143513
144038
|
import path16 from "path";
|
|
143514
144039
|
function ownerPath(dataDir) {
|
|
@@ -143538,7 +144063,7 @@ async function resolveLocalMemoryOwner(dataDir, options = {}) {
|
|
|
143538
144063
|
await fs9.mkdir(path16.dirname(filePath), { recursive: true });
|
|
143539
144064
|
const created = {
|
|
143540
144065
|
version: 1,
|
|
143541
|
-
id: "local-" +
|
|
144066
|
+
id: "local-" + randomUUID8(),
|
|
143542
144067
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
143543
144068
|
};
|
|
143544
144069
|
try {
|
|
@@ -143561,7 +144086,7 @@ var init_owner = __esm({
|
|
|
143561
144086
|
});
|
|
143562
144087
|
|
|
143563
144088
|
// src/memory/long-term-store.ts
|
|
143564
|
-
import { randomUUID as
|
|
144089
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
143565
144090
|
function optionalText2(value) {
|
|
143566
144091
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
143567
144092
|
}
|
|
@@ -143612,7 +144137,7 @@ function rowToEvidence(row) {
|
|
|
143612
144137
|
createdAt: row.createdAt
|
|
143613
144138
|
};
|
|
143614
144139
|
}
|
|
143615
|
-
function
|
|
144140
|
+
function rowToEvent2(row) {
|
|
143616
144141
|
return {
|
|
143617
144142
|
id: row.id,
|
|
143618
144143
|
memoryId: row.memoryId,
|
|
@@ -143721,7 +144246,7 @@ var init_long_term_store = __esm({
|
|
|
143721
144246
|
}
|
|
143722
144247
|
insertEvidence(input) {
|
|
143723
144248
|
const evidence = {
|
|
143724
|
-
id:
|
|
144249
|
+
id: randomUUID9(),
|
|
143725
144250
|
...input,
|
|
143726
144251
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
143727
144252
|
};
|
|
@@ -143748,7 +144273,7 @@ var init_long_term_store = __esm({
|
|
|
143748
144273
|
}
|
|
143749
144274
|
recordEvent(input) {
|
|
143750
144275
|
const event = {
|
|
143751
|
-
id:
|
|
144276
|
+
id: randomUUID9(),
|
|
143752
144277
|
...input,
|
|
143753
144278
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
143754
144279
|
};
|
|
@@ -143769,7 +144294,7 @@ var init_long_term_store = __esm({
|
|
|
143769
144294
|
listEvents(memoryId) {
|
|
143770
144295
|
return this.db.prepare(`
|
|
143771
144296
|
SELECT * FROM long_term_memory_events WHERE memoryId = ? ORDER BY createdAt ASC, rowid ASC
|
|
143772
|
-
`).all(memoryId).map(
|
|
144297
|
+
`).all(memoryId).map(rowToEvent2);
|
|
143773
144298
|
}
|
|
143774
144299
|
markAccess(ids, at = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
143775
144300
|
const unique = [...new Set(ids.filter(Boolean))];
|
|
@@ -143838,7 +144363,7 @@ __export(long_term_exports, {
|
|
|
143838
144363
|
selectLongTermMemoriesForTask: () => selectLongTermMemoriesForTask,
|
|
143839
144364
|
supersedeLongTermMemory: () => supersedeLongTermMemory
|
|
143840
144365
|
});
|
|
143841
|
-
import { randomUUID as
|
|
144366
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
143842
144367
|
function isOneOf(value, values) {
|
|
143843
144368
|
return typeof value === "string" && values.includes(value);
|
|
143844
144369
|
}
|
|
@@ -144020,7 +144545,7 @@ async function createManualLongTermMemory(input) {
|
|
|
144020
144545
|
const owner = await resolveLocalMemoryOwner(input.dataDir, { create: true });
|
|
144021
144546
|
if (!owner) throw new Error("Memorix could not resolve a local memory owner.");
|
|
144022
144547
|
assertScope(input.scope);
|
|
144023
|
-
const evidence = input.scope === "user" ? [{ kind: "user", referenceId: owner.id, relation: "user-confirmed" }] : [{ kind: "manual", referenceId: "manual:" +
|
|
144548
|
+
const evidence = input.scope === "user" ? [{ kind: "user", referenceId: owner.id, relation: "user-confirmed" }] : [{ kind: "manual", referenceId: "manual:" + randomUUID10(), relation: "supports" }];
|
|
144024
144549
|
return createLongTermMemoryWithDataDir({
|
|
144025
144550
|
dataDir: input.dataDir,
|
|
144026
144551
|
originProjectId: input.projectId,
|
|
@@ -144075,7 +144600,7 @@ async function createLongTermMemoryWithDataDir(input) {
|
|
|
144075
144600
|
assertPortableEvidence(input.scope, portability, evidenceInputs);
|
|
144076
144601
|
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
144077
144602
|
const memory = {
|
|
144078
|
-
id:
|
|
144603
|
+
id: randomUUID10(),
|
|
144079
144604
|
originProjectId: compactText(input.originProjectId, "origin project id", 1e3),
|
|
144080
144605
|
ownerId: compactText(input.ownerId, "owner id", 160),
|
|
144081
144606
|
scope: input.scope,
|
|
@@ -144393,9 +144918,9 @@ var init_long_term = __esm({
|
|
|
144393
144918
|
});
|
|
144394
144919
|
|
|
144395
144920
|
// src/codegraph/ids.ts
|
|
144396
|
-
import { createHash as
|
|
144921
|
+
import { createHash as createHash6 } from "crypto";
|
|
144397
144922
|
function digest(input) {
|
|
144398
|
-
return
|
|
144923
|
+
return createHash6("sha256").update(input).digest("hex").slice(0, 16);
|
|
144399
144924
|
}
|
|
144400
144925
|
function normalizeCodePath(path22) {
|
|
144401
144926
|
return path22.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/");
|
|
@@ -144430,7 +144955,7 @@ var store_exports = {};
|
|
|
144430
144955
|
__export(store_exports, {
|
|
144431
144956
|
CodeGraphStore: () => CodeGraphStore
|
|
144432
144957
|
});
|
|
144433
|
-
import { randomUUID as
|
|
144958
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
144434
144959
|
import { posix as pathPosix } from "path";
|
|
144435
144960
|
function rowToFile(row) {
|
|
144436
144961
|
return {
|
|
@@ -145147,7 +145672,7 @@ var init_store = __esm({
|
|
|
145147
145672
|
* so an interrupted scan cannot be advertised as complete.
|
|
145148
145673
|
*/
|
|
145149
145674
|
recordCodeStateSnapshot(input) {
|
|
145150
|
-
const id =
|
|
145675
|
+
const id = randomUUID11();
|
|
145151
145676
|
let snapshot;
|
|
145152
145677
|
const tx = this.db.transaction(() => {
|
|
145153
145678
|
const previous = this.db.prepare(
|
|
@@ -145225,7 +145750,7 @@ var init_store = __esm({
|
|
|
145225
145750
|
|
|
145226
145751
|
// src/codegraph/code-state.ts
|
|
145227
145752
|
import { execFile as execFile2 } from "child_process";
|
|
145228
|
-
import { createHash as
|
|
145753
|
+
import { createHash as createHash7 } from "crypto";
|
|
145229
145754
|
import { promisify as promisify3 } from "util";
|
|
145230
145755
|
async function runGit(rootPath, args) {
|
|
145231
145756
|
try {
|
|
@@ -145254,7 +145779,7 @@ function changedPathCount(status) {
|
|
|
145254
145779
|
return count2;
|
|
145255
145780
|
}
|
|
145256
145781
|
function fingerprint(baseRevision, status) {
|
|
145257
|
-
return
|
|
145782
|
+
return createHash7("sha256").update(baseRevision ?? "").update("\0").update(status).digest("hex");
|
|
145258
145783
|
}
|
|
145259
145784
|
async function collectCodeStateSnapshot(input) {
|
|
145260
145785
|
const [revision, status] = await Promise.all([
|
|
@@ -145354,11 +145879,11 @@ __export(lite_provider_exports, {
|
|
|
145354
145879
|
indexProjectLite: () => indexProjectLite,
|
|
145355
145880
|
refreshProjectLite: () => refreshProjectLite
|
|
145356
145881
|
});
|
|
145357
|
-
import { createHash as
|
|
145882
|
+
import { createHash as createHash8 } from "crypto";
|
|
145358
145883
|
import { readdirSync as readdirSync2, readFileSync as readFileSync7, statSync as statSync3 } from "fs";
|
|
145359
145884
|
import { join as join4, relative } from "path";
|
|
145360
145885
|
function hashText(text2) {
|
|
145361
|
-
return
|
|
145886
|
+
return createHash8("sha256").update(text2).digest("hex");
|
|
145362
145887
|
}
|
|
145363
145888
|
function extension2(path22) {
|
|
145364
145889
|
const index = path22.lastIndexOf(".");
|
|
@@ -145925,7 +146450,7 @@ var claim_store_exports = {};
|
|
|
145925
146450
|
__export(claim_store_exports, {
|
|
145926
146451
|
ClaimStore: () => ClaimStore
|
|
145927
146452
|
});
|
|
145928
|
-
import { createHash as
|
|
146453
|
+
import { createHash as createHash9, randomUUID as randomUUID12 } from "crypto";
|
|
145929
146454
|
function optionalText3(value) {
|
|
145930
146455
|
return typeof value === "string" && value ? value : void 0;
|
|
145931
146456
|
}
|
|
@@ -145964,7 +146489,7 @@ function rowToEvidence2(row) {
|
|
|
145964
146489
|
createdAt: row.createdAt
|
|
145965
146490
|
};
|
|
145966
146491
|
}
|
|
145967
|
-
function
|
|
146492
|
+
function rowToEvent3(row) {
|
|
145968
146493
|
return {
|
|
145969
146494
|
id: row.id,
|
|
145970
146495
|
projectId: row.projectId,
|
|
@@ -145978,7 +146503,7 @@ function rowToEvent2(row) {
|
|
|
145978
146503
|
};
|
|
145979
146504
|
}
|
|
145980
146505
|
function evidenceKey(input) {
|
|
145981
|
-
return
|
|
146506
|
+
return createHash9("sha256").update(JSON.stringify([
|
|
145982
146507
|
input.evidenceKind,
|
|
145983
146508
|
input.evidenceId,
|
|
145984
146509
|
input.relation,
|
|
@@ -146109,7 +146634,7 @@ var init_claim_store = __esm({
|
|
|
146109
146634
|
locator, capturedHash, evidenceKey, createdAt
|
|
146110
146635
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
146111
146636
|
`).run(
|
|
146112
|
-
|
|
146637
|
+
randomUUID12(),
|
|
146113
146638
|
input.claimId,
|
|
146114
146639
|
input.evidenceKind,
|
|
146115
146640
|
input.evidenceId,
|
|
@@ -146131,7 +146656,7 @@ var init_claim_store = __esm({
|
|
|
146131
146656
|
}
|
|
146132
146657
|
recordEvent(input) {
|
|
146133
146658
|
const event = {
|
|
146134
|
-
id:
|
|
146659
|
+
id: randomUUID12(),
|
|
146135
146660
|
...input,
|
|
146136
146661
|
...input.detail ? { detail: sanitizeCredentials(input.detail) } : {},
|
|
146137
146662
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -146159,7 +146684,7 @@ var init_claim_store = __esm({
|
|
|
146159
146684
|
SELECT * FROM knowledge_claim_events
|
|
146160
146685
|
WHERE claimId = ?
|
|
146161
146686
|
ORDER BY createdAt ASC, id
|
|
146162
|
-
`).all(claimId).map(
|
|
146687
|
+
`).all(claimId).map(rowToEvent3);
|
|
146163
146688
|
}
|
|
146164
146689
|
};
|
|
146165
146690
|
}
|
|
@@ -146176,7 +146701,7 @@ __export(claims_exports, {
|
|
|
146176
146701
|
supersedeClaim: () => supersedeClaim,
|
|
146177
146702
|
writeClaim: () => writeClaim
|
|
146178
146703
|
});
|
|
146179
|
-
import { createHash as
|
|
146704
|
+
import { createHash as createHash10, randomUUID as randomUUID13 } from "crypto";
|
|
146180
146705
|
function compactText2(value, field) {
|
|
146181
146706
|
if (typeof value !== "string") throw new Error("Claim " + field + " must be text");
|
|
146182
146707
|
const sanitized = sanitizeCredentials(value).trim().replace(/\s+/g, " ");
|
|
@@ -146188,7 +146713,7 @@ function normalizedTerm(value) {
|
|
|
146188
146713
|
return compactText2(value, "identity").toLocaleLowerCase("en-US");
|
|
146189
146714
|
}
|
|
146190
146715
|
function hashIdentity(parts) {
|
|
146191
|
-
return
|
|
146716
|
+
return createHash10("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
|
|
146192
146717
|
}
|
|
146193
146718
|
function buildClaimIdentity(input) {
|
|
146194
146719
|
const subject = normalizedTerm(input.subject);
|
|
@@ -146262,7 +146787,7 @@ function normalizeClaimInput(input) {
|
|
|
146262
146787
|
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
146263
146788
|
return {
|
|
146264
146789
|
claim: {
|
|
146265
|
-
id:
|
|
146790
|
+
id: randomUUID13(),
|
|
146266
146791
|
projectId,
|
|
146267
146792
|
subject,
|
|
146268
146793
|
predicate,
|
|
@@ -146429,7 +146954,7 @@ function supersedeClaim(store, input) {
|
|
|
146429
146954
|
});
|
|
146430
146955
|
}
|
|
146431
146956
|
function hashObservation(observation) {
|
|
146432
|
-
return
|
|
146957
|
+
return createHash10("sha256").update(JSON.stringify([
|
|
146433
146958
|
observation.title,
|
|
146434
146959
|
observation.narrative,
|
|
146435
146960
|
observation.facts,
|
|
@@ -146673,11 +147198,11 @@ var init_frontmatter = __esm({
|
|
|
146673
147198
|
});
|
|
146674
147199
|
|
|
146675
147200
|
// src/knowledge/markdown.ts
|
|
146676
|
-
import { createHash as
|
|
147201
|
+
import { createHash as createHash11 } from "crypto";
|
|
146677
147202
|
import { promises as fs10 } from "fs";
|
|
146678
147203
|
import path17 from "path";
|
|
146679
147204
|
function hashContent(content) {
|
|
146680
|
-
return
|
|
147205
|
+
return createHash11("sha256").update(content).digest("hex");
|
|
146681
147206
|
}
|
|
146682
147207
|
function stringField(data, key) {
|
|
146683
147208
|
const value = data[key];
|
|
@@ -146803,11 +147328,11 @@ __export(wiki_exports, {
|
|
|
146803
147328
|
lintKnowledgeWorkspace: () => lintKnowledgeWorkspace,
|
|
146804
147329
|
readKnowledgePage: () => readKnowledgePage
|
|
146805
147330
|
});
|
|
146806
|
-
import { createHash as
|
|
147331
|
+
import { createHash as createHash12 } from "crypto";
|
|
146807
147332
|
import { promises as fs11 } from "fs";
|
|
146808
147333
|
import path18 from "path";
|
|
146809
147334
|
function hash2(value) {
|
|
146810
|
-
return
|
|
147335
|
+
return createHash12("sha256").update(value).digest("hex");
|
|
146811
147336
|
}
|
|
146812
147337
|
function now() {
|
|
146813
147338
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -147347,7 +147872,7 @@ var init_workflow_sync = __esm({
|
|
|
147347
147872
|
});
|
|
147348
147873
|
|
|
147349
147874
|
// src/knowledge/workflow-store.ts
|
|
147350
|
-
import { randomUUID as
|
|
147875
|
+
import { randomUUID as randomUUID14 } from "crypto";
|
|
147351
147876
|
function parseJson(value, fallback) {
|
|
147352
147877
|
if (typeof value !== "string" || !value) return fallback;
|
|
147353
147878
|
try {
|
|
@@ -147447,7 +147972,7 @@ var init_workflow_store = __esm({
|
|
|
147447
147972
|
}
|
|
147448
147973
|
recordRun(input) {
|
|
147449
147974
|
const run = {
|
|
147450
|
-
id:
|
|
147975
|
+
id: randomUUID14(),
|
|
147451
147976
|
workflowId: input.workflowId,
|
|
147452
147977
|
projectId: input.projectId,
|
|
147453
147978
|
task: input.task.trim(),
|
|
@@ -147515,7 +148040,7 @@ var init_outcome_types = __esm({
|
|
|
147515
148040
|
});
|
|
147516
148041
|
|
|
147517
148042
|
// src/knowledge/outcome-store.ts
|
|
147518
|
-
import { randomUUID as
|
|
148043
|
+
import { randomUUID as randomUUID15 } from "crypto";
|
|
147519
148044
|
function optionalText5(value) {
|
|
147520
148045
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
147521
148046
|
}
|
|
@@ -147559,7 +148084,7 @@ var init_outcome_store = __esm({
|
|
|
147559
148084
|
}
|
|
147560
148085
|
record(input) {
|
|
147561
148086
|
const signal = {
|
|
147562
|
-
id:
|
|
148087
|
+
id: randomUUID15(),
|
|
147563
148088
|
projectId: text(input.projectId, "project id"),
|
|
147564
148089
|
candidateKind: oneOf(input.candidateKind, MEMORY_OUTCOME_CANDIDATE_KINDS, "candidate kind"),
|
|
147565
148090
|
candidateId: text(input.candidateId, "candidate id"),
|
|
@@ -147664,11 +148189,11 @@ __export(workflows_exports, {
|
|
|
147664
148189
|
syncCanonicalWorkflows: () => syncCanonicalWorkflows,
|
|
147665
148190
|
writeCanonicalWorkflow: () => writeCanonicalWorkflow
|
|
147666
148191
|
});
|
|
147667
|
-
import { createHash as
|
|
148192
|
+
import { createHash as createHash13 } from "crypto";
|
|
147668
148193
|
import { promises as fs12 } from "fs";
|
|
147669
148194
|
import path19 from "path";
|
|
147670
148195
|
function hash3(value) {
|
|
147671
|
-
return
|
|
148196
|
+
return createHash13("sha256").update(value).digest("hex");
|
|
147672
148197
|
}
|
|
147673
148198
|
function now2() {
|
|
147674
148199
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -149050,6 +149575,16 @@ async function bindObservationCodeRefsBestEffort(observation) {
|
|
|
149050
149575
|
} catch {
|
|
149051
149576
|
}
|
|
149052
149577
|
}
|
|
149578
|
+
async function persistEvidenceCard(observation) {
|
|
149579
|
+
if (!projectDir) return;
|
|
149580
|
+
try {
|
|
149581
|
+
const evidence = new EvidenceCardStore();
|
|
149582
|
+
await evidence.init(projectDir);
|
|
149583
|
+
evidence.upsertObservation(observation);
|
|
149584
|
+
} catch (error) {
|
|
149585
|
+
console.error(`[memorix] Evidence card projection failed for obs-${observation.id}: ${error instanceof Error ? error.message : String(error)}`);
|
|
149586
|
+
}
|
|
149587
|
+
}
|
|
149053
149588
|
function queueClaimDerivation(observation) {
|
|
149054
149589
|
const dataDir = projectDir;
|
|
149055
149590
|
const isExplicit = observation.sourceDetail === "explicit";
|
|
@@ -149396,6 +149931,7 @@ async function storeObservation(input) {
|
|
|
149396
149931
|
}
|
|
149397
149932
|
if (!persistedCallbackInvoked) await input.onPersisted?.(observation);
|
|
149398
149933
|
await bindObservationCodeRefsBestEffort(observation);
|
|
149934
|
+
await persistEvidenceCard(observation);
|
|
149399
149935
|
queueObservationQualification(observation);
|
|
149400
149936
|
if (resolveObservationVisibility(observation) === "project") {
|
|
149401
149937
|
queueClaimDerivation(observation);
|
|
@@ -149488,6 +150024,7 @@ async function upsertObservation(existing, input, now3) {
|
|
|
149488
150024
|
await store.update(existing);
|
|
149489
150025
|
}
|
|
149490
150026
|
await bindObservationCodeRefsBestEffort(existing);
|
|
150027
|
+
await persistEvidenceCard(existing);
|
|
149491
150028
|
queueObservationQualification(existing);
|
|
149492
150029
|
if (resolveObservationVisibility(existing) === "project") {
|
|
149493
150030
|
queueClaimDerivation(existing);
|
|
@@ -149621,6 +150158,7 @@ async function resolveObservations(ids, status = "resolved") {
|
|
|
149621
150158
|
await Promise.all(changed.map((observation) => tx.update(observation)));
|
|
149622
150159
|
});
|
|
149623
150160
|
}
|
|
150161
|
+
for (const observation of changed) await persistEvidenceCard(observation);
|
|
149624
150162
|
return { resolved, notFound };
|
|
149625
150163
|
}
|
|
149626
150164
|
function getProjectObservations(projectId) {
|
|
@@ -149958,6 +150496,7 @@ var init_observations = __esm({
|
|
|
149958
150496
|
init_secret_filter();
|
|
149959
150497
|
init_lifecycle();
|
|
149960
150498
|
init_visibility();
|
|
150499
|
+
init_evidence_store();
|
|
149961
150500
|
observations = [];
|
|
149962
150501
|
nextId = 1;
|
|
149963
150502
|
projectDir = null;
|