memorix 1.4.1 → 1.4.2

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/dist/index.js CHANGED
@@ -312,7 +312,7 @@ function closeAllDatabases() {
312
312
  _dbCache.delete(key);
313
313
  }
314
314
  }
315
- 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_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_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;
315
+ 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;
316
316
  var init_sqlite_db = __esm({
317
317
  "src/store/sqlite-db.ts"() {
318
318
  "use strict";
@@ -578,6 +578,17 @@ CREATE TABLE IF NOT EXISTS observation_code_refs (
578
578
  " UNIQUE(projectId, sourceEpoch)",
579
579
  ");"
580
580
  ].join("\n");
581
+ CREATE_CODE_STATE_SNAPSHOT_FILES_TABLE = [
582
+ "CREATE TABLE IF NOT EXISTS code_state_snapshot_files (",
583
+ " snapshotId TEXT NOT NULL,",
584
+ " projectId TEXT NOT NULL,",
585
+ " fileId TEXT NOT NULL,",
586
+ " path TEXT NOT NULL,",
587
+ " contentHash TEXT NOT NULL,",
588
+ " PRIMARY KEY (snapshotId, path),",
589
+ " FOREIGN KEY (snapshotId) REFERENCES code_state_snapshots(id) ON DELETE CASCADE",
590
+ ");"
591
+ ].join("\n");
581
592
  CREATE_KNOWLEDGE_CLAIMS_TABLE = `
582
593
  CREATE TABLE IF NOT EXISTS knowledge_claims (
583
594
  id TEXT PRIMARY KEY,
@@ -788,6 +799,19 @@ CREATE TABLE IF NOT EXISTS long_term_memory_events (
788
799
  createdAt TEXT NOT NULL,
789
800
  FOREIGN KEY (memoryId) REFERENCES long_term_memories(id) ON DELETE CASCADE
790
801
  );
802
+ `;
803
+ CREATE_MEMORY_OUTCOME_SIGNALS_TABLE = `
804
+ CREATE TABLE IF NOT EXISTS memory_outcome_signals (
805
+ id TEXT PRIMARY KEY,
806
+ projectId TEXT NOT NULL,
807
+ candidateKind TEXT NOT NULL,
808
+ candidateId TEXT NOT NULL,
809
+ kind TEXT NOT NULL,
810
+ sourceRef TEXT NOT NULL,
811
+ snapshotId TEXT,
812
+ detail TEXT,
813
+ observedAt TEXT NOT NULL
814
+ );
791
815
  `;
792
816
  CREATE_MEDIA_ASSETS_TABLE = `
793
817
  CREATE TABLE IF NOT EXISTS media_assets (
@@ -1030,6 +1054,20 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
1030
1054
  db2.exec("CREATE INDEX IF NOT EXISTS idx_code_edges_snapshot ON code_edges(projectId, snapshotId)");
1031
1055
  }
1032
1056
  },
1057
+ {
1058
+ id: "1.4-codegraph-snapshot-manifest",
1059
+ apply: (db2) => {
1060
+ db2.exec(CREATE_CODE_STATE_SNAPSHOT_FILES_TABLE);
1061
+ db2.exec("CREATE INDEX IF NOT EXISTS idx_code_snapshot_files_project_path ON code_state_snapshot_files(projectId, path)");
1062
+ }
1063
+ },
1064
+ {
1065
+ id: "1.4-memory-outcome-signals",
1066
+ apply: (db2) => {
1067
+ db2.exec(CREATE_MEMORY_OUTCOME_SIGNALS_TABLE);
1068
+ db2.exec("CREATE INDEX IF NOT EXISTS idx_memory_outcomes_candidate ON memory_outcome_signals(projectId, candidateKind, candidateId, observedAt DESC)");
1069
+ }
1070
+ },
1033
1071
  {
1034
1072
  id: "1.2-knowledge-claim-ledger",
1035
1073
  apply: (db2) => {
@@ -2224,17 +2262,17 @@ var init_mini_skill_store = __esm({
2224
2262
 
2225
2263
  // src/compact/token-budget.ts
2226
2264
  import { countTokens, isWithinTokenLimit } from "gpt-tokenizer";
2227
- function countTextTokens(text) {
2228
- return countTokens(text);
2265
+ function countTextTokens(text2) {
2266
+ return countTokens(text2);
2229
2267
  }
2230
- function fitsInBudget(text, limit2) {
2231
- return isWithinTokenLimit(text, limit2);
2268
+ function fitsInBudget(text2, limit2) {
2269
+ return isWithinTokenLimit(text2, limit2);
2232
2270
  }
2233
- function truncateToTokenBudget(text, budget) {
2234
- if (fitsInBudget(text, budget) !== false) {
2235
- return text;
2271
+ function truncateToTokenBudget(text2, budget) {
2272
+ if (fitsInBudget(text2, budget) !== false) {
2273
+ return text2;
2236
2274
  }
2237
- const sentences = text.split(/(?<=[.!?])\s+/);
2275
+ const sentences = text2.split(/(?<=[.!?])\s+/);
2238
2276
  let result = "";
2239
2277
  for (const sentence of sentences) {
2240
2278
  const candidate = result ? `${result} ${sentence}` : sentence;
@@ -2245,12 +2283,12 @@ function truncateToTokenBudget(text, budget) {
2245
2283
  }
2246
2284
  if (!result) {
2247
2285
  const estimatedChars = budget * 2;
2248
- result = text.slice(0, estimatedChars);
2286
+ result = text2.slice(0, estimatedChars);
2249
2287
  while (fitsInBudget(result, budget) === false && result.length > 0) {
2250
2288
  result = result.slice(0, Math.floor(result.length * 0.9));
2251
2289
  }
2252
- if (result.length < text.length) {
2253
- const nextCharacter = text.charAt(result.length);
2290
+ if (result.length < text2.length) {
2291
+ const nextCharacter = text2.charAt(result.length);
2254
2292
  if (nextCharacter && !/[\s.,;:!?)}\]]/.test(nextCharacter)) {
2255
2293
  const boundary = result.search(/\s+\S*$/);
2256
2294
  result = boundary > 0 ? result.slice(0, boundary).trimEnd() : "";
@@ -3434,8 +3472,8 @@ import { createHash } from "crypto";
3434
3472
  import { readFile, writeFile, mkdir } from "fs/promises";
3435
3473
  import { join as join2 } from "path";
3436
3474
  import { homedir as homedir6 } from "os";
3437
- function textHash(text) {
3438
- return createHash("sha256").update(text).digest("hex").slice(0, 16);
3475
+ function textHash(text2) {
3476
+ return createHash("sha256").update(text2).digest("hex").slice(0, 16);
3439
3477
  }
3440
3478
  async function loadDiskCache() {
3441
3479
  try {
@@ -3498,11 +3536,11 @@ var init_fastembed_provider = __esm({
3498
3536
  async embedInputs(inputs, options = {}) {
3499
3537
  return Promise.all(inputs.map((input) => this.embedInput(input, options)));
3500
3538
  }
3501
- async embed(text) {
3502
- const hash4 = textHash(text);
3539
+ async embed(text2) {
3540
+ const hash4 = textHash(text2);
3503
3541
  const cached = cache.get(hash4);
3504
3542
  if (cached) return cached;
3505
- const raw = await this.model.queryEmbed(text);
3543
+ const raw = await this.model.queryEmbed(text2);
3506
3544
  const result = Array.from(raw);
3507
3545
  if (result.length !== this.dimensions) {
3508
3546
  throw new Error(`Expected ${this.dimensions}d embedding, got ${result.length}d`);
@@ -3598,10 +3636,10 @@ var init_transformers_provider = __esm({
3598
3636
  async embedInputs(inputs, options = {}) {
3599
3637
  return Promise.all(inputs.map((input) => this.embedInput(input, options)));
3600
3638
  }
3601
- async embed(text) {
3602
- const cached = cache2.get(text);
3639
+ async embed(text2) {
3640
+ const cached = cache2.get(text2);
3603
3641
  if (cached) return cached;
3604
- const output = await this.extractor(text, {
3642
+ const output = await this.extractor(text2, {
3605
3643
  pooling: "mean",
3606
3644
  normalize: true
3607
3645
  });
@@ -3609,7 +3647,7 @@ var init_transformers_provider = __esm({
3609
3647
  if (result.length !== this.dimensions) {
3610
3648
  throw new Error(`Expected ${this.dimensions}d embedding, got ${result.length}d`);
3611
3649
  }
3612
- this.cacheSet(text, result);
3650
+ this.cacheSet(text2, result);
3613
3651
  return result;
3614
3652
  }
3615
3653
  async embedBatch(texts) {
@@ -3672,8 +3710,8 @@ function dimsCacheFile() {
3672
3710
  function cacheMetaFile() {
3673
3711
  return join3(cacheDir(), ".embedding-api-cache-meta.json");
3674
3712
  }
3675
- function normalizeText(text) {
3676
- return text.replace(/\s+/g, " ").trim().slice(0, MAX_INPUT_CHARS);
3713
+ function normalizeText(text2) {
3714
+ return text2.replace(/\s+/g, " ").trim().slice(0, MAX_INPUT_CHARS);
3677
3715
  }
3678
3716
  function cacheNamespace(config) {
3679
3717
  return [
@@ -3683,8 +3721,8 @@ function cacheNamespace(config) {
3683
3721
  config.requestedDimensions ?? "native"
3684
3722
  ].join("|");
3685
3723
  }
3686
- function textHash2(text, namespace) {
3687
- return createHash2("sha256").update(`${namespace}\0${text}`).digest("hex").slice(0, 16);
3724
+ function textHash2(text2, namespace) {
3725
+ return createHash2("sha256").update(`${namespace}\0${text2}`).digest("hex").slice(0, 16);
3688
3726
  }
3689
3727
  function inputIdentity(input, options = {}) {
3690
3728
  return JSON.stringify({
@@ -4096,8 +4134,8 @@ var init_api_provider = __esm({
4096
4134
  if (!embedding) throw new Error("API probe returned no embeddings; check model name and API key");
4097
4135
  return embedding.length;
4098
4136
  }
4099
- async embed(text, options) {
4100
- const normalized = normalizeText(text);
4137
+ async embed(text2, options) {
4138
+ const normalized = normalizeText(text2);
4101
4139
  if (isNativeGeminiEndpoint(this.config.baseUrl)) {
4102
4140
  return this.embedInput({ modality: "text", text: normalized }, { intent: "document", ...options });
4103
4141
  }
@@ -4154,7 +4192,7 @@ var init_api_provider = __esm({
4154
4192
  }
4155
4193
  async embedBatch(texts, options) {
4156
4194
  if (isNativeGeminiEndpoint(this.config.baseUrl)) {
4157
- return Promise.all(texts.map((text) => this.embedInput({ modality: "text", text }, { intent: "document", ...options })));
4195
+ return Promise.all(texts.map((text2) => this.embedInput({ modality: "text", text: text2 }, { intent: "document", ...options })));
4158
4196
  }
4159
4197
  await ensureDiskCacheLoaded();
4160
4198
  const normalizedTexts = texts.map(normalizeText);
@@ -4233,8 +4271,8 @@ var init_api_provider = __esm({
4233
4271
  }
4234
4272
  async getCachedEmbeddings(texts) {
4235
4273
  await ensureDiskCacheLoaded();
4236
- return texts.map((text) => {
4237
- const hash4 = textHash2(normalizeText(text), this.cacheKeyNamespace);
4274
+ return texts.map((text2) => {
4275
+ const hash4 = textHash2(normalizeText(text2), this.cacheKeyNamespace);
4238
4276
  return cache3.get(hash4) ?? null;
4239
4277
  });
4240
4278
  }
@@ -4464,9 +4502,9 @@ function wrapProvider(candidate) {
4464
4502
  return {
4465
4503
  name: candidate.name,
4466
4504
  dimensions: candidate.dimensions,
4467
- async embed(text, options) {
4505
+ async embed(text2, options) {
4468
4506
  try {
4469
- return await candidate.embed(text, options);
4507
+ return await candidate.embed(text2, options);
4470
4508
  } catch (error) {
4471
4509
  if (kind === "api" && getEmbeddingMode2() === "auto" && isTemporaryEmbeddingFailure(error)) {
4472
4510
  warnOnce("[memorix] API embedding temporarily unavailable \u2014 switching to local fallback provider");
@@ -4474,7 +4512,7 @@ function wrapProvider(candidate) {
4474
4512
  if (fallback) {
4475
4513
  provider = wrapProvider(fallback);
4476
4514
  warnOnce(`[memorix] Embedding fallback activated: ${provider.name} (${provider.dimensions}d)`);
4477
- return provider.embed(text, options);
4515
+ return provider.embed(text2, options);
4478
4516
  }
4479
4517
  }
4480
4518
  if (isTemporaryEmbeddingFailure(error)) {
@@ -5033,8 +5071,8 @@ async function readResponseText(response, signal, maxBytes = MAX_LLM_RESPONSE_BY
5033
5071
  }
5034
5072
  }
5035
5073
  async function readResponseJson(response, signal, maxBytes = MAX_LLM_RESPONSE_BYTES) {
5036
- const text = await readResponseText(response, signal, maxBytes);
5037
- return JSON.parse(text);
5074
+ const text2 = await readResponseText(response, signal, maxBytes);
5075
+ return JSON.parse(text2);
5038
5076
  }
5039
5077
  async function* callLLMWithToolsStream(messages, tools) {
5040
5078
  if (!currentConfig) {
@@ -5587,8 +5625,8 @@ function isCjkHeavy(query) {
5587
5625
  const cjkCount = (query.match(CJK_PATTERN) || []).length;
5588
5626
  return query.length > 0 && cjkCount / query.length > 0.3;
5589
5627
  }
5590
- function normalizeExpansion(text) {
5591
- return text.trim().replace(/^[-*]\s*/, "").replace(/^["'`]+|["'`]+$/g, "").split(/\r?\n/)[0].trim();
5628
+ function normalizeExpansion(text2) {
5629
+ return text2.trim().replace(/^[-*]\s*/, "").replace(/^["'`]+|["'`]+$/g, "").split(/\r?\n/)[0].trim();
5592
5630
  }
5593
5631
  async function maybeExpandSearchQuery(query) {
5594
5632
  if (!query || !isCjkHeavy(query) || COMMAND_LIKE_QUERY.test(query)) {
@@ -5951,9 +5989,9 @@ function shouldSkipCompression(narrative, type) {
5951
5989
  if (specialChars / narrative.length > 0.35) return true;
5952
5990
  return false;
5953
5991
  }
5954
- function estimateTokens(text) {
5955
- const cjkChars = (text.match(/[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]/g) || []).length;
5956
- const otherChars = text.length - cjkChars;
5992
+ function estimateTokens(text2) {
5993
+ const cjkChars = (text2.match(/[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]/g) || []).length;
5994
+ const otherChars = text2.length - cjkChars;
5957
5995
  return Math.ceil(cjkChars / 1.5 + otherChars / 4);
5958
5996
  }
5959
5997
  var COMPRESS_PROMPT, COMPRESS_PROMPT_GENTLE, RERANK_PROMPT, SKIP_PATTERNS, LOW_COMPRESSION_TYPES;
@@ -6256,10 +6294,10 @@ function isEmbeddingEnabled() {
6256
6294
  function getVectorDimensions() {
6257
6295
  return embeddingEnabled ? embeddingDimensions : null;
6258
6296
  }
6259
- async function generateEmbedding(text) {
6297
+ async function generateEmbedding(text2) {
6260
6298
  const provider2 = await getEmbeddingProvider();
6261
6299
  if (!provider2) return null;
6262
- return provider2.embedInput ? provider2.embedInput({ modality: "text", text }, { intent: "document" }) : provider2.embed(text);
6300
+ return provider2.embedInput ? provider2.embedInput({ modality: "text", text: text2 }, { intent: "document" }) : provider2.embed(text2);
6263
6301
  }
6264
6302
  async function generateEmbeddingInput(input, options = {}) {
6265
6303
  const provider2 = await getEmbeddingProvider();
@@ -7591,9 +7629,9 @@ var init_entity_extractor = __esm({
7591
7629
  });
7592
7630
 
7593
7631
  // src/memory/secret-filter.ts
7594
- function applyRedaction(text) {
7595
- if (!text) return text;
7596
- let out = text;
7632
+ function applyRedaction(text2) {
7633
+ if (!text2) return text2;
7634
+ let out = text2;
7597
7635
  out = out.replace(
7598
7636
  /((?:password|passwd|pwd|secret|token|api[_-]?key|auth[_-]?key|access[_-]?key|private[_-]?key|client[_-]?secret)\s*[:=]\s*["']?)([^\s"',;\n]{6,})/gi,
7599
7637
  "$1[REDACTED]"
@@ -7607,11 +7645,11 @@ function applyRedaction(text) {
7607
7645
  out = out.replace(/\beyJ[A-Za-z0-9._-]{40,}\b/g, "[REDACTED]");
7608
7646
  return out;
7609
7647
  }
7610
- function sanitizeCredentials(text) {
7611
- return applyRedaction(text);
7648
+ function sanitizeCredentials(text2) {
7649
+ return applyRedaction(text2);
7612
7650
  }
7613
- function redactCredentials(text) {
7614
- return applyRedaction(text);
7651
+ function redactCredentials(text2) {
7652
+ return applyRedaction(text2);
7615
7653
  }
7616
7654
  var init_secret_filter = __esm({
7617
7655
  "src/memory/secret-filter.ts"() {
@@ -7662,8 +7700,8 @@ function clampPositiveInteger(value, fallback) {
7662
7700
  return Math.max(1, Math.floor(value));
7663
7701
  }
7664
7702
  function errorText(error) {
7665
- const text = error instanceof Error ? error.message : String(error);
7666
- return sanitizeCredentials(text).slice(0, MAX_ERROR_LENGTH);
7703
+ const text2 = error instanceof Error ? error.message : String(error);
7704
+ return sanitizeCredentials(text2).slice(0, MAX_ERROR_LENGTH);
7667
7705
  }
7668
7706
  function normalizedKinds(kinds) {
7669
7707
  if (!kinds) return void 0;
@@ -8757,9 +8795,9 @@ __export(consolidation_exports, {
8757
8795
  executeConsolidation: () => executeConsolidation,
8758
8796
  findConsolidationCandidates: () => findConsolidationCandidates
8759
8797
  });
8760
- function tokenize(text) {
8798
+ function tokenize(text2) {
8761
8799
  return new Set(
8762
- text.toLowerCase().replace(/[^a-z0-9\u4e00-\u9fff\s-]/g, " ").split(/\s+/).filter((t2) => t2.length > 1)
8800
+ text2.toLowerCase().replace(/[^a-z0-9\u4e00-\u9fff\s-]/g, " ").split(/\s+/).filter((t2) => t2.length > 1)
8763
8801
  );
8764
8802
  }
8765
8803
  function jaccardSimilarity(a, b) {
@@ -17911,8 +17949,8 @@ var init_headers = __esm({
17911
17949
  });
17912
17950
 
17913
17951
  // packages/ai/dist/utils/sanitize-unicode.js
17914
- function sanitizeSurrogates(text) {
17915
- return text.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "");
17952
+ function sanitizeSurrogates(text2) {
17953
+ return text2.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "");
17916
17954
  }
17917
17955
  var init_sanitize_unicode = __esm({
17918
17956
  "packages/ai/dist/utils/sanitize-unicode.js"() {
@@ -18394,9 +18432,9 @@ var init_values = __esm({
18394
18432
  }
18395
18433
  return n;
18396
18434
  };
18397
- safeJSON = (text) => {
18435
+ safeJSON = (text2) => {
18398
18436
  try {
18399
- return JSON.parse(text);
18437
+ return JSON.parse(text2);
18400
18438
  } catch (err) {
18401
18439
  return void 0;
18402
18440
  }
@@ -19559,8 +19597,8 @@ async function defaultParseResponse(client, props) {
19559
19597
  const json2 = await response.json();
19560
19598
  return addRequestID(json2, response);
19561
19599
  }
19562
- const text = await response.text();
19563
- return text;
19600
+ const text2 = await response.text();
19601
+ return text2;
19564
19602
  })();
19565
19603
  loggerFor(client).debug(`[${requestLogID}] response parsed`, formatRequestDetails({
19566
19604
  retryOfRequestLogID,
@@ -45178,9 +45216,9 @@ var init_values2 = __esm({
45178
45216
  }
45179
45217
  return n;
45180
45218
  };
45181
- safeJSON2 = (text) => {
45219
+ safeJSON2 = (text2) => {
45182
45220
  try {
45183
- return JSON.parse(text);
45221
+ return JSON.parse(text2);
45184
45222
  } catch (err) {
45185
45223
  return void 0;
45186
45224
  }
@@ -45954,8 +45992,8 @@ async function defaultParseResponse2(client, props) {
45954
45992
  const json2 = await response.json();
45955
45993
  return addRequestID2(json2, response);
45956
45994
  }
45957
- const text = await response.text();
45958
- return text;
45995
+ const text2 = await response.text();
45996
+ return text2;
45959
45997
  })();
45960
45998
  loggerFor2(client).debug(`[${requestLogID}] response parsed`, formatRequestDetails2({
45961
45999
  retryOfRequestLogID,
@@ -52548,9 +52586,9 @@ function decodeSseLine(line, state) {
52548
52586
  }
52549
52587
  return null;
52550
52588
  }
52551
- function nextLineBreakIndex(text) {
52552
- const carriageReturnIndex = text.indexOf("\r");
52553
- const newlineIndex = text.indexOf("\n");
52589
+ function nextLineBreakIndex(text2) {
52590
+ const carriageReturnIndex = text2.indexOf("\r");
52591
+ const newlineIndex = text2.indexOf("\n");
52554
52592
  if (carriageReturnIndex === -1) {
52555
52593
  return newlineIndex;
52556
52594
  }
@@ -52559,18 +52597,18 @@ function nextLineBreakIndex(text) {
52559
52597
  }
52560
52598
  return Math.min(carriageReturnIndex, newlineIndex);
52561
52599
  }
52562
- function consumeLine(text) {
52563
- const lineBreakIndex = nextLineBreakIndex(text);
52600
+ function consumeLine(text2) {
52601
+ const lineBreakIndex = nextLineBreakIndex(text2);
52564
52602
  if (lineBreakIndex === -1) {
52565
52603
  return null;
52566
52604
  }
52567
52605
  let nextIndex = lineBreakIndex + 1;
52568
- if (text[lineBreakIndex] === "\r" && text[nextIndex] === "\n") {
52606
+ if (text2[lineBreakIndex] === "\r" && text2[nextIndex] === "\n") {
52569
52607
  nextIndex += 1;
52570
52608
  }
52571
52609
  return {
52572
- line: text.slice(0, lineBreakIndex),
52573
- rest: text.slice(nextIndex)
52610
+ line: text2.slice(0, lineBreakIndex),
52611
+ rest: text2.slice(nextIndex)
52574
52612
  };
52575
52613
  }
52576
52614
  async function* iterateSseMessages(body, signal) {
@@ -54737,8 +54775,8 @@ var require_common = __commonJS({
54737
54775
  }
54738
54776
  function redactString(obj, key) {
54739
54777
  if (typeof obj === "object" && obj !== null && typeof obj[key] === "string") {
54740
- const text = obj[key];
54741
- if (/grant_type=/i.test(text) || /assertion=/i.test(text) || /secret/i.test(text)) {
54778
+ const text2 = obj[key];
54779
+ if (/grant_type=/i.test(text2) || /assertion=/i.test(text2) || /secret/i.test(text2)) {
54742
54780
  obj[key] = REDACT;
54743
54781
  }
54744
54782
  }
@@ -61566,8 +61604,8 @@ var init_body = __esm({
61566
61604
  * @return Promise
61567
61605
  */
61568
61606
  async json() {
61569
- const text = await this.text();
61570
- return JSON.parse(text);
61607
+ const text2 = await this.text();
61608
+ return JSON.parse(text2);
61571
61609
  }
61572
61610
  /**
61573
61611
  * Decode response as text
@@ -62719,7 +62757,7 @@ var require_gaxios = __commonJS({
62719
62757
  var retry_js_1 = require_retry3();
62720
62758
  var stream_1 = __require("stream");
62721
62759
  var interceptor_js_1 = require_interceptor();
62722
- var randomUUID16 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
62760
+ var randomUUID17 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
62723
62761
  var HTTP_STATUS_NO_CONTENT = 204;
62724
62762
  var Gaxios = class {
62725
62763
  agentCache = /* @__PURE__ */ new Map();
@@ -62992,7 +63030,7 @@ var require_gaxios = __commonJS({
62992
63030
  */
62993
63031
  ["Blob", "File", "FormData"].includes(opts.data?.constructor?.name || "");
62994
63032
  if (opts.multipart?.length) {
62995
- const boundary = await randomUUID16();
63033
+ const boundary = await randomUUID17();
62996
63034
  preparedHeaders.set("content-type", `multipart/related; boundary=${boundary}`);
62997
63035
  opts.body = stream_1.Readable.from(this.getMultipartRequest(opts.multipart, boundary));
62998
63036
  } else if (shouldDirectlyPassData) {
@@ -64743,18 +64781,18 @@ var require_parse = __commonJS({
64743
64781
  n: "\n",
64744
64782
  r: "\r",
64745
64783
  t: " "
64746
- }, text, error = function(m2) {
64784
+ }, text2, error = function(m2) {
64747
64785
  throw {
64748
64786
  name: "SyntaxError",
64749
64787
  message: m2,
64750
64788
  at,
64751
- text
64789
+ text: text2
64752
64790
  };
64753
64791
  }, next = function(c) {
64754
64792
  if (c && c !== ch) {
64755
64793
  error("Expected '" + c + "' instead of '" + ch + "'");
64756
64794
  }
64757
- ch = text.charAt(at);
64795
+ ch = text2.charAt(at);
64758
64796
  at += 1;
64759
64797
  return ch;
64760
64798
  }, number44 = function() {
@@ -64801,12 +64839,12 @@ var require_parse = __commonJS({
64801
64839
  var startAt = at;
64802
64840
  while (next()) {
64803
64841
  if (ch === '"') {
64804
- if (at - 1 > startAt) string474 += text.substring(startAt, at - 1);
64842
+ if (at - 1 > startAt) string474 += text2.substring(startAt, at - 1);
64805
64843
  next();
64806
64844
  return string474;
64807
64845
  }
64808
64846
  if (ch === "\\") {
64809
- if (at - 1 > startAt) string474 += text.substring(startAt, at - 1);
64847
+ if (at - 1 > startAt) string474 += text2.substring(startAt, at - 1);
64810
64848
  next();
64811
64849
  if (ch === "u") {
64812
64850
  uffff = 0;
@@ -64939,7 +64977,7 @@ var require_parse = __commonJS({
64939
64977
  };
64940
64978
  return function(source, reviver) {
64941
64979
  var result;
64942
- text = source + "";
64980
+ text2 = source + "";
64943
64981
  at = 0;
64944
64982
  ch = " ";
64945
64983
  result = value();
@@ -65851,8 +65889,8 @@ var require_crypto = __commonJS({
65851
65889
  const result = new TextDecoder().decode(uint8array);
65852
65890
  return result;
65853
65891
  }
65854
- encodeBase64StringUtf8(text) {
65855
- const uint8array = new TextEncoder().encode(text);
65892
+ encodeBase64StringUtf8(text2) {
65893
+ const uint8array = new TextEncoder().encode(text2);
65856
65894
  const result = base64js.fromByteArray(uint8array);
65857
65895
  return result;
65858
65896
  }
@@ -65921,8 +65959,8 @@ var require_crypto2 = __commonJS({
65921
65959
  decodeBase64StringUtf8(base64) {
65922
65960
  return Buffer.from(base64, "base64").toString("utf-8");
65923
65961
  }
65924
- encodeBase64StringUtf8(text) {
65925
- return Buffer.from(text, "utf-8").toString("base64");
65962
+ encodeBase64StringUtf8(text2) {
65963
+ return Buffer.from(text2, "utf-8").toString("base64");
65926
65964
  }
65927
65965
  /**
65928
65966
  * Computes the SHA-256 hash of the provided string.
@@ -86367,8 +86405,8 @@ async function defaultParseResponse3(client, props) {
86367
86405
  const json2 = await response.json();
86368
86406
  return json2;
86369
86407
  }
86370
- const text = await response.text();
86371
- return text;
86408
+ const text2 = await response.text();
86409
+ return text2;
86372
86410
  })();
86373
86411
  loggerFor3(client).debug(`[${requestLogID}] response parsed`, formatRequestDetails3({
86374
86412
  retryOfRequestLogID,
@@ -87945,7 +87983,7 @@ var init_node = __esm({
87945
87983
  if (this.candidates && this.candidates.length > 1) {
87946
87984
  console.warn("there are multiple candidates in the response, returning text from the first one.");
87947
87985
  }
87948
- let text = "";
87986
+ let text2 = "";
87949
87987
  let anyTextPartText = false;
87950
87988
  const nonTextParts = [];
87951
87989
  for (const part of (_h = (_g = (_f = (_e = this.candidates) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g.parts) !== null && _h !== void 0 ? _h : []) {
@@ -87959,13 +87997,13 @@ var init_node = __esm({
87959
87997
  continue;
87960
87998
  }
87961
87999
  anyTextPartText = true;
87962
- text += part.text;
88000
+ text2 += part.text;
87963
88001
  }
87964
88002
  }
87965
88003
  if (nonTextParts.length > 0) {
87966
88004
  console.warn(`there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`);
87967
88005
  }
87968
- return anyTextPartText ? text : void 0;
88006
+ return anyTextPartText ? text2 : void 0;
87969
88007
  }
87970
88008
  /**
87971
88009
  * Returns the concatenation of all inline data parts from the first candidate
@@ -88218,7 +88256,7 @@ var init_node = __esm({
88218
88256
  */
88219
88257
  get text() {
88220
88258
  var _a5, _b, _c;
88221
- let text = "";
88259
+ let text2 = "";
88222
88260
  let anyTextPartFound = false;
88223
88261
  const nonTextParts = [];
88224
88262
  for (const part of (_c = (_b = (_a5 = this.serverContent) === null || _a5 === void 0 ? void 0 : _a5.modelTurn) === null || _b === void 0 ? void 0 : _b.parts) !== null && _c !== void 0 ? _c : []) {
@@ -88232,13 +88270,13 @@ var init_node = __esm({
88232
88270
  continue;
88233
88271
  }
88234
88272
  anyTextPartFound = true;
88235
- text += part.text;
88273
+ text2 += part.text;
88236
88274
  }
88237
88275
  }
88238
88276
  if (nonTextParts.length > 0) {
88239
88277
  console.warn(`there are non-text parts ${nonTextParts} in the response, returning concatenation of all text parts. Please refer to the non text parts for a full response from model.`);
88240
88278
  }
88241
- return anyTextPartFound ? text : void 0;
88279
+ return anyTextPartFound ? text2 : void 0;
88242
88280
  }
88243
88281
  /**
88244
88282
  * Returns the concatenation of all inline data parts from the server content if present.
@@ -92910,9 +92948,9 @@ var init_node = __esm({
92910
92948
  }
92911
92949
  return n;
92912
92950
  };
92913
- safeJSON3 = (text) => {
92951
+ safeJSON3 = (text2) => {
92914
92952
  try {
92915
- return JSON.parse(text);
92953
+ return JSON.parse(text2);
92916
92954
  } catch (err) {
92917
92955
  return void 0;
92918
92956
  }
@@ -110775,8 +110813,8 @@ function findBoundary(buf) {
110775
110813
  return null;
110776
110814
  }
110777
110815
  function parseMessage2(chunk, parse2, state, dataRequired) {
110778
- const text = new TextDecoder().decode(chunk);
110779
- const lines = text.split(/\r\n|\r|\n/);
110816
+ const text2 = new TextDecoder().decode(chunk);
110817
+ const lines = text2.split(/\r\n|\r|\n/);
110780
110818
  const dataLines = [];
110781
110819
  const ret = {};
110782
110820
  let ignore = true;
@@ -133650,10 +133688,10 @@ function formatMistralError(error) {
133650
133688
  }
133651
133689
  return safeJsonStringify(error);
133652
133690
  }
133653
- function truncateErrorText(text, maxChars) {
133654
- if (text.length <= maxChars)
133655
- return text;
133656
- return `${text.slice(0, maxChars)}... [truncated ${text.length - maxChars} chars]`;
133691
+ function truncateErrorText(text2, maxChars) {
133692
+ if (text2.length <= maxChars)
133693
+ return text2;
133694
+ return `${text2.slice(0, maxChars)}... [truncated ${text2.length - maxChars} chars]`;
133657
133695
  }
133658
133696
  function safeJsonStringify(value) {
133659
133697
  try {
@@ -133773,7 +133811,7 @@ async function consumeChatStream(model, output, stream2, mistralStream) {
133773
133811
  continue;
133774
133812
  }
133775
133813
  if (item.type === "thinking") {
133776
- const deltaText = item.thinking.map((part) => "text" in part ? part.text : "").filter((text) => text.length > 0).join("");
133814
+ const deltaText = item.thinking.map((part) => "text" in part ? part.text : "").filter((text2) => text2.length > 0).join("");
133777
133815
  const thinkingDelta = sanitizeSurrogates(deltaText);
133778
133816
  if (!thinkingDelta)
133779
133817
  continue;
@@ -133970,8 +134008,8 @@ function toChatMessages(messages, supportsImages) {
133970
134008
  }
133971
134009
  return result;
133972
134010
  }
133973
- function buildToolResultText(text, hasImages, supportsImages, isError) {
133974
- const trimmed = text.trim();
134011
+ function buildToolResultText(text2, hasImages, supportsImages, isError) {
134012
+ const trimmed = text2.trim();
133975
134013
  const errorPrefix = isError ? "[tool error] " : "";
133976
134014
  if (trimmed.length > 0) {
133977
134015
  const imageSuffix = hasImages && !supportsImages ? "\n[tool image omitted: model does not support images]" : "";
@@ -134772,14 +134810,14 @@ async function* parseWebSocket(socket, signal, idleTimeoutMs) {
134772
134810
  };
134773
134811
  const onMessage = (event) => {
134774
134812
  void (async () => {
134775
- let text = null;
134813
+ let text2 = null;
134776
134814
  try {
134777
134815
  if (!event || typeof event !== "object" || !("data" in event))
134778
134816
  return;
134779
- text = await decodeWebSocketData(event.data);
134780
- if (!text)
134817
+ text2 = await decodeWebSocketData(event.data);
134818
+ if (!text2)
134781
134819
  return;
134782
- const parsed = JSON.parse(text);
134820
+ const parsed = JSON.parse(text2);
134783
134821
  const type = typeof parsed.type === "string" ? parsed.type : "";
134784
134822
  if (type === "response.completed" || type === "response.done" || type === "response.incomplete") {
134785
134823
  sawCompletion = true;
@@ -134790,7 +134828,7 @@ async function* parseWebSocket(socket, signal, idleTimeoutMs) {
134790
134828
  } catch (cause) {
134791
134829
  failed = new CodexProtocolError(`Invalid Codex WebSocket JSON: ${formatThrownValue(cause)}`, {
134792
134830
  cause,
134793
- payload: text
134831
+ payload: text2
134794
134832
  });
134795
134833
  done = true;
134796
134834
  wake();
@@ -142983,11 +143021,11 @@ function videoRequestConfig(input) {
142983
143021
  };
142984
143022
  }
142985
143023
  async function readMiniMaxJson(response) {
142986
- const text = await response.text();
143024
+ const text2 = await response.text();
142987
143025
  let body = {};
142988
- if (text) {
143026
+ if (text2) {
142989
143027
  try {
142990
- const parsed = JSON.parse(text);
143028
+ const parsed = JSON.parse(text2);
142991
143029
  if (isRecord2(parsed)) body = parsed;
142992
143030
  } catch {
142993
143031
  throw new Error("MiniMax video API returned invalid JSON");
@@ -143890,6 +143928,7 @@ __export(store_exports, {
143890
143928
  CodeGraphStore: () => CodeGraphStore
143891
143929
  });
143892
143930
  import { randomUUID as randomUUID6 } from "crypto";
143931
+ import { posix as pathPosix } from "path";
143893
143932
  function rowToFile(row) {
143894
143933
  return {
143895
143934
  id: row.id,
@@ -143940,6 +143979,26 @@ function rowToEdge(row) {
143940
143979
  ...row.sourceEpoch != null ? { sourceEpoch: Number(row.sourceEpoch) } : {}
143941
143980
  };
143942
143981
  }
143982
+ function resolveRelativeImportTarget(sourcePath, evidence, fileByPath) {
143983
+ const target = evidence?.trim().replace(/\\/g, "/");
143984
+ if (!target?.startsWith(".")) return void 0;
143985
+ const base = normalizeCodePath(pathPosix.normalize(pathPosix.join(pathPosix.dirname(sourcePath), target)));
143986
+ if (!base || base === ".." || base.startsWith("../")) return void 0;
143987
+ const candidates = [base];
143988
+ const extensionMatch = base.match(/(\.[A-Za-z0-9]+)$/);
143989
+ const hasExtension = Boolean(extensionMatch);
143990
+ if (!hasExtension) {
143991
+ const extensions = [...new Set([...fileByPath.keys()].map((path36) => path36.match(/(\.[A-Za-z0-9]+)$/)?.[1]).filter((extension3) => Boolean(extension3)))];
143992
+ for (const extension3 of extensions) {
143993
+ candidates.push(`${base}${extension3}`, `${base}/index${extension3}`);
143994
+ }
143995
+ } else {
143996
+ const sourceStem = base.slice(0, -extensionMatch[1].length);
143997
+ const sourceExtensions = extensionMatch[1] === ".js" ? [".ts", ".tsx", ".js", ".jsx"] : extensionMatch[1] === ".mjs" ? [".mts", ".mjs"] : extensionMatch[1] === ".cjs" ? [".cts", ".cjs"] : [];
143998
+ for (const extension3 of sourceExtensions) candidates.push(`${sourceStem}${extension3}`);
143999
+ }
144000
+ return candidates.map((candidate) => fileByPath.get(candidate)).find((file) => Boolean(file));
144001
+ }
143943
144002
  function rowToRef(row) {
143944
144003
  return {
143945
144004
  id: row.id,
@@ -144000,6 +144059,18 @@ function rowToSnapshot(row) {
144000
144059
  ...row.previousSnapshotId ? { previousSnapshotId: row.previousSnapshotId } : {}
144001
144060
  };
144002
144061
  }
144062
+ function rowToSnapshotFile(row) {
144063
+ return {
144064
+ snapshotId: row.snapshotId,
144065
+ projectId: row.projectId,
144066
+ fileId: row.fileId,
144067
+ path: row.path,
144068
+ contentHash: row.contentHash
144069
+ };
144070
+ }
144071
+ function snapshotIsIncomplete(snapshot) {
144072
+ return snapshot.completeness.skippedOversizedFiles > 0 || (snapshot.completeness.unreadableFiles ?? 0) > 0 || snapshot.completeness.removalScanDeferred;
144073
+ }
144003
144074
  var CodeGraphStore;
144004
144075
  var init_store = __esm({
144005
144076
  "src/codegraph/store.ts"() {
@@ -144171,6 +144242,7 @@ var init_store = __esm({
144171
144242
  }
144172
144243
  });
144173
144244
  tx();
144245
+ this.reconcileLocalImportTargets(projectId);
144174
144246
  }
144175
144247
  /**
144176
144248
  * Reconcile only files whose source changed plus files that disappeared.
@@ -144180,7 +144252,10 @@ var init_store = __esm({
144180
144252
  const changed = input.changed.filter((delta) => delta.file.projectId === projectId);
144181
144253
  const metadataOnly = (input.metadataOnly ?? []).filter((file) => file.projectId === projectId);
144182
144254
  const removedFileIds = input.removedFileIds ?? [];
144183
- if (changed.length === 0 && metadataOnly.length === 0 && removedFileIds.length === 0) return;
144255
+ if (changed.length === 0 && metadataOnly.length === 0 && removedFileIds.length === 0) {
144256
+ this.reconcileLocalImportTargets(projectId);
144257
+ return;
144258
+ }
144184
144259
  const staleRefsForFile = this.db.prepare(`
144185
144260
  UPDATE observation_code_refs
144186
144261
  SET status = 'stale', updatedAt = ?
@@ -144190,9 +144265,18 @@ var init_store = __esm({
144190
144265
  )
144191
144266
  )
144192
144267
  `);
144193
- const deleteEdgesForFile = this.db.prepare(`
144268
+ const deleteEdgesFromFile = this.db.prepare(`
144269
+ DELETE FROM code_edges
144270
+ WHERE projectId = ? AND fromFileId = ?
144271
+ `);
144272
+ const clearImportTargetsForFile = this.db.prepare(`
144273
+ UPDATE code_edges
144274
+ SET toFileId = NULL
144275
+ WHERE projectId = ? AND toFileId = ? AND type = 'imports'
144276
+ `);
144277
+ const deleteOtherIncomingEdgesForFile = this.db.prepare(`
144194
144278
  DELETE FROM code_edges
144195
- WHERE projectId = ? AND (fromFileId = ? OR toFileId = ?)
144279
+ WHERE projectId = ? AND toFileId = ? AND type != 'imports'
144196
144280
  `);
144197
144281
  const deleteSymbolsForFile = this.db.prepare(`DELETE FROM code_symbols WHERE projectId = ? AND fileId = ?`);
144198
144282
  const deleteFile = this.db.prepare(`DELETE FROM code_files WHERE projectId = ? AND id = ?`);
@@ -144229,14 +144313,18 @@ var init_store = __esm({
144229
144313
  const staleAt = (/* @__PURE__ */ new Date()).toISOString();
144230
144314
  for (const fileId of removedFileIds) {
144231
144315
  staleRefsForFile.run(staleAt, projectId, fileId, projectId, fileId);
144232
- deleteEdgesForFile.run(projectId, fileId, fileId);
144316
+ deleteEdgesFromFile.run(projectId, fileId);
144317
+ clearImportTargetsForFile.run(projectId, fileId);
144318
+ deleteOtherIncomingEdgesForFile.run(projectId, fileId);
144233
144319
  deleteSymbolsForFile.run(projectId, fileId);
144234
144320
  deleteFile.run(projectId, fileId);
144235
144321
  }
144236
144322
  for (const delta of changed) {
144237
144323
  const fileId = delta.file.id;
144238
144324
  staleRefsForFile.run(staleAt, projectId, fileId, projectId, fileId);
144239
- deleteEdgesForFile.run(projectId, fileId, fileId);
144325
+ deleteEdgesFromFile.run(projectId, fileId);
144326
+ clearImportTargetsForFile.run(projectId, fileId);
144327
+ deleteOtherIncomingEdgesForFile.run(projectId, fileId);
144240
144328
  deleteSymbolsForFile.run(projectId, fileId);
144241
144329
  writeFile8(delta.file);
144242
144330
  for (const symbol of delta.symbols) {
@@ -144274,6 +144362,7 @@ var init_store = __esm({
144274
144362
  for (const file of metadataOnly) writeFile8(file);
144275
144363
  });
144276
144364
  tx();
144365
+ this.reconcileLocalImportTargets(projectId);
144277
144366
  }
144278
144367
  upsertObservationRefs(refs) {
144279
144368
  if (refs.length === 0) return;
@@ -144335,6 +144424,25 @@ var init_store = __esm({
144335
144424
  });
144336
144425
  tx();
144337
144426
  }
144427
+ /**
144428
+ * Lite import extraction records the original import text first. Resolve only
144429
+ * local relative imports against the current index after each refresh, so an
144430
+ * added or removed target cannot leave a fabricated file-to-file relation.
144431
+ */
144432
+ reconcileLocalImportTargets(projectId) {
144433
+ const fileById = new Map(this.listFiles(projectId).map((file) => [file.id, file]));
144434
+ const fileByPath = new Map([...fileById.values()].map((file) => [file.path, file]));
144435
+ const update2 = this.db.prepare("UPDATE code_edges SET toFileId = ? WHERE id = ?");
144436
+ const tx = this.db.transaction(() => {
144437
+ for (const edge of this.listEdges(projectId)) {
144438
+ if (edge.type !== "imports" || !edge.fromFileId) continue;
144439
+ const source = fileById.get(edge.fromFileId);
144440
+ const target = source ? resolveRelativeImportTarget(source.path, edge.evidence, fileByPath) : void 0;
144441
+ update2.run(target?.id ?? null, edge.id);
144442
+ }
144443
+ });
144444
+ tx();
144445
+ }
144338
144446
  getFile(projectId, path36) {
144339
144447
  const row = this.db.prepare(`SELECT * FROM code_files WHERE projectId = ? AND path = ?`).get(projectId, normalizeCodePath(path36));
144340
144448
  return row ? rowToFile(row) : null;
@@ -144409,6 +144517,18 @@ var init_store = __esm({
144409
144517
  ORDER BY observationId, status, id
144410
144518
  `).all(projectId).map(rowToRef);
144411
144519
  }
144520
+ /** Count distinct observations whose binding to these exact files is stale. */
144521
+ countStaleObservationRefsForFiles(projectId, fileIds) {
144522
+ const ids = [...new Set(fileIds.filter(Boolean))];
144523
+ if (ids.length === 0) return 0;
144524
+ const placeholders = ids.map(() => "?").join(", ");
144525
+ const row = this.db.prepare(`
144526
+ SELECT COUNT(DISTINCT observationId) AS count
144527
+ FROM observation_code_refs
144528
+ WHERE projectId = ? AND status = 'stale' AND fileId IN (${placeholders})
144529
+ `).get(projectId, ...ids);
144530
+ return Number(row?.count ?? 0);
144531
+ }
144412
144532
  listReferencedSymbols(projectId) {
144413
144533
  return this.db.prepare(`
144414
144534
  SELECT DISTINCT symbols.*
@@ -144430,6 +144550,94 @@ var init_store = __esm({
144430
144550
  "SELECT * FROM code_state_snapshots WHERE projectId = ? ORDER BY sourceEpoch DESC LIMIT ?"
144431
144551
  ).all(projectId, safeLimit2).map(rowToSnapshot);
144432
144552
  }
144553
+ listSnapshotFiles(snapshotId) {
144554
+ return this.db.prepare(`
144555
+ SELECT snapshotId, projectId, fileId, path, contentHash
144556
+ FROM code_state_snapshot_files
144557
+ WHERE snapshotId = ?
144558
+ ORDER BY path
144559
+ `).all(snapshotId).map(rowToSnapshotFile);
144560
+ }
144561
+ diffSnapshots(projectId, fromSnapshotId, toSnapshotId) {
144562
+ const snapshots = this.db.prepare(`
144563
+ SELECT * FROM code_state_snapshots WHERE id IN (?, ?)
144564
+ `).all(fromSnapshotId, toSnapshotId).map(rowToSnapshot);
144565
+ if (snapshots.length !== 2) {
144566
+ return { projectId, fromSnapshotId, toSnapshotId, available: false, reason: "missing-snapshot", changes: [] };
144567
+ }
144568
+ if (snapshots.some((snapshot) => snapshot.projectId !== projectId)) {
144569
+ return { projectId, fromSnapshotId, toSnapshotId, available: false, reason: "project-mismatch", changes: [] };
144570
+ }
144571
+ if (snapshots.some(snapshotIsIncomplete)) {
144572
+ return { projectId, fromSnapshotId, toSnapshotId, available: false, reason: "incomplete-snapshot", changes: [] };
144573
+ }
144574
+ const before = this.listSnapshotFiles(fromSnapshotId);
144575
+ const after = this.listSnapshotFiles(toSnapshotId);
144576
+ if (before.length === 0 || after.length === 0) {
144577
+ return {
144578
+ projectId,
144579
+ fromSnapshotId,
144580
+ toSnapshotId,
144581
+ available: false,
144582
+ reason: "legacy-snapshot-without-manifest",
144583
+ changes: []
144584
+ };
144585
+ }
144586
+ const beforeByPath = new Map(before.map((file) => [file.path, file]));
144587
+ const afterByPath = new Map(after.map((file) => [file.path, file]));
144588
+ const paths = [.../* @__PURE__ */ new Set([...beforeByPath.keys(), ...afterByPath.keys()])].sort();
144589
+ const changes = [];
144590
+ for (const path36 of paths) {
144591
+ const oldFile = beforeByPath.get(path36);
144592
+ const newFile = afterByPath.get(path36);
144593
+ if (!oldFile && newFile) {
144594
+ changes.push({ path: path36, kind: "added", afterHash: newFile.contentHash });
144595
+ } else if (oldFile && !newFile) {
144596
+ changes.push({ path: path36, kind: "removed", beforeHash: oldFile.contentHash });
144597
+ } else if (oldFile && newFile && oldFile.contentHash !== newFile.contentHash) {
144598
+ changes.push({ path: path36, kind: "modified", beforeHash: oldFile.contentHash, afterHash: newFile.contentHash });
144599
+ }
144600
+ }
144601
+ return { projectId, fromSnapshotId, toSnapshotId, available: true, changes };
144602
+ }
144603
+ impactSlice(projectId, changedPaths, maxRelations = 24) {
144604
+ const safeLimit2 = Number.isFinite(maxRelations) ? Math.max(1, Math.min(100, Math.floor(maxRelations))) : 24;
144605
+ const normalizedPaths = [...new Set(changedPaths.map(normalizeCodePath).filter(Boolean))].sort();
144606
+ const files = this.listFiles(projectId);
144607
+ const fileById = new Map(files.map((file) => [file.id, file.path]));
144608
+ const fileIdBySymbolId = new Map(this.listSymbols(projectId).map((symbol) => [symbol.id, symbol.fileId]));
144609
+ const changedIds = new Set(files.filter((file) => normalizedPaths.includes(file.path)).map((file) => file.id));
144610
+ const direct = /* @__PURE__ */ new Set();
144611
+ let relationCount = 0;
144612
+ let truncated = false;
144613
+ for (const edge of this.listEdges(projectId)) {
144614
+ const endpoints = [
144615
+ edge.fromFileId,
144616
+ edge.toFileId,
144617
+ edge.fromSymbolId ? fileIdBySymbolId.get(edge.fromSymbolId) : void 0,
144618
+ edge.toSymbolId ? fileIdBySymbolId.get(edge.toSymbolId) : void 0
144619
+ ].filter((id) => Boolean(id));
144620
+ if (!endpoints.some((id) => changedIds.has(id))) continue;
144621
+ const relatedPaths = endpoints.filter((id) => !changedIds.has(id)).map((id) => fileById.get(id)).filter((path36) => Boolean(path36));
144622
+ if (relatedPaths.length === 0) continue;
144623
+ if (relationCount >= safeLimit2) {
144624
+ truncated = true;
144625
+ break;
144626
+ }
144627
+ relationCount += 1;
144628
+ for (const path36 of relatedPaths) direct.add(path36);
144629
+ }
144630
+ const snapshot = this.latestSnapshot(projectId);
144631
+ return {
144632
+ projectId,
144633
+ ...snapshot ? { snapshotId: snapshot.id } : {},
144634
+ changedPaths: normalizedPaths,
144635
+ directlyConnectedPaths: [...direct].sort(),
144636
+ relationCount,
144637
+ truncated,
144638
+ provider: snapshot?.provider ?? "lite"
144639
+ };
144640
+ }
144433
144641
  /**
144434
144642
  * Record a completed scan and mark all current structural facts with its
144435
144643
  * epoch. The snapshot is written only after refresh reconciliation succeeds,
@@ -144471,6 +144679,16 @@ var init_store = __esm({
144471
144679
  this.db.prepare(
144472
144680
  "UPDATE observation_code_refs SET snapshotId = ? WHERE projectId = ? AND status = 'current'"
144473
144681
  ).run(id, input.projectId);
144682
+ const snapshotFileRows = this.db.prepare(`
144683
+ SELECT id, projectId, path, contentHash FROM code_files WHERE projectId = ? ORDER BY path
144684
+ `).all(input.projectId);
144685
+ const insertSnapshotFile = this.db.prepare(`
144686
+ INSERT INTO code_state_snapshot_files (snapshotId, projectId, fileId, path, contentHash)
144687
+ VALUES (?, ?, ?, ?, ?)
144688
+ `);
144689
+ for (const file of snapshotFileRows) {
144690
+ insertSnapshotFile.run(id, file.projectId, file.id, file.path, file.contentHash);
144691
+ }
144474
144692
  snapshot = {
144475
144693
  ...input,
144476
144694
  id,
@@ -144636,8 +144854,8 @@ __export(lite_provider_exports, {
144636
144854
  import { createHash as createHash7 } from "crypto";
144637
144855
  import { readdirSync as readdirSync2, readFileSync as readFileSync6, statSync as statSync3 } from "fs";
144638
144856
  import { join as join4, relative } from "path";
144639
- function hashText(text) {
144640
- return createHash7("sha256").update(text).digest("hex");
144857
+ function hashText(text2) {
144858
+ return createHash7("sha256").update(text2).digest("hex");
144641
144859
  }
144642
144860
  function extension2(path36) {
144643
144861
  const index = path36.lastIndexOf(".");
@@ -144681,19 +144899,19 @@ function walk(root, exclude, maxFiles) {
144681
144899
  visit(root);
144682
144900
  return out;
144683
144901
  }
144684
- function lineOf(text, index) {
144685
- return text.slice(0, index).split(/\r?\n/).length;
144902
+ function lineOf(text2, index) {
144903
+ return text2.slice(0, index).split(/\r?\n/).length;
144686
144904
  }
144687
- function extractSymbols(projectId, file, text, indexedAt) {
144905
+ function extractSymbols(projectId, file, text2, indexedAt) {
144688
144906
  const symbols = [];
144689
144907
  const profile = file.language ? languageProfiles[file.language] : void 0;
144690
144908
  const patterns = profile?.symbols ?? [];
144691
144909
  for (const { kind, re } of patterns) {
144692
144910
  re.lastIndex = 0;
144693
- for (const match2 of text.matchAll(re)) {
144911
+ for (const match2 of text2.matchAll(re)) {
144694
144912
  const name = match2[1];
144695
144913
  if (!name || name.includes("\n")) continue;
144696
- const startLine = lineOf(text, match2.index ?? 0);
144914
+ const startLine = lineOf(text2, match2.index ?? 0);
144697
144915
  const id = makeCodeSymbolId({ projectId, path: file.path, qualifiedName: name, kind });
144698
144916
  symbols.push({
144699
144917
  id,
@@ -144713,13 +144931,13 @@ function extractSymbols(projectId, file, text, indexedAt) {
144713
144931
  }
144714
144932
  return symbols;
144715
144933
  }
144716
- function extractImportEdges(projectId, file, text, indexedAt) {
144934
+ function extractImportEdges(projectId, file, text2, indexedAt) {
144717
144935
  const edges = [];
144718
144936
  const profile = file.language ? languageProfiles[file.language] : void 0;
144719
144937
  const imports = profile?.imports ?? [];
144720
144938
  for (const re of imports) {
144721
144939
  re.lastIndex = 0;
144722
- for (const match2 of text.matchAll(re)) {
144940
+ for (const match2 of text2.matchAll(re)) {
144723
144941
  const target = (match2[1] ?? "").trim();
144724
144942
  if (!target) continue;
144725
144943
  if (target.includes("\n")) {
@@ -144754,14 +144972,14 @@ function extractImportEdges(projectId, file, text, indexedAt) {
144754
144972
  function indexFileLite(projectId, projectRoot, abs, indexedAt, fileStat) {
144755
144973
  const rel = normalizeCodePath(relative(projectRoot, abs));
144756
144974
  try {
144757
- const text = readFileSync6(abs, "utf-8");
144975
+ const text2 = readFileSync6(abs, "utf-8");
144758
144976
  const stat4 = fileStat ?? statSync3(abs);
144759
144977
  const file = {
144760
144978
  id: makeCodeFileId(projectId, rel),
144761
144979
  projectId,
144762
144980
  path: rel,
144763
144981
  language: languageForPath(rel),
144764
- contentHash: hashText(text),
144982
+ contentHash: hashText(text2),
144765
144983
  // Preserve filesystem precision. Rounding here made same-size edits in
144766
144984
  // a short Windows timestamp window indistinguishable to refresh.
144767
144985
  mtimeMs: Number(stat4.mtimeMs),
@@ -144771,8 +144989,8 @@ function indexFileLite(projectId, projectRoot, abs, indexedAt, fileStat) {
144771
144989
  return {
144772
144990
  delta: {
144773
144991
  file,
144774
- symbols: extractSymbols(projectId, file, text, indexedAt),
144775
- edges: extractImportEdges(projectId, file, text, indexedAt)
144992
+ symbols: extractSymbols(projectId, file, text2, indexedAt),
144993
+ edges: extractImportEdges(projectId, file, text2, indexedAt)
144776
144994
  },
144777
144995
  unreadable: false
144778
144996
  };
@@ -145051,18 +145269,18 @@ __export(binder_exports, {
145051
145269
  function observationText(obs) {
145052
145270
  return [obs.title, obs.narrative, ...obs.facts ?? []].join("\n");
145053
145271
  }
145054
- function mentionsSymbol(text, symbol) {
145272
+ function mentionsSymbol(text2, symbol) {
145055
145273
  const name = symbol.name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
145056
- return new RegExp(`(^|[^\\w$])${name}([^\\w$]|$)`).test(text);
145274
+ return new RegExp(`(^|[^\\w$])${name}([^\\w$]|$)`).test(text2);
145057
145275
  }
145058
- function identifierCandidates(text) {
145059
- return [...new Set(text.match(/[A-Za-z_$][\w$]*(?:::[A-Za-z_$][\w$]*)*[!?=]?/g) ?? [])];
145276
+ function identifierCandidates(text2) {
145277
+ return [...new Set(text2.match(/[A-Za-z_$][\w$]*(?:::[A-Za-z_$][\w$]*)*[!?=]?/g) ?? [])];
145060
145278
  }
145061
- function codeIdentifierCandidates(text) {
145279
+ function codeIdentifierCandidates(text2) {
145062
145280
  const explicit = /* @__PURE__ */ new Set();
145063
- for (const match2 of text.matchAll(/`([A-Za-z_$][\w$]*(?:::[A-Za-z_$][\w$]*)*[!?=]?)`/g)) explicit.add(match2[1]);
145064
- for (const match2 of text.matchAll(/\b([A-Za-z_$][\w$]*(?:::[A-Za-z_$][\w$]*)*[!?=]?)\s*\(/g)) explicit.add(match2[1]);
145065
- return identifierCandidates(text).filter((candidate) => explicit.has(candidate) || candidate.includes("::") || /[!?=]$/.test(candidate) || /^[A-Z]/.test(candidate) || /[_$]/.test(candidate) || /[a-z0-9][A-Z]/.test(candidate) || /[A-Z]{2}/.test(candidate));
145281
+ for (const match2 of text2.matchAll(/`([A-Za-z_$][\w$]*(?:::[A-Za-z_$][\w$]*)*[!?=]?)`/g)) explicit.add(match2[1]);
145282
+ for (const match2 of text2.matchAll(/\b([A-Za-z_$][\w$]*(?:::[A-Za-z_$][\w$]*)*[!?=]?)\s*\(/g)) explicit.add(match2[1]);
145283
+ return identifierCandidates(text2).filter((candidate) => explicit.has(candidate) || candidate.includes("::") || /[!?=]$/.test(candidate) || /^[A-Z]/.test(candidate) || /[_$]/.test(candidate) || /[a-z0-9][A-Z]/.test(candidate) || /[A-Z]{2}/.test(candidate));
145066
145284
  }
145067
145285
  function fileRef(projectId, obs, file) {
145068
145286
  return {
@@ -145092,7 +145310,7 @@ function symbolRef(projectId, obs, file, symbol) {
145092
145310
  }
145093
145311
  function resolveObservationCodeRefs(obs, lookup2) {
145094
145312
  const refs = /* @__PURE__ */ new Map();
145095
- const text = observationText(obs);
145313
+ const text2 = observationText(obs);
145096
145314
  const candidateFiles = /* @__PURE__ */ new Map();
145097
145315
  for (const rawPath of obs.filesModified ?? []) {
145098
145316
  const file = lookup2.findFile(normalizeCodePath(rawPath));
@@ -145102,7 +145320,7 @@ function resolveObservationCodeRefs(obs, lookup2) {
145102
145320
  refs.set(ref.id, ref);
145103
145321
  }
145104
145322
  const hintedFileIds = new Set(candidateFiles.keys());
145105
- const symbolNames = hintedFileIds.size > 0 ? identifierCandidates(text) : codeIdentifierCandidates(text);
145323
+ const symbolNames = hintedFileIds.size > 0 ? identifierCandidates(text2) : codeIdentifierCandidates(text2);
145106
145324
  const symbols = lookup2.findSymbols(symbolNames, [...hintedFileIds]);
145107
145325
  const symbolsByName = /* @__PURE__ */ new Map();
145108
145326
  for (const symbol of symbols) {
@@ -145113,7 +145331,7 @@ function resolveObservationCodeRefs(obs, lookup2) {
145113
145331
  for (const group of symbolsByName.values()) {
145114
145332
  const candidates = group.length === 1 ? group : [];
145115
145333
  for (const symbol of candidates) {
145116
- if (!mentionsSymbol(text, symbol)) continue;
145334
+ if (!mentionsSymbol(text2, symbol)) continue;
145117
145335
  const file = candidateFiles.get(symbol.fileId) ?? lookup2.findFile(symbol.path);
145118
145336
  if (!file) continue;
145119
145337
  candidateFiles.set(file.id, file);
@@ -145841,8 +146059,8 @@ function taskTokens(task) {
145841
146059
  return normalizedTokens(task);
145842
146060
  }
145843
146061
  function scoreClaim(claim, tokens) {
145844
- const text = [claim.subject, claim.predicate, claim.objectValue].join(" ").toLocaleLowerCase("en-US");
145845
- const words = normalizedTokens(text);
146062
+ const text2 = [claim.subject, claim.predicate, claim.objectValue].join(" ").toLocaleLowerCase("en-US");
146063
+ const words = normalizedTokens(text2);
145846
146064
  let matches = 0;
145847
146065
  for (const token of tokens) {
145848
146066
  if (words.has(token)) matches += 1;
@@ -146742,6 +146960,128 @@ var init_workflow_store = __esm({
146742
146960
  }
146743
146961
  });
146744
146962
 
146963
+ // src/knowledge/outcome-types.ts
146964
+ function qualityFromOutcome(signal) {
146965
+ if (!signal) return void 0;
146966
+ if (signal.kind === "verification-failed" || signal.kind === "user-correction" || signal.kind === "source-changed" || signal.kind === "conflict-confirmed") {
146967
+ return "degraded";
146968
+ }
146969
+ if (signal.kind === "verification-passed" || signal.kind === "verified-reuse" || signal.kind === "user-pin") {
146970
+ return "verified";
146971
+ }
146972
+ return void 0;
146973
+ }
146974
+ var MEMORY_OUTCOME_CANDIDATE_KINDS, MEMORY_OUTCOME_SIGNAL_KINDS;
146975
+ var init_outcome_types = __esm({
146976
+ "src/knowledge/outcome-types.ts"() {
146977
+ "use strict";
146978
+ init_esm_shims();
146979
+ MEMORY_OUTCOME_CANDIDATE_KINDS = ["claim", "durable-memory", "workflow"];
146980
+ MEMORY_OUTCOME_SIGNAL_KINDS = [
146981
+ "verification-passed",
146982
+ "verification-failed",
146983
+ "verified-reuse",
146984
+ "user-pin",
146985
+ "user-correction",
146986
+ "source-changed",
146987
+ "conflict-confirmed",
146988
+ "manual-review"
146989
+ ];
146990
+ }
146991
+ });
146992
+
146993
+ // src/knowledge/outcome-store.ts
146994
+ import { randomUUID as randomUUID10 } from "crypto";
146995
+ function optionalText4(value) {
146996
+ return typeof value === "string" && value.trim() ? value : void 0;
146997
+ }
146998
+ function text(value, field, max = 1e3) {
146999
+ const safe = sanitizeCredentials(value).replace(/\s+/g, " ").trim();
147000
+ if (!safe) throw new Error("Outcome signal " + field + " is required.");
147001
+ if (safe.length > max) throw new Error("Outcome signal " + field + " is too long.");
147002
+ return safe;
147003
+ }
147004
+ function oneOf(value, values, field) {
147005
+ if (typeof value !== "string" || !values.includes(value)) {
147006
+ throw new Error("Outcome signal " + field + " is invalid.");
147007
+ }
147008
+ return value;
147009
+ }
147010
+ function rowToSignal(row) {
147011
+ return {
147012
+ id: row.id,
147013
+ projectId: row.projectId,
147014
+ candidateKind: row.candidateKind,
147015
+ candidateId: row.candidateId,
147016
+ kind: row.kind,
147017
+ sourceRef: row.sourceRef,
147018
+ ...optionalText4(row.snapshotId) ? { snapshotId: row.snapshotId } : {},
147019
+ ...optionalText4(row.detail) ? { detail: row.detail } : {},
147020
+ observedAt: row.observedAt
147021
+ };
147022
+ }
147023
+ var OutcomeStore;
147024
+ var init_outcome_store = __esm({
147025
+ "src/knowledge/outcome-store.ts"() {
147026
+ "use strict";
147027
+ init_esm_shims();
147028
+ init_secret_filter();
147029
+ init_sqlite_db();
147030
+ init_outcome_types();
147031
+ OutcomeStore = class {
147032
+ db = null;
147033
+ async init(dataDir) {
147034
+ this.db = getDatabase(dataDir);
147035
+ }
147036
+ record(input) {
147037
+ const signal = {
147038
+ id: randomUUID10(),
147039
+ projectId: text(input.projectId, "project id"),
147040
+ candidateKind: oneOf(input.candidateKind, MEMORY_OUTCOME_CANDIDATE_KINDS, "candidate kind"),
147041
+ candidateId: text(input.candidateId, "candidate id"),
147042
+ kind: oneOf(input.kind, MEMORY_OUTCOME_SIGNAL_KINDS, "kind"),
147043
+ sourceRef: text(input.sourceRef, "source reference"),
147044
+ ...input.snapshotId ? { snapshotId: text(input.snapshotId, "snapshot id") } : {},
147045
+ ...input.detail ? { detail: text(input.detail, "detail") } : {},
147046
+ observedAt: input.observedAt ?? (/* @__PURE__ */ new Date()).toISOString()
147047
+ };
147048
+ this.db.prepare(`
147049
+ INSERT INTO memory_outcome_signals (
147050
+ id, projectId, candidateKind, candidateId, kind, sourceRef, snapshotId, detail, observedAt
147051
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
147052
+ `).run(
147053
+ signal.id,
147054
+ signal.projectId,
147055
+ signal.candidateKind,
147056
+ signal.candidateId,
147057
+ signal.kind,
147058
+ signal.sourceRef,
147059
+ signal.snapshotId ?? null,
147060
+ signal.detail ?? null,
147061
+ signal.observedAt
147062
+ );
147063
+ return signal;
147064
+ }
147065
+ latestForCandidates(projectId, candidateKind, candidateIds) {
147066
+ const ids = [...new Set(candidateIds.filter(Boolean))];
147067
+ if (ids.length === 0) return /* @__PURE__ */ new Map();
147068
+ const placeholders = ids.map(() => "?").join(", ");
147069
+ const rows = this.db.prepare(`
147070
+ SELECT * FROM memory_outcome_signals
147071
+ WHERE projectId = ? AND candidateKind = ? AND candidateId IN (${placeholders})
147072
+ ORDER BY observedAt DESC, id DESC
147073
+ `).all(projectId, candidateKind, ...ids);
147074
+ const latest = /* @__PURE__ */ new Map();
147075
+ for (const row of rows) {
147076
+ const signal = rowToSignal(row);
147077
+ if (!latest.has(signal.candidateId)) latest.set(signal.candidateId, signal);
147078
+ }
147079
+ return latest;
147080
+ }
147081
+ };
147082
+ }
147083
+ });
147084
+
146745
147085
  // src/codegraph/task-lens.ts
146746
147086
  var task_lens_exports = {};
146747
147087
  __export(task_lens_exports, {
@@ -146758,31 +147098,31 @@ __export(task_lens_exports, {
146758
147098
  function normalizePath2(path36) {
146759
147099
  return path36.replace(/\\/g, "/");
146760
147100
  }
146761
- function tokenize3(text) {
146762
- return (text.toLowerCase().match(/[a-z0-9_./-]+|[\u4e00-\u9fff]+/g) ?? []).map((token) => token.trim()).filter((token) => token.length > 1 && !STOP_WORDS.has(token));
147101
+ function tokenize3(text2) {
147102
+ return (text2.toLowerCase().match(/[a-z0-9_./-]+|[\u4e00-\u9fff]+/g) ?? []).map((token) => token.trim()).filter((token) => token.length > 1 && !STOP_WORDS.has(token));
146763
147103
  }
146764
- function containsTaskKeyword(text, keyword) {
147104
+ function containsTaskKeyword(text2, keyword) {
146765
147105
  const matcher = /^[a-z0-9_-]+$/i.test(keyword) ? new RegExp(`(^|[^a-z0-9_-])${keyword.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?=[^a-z0-9_-]|$)`, "gi") : new RegExp(keyword.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "gi");
146766
147106
  let match2;
146767
- while ((match2 = matcher.exec(text)) !== null) {
147107
+ while ((match2 = matcher.exec(text2)) !== null) {
146768
147108
  const keywordIndex = match2.index + (match2[1]?.length ?? 0);
146769
- if (!isNegatedTaskKeyword(text, keywordIndex)) return true;
147109
+ if (!isNegatedTaskKeyword(text2, keywordIndex)) return true;
146770
147110
  }
146771
147111
  return false;
146772
147112
  }
146773
- function isNegatedTaskKeyword(text, keywordIndex) {
147113
+ function isNegatedTaskKeyword(text2, keywordIndex) {
146774
147114
  const boundary = Math.max(
146775
- text.lastIndexOf(".", keywordIndex - 1),
146776
- text.lastIndexOf("!", keywordIndex - 1),
146777
- text.lastIndexOf("?", keywordIndex - 1),
146778
- text.lastIndexOf(";", keywordIndex - 1),
146779
- text.lastIndexOf("\n", keywordIndex - 1),
146780
- text.lastIndexOf("\u3002", keywordIndex - 1),
146781
- text.lastIndexOf("\uFF01", keywordIndex - 1),
146782
- text.lastIndexOf("\uFF1F", keywordIndex - 1),
146783
- text.lastIndexOf("\uFF1B", keywordIndex - 1)
147115
+ text2.lastIndexOf(".", keywordIndex - 1),
147116
+ text2.lastIndexOf("!", keywordIndex - 1),
147117
+ text2.lastIndexOf("?", keywordIndex - 1),
147118
+ text2.lastIndexOf(";", keywordIndex - 1),
147119
+ text2.lastIndexOf("\n", keywordIndex - 1),
147120
+ text2.lastIndexOf("\u3002", keywordIndex - 1),
147121
+ text2.lastIndexOf("\uFF01", keywordIndex - 1),
147122
+ text2.lastIndexOf("\uFF1F", keywordIndex - 1),
147123
+ text2.lastIndexOf("\uFF1B", keywordIndex - 1)
146784
147124
  );
146785
- let prefix = text.slice(boundary + 1, keywordIndex).toLowerCase();
147125
+ let prefix = text2.slice(boundary + 1, keywordIndex).toLowerCase();
146786
147126
  const contrast = /(?:,|\uff0c)\s*(?:but|however|instead|yet|\u4f46\u662f|\u4f46|\u800c\u662f)\s*/gi;
146787
147127
  let contrastMatch;
146788
147128
  let contrastEnd = -1;
@@ -146805,9 +147145,9 @@ function resolveTaskLens(task) {
146805
147145
  };
146806
147146
  for (const id of LENS_PRIORITY) {
146807
147147
  const score = KEYWORDS[id].reduce((sum, keyword) => sum + (containsTaskKeyword(normalized, keyword) ? 1 : 0), 0);
146808
- const priority = LENS_PRIORITY.indexOf(id);
146809
- if (score > best.score || score === best.score && score > 0 && priority < best.priority) {
146810
- best = { id, score, priority };
147148
+ const priority2 = LENS_PRIORITY.indexOf(id);
147149
+ if (score > best.score || score === best.score && score > 0 && priority2 < best.priority) {
147150
+ best = { id, score, priority: priority2 };
146811
147151
  }
146812
147152
  }
146813
147153
  return best.score > 0 ? LENSES[best.id] : LENSES.general;
@@ -146849,20 +147189,20 @@ function pathKindScore(path36, lens) {
146849
147189
  return 0;
146850
147190
  }
146851
147191
  }
146852
- function tokenScore(text, tokens) {
147192
+ function tokenScore(text2, tokens) {
146853
147193
  if (tokens.length === 0) return 0;
146854
- const normalized = text.toLowerCase();
147194
+ const normalized = text2.toLowerCase();
146855
147195
  return tokens.reduce((sum, token) => sum + (normalized.includes(token) ? 12 : 0), 0);
146856
147196
  }
146857
147197
  function sourceTaskMatchScore(source, task) {
146858
147198
  const tokens = tokenize3(task ?? "");
146859
147199
  if (tokens.length === 0) return 0;
146860
- const text = [
147200
+ const text2 = [
146861
147201
  source.title,
146862
147202
  source.path ?? "",
146863
147203
  source.symbol ?? ""
146864
147204
  ].join("\n").toLowerCase();
146865
- const matches = tokens.filter((token) => text.includes(token)).length;
147205
+ const matches = tokens.filter((token) => text2.includes(token)).length;
146866
147206
  if (matches >= 2) return 40;
146867
147207
  if (matches === 1) return 24;
146868
147208
  return 0;
@@ -146901,8 +147241,8 @@ function lensPathCandidates(lens) {
146901
147241
  }
146902
147242
  function scoreLensSource(source, lens, task) {
146903
147243
  const tokens = tokenize3(task ?? "");
146904
- const text = [source.title, source.type, source.path ?? "", source.symbol ?? ""].join("\n");
146905
- return pathKindScore(source.path ?? "", lens) + tokenScore(text, tokens) + sourceTaskMatchScore(source, task);
147244
+ const text2 = [source.title, source.type, source.path ?? "", source.symbol ?? ""].join("\n");
147245
+ return pathKindScore(source.path ?? "", lens) + tokenScore(text2, tokens) + sourceTaskMatchScore(source, task);
146906
147246
  }
146907
147247
  function rankLensSources(sources, lens, task) {
146908
147248
  return [...sources].map((source, index) => ({
@@ -147145,7 +147485,7 @@ function requiredText(data, key) {
147145
147485
  }
147146
147486
  return value.trim();
147147
147487
  }
147148
- function optionalText4(data, key) {
147488
+ function optionalText5(data, key) {
147149
147489
  const value = data[key];
147150
147490
  if (value === void 0 || value === null || value === "") return void 0;
147151
147491
  if (typeof value !== "string") throw new Error("workflow frontmatter field " + key + " must be text");
@@ -147188,11 +147528,11 @@ function phaseFromValue(value, index) {
147188
147528
  }
147189
147529
  const data = value;
147190
147530
  const title = requiredText(data, "title");
147191
- const phaseId = optionalText4(data, "id") ?? slug(title) + "-" + (index + 1);
147531
+ const phaseId = optionalText5(data, "id") ?? slug(title) + "-" + (index + 1);
147192
147532
  return {
147193
147533
  id: phaseId,
147194
147534
  title,
147195
- instructions: optionalText4(data, "instructions") ?? "",
147535
+ instructions: optionalText5(data, "instructions") ?? "",
147196
147536
  branches: optionalStringArray(data, "branches"),
147197
147537
  expectedOutputs: optionalStringArray(data, "expectedOutputs"),
147198
147538
  verificationGates: optionalStringArray(data, "verificationGates")
@@ -147301,7 +147641,7 @@ function parsedWorkflow(data, body, input) {
147301
147641
  id: requiredText(data, "id"),
147302
147642
  workspaceId: input.workspaceId,
147303
147643
  title: requiredText(data, "title"),
147304
- description: optionalText4(data, "description") ?? "",
147644
+ description: optionalText5(data, "description") ?? "",
147305
147645
  status: optionalStatus(data),
147306
147646
  version: optionalNumber(data, "version", 1),
147307
147647
  taskLenses: optionalStringArray(data, "taskLenses"),
@@ -147320,9 +147660,9 @@ function parsedWorkflow(data, body, input) {
147320
147660
  sourcePath: normalizeSourcePath(input.sourcePath),
147321
147661
  sourceHash: "",
147322
147662
  contentHash: input.contentHash,
147323
- createdAt: optionalText4(data, "createdAt") ?? now2(),
147324
- updatedAt: optionalText4(data, "updatedAt") ?? now2(),
147325
- ...optionalText4(data, "importedFrom") ? { importedFrom: optionalText4(data, "importedFrom") } : {}
147663
+ createdAt: optionalText5(data, "createdAt") ?? now2(),
147664
+ updatedAt: optionalText5(data, "updatedAt") ?? now2(),
147665
+ ...optionalText5(data, "importedFrom") ? { importedFrom: optionalText5(data, "importedFrom") } : {}
147326
147666
  };
147327
147667
  if (candidate.phases.length === 0) {
147328
147668
  throw new Error("workflow must contain at least one phase or a non-empty body");
@@ -147421,11 +147761,11 @@ async function syncCanonicalWorkflows(workspace) {
147421
147761
  return { workflows, errors };
147422
147762
  }
147423
147763
  function inferTaskLenses(value) {
147424
- const text = value.toLowerCase();
147425
- return Object.entries(LENS_TERMS).filter(([, terms]) => terms.some((term) => text.includes(term))).map(([lens]) => lens);
147764
+ const text2 = value.toLowerCase();
147765
+ return Object.entries(LENS_TERMS).filter(([, terms]) => terms.some((term) => text2.includes(term))).map(([lens]) => lens);
147426
147766
  }
147427
147767
  function taskScore(workflow, task) {
147428
- const text = task.toLowerCase();
147768
+ const text2 = task.toLowerCase();
147429
147769
  let score = 0;
147430
147770
  const reasons = [];
147431
147771
  const matchedLenses = /* @__PURE__ */ new Set();
@@ -147692,7 +148032,31 @@ async function recordWorkflowRun(input) {
147692
148032
  throw new Error("Workflow was not found for this workspace");
147693
148033
  }
147694
148034
  if (!input.run.task.trim()) throw new Error("Workflow run task is required");
147695
- return store.recordRun(input.run);
148035
+ const run = store.recordRun(input.run);
148036
+ const kind = run.outcome === "passed" && run.verificationVerdict === "passed" ? "verification-passed" : run.outcome === "failed" || run.verificationVerdict === "failed" ? "verification-failed" : void 0;
148037
+ if (!kind) return run;
148038
+ const evidence = /* @__PURE__ */ new Map();
148039
+ evidence.set(workflow.id, "workflow");
148040
+ for (const reference of run.selectedEvidence) {
148041
+ const match2 = /^(claim|durable):(.+)$/.exec(reference);
148042
+ if (!match2) continue;
148043
+ evidence.set(match2[2], match2[1] === "claim" ? "claim" : "durable-memory");
148044
+ }
148045
+ const outcomes = new OutcomeStore();
148046
+ await outcomes.init(workflowStoreDataDir(input.workspace));
148047
+ for (const [candidateId, candidateKind] of evidence) {
148048
+ outcomes.record({
148049
+ projectId: run.projectId,
148050
+ candidateKind,
148051
+ candidateId,
148052
+ kind,
148053
+ sourceRef: "workflow-run:" + run.id,
148054
+ ...run.startingSnapshotId ? { snapshotId: run.startingSnapshotId } : {},
148055
+ ...run.failureReason ? { detail: run.failureReason } : {},
148056
+ observedAt: run.completedAt ?? run.startedAt
148057
+ });
148058
+ }
148059
+ return run;
147696
148060
  }
147697
148061
  async function selectWorkspaceWorkflows(input) {
147698
148062
  const synced = await syncCanonicalWorkflows(input.workspace);
@@ -147717,6 +148081,7 @@ var init_workflows2 = __esm({
147717
148081
  init_workflow_sync();
147718
148082
  init_workspace();
147719
148083
  init_workflow_store();
148084
+ init_outcome_store();
147720
148085
  init_task_lens();
147721
148086
  KNOWN_AGENTS = [
147722
148087
  "windsurf",
@@ -150740,7 +151105,7 @@ function evidenceScore2(obs) {
150740
151105
  }
150741
151106
  function scoreForPacket(obs, queryTokens, referenceTime, broadMemoryQuery) {
150742
151107
  let score = 0;
150743
- const text = normalizeText3([
151108
+ const text2 = normalizeText3([
150744
151109
  obs.title,
150745
151110
  obs.narrative,
150746
151111
  obs.entityName,
@@ -150749,15 +151114,15 @@ function scoreForPacket(obs, queryTokens, referenceTime, broadMemoryQuery) {
150749
151114
  ...obs.relatedEntities ?? [],
150750
151115
  ...obs.relatedCommits ?? []
150751
151116
  ].join(" "));
150752
- const matchingTokens = queryTokens.filter((token) => text.includes(token));
151117
+ const matchingTokens = queryTokens.filter((token) => text2.includes(token));
150753
151118
  score += matchingTokens.length * 4;
150754
151119
  if (queryTokens.length > 0 && matchingTokens.length === 0) {
150755
151120
  score -= 8;
150756
151121
  }
150757
- if (broadMemoryQuery && /memorix|memcode|memory-(?:graph|injection|runtime|quality|formation)|graph-context/.test(text)) {
151122
+ if (broadMemoryQuery && /memorix|memcode|memory-(?:graph|injection|runtime|quality|formation)|graph-context/.test(text2)) {
150758
151123
  score += 8;
150759
151124
  }
150760
- if (/\bmemory[- ]?game\b|e2e-test\/memory-game|team-handoff/.test(text)) {
151125
+ if (/\bmemory[- ]?game\b|e2e-test\/memory-game|team-handoff/.test(text2)) {
150761
151126
  score -= broadMemoryQuery ? 12 : 4;
150762
151127
  }
150763
151128
  score += obs.valueCategory === "core" ? 6 : 0;
@@ -153487,8 +153852,8 @@ async function extractFactsWithLLM(narrative, title, existingFacts) {
153487
153852
  Content: ${narrative}${existingFacts.length > 0 ? `
153488
153853
  Already known facts (don't repeat): ${existingFacts.join("; ")}` : ""}`;
153489
153854
  const response = await callLLM2(LLM_EXTRACT_PROMPT, input);
153490
- const text = response.content.trim();
153491
- const jsonMatch = text.match(/\{[\s\S]*\}/);
153855
+ const text2 = response.content.trim();
153856
+ const jsonMatch = text2.match(/\{[\s\S]*\}/);
153492
153857
  if (!jsonMatch) return [];
153493
153858
  const parsed = JSON.parse(jsonMatch[0]);
153494
153859
  const facts = parsed.facts;
@@ -153741,8 +154106,8 @@ Facts: ${extracted.facts.join("; ")}
153741
154106
  EXISTING MEMORIES:
153742
154107
  ${existingMemories.map((m2) => `[ID:${m2.id}] ${m2.title} | ${m2.content} | Facts: ${m2.facts}`).join("\n")}`;
153743
154108
  const response = await callLLM2(LLM_RESOLVE_PROMPT, input);
153744
- const text = response.content.trim();
153745
- const jsonMatch = text.match(/\{[\s\S]*\}/);
154109
+ const text2 = response.content.trim();
154110
+ const jsonMatch = text2.match(/\{[\s\S]*\}/);
153746
154111
  if (!jsonMatch) return null;
153747
154112
  const parsed = JSON.parse(jsonMatch[0]);
153748
154113
  const action = parsed.action?.toUpperCase();
@@ -154619,8 +154984,8 @@ function isNoiseObservation(obs) {
154619
154984
  return NOISE_PATTERNS2.some((pattern) => pattern.test(title)) || isCommandTrace(obs);
154620
154985
  }
154621
154986
  function isSystemSelfObservation(obs) {
154622
- const text = stringifyObservation(obs, false);
154623
- return SYSTEM_SELF_PATTERNS.some((pattern) => pattern.test(text));
154987
+ const text2 = stringifyObservation(obs, false);
154988
+ return SYSTEM_SELF_PATTERNS.some((pattern) => pattern.test(text2));
154624
154989
  }
154625
154990
  function readerForAlias(reader, aliases, observation) {
154626
154991
  if (!reader) return void 0;
@@ -154643,8 +155008,8 @@ function continuationTaskTokens(task) {
154643
155008
  function continuationScore(observation, projectTokens, task) {
154644
155009
  let score = scoreObservationForSessionContext(observation, projectTokens);
154645
155010
  if (observation.type === "session-request" || observation.type === "what-changed") score += 1;
154646
- const text = stringifyObservation(observation);
154647
- const matches = continuationTaskTokens(task).filter((token) => text.includes(token)).length;
155011
+ const text2 = stringifyObservation(observation);
155012
+ const matches = continuationTaskTokens(task).filter((token) => text2.includes(token)).length;
154648
155013
  score += Math.min(matches, 2) * 2;
154649
155014
  return score;
154650
155015
  }
@@ -154678,8 +155043,8 @@ async function getSessionResumeBrief(projectId, task, reader) {
154678
155043
  memories
154679
155044
  };
154680
155045
  }
154681
- function compactResumeText(text, limit2) {
154682
- const normalized = text.replace(/\s+/g, " ").trim();
155046
+ function compactResumeText(text2, limit2) {
155047
+ const normalized = text2.replace(/\s+/g, " ").trim();
154683
155048
  return normalized.length <= limit2 ? normalized : `${normalized.slice(0, Math.max(0, limit2 - 3)).trimEnd()}...`;
154684
155049
  }
154685
155050
  function renderSessionResumeCard(brief) {
@@ -154701,11 +155066,11 @@ function renderSessionResumeCard(brief) {
154701
155066
  }
154702
155067
  function scoreObservationForSessionContext(obs, projectTokens, now3 = Date.now()) {
154703
155068
  let score = TYPE_WEIGHTS2[obs.type] ?? 1;
154704
- const text = stringifyObservation(obs);
155069
+ const text2 = stringifyObservation(obs);
154705
155070
  const ageDays = Math.max(0, (now3 - new Date(obs.createdAt).getTime()) / (1e3 * 60 * 60 * 24));
154706
155071
  score += Math.max(0.2, 2.5 - Math.min(ageDays, 45) * 0.05);
154707
155072
  if (projectTokens.length > 0) {
154708
- const matchingTokens = projectTokens.filter((token) => text.includes(token));
155073
+ const matchingTokens = projectTokens.filter((token) => text2.includes(token));
154709
155074
  if (matchingTokens.length > 0) {
154710
155075
  score += 2 + matchingTokens.length * 0.6;
154711
155076
  } else if ((obs.filesModified?.length ?? 0) > 0) {
@@ -155021,7 +155386,7 @@ var owner_exports = {};
155021
155386
  __export(owner_exports, {
155022
155387
  resolveLocalMemoryOwner: () => resolveLocalMemoryOwner
155023
155388
  });
155024
- import { randomUUID as randomUUID10 } from "crypto";
155389
+ import { randomUUID as randomUUID11 } from "crypto";
155025
155390
  import { promises as fs17 } from "fs";
155026
155391
  import path25 from "path";
155027
155392
  function ownerPath(dataDir) {
@@ -155051,7 +155416,7 @@ async function resolveLocalMemoryOwner(dataDir, options = {}) {
155051
155416
  await fs17.mkdir(path25.dirname(filePath), { recursive: true });
155052
155417
  const created = {
155053
155418
  version: 1,
155054
- id: "local-" + randomUUID10(),
155419
+ id: "local-" + randomUUID11(),
155055
155420
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
155056
155421
  };
155057
155422
  try {
@@ -155074,8 +155439,8 @@ var init_owner = __esm({
155074
155439
  });
155075
155440
 
155076
155441
  // src/memory/long-term-store.ts
155077
- import { randomUUID as randomUUID11 } from "crypto";
155078
- function optionalText5(value) {
155442
+ import { randomUUID as randomUUID12 } from "crypto";
155443
+ function optionalText6(value) {
155079
155444
  return typeof value === "string" && value.trim() ? value : void 0;
155080
155445
  }
155081
155446
  function arrayValue2(value) {
@@ -155100,17 +155465,17 @@ function rowToMemory(row) {
155100
155465
  content: row.content,
155101
155466
  facts: arrayValue2(row.factsJson),
155102
155467
  tags: arrayValue2(row.tagsJson),
155103
- ...optionalText5(row.applicability) ? { applicability: row.applicability } : {},
155468
+ ...optionalText6(row.applicability) ? { applicability: row.applicability } : {},
155104
155469
  origin: row.origin,
155105
155470
  createdAt: row.createdAt,
155106
155471
  updatedAt: row.updatedAt,
155107
- ...optionalText5(row.qualifiedAt) ? { qualifiedAt: row.qualifiedAt } : {},
155108
- ...optionalText5(row.approvedAt) ? { approvedAt: row.approvedAt } : {},
155109
- ...optionalText5(row.archivedAt) ? { archivedAt: row.archivedAt } : {},
155110
- ...optionalText5(row.supersededBy) ? { supersededBy: row.supersededBy } : {},
155111
- ...optionalText5(row.lastValidatedAt) ? { lastValidatedAt: row.lastValidatedAt } : {},
155472
+ ...optionalText6(row.qualifiedAt) ? { qualifiedAt: row.qualifiedAt } : {},
155473
+ ...optionalText6(row.approvedAt) ? { approvedAt: row.approvedAt } : {},
155474
+ ...optionalText6(row.archivedAt) ? { archivedAt: row.archivedAt } : {},
155475
+ ...optionalText6(row.supersededBy) ? { supersededBy: row.supersededBy } : {},
155476
+ ...optionalText6(row.lastValidatedAt) ? { lastValidatedAt: row.lastValidatedAt } : {},
155112
155477
  accessCount: Number(row.accessCount ?? 0),
155113
- ...optionalText5(row.lastAccessedAt) ? { lastAccessedAt: row.lastAccessedAt } : {}
155478
+ ...optionalText6(row.lastAccessedAt) ? { lastAccessedAt: row.lastAccessedAt } : {}
155114
155479
  };
155115
155480
  }
155116
155481
  function rowToEvidence2(row) {
@@ -155120,8 +155485,8 @@ function rowToEvidence2(row) {
155120
155485
  kind: row.kind,
155121
155486
  referenceId: row.referenceId,
155122
155487
  relation: row.relation,
155123
- ...optionalText5(row.locator) ? { locator: row.locator } : {},
155124
- ...optionalText5(row.capturedHash) ? { capturedHash: row.capturedHash } : {},
155488
+ ...optionalText6(row.locator) ? { locator: row.locator } : {},
155489
+ ...optionalText6(row.capturedHash) ? { capturedHash: row.capturedHash } : {},
155125
155490
  createdAt: row.createdAt
155126
155491
  };
155127
155492
  }
@@ -155130,9 +155495,9 @@ function rowToEvent2(row) {
155130
155495
  id: row.id,
155131
155496
  memoryId: row.memoryId,
155132
155497
  kind: row.kind,
155133
- ...optionalText5(row.fromState) ? { fromState: row.fromState } : {},
155134
- ...optionalText5(row.toState) ? { toState: row.toState } : {},
155135
- ...optionalText5(row.detail) ? { detail: row.detail } : {},
155498
+ ...optionalText6(row.fromState) ? { fromState: row.fromState } : {},
155499
+ ...optionalText6(row.toState) ? { toState: row.toState } : {},
155500
+ ...optionalText6(row.detail) ? { detail: row.detail } : {},
155136
155501
  createdAt: row.createdAt
155137
155502
  };
155138
155503
  }
@@ -155234,7 +155599,7 @@ var init_long_term_store = __esm({
155234
155599
  }
155235
155600
  insertEvidence(input) {
155236
155601
  const evidence = {
155237
- id: randomUUID11(),
155602
+ id: randomUUID12(),
155238
155603
  ...input,
155239
155604
  createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
155240
155605
  };
@@ -155261,7 +155626,7 @@ var init_long_term_store = __esm({
155261
155626
  }
155262
155627
  recordEvent(input) {
155263
155628
  const event = {
155264
- id: randomUUID11(),
155629
+ id: randomUUID12(),
155265
155630
  ...input,
155266
155631
  createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
155267
155632
  };
@@ -155349,7 +155714,7 @@ __export(long_term_exports, {
155349
155714
  selectLongTermMemoriesForTask: () => selectLongTermMemoriesForTask,
155350
155715
  supersedeLongTermMemory: () => supersedeLongTermMemory
155351
155716
  });
155352
- import { randomUUID as randomUUID12 } from "crypto";
155717
+ import { randomUUID as randomUUID13 } from "crypto";
155353
155718
  function isOneOf(value, values) {
155354
155719
  return typeof value === "string" && values.includes(value);
155355
155720
  }
@@ -155531,7 +155896,7 @@ async function createManualLongTermMemory(input) {
155531
155896
  const owner = await resolveLocalMemoryOwner(input.dataDir, { create: true });
155532
155897
  if (!owner) throw new Error("Memorix could not resolve a local memory owner.");
155533
155898
  assertScope(input.scope);
155534
- const evidence = input.scope === "user" ? [{ kind: "user", referenceId: owner.id, relation: "user-confirmed" }] : [{ kind: "manual", referenceId: "manual:" + randomUUID12(), relation: "supports" }];
155899
+ const evidence = input.scope === "user" ? [{ kind: "user", referenceId: owner.id, relation: "user-confirmed" }] : [{ kind: "manual", referenceId: "manual:" + randomUUID13(), relation: "supports" }];
155535
155900
  return createLongTermMemoryWithDataDir({
155536
155901
  dataDir: input.dataDir,
155537
155902
  originProjectId: input.projectId,
@@ -155586,7 +155951,7 @@ async function createLongTermMemoryWithDataDir(input) {
155586
155951
  assertPortableEvidence(input.scope, portability, evidenceInputs);
155587
155952
  const now3 = (/* @__PURE__ */ new Date()).toISOString();
155588
155953
  const memory = {
155589
- id: randomUUID12(),
155954
+ id: randomUUID13(),
155590
155955
  originProjectId: compactText2(input.originProjectId, "origin project id", 1e3),
155591
155956
  ownerId: compactText2(input.ownerId, "owner id", 160),
155592
155957
  scope: input.scope,
@@ -155837,12 +156202,99 @@ var init_long_term = __esm({
155837
156202
  }
155838
156203
  });
155839
156204
 
156205
+ // src/knowledge/governor.ts
156206
+ function clampRelevance(value) {
156207
+ if (!Number.isFinite(value)) return 0;
156208
+ return Math.max(0, Math.min(1, value));
156209
+ }
156210
+ function classify(candidate) {
156211
+ const freshness = candidate.freshness ?? "unknown";
156212
+ const trust = candidate.trust ?? "historical";
156213
+ const quality = candidate.quality ?? "probationary";
156214
+ const conflict = candidate.conflict ?? "none";
156215
+ if (!candidate.scopeAllowed) {
156216
+ return { disposition: "exclude", reasons: ["scope-forbidden"] };
156217
+ }
156218
+ if (conflict === "confirmed") {
156219
+ return { disposition: "exclude", reasons: ["confirmed-conflict"] };
156220
+ }
156221
+ if (quality === "blocked") {
156222
+ return { disposition: "exclude", reasons: ["blocked-quality"] };
156223
+ }
156224
+ if (quality === "degraded") {
156225
+ return { disposition: "defer", reasons: ["degraded-quality"] };
156226
+ }
156227
+ if (freshness === "stale") {
156228
+ return { disposition: "defer", reasons: ["stale-evidence"] };
156229
+ }
156230
+ const reasons = [];
156231
+ let disposition = "include";
156232
+ if (freshness === "unknown") {
156233
+ disposition = "compact";
156234
+ reasons.push("unknown-freshness");
156235
+ }
156236
+ if (conflict === "possible") {
156237
+ disposition = "compact";
156238
+ reasons.push("possible-conflict");
156239
+ }
156240
+ if (quality === "probationary") {
156241
+ disposition = "compact";
156242
+ reasons.push("probationary-evidence");
156243
+ }
156244
+ if (disposition === "include" && freshness === "current" && trust === "source-backed") {
156245
+ reasons.push("current-source-backed-evidence");
156246
+ } else if (reasons.length === 0) {
156247
+ reasons.push("relevant-evidence");
156248
+ }
156249
+ return { disposition, reasons };
156250
+ }
156251
+ function priority(decision) {
156252
+ const dispositionWeight = {
156253
+ include: 3,
156254
+ compact: 2,
156255
+ defer: 1,
156256
+ exclude: 0
156257
+ };
156258
+ const evidence = Math.min(3, decision.candidate.evidenceCount ?? 0) / 10;
156259
+ return dispositionWeight[decision.disposition] + clampRelevance(decision.candidate.relevance) + evidence;
156260
+ }
156261
+ function governContextCandidates(candidates, maxTokens) {
156262
+ const safeBudget = Math.max(0, Math.floor(maxTokens));
156263
+ const decisions = candidates.map((candidate) => ({ candidate, ...classify(candidate) }));
156264
+ const eligible = decisions.filter((decision) => decision.disposition === "include" || decision.disposition === "compact").sort((left, right) => priority(right) - priority(left));
156265
+ let usedTokens = 0;
156266
+ for (const decision of eligible) {
156267
+ const tokens = Math.max(0, Math.ceil(decision.candidate.estimatedTokens));
156268
+ if (usedTokens + tokens <= safeBudget) {
156269
+ usedTokens += tokens;
156270
+ continue;
156271
+ }
156272
+ decision.disposition = "defer";
156273
+ decision.reasons = [...decision.reasons, "token-budget"];
156274
+ }
156275
+ const delivered = decisions.filter((decision) => decision.disposition === "include" || decision.disposition === "compact");
156276
+ const mode = delivered.length === 0 ? "abstain" : delivered.some((decision) => decision.disposition === "include") ? "workset" : "card";
156277
+ const cautions = [...new Set(decisions.filter((decision) => decision.disposition !== "include").flatMap((decision) => decision.reasons))];
156278
+ return {
156279
+ mode,
156280
+ budget: { maxTokens: safeBudget, usedTokens },
156281
+ decisions,
156282
+ cautions: cautions.length > 0 ? cautions : ["no-qualified-evidence"]
156283
+ };
156284
+ }
156285
+ var init_governor = __esm({
156286
+ "src/knowledge/governor.ts"() {
156287
+ "use strict";
156288
+ init_esm_shims();
156289
+ }
156290
+ });
156291
+
155840
156292
  // src/knowledge/workset.ts
155841
156293
  function unique(values) {
155842
156294
  return [...new Set(values.filter(Boolean))];
155843
156295
  }
155844
- function short(text, budget = 28) {
155845
- const safe = sanitizeCredentials(text).replace(/\s+/g, " ").trim();
156296
+ function short(text2, budget = 28) {
156297
+ const safe = sanitizeCredentials(text2).replace(/\s+/g, " ").trim();
155846
156298
  return countTextTokens(safe) <= budget ? safe : truncateToTokenBudget(safe, budget);
155847
156299
  }
155848
156300
  function claimAssertion(claim) {
@@ -155973,6 +156425,65 @@ function receiptOmissions(omitted, hiddenCautionMemoryCount) {
155973
156425
  function scheduledActions(cautions) {
155974
156426
  return cautions.filter((caution) => caution.kind === "codegraph-refresh-queued").map((caution) => short(caution.message, 28));
155975
156427
  }
156428
+ function isGovernedDelivery(disposition) {
156429
+ return disposition === "include" || disposition === "compact";
156430
+ }
156431
+ function governOptionalArtifacts(input) {
156432
+ const candidates = [
156433
+ ...input.reliableMemory.map((memory, index) => ({
156434
+ kind: "memory",
156435
+ id: "memory:" + memory.id,
156436
+ estimatedTokens: 10,
156437
+ relevance: Math.max(0.2, 0.9 - index * 0.1),
156438
+ scopeAllowed: true,
156439
+ freshness: freshnessForMemory(memory.status),
156440
+ trust: "historical",
156441
+ quality: memory.status === "current" ? "verified" : "degraded"
156442
+ })),
156443
+ ...input.claims.map((claim, index) => ({
156444
+ kind: "claim",
156445
+ id: "claim:" + claim.id,
156446
+ estimatedTokens: 12,
156447
+ relevance: Math.max(0.2, 0.95 - index * 0.1),
156448
+ scopeAllowed: true,
156449
+ freshness: claim.status === "active" ? "current" : "unknown",
156450
+ trust: "source-backed",
156451
+ quality: claim.reviewState === "approved" ? "verified" : "probationary",
156452
+ conflict: claim.status === "disputed" ? "confirmed" : "none",
156453
+ evidenceCount: claim.evidenceRefs.length
156454
+ })),
156455
+ ...input.durableMemory.map((memory, index) => ({
156456
+ kind: "durable-memory",
156457
+ id: "durable:" + memory.id,
156458
+ estimatedTokens: 14,
156459
+ relevance: Math.max(0.2, 0.8 - index * 0.1),
156460
+ scopeAllowed: true,
156461
+ freshness: memory.state === "approved" ? "current" : "unknown",
156462
+ trust: "source-backed",
156463
+ quality: memory.quality,
156464
+ evidenceCount: memory.evidenceRefs.length
156465
+ })),
156466
+ ...input.workflows.map((workflow, index) => ({
156467
+ kind: "workflow",
156468
+ id: "workflow:" + workflow.id,
156469
+ estimatedTokens: 14,
156470
+ relevance: Math.max(0.2, 0.85 - index * 0.1),
156471
+ scopeAllowed: true,
156472
+ freshness: "current",
156473
+ trust: "source-backed",
156474
+ quality: "verified"
156475
+ }))
156476
+ ];
156477
+ const plan = governContextCandidates(candidates, Number.MAX_SAFE_INTEGER);
156478
+ const permitted = new Set(plan.decisions.filter((decision) => isGovernedDelivery(decision.disposition)).map((decision) => decision.candidate.id));
156479
+ return {
156480
+ plan,
156481
+ reliableMemory: input.reliableMemory.filter((memory) => permitted.has("memory:" + memory.id)),
156482
+ claims: input.claims.filter((claim) => permitted.has("claim:" + claim.id)),
156483
+ durableMemory: input.durableMemory.filter((memory) => permitted.has("durable:" + memory.id)),
156484
+ workflows: input.workflows.filter((workflow) => permitted.has("workflow:" + workflow.id))
156485
+ };
156486
+ }
155976
156487
  function renderTaskWorksetPrompt(input) {
155977
156488
  const maxTokens = input.budget?.maxTokens ?? 180;
155978
156489
  const omitted = [];
@@ -156100,6 +156611,56 @@ function renderTaskWorksetPrompt(input) {
156100
156611
  trust: "source-backed"
156101
156612
  });
156102
156613
  }
156614
+ if (input.codeEvolution && input.codeEvolution.changes.length > 0) {
156615
+ appendLine(lines, "", maxTokens, omitted, "code-evolution-heading");
156616
+ appendLine(lines, "Code changes since prior scan", maxTokens, omitted, "code-evolution-heading");
156617
+ for (const change of input.codeEvolution.changes.slice(0, 3)) {
156618
+ appendLine(
156619
+ lines,
156620
+ "- " + change.kind + ": " + change.path,
156621
+ maxTokens,
156622
+ omitted,
156623
+ "code-evolution-change",
156624
+ selected,
156625
+ {
156626
+ kind: "code-state",
156627
+ id: "snapshot:" + input.codeEvolution.toSnapshotId,
156628
+ reason: "exact file hash change between complete CodeGraph snapshots",
156629
+ freshness: "current",
156630
+ trust: "source-backed"
156631
+ }
156632
+ );
156633
+ }
156634
+ for (const path36 of input.codeEvolution.directlyConnectedPaths.slice(0, 2)) {
156635
+ appendLine(
156636
+ lines,
156637
+ "- connected now: " + path36,
156638
+ maxTokens,
156639
+ omitted,
156640
+ "code-evolution-impact",
156641
+ selected,
156642
+ {
156643
+ kind: "code-state",
156644
+ id: "snapshot:" + input.codeEvolution.toSnapshotId,
156645
+ reason: "bounded current CodeGraph impact relation",
156646
+ freshness: "current",
156647
+ trust: "derived"
156648
+ }
156649
+ );
156650
+ }
156651
+ if ((input.codeEvolution.affectedMemoryCount ?? 0) > 0) {
156652
+ appendLine(
156653
+ lines,
156654
+ "- " + input.codeEvolution.affectedMemoryCount + " stored memory link(s) reference this changed code; reread source before relying on their conclusions.",
156655
+ maxTokens,
156656
+ omitted,
156657
+ "code-evolution-stale-memory"
156658
+ );
156659
+ }
156660
+ if (input.codeEvolution.truncated) {
156661
+ appendLine(lines, "- More connected files exist; inspect CodeGraph before assuming complete impact.", maxTokens, omitted, "code-evolution-truncated");
156662
+ }
156663
+ }
156103
156664
  if (input.semanticCode && (input.semanticCode.entryPoints.length > 0 || input.semanticCode.relations.length > 0)) {
156104
156665
  appendLine(lines, "", maxTokens, omitted, "semantic-code-heading");
156105
156666
  appendLine(lines, "Semantic code outline", maxTokens, omitted, "semantic-code-heading");
@@ -156290,6 +156851,17 @@ async function buildTaskWorkset(input) {
156290
156851
  }));
156291
156852
  let durableMemory = [];
156292
156853
  let durableEvidence = [];
156854
+ let outcomeStore;
156855
+ try {
156856
+ outcomeStore = new OutcomeStore();
156857
+ await outcomeStore.init(input.dataDir);
156858
+ } catch {
156859
+ }
156860
+ const claimQuality = outcomeStore ? outcomeStore.latestForCandidates(input.projectId, "claim", claims.map((claim) => claim.id)) : /* @__PURE__ */ new Map();
156861
+ for (const claim of claims) {
156862
+ const outcomeQuality = qualityFromOutcome(claimQuality.get(claim.id));
156863
+ if (outcomeQuality === "degraded") claim.reviewState = "needs-review";
156864
+ }
156293
156865
  if (task) {
156294
156866
  try {
156295
156867
  const selected = await selectLongTermMemoriesForTask({
@@ -156300,11 +156872,13 @@ async function buildTaskWorkset(input) {
156300
156872
  ...input.reader?.isTeamMember ? { isTeamMember: true } : {},
156301
156873
  limit: 3
156302
156874
  });
156875
+ const durableQuality = outcomeStore ? outcomeStore.latestForCandidates(input.projectId, "durable-memory", selected.map((item) => item.memory.id)) : /* @__PURE__ */ new Map();
156303
156876
  durableMemory = selected.map((item) => ({
156304
156877
  id: item.memory.id,
156305
156878
  kind: item.memory.kind,
156306
156879
  scope: item.memory.scope,
156307
156880
  state: item.memory.state,
156881
+ quality: qualityFromOutcome(durableQuality.get(item.memory.id)) ?? (item.memory.state === "approved" ? "verified" : "probationary"),
156308
156882
  title: item.memory.title,
156309
156883
  summary: renderLongTermMemorySummary(item.memory, 20),
156310
156884
  evidenceRefs: item.evidence.map((evidence) => evidence.id),
@@ -156350,18 +156924,25 @@ async function buildTaskWorkset(input) {
156350
156924
  }
156351
156925
  } catch {
156352
156926
  }
156353
- const evidenceIds = unique(selection.claims.flatMap((claim) => evidenceIdsForClaim(
156354
- claim,
156355
- evidenceByClaim.get(claim.id) ?? []
156356
- )).concat(
156357
- durableMemory.map((memory) => "durable:" + memory.id),
156358
- durableEvidence.map((evidence) => "durable-evidence:" + evidence.id)
156359
- ));
156360
156927
  const verification = unique([
156361
156928
  ...workflows.flatMap((workflow) => workflow.verificationGates),
156362
156929
  ...input.verificationHints
156363
156930
  ]).slice(0, 4);
156364
156931
  const normalizedCautions = unique(cautions.map((caution) => caution.kind)).map((kind) => cautions.find((caution) => caution.kind === kind)).slice(0, 6);
156932
+ const governed = governOptionalArtifacts({
156933
+ reliableMemory: input.reliableMemory?.slice(0, 3) ?? [],
156934
+ claims,
156935
+ durableMemory,
156936
+ workflows
156937
+ });
156938
+ const governedDurableIds = new Set(governed.durableMemory.map((memory) => memory.id));
156939
+ const evidenceIds = unique(governed.claims.flatMap((claim) => evidenceIdsForClaim(
156940
+ claim,
156941
+ evidenceByClaim.get(claim.id) ?? []
156942
+ )).concat(
156943
+ governed.durableMemory.map((memory) => "durable:" + memory.id),
156944
+ durableEvidence.filter((evidence) => governedDurableIds.has(evidence.memoryId)).map((evidence) => "durable-evidence:" + evidence.id)
156945
+ ));
156365
156946
  const continuation = input.continuation && (input.continuation.previousSession || input.continuation.memories.length > 0 || input.continuation.compactCheckpoint) ? {
156366
156947
  ...input.continuation.previousSession ? {
156367
156948
  previousSession: {
@@ -156388,15 +156969,16 @@ async function buildTaskWorkset(input) {
156388
156969
  currentFacts: input.currentFacts?.map((fact) => fact.startsWith("Historical note:") ? short(fact, 48) : short(fact, 28)).slice(0, 4) ?? [],
156389
156970
  ...continuation ? { continuation } : {},
156390
156971
  ...input.codeState ? { codeState: short(input.codeState, 28) } : {},
156972
+ ...input.codeEvolution ? { codeEvolution: input.codeEvolution } : {},
156391
156973
  startHere: unique(input.startHere).slice(0, 5),
156392
156974
  ...input.semanticCode ? { semanticCode: input.semanticCode } : {},
156393
- reliableMemory: input.reliableMemory?.slice(0, 3) ?? [],
156975
+ reliableMemory: governed.reliableMemory,
156394
156976
  cautionMemory: input.cautionMemory?.slice(0, 3) ?? [],
156395
156977
  hiddenCautionMemoryCount: input.hiddenCautionMemoryCount ?? 0,
156396
- claims,
156397
- pages,
156398
- durableMemory,
156399
- workflows,
156978
+ claims: governed.claims,
156979
+ pages: pages.filter((page) => page.claimIds.some((claimId) => governed.claims.some((claim) => claim.id === claimId))),
156980
+ durableMemory: governed.durableMemory,
156981
+ workflows: governed.workflows,
156400
156982
  cautions: normalizedCautions,
156401
156983
  verification,
156402
156984
  evidenceIds,
@@ -156421,6 +157003,17 @@ async function buildTaskWorkset(input) {
156421
157003
  },
156422
157004
  selected: rendered.selected,
156423
157005
  omitted: receiptOmissions(rendered.omittedItems, base.hiddenCautionMemoryCount),
157006
+ governance: {
157007
+ scope: "optional-evidence",
157008
+ mode: governed.plan.mode,
157009
+ decisions: governed.plan.decisions.map((decision) => ({
157010
+ kind: decision.candidate.kind,
157011
+ ...decision.candidate.id ? { id: decision.candidate.id } : {},
157012
+ disposition: decision.disposition,
157013
+ reasons: decision.reasons
157014
+ })),
157015
+ cautions: governed.plan.cautions
157016
+ },
156424
157017
  scheduledActions: scheduledActions(normalizedCautions)
156425
157018
  };
156426
157019
  return {
@@ -156446,8 +157039,11 @@ var init_workset = __esm({
156446
157039
  init_workspace_store();
156447
157040
  init_workspace();
156448
157041
  init_workflow_store();
157042
+ init_outcome_store();
157043
+ init_outcome_types();
156449
157044
  init_workflows2();
156450
157045
  init_long_term();
157046
+ init_governor();
156451
157047
  CONTINUATION_DETAIL_TOKEN_BUDGET = 20;
156452
157048
  }
156453
157049
  });
@@ -156470,19 +157066,19 @@ function readTextIfExists(filePath) {
156470
157066
  }
156471
157067
  }
156472
157068
  function readPackageVersion(rootPath) {
156473
- const text = readTextIfExists(path26.join(rootPath, "package.json"));
156474
- if (!text) return void 0;
157069
+ const text2 = readTextIfExists(path26.join(rootPath, "package.json"));
157070
+ if (!text2) return void 0;
156475
157071
  try {
156476
- const parsed = JSON.parse(text);
157072
+ const parsed = JSON.parse(text2);
156477
157073
  return typeof parsed.version === "string" ? parsed.version : void 0;
156478
157074
  } catch {
156479
157075
  return void 0;
156480
157076
  }
156481
157077
  }
156482
157078
  function readLatestChangelog(rootPath) {
156483
- const text = readTextIfExists(path26.join(rootPath, "CHANGELOG.md"));
156484
- if (!text) return void 0;
156485
- const match2 = text.match(/^##\s+\[?v?([^\]\s]+)\]?\s*(?:-\s*(\d{4}-\d{2}-\d{2}))?/m);
157079
+ const text2 = readTextIfExists(path26.join(rootPath, "CHANGELOG.md"));
157080
+ if (!text2) return void 0;
157081
+ const match2 = text2.match(/^##\s+\[?v?([^\]\s]+)\]?\s*(?:-\s*(\d{4}-\d{2}-\d{2}))?/m);
156486
157082
  if (!match2) return void 0;
156487
157083
  return {
156488
157084
  version: match2[1],
@@ -156683,6 +157279,7 @@ function providerQuality(input) {
156683
157279
  capabilities: {
156684
157280
  declarations: true,
156685
157281
  importHints: true,
157282
+ localRelativeImportTargets: true,
156686
157283
  resolvedRelations: false,
156687
157284
  exactLocations: false
156688
157285
  },
@@ -157204,8 +157801,8 @@ var compaction_checkpoint_store_exports = {};
157204
157801
  __export(compaction_checkpoint_store_exports, {
157205
157802
  CompactionCheckpointStore: () => CompactionCheckpointStore
157206
157803
  });
157207
- import { createHash as createHash14, randomUUID as randomUUID13 } from "crypto";
157208
- function optionalText6(value) {
157804
+ import { createHash as createHash14, randomUUID as randomUUID14 } from "crypto";
157805
+ function optionalText7(value) {
157209
157806
  return typeof value === "string" && value ? value : void 0;
157210
157807
  }
157211
157808
  function optionalNumber2(value) {
@@ -157259,15 +157856,15 @@ function rowToCheckpoint(row) {
157259
157856
  reason: row.reason,
157260
157857
  sourceEvent: row.source_event,
157261
157858
  sourceKey: row.source_key,
157262
- ...optionalText6(row.summary) ? { summary: row.summary } : {},
157859
+ ...optionalText7(row.summary) ? { summary: row.summary } : {},
157263
157860
  ...optionalNumber2(row.tokens_before) !== void 0 ? { tokensBefore: Number(row.tokens_before) } : {},
157264
- ...optionalText6(row.first_kept_entry_id) ? { firstKeptEntryId: row.first_kept_entry_id } : {},
157861
+ ...optionalText7(row.first_kept_entry_id) ? { firstKeptEntryId: row.first_kept_entry_id } : {},
157265
157862
  ...parseDetails(row.details_json) ? { details: parseDetails(row.details_json) } : {},
157266
157863
  transcriptAvailable: Boolean(row.transcript_available),
157267
157864
  status: row.status,
157268
157865
  preCapturedAt: row.pre_captured_at,
157269
- ...optionalText6(row.completed_at) ? { completedAt: row.completed_at } : {},
157270
- ...optionalText6(row.delivered_at) ? { deliveredAt: row.delivered_at } : {},
157866
+ ...optionalText7(row.completed_at) ? { completedAt: row.completed_at } : {},
157867
+ ...optionalText7(row.delivered_at) ? { deliveredAt: row.delivered_at } : {},
157271
157868
  deliveryCount: Number(row.delivery_count ?? 0),
157272
157869
  createdAt: row.created_at,
157273
157870
  updatedAt: row.updated_at
@@ -157305,7 +157902,7 @@ var init_compaction_checkpoint_store = __esm({
157305
157902
  if (pending) return rowToCheckpoint(pending);
157306
157903
  const now3 = input.capturedAt ?? (/* @__PURE__ */ new Date()).toISOString();
157307
157904
  const checkpoint = {
157308
- id: randomUUID13(),
157905
+ id: randomUUID14(),
157309
157906
  projectId: input.projectId,
157310
157907
  sessionId: input.sessionId,
157311
157908
  agent: input.agent,
@@ -157313,7 +157910,7 @@ var init_compaction_checkpoint_store = __esm({
157313
157910
  captureKind: "preflight",
157314
157911
  reason: safeReason(input.reason),
157315
157912
  sourceEvent: input.sourceEvent,
157316
- sourceKey: `pre:${randomUUID13()}`,
157913
+ sourceKey: `pre:${randomUUID14()}`,
157317
157914
  transcriptAvailable: Boolean(input.transcriptAvailable),
157318
157915
  status: "active",
157319
157916
  preCapturedAt: now3,
@@ -157379,7 +157976,7 @@ var init_compaction_checkpoint_store = __esm({
157379
157976
  return this.get(checkpoint2.id);
157380
157977
  }
157381
157978
  const checkpoint = {
157382
- id: randomUUID13(),
157979
+ id: randomUUID14(),
157383
157980
  projectId: input.projectId,
157384
157981
  sessionId: input.sessionId,
157385
157982
  agent: input.agent,
@@ -157641,6 +158238,25 @@ async function buildAutoProjectContext(input) {
157641
158238
  const overview = explain.overview;
157642
158239
  const currentFacts = collectCurrentProjectFacts({ project: input.project, now: now3 });
157643
158240
  const latestSnapshot = overview.code.latestSnapshot;
158241
+ let codeEvolution;
158242
+ if (continuationRequested && latestSnapshot?.previousSnapshotId && latestSnapshot.changedPathCount > 0) {
158243
+ const diff = store.diffSnapshots(input.project.id, latestSnapshot.previousSnapshotId, latestSnapshot.id);
158244
+ if (diff.available && diff.changes.length > 0) {
158245
+ const impact = store.impactSlice(input.project.id, diff.changes.map((change) => change.path));
158246
+ const changedFileIds = new Set([
158247
+ ...store.listSnapshotFiles(diff.fromSnapshotId),
158248
+ ...store.listSnapshotFiles(diff.toSnapshotId)
158249
+ ].filter((file) => diff.changes.some((change) => change.path === file.path)).map((file) => file.fileId));
158250
+ codeEvolution = {
158251
+ fromSnapshotId: diff.fromSnapshotId,
158252
+ toSnapshotId: diff.toSnapshotId,
158253
+ changes: diff.changes.slice(0, 5).map((change) => ({ path: change.path, kind: change.kind })),
158254
+ directlyConnectedPaths: impact.directlyConnectedPaths.slice(0, 3),
158255
+ affectedMemoryCount: store.countStaleObservationRefsForFiles(input.project.id, [...changedFileIds]),
158256
+ truncated: impact.truncated || diff.changes.length > 5
158257
+ };
158258
+ }
158259
+ }
157644
158260
  const sourceSets = lensSourceSets({ task, lens, explain });
157645
158261
  let externalOutline;
157646
158262
  let externalCaution;
@@ -157717,6 +158333,7 @@ async function buildAutoProjectContext(input) {
157717
158333
  currentFacts: worksetFactLines(currentFacts),
157718
158334
  ...continuation ? { continuation } : {},
157719
158335
  codeState: codeStateLine(overview),
158336
+ ...codeEvolution ? { codeEvolution } : {},
157720
158337
  reliableMemory: sourceSets.reliableSources.slice(0, lens.sourceLimit).map((source) => ({
157721
158338
  id: source.observationId,
157722
158339
  title: source.title,
@@ -157768,9 +158385,9 @@ async function buildAutoProjectContext(input) {
157768
158385
  function formatLanguages(overview) {
157769
158386
  return overview.code.languages.length > 0 ? overview.code.languages.map((item) => `${item.language} ${item.files}`).join(", ") : "none indexed yet";
157770
158387
  }
157771
- function compactContinuationText(text, budget) {
158388
+ function compactContinuationText(text2, budget) {
157772
158389
  return truncateToTokenBudget(
157773
- sanitizeCredentials(text).replace(/\s+/g, " ").trim(),
158390
+ sanitizeCredentials(text2).replace(/\s+/g, " ").trim(),
157774
158391
  budget
157775
158392
  );
157776
158393
  }
@@ -158045,8 +158662,8 @@ __export(context_pack_exports, {
158045
158662
  function uniq2(items) {
158046
158663
  return [...new Set(items)];
158047
158664
  }
158048
- function tokenize4(text) {
158049
- return (text.toLowerCase().match(/[a-z0-9_./-]+|[\u4e00-\u9fff]+/g) ?? []).map((token) => token.trim()).filter((token) => token.length > 1);
158665
+ function tokenize4(text2) {
158666
+ return (text2.toLowerCase().match(/[a-z0-9_./-]+|[\u4e00-\u9fff]+/g) ?? []).map((token) => token.trim()).filter((token) => token.length > 1);
158050
158667
  }
158051
158668
  function timestampOf(observation) {
158052
158669
  return Date.parse(observation.updatedAt ?? observation.createdAt ?? "") || 0;
@@ -158648,7 +159265,7 @@ __export(team_store_exports, {
158648
159265
  isTeamStoreInitialized: () => isTeamStoreInitialized,
158649
159266
  resetTeamStore: () => resetTeamStore
158650
159267
  });
158651
- import { randomUUID as randomUUID14 } from "crypto";
159268
+ import { randomUUID as randomUUID15 } from "crypto";
158652
159269
  import path28 from "path";
158653
159270
  import fs18 from "fs";
158654
159271
  function getTeamStore() {
@@ -158937,7 +159554,7 @@ var init_team_store = __esm({
158937
159554
  * reactivate it (preserving agent_id). Otherwise create a new one.
158938
159555
  */
158939
159556
  registerAgent(input) {
158940
- const instanceId = input.instanceId || randomUUID14();
159557
+ const instanceId = input.instanceId || randomUUID15();
158941
159558
  const now3 = Date.now();
158942
159559
  const existing = this.stmtAgentFindByInstance.get(
158943
159560
  input.projectId,
@@ -158963,7 +159580,7 @@ var init_team_store = __esm({
158963
159580
  this.eventBus?.emit("agent:joined", { agentId: row2.agent_id, projectId: input.projectId, agentType: input.agentType });
158964
159581
  return row2;
158965
159582
  }
158966
- const agentId = randomUUID14();
159583
+ const agentId = randomUUID15();
158967
159584
  this.stmtAgentUpsert.run({
158968
159585
  agent_id: agentId,
158969
159586
  project_id: input.projectId,
@@ -159065,7 +159682,7 @@ var init_team_store = __esm({
159065
159682
  return { error: `Recipient agent '${input.recipientAgentId}' not found \u2014 cannot send to unknown agent` };
159066
159683
  }
159067
159684
  }
159068
- const id = randomUUID14();
159685
+ const id = randomUUID15();
159069
159686
  const now3 = Date.now();
159070
159687
  const row = {
159071
159688
  id,
@@ -159115,7 +159732,7 @@ var init_team_store = __esm({
159115
159732
  // Task Operations (with atomic claim semantics)
159116
159733
  // ═══════════════════════════════════════════════════════════════════
159117
159734
  createTask(input) {
159118
- const taskId = randomUUID14();
159735
+ const taskId = randomUUID15();
159119
159736
  const now3 = Date.now();
159120
159737
  const row = {
159121
159738
  task_id: taskId,
@@ -159387,7 +160004,7 @@ var init_team_store = __esm({
159387
160004
  for (const [agentId, msgs] of Object.entries(snap.messages.inboxes)) {
159388
160005
  for (const msg of msgs) {
159389
160006
  this.stmtMsgInsert.run({
159390
- id: msg.id ?? randomUUID14(),
160007
+ id: msg.id ?? randomUUID15(),
159391
160008
  project_id: "migrated",
159392
160009
  sender_agent_id: msg.from ?? "unknown",
159393
160010
  recipient_agent_id: msg.to === "__broadcast__" ? null : msg.to ?? agentId,
@@ -159660,19 +160277,19 @@ function buildCompactionWorkset(checkpoint, options = {}) {
159660
160277
  const source = sanitizeCredentials(checkpoint.summary?.trim() || fallback);
159661
160278
  const available = Math.max(0, budget - countTextTokens(header) - 4);
159662
160279
  let excerpt = source ? truncateToTokenBudget(source, available) : "";
159663
- let text = `${header}${excerpt ? `### Host checkpoint
160280
+ let text2 = `${header}${excerpt ? `### Host checkpoint
159664
160281
  ${excerpt}` : ""}`.trim();
159665
- while (excerpt && countTextTokens(text) > budget) {
160282
+ while (excerpt && countTextTokens(text2) > budget) {
159666
160283
  const nextExcerptBudget = Math.max(1, Math.floor(countTextTokens(excerpt) * 0.8));
159667
160284
  excerpt = truncateToTokenBudget(excerpt, nextExcerptBudget);
159668
- text = `${header}${excerpt ? `### Host checkpoint
160285
+ text2 = `${header}${excerpt ? `### Host checkpoint
159669
160286
  ${excerpt}` : ""}`.trim();
159670
160287
  }
159671
- if (countTextTokens(text) > budget) text = truncateToTokenBudget(text, budget);
160288
+ if (countTextTokens(text2) > budget) text2 = truncateToTokenBudget(text2, budget);
159672
160289
  return {
159673
160290
  checkpointId: checkpoint.id,
159674
- text,
159675
- tokens: countTextTokens(text)
160291
+ text: text2,
160292
+ tokens: countTextTokens(text2)
159676
160293
  };
159677
160294
  }
159678
160295
  function sourceEvent(input) {
@@ -161563,15 +162180,15 @@ function validateSemantics(graph) {
161563
162180
  return warnings;
161564
162181
  }
161565
162182
  function extractJson(raw) {
161566
- let text = raw;
162183
+ let text2 = raw;
161567
162184
  try {
161568
162185
  const envelope = JSON.parse(raw.trim());
161569
162186
  if (envelope && typeof envelope.result === "string" && envelope.type === "result") {
161570
- text = envelope.result;
162187
+ text2 = envelope.result;
161571
162188
  }
161572
162189
  } catch {
161573
162190
  }
161574
- if (text === raw && raw.includes('"type"')) {
162191
+ if (text2 === raw && raw.includes('"type"')) {
161575
162192
  const textBlocks = [];
161576
162193
  for (const line of raw.split("\n")) {
161577
162194
  const trimmed = line.trim();
@@ -161595,27 +162212,27 @@ function extractJson(raw) {
161595
162212
  }
161596
162213
  }
161597
162214
  if (textBlocks.length > 0) {
161598
- text = textBlocks.join("");
162215
+ text2 = textBlocks.join("");
161599
162216
  }
161600
162217
  }
161601
- const fenced = text.match(/```(?:json)?\s*\n?([\s\S]*?)```/);
162218
+ const fenced = text2.match(/```(?:json)?\s*\n?([\s\S]*?)```/);
161602
162219
  if (fenced) {
161603
162220
  const candidate = fenced[1].trim();
161604
162221
  if (candidate.startsWith("{")) return candidate;
161605
162222
  }
161606
- const braceStart = text.indexOf("{");
162223
+ const braceStart = text2.indexOf("{");
161607
162224
  if (braceStart !== -1) {
161608
- const extracted = extractBalancedJson(text, braceStart);
162225
+ const extracted = extractBalancedJson(text2, braceStart);
161609
162226
  if (extracted) return extracted;
161610
162227
  }
161611
162228
  return null;
161612
162229
  }
161613
- function extractBalancedJson(text, startIdx) {
162230
+ function extractBalancedJson(text2, startIdx) {
161614
162231
  let depth = 0;
161615
162232
  let inString = false;
161616
162233
  let escape2 = false;
161617
- for (let i2 = startIdx; i2 < text.length; i2++) {
161618
- const ch = text[i2];
162234
+ for (let i2 = startIdx; i2 < text2.length; i2++) {
162235
+ const ch = text2[i2];
161619
162236
  if (escape2) {
161620
162237
  escape2 = false;
161621
162238
  continue;
@@ -161633,7 +162250,7 @@ function extractBalancedJson(text, startIdx) {
161633
162250
  else if (ch === "}") {
161634
162251
  depth--;
161635
162252
  if (depth === 0) {
161636
- return text.slice(startIdx, i2 + 1);
162253
+ return text2.slice(startIdx, i2 + 1);
161637
162254
  }
161638
162255
  }
161639
162256
  }
@@ -161852,7 +162469,7 @@ __export(planner_exports, {
161852
162469
  materializeTaskGraph: () => materializeTaskGraph,
161853
162470
  seedAutonomousPipeline: () => seedAutonomousPipeline
161854
162471
  });
161855
- import { randomUUID as randomUUID15 } from "crypto";
162472
+ import { randomUUID as randomUUID16 } from "crypto";
161856
162473
  function isPlannerTask(metadata) {
161857
162474
  if (!metadata) return null;
161858
162475
  try {
@@ -161910,7 +162527,7 @@ function seedAutonomousPipeline(teamStore, projectId, config, opts) {
161910
162527
  const maxIterations = config.maxIterations ?? 3;
161911
162528
  const taskBudget = config.taskBudget ?? 15;
161912
162529
  const structuredPlan = opts?.structuredPlan ?? true;
161913
- const pipelineId = randomUUID15();
162530
+ const pipelineId = randomUUID16();
161914
162531
  const meta = {
161915
162532
  plannerType: "plan",
161916
162533
  pipelineId,
@@ -162355,8 +162972,8 @@ async function callVisionLLM(systemPrompt, imageBase64, mimeType) {
162355
162972
  return data.choices[0]?.message?.content ?? "";
162356
162973
  }
162357
162974
  function normalizeText4(value, fallback = "") {
162358
- const text = typeof value === "string" && value.trim() ? value.trim() : fallback;
162359
- return sanitizeCredentials(text).slice(0, MAX_VISION_DESCRIPTION_CHARS);
162975
+ const text2 = typeof value === "string" && value.trim() ? value.trim() : fallback;
162976
+ return sanitizeCredentials(text2).slice(0, MAX_VISION_DESCRIPTION_CHARS);
162360
162977
  }
162361
162978
  function normalizeLabels(value) {
162362
162979
  if (!Array.isArray(value)) return [];
@@ -164345,7 +164962,7 @@ The path should point to a directory containing a .git folder.`
164345
164962
  };
164346
164963
  const server = existingServer ?? new McpServer({
164347
164964
  name: "memorix",
164348
- version: true ? "1.4.1" : "1.0.1"
164965
+ version: true ? "1.4.2" : "1.0.1"
164349
164966
  });
164350
164967
  const originalRegisterTool = server.registerTool.bind(server);
164351
164968
  server.registerTool = ((name, ...args) => {
@@ -165081,10 +165698,10 @@ Use this as the \`topicKey\` parameter in \`memorix_store\` to enable upsert beh
165081
165698
  const duplicate = blockCoveredAutopilotEvidence("memorix_search", result.entries.map((entry) => entry.id), force);
165082
165699
  if (duplicate) return duplicate;
165083
165700
  }
165084
- let text = result.formatted;
165701
+ let text2 = result.formatted;
165085
165702
  try {
165086
165703
  const { getLastSearchMode: getLastSearchMode2 } = await Promise.resolve().then(() => (init_orama_store(), orama_store_exports));
165087
- text += `
165704
+ text2 += `
165088
165705
 
165089
165706
  _Search mode: ${getLastSearchMode2(project.id)}_`;
165090
165707
  } catch {
@@ -165093,7 +165710,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165093
165710
  content: [
165094
165711
  {
165095
165712
  type: "text",
165096
- text
165713
+ text: text2
165097
165714
  }
165098
165715
  ]
165099
165716
  };
@@ -165126,14 +165743,14 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165126
165743
  query,
165127
165744
  limit: limit2 != null ? coerceNumber(limit2, 5) : void 0
165128
165745
  });
165129
- const text = format === "summary" ? [
165746
+ const text2 = format === "summary" ? [
165130
165747
  `Graph context packet for ${project.name}`,
165131
165748
  `- ${packet.summary}`,
165132
165749
  "",
165133
165750
  ...packet.entities.map((entity) => `* ${entity.name} (#${entity.observationIds.join(", #")})`)
165134
165751
  ].join("\n") : formatGraphContextPrompt(packet);
165135
165752
  return {
165136
- content: [{ type: "text", text }]
165753
+ content: [{ type: "text", text: text2 }]
165137
165754
  };
165138
165755
  }
165139
165756
  );
@@ -165193,7 +165810,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165193
165810
  });
165194
165811
  }
165195
165812
  });
165196
- const text = format === "json" ? JSON.stringify({ ...context, brief: buildAutoProjectBrief2(context) }, null, 2) : format === "summary" ? formatAutoProjectContextSummary2(context) : formatAutoProjectContextPrompt2(context);
165813
+ const text2 = format === "json" ? JSON.stringify({ ...context, brief: buildAutoProjectBrief2(context) }, null, 2) : format === "summary" ? formatAutoProjectContextSummary2(context) : formatAutoProjectContextPrompt2(context);
165197
165814
  autopilotRetrievalBoundary = {
165198
165815
  projectId: project.id,
165199
165816
  issuedAt: Date.now(),
@@ -165205,7 +165822,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165205
165822
  readOnly: READ_ONLY_TASK_PATTERN.test(task ?? "")
165206
165823
  };
165207
165824
  return {
165208
- content: [{ type: "text", text }]
165825
+ content: [{ type: "text", text: text2 }]
165209
165826
  };
165210
165827
  }
165211
165828
  );
@@ -165333,9 +165950,9 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165333
165950
  ...external.caution ? { runtimeCautions: [{ kind: "external-codegraph-fallback", message: external.caution }] } : {},
165334
165951
  reader: getObservationReader()
165335
165952
  });
165336
- const text = buildContextPackPrompt2(pack);
165953
+ const text2 = buildContextPackPrompt2(pack);
165337
165954
  return {
165338
- content: [{ type: "text", text }]
165955
+ content: [{ type: "text", text: text2 }]
165339
165956
  };
165340
165957
  }
165341
165958
  );
@@ -165397,7 +166014,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165397
166014
  }) => {
165398
166015
  const unresolved = requireResolvedProject("manage the Knowledge Workspace for the current project");
165399
166016
  if (unresolved) return unresolved;
165400
- const text = (value, isError = false) => ({
166017
+ const text2 = (value, isError = false) => ({
165401
166018
  content: [{ type: "text", text: JSON.stringify(value, null, 2) }],
165402
166019
  ...isError ? { isError: true } : {}
165403
166020
  });
@@ -165434,7 +166051,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165434
166051
  ]);
165435
166052
  if (action === "workspace_init") {
165436
166053
  if (modeValue === "versioned" && !requireText(workspacePath, "path")) {
165437
- return text({ error: "path is required to initialize a versioned Knowledge Workspace." }, true);
166054
+ return text2({ error: "path is required to initialize a versioned Knowledge Workspace." }, true);
165438
166055
  }
165439
166056
  const workspace2 = await initializeKnowledgeWorkspace2({
165440
166057
  projectId: project.id,
@@ -165442,7 +166059,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165442
166059
  mode: modeValue,
165443
166060
  ...modeValue === "versioned" ? { projectRoot: project.rootPath, rootPath: requireText(workspacePath, "path") } : {}
165444
166061
  });
165445
- return text({
166062
+ return text2({
165446
166063
  workspace: {
165447
166064
  id: workspace2.id,
165448
166065
  mode: workspace2.mode,
@@ -165454,7 +166071,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165454
166071
  }
165455
166072
  const workspace = await loadKnowledgeWorkspace2({ projectId: project.id, dataDir: projectDir2, mode: modeValue });
165456
166073
  if (!workspace) {
165457
- return text({ error: "Knowledge Workspace is not initialized. Run workspace_init first." }, true);
166074
+ return text2({ error: "Knowledge Workspace is not initialized. Run workspace_init first." }, true);
165458
166075
  }
165459
166076
  const claims = new ClaimStore2();
165460
166077
  const workspaceStore = new KnowledgeWorkspaceStore2();
@@ -165462,7 +166079,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165462
166079
  if (action === "status") {
165463
166080
  const pages = workspaceStore.listPages(workspace.id);
165464
166081
  const pending = workspaceStore.listProposals(workspace.id, "pending");
165465
- return text({
166082
+ return text2({
165466
166083
  workspace: {
165467
166084
  id: workspace.id,
165468
166085
  mode: workspace.mode,
@@ -165480,7 +166097,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165480
166097
  });
165481
166098
  }
165482
166099
  if (action === "claim_list") {
165483
- return text({
166100
+ return text2({
165484
166101
  claims: claims.listClaims(project.id, { limit: 100 }).map((claim) => ({
165485
166102
  id: claim.id,
165486
166103
  subject: claim.subject,
@@ -165499,18 +166116,18 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165499
166116
  const requestedClaimId = requireText(claimId, "claimId");
165500
166117
  const detail = requireText(reviewDetail, "reviewDetail");
165501
166118
  if (!requestedClaimId || !claimReviewState || !detail) {
165502
- return text({ error: "claimId, claimReviewState, and reviewDetail are required for claim_review." }, true);
166119
+ return text2({ error: "claimId, claimReviewState, and reviewDetail are required for claim_review." }, true);
165503
166120
  }
165504
166121
  const existing = claims.getClaim(requestedClaimId);
165505
166122
  if (!existing || existing.projectId !== project.id) {
165506
- return text({ error: "Claim was not found for the current project." }, true);
166123
+ return text2({ error: "Claim was not found for the current project." }, true);
165507
166124
  }
165508
166125
  const claim = reviewClaim2(claims, {
165509
166126
  claimId: requestedClaimId,
165510
166127
  reviewState: claimReviewState,
165511
166128
  detail
165512
166129
  });
165513
- return text({
166130
+ return text2({
165514
166131
  claim: {
165515
166132
  id: claim.id,
165516
166133
  status: claim.status,
@@ -165522,7 +166139,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165522
166139
  }
165523
166140
  if (action === "compile") {
165524
166141
  const result = await compileKnowledgeWorkspace2({ workspace, claims });
165525
- return text({
166142
+ return text2({
165526
166143
  proposals: result.proposals.map((proposal) => ({
165527
166144
  id: proposal.id,
165528
166145
  targetPath: proposal.targetPath,
@@ -165537,17 +166154,17 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165537
166154
  const codeStore = new CodeGraphStore2();
165538
166155
  await codeStore.init(projectDir2);
165539
166156
  const result = await lintKnowledgeWorkspace2({ workspace, claims, codeStore });
165540
- return text(result);
166157
+ return text2(result);
165541
166158
  }
165542
166159
  if (action === "proposal_apply") {
165543
166160
  const proposal = requireText(proposalId, "proposalId");
165544
- if (!proposal) return text({ error: "proposalId is required for proposal_apply." }, true);
166161
+ if (!proposal) return text2({ error: "proposalId is required for proposal_apply." }, true);
165545
166162
  const result = await applyKnowledgeProposal2({
165546
166163
  workspace,
165547
166164
  proposalId: proposal,
165548
166165
  allowManualOverwrite: !!allowManualOverwrite
165549
166166
  });
165550
- return text({
166167
+ return text2({
165551
166168
  proposal: { id: result.proposal.id, status: result.proposal.status },
165552
166169
  targetPath: result.targetPath
165553
166170
  });
@@ -165557,7 +166174,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165557
166174
  const projectRoot = workspace.projectRoot ?? project.rootPath;
165558
166175
  if (action === "workflow_import") {
165559
166176
  const result = await importWindsurfWorkflows2({ workspace, projectRoot });
165560
- return text({
166177
+ return text2({
165561
166178
  imported: result.imported.map((workflow2) => ({
165562
166179
  id: workflow2.id,
165563
166180
  title: workflow2.title,
@@ -165570,7 +166187,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165570
166187
  }
165571
166188
  const synced = await syncCanonicalWorkflows2(workspace);
165572
166189
  if (action === "workflow_list") {
165573
- return text({
166190
+ return text2({
165574
166191
  workflows: workflowStore.listWorkflows(workspace.id).map((workflow2) => ({
165575
166192
  id: workflow2.id,
165576
166193
  title: workflow2.title,
@@ -165585,9 +166202,9 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165585
166202
  }
165586
166203
  if (action === "workflow_select") {
165587
166204
  const selectedTask = requireText(task, "task");
165588
- if (!selectedTask) return text({ error: "task is required for workflow_select." }, true);
166205
+ if (!selectedTask) return text2({ error: "task is required for workflow_select." }, true);
165589
166206
  const result = await selectWorkspaceWorkflows2({ workspace, task: selectedTask });
165590
- return text({
166207
+ return text2({
165591
166208
  selections: result.selections.map((selection) => ({
165592
166209
  id: selection.workflow.id,
165593
166210
  title: selection.workflow.title,
@@ -165599,16 +166216,16 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165599
166216
  });
165600
166217
  }
165601
166218
  const requestedWorkflowId = requireText(workflowId, "workflowId");
165602
- if (!requestedWorkflowId) return text({ error: "workflowId is required for this workflow action." }, true);
166219
+ if (!requestedWorkflowId) return text2({ error: "workflowId is required for this workflow action." }, true);
165603
166220
  const workflow = workflowStore.getWorkflow(requestedWorkflowId);
165604
166221
  if (!workflow || workflow.workspaceId !== workspace.id) {
165605
- return text({ error: "Workflow was not found for this Knowledge Workspace." }, true);
166222
+ return text2({ error: "Workflow was not found for this Knowledge Workspace." }, true);
165606
166223
  }
165607
166224
  if (action === "workflow_preview" || action === "workflow_apply") {
165608
166225
  const targetAgent = requireText(agent, "agent");
165609
- if (!targetAgent) return text({ error: "agent is required for a workflow adapter action." }, true);
166226
+ if (!targetAgent) return text2({ error: "agent is required for a workflow adapter action." }, true);
165610
166227
  const result = action === "workflow_preview" ? await previewWorkflowAdapter2({ workflow, projectRoot, agent: targetAgent }) : await applyWorkflowAdapter2({ workflow, projectRoot, agent: targetAgent });
165611
- return text({
166228
+ return text2({
165612
166229
  workflowId: workflow.id,
165613
166230
  agent: targetAgent,
165614
166231
  status: result.status,
@@ -165619,8 +166236,8 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165619
166236
  }
165620
166237
  if (action === "workflow_run") {
165621
166238
  const runTask = requireText(task, "task");
165622
- if (!runTask) return text({ error: "task is required for workflow_run." }, true);
165623
- if (!outcome) return text({ error: "outcome is required for workflow_run." }, true);
166239
+ if (!runTask) return text2({ error: "task is required for workflow_run." }, true);
166240
+ if (!outcome) return text2({ error: "outcome is required for workflow_run." }, true);
165624
166241
  const result = await recordWorkflowRun2({
165625
166242
  workspace,
165626
166243
  run: {
@@ -165634,14 +166251,14 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
165634
166251
  selectedEvidence: [...new Set((evidenceIds ?? []).map((item) => item.trim()).filter(Boolean))]
165635
166252
  }
165636
166253
  });
165637
- return text({
166254
+ return text2({
165638
166255
  id: result.id,
165639
166256
  workflowId: result.workflowId,
165640
166257
  outcome: result.outcome,
165641
166258
  verificationVerdict: result.verificationVerdict
165642
166259
  });
165643
166260
  }
165644
- return text({ error: "Unsupported knowledge action." }, true);
166261
+ return text2({ error: "Unsupported knowledge action." }, true);
165645
166262
  }
165646
166263
  );
165647
166264
  server.registerTool(
@@ -167116,10 +167733,10 @@ Ensure the path points to a directory containing a .git folder (or a subdirector
167116
167733
  ];
167117
167734
  const allSkills = await loadMiniSkills2(projectDir2, project.id);
167118
167735
  const miniSkills = allSkills.filter((s2) => {
167119
- const text = `${s2.title}
167736
+ const text2 = `${s2.title}
167120
167737
  ${s2.sourceEntity}
167121
167738
  ${s2.instruction}`.toLowerCase();
167122
- return !SKILL_NOISE.some((p) => p.test(text));
167739
+ return !SKILL_NOISE.some((p) => p.test(text2));
167123
167740
  });
167124
167741
  if (miniSkills.length > 0) {
167125
167742
  const formatted = formatMiniSkillsForInjection2(miniSkills);
@@ -168610,7 +169227,7 @@ var init_serve_shared = __esm({
168610
169227
 
168611
169228
  // src/cli/version.ts
168612
169229
  function getCliVersion() {
168613
- return true ? "1.4.1" : pkg.version;
169230
+ return true ? "1.4.2" : pkg.version;
168614
169231
  }
168615
169232
  var init_version3 = __esm({
168616
169233
  "src/cli/version.ts"() {