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
package/dist/sdk.js
CHANGED
|
@@ -437,7 +437,7 @@ function isSqliteAvailable() {
|
|
|
437
437
|
return false;
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
|
-
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;
|
|
440
|
+
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;
|
|
441
441
|
var init_sqlite_db = __esm({
|
|
442
442
|
"src/store/sqlite-db.ts"() {
|
|
443
443
|
"use strict";
|
|
@@ -1083,6 +1083,79 @@ CREATE TABLE IF NOT EXISTS compaction_checkpoints (
|
|
|
1083
1083
|
created_at TEXT NOT NULL,
|
|
1084
1084
|
updated_at TEXT NOT NULL
|
|
1085
1085
|
);
|
|
1086
|
+
`;
|
|
1087
|
+
CREATE_EVIDENCE_CARDS_TABLE = `
|
|
1088
|
+
CREATE TABLE IF NOT EXISTS evidence_cards (
|
|
1089
|
+
id TEXT PRIMARY KEY,
|
|
1090
|
+
project_id TEXT NOT NULL,
|
|
1091
|
+
candidate_kind TEXT NOT NULL,
|
|
1092
|
+
candidate_id TEXT NOT NULL,
|
|
1093
|
+
title TEXT NOT NULL,
|
|
1094
|
+
summary TEXT NOT NULL DEFAULT '',
|
|
1095
|
+
entity_name TEXT,
|
|
1096
|
+
source_kind TEXT NOT NULL,
|
|
1097
|
+
source_ref TEXT NOT NULL,
|
|
1098
|
+
locator TEXT,
|
|
1099
|
+
captured_hash TEXT,
|
|
1100
|
+
session_id TEXT,
|
|
1101
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
1102
|
+
verification TEXT NOT NULL DEFAULT 'unverified',
|
|
1103
|
+
freshness TEXT NOT NULL DEFAULT 'current',
|
|
1104
|
+
stale_reason TEXT,
|
|
1105
|
+
files_json TEXT NOT NULL DEFAULT '[]',
|
|
1106
|
+
related_entities_json TEXT NOT NULL DEFAULT '[]',
|
|
1107
|
+
created_at TEXT NOT NULL,
|
|
1108
|
+
updated_at TEXT NOT NULL,
|
|
1109
|
+
UNIQUE(project_id, candidate_kind, candidate_id)
|
|
1110
|
+
);
|
|
1111
|
+
`;
|
|
1112
|
+
CREATE_EVIDENCE_CARD_EVENTS_TABLE = `
|
|
1113
|
+
CREATE TABLE IF NOT EXISTS evidence_card_events (
|
|
1114
|
+
id TEXT PRIMARY KEY,
|
|
1115
|
+
project_id TEXT NOT NULL,
|
|
1116
|
+
card_id TEXT NOT NULL,
|
|
1117
|
+
kind TEXT NOT NULL,
|
|
1118
|
+
detail TEXT,
|
|
1119
|
+
created_at TEXT NOT NULL,
|
|
1120
|
+
FOREIGN KEY (card_id) REFERENCES evidence_cards(id) ON DELETE CASCADE
|
|
1121
|
+
);
|
|
1122
|
+
`;
|
|
1123
|
+
CREATE_MEMORY_FEEDBACK_STATES_TABLE = `
|
|
1124
|
+
CREATE TABLE IF NOT EXISTS memory_feedback_states (
|
|
1125
|
+
project_id TEXT NOT NULL,
|
|
1126
|
+
candidate_kind TEXT NOT NULL,
|
|
1127
|
+
candidate_id TEXT NOT NULL,
|
|
1128
|
+
weight REAL NOT NULL DEFAULT 1.0,
|
|
1129
|
+
lifecycle_status TEXT NOT NULL DEFAULT 'active',
|
|
1130
|
+
updated_at TEXT NOT NULL,
|
|
1131
|
+
PRIMARY KEY (project_id, candidate_kind, candidate_id)
|
|
1132
|
+
);
|
|
1133
|
+
`;
|
|
1134
|
+
CREATE_MEMORY_FEEDBACK_EVENTS_TABLE = `
|
|
1135
|
+
CREATE TABLE IF NOT EXISTS memory_feedback_events (
|
|
1136
|
+
id TEXT PRIMARY KEY,
|
|
1137
|
+
project_id TEXT NOT NULL,
|
|
1138
|
+
candidate_kind TEXT NOT NULL,
|
|
1139
|
+
candidate_id TEXT NOT NULL,
|
|
1140
|
+
signal TEXT NOT NULL,
|
|
1141
|
+
actor TEXT,
|
|
1142
|
+
note TEXT,
|
|
1143
|
+
source_ref TEXT NOT NULL,
|
|
1144
|
+
target_event_id TEXT,
|
|
1145
|
+
delta REAL NOT NULL DEFAULT 0,
|
|
1146
|
+
observed_at TEXT NOT NULL
|
|
1147
|
+
);
|
|
1148
|
+
`;
|
|
1149
|
+
CREATE_MCP_BINDINGS_TABLE = `
|
|
1150
|
+
CREATE TABLE IF NOT EXISTS mcp_bindings (
|
|
1151
|
+
handle_id TEXT PRIMARY KEY,
|
|
1152
|
+
project_id TEXT NOT NULL,
|
|
1153
|
+
project_root TEXT NOT NULL,
|
|
1154
|
+
data_dir TEXT NOT NULL,
|
|
1155
|
+
created_at TEXT NOT NULL,
|
|
1156
|
+
last_used_at TEXT NOT NULL,
|
|
1157
|
+
expires_at TEXT
|
|
1158
|
+
);
|
|
1086
1159
|
`;
|
|
1087
1160
|
CREATE_INDEXES = `
|
|
1088
1161
|
CREATE INDEX IF NOT EXISTS idx_observations_projectId ON observations(projectId);
|
|
@@ -1145,6 +1218,12 @@ CREATE INDEX IF NOT EXISTS idx_maintenance_targets_updated ON maintenance_target
|
|
|
1145
1218
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_project_recent ON compaction_checkpoints(project_id, status, completed_at DESC, pre_captured_at DESC);
|
|
1146
1219
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_session_pending ON compaction_checkpoints(project_id, session_id, agent, phase, status, pre_captured_at DESC);
|
|
1147
1220
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_source ON compaction_checkpoints(project_id, source_key);
|
|
1221
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_cards_project ON evidence_cards(project_id, status, updated_at DESC);
|
|
1222
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(project_id, candidate_kind, candidate_id);
|
|
1223
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at);
|
|
1224
|
+
CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC);
|
|
1225
|
+
CREATE INDEX IF NOT EXISTS idx_memory_feedback_events_candidate ON memory_feedback_events(project_id, candidate_kind, candidate_id, observed_at DESC);
|
|
1226
|
+
CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC);
|
|
1148
1227
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
1149
1228
|
ON maintenance_jobs(project_id, kind, dedupe_key)
|
|
1150
1229
|
WHERE status IN ('pending', 'running', 'retry');
|
|
@@ -1300,6 +1379,22 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
|
1300
1379
|
}
|
|
1301
1380
|
db2.exec("CREATE INDEX IF NOT EXISTS idx_media_jobs_source_asset ON media_jobs(project_id, source_asset_id, status)");
|
|
1302
1381
|
}
|
|
1382
|
+
},
|
|
1383
|
+
{
|
|
1384
|
+
id: "1.8-context-control-plane",
|
|
1385
|
+
apply: (db2) => {
|
|
1386
|
+
db2.exec(CREATE_EVIDENCE_CARDS_TABLE);
|
|
1387
|
+
db2.exec(CREATE_EVIDENCE_CARD_EVENTS_TABLE);
|
|
1388
|
+
db2.exec(CREATE_MEMORY_FEEDBACK_STATES_TABLE);
|
|
1389
|
+
db2.exec(CREATE_MEMORY_FEEDBACK_EVENTS_TABLE);
|
|
1390
|
+
db2.exec(CREATE_MCP_BINDINGS_TABLE);
|
|
1391
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_cards_project ON evidence_cards(project_id, status, updated_at DESC)");
|
|
1392
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(project_id, candidate_kind, candidate_id)");
|
|
1393
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at)");
|
|
1394
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC)");
|
|
1395
|
+
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)");
|
|
1396
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC)");
|
|
1397
|
+
}
|
|
1303
1398
|
}
|
|
1304
1399
|
];
|
|
1305
1400
|
_dbCache = /* @__PURE__ */ new Map();
|
|
@@ -3150,6 +3245,8 @@ var init_toml_loader = __esm({
|
|
|
3150
3245
|
var dotenv_loader_exports = {};
|
|
3151
3246
|
__export(dotenv_loader_exports, {
|
|
3152
3247
|
getLoadedEnvFiles: () => getLoadedEnvFiles,
|
|
3248
|
+
getLoadedEnvKeys: () => getLoadedEnvKeys,
|
|
3249
|
+
getLoadedEnvValue: () => getLoadedEnvValue,
|
|
3153
3250
|
loadDotenv: () => loadDotenv,
|
|
3154
3251
|
resetDotenv: () => resetDotenv
|
|
3155
3252
|
});
|
|
@@ -3161,6 +3258,8 @@ function loadEnvFile(filePath) {
|
|
|
3161
3258
|
const parsed = parse(readFileSync6(filePath, "utf-8"));
|
|
3162
3259
|
for (const [key, value] of Object.entries(parsed)) {
|
|
3163
3260
|
if (!(key in process.env)) {
|
|
3261
|
+
loadedEnvKeys.add(key);
|
|
3262
|
+
loadedEnvValues.set(key, value);
|
|
3164
3263
|
process.env[key] = value;
|
|
3165
3264
|
injectedKeys.add(key);
|
|
3166
3265
|
}
|
|
@@ -3173,6 +3272,8 @@ function loadDotenv(projectRoot, options = {}) {
|
|
|
3173
3272
|
resetDotenv();
|
|
3174
3273
|
}
|
|
3175
3274
|
loadedEnvFiles.length = 0;
|
|
3275
|
+
loadedEnvKeys.clear();
|
|
3276
|
+
loadedEnvValues.clear();
|
|
3176
3277
|
if (projectRoot) {
|
|
3177
3278
|
loadEnvFile(getProjectDotenvPath(projectRoot));
|
|
3178
3279
|
}
|
|
@@ -3188,11 +3289,18 @@ function resetDotenv() {
|
|
|
3188
3289
|
dotenvLoaded = false;
|
|
3189
3290
|
dotenvProjectRoot = null;
|
|
3190
3291
|
loadedEnvFiles.length = 0;
|
|
3292
|
+
loadedEnvKeys.clear();
|
|
3191
3293
|
}
|
|
3192
3294
|
function getLoadedEnvFiles() {
|
|
3193
3295
|
return loadedEnvFiles;
|
|
3194
3296
|
}
|
|
3195
|
-
|
|
3297
|
+
function getLoadedEnvKeys() {
|
|
3298
|
+
return loadedEnvKeys;
|
|
3299
|
+
}
|
|
3300
|
+
function getLoadedEnvValue(key) {
|
|
3301
|
+
return loadedEnvValues.get(key);
|
|
3302
|
+
}
|
|
3303
|
+
var dotenvLoaded, dotenvProjectRoot, loadedEnvFiles, loadedEnvKeys, loadedEnvValues, injectedKeys;
|
|
3196
3304
|
var init_dotenv_loader = __esm({
|
|
3197
3305
|
"src/config/dotenv-loader.ts"() {
|
|
3198
3306
|
"use strict";
|
|
@@ -3201,6 +3309,8 @@ var init_dotenv_loader = __esm({
|
|
|
3201
3309
|
dotenvLoaded = false;
|
|
3202
3310
|
dotenvProjectRoot = null;
|
|
3203
3311
|
loadedEnvFiles = [];
|
|
3312
|
+
loadedEnvKeys = /* @__PURE__ */ new Set();
|
|
3313
|
+
loadedEnvValues = /* @__PURE__ */ new Map();
|
|
3204
3314
|
injectedKeys = /* @__PURE__ */ new Set();
|
|
3205
3315
|
}
|
|
3206
3316
|
});
|
|
@@ -9291,6 +9401,226 @@ var init_lifecycle = __esm({
|
|
|
9291
9401
|
}
|
|
9292
9402
|
});
|
|
9293
9403
|
|
|
9404
|
+
// src/store/evidence-store.ts
|
|
9405
|
+
import { createHash as createHash3, randomUUID as randomUUID3 } from "crypto";
|
|
9406
|
+
function safeJson(value, fallback) {
|
|
9407
|
+
if (typeof value !== "string" || value.length === 0) return fallback;
|
|
9408
|
+
try {
|
|
9409
|
+
return JSON.parse(value);
|
|
9410
|
+
} catch {
|
|
9411
|
+
return fallback;
|
|
9412
|
+
}
|
|
9413
|
+
}
|
|
9414
|
+
function rowToCard(row) {
|
|
9415
|
+
return {
|
|
9416
|
+
id: String(row.id),
|
|
9417
|
+
projectId: String(row.project_id),
|
|
9418
|
+
candidateKind: row.candidate_kind,
|
|
9419
|
+
candidateId: String(row.candidate_id),
|
|
9420
|
+
title: String(row.title),
|
|
9421
|
+
summary: String(row.summary ?? ""),
|
|
9422
|
+
...row.entity_name ? { entityName: String(row.entity_name) } : {},
|
|
9423
|
+
sourceKind: String(row.source_kind),
|
|
9424
|
+
sourceRef: String(row.source_ref),
|
|
9425
|
+
...row.locator ? { locator: String(row.locator) } : {},
|
|
9426
|
+
...row.captured_hash ? { capturedHash: String(row.captured_hash) } : {},
|
|
9427
|
+
...row.session_id ? { sessionId: String(row.session_id) } : {},
|
|
9428
|
+
status: String(row.status ?? "active"),
|
|
9429
|
+
verification: row.verification,
|
|
9430
|
+
freshness: row.freshness,
|
|
9431
|
+
...row.stale_reason ? { staleReason: String(row.stale_reason) } : {},
|
|
9432
|
+
files: safeJson(row.files_json, []),
|
|
9433
|
+
relatedEntities: safeJson(row.related_entities_json, []),
|
|
9434
|
+
createdAt: String(row.created_at),
|
|
9435
|
+
updatedAt: String(row.updated_at)
|
|
9436
|
+
};
|
|
9437
|
+
}
|
|
9438
|
+
function observationHash(observation) {
|
|
9439
|
+
return createHash3("sha256").update(JSON.stringify({
|
|
9440
|
+
projectId: observation.projectId,
|
|
9441
|
+
id: observation.id,
|
|
9442
|
+
title: observation.title,
|
|
9443
|
+
narrative: observation.narrative,
|
|
9444
|
+
facts: observation.facts,
|
|
9445
|
+
files: observation.filesModified,
|
|
9446
|
+
relatedEntities: observation.relatedEntities
|
|
9447
|
+
})).digest("hex");
|
|
9448
|
+
}
|
|
9449
|
+
function sourceKind(observation) {
|
|
9450
|
+
if (observation.source === "git" || observation.sourceDetail === "git-ingest") return "git";
|
|
9451
|
+
if (observation.sourceDetail === "hook") return "hook";
|
|
9452
|
+
return observation.source ?? "agent";
|
|
9453
|
+
}
|
|
9454
|
+
var EvidenceCardStore;
|
|
9455
|
+
var init_evidence_store = __esm({
|
|
9456
|
+
"src/store/evidence-store.ts"() {
|
|
9457
|
+
"use strict";
|
|
9458
|
+
init_esm_shims();
|
|
9459
|
+
init_sqlite_db();
|
|
9460
|
+
EvidenceCardStore = class {
|
|
9461
|
+
db = null;
|
|
9462
|
+
async init(dataDir) {
|
|
9463
|
+
this.db = getDatabase(dataDir);
|
|
9464
|
+
}
|
|
9465
|
+
requireDb() {
|
|
9466
|
+
if (!this.db) throw new Error("EvidenceCardStore is not initialized.");
|
|
9467
|
+
return this.db;
|
|
9468
|
+
}
|
|
9469
|
+
upsertObservation(observation) {
|
|
9470
|
+
const db2 = this.requireDb();
|
|
9471
|
+
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
9472
|
+
const card = {
|
|
9473
|
+
id: `evidence:observation:${observation.projectId}:${observation.id}`,
|
|
9474
|
+
projectId: observation.projectId,
|
|
9475
|
+
candidateKind: "observation",
|
|
9476
|
+
candidateId: String(observation.id),
|
|
9477
|
+
title: observation.title,
|
|
9478
|
+
summary: observation.narrative.slice(0, 500),
|
|
9479
|
+
entityName: observation.entityName,
|
|
9480
|
+
sourceKind: sourceKind(observation),
|
|
9481
|
+
sourceRef: `observation:${observation.id}`,
|
|
9482
|
+
locator: observation.filesModified?.join(", ") || `observation:${observation.id}`,
|
|
9483
|
+
capturedHash: observationHash(observation),
|
|
9484
|
+
...observation.sessionId ? { sessionId: observation.sessionId } : {},
|
|
9485
|
+
status: observation.status ?? "active",
|
|
9486
|
+
verification: observation.status === "resolved" ? "verified" : "unverified",
|
|
9487
|
+
freshness: "current",
|
|
9488
|
+
files: observation.filesModified ?? [],
|
|
9489
|
+
relatedEntities: observation.relatedEntities ?? [],
|
|
9490
|
+
createdAt: observation.createdAt,
|
|
9491
|
+
updatedAt: now3
|
|
9492
|
+
};
|
|
9493
|
+
db2.prepare(`
|
|
9494
|
+
INSERT INTO evidence_cards (
|
|
9495
|
+
id, project_id, candidate_kind, candidate_id, title, summary, entity_name,
|
|
9496
|
+
source_kind, source_ref, locator, captured_hash, session_id, status,
|
|
9497
|
+
verification, freshness, stale_reason, files_json, related_entities_json,
|
|
9498
|
+
created_at, updated_at
|
|
9499
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?)
|
|
9500
|
+
ON CONFLICT(project_id, candidate_kind, candidate_id) DO UPDATE SET
|
|
9501
|
+
title = excluded.title,
|
|
9502
|
+
summary = excluded.summary,
|
|
9503
|
+
entity_name = excluded.entity_name,
|
|
9504
|
+
source_kind = excluded.source_kind,
|
|
9505
|
+
source_ref = excluded.source_ref,
|
|
9506
|
+
locator = excluded.locator,
|
|
9507
|
+
captured_hash = excluded.captured_hash,
|
|
9508
|
+
session_id = excluded.session_id,
|
|
9509
|
+
status = excluded.status,
|
|
9510
|
+
freshness = 'current',
|
|
9511
|
+
stale_reason = NULL,
|
|
9512
|
+
files_json = excluded.files_json,
|
|
9513
|
+
related_entities_json = excluded.related_entities_json,
|
|
9514
|
+
updated_at = excluded.updated_at
|
|
9515
|
+
`).run(
|
|
9516
|
+
card.id,
|
|
9517
|
+
card.projectId,
|
|
9518
|
+
card.candidateKind,
|
|
9519
|
+
card.candidateId,
|
|
9520
|
+
card.title,
|
|
9521
|
+
card.summary,
|
|
9522
|
+
card.entityName ?? null,
|
|
9523
|
+
card.sourceKind,
|
|
9524
|
+
card.sourceRef,
|
|
9525
|
+
card.locator ?? null,
|
|
9526
|
+
card.capturedHash ?? null,
|
|
9527
|
+
card.sessionId ?? null,
|
|
9528
|
+
card.status,
|
|
9529
|
+
card.verification,
|
|
9530
|
+
card.freshness,
|
|
9531
|
+
JSON.stringify(card.files),
|
|
9532
|
+
JSON.stringify(card.relatedEntities),
|
|
9533
|
+
card.createdAt,
|
|
9534
|
+
card.updatedAt
|
|
9535
|
+
);
|
|
9536
|
+
return this.get(card.projectId, card.candidateKind, card.candidateId) ?? card;
|
|
9537
|
+
}
|
|
9538
|
+
get(projectId, candidateKind, candidateId) {
|
|
9539
|
+
const row = this.requireDb().prepare(`
|
|
9540
|
+
SELECT * FROM evidence_cards WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
9541
|
+
`).get(projectId, candidateKind, candidateId);
|
|
9542
|
+
return row ? rowToCard(row) : void 0;
|
|
9543
|
+
}
|
|
9544
|
+
list(projectId, options = {}) {
|
|
9545
|
+
const limit2 = Math.min(100, Math.max(1, Math.floor(options.limit ?? 20)));
|
|
9546
|
+
const clauses = ["project_id = ?"];
|
|
9547
|
+
const args = [projectId];
|
|
9548
|
+
if (options.freshness) {
|
|
9549
|
+
clauses.push("freshness = ?");
|
|
9550
|
+
args.push(options.freshness);
|
|
9551
|
+
}
|
|
9552
|
+
if (options.status) {
|
|
9553
|
+
clauses.push("status = ?");
|
|
9554
|
+
args.push(options.status);
|
|
9555
|
+
}
|
|
9556
|
+
args.push(limit2);
|
|
9557
|
+
const rows = this.requireDb().prepare(`
|
|
9558
|
+
SELECT * FROM evidence_cards WHERE ${clauses.join(" AND ")} ORDER BY updated_at DESC, id DESC LIMIT ?
|
|
9559
|
+
`).all(...args);
|
|
9560
|
+
return rows.map(rowToCard);
|
|
9561
|
+
}
|
|
9562
|
+
syncObservations(observations2) {
|
|
9563
|
+
return observations2.map((observation) => this.upsertObservation(observation));
|
|
9564
|
+
}
|
|
9565
|
+
markStaleForPaths(projectId, paths, reason = "source file changed") {
|
|
9566
|
+
const normalized = new Set(paths.map((value) => value.replace(/\\/g, "/").toLowerCase()));
|
|
9567
|
+
if (normalized.size === 0) return 0;
|
|
9568
|
+
const db2 = this.requireDb();
|
|
9569
|
+
const rows = db2.prepare(`SELECT * FROM evidence_cards WHERE project_id = ? AND freshness != 'stale'`).all(projectId);
|
|
9570
|
+
const update2 = db2.prepare(`
|
|
9571
|
+
UPDATE evidence_cards SET freshness = 'stale', stale_reason = ?, updated_at = ?
|
|
9572
|
+
WHERE id = ?
|
|
9573
|
+
`);
|
|
9574
|
+
let changed = 0;
|
|
9575
|
+
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
9576
|
+
const run = db2.transaction(() => {
|
|
9577
|
+
for (const row of rows) {
|
|
9578
|
+
const files = safeJson(row.files_json, []);
|
|
9579
|
+
if (!files.some((file) => normalized.has(file.replace(/\\/g, "/").toLowerCase()))) continue;
|
|
9580
|
+
update2.run(reason, now3, row.id);
|
|
9581
|
+
changed++;
|
|
9582
|
+
}
|
|
9583
|
+
});
|
|
9584
|
+
run();
|
|
9585
|
+
return changed;
|
|
9586
|
+
}
|
|
9587
|
+
setVerification(projectId, cardId, verification) {
|
|
9588
|
+
this.requireDb().prepare(`
|
|
9589
|
+
UPDATE evidence_cards SET verification = ?, updated_at = ? WHERE project_id = ? AND id = ?
|
|
9590
|
+
`).run(verification, (/* @__PURE__ */ new Date()).toISOString(), projectId, cardId);
|
|
9591
|
+
}
|
|
9592
|
+
recordEvent(projectId, cardId, kind, detail) {
|
|
9593
|
+
const event = {
|
|
9594
|
+
id: randomUUID3(),
|
|
9595
|
+
projectId,
|
|
9596
|
+
cardId,
|
|
9597
|
+
kind,
|
|
9598
|
+
...detail ? { detail: detail.slice(0, 2e3) } : {},
|
|
9599
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
9600
|
+
};
|
|
9601
|
+
this.requireDb().prepare(`
|
|
9602
|
+
INSERT INTO evidence_card_events (id, project_id, card_id, kind, detail, created_at)
|
|
9603
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
9604
|
+
`).run(event.id, event.projectId, event.cardId, event.kind, event.detail ?? null, event.createdAt);
|
|
9605
|
+
return event;
|
|
9606
|
+
}
|
|
9607
|
+
listEvents(cardId, limit2 = 50) {
|
|
9608
|
+
const rows = this.requireDb().prepare(`
|
|
9609
|
+
SELECT * FROM evidence_card_events WHERE card_id = ? ORDER BY created_at DESC LIMIT ?
|
|
9610
|
+
`).all(cardId, Math.min(200, Math.max(1, Math.floor(limit2))));
|
|
9611
|
+
return rows.map((row) => ({
|
|
9612
|
+
id: String(row.id),
|
|
9613
|
+
projectId: String(row.project_id),
|
|
9614
|
+
cardId: String(row.card_id),
|
|
9615
|
+
kind: String(row.kind),
|
|
9616
|
+
...row.detail ? { detail: String(row.detail) } : {},
|
|
9617
|
+
createdAt: String(row.created_at)
|
|
9618
|
+
}));
|
|
9619
|
+
}
|
|
9620
|
+
};
|
|
9621
|
+
}
|
|
9622
|
+
});
|
|
9623
|
+
|
|
9294
9624
|
// src/runtime/isolated-maintenance.ts
|
|
9295
9625
|
import { spawn } from "child_process";
|
|
9296
9626
|
import { existsSync as existsSync8 } from "fs";
|
|
@@ -9452,7 +9782,7 @@ var workspace_store_exports = {};
|
|
|
9452
9782
|
__export(workspace_store_exports, {
|
|
9453
9783
|
KnowledgeWorkspaceStore: () => KnowledgeWorkspaceStore
|
|
9454
9784
|
});
|
|
9455
|
-
import { randomUUID as
|
|
9785
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
9456
9786
|
function arrayValue(raw) {
|
|
9457
9787
|
if (typeof raw !== "string" || !raw) return [];
|
|
9458
9788
|
try {
|
|
@@ -9593,7 +9923,7 @@ var init_workspace_store = __esm({
|
|
|
9593
9923
|
}
|
|
9594
9924
|
createProposal(input) {
|
|
9595
9925
|
const proposal = {
|
|
9596
|
-
id: input.id ??
|
|
9926
|
+
id: input.id ?? randomUUID4(),
|
|
9597
9927
|
...input,
|
|
9598
9928
|
status: input.status ?? "pending",
|
|
9599
9929
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -9646,13 +9976,13 @@ __export(workspace_exports, {
|
|
|
9646
9976
|
loadKnowledgeWorkspace: () => loadKnowledgeWorkspace,
|
|
9647
9977
|
resolveKnowledgeWorkspaceFile: () => resolveKnowledgeWorkspaceFile
|
|
9648
9978
|
});
|
|
9649
|
-
import { createHash as
|
|
9979
|
+
import { createHash as createHash4 } from "crypto";
|
|
9650
9980
|
import { execFile } from "child_process";
|
|
9651
9981
|
import { promises as fs9 } from "fs";
|
|
9652
9982
|
import path13 from "path";
|
|
9653
9983
|
import { promisify } from "util";
|
|
9654
9984
|
function hash(value) {
|
|
9655
|
-
return
|
|
9985
|
+
return createHash4("sha256").update(value).digest("hex");
|
|
9656
9986
|
}
|
|
9657
9987
|
function workspaceId(projectId, mode) {
|
|
9658
9988
|
return "workspace:" + hash(projectId + ":" + mode).slice(0, 24);
|
|
@@ -10252,7 +10582,7 @@ var media_store_exports = {};
|
|
|
10252
10582
|
__export(media_store_exports, {
|
|
10253
10583
|
MediaStore: () => MediaStore
|
|
10254
10584
|
});
|
|
10255
|
-
import { randomUUID as
|
|
10585
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
10256
10586
|
function asOptionalText(value) {
|
|
10257
10587
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
10258
10588
|
}
|
|
@@ -10422,7 +10752,7 @@ var init_media_store = __esm({
|
|
|
10422
10752
|
return { asset: this.getAsset(input.projectId, existing.id), deduplicated: true };
|
|
10423
10753
|
}
|
|
10424
10754
|
const asset = {
|
|
10425
|
-
id:
|
|
10755
|
+
id: randomUUID5(),
|
|
10426
10756
|
...input,
|
|
10427
10757
|
createdAt: now3,
|
|
10428
10758
|
updatedAt: now3
|
|
@@ -10502,7 +10832,7 @@ var init_media_store = __esm({
|
|
|
10502
10832
|
`).get(input.assetId, input.observationId ?? null, input.role);
|
|
10503
10833
|
if (existing) return rowToLink(existing);
|
|
10504
10834
|
const link = {
|
|
10505
|
-
id:
|
|
10835
|
+
id: randomUUID5(),
|
|
10506
10836
|
assetId: input.assetId,
|
|
10507
10837
|
projectId: input.projectId,
|
|
10508
10838
|
...input.observationId !== void 0 ? { observationId: input.observationId } : {},
|
|
@@ -10541,7 +10871,7 @@ var init_media_store = __esm({
|
|
|
10541
10871
|
return rowToDerivation(this.db.prepare("SELECT * FROM media_derivations WHERE id = ?").get(existing.id));
|
|
10542
10872
|
}
|
|
10543
10873
|
const derivation = {
|
|
10544
|
-
id:
|
|
10874
|
+
id: randomUUID5(),
|
|
10545
10875
|
...input,
|
|
10546
10876
|
content,
|
|
10547
10877
|
...error ? { error } : {},
|
|
@@ -10628,7 +10958,7 @@ var init_media_store = __esm({
|
|
|
10628
10958
|
createJob(input) {
|
|
10629
10959
|
const now3 = Date.now();
|
|
10630
10960
|
const job = {
|
|
10631
|
-
id:
|
|
10961
|
+
id: randomUUID5(),
|
|
10632
10962
|
projectId: input.projectId,
|
|
10633
10963
|
kind: input.kind,
|
|
10634
10964
|
status: "queued",
|
|
@@ -10804,14 +11134,14 @@ __export(asset_store_exports, {
|
|
|
10804
11134
|
readMediaAsset: () => readMediaAsset,
|
|
10805
11135
|
removeMediaAsset: () => removeMediaAsset
|
|
10806
11136
|
});
|
|
10807
|
-
import { createHash as
|
|
11137
|
+
import { createHash as createHash5, randomUUID as randomUUID6 } from "crypto";
|
|
10808
11138
|
import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename as rename2, rm, stat as stat2, writeFile as writeFile3 } from "fs/promises";
|
|
10809
11139
|
import path14 from "path";
|
|
10810
11140
|
function mediaRoot(dataDir) {
|
|
10811
11141
|
return path14.resolve(dataDir, "media");
|
|
10812
11142
|
}
|
|
10813
11143
|
function projectStorageKey(projectId) {
|
|
10814
|
-
return
|
|
11144
|
+
return createHash5("sha256").update(projectId).digest("hex").slice(0, 16);
|
|
10815
11145
|
}
|
|
10816
11146
|
function validateUnderRoot(root, candidate) {
|
|
10817
11147
|
const resolved = path14.resolve(candidate);
|
|
@@ -10871,14 +11201,14 @@ async function readHeader(filePath, bytes = 32) {
|
|
|
10871
11201
|
}
|
|
10872
11202
|
async function sha256File(filePath) {
|
|
10873
11203
|
const bytes = await readFile3(filePath);
|
|
10874
|
-
return
|
|
11204
|
+
return createHash5("sha256").update(bytes).digest("hex");
|
|
10875
11205
|
}
|
|
10876
11206
|
function destinationFor(root, projectId, sha256, extension3) {
|
|
10877
11207
|
const relative3 = path14.join("assets", projectStorageKey(projectId), sha256.slice(0, 2), `${sha256}${extension3}`);
|
|
10878
11208
|
return { relative: relative3, absolute: validateUnderRoot(root, path14.join(root, relative3)) };
|
|
10879
11209
|
}
|
|
10880
11210
|
function deletionStagingPath(root, assetId) {
|
|
10881
|
-
return validateUnderRoot(root, path14.join(root, ".trash", `${assetId}.${
|
|
11211
|
+
return validateUnderRoot(root, path14.join(root, ".trash", `${assetId}.${randomUUID6()}.pending-delete`));
|
|
10882
11212
|
}
|
|
10883
11213
|
async function destinationExists(destination) {
|
|
10884
11214
|
try {
|
|
@@ -10892,7 +11222,7 @@ async function destinationExists(destination) {
|
|
|
10892
11222
|
async function persistFile(source, destination) {
|
|
10893
11223
|
await mkdir3(path14.dirname(destination), { recursive: true });
|
|
10894
11224
|
if (await destinationExists(destination)) return false;
|
|
10895
|
-
const temporary = `${destination}.${
|
|
11225
|
+
const temporary = `${destination}.${randomUUID6()}.tmp`;
|
|
10896
11226
|
try {
|
|
10897
11227
|
await copyFile(source, temporary);
|
|
10898
11228
|
await rename2(temporary, destination);
|
|
@@ -10908,7 +11238,7 @@ async function persistFile(source, destination) {
|
|
|
10908
11238
|
async function persistBuffer(bytes, destination) {
|
|
10909
11239
|
await mkdir3(path14.dirname(destination), { recursive: true });
|
|
10910
11240
|
if (await destinationExists(destination)) return false;
|
|
10911
|
-
const temporary = `${destination}.${
|
|
11241
|
+
const temporary = `${destination}.${randomUUID6()}.tmp`;
|
|
10912
11242
|
try {
|
|
10913
11243
|
await writeFile3(temporary, bytes, { flag: "wx" });
|
|
10914
11244
|
await rename2(temporary, destination);
|
|
@@ -10977,7 +11307,7 @@ async function importMediaBuffer(input) {
|
|
|
10977
11307
|
if (input.bytes.length === 0) throw new Error("Media import rejects empty payloads");
|
|
10978
11308
|
if (input.bytes.length > maxBytes) throw new Error(`Media payload is too large (${input.bytes.length} bytes; limit ${maxBytes})`);
|
|
10979
11309
|
const detected = detectMedia(input.bytes.subarray(0, 32));
|
|
10980
|
-
const sha256 =
|
|
11310
|
+
const sha256 = createHash5("sha256").update(input.bytes).digest("hex");
|
|
10981
11311
|
return importKnownMedia({
|
|
10982
11312
|
dataDir: input.dataDir,
|
|
10983
11313
|
projectId: input.projectId,
|
|
@@ -10995,7 +11325,7 @@ async function readMediaAsset(dataDir, asset, maxBytes = DEFAULT_MAX_MEDIA_BYTES
|
|
|
10995
11325
|
if (asset.byteSize > maxBytes) throw new Error(`Media asset exceeds read limit (${asset.byteSize} bytes; limit ${maxBytes})`);
|
|
10996
11326
|
const bytes = await readFile3(getMediaAssetPath(dataDir, asset));
|
|
10997
11327
|
if (bytes.length !== asset.byteSize) throw new Error(`Media asset size no longer matches metadata: ${asset.id}`);
|
|
10998
|
-
const sha256 =
|
|
11328
|
+
const sha256 = createHash5("sha256").update(bytes).digest("hex");
|
|
10999
11329
|
if (sha256 !== asset.sha256) throw new Error(`Media asset hash no longer matches metadata: ${asset.id}`);
|
|
11000
11330
|
return bytes;
|
|
11001
11331
|
}
|
|
@@ -63865,7 +64195,7 @@ var require_gaxios = __commonJS({
|
|
|
63865
64195
|
var retry_js_1 = require_retry3();
|
|
63866
64196
|
var stream_1 = __require("stream");
|
|
63867
64197
|
var interceptor_js_1 = require_interceptor();
|
|
63868
|
-
var
|
|
64198
|
+
var randomUUID19 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
|
|
63869
64199
|
var HTTP_STATUS_NO_CONTENT = 204;
|
|
63870
64200
|
var Gaxios = class {
|
|
63871
64201
|
agentCache = /* @__PURE__ */ new Map();
|
|
@@ -64138,7 +64468,7 @@ var require_gaxios = __commonJS({
|
|
|
64138
64468
|
*/
|
|
64139
64469
|
["Blob", "File", "FormData"].includes(opts.data?.constructor?.name || "");
|
|
64140
64470
|
if (opts.multipart?.length) {
|
|
64141
|
-
const boundary = await
|
|
64471
|
+
const boundary = await randomUUID19();
|
|
64142
64472
|
preparedHeaders.set("content-type", `multipart/related; boundary=${boundary}`);
|
|
64143
64473
|
opts.body = stream_1.Readable.from(this.getMultipartRequest(opts.multipart, boundary));
|
|
64144
64474
|
} else if (shouldDirectlyPassData) {
|
|
@@ -76365,7 +76695,7 @@ var require_websocket = __commonJS({
|
|
|
76365
76695
|
var http3 = __require("http");
|
|
76366
76696
|
var net = __require("net");
|
|
76367
76697
|
var tls = __require("tls");
|
|
76368
|
-
var { randomBytes: randomBytes2, createHash:
|
|
76698
|
+
var { randomBytes: randomBytes2, createHash: createHash17 } = __require("crypto");
|
|
76369
76699
|
var { Duplex, Readable: Readable2 } = __require("stream");
|
|
76370
76700
|
var { URL: URL2 } = __require("url");
|
|
76371
76701
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -77033,7 +77363,7 @@ var require_websocket = __commonJS({
|
|
|
77033
77363
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
77034
77364
|
return;
|
|
77035
77365
|
}
|
|
77036
|
-
const digest2 =
|
|
77366
|
+
const digest2 = createHash17("sha1").update(key + GUID).digest("base64");
|
|
77037
77367
|
if (res.headers["sec-websocket-accept"] !== digest2) {
|
|
77038
77368
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
77039
77369
|
return;
|
|
@@ -77405,7 +77735,7 @@ var require_websocket_server = __commonJS({
|
|
|
77405
77735
|
var EventEmitter2 = __require("events");
|
|
77406
77736
|
var http3 = __require("http");
|
|
77407
77737
|
var { Duplex } = __require("stream");
|
|
77408
|
-
var { createHash:
|
|
77738
|
+
var { createHash: createHash17 } = __require("crypto");
|
|
77409
77739
|
var extension3 = require_extension();
|
|
77410
77740
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
77411
77741
|
var subprotocol2 = require_subprotocol();
|
|
@@ -77712,7 +78042,7 @@ var require_websocket_server = __commonJS({
|
|
|
77712
78042
|
);
|
|
77713
78043
|
}
|
|
77714
78044
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
77715
|
-
const digest2 =
|
|
78045
|
+
const digest2 = createHash17("sha1").update(key + GUID).digest("base64");
|
|
77716
78046
|
const headers = [
|
|
77717
78047
|
"HTTP/1.1 101 Switching Protocols",
|
|
77718
78048
|
"Upgrade: websocket",
|
|
@@ -144966,6 +145296,186 @@ var init_audio_jobs = __esm({
|
|
|
144966
145296
|
}
|
|
144967
145297
|
});
|
|
144968
145298
|
|
|
145299
|
+
// src/memory/feedback-model.ts
|
|
145300
|
+
function feedbackWeightMultiplier(weight) {
|
|
145301
|
+
return Math.max(0.35, Math.min(1.4, 0.35 + Math.max(0, Math.min(2, weight)) * 0.525));
|
|
145302
|
+
}
|
|
145303
|
+
var init_feedback_model = __esm({
|
|
145304
|
+
"src/memory/feedback-model.ts"() {
|
|
145305
|
+
"use strict";
|
|
145306
|
+
init_esm_shims();
|
|
145307
|
+
}
|
|
145308
|
+
});
|
|
145309
|
+
|
|
145310
|
+
// src/memory/feedback.ts
|
|
145311
|
+
var feedback_exports = {};
|
|
145312
|
+
__export(feedback_exports, {
|
|
145313
|
+
FEEDBACK_DELTAS: () => FEEDBACK_DELTAS,
|
|
145314
|
+
MemoryFeedbackStore: () => MemoryFeedbackStore,
|
|
145315
|
+
applyMemoryFeedback: () => applyMemoryFeedback,
|
|
145316
|
+
feedbackWeightMultiplier: () => feedbackWeightMultiplier
|
|
145317
|
+
});
|
|
145318
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
145319
|
+
function applyMemoryFeedback(current, event) {
|
|
145320
|
+
const delta = event.signal === "revoke" ? 0 : FEEDBACK_DELTAS[event.signal];
|
|
145321
|
+
const weight = Math.max(0, Math.min(2, current.weight + delta));
|
|
145322
|
+
const status = (event.signal === "code-conflict" || event.signal === "user-correction" || event.signal === "weaken") && weight < 0.5 ? "archived" : current.status;
|
|
145323
|
+
return { weight, status, audit: [...current.audit, { ...event }] };
|
|
145324
|
+
}
|
|
145325
|
+
function rowToEvent(row) {
|
|
145326
|
+
return {
|
|
145327
|
+
id: String(row.id),
|
|
145328
|
+
projectId: String(row.project_id),
|
|
145329
|
+
candidateKind: row.candidate_kind,
|
|
145330
|
+
candidateId: String(row.candidate_id),
|
|
145331
|
+
signal: row.signal,
|
|
145332
|
+
...row.observed_at ? { at: String(row.observed_at) } : { at: (/* @__PURE__ */ new Date()).toISOString() },
|
|
145333
|
+
...row.actor ? { actor: String(row.actor) } : {},
|
|
145334
|
+
...row.note ? { note: String(row.note) } : {},
|
|
145335
|
+
...row.source_ref ? { sourceRef: String(row.source_ref) } : {},
|
|
145336
|
+
...row.target_event_id ? { targetEventId: String(row.target_event_id) } : {},
|
|
145337
|
+
delta: Number(row.delta ?? 0)
|
|
145338
|
+
};
|
|
145339
|
+
}
|
|
145340
|
+
var FEEDBACK_DELTAS, MemoryFeedbackStore;
|
|
145341
|
+
var init_feedback = __esm({
|
|
145342
|
+
"src/memory/feedback.ts"() {
|
|
145343
|
+
"use strict";
|
|
145344
|
+
init_esm_shims();
|
|
145345
|
+
init_sqlite_db();
|
|
145346
|
+
init_feedback_model();
|
|
145347
|
+
FEEDBACK_DELTAS = {
|
|
145348
|
+
"user-correction": -0.35,
|
|
145349
|
+
"verification-success": 0.25,
|
|
145350
|
+
"verification-failure": -0.25,
|
|
145351
|
+
"code-change": -0.15,
|
|
145352
|
+
used: 0.1,
|
|
145353
|
+
"not-used": -0.05,
|
|
145354
|
+
"code-conflict": -0.4,
|
|
145355
|
+
strengthen: 0.2,
|
|
145356
|
+
weaken: -0.2
|
|
145357
|
+
};
|
|
145358
|
+
MemoryFeedbackStore = class {
|
|
145359
|
+
db = null;
|
|
145360
|
+
async init(dataDir) {
|
|
145361
|
+
this.db = getDatabase(dataDir);
|
|
145362
|
+
}
|
|
145363
|
+
requireDb() {
|
|
145364
|
+
if (!this.db) throw new Error("MemoryFeedbackStore is not initialized.");
|
|
145365
|
+
return this.db;
|
|
145366
|
+
}
|
|
145367
|
+
loadEvents(projectId, candidateKind, candidateId) {
|
|
145368
|
+
return this.requireDb().prepare(`
|
|
145369
|
+
SELECT * FROM memory_feedback_events
|
|
145370
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
145371
|
+
ORDER BY observed_at ASC, rowid ASC
|
|
145372
|
+
`).all(projectId, candidateKind, candidateId).map(rowToEvent);
|
|
145373
|
+
}
|
|
145374
|
+
rebuild(projectId, candidateKind, candidateId) {
|
|
145375
|
+
const events = this.loadEvents(projectId, candidateKind, candidateId);
|
|
145376
|
+
const revoked = new Set(events.filter((event) => event.signal === "revoke" && event.targetEventId).map((event) => event.targetEventId));
|
|
145377
|
+
let state = { weight: 1, status: "active", audit: [] };
|
|
145378
|
+
for (const event of events) {
|
|
145379
|
+
if (event.signal === "revoke" || revoked.has(event.id)) {
|
|
145380
|
+
state.audit.push(event);
|
|
145381
|
+
continue;
|
|
145382
|
+
}
|
|
145383
|
+
state = applyMemoryFeedback(state, event);
|
|
145384
|
+
}
|
|
145385
|
+
this.requireDb().prepare(`
|
|
145386
|
+
INSERT INTO memory_feedback_states (project_id, candidate_kind, candidate_id, weight, lifecycle_status, updated_at)
|
|
145387
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
145388
|
+
ON CONFLICT(project_id, candidate_kind, candidate_id) DO UPDATE SET
|
|
145389
|
+
weight = excluded.weight, lifecycle_status = excluded.lifecycle_status, updated_at = excluded.updated_at
|
|
145390
|
+
`).run(projectId, candidateKind, candidateId, state.weight, state.status, (/* @__PURE__ */ new Date()).toISOString());
|
|
145391
|
+
return state;
|
|
145392
|
+
}
|
|
145393
|
+
getState(projectId, candidateKind, candidateId) {
|
|
145394
|
+
const row = this.requireDb().prepare(`
|
|
145395
|
+
SELECT weight, lifecycle_status FROM memory_feedback_states
|
|
145396
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
145397
|
+
`).get(projectId, candidateKind, candidateId);
|
|
145398
|
+
if (!row) return { weight: 1, status: "active", audit: [] };
|
|
145399
|
+
return {
|
|
145400
|
+
weight: Number(row.weight ?? 1),
|
|
145401
|
+
status: row.lifecycle_status ?? "active",
|
|
145402
|
+
audit: this.loadEvents(projectId, candidateKind, candidateId)
|
|
145403
|
+
};
|
|
145404
|
+
}
|
|
145405
|
+
listStates(projectId, candidateKind = "observation") {
|
|
145406
|
+
return this.requireDb().prepare(`
|
|
145407
|
+
SELECT candidate_id, weight, lifecycle_status, updated_at
|
|
145408
|
+
FROM memory_feedback_states WHERE project_id = ? AND candidate_kind = ?
|
|
145409
|
+
ORDER BY updated_at DESC
|
|
145410
|
+
`).all(projectId, candidateKind).map((row) => ({
|
|
145411
|
+
candidateId: String(row.candidate_id),
|
|
145412
|
+
weight: Number(row.weight),
|
|
145413
|
+
status: row.lifecycle_status,
|
|
145414
|
+
updatedAt: String(row.updated_at)
|
|
145415
|
+
}));
|
|
145416
|
+
}
|
|
145417
|
+
weights(projectId, candidateKind = "observation") {
|
|
145418
|
+
const states = /* @__PURE__ */ new Map();
|
|
145419
|
+
for (const row of this.listStates(projectId, candidateKind)) {
|
|
145420
|
+
states.set(row.candidateId, this.getState(projectId, candidateKind, row.candidateId));
|
|
145421
|
+
}
|
|
145422
|
+
return states;
|
|
145423
|
+
}
|
|
145424
|
+
record(input) {
|
|
145425
|
+
if (input.signal === "revoke" && !input.targetEventId) {
|
|
145426
|
+
throw new Error("A revoke feedback event requires targetEventId.");
|
|
145427
|
+
}
|
|
145428
|
+
if (input.signal === "revoke") {
|
|
145429
|
+
const target = this.requireDb().prepare(`
|
|
145430
|
+
SELECT 1 FROM memory_feedback_events
|
|
145431
|
+
WHERE id = ? AND project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
145432
|
+
`).get(input.targetEventId, input.projectId, input.candidateKind, input.candidateId);
|
|
145433
|
+
if (!target) throw new Error("The feedback event to revoke was not found in the same candidate scope.");
|
|
145434
|
+
}
|
|
145435
|
+
const event = {
|
|
145436
|
+
id: randomUUID7(),
|
|
145437
|
+
projectId: input.projectId,
|
|
145438
|
+
candidateKind: input.candidateKind,
|
|
145439
|
+
candidateId: input.candidateId,
|
|
145440
|
+
signal: input.signal,
|
|
145441
|
+
sourceRef: input.sourceRef,
|
|
145442
|
+
...input.actor ? { actor: input.actor } : {},
|
|
145443
|
+
...input.note ? { note: input.note.slice(0, 2e3) } : {},
|
|
145444
|
+
...input.targetEventId ? { targetEventId: input.targetEventId } : {},
|
|
145445
|
+
at: input.at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
145446
|
+
delta: input.signal === "revoke" ? 0 : FEEDBACK_DELTAS[input.signal]
|
|
145447
|
+
};
|
|
145448
|
+
this.requireDb().prepare(`
|
|
145449
|
+
INSERT INTO memory_feedback_events (
|
|
145450
|
+
id, project_id, candidate_kind, candidate_id, signal, actor, note,
|
|
145451
|
+
source_ref, target_event_id, delta, observed_at
|
|
145452
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
145453
|
+
`).run(
|
|
145454
|
+
event.id,
|
|
145455
|
+
event.projectId,
|
|
145456
|
+
event.candidateKind,
|
|
145457
|
+
event.candidateId,
|
|
145458
|
+
event.signal,
|
|
145459
|
+
event.actor ?? null,
|
|
145460
|
+
event.note ?? null,
|
|
145461
|
+
event.sourceRef,
|
|
145462
|
+
event.targetEventId ?? null,
|
|
145463
|
+
event.delta,
|
|
145464
|
+
event.at
|
|
145465
|
+
);
|
|
145466
|
+
return { event, state: this.rebuild(input.projectId, input.candidateKind, input.candidateId) };
|
|
145467
|
+
}
|
|
145468
|
+
audit(projectId, candidateKind, candidateId, limit2 = 100) {
|
|
145469
|
+
return this.requireDb().prepare(`
|
|
145470
|
+
SELECT * FROM memory_feedback_events
|
|
145471
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
145472
|
+
ORDER BY observed_at DESC, rowid DESC LIMIT ?
|
|
145473
|
+
`).all(projectId, candidateKind, candidateId, Math.min(200, Math.max(1, Math.floor(limit2)))).map(rowToEvent);
|
|
145474
|
+
}
|
|
145475
|
+
};
|
|
145476
|
+
}
|
|
145477
|
+
});
|
|
145478
|
+
|
|
144969
145479
|
// src/memory/retention.ts
|
|
144970
145480
|
var retention_exports = {};
|
|
144971
145481
|
__export(retention_exports, {
|
|
@@ -145007,6 +145517,7 @@ function getEffectiveRetentionDays(doc) {
|
|
|
145007
145517
|
}
|
|
145008
145518
|
function isImmune(doc) {
|
|
145009
145519
|
if (doc.type === "probe") return false;
|
|
145520
|
+
if (doc.feedbackStatus === "archived") return false;
|
|
145010
145521
|
if (doc.admissionState === "candidate" || doc.admissionState === "ephemeral") return false;
|
|
145011
145522
|
if (doc.valueCategory === "core") return true;
|
|
145012
145523
|
const importance = getImportanceLevel(doc);
|
|
@@ -145039,7 +145550,8 @@ function calculateRelevance(doc, referenceTime) {
|
|
|
145039
145550
|
const decayFactor = Math.exp(-ageDays / retention);
|
|
145040
145551
|
const accessCount = doc.accessCount ?? 0;
|
|
145041
145552
|
const accessBoost = Math.min(2, 1 + 0.1 * accessCount);
|
|
145042
|
-
|
|
145553
|
+
const feedbackMultiplier = doc.feedbackWeight === void 0 ? 1 : feedbackWeightMultiplier(doc.feedbackWeight);
|
|
145554
|
+
let totalScore = base * decayFactor * accessBoost * feedbackMultiplier;
|
|
145043
145555
|
const immune = isImmune(doc);
|
|
145044
145556
|
if (immune) {
|
|
145045
145557
|
totalScore = Math.max(totalScore, 0.5);
|
|
@@ -145051,7 +145563,8 @@ function calculateRelevance(doc, referenceTime) {
|
|
|
145051
145563
|
decayFactor,
|
|
145052
145564
|
accessBoost,
|
|
145053
145565
|
ageDays,
|
|
145054
|
-
isImmune: immune
|
|
145566
|
+
isImmune: immune,
|
|
145567
|
+
feedbackMultiplier
|
|
145055
145568
|
};
|
|
145056
145569
|
}
|
|
145057
145570
|
function rankByRelevance(docs, referenceTime) {
|
|
@@ -145059,6 +145572,7 @@ function rankByRelevance(docs, referenceTime) {
|
|
|
145059
145572
|
}
|
|
145060
145573
|
function getRetentionZone(doc, referenceTime) {
|
|
145061
145574
|
const now3 = referenceTime ?? /* @__PURE__ */ new Date();
|
|
145575
|
+
if (doc.feedbackStatus === "archived") return "archive-candidate";
|
|
145062
145576
|
const importance = getImportanceLevel(doc);
|
|
145063
145577
|
const retention = getEffectiveRetentionDays(doc);
|
|
145064
145578
|
const createdAt = new Date(doc.createdAt);
|
|
@@ -145130,7 +145644,7 @@ function explainRetention(doc, referenceTime) {
|
|
|
145130
145644
|
summary: parts.join(" ; ")
|
|
145131
145645
|
};
|
|
145132
145646
|
}
|
|
145133
|
-
function toRetentionDocument(obs, accessMap) {
|
|
145647
|
+
function toRetentionDocument(obs, accessMap, feedback) {
|
|
145134
145648
|
const access3 = accessMap?.get(obs.id);
|
|
145135
145649
|
return {
|
|
145136
145650
|
id: `obs-${obs.id}`,
|
|
@@ -145152,11 +145666,12 @@ function toRetentionDocument(obs, accessMap) {
|
|
|
145152
145666
|
sourceDetail: obs.sourceDetail ?? "",
|
|
145153
145667
|
valueCategory: obs.valueCategory ?? "",
|
|
145154
145668
|
admissionState: obs.admissionState ?? "",
|
|
145155
|
-
admissionReason: obs.admissionReason ?? ""
|
|
145669
|
+
admissionReason: obs.admissionReason ?? "",
|
|
145670
|
+
...feedback ? { feedbackWeight: feedback.weight, feedbackStatus: feedback.status } : {}
|
|
145156
145671
|
};
|
|
145157
145672
|
}
|
|
145158
145673
|
function projectObservationRetention(observation, options = {}) {
|
|
145159
|
-
const document2 = toRetentionDocument(observation, options.accessMap);
|
|
145674
|
+
const document2 = toRetentionDocument(observation, options.accessMap, options.feedback);
|
|
145160
145675
|
const relevance = calculateRelevance(document2, options.referenceTime);
|
|
145161
145676
|
const explanation = explainRetention(document2, options.referenceTime);
|
|
145162
145677
|
return {
|
|
@@ -145181,7 +145696,17 @@ function summarizeRetentionProjections(projections) {
|
|
|
145181
145696
|
}
|
|
145182
145697
|
return { active, stale, archiveCandidates, immune };
|
|
145183
145698
|
}
|
|
145184
|
-
async function
|
|
145699
|
+
async function loadFeedbackStore(dataDir) {
|
|
145700
|
+
try {
|
|
145701
|
+
const { MemoryFeedbackStore: MemoryFeedbackStore2 } = await Promise.resolve().then(() => (init_feedback(), feedback_exports));
|
|
145702
|
+
const store = new MemoryFeedbackStore2();
|
|
145703
|
+
await store.init(dataDir);
|
|
145704
|
+
return store;
|
|
145705
|
+
} catch {
|
|
145706
|
+
return void 0;
|
|
145707
|
+
}
|
|
145708
|
+
}
|
|
145709
|
+
async function archiveExpiredBatch(projectDir2, options) {
|
|
145185
145710
|
const store = getObservationStore();
|
|
145186
145711
|
const limit2 = Math.min(500, Math.max(1, Math.floor(options.limit ?? 100)));
|
|
145187
145712
|
const afterId = Math.max(0, Math.floor(options.afterId ?? 0));
|
|
@@ -145190,11 +145715,13 @@ async function archiveExpiredBatch(_projectDir, options) {
|
|
|
145190
145715
|
afterId,
|
|
145191
145716
|
limit: limit2 + 1
|
|
145192
145717
|
});
|
|
145718
|
+
const feedback = await loadFeedbackStore(projectDir2);
|
|
145193
145719
|
const hasMore = page.length > limit2;
|
|
145194
145720
|
const scanned = hasMore ? page.slice(0, limit2) : page;
|
|
145195
145721
|
const candidateIds = scanned.filter((observation) => !options.reader || canManageObservation(observation, options.reader)).filter((observation) => projectObservationRetention(observation, {
|
|
145196
145722
|
accessMap: options.accessMap,
|
|
145197
|
-
referenceTime: options.referenceTime
|
|
145723
|
+
referenceTime: options.referenceTime,
|
|
145724
|
+
...feedback ? { feedback: feedback.getState(options.projectId, "observation", String(observation.id)) } : {}
|
|
145198
145725
|
}).zone === "archive-candidate").map((observation) => observation.id);
|
|
145199
145726
|
const archived = candidateIds.length === 0 ? 0 : await store.atomic(async (tx) => {
|
|
145200
145727
|
const updates = await Promise.all(
|
|
@@ -145225,6 +145752,7 @@ async function archiveExpired(projectDir2, referenceTime, accessMap, projectId,
|
|
|
145225
145752
|
const remaining = reader2 ? remainingObservations.filter((observation) => canManageObservation(observation, reader2)).length : remainingObservations.length;
|
|
145226
145753
|
return { archived, remaining };
|
|
145227
145754
|
}
|
|
145755
|
+
const feedback = await loadFeedbackStore(projectDir2);
|
|
145228
145756
|
return await store.atomic(async (tx) => {
|
|
145229
145757
|
const allObs = await tx.loadAll();
|
|
145230
145758
|
const activeObs = allObs.filter(
|
|
@@ -145232,7 +145760,11 @@ async function archiveExpired(projectDir2, referenceTime, accessMap, projectId,
|
|
|
145232
145760
|
);
|
|
145233
145761
|
const archivedIds = [];
|
|
145234
145762
|
for (const obs of activeObs) {
|
|
145235
|
-
const retention = projectObservationRetention(obs, {
|
|
145763
|
+
const retention = projectObservationRetention(obs, {
|
|
145764
|
+
accessMap,
|
|
145765
|
+
referenceTime,
|
|
145766
|
+
...feedback ? { feedback: feedback.getState(obs.projectId, "observation", String(obs.id)) } : {}
|
|
145767
|
+
});
|
|
145236
145768
|
if (retention.zone === "archive-candidate") {
|
|
145237
145769
|
archivedIds.push(obs.id);
|
|
145238
145770
|
}
|
|
@@ -145252,6 +145784,7 @@ var init_retention = __esm({
|
|
|
145252
145784
|
init_esm_shims();
|
|
145253
145785
|
init_obs_store();
|
|
145254
145786
|
init_visibility();
|
|
145787
|
+
init_feedback_model();
|
|
145255
145788
|
RETENTION_DAYS = {
|
|
145256
145789
|
critical: 365,
|
|
145257
145790
|
high: 180,
|
|
@@ -145292,7 +145825,7 @@ var owner_exports = {};
|
|
|
145292
145825
|
__export(owner_exports, {
|
|
145293
145826
|
resolveLocalMemoryOwner: () => resolveLocalMemoryOwner
|
|
145294
145827
|
});
|
|
145295
|
-
import { randomUUID as
|
|
145828
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
145296
145829
|
import { promises as fs12 } from "fs";
|
|
145297
145830
|
import path20 from "path";
|
|
145298
145831
|
function ownerPath(dataDir) {
|
|
@@ -145322,7 +145855,7 @@ async function resolveLocalMemoryOwner(dataDir, options = {}) {
|
|
|
145322
145855
|
await fs12.mkdir(path20.dirname(filePath), { recursive: true });
|
|
145323
145856
|
const created = {
|
|
145324
145857
|
version: 1,
|
|
145325
|
-
id: "local-" +
|
|
145858
|
+
id: "local-" + randomUUID8(),
|
|
145326
145859
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
145327
145860
|
};
|
|
145328
145861
|
try {
|
|
@@ -145345,7 +145878,7 @@ var init_owner = __esm({
|
|
|
145345
145878
|
});
|
|
145346
145879
|
|
|
145347
145880
|
// src/memory/long-term-store.ts
|
|
145348
|
-
import { randomUUID as
|
|
145881
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
145349
145882
|
function optionalText2(value) {
|
|
145350
145883
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
145351
145884
|
}
|
|
@@ -145396,7 +145929,7 @@ function rowToEvidence(row) {
|
|
|
145396
145929
|
createdAt: row.createdAt
|
|
145397
145930
|
};
|
|
145398
145931
|
}
|
|
145399
|
-
function
|
|
145932
|
+
function rowToEvent2(row) {
|
|
145400
145933
|
return {
|
|
145401
145934
|
id: row.id,
|
|
145402
145935
|
memoryId: row.memoryId,
|
|
@@ -145505,7 +146038,7 @@ var init_long_term_store = __esm({
|
|
|
145505
146038
|
}
|
|
145506
146039
|
insertEvidence(input) {
|
|
145507
146040
|
const evidence = {
|
|
145508
|
-
id:
|
|
146041
|
+
id: randomUUID9(),
|
|
145509
146042
|
...input,
|
|
145510
146043
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
145511
146044
|
};
|
|
@@ -145532,7 +146065,7 @@ var init_long_term_store = __esm({
|
|
|
145532
146065
|
}
|
|
145533
146066
|
recordEvent(input) {
|
|
145534
146067
|
const event = {
|
|
145535
|
-
id:
|
|
146068
|
+
id: randomUUID9(),
|
|
145536
146069
|
...input,
|
|
145537
146070
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
145538
146071
|
};
|
|
@@ -145553,7 +146086,7 @@ var init_long_term_store = __esm({
|
|
|
145553
146086
|
listEvents(memoryId) {
|
|
145554
146087
|
return this.db.prepare(`
|
|
145555
146088
|
SELECT * FROM long_term_memory_events WHERE memoryId = ? ORDER BY createdAt ASC, rowid ASC
|
|
145556
|
-
`).all(memoryId).map(
|
|
146089
|
+
`).all(memoryId).map(rowToEvent2);
|
|
145557
146090
|
}
|
|
145558
146091
|
markAccess(ids, at = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
145559
146092
|
const unique2 = [...new Set(ids.filter(Boolean))];
|
|
@@ -145622,7 +146155,7 @@ __export(long_term_exports, {
|
|
|
145622
146155
|
selectLongTermMemoriesForTask: () => selectLongTermMemoriesForTask,
|
|
145623
146156
|
supersedeLongTermMemory: () => supersedeLongTermMemory
|
|
145624
146157
|
});
|
|
145625
|
-
import { randomUUID as
|
|
146158
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
145626
146159
|
function isOneOf(value, values) {
|
|
145627
146160
|
return typeof value === "string" && values.includes(value);
|
|
145628
146161
|
}
|
|
@@ -145804,7 +146337,7 @@ async function createManualLongTermMemory(input) {
|
|
|
145804
146337
|
const owner = await resolveLocalMemoryOwner(input.dataDir, { create: true });
|
|
145805
146338
|
if (!owner) throw new Error("Memorix could not resolve a local memory owner.");
|
|
145806
146339
|
assertScope(input.scope);
|
|
145807
|
-
const evidence = input.scope === "user" ? [{ kind: "user", referenceId: owner.id, relation: "user-confirmed" }] : [{ kind: "manual", referenceId: "manual:" +
|
|
146340
|
+
const evidence = input.scope === "user" ? [{ kind: "user", referenceId: owner.id, relation: "user-confirmed" }] : [{ kind: "manual", referenceId: "manual:" + randomUUID10(), relation: "supports" }];
|
|
145808
146341
|
return createLongTermMemoryWithDataDir({
|
|
145809
146342
|
dataDir: input.dataDir,
|
|
145810
146343
|
originProjectId: input.projectId,
|
|
@@ -145859,7 +146392,7 @@ async function createLongTermMemoryWithDataDir(input) {
|
|
|
145859
146392
|
assertPortableEvidence(input.scope, portability, evidenceInputs);
|
|
145860
146393
|
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
145861
146394
|
const memory = {
|
|
145862
|
-
id:
|
|
146395
|
+
id: randomUUID10(),
|
|
145863
146396
|
originProjectId: compactText(input.originProjectId, "origin project id", 1e3),
|
|
145864
146397
|
ownerId: compactText(input.ownerId, "owner id", 160),
|
|
145865
146398
|
scope: input.scope,
|
|
@@ -146177,9 +146710,9 @@ var init_long_term = __esm({
|
|
|
146177
146710
|
});
|
|
146178
146711
|
|
|
146179
146712
|
// src/codegraph/ids.ts
|
|
146180
|
-
import { createHash as
|
|
146713
|
+
import { createHash as createHash6 } from "crypto";
|
|
146181
146714
|
function digest(input) {
|
|
146182
|
-
return
|
|
146715
|
+
return createHash6("sha256").update(input).digest("hex").slice(0, 16);
|
|
146183
146716
|
}
|
|
146184
146717
|
function normalizeCodePath(path35) {
|
|
146185
146718
|
return path35.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/");
|
|
@@ -146214,7 +146747,7 @@ var store_exports = {};
|
|
|
146214
146747
|
__export(store_exports, {
|
|
146215
146748
|
CodeGraphStore: () => CodeGraphStore
|
|
146216
146749
|
});
|
|
146217
|
-
import { randomUUID as
|
|
146750
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
146218
146751
|
import { posix as pathPosix } from "path";
|
|
146219
146752
|
function rowToFile(row) {
|
|
146220
146753
|
return {
|
|
@@ -146931,7 +147464,7 @@ var init_store = __esm({
|
|
|
146931
147464
|
* so an interrupted scan cannot be advertised as complete.
|
|
146932
147465
|
*/
|
|
146933
147466
|
recordCodeStateSnapshot(input) {
|
|
146934
|
-
const id =
|
|
147467
|
+
const id = randomUUID11();
|
|
146935
147468
|
let snapshot;
|
|
146936
147469
|
const tx = this.db.transaction(() => {
|
|
146937
147470
|
const previous = this.db.prepare(
|
|
@@ -147009,7 +147542,7 @@ var init_store = __esm({
|
|
|
147009
147542
|
|
|
147010
147543
|
// src/codegraph/code-state.ts
|
|
147011
147544
|
import { execFile as execFile2 } from "child_process";
|
|
147012
|
-
import { createHash as
|
|
147545
|
+
import { createHash as createHash7 } from "crypto";
|
|
147013
147546
|
import { promisify as promisify3 } from "util";
|
|
147014
147547
|
async function runGit(rootPath, args) {
|
|
147015
147548
|
try {
|
|
@@ -147038,7 +147571,7 @@ function changedPathCount(status) {
|
|
|
147038
147571
|
return count2;
|
|
147039
147572
|
}
|
|
147040
147573
|
function fingerprint(baseRevision, status) {
|
|
147041
|
-
return
|
|
147574
|
+
return createHash7("sha256").update(baseRevision ?? "").update("\0").update(status).digest("hex");
|
|
147042
147575
|
}
|
|
147043
147576
|
async function collectCodeStateSnapshot(input) {
|
|
147044
147577
|
const [revision, status] = await Promise.all([
|
|
@@ -147138,11 +147671,11 @@ __export(lite_provider_exports, {
|
|
|
147138
147671
|
indexProjectLite: () => indexProjectLite,
|
|
147139
147672
|
refreshProjectLite: () => refreshProjectLite
|
|
147140
147673
|
});
|
|
147141
|
-
import { createHash as
|
|
147674
|
+
import { createHash as createHash8 } from "crypto";
|
|
147142
147675
|
import { readdirSync as readdirSync2, readFileSync as readFileSync7, statSync as statSync3 } from "fs";
|
|
147143
147676
|
import { join as join4, relative } from "path";
|
|
147144
147677
|
function hashText(text2) {
|
|
147145
|
-
return
|
|
147678
|
+
return createHash8("sha256").update(text2).digest("hex");
|
|
147146
147679
|
}
|
|
147147
147680
|
function extension2(path35) {
|
|
147148
147681
|
const index = path35.lastIndexOf(".");
|
|
@@ -147709,7 +148242,7 @@ var claim_store_exports = {};
|
|
|
147709
148242
|
__export(claim_store_exports, {
|
|
147710
148243
|
ClaimStore: () => ClaimStore
|
|
147711
148244
|
});
|
|
147712
|
-
import { createHash as
|
|
148245
|
+
import { createHash as createHash9, randomUUID as randomUUID12 } from "crypto";
|
|
147713
148246
|
function optionalText3(value) {
|
|
147714
148247
|
return typeof value === "string" && value ? value : void 0;
|
|
147715
148248
|
}
|
|
@@ -147748,7 +148281,7 @@ function rowToEvidence2(row) {
|
|
|
147748
148281
|
createdAt: row.createdAt
|
|
147749
148282
|
};
|
|
147750
148283
|
}
|
|
147751
|
-
function
|
|
148284
|
+
function rowToEvent3(row) {
|
|
147752
148285
|
return {
|
|
147753
148286
|
id: row.id,
|
|
147754
148287
|
projectId: row.projectId,
|
|
@@ -147762,7 +148295,7 @@ function rowToEvent2(row) {
|
|
|
147762
148295
|
};
|
|
147763
148296
|
}
|
|
147764
148297
|
function evidenceKey(input) {
|
|
147765
|
-
return
|
|
148298
|
+
return createHash9("sha256").update(JSON.stringify([
|
|
147766
148299
|
input.evidenceKind,
|
|
147767
148300
|
input.evidenceId,
|
|
147768
148301
|
input.relation,
|
|
@@ -147893,7 +148426,7 @@ var init_claim_store = __esm({
|
|
|
147893
148426
|
locator, capturedHash, evidenceKey, createdAt
|
|
147894
148427
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
147895
148428
|
`).run(
|
|
147896
|
-
|
|
148429
|
+
randomUUID12(),
|
|
147897
148430
|
input.claimId,
|
|
147898
148431
|
input.evidenceKind,
|
|
147899
148432
|
input.evidenceId,
|
|
@@ -147915,7 +148448,7 @@ var init_claim_store = __esm({
|
|
|
147915
148448
|
}
|
|
147916
148449
|
recordEvent(input) {
|
|
147917
148450
|
const event = {
|
|
147918
|
-
id:
|
|
148451
|
+
id: randomUUID12(),
|
|
147919
148452
|
...input,
|
|
147920
148453
|
...input.detail ? { detail: sanitizeCredentials(input.detail) } : {},
|
|
147921
148454
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -147943,7 +148476,7 @@ var init_claim_store = __esm({
|
|
|
147943
148476
|
SELECT * FROM knowledge_claim_events
|
|
147944
148477
|
WHERE claimId = ?
|
|
147945
148478
|
ORDER BY createdAt ASC, id
|
|
147946
|
-
`).all(claimId).map(
|
|
148479
|
+
`).all(claimId).map(rowToEvent3);
|
|
147947
148480
|
}
|
|
147948
148481
|
};
|
|
147949
148482
|
}
|
|
@@ -147960,7 +148493,7 @@ __export(claims_exports, {
|
|
|
147960
148493
|
supersedeClaim: () => supersedeClaim,
|
|
147961
148494
|
writeClaim: () => writeClaim
|
|
147962
148495
|
});
|
|
147963
|
-
import { createHash as
|
|
148496
|
+
import { createHash as createHash10, randomUUID as randomUUID13 } from "crypto";
|
|
147964
148497
|
function compactText2(value, field) {
|
|
147965
148498
|
if (typeof value !== "string") throw new Error("Claim " + field + " must be text");
|
|
147966
148499
|
const sanitized = sanitizeCredentials(value).trim().replace(/\s+/g, " ");
|
|
@@ -147972,7 +148505,7 @@ function normalizedTerm(value) {
|
|
|
147972
148505
|
return compactText2(value, "identity").toLocaleLowerCase("en-US");
|
|
147973
148506
|
}
|
|
147974
148507
|
function hashIdentity(parts) {
|
|
147975
|
-
return
|
|
148508
|
+
return createHash10("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
|
|
147976
148509
|
}
|
|
147977
148510
|
function buildClaimIdentity(input) {
|
|
147978
148511
|
const subject = normalizedTerm(input.subject);
|
|
@@ -148046,7 +148579,7 @@ function normalizeClaimInput(input) {
|
|
|
148046
148579
|
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
148047
148580
|
return {
|
|
148048
148581
|
claim: {
|
|
148049
|
-
id:
|
|
148582
|
+
id: randomUUID13(),
|
|
148050
148583
|
projectId,
|
|
148051
148584
|
subject,
|
|
148052
148585
|
predicate,
|
|
@@ -148213,7 +148746,7 @@ function supersedeClaim(store, input) {
|
|
|
148213
148746
|
});
|
|
148214
148747
|
}
|
|
148215
148748
|
function hashObservation(observation) {
|
|
148216
|
-
return
|
|
148749
|
+
return createHash10("sha256").update(JSON.stringify([
|
|
148217
148750
|
observation.title,
|
|
148218
148751
|
observation.narrative,
|
|
148219
148752
|
observation.facts,
|
|
@@ -148457,11 +148990,11 @@ var init_frontmatter = __esm({
|
|
|
148457
148990
|
});
|
|
148458
148991
|
|
|
148459
148992
|
// src/knowledge/markdown.ts
|
|
148460
|
-
import { createHash as
|
|
148993
|
+
import { createHash as createHash11 } from "crypto";
|
|
148461
148994
|
import { promises as fs13 } from "fs";
|
|
148462
148995
|
import path21 from "path";
|
|
148463
148996
|
function hashContent(content) {
|
|
148464
|
-
return
|
|
148997
|
+
return createHash11("sha256").update(content).digest("hex");
|
|
148465
148998
|
}
|
|
148466
148999
|
function stringField(data, key) {
|
|
148467
149000
|
const value = data[key];
|
|
@@ -148587,11 +149120,11 @@ __export(wiki_exports, {
|
|
|
148587
149120
|
lintKnowledgeWorkspace: () => lintKnowledgeWorkspace,
|
|
148588
149121
|
readKnowledgePage: () => readKnowledgePage
|
|
148589
149122
|
});
|
|
148590
|
-
import { createHash as
|
|
149123
|
+
import { createHash as createHash12 } from "crypto";
|
|
148591
149124
|
import { promises as fs14 } from "fs";
|
|
148592
149125
|
import path22 from "path";
|
|
148593
149126
|
function hash2(value) {
|
|
148594
|
-
return
|
|
149127
|
+
return createHash12("sha256").update(value).digest("hex");
|
|
148595
149128
|
}
|
|
148596
149129
|
function now() {
|
|
148597
149130
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -149135,7 +149668,7 @@ var workflow_store_exports = {};
|
|
|
149135
149668
|
__export(workflow_store_exports, {
|
|
149136
149669
|
WorkflowStore: () => WorkflowStore
|
|
149137
149670
|
});
|
|
149138
|
-
import { randomUUID as
|
|
149671
|
+
import { randomUUID as randomUUID14 } from "crypto";
|
|
149139
149672
|
function parseJson(value, fallback) {
|
|
149140
149673
|
if (typeof value !== "string" || !value) return fallback;
|
|
149141
149674
|
try {
|
|
@@ -149235,7 +149768,7 @@ var init_workflow_store = __esm({
|
|
|
149235
149768
|
}
|
|
149236
149769
|
recordRun(input) {
|
|
149237
149770
|
const run = {
|
|
149238
|
-
id:
|
|
149771
|
+
id: randomUUID14(),
|
|
149239
149772
|
workflowId: input.workflowId,
|
|
149240
149773
|
projectId: input.projectId,
|
|
149241
149774
|
task: input.task.trim(),
|
|
@@ -149313,7 +149846,7 @@ var init_outcome_types = __esm({
|
|
|
149313
149846
|
});
|
|
149314
149847
|
|
|
149315
149848
|
// src/knowledge/outcome-store.ts
|
|
149316
|
-
import { randomUUID as
|
|
149849
|
+
import { randomUUID as randomUUID15 } from "crypto";
|
|
149317
149850
|
function optionalText5(value) {
|
|
149318
149851
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
149319
149852
|
}
|
|
@@ -149357,7 +149890,7 @@ var init_outcome_store = __esm({
|
|
|
149357
149890
|
}
|
|
149358
149891
|
record(input) {
|
|
149359
149892
|
const signal = {
|
|
149360
|
-
id:
|
|
149893
|
+
id: randomUUID15(),
|
|
149361
149894
|
projectId: text(input.projectId, "project id"),
|
|
149362
149895
|
candidateKind: oneOf(input.candidateKind, MEMORY_OUTCOME_CANDIDATE_KINDS, "candidate kind"),
|
|
149363
149896
|
candidateId: text(input.candidateId, "candidate id"),
|
|
@@ -149784,11 +150317,11 @@ __export(workflows_exports, {
|
|
|
149784
150317
|
syncCanonicalWorkflows: () => syncCanonicalWorkflows,
|
|
149785
150318
|
writeCanonicalWorkflow: () => writeCanonicalWorkflow
|
|
149786
150319
|
});
|
|
149787
|
-
import { createHash as
|
|
150320
|
+
import { createHash as createHash13 } from "crypto";
|
|
149788
150321
|
import { promises as fs15 } from "fs";
|
|
149789
150322
|
import path23 from "path";
|
|
149790
150323
|
function hash3(value) {
|
|
149791
|
-
return
|
|
150324
|
+
return createHash13("sha256").update(value).digest("hex");
|
|
149792
150325
|
}
|
|
149793
150326
|
function now2() {
|
|
149794
150327
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -151185,6 +151718,16 @@ async function bindObservationCodeRefsBestEffort(observation) {
|
|
|
151185
151718
|
} catch {
|
|
151186
151719
|
}
|
|
151187
151720
|
}
|
|
151721
|
+
async function persistEvidenceCard(observation) {
|
|
151722
|
+
if (!projectDir) return;
|
|
151723
|
+
try {
|
|
151724
|
+
const evidence = new EvidenceCardStore();
|
|
151725
|
+
await evidence.init(projectDir);
|
|
151726
|
+
evidence.upsertObservation(observation);
|
|
151727
|
+
} catch (error) {
|
|
151728
|
+
console.error(`[memorix] Evidence card projection failed for obs-${observation.id}: ${error instanceof Error ? error.message : String(error)}`);
|
|
151729
|
+
}
|
|
151730
|
+
}
|
|
151188
151731
|
function queueClaimDerivation(observation) {
|
|
151189
151732
|
const dataDir = projectDir;
|
|
151190
151733
|
const isExplicit = observation.sourceDetail === "explicit";
|
|
@@ -151531,6 +152074,7 @@ async function storeObservation(input) {
|
|
|
151531
152074
|
}
|
|
151532
152075
|
if (!persistedCallbackInvoked) await input.onPersisted?.(observation);
|
|
151533
152076
|
await bindObservationCodeRefsBestEffort(observation);
|
|
152077
|
+
await persistEvidenceCard(observation);
|
|
151534
152078
|
queueObservationQualification(observation);
|
|
151535
152079
|
if (resolveObservationVisibility(observation) === "project") {
|
|
151536
152080
|
queueClaimDerivation(observation);
|
|
@@ -151623,6 +152167,7 @@ async function upsertObservation(existing, input, now3) {
|
|
|
151623
152167
|
await store.update(existing);
|
|
151624
152168
|
}
|
|
151625
152169
|
await bindObservationCodeRefsBestEffort(existing);
|
|
152170
|
+
await persistEvidenceCard(existing);
|
|
151626
152171
|
queueObservationQualification(existing);
|
|
151627
152172
|
if (resolveObservationVisibility(existing) === "project") {
|
|
151628
152173
|
queueClaimDerivation(existing);
|
|
@@ -151756,6 +152301,7 @@ async function resolveObservations(ids, status = "resolved") {
|
|
|
151756
152301
|
await Promise.all(changed.map((observation) => tx.update(observation)));
|
|
151757
152302
|
});
|
|
151758
152303
|
}
|
|
152304
|
+
for (const observation of changed) await persistEvidenceCard(observation);
|
|
151759
152305
|
return { resolved, notFound };
|
|
151760
152306
|
}
|
|
151761
152307
|
function getProjectObservations(projectId) {
|
|
@@ -152093,6 +152639,7 @@ var init_observations = __esm({
|
|
|
152093
152639
|
init_secret_filter();
|
|
152094
152640
|
init_lifecycle();
|
|
152095
152641
|
init_visibility();
|
|
152642
|
+
init_evidence_store();
|
|
152096
152643
|
observations = [];
|
|
152097
152644
|
nextId = 1;
|
|
152098
152645
|
projectDir = null;
|
|
@@ -155772,7 +156319,7 @@ var compaction_checkpoint_store_exports = {};
|
|
|
155772
156319
|
__export(compaction_checkpoint_store_exports, {
|
|
155773
156320
|
CompactionCheckpointStore: () => CompactionCheckpointStore
|
|
155774
156321
|
});
|
|
155775
|
-
import { createHash as
|
|
156322
|
+
import { createHash as createHash15, randomUUID as randomUUID16 } from "crypto";
|
|
155776
156323
|
function optionalText7(value) {
|
|
155777
156324
|
return typeof value === "string" && value ? value : void 0;
|
|
155778
156325
|
}
|
|
@@ -155814,7 +156361,7 @@ function sourceKeyFor(input, summary) {
|
|
|
155814
156361
|
input.tokensBefore ?? "",
|
|
155815
156362
|
input.firstKeptEntryId ?? ""
|
|
155816
156363
|
].join("\0");
|
|
155817
|
-
return `derived:${
|
|
156364
|
+
return `derived:${createHash15("sha256").update(material).digest("hex").slice(0, 32)}`;
|
|
155818
156365
|
}
|
|
155819
156366
|
function rowToCheckpoint(row) {
|
|
155820
156367
|
return {
|
|
@@ -155873,7 +156420,7 @@ var init_compaction_checkpoint_store = __esm({
|
|
|
155873
156420
|
if (pending) return rowToCheckpoint(pending);
|
|
155874
156421
|
const now3 = input.capturedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
155875
156422
|
const checkpoint = {
|
|
155876
|
-
id:
|
|
156423
|
+
id: randomUUID16(),
|
|
155877
156424
|
projectId: input.projectId,
|
|
155878
156425
|
sessionId: input.sessionId,
|
|
155879
156426
|
agent: input.agent,
|
|
@@ -155881,7 +156428,7 @@ var init_compaction_checkpoint_store = __esm({
|
|
|
155881
156428
|
captureKind: "preflight",
|
|
155882
156429
|
reason: safeReason(input.reason),
|
|
155883
156430
|
sourceEvent: input.sourceEvent,
|
|
155884
|
-
sourceKey: `pre:${
|
|
156431
|
+
sourceKey: `pre:${randomUUID16()}`,
|
|
155885
156432
|
transcriptAvailable: Boolean(input.transcriptAvailable),
|
|
155886
156433
|
status: "active",
|
|
155887
156434
|
preCapturedAt: now3,
|
|
@@ -155947,7 +156494,7 @@ var init_compaction_checkpoint_store = __esm({
|
|
|
155947
156494
|
return this.get(checkpoint2.id);
|
|
155948
156495
|
}
|
|
155949
156496
|
const checkpoint = {
|
|
155950
|
-
id:
|
|
156497
|
+
id: randomUUID16(),
|
|
155951
156498
|
projectId: input.projectId,
|
|
155952
156499
|
sessionId: input.sessionId,
|
|
155953
156500
|
agent: input.agent,
|
|
@@ -157311,7 +157858,7 @@ __export(team_store_exports, {
|
|
|
157311
157858
|
isTeamStoreInitialized: () => isTeamStoreInitialized,
|
|
157312
157859
|
resetTeamStore: () => resetTeamStore
|
|
157313
157860
|
});
|
|
157314
|
-
import { randomUUID as
|
|
157861
|
+
import { randomUUID as randomUUID17 } from "crypto";
|
|
157315
157862
|
import path30 from "path";
|
|
157316
157863
|
import fs18 from "fs";
|
|
157317
157864
|
function getTeamStore() {
|
|
@@ -157600,7 +158147,7 @@ var init_team_store = __esm({
|
|
|
157600
158147
|
* reactivate it (preserving agent_id). Otherwise create a new one.
|
|
157601
158148
|
*/
|
|
157602
158149
|
registerAgent(input) {
|
|
157603
|
-
const instanceId = input.instanceId ||
|
|
158150
|
+
const instanceId = input.instanceId || randomUUID17();
|
|
157604
158151
|
const now3 = Date.now();
|
|
157605
158152
|
const existing = this.stmtAgentFindByInstance.get(
|
|
157606
158153
|
input.projectId,
|
|
@@ -157626,7 +158173,7 @@ var init_team_store = __esm({
|
|
|
157626
158173
|
this.eventBus?.emit("agent:joined", { agentId: row2.agent_id, projectId: input.projectId, agentType: input.agentType });
|
|
157627
158174
|
return row2;
|
|
157628
158175
|
}
|
|
157629
|
-
const agentId =
|
|
158176
|
+
const agentId = randomUUID17();
|
|
157630
158177
|
this.stmtAgentUpsert.run({
|
|
157631
158178
|
agent_id: agentId,
|
|
157632
158179
|
project_id: input.projectId,
|
|
@@ -157728,7 +158275,7 @@ var init_team_store = __esm({
|
|
|
157728
158275
|
return { error: `Recipient agent '${input.recipientAgentId}' not found \u2014 cannot send to unknown agent` };
|
|
157729
158276
|
}
|
|
157730
158277
|
}
|
|
157731
|
-
const id =
|
|
158278
|
+
const id = randomUUID17();
|
|
157732
158279
|
const now3 = Date.now();
|
|
157733
158280
|
const row = {
|
|
157734
158281
|
id,
|
|
@@ -157778,7 +158325,7 @@ var init_team_store = __esm({
|
|
|
157778
158325
|
// Task Operations (with atomic claim semantics)
|
|
157779
158326
|
// ═══════════════════════════════════════════════════════════════════
|
|
157780
158327
|
createTask(input) {
|
|
157781
|
-
const taskId =
|
|
158328
|
+
const taskId = randomUUID17();
|
|
157782
158329
|
const now3 = Date.now();
|
|
157783
158330
|
const row = {
|
|
157784
158331
|
task_id: taskId,
|
|
@@ -158050,7 +158597,7 @@ var init_team_store = __esm({
|
|
|
158050
158597
|
for (const [agentId, msgs] of Object.entries(snap.messages.inboxes)) {
|
|
158051
158598
|
for (const msg of msgs) {
|
|
158052
158599
|
this.stmtMsgInsert.run({
|
|
158053
|
-
id: msg.id ??
|
|
158600
|
+
id: msg.id ?? randomUUID17(),
|
|
158054
158601
|
project_id: "migrated",
|
|
158055
158602
|
sender_agent_id: msg.from ?? "unknown",
|
|
158056
158603
|
recipient_agent_id: msg.to === "__broadcast__" ? null : msg.to ?? agentId,
|
|
@@ -158921,6 +159468,23 @@ var init_maintenance = __esm({
|
|
|
158921
159468
|
}
|
|
158922
159469
|
});
|
|
158923
159470
|
|
|
159471
|
+
// src/dashboard/config-provenance.ts
|
|
159472
|
+
function resolveDashboardKeySource({ value, envKeys, configSource }) {
|
|
159473
|
+
for (const envKey of envKeys) {
|
|
159474
|
+
const envValue = process.env[envKey];
|
|
159475
|
+
if (envValue !== value) continue;
|
|
159476
|
+
return getLoadedEnvValue(envKey) === envValue ? ".env" : `env:${envKey}`;
|
|
159477
|
+
}
|
|
159478
|
+
return configSource;
|
|
159479
|
+
}
|
|
159480
|
+
var init_config_provenance = __esm({
|
|
159481
|
+
"src/dashboard/config-provenance.ts"() {
|
|
159482
|
+
"use strict";
|
|
159483
|
+
init_esm_shims();
|
|
159484
|
+
init_dotenv_loader();
|
|
159485
|
+
}
|
|
159486
|
+
});
|
|
159487
|
+
|
|
158924
159488
|
// src/dashboard/project-classification.ts
|
|
158925
159489
|
var project_classification_exports = {};
|
|
158926
159490
|
__export(project_classification_exports, {
|
|
@@ -159700,6 +160264,20 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
159700
160264
|
sendJson(res, observations2);
|
|
159701
160265
|
break;
|
|
159702
160266
|
}
|
|
160267
|
+
case "/evidence": {
|
|
160268
|
+
const observations2 = filterDashboardObservations(
|
|
160269
|
+
await getObservationStore().loadByProject(effectiveProjectId, { status: "active" }),
|
|
160270
|
+
effectiveProjectId
|
|
160271
|
+
);
|
|
160272
|
+
const evidenceStore = new EvidenceCardStore();
|
|
160273
|
+
await evidenceStore.init(effectiveDataDir);
|
|
160274
|
+
evidenceStore.syncObservations(observations2);
|
|
160275
|
+
const query = url.searchParams.get("q") || "";
|
|
160276
|
+
const limit2 = Number(url.searchParams.get("limit") || 20);
|
|
160277
|
+
const cards = evidenceStore.list(effectiveProjectId, { limit: Math.min(100, Math.max(1, limit2)) }).filter((card) => !query || [card.title, card.summary, card.sourceRef, card.locator ?? ""].join(" ").toLowerCase().includes(query.toLowerCase()));
|
|
160278
|
+
sendJson(res, { cards, projectId: effectiveProjectId });
|
|
160279
|
+
break;
|
|
160280
|
+
}
|
|
159703
160281
|
case "/sessions": {
|
|
159704
160282
|
const allSessions = await getSessionStore().loadAll();
|
|
159705
160283
|
const sessions = filterByProject(allSessions, effectiveProjectId);
|
|
@@ -159747,8 +160325,13 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
159747
160325
|
filesModified: o.filesModified
|
|
159748
160326
|
}));
|
|
159749
160327
|
const retentionReferenceTime = new Date(now3);
|
|
160328
|
+
const feedback = new MemoryFeedbackStore();
|
|
160329
|
+
await feedback.init(effectiveDataDir).catch(() => void 0);
|
|
159750
160330
|
const retention = summarizeRetentionProjections(
|
|
159751
|
-
observations2.filter((observation) => observation.type !== "probe").map((observation) => projectObservationRetention(observation, {
|
|
160331
|
+
observations2.filter((observation) => observation.type !== "probe").map((observation) => projectObservationRetention(observation, {
|
|
160332
|
+
referenceTime: retentionReferenceTime,
|
|
160333
|
+
feedback: feedback.getState(effectiveProjectId, "observation", String(observation.id))
|
|
160334
|
+
}))
|
|
159752
160335
|
);
|
|
159753
160336
|
const retentionSummary = {
|
|
159754
160337
|
active: retention.active,
|
|
@@ -159842,9 +160425,14 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
159842
160425
|
effectiveProjectId
|
|
159843
160426
|
);
|
|
159844
160427
|
const referenceTime = /* @__PURE__ */ new Date();
|
|
160428
|
+
const feedback = new MemoryFeedbackStore();
|
|
160429
|
+
await feedback.init(effectiveDataDir).catch(() => void 0);
|
|
159845
160430
|
const rows = observations2.filter((observation) => observation.type !== "probe").map((observation) => ({
|
|
159846
160431
|
observation,
|
|
159847
|
-
retention: projectObservationRetention(observation, {
|
|
160432
|
+
retention: projectObservationRetention(observation, {
|
|
160433
|
+
referenceTime,
|
|
160434
|
+
feedback: feedback.getState(effectiveProjectId, "observation", String(observation.id))
|
|
160435
|
+
})
|
|
159848
160436
|
})).sort((a, b) => b.retention.displayScore - a.retention.displayScore);
|
|
159849
160437
|
const summary = summarizeRetentionProjections(rows.map((row) => row.retention));
|
|
159850
160438
|
const scored = rows.map(({ observation, retention }) => ({
|
|
@@ -159915,23 +160503,13 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
159915
160503
|
const os6 = await import("os");
|
|
159916
160504
|
const { existsSync: existsSync21 } = await import("fs");
|
|
159917
160505
|
const { join: join25 } = await import("path");
|
|
159918
|
-
let yml = {};
|
|
159919
160506
|
const configProjectRoot = effectiveProjectRoot;
|
|
159920
|
-
|
|
159921
|
-
const { loadYamlConfig: loadYamlConfig2 } = await Promise.resolve().then(() => (init_yaml_loader(), yaml_loader_exports));
|
|
159922
|
-
yml = configProjectRoot ? loadYamlConfig2(configProjectRoot) : loadYamlConfig2(null);
|
|
159923
|
-
} catch {
|
|
159924
|
-
}
|
|
159925
|
-
if (configProjectRoot) {
|
|
159926
|
-
try {
|
|
159927
|
-
const { loadDotenv: loadDotenv2 } = await Promise.resolve().then(() => (init_dotenv_loader(), dotenv_loader_exports));
|
|
159928
|
-
loadDotenv2(configProjectRoot);
|
|
159929
|
-
} catch {
|
|
159930
|
-
}
|
|
159931
|
-
}
|
|
160507
|
+
const resolved = getResolvedConfig({ projectRoot: configProjectRoot });
|
|
159932
160508
|
const files = {
|
|
159933
160509
|
"project memorix.yml": { exists: false, path: "", unavailable: !configProjectRoot },
|
|
159934
160510
|
"user memorix.yml": { exists: false, path: "" },
|
|
160511
|
+
"project memorix.toml": { exists: false, path: "", unavailable: !configProjectRoot },
|
|
160512
|
+
"user config.toml": { exists: false, path: "" },
|
|
159935
160513
|
"project .env": { exists: false, path: "", unavailable: !configProjectRoot },
|
|
159936
160514
|
"user .env": { exists: false, path: "" },
|
|
159937
160515
|
"legacy config.json": { exists: false, path: "" }
|
|
@@ -159941,6 +160519,8 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
159941
160519
|
const paths = {
|
|
159942
160520
|
"project memorix.yml": configProjectRoot ? join25(configProjectRoot, "memorix.yml") : null,
|
|
159943
160521
|
"user memorix.yml": join25(home, ".memorix", "memorix.yml"),
|
|
160522
|
+
"project memorix.toml": configProjectRoot ? join25(configProjectRoot, "memorix.toml") : null,
|
|
160523
|
+
"user config.toml": join25(home, ".memorix", "config.toml"),
|
|
159944
160524
|
"project .env": configProjectRoot ? join25(configProjectRoot, ".env") : null,
|
|
159945
160525
|
"user .env": join25(home, ".memorix", ".env"),
|
|
159946
160526
|
"legacy config.json": join25(home, ".memorix", "config.json")
|
|
@@ -159955,67 +160535,61 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
159955
160535
|
} catch {
|
|
159956
160536
|
}
|
|
159957
160537
|
const values = [];
|
|
159958
|
-
const
|
|
159959
|
-
|
|
159960
|
-
|
|
159961
|
-
|
|
159962
|
-
|
|
159963
|
-
|
|
159964
|
-
|
|
159965
|
-
|
|
159966
|
-
|
|
159967
|
-
|
|
159968
|
-
|
|
159969
|
-
|
|
159970
|
-
|
|
159971
|
-
|
|
159972
|
-
|
|
159973
|
-
|
|
159974
|
-
|
|
160538
|
+
const tomlSource = configProjectRoot && files["project memorix.toml"].exists ? "memorix.toml" : files["user config.toml"].exists ? "config.toml" : "default";
|
|
160539
|
+
const legacySource = files["project memorix.yml"].exists || files["user memorix.yml"].exists ? "memorix.yml" : files["legacy config.json"].exists ? "config.json" : "default";
|
|
160540
|
+
const configSource = resolved.sources.toml.length > 0 ? tomlSource : resolved.sources.legacy.length > 0 ? legacySource : "default";
|
|
160541
|
+
const source = (envKey) => resolveDashboardKeySource({
|
|
160542
|
+
value: process.env[envKey] ?? "",
|
|
160543
|
+
envKeys: [envKey],
|
|
160544
|
+
configSource
|
|
160545
|
+
});
|
|
160546
|
+
if (resolved.memory.llm.provider) values.push({ key: "llm.provider", value: resolved.memory.llm.provider, source: source("MEMORIX_LLM_PROVIDER") });
|
|
160547
|
+
if (resolved.memory.llm.model) values.push({ key: "llm.model", value: resolved.memory.llm.model, source: source("MEMORIX_LLM_MODEL") });
|
|
160548
|
+
const llmKey = resolved.memory.llm.apiKey;
|
|
160549
|
+
const memoryKeyEnv = [
|
|
160550
|
+
"MEMORIX_LLM_API_KEY",
|
|
160551
|
+
"MEMORIX_API_KEY",
|
|
160552
|
+
"OPENAI_API_KEY",
|
|
160553
|
+
"ANTHROPIC_API_KEY",
|
|
160554
|
+
...resolved.memory.llm.provider === "openrouter" || resolved.memory.llm.baseUrl?.includes("openrouter.ai") ? ["OPENROUTER_API_KEY"] : []
|
|
160555
|
+
];
|
|
159975
160556
|
if (llmKey) {
|
|
159976
|
-
|
|
159977
|
-
if (process.env.MEMORIX_LLM_API_KEY) src = await getEnvSource("MEMORIX_LLM_API_KEY");
|
|
159978
|
-
else if (process.env.MEMORIX_API_KEY) src = await getEnvSource("MEMORIX_API_KEY");
|
|
159979
|
-
else if (yml.llm?.apiKey) src = "memorix.yml (move to .env!)";
|
|
159980
|
-
else if (process.env.OPENAI_API_KEY) src = await getEnvSource("OPENAI_API_KEY");
|
|
160557
|
+
const src = resolveDashboardKeySource({ value: llmKey, envKeys: memoryKeyEnv, configSource });
|
|
159981
160558
|
values.push({ key: "llm.apiKey", value: "****" + llmKey.slice(-4), source: src, sensitive: true });
|
|
159982
160559
|
} else {
|
|
159983
160560
|
values.push({ key: "llm.apiKey", value: "not set", source: "none" });
|
|
159984
160561
|
}
|
|
159985
|
-
|
|
159986
|
-
|
|
159987
|
-
|
|
159988
|
-
|
|
159989
|
-
|
|
159990
|
-
|
|
159991
|
-
|
|
159992
|
-
}
|
|
159993
|
-
const agentModel = process.env.MEMORIX_AGENT_MODEL || process.env.MEMORIX_AGENT_LLM_MODEL || yml.agent?.model;
|
|
159994
|
-
if (agentModel) {
|
|
159995
|
-
let source;
|
|
159996
|
-
if (process.env.MEMORIX_AGENT_MODEL) source = await getEnvSource("MEMORIX_AGENT_MODEL");
|
|
159997
|
-
else if (process.env.MEMORIX_AGENT_LLM_MODEL) source = `${await getEnvSource("MEMORIX_AGENT_LLM_MODEL")} (legacy)`;
|
|
159998
|
-
else source = yml.agent?.model ? "memorix.yml" : "default";
|
|
159999
|
-
values.push({ key: "agent.model", value: agentModel, source });
|
|
160000
|
-
}
|
|
160001
|
-
const agentKey = process.env.MEMORIX_AGENT_API_KEY || process.env.MEMORIX_AGENT_LLM_API_KEY || yml.agent?.apiKey;
|
|
160562
|
+
if (resolved.agent.provider) {
|
|
160563
|
+
values.push({ key: "agent.provider", value: resolved.agent.provider, source: source("MEMORIX_AGENT_PROVIDER") });
|
|
160564
|
+
}
|
|
160565
|
+
if (resolved.agent.model) {
|
|
160566
|
+
values.push({ key: "agent.model", value: resolved.agent.model, source: source("MEMORIX_AGENT_MODEL") });
|
|
160567
|
+
}
|
|
160568
|
+
const agentKey = resolved.agent.apiKey;
|
|
160002
160569
|
if (agentKey) {
|
|
160003
|
-
|
|
160004
|
-
|
|
160005
|
-
|
|
160006
|
-
|
|
160570
|
+
const src = resolveDashboardKeySource({
|
|
160571
|
+
value: agentKey,
|
|
160572
|
+
envKeys: ["MEMORIX_AGENT_API_KEY", "MEMORIX_AGENT_LLM_API_KEY"],
|
|
160573
|
+
configSource
|
|
160574
|
+
});
|
|
160007
160575
|
values.push({ key: "agent.apiKey", value: "****" + agentKey.slice(-4), source: src, sensitive: true });
|
|
160008
160576
|
} else {
|
|
160009
|
-
values.push({
|
|
160010
|
-
|
|
160011
|
-
|
|
160012
|
-
|
|
160013
|
-
|
|
160014
|
-
|
|
160015
|
-
|
|
160016
|
-
if (
|
|
160017
|
-
|
|
160018
|
-
|
|
160577
|
+
values.push({
|
|
160578
|
+
key: "agent.apiKey",
|
|
160579
|
+
value: "fallback to llm.apiKey",
|
|
160580
|
+
source: llmKey ? resolveDashboardKeySource({ value: llmKey, envKeys: memoryKeyEnv, configSource }) : "default"
|
|
160581
|
+
});
|
|
160582
|
+
}
|
|
160583
|
+
values.push({ key: "embedding.provider", value: resolved.embedding.provider || "off", source: source("MEMORIX_EMBEDDING") });
|
|
160584
|
+
if (resolved.embedding.model) values.push({ key: "embedding.model", value: resolved.embedding.model, source: source("MEMORIX_EMBEDDING_MODEL") });
|
|
160585
|
+
if (resolved.rerank.provider !== "off") {
|
|
160586
|
+
values.push({ key: "rerank.provider", value: resolved.rerank.provider, source: source("MEMORIX_RERANK_PROVIDER") });
|
|
160587
|
+
if (resolved.rerank.model) values.push({ key: "rerank.model", value: resolved.rerank.model, source: source("MEMORIX_RERANK_MODEL") });
|
|
160588
|
+
}
|
|
160589
|
+
values.push({ key: "git.autoHook", value: String(resolved.git.autoHook ?? false), source: configSource });
|
|
160590
|
+
values.push({ key: "git.skipMergeCommits", value: String(resolved.git.skipMergeCommits ?? true), source: configSource });
|
|
160591
|
+
values.push({ key: "server.transport", value: resolved.server.transport || "stdio", source: configSource });
|
|
160592
|
+
values.push({ key: "server.dashboard", value: String(resolved.server.dashboard ?? true), source: configSource });
|
|
160019
160593
|
sendJson(res, { files, values });
|
|
160020
160594
|
break;
|
|
160021
160595
|
}
|
|
@@ -160463,10 +161037,14 @@ var init_server = __esm({
|
|
|
160463
161037
|
init_dotenv_loader();
|
|
160464
161038
|
init_yaml_loader();
|
|
160465
161039
|
init_yaml_loader();
|
|
161040
|
+
init_resolved_config();
|
|
160466
161041
|
init_graph_scope();
|
|
160467
161042
|
init_retention();
|
|
160468
161043
|
init_visibility();
|
|
161044
|
+
init_evidence_store();
|
|
161045
|
+
init_feedback();
|
|
160469
161046
|
init_maintenance();
|
|
161047
|
+
init_config_provenance();
|
|
160470
161048
|
MIME_TYPES = {
|
|
160471
161049
|
".html": "text/html; charset=utf-8",
|
|
160472
161050
|
".css": "text/css; charset=utf-8",
|
|
@@ -160934,7 +161512,7 @@ __export(planner_exports, {
|
|
|
160934
161512
|
materializeTaskGraph: () => materializeTaskGraph,
|
|
160935
161513
|
seedAutonomousPipeline: () => seedAutonomousPipeline
|
|
160936
161514
|
});
|
|
160937
|
-
import { randomUUID as
|
|
161515
|
+
import { randomUUID as randomUUID18 } from "crypto";
|
|
160938
161516
|
function isPlannerTask(metadata) {
|
|
160939
161517
|
if (!metadata) return null;
|
|
160940
161518
|
try {
|
|
@@ -160992,7 +161570,7 @@ function seedAutonomousPipeline(teamStore, projectId, config, opts) {
|
|
|
160992
161570
|
const maxIterations = config.maxIterations ?? 3;
|
|
160993
161571
|
const taskBudget = config.taskBudget ?? 15;
|
|
160994
161572
|
const structuredPlan = opts?.structuredPlan ?? true;
|
|
160995
|
-
const pipelineId =
|
|
161573
|
+
const pipelineId = randomUUID18();
|
|
160996
161574
|
const meta = {
|
|
160997
161575
|
plannerType: "plan",
|
|
160998
161576
|
pipelineId,
|
|
@@ -161664,8 +162242,8 @@ var init_official_skills = __esm({
|
|
|
161664
162242
|
"",
|
|
161665
162243
|
"| Situation | Prefer | CLI fallback |",
|
|
161666
162244
|
"|---|---|---|",
|
|
161667
|
-
'| Starting a coding task and needing the best task-lensed project map | `memorix_project_context` with the user\'s task | `memorix context "<task>" --brief-json` |',
|
|
161668
|
-
'| Continuing prior project work | `memorix_project_context` with the user\'s task | `memorix resume "<task>" --brief-json` |',
|
|
162245
|
+
'| Starting a coding task and needing the best task-lensed project map | `memorix_project_context` with the user\'s task | `memorix context "<task>" --fallback --brief-json` |',
|
|
162246
|
+
'| Continuing prior project work | `memorix_project_context` with the user\'s task | `memorix resume "<task>" --fallback --brief-json` |',
|
|
161669
162247
|
'| Need structured refs/freshness for code-bound memories | `memorix_context_pack` | `memorix codegraph context-pack --task "<topic>"` |',
|
|
161670
162248
|
'| Explicit memory graph question | `memorix_graph_context` | `memorix memory graph-context --query "<topic>"` |',
|
|
161671
162249
|
'| Specific past decision, bug, file, or change | `memorix_search` | `memorix memory search --query "<topic>"` |',
|
|
@@ -161678,7 +162256,7 @@ var init_official_skills = __esm({
|
|
|
161678
162256
|
"",
|
|
161679
162257
|
"- Default first step for non-trivial coding work: call `memorix_project_context` before progress files, dev-log reads, ad-hoc file reads, or git archaeology. Pass the user's actual task so Memorix can choose a bugfix, feature, release, onboarding, refactor, docs, test, or general brief. Start by reading its suggested files.",
|
|
161680
162258
|
"- In Claude Code headless/print-mode, an initial MCP `pending` status is not a failure by itself. Prefer MCP first: use the client's tool discovery/dynamic loading to find `memorix_project_context` when it is not in the first visible tool list.",
|
|
161681
|
-
'- Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run `memorix resume "<task>" --brief-json` exactly once before inspecting files, Git history, progress notes, or guessing. The absence of `.memorix` or visible memory files never proves project memory is empty. For a new task, use `memorix context "<task>" --brief-json` instead. Use `--json` only when a diagnostic needs the detailed legacy payload. If that one command fails, report it and proceed normally; do not probe help, enumerate commands, or chain broad searches.',
|
|
162259
|
+
'- Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run `memorix resume "<task>" --fallback --brief-json` exactly once before inspecting files, Git history, progress notes, or guessing. The absence of `.memorix` or visible memory files never proves project memory is empty. For a new task, use `memorix context "<task>" --fallback --brief-json` instead. Use `--json` only when a diagnostic needs the detailed legacy payload. If that one command fails, report it and proceed normally; do not probe help, enumerate commands, or chain broad searches.',
|
|
161682
162260
|
"- After a successful `memorix_project_context`, the brief is the default retrieval boundary. Do not call more Memorix retrieval tools after a complete brief. Use Context Pack, search, or detail only when the brief lacks a specific reference, freshness field, or fact needed for the task, or when the user explicitly asks for deeper history. In MCP, name that missing fact in `purpose` when intentionally expanding beyond the brief. Do not retrieve the same decision twice just to confirm an already-complete brief.",
|
|
161683
162261
|
"- If the user asks for read-only work or says not to modify files, do not call `memorix_store` just to record an assessment. Store only when the user explicitly asks to preserve it.",
|
|
161684
162262
|
"- Use `memorix_search` for a specific decision, bug, file, or prior change that the project context did not answer. Fetch detail only for a result you still need after the brief.",
|
|
@@ -162937,7 +163515,7 @@ alwaysApply: true
|
|
|
162937
163515
|
"",
|
|
162938
163516
|
`Default first step for non-trivial coding work: call \`memorix_project_context\` with the user's actual task before progress files, dev-log reads, ad-hoc file reads, or git archaeology. Memorix will choose a task-lensed brief (bugfix, feature, release, onboarding, refactor, docs, test, or general). When the task is continuing prior work, the same brief also includes a bounded prior-work projection. Treat its "Start here" files as the first ${contextNoun} files to inspect.`,
|
|
162939
163517
|
"",
|
|
162940
|
-
'If the MCP tool is not visible yet but the client supports tool discovery or dynamic loading, search/select `memorix_project_context` first. Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run exactly one CLI brief with the user\'s real task before inspecting files, Git history, progress notes, or guessing: `memorix resume "<task>" --brief-json`. For a new task, use `memorix context "<task>" --brief-json` instead. The absence of `.memorix` or visible memory files never proves project memory is empty. Use `--json` only when a diagnostic needs the detailed legacy payload. If that one command fails, report it and proceed normally. Do not probe help, enumerate commands, chain broad searches, wait indefinitely on MCP startup, or hand-write tool-call syntax.',
|
|
163518
|
+
'If the MCP tool is not visible yet but the client supports tool discovery or dynamic loading, search/select `memorix_project_context` first. Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run exactly one CLI brief with the user\'s real task before inspecting files, Git history, progress notes, or guessing: `memorix resume "<task>" --fallback --brief-json`. For a new task, use `memorix context "<task>" --fallback --brief-json` instead. The absence of `.memorix` or visible memory files never proves project memory is empty. Use `--json` only when a diagnostic needs the detailed legacy payload. If that one command fails, report it and proceed normally. Do not probe help, enumerate commands, chain broad searches, wait indefinitely on MCP startup, or hand-write tool-call syntax.',
|
|
162941
163519
|
"",
|
|
162942
163520
|
"After a successful `memorix_project_context` result, the brief is the default retrieval boundary. Do not call more Memorix retrieval tools after a complete brief. Use `memorix_context_pack`, `memorix_search`, or `memorix_detail` only when the brief lacks a specific reference, freshness field, or fact needed for the task, or when the user explicitly asks for deeper history. In MCP, name that missing fact in `purpose` when intentionally expanding beyond the brief. Do not retrieve the same decision twice just to confirm an already-complete brief.",
|
|
162943
163521
|
"If the user asks for read-only work or says not to modify files, do not call `memorix_store` just to record an assessment. Store only when the user explicitly asks to preserve it.",
|
|
@@ -163240,7 +163818,7 @@ init_freshness();
|
|
|
163240
163818
|
init_obs_store();
|
|
163241
163819
|
init_mini_skill_store();
|
|
163242
163820
|
init_session_store();
|
|
163243
|
-
import { createHash as
|
|
163821
|
+
import { createHash as createHash16 } from "crypto";
|
|
163244
163822
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
163245
163823
|
import { z as z626 } from "zod";
|
|
163246
163824
|
|
|
@@ -163720,6 +164298,8 @@ init_mini_skill_store();
|
|
|
163720
164298
|
init_mini_skills();
|
|
163721
164299
|
init_secret_filter();
|
|
163722
164300
|
init_visibility();
|
|
164301
|
+
init_persistence();
|
|
164302
|
+
init_feedback();
|
|
163723
164303
|
function normalizeMemoryBrowseQuery(query) {
|
|
163724
164304
|
const trimmed = query.trim();
|
|
163725
164305
|
if (!trimmed) return "";
|
|
@@ -163757,9 +164337,27 @@ function normalizeMemoryBrowseQuery(query) {
|
|
|
163757
164337
|
async function compactSearch(options, surface = "mcp") {
|
|
163758
164338
|
await ensureFreshIndex();
|
|
163759
164339
|
const searchOptions = { ...options, query: normalizeMemoryBrowseQuery(options.query) };
|
|
163760
|
-
|
|
164340
|
+
let entries = (await searchObservations(searchOptions)).map(
|
|
163761
164341
|
(entry) => entry.projectId || !options.projectId ? entry : { ...entry, projectId: options.projectId }
|
|
163762
164342
|
);
|
|
164343
|
+
if (options.projectId) {
|
|
164344
|
+
try {
|
|
164345
|
+
const feedback = new MemoryFeedbackStore();
|
|
164346
|
+
await feedback.init(await getProjectDataDir(options.projectId));
|
|
164347
|
+
const states = feedback.weights(options.projectId, "observation");
|
|
164348
|
+
entries = entries.map((entry) => {
|
|
164349
|
+
const state = states.get(String(entry.id));
|
|
164350
|
+
if (!state) return entry;
|
|
164351
|
+
return {
|
|
164352
|
+
...entry,
|
|
164353
|
+
score: (entry.score ?? 0) * feedbackWeightMultiplier(state.weight),
|
|
164354
|
+
feedbackWeight: state.weight,
|
|
164355
|
+
feedbackStatus: state.status
|
|
164356
|
+
};
|
|
164357
|
+
}).filter((entry) => entry.feedbackStatus !== "archived" || options.status === "all").sort((a, b) => (b.score ?? 0) - (a.score ?? 0));
|
|
164358
|
+
} catch {
|
|
164359
|
+
}
|
|
164360
|
+
}
|
|
163763
164361
|
let formatted = formatIndexTable(entries, searchOptions.query, !options.projectId, surface);
|
|
163764
164362
|
if (entries.length === 0 && options.projectId) {
|
|
163765
164363
|
const allObservations = filterReadableObservations(getAllObservations(), options.reader);
|
|
@@ -164588,6 +165186,8 @@ init_detector();
|
|
|
164588
165186
|
init_launch_root();
|
|
164589
165187
|
init_aliases();
|
|
164590
165188
|
init_persistence();
|
|
165189
|
+
init_evidence_store();
|
|
165190
|
+
init_feedback();
|
|
164591
165191
|
|
|
164592
165192
|
// src/rules/syncer.ts
|
|
164593
165193
|
init_esm_shims();
|
|
@@ -164600,9 +165200,9 @@ init_frontmatter();
|
|
|
164600
165200
|
|
|
164601
165201
|
// src/rules/utils.ts
|
|
164602
165202
|
init_esm_shims();
|
|
164603
|
-
import { createHash as
|
|
165203
|
+
import { createHash as createHash14 } from "crypto";
|
|
164604
165204
|
function hashContent2(content) {
|
|
164605
|
-
return
|
|
165205
|
+
return createHash14("sha256").update(content.trim()).digest("hex").substring(0, 16);
|
|
164606
165206
|
}
|
|
164607
165207
|
function generateRuleId(source, filePath) {
|
|
164608
165208
|
const sanitized = filePath.replace(/[\/\\]/g, "-").replace(/^\./, "");
|
|
@@ -166804,6 +167404,10 @@ var TOOL_PROFILES = Object.freeze({
|
|
|
166804
167404
|
// multimodal support to one additional schema rather than enabling lite.
|
|
166805
167405
|
memorix_session_start: ["micro", "lite", "team", "full"],
|
|
166806
167406
|
memorix_media: ["micro", "lite", "team", "full"],
|
|
167407
|
+
// Evidence and feedback are deliberate operator/context-control surfaces;
|
|
167408
|
+
// keep the default micro profile at its nine-tool token budget.
|
|
167409
|
+
memorix_evidence: ["lite", "team", "full"],
|
|
167410
|
+
memorix_feedback: ["lite", "team", "full"],
|
|
166807
167411
|
// ── lite: extended solo memory surface ────────────────────────────
|
|
166808
167412
|
memorix_graph_context: ["lite", "team", "full"],
|
|
166809
167413
|
memorix_timeline: ["lite", "team", "full"],
|
|
@@ -167102,7 +167706,7 @@ function coerceObjectArray(val) {
|
|
|
167102
167706
|
return [];
|
|
167103
167707
|
}
|
|
167104
167708
|
function createDeterministicInstanceId(projectId, agentType, agentName) {
|
|
167105
|
-
const digest2 =
|
|
167709
|
+
const digest2 = createHash16("sha256").update(projectId).update("\n").update(agentType).update("\n").update(agentName ?? "").digest("hex").slice(0, 24);
|
|
167106
167710
|
return `auto-${digest2}`;
|
|
167107
167711
|
}
|
|
167108
167712
|
var BOOTSTRAP_SAFE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
@@ -167403,7 +168007,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
167403
168007
|
};
|
|
167404
168008
|
const server = existingServer ?? new McpServer({
|
|
167405
168009
|
name: "memorix",
|
|
167406
|
-
version: true ? "1.
|
|
168010
|
+
version: true ? "1.8.0" : "1.0.1"
|
|
167407
168011
|
});
|
|
167408
168012
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
167409
168013
|
server.registerTool = ((name, ...args) => {
|
|
@@ -170582,7 +171186,7 @@ ${json2}
|
|
|
170582
171186
|
dashboardRunning = true;
|
|
170583
171187
|
const { exec: execCmd } = await import("child_process");
|
|
170584
171188
|
const openCmd = process.platform === "win32" ? `start "" "${url}"` : process.platform === "darwin" ? `open "${url}"` : `xdg-open "${url}"`;
|
|
170585
|
-
execCmd(openCmd, () => {
|
|
171189
|
+
execCmd(openCmd, { windowsHide: true }, () => {
|
|
170586
171190
|
});
|
|
170587
171191
|
return {
|
|
170588
171192
|
content: [{
|
|
@@ -170606,6 +171210,113 @@ ${json2}
|
|
|
170606
171210
|
}
|
|
170607
171211
|
}
|
|
170608
171212
|
);
|
|
171213
|
+
server.registerTool(
|
|
171214
|
+
"memorix_evidence",
|
|
171215
|
+
{
|
|
171216
|
+
title: "Evidence Cards",
|
|
171217
|
+
description: "Inspect the bounded, project-scoped provenance cards behind Memorix context. Use list for a compact index, get/events for one source, sync to repair the projection, and stale when known source files changed. Cards expose sourceRef, locator, capturedHash, and freshness.",
|
|
171218
|
+
inputSchema: {
|
|
171219
|
+
action: z626.enum(["list", "get", "sync", "stale", "events"]).describe("Evidence operation"),
|
|
171220
|
+
candidateKind: z626.enum(["observation", "code", "git", "test", "document", "workflow", "graph"]).optional().default("observation"),
|
|
171221
|
+
candidateId: z626.string().optional().describe("Candidate id, usually an observation id"),
|
|
171222
|
+
query: z626.string().optional().describe("Optional title/source query for list"),
|
|
171223
|
+
paths: z626.array(z626.string()).max(200).optional().describe("Changed source paths for stale"),
|
|
171224
|
+
reason: z626.string().max(500).optional().describe("Why evidence became stale"),
|
|
171225
|
+
limit: z626.number().int().positive().max(100).optional().default(20)
|
|
171226
|
+
}
|
|
171227
|
+
},
|
|
171228
|
+
async ({ action, candidateKind, candidateId, query, paths, reason, limit: limit2 }) => {
|
|
171229
|
+
const unresolved = requireResolvedProject("inspect evidence cards for the current project");
|
|
171230
|
+
if (unresolved) return unresolved;
|
|
171231
|
+
const cards = new EvidenceCardStore();
|
|
171232
|
+
await cards.init(projectDir2);
|
|
171233
|
+
if (action === "sync") {
|
|
171234
|
+
const observations2 = await getObservationStore().loadByProject(project.id);
|
|
171235
|
+
const synced = cards.syncObservations(observations2);
|
|
171236
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, synced: synced.length, cards: synced.slice(0, limit2 ?? 20) }, null, 2) }] };
|
|
171237
|
+
}
|
|
171238
|
+
if (action === "stale") {
|
|
171239
|
+
const changed = cards.markStaleForPaths(project.id, paths ?? [], reason ?? "source file changed");
|
|
171240
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, staleMarked: changed, paths: paths ?? [] }, null, 2) }] };
|
|
171241
|
+
}
|
|
171242
|
+
if (action === "get") {
|
|
171243
|
+
if (!candidateId?.trim()) return { content: [{ type: "text", text: "candidateId is required for evidence get." }], isError: true };
|
|
171244
|
+
const card = cards.get(project.id, candidateKind ?? "observation", candidateId.trim());
|
|
171245
|
+
if (!card) return { content: [{ type: "text", text: "Evidence card not found." }], isError: true };
|
|
171246
|
+
return { content: [{ type: "text", text: JSON.stringify({ card, events: cards.listEvents(card.id), projectId: project.id }, null, 2) }] };
|
|
171247
|
+
}
|
|
171248
|
+
if (action === "events") {
|
|
171249
|
+
if (!candidateId?.trim()) return { content: [{ type: "text", text: "candidateId is required for evidence events." }], isError: true };
|
|
171250
|
+
const card = cards.get(project.id, candidateKind ?? "observation", candidateId.trim());
|
|
171251
|
+
if (!card) return { content: [{ type: "text", text: "Evidence card not found." }], isError: true };
|
|
171252
|
+
return { content: [{ type: "text", text: JSON.stringify(cards.listEvents(card.id, limit2), null, 2) }] };
|
|
171253
|
+
}
|
|
171254
|
+
const needle = query?.trim().toLowerCase();
|
|
171255
|
+
const listed = cards.list(project.id, { limit: Math.max(limit2 ?? 20, 100) }).filter((card) => !needle || [card.title, card.summary, card.sourceRef, card.locator ?? ""].join(" ").toLowerCase().includes(needle)).slice(0, limit2 ?? 20);
|
|
171256
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, cards: listed }, null, 2) }] };
|
|
171257
|
+
}
|
|
171258
|
+
);
|
|
171259
|
+
server.registerTool(
|
|
171260
|
+
"memorix_feedback",
|
|
171261
|
+
{
|
|
171262
|
+
title: "Memory Feedback",
|
|
171263
|
+
description: "Record or inspect auditable memory outcomes. Positive verification/use strengthens recall; correction, conflict, source change, or weaken lowers it. Use revoke with targetEventId to undo one prior signal without deleting audit history.",
|
|
171264
|
+
inputSchema: {
|
|
171265
|
+
action: z626.enum(["record", "show", "audit"]).describe("Feedback operation"),
|
|
171266
|
+
candidateKind: z626.enum(["observation", "claim", "durable-memory", "workflow"]).optional().default("observation"),
|
|
171267
|
+
candidateId: z626.string().describe("Memory or knowledge candidate id"),
|
|
171268
|
+
signal: z626.enum(["user-correction", "verification-success", "verification-failure", "code-change", "used", "not-used", "code-conflict", "strengthen", "weaken", "revoke"]).optional(),
|
|
171269
|
+
sourceRef: z626.string().max(500).optional().describe("Source of this feedback, such as test:run-42 or user:chat"),
|
|
171270
|
+
actor: z626.string().max(200).optional(),
|
|
171271
|
+
note: z626.string().max(2e3).optional(),
|
|
171272
|
+
targetEventId: z626.string().optional().describe("Existing event id when action=record and signal=revoke"),
|
|
171273
|
+
limit: z626.number().int().positive().max(200).optional().default(100)
|
|
171274
|
+
}
|
|
171275
|
+
},
|
|
171276
|
+
async ({ action, candidateKind, candidateId, signal, sourceRef, actor, note, targetEventId, limit: limit2 }) => {
|
|
171277
|
+
const unresolved = requireResolvedProject("record memory feedback for the current project");
|
|
171278
|
+
if (unresolved) return unresolved;
|
|
171279
|
+
const feedback = new MemoryFeedbackStore();
|
|
171280
|
+
await feedback.init(projectDir2);
|
|
171281
|
+
const kind = candidateKind ?? "observation";
|
|
171282
|
+
if (action === "show") {
|
|
171283
|
+
return { content: [{ type: "text", text: JSON.stringify(feedback.getState(project.id, kind, candidateId), null, 2) }] };
|
|
171284
|
+
}
|
|
171285
|
+
if (action === "audit") {
|
|
171286
|
+
return { content: [{ type: "text", text: JSON.stringify(feedback.audit(project.id, kind, candidateId, limit2), null, 2) }] };
|
|
171287
|
+
}
|
|
171288
|
+
if (!signal || !sourceRef?.trim()) {
|
|
171289
|
+
return { content: [{ type: "text", text: "record requires signal and sourceRef." }], isError: true };
|
|
171290
|
+
}
|
|
171291
|
+
try {
|
|
171292
|
+
const result = feedback.record({
|
|
171293
|
+
projectId: project.id,
|
|
171294
|
+
candidateKind: kind,
|
|
171295
|
+
candidateId,
|
|
171296
|
+
signal,
|
|
171297
|
+
sourceRef,
|
|
171298
|
+
...actor || currentAgentId ? { actor: actor ?? currentAgentId } : {},
|
|
171299
|
+
...note ? { note } : {},
|
|
171300
|
+
...targetEventId ? { targetEventId } : {}
|
|
171301
|
+
});
|
|
171302
|
+
if (kind === "observation") {
|
|
171303
|
+
const cards = new EvidenceCardStore();
|
|
171304
|
+
await cards.init(projectDir2);
|
|
171305
|
+
const card = cards.get(project.id, "observation", candidateId);
|
|
171306
|
+
if (card) {
|
|
171307
|
+
const verification = signal === "verification-success" || signal === "strengthen" ? "verified" : signal === "user-correction" || signal === "code-conflict" || signal === "weaken" ? "conflicted" : card.verification;
|
|
171308
|
+
cards.recordEvent(project.id, card.id, `feedback:${signal}`, note);
|
|
171309
|
+
if (verification !== card.verification) {
|
|
171310
|
+
cards.setVerification(project.id, card.id, verification);
|
|
171311
|
+
}
|
|
171312
|
+
}
|
|
171313
|
+
}
|
|
171314
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
171315
|
+
} catch (error) {
|
|
171316
|
+
return { content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }], isError: true };
|
|
171317
|
+
}
|
|
171318
|
+
}
|
|
171319
|
+
);
|
|
170609
171320
|
if (teamFeaturesEnabled) {
|
|
170610
171321
|
const { initTeamStore: initTeamStore2 } = await Promise.resolve().then(() => (init_team_store(), team_store_exports));
|
|
170611
171322
|
initTeamStoreForProject = initTeamStore2;
|