memorix 1.5.1 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +3 -3
  3. package/README.zh-CN.md +3 -3
  4. package/dist/cli/index.js +558 -102
  5. package/dist/cli/memcode.js +12 -1
  6. package/dist/index.js +221 -27
  7. package/dist/maintenance-runner.js +59 -11
  8. package/dist/media-audio-runner.js +59 -11
  9. package/dist/media-video-runner.js +59 -11
  10. package/dist/memcode-runtime/CHANGELOG.md +47 -0
  11. package/dist/sdk.js +220 -26
  12. package/dist/vector-backfill-runner.js +59 -11
  13. package/docs/1.2.4-PERSISTENT-MEMORY-DELIVERY.md +1 -1
  14. package/docs/AGENT_OPERATOR_PLAYBOOK.md +11 -3
  15. package/docs/API_REFERENCE.md +2 -2
  16. package/docs/DEVELOPMENT.md +5 -3
  17. package/docs/DOCKER.md +5 -1
  18. package/docs/PERFORMANCE.md +2 -2
  19. package/docs/README.md +3 -1
  20. package/docs/SETUP.md +8 -2
  21. package/package.json +1 -1
  22. package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
  23. package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
  24. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  25. package/plugins/copilot/memorix/plugin.json +1 -1
  26. package/plugins/gemini/memorix/gemini-extension.json +1 -1
  27. package/plugins/omp/memorix/package.json +1 -1
  28. package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
  29. package/plugins/pi/memorix/package.json +1 -1
  30. package/server.json +2 -2
  31. package/src/cli/commands/agent-integrations.ts +9 -3
  32. package/src/cli/commands/codegraph.ts +48 -5
  33. package/src/cli/commands/context.ts +20 -4
  34. package/src/cli/commands/doctor.ts +46 -15
  35. package/src/cli/commands/hook.ts +13 -1
  36. package/src/cli/commands/resume.ts +4 -0
  37. package/src/cli/commands/serve-http.ts +68 -7
  38. package/src/cli/heap.ts +76 -0
  39. package/src/cli/invocation.ts +7 -4
  40. package/src/codegraph/auto-context.ts +4 -1
  41. package/src/codegraph/context-pack.ts +3 -1
  42. package/src/codegraph/external-provider.ts +93 -0
  43. package/src/embedding/provider.ts +76 -6
  44. package/src/hooks/handler.ts +9 -18
  45. package/src/hooks/installers/index.ts +1 -1
  46. package/src/hooks/lifecycle.ts +173 -0
  47. package/src/hooks/official-skills.ts +3 -3
  48. package/src/hooks/rules/memorix-agent-rules.md +1 -1
  49. package/src/knowledge/context-receipt.ts +41 -0
  50. package/src/knowledge/workflows.ts +6 -3
  51. package/src/knowledge/workset.ts +56 -2
  52. package/src/server.ts +15 -3
package/dist/sdk.js CHANGED
@@ -4442,6 +4442,7 @@ __export(provider_exports, {
4442
4442
  MAX_INLINE_EMBEDDING_BYTES: () => MAX_INLINE_EMBEDDING_BYTES,
4443
4443
  UnsupportedEmbeddingModalityError: () => UnsupportedEmbeddingModalityError,
4444
4444
  getEmbeddingProvider: () => getEmbeddingProvider,
4445
+ getEmbeddingRuntimeHealth: () => getEmbeddingRuntimeHealth,
4445
4446
  isEmbeddingExplicitlyDisabled: () => isEmbeddingExplicitlyDisabled,
4446
4447
  isVectorSearchAvailable: () => isVectorSearchAvailable,
4447
4448
  resetProvider: () => resetProvider,
@@ -4549,13 +4550,36 @@ function isTemporaryEmbeddingFailure(error) {
4549
4550
  if (!(error instanceof Error)) return false;
4550
4551
  return /embedding api error \(401\)/i.test(error.message) || /invalid_api_key/i.test(error.message) || /incorrect api key/i.test(error.message) || /unauthorized/i.test(error.message) || /embedding api timeout/i.test(error.message) || /embedding api error \((402|429|5\d\d)\)/i.test(error.message) || /quota exceeded/i.test(error.message) || /account balance/i.test(error.message) || /fetch failed/i.test(error.message) || /econnreset/i.test(error.message) || /econnrefused/i.test(error.message) || /temporarily unavailable/i.test(error.message);
4551
4552
  }
4553
+ function classifyEmbeddingFailure(error) {
4554
+ const message = error instanceof Error ? error.message : String(error);
4555
+ if (/embedding api error \(401\)|invalid_api_key|incorrect api key|unauthorized/i.test(message)) {
4556
+ return "authorization";
4557
+ }
4558
+ if (/embedding api error \(402\)|quota exceeded|account balance/i.test(message)) {
4559
+ return "billing";
4560
+ }
4561
+ if (/embedding api timeout|abort/i.test(message)) {
4562
+ return "timeout";
4563
+ }
4564
+ return "upstream";
4565
+ }
4552
4566
  function markTemporaryFailure(reason) {
4553
4567
  provider = null;
4554
4568
  initPromise = null;
4555
4569
  lastInitWasTemporaryFailure = true;
4556
4570
  lastFailureTimestamp = Date.now();
4571
+ lastEmbeddingFailure = {
4572
+ kind: classifyEmbeddingFailure(reason),
4573
+ occurredAt: lastFailureTimestamp
4574
+ };
4557
4575
  const message = reason instanceof Error ? reason.message : String(reason);
4558
- warnOnce(`[memorix] Embedding provider temporarily unavailable at runtime: ${message}`);
4576
+ warnOnce(`[memorix] Embedding provider unavailable at runtime: ${message}`);
4577
+ }
4578
+ function markProviderReady(candidate) {
4579
+ provider = wrapProvider(candidate);
4580
+ lastInitWasTemporaryFailure = false;
4581
+ lastEmbeddingFailure = null;
4582
+ return provider;
4559
4583
  }
4560
4584
  async function createFastEmbedProvider() {
4561
4585
  try {
@@ -4671,35 +4695,35 @@ async function getEmbeddingProvider(options = {}) {
4671
4695
  if (mode === "fastembed") {
4672
4696
  const initialized = await createFastEmbedProvider();
4673
4697
  if (!initialized) return null;
4674
- provider = wrapProvider(initialized);
4698
+ provider = markProviderReady(initialized);
4675
4699
  warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
4676
4700
  return provider;
4677
4701
  }
4678
4702
  if (mode === "transformers") {
4679
4703
  const initialized = await createTransformersProvider();
4680
4704
  if (!initialized) return null;
4681
- provider = wrapProvider(initialized);
4705
+ provider = markProviderReady(initialized);
4682
4706
  warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
4683
4707
  return provider;
4684
4708
  }
4685
4709
  if (mode === "api") {
4686
4710
  const initialized = await createAPIProvider(options);
4687
4711
  if (!initialized) return null;
4688
- provider = wrapProvider(initialized);
4712
+ provider = markProviderReady(initialized);
4689
4713
  warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
4690
4714
  return provider;
4691
4715
  }
4692
4716
  if (hasAPIEmbeddingConfig()) {
4693
4717
  const initialized = await createAPIProvider(options);
4694
4718
  if (initialized) {
4695
- provider = wrapProvider(initialized);
4719
+ provider = markProviderReady(initialized);
4696
4720
  warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
4697
4721
  return provider;
4698
4722
  }
4699
4723
  }
4700
4724
  const localFallback = await createLocalFallbackProvider();
4701
4725
  if (localFallback) {
4702
- provider = wrapProvider(localFallback);
4726
+ provider = markProviderReady(localFallback);
4703
4727
  warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
4704
4728
  return provider;
4705
4729
  }
@@ -4721,6 +4745,27 @@ async function isVectorSearchAvailable() {
4721
4745
  const p = await getEmbeddingProvider();
4722
4746
  return p !== null;
4723
4747
  }
4748
+ function getEmbeddingRuntimeHealth() {
4749
+ const mode = getEmbeddingMode2();
4750
+ if (mode === "off") return { status: "disabled" };
4751
+ if (lastInitWasTemporaryFailure && lastEmbeddingFailure) {
4752
+ return {
4753
+ status: "degraded",
4754
+ failure: {
4755
+ kind: lastEmbeddingFailure.kind,
4756
+ occurredAt: new Date(lastEmbeddingFailure.occurredAt).toISOString(),
4757
+ retryAfterMs: Math.max(0, RETRY_COOLDOWN_MS - (Date.now() - lastEmbeddingFailure.occurredAt))
4758
+ }
4759
+ };
4760
+ }
4761
+ if (provider) {
4762
+ return {
4763
+ status: "ready",
4764
+ provider: { name: provider.name, dimensions: provider.dimensions }
4765
+ };
4766
+ }
4767
+ return { status: "uninitialized" };
4768
+ }
4724
4769
  function isEmbeddingExplicitlyDisabled() {
4725
4770
  return getEmbeddingMode2() === "off";
4726
4771
  }
@@ -4729,10 +4774,11 @@ function resetProvider() {
4729
4774
  initPromise = null;
4730
4775
  lastInitWasTemporaryFailure = false;
4731
4776
  lastFailureTimestamp = 0;
4777
+ lastEmbeddingFailure = null;
4732
4778
  lastEmbeddingWarning = "";
4733
4779
  lastEmbeddingWarningAt = 0;
4734
4780
  }
4735
- var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
4781
+ var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
4736
4782
  var init_provider = __esm({
4737
4783
  "src/embedding/provider.ts"() {
4738
4784
  "use strict";
@@ -4757,6 +4803,7 @@ var init_provider = __esm({
4757
4803
  provider = null;
4758
4804
  initPromise = null;
4759
4805
  lastInitWasTemporaryFailure = false;
4806
+ lastEmbeddingFailure = null;
4760
4807
  lastEmbeddingWarning = "";
4761
4808
  lastEmbeddingWarningAt = 0;
4762
4809
  WARNING_COOLDOWN_MS = 3e4;
@@ -148862,6 +148909,7 @@ var init_task_lens = __esm({
148862
148909
  var workflows_exports = {};
148863
148910
  __export(workflows_exports, {
148864
148911
  WORKFLOW_ADAPTER_TARGETS: () => WORKFLOW_ADAPTER_TARGETS,
148912
+ WORKFLOW_AGENT_TARGETS: () => WORKFLOW_AGENT_TARGETS,
148865
148913
  applyWorkflowAdapter: () => applyWorkflowAdapter,
148866
148914
  importWindsurfWorkflows: () => importWindsurfWorkflows,
148867
148915
  parseWorkflowMarkdown: () => parseWorkflowMarkdown,
@@ -148927,7 +148975,7 @@ function optionalStatus(data) {
148927
148975
  return value;
148928
148976
  }
148929
148977
  function normalizeAgents(values) {
148930
- const unknown3 = values.filter((value) => !KNOWN_AGENTS.includes(value));
148978
+ const unknown3 = values.filter((value) => !WORKFLOW_AGENT_TARGETS.includes(value));
148931
148979
  if (unknown3.length > 0) {
148932
148980
  throw new Error("workflow frontmatter has unsupported agent: " + unknown3[0]);
148933
148981
  }
@@ -149203,7 +149251,7 @@ function taskScore(workflow, task) {
149203
149251
  return { score, reasons: [...new Set(reasons)] };
149204
149252
  }
149205
149253
  function selectWorkflows(input) {
149206
- const selected = input.workflows.filter((workflow) => workflow.status === "active").map((workflow) => {
149254
+ const selected = input.workflows.filter((workflow) => workflow.status === "active" && (!input.agent || workflow.compatibleAgents.includes(input.agent))).map((workflow) => {
149207
149255
  const match2 = taskScore(workflow, input.task);
149208
149256
  const cautions = input.store && input.projectId ? input.store.recentFailureCautions(input.projectId, workflow.id) : [];
149209
149257
  return {
@@ -149483,7 +149531,7 @@ async function selectWorkspaceWorkflows(input) {
149483
149531
  errors: synced.errors
149484
149532
  };
149485
149533
  }
149486
- var KNOWN_AGENTS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
149534
+ var WORKFLOW_AGENT_TARGETS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
149487
149535
  var init_workflows2 = __esm({
149488
149536
  "src/knowledge/workflows.ts"() {
149489
149537
  "use strict";
@@ -149495,7 +149543,7 @@ var init_workflows2 = __esm({
149495
149543
  init_workflow_store();
149496
149544
  init_outcome_store();
149497
149545
  init_task_lens();
149498
- KNOWN_AGENTS = [
149546
+ WORKFLOW_AGENT_TARGETS = [
149499
149547
  "windsurf",
149500
149548
  "cursor",
149501
149549
  "claude-code",
@@ -153146,6 +153194,15 @@ function workflowOutput(selection) {
153146
153194
  cautions: selection.cautions.map((caution) => short(caution, 22))
153147
153195
  };
153148
153196
  }
153197
+ function workflowLoadout(agent, selections) {
153198
+ if (!agent) return void 0;
153199
+ return {
153200
+ agent,
153201
+ workflowIds: selections.map((selection) => selection.workflow.id),
153202
+ requiredContext: unique(selections.flatMap((selection) => selection.workflow.requiredContext)).map((item) => short(item, 18)).slice(0, 4),
153203
+ allowedTools: unique(selections.flatMap((selection) => selection.workflow.allowedTools)).map((item) => short(item, 12)).slice(0, 6)
153204
+ };
153205
+ }
153149
153206
  function appendLine(lines, candidate, maxTokens, omitted, omittedKind, selected, receiptSelection) {
153150
153207
  const next = lines.length ? lines.join("\n") + "\n" + candidate : candidate;
153151
153208
  if (countTextTokens(next) <= maxTokens) {
@@ -153606,6 +153663,22 @@ function renderTaskWorksetPrompt(input) {
153606
153663
  );
153607
153664
  }
153608
153665
  }
153666
+ if (input.agentLoadout) {
153667
+ appendLine(lines, "", maxTokens, omitted, "agent-loadout-heading");
153668
+ appendLine(lines, "Agent loadout (" + input.agentLoadout.agent + ")", maxTokens, omitted, "agent-loadout-heading");
153669
+ for (const required of input.agentLoadout.requiredContext.slice(0, 2)) {
153670
+ appendLine(lines, "- Need: " + required, maxTokens, omitted, "agent-loadout-context");
153671
+ }
153672
+ if (input.agentLoadout.allowedTools.length > 0) {
153673
+ appendLine(
153674
+ lines,
153675
+ "- Workflow tools: " + input.agentLoadout.allowedTools.join(", "),
153676
+ maxTokens,
153677
+ omitted,
153678
+ "agent-loadout-tools"
153679
+ );
153680
+ }
153681
+ }
153609
153682
  if (input.verification.length > 0) {
153610
153683
  appendLine(lines, "", maxTokens, omitted, "verification-heading");
153611
153684
  appendLine(lines, "Verify", maxTokens, omitted, "verification-heading");
@@ -153697,6 +153770,7 @@ async function buildTaskWorkset(input) {
153697
153770
  let workspace;
153698
153771
  let pages = [];
153699
153772
  let workflows = [];
153773
+ let workflowSelections = [];
153700
153774
  try {
153701
153775
  workspace = await preferredWorkspace(input.projectId, input.dataDir);
153702
153776
  if (workspace) {
@@ -153713,14 +153787,15 @@ async function buildTaskWorkset(input) {
153713
153787
  if (task) {
153714
153788
  const workflowStore = new WorkflowStore();
153715
153789
  await workflowStore.init(input.dataDir);
153716
- const selected = selectWorkflows({
153790
+ workflowSelections = selectWorkflows({
153717
153791
  workflows: workflowStore.listWorkflows(workspace.id, "active"),
153718
153792
  task,
153719
153793
  projectId: input.projectId,
153720
153794
  store: workflowStore,
153795
+ ...input.agent ? { agent: input.agent } : {},
153721
153796
  limit: 2
153722
153797
  });
153723
- workflows = selected.map(workflowOutput);
153798
+ workflows = workflowSelections.map(workflowOutput);
153724
153799
  for (const workflow of workflows) {
153725
153800
  for (const caution of workflow.cautions) {
153726
153801
  cautions.push({ kind: "workflow-failed-verification", message: caution });
@@ -153742,6 +153817,10 @@ async function buildTaskWorkset(input) {
153742
153817
  workflows
153743
153818
  });
153744
153819
  const governedDurableIds = new Set(governed.durableMemory.map((memory) => memory.id));
153820
+ const agentLoadout = workflowLoadout(
153821
+ input.agent,
153822
+ workflowSelections.filter((selection2) => governed.workflows.some((workflow) => workflow.id === selection2.workflow.id))
153823
+ );
153745
153824
  const evidenceIds = unique(governed.claims.flatMap((claim) => evidenceIdsForClaim(
153746
153825
  claim,
153747
153826
  evidenceByClaim.get(claim.id) ?? []
@@ -153786,6 +153865,7 @@ async function buildTaskWorkset(input) {
153786
153865
  pages: pages.filter((page) => page.claimIds.some((claimId) => governed.claims.some((claim) => claim.id === claimId))),
153787
153866
  durableMemory: governed.durableMemory,
153788
153867
  workflows: governed.workflows,
153868
+ ...agentLoadout ? { agentLoadout } : {},
153789
153869
  cautions: normalizedCautions,
153790
153870
  verification,
153791
153871
  evidenceIds,
@@ -154004,10 +154084,12 @@ var init_current_facts = __esm({
154004
154084
  var external_provider_exports = {};
154005
154085
  __export(external_provider_exports, {
154006
154086
  DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS: () => DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS,
154087
+ EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS: () => EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS,
154007
154088
  MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES: () => MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES,
154008
154089
  MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS: () => MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS,
154009
154090
  getExternalCodeGraphContext: () => getExternalCodeGraphContext,
154010
- inspectExternalCodeGraph: () => inspectExternalCodeGraph
154091
+ inspectExternalCodeGraph: () => inspectExternalCodeGraph,
154092
+ runExternalCodeGraphLifecycle: () => runExternalCodeGraphLifecycle
154011
154093
  });
154012
154094
  import { spawn as spawn5 } from "child_process";
154013
154095
  import { existsSync as existsSync15, readFileSync as readFileSync10 } from "fs";
@@ -154206,6 +154288,66 @@ async function inspectExternalCodeGraph(input) {
154206
154288
  const health = healthFromStatus(status);
154207
154289
  return { health, quality: providerQuality({ mode, health }) };
154208
154290
  }
154291
+ async function runExternalCodeGraphLifecycle(input) {
154292
+ const mode = input.mode ?? "auto";
154293
+ if (mode === "off") {
154294
+ const health = { state: "disabled", reason: "External CodeGraph is disabled by configuration." };
154295
+ return {
154296
+ action: input.action,
154297
+ performed: false,
154298
+ message: "External CodeGraph is disabled by configuration.",
154299
+ health,
154300
+ quality: providerQuality({ mode, health })
154301
+ };
154302
+ }
154303
+ const indexPath = join20(input.projectRoot, ".codegraph");
154304
+ if (input.action === "sync" && !existsSync15(indexPath)) {
154305
+ const health = { state: "not-detected", reason: "No local .codegraph index is present for this project." };
154306
+ return {
154307
+ action: input.action,
154308
+ performed: false,
154309
+ message: 'Initialize CodeGraph first with "memorix codegraph init".',
154310
+ health,
154311
+ quality: providerQuality({ mode, health })
154312
+ };
154313
+ }
154314
+ if (input.action === "init" && existsSync15(indexPath)) {
154315
+ const inspected2 = await inspectExternalCodeGraph(input);
154316
+ return {
154317
+ action: input.action,
154318
+ performed: false,
154319
+ message: "A local CodeGraph directory already exists; no initialization was performed.",
154320
+ ...inspected2
154321
+ };
154322
+ }
154323
+ const result = await runSafely(input.runner ?? defaultRunner, {
154324
+ command: input.command,
154325
+ args: input.action === "init" ? ["init", input.projectRoot] : ["sync", input.projectRoot, "--quiet"],
154326
+ cwd: input.projectRoot,
154327
+ // A context read must stay fast; an explicit user-requested index sync is
154328
+ // a different operation and gets its own bounded maintenance window.
154329
+ timeoutMs: EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS,
154330
+ maxOutputBytes: MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES
154331
+ });
154332
+ if (!result.ok) {
154333
+ const health = unavailableHealth(result);
154334
+ return {
154335
+ action: input.action,
154336
+ performed: false,
154337
+ message: "CodeGraph " + input.action + " did not complete: " + (health.reason ?? "unknown local error"),
154338
+ health,
154339
+ quality: providerQuality({ mode, health })
154340
+ };
154341
+ }
154342
+ const inspected = await inspectExternalCodeGraph(input);
154343
+ const remainsStale = inspected.health.state === "stale";
154344
+ return {
154345
+ action: input.action,
154346
+ performed: true,
154347
+ message: input.action === "init" ? 'Local CodeGraph initialization completed. Run "memorix codegraph sync" when source changes.' : remainsStale ? "Local CodeGraph synchronization completed, but the graph remains stale against the current worktree; this task will use Lite evidence." : "Local CodeGraph synchronization completed and is ready for task-scoped semantic context.",
154348
+ ...inspected
154349
+ };
154350
+ }
154209
154351
  function safeRelativePath(projectRoot, value, exclude) {
154210
154352
  const path34 = safeText(value, 1024);
154211
154353
  if (!path34 || isAbsolute(path34)) return void 0;
@@ -154331,7 +154473,7 @@ async function getExternalCodeGraphContext(input) {
154331
154473
  quality: providerQuality({ mode, health: inspected.health, ...contributes ? { selected: "external" } : {} })
154332
154474
  };
154333
154475
  }
154334
- var DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS, MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS, MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES, MAX_EXTERNAL_NODE_COUNT, MAX_EXTERNAL_EDGE_COUNT, MAX_EXTERNAL_FILE_COUNT, MAX_EXTERNAL_TEXT_LENGTH, LITE_SUPPORTED_LANGUAGES, defaultRunner;
154476
+ var DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS, MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS, EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS, MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES, MAX_EXTERNAL_NODE_COUNT, MAX_EXTERNAL_EDGE_COUNT, MAX_EXTERNAL_FILE_COUNT, MAX_EXTERNAL_TEXT_LENGTH, LITE_SUPPORTED_LANGUAGES, defaultRunner;
154335
154477
  var init_external_provider = __esm({
154336
154478
  "src/codegraph/external-provider.ts"() {
154337
154479
  "use strict";
@@ -154341,6 +154483,7 @@ var init_external_provider = __esm({
154341
154483
  init_ids();
154342
154484
  DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS = 1200;
154343
154485
  MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS = 5e3;
154486
+ EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS = 3e4;
154344
154487
  MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES = 256 * 1024;
154345
154488
  MAX_EXTERNAL_NODE_COUNT = 16;
154346
154489
  MAX_EXTERNAL_EDGE_COUNT = 24;
@@ -155166,6 +155309,7 @@ async function buildAutoProjectContext(input) {
155166
155309
  projectId: input.project.id,
155167
155310
  dataDir: input.dataDir,
155168
155311
  ...task ? { task } : {},
155312
+ ...input.agent ? { agent: input.agent } : {},
155169
155313
  lens: lens.id,
155170
155314
  startHere,
155171
155315
  ...alwaysOn.profile.length > 0 || alwaysOn.state || alwaysOn.durable.length > 0 ? { alwaysOn } : {},
@@ -155502,6 +155646,34 @@ var init_auto_context = __esm({
155502
155646
  }
155503
155647
  });
155504
155648
 
155649
+ // src/knowledge/context-receipt.ts
155650
+ var context_receipt_exports = {};
155651
+ __export(context_receipt_exports, {
155652
+ buildBoundedContextReceipt: () => buildBoundedContextReceipt
155653
+ });
155654
+ function buildBoundedContextReceipt(input) {
155655
+ const provider2 = input.providerQuality ?? input.workset.provenance.codeProvider;
155656
+ return {
155657
+ schemaVersion: "1",
155658
+ task: input.workset.task,
155659
+ brief: input.workset.prompt,
155660
+ receipt: input.workset.receipt,
155661
+ code: {
155662
+ selected: provider2?.selected ?? "lite",
155663
+ quality: provider2?.selectedQuality ?? "heuristic",
155664
+ externalState: provider2?.external.state ?? "not-detected",
155665
+ ...input.workset.provenance.snapshotId ? { snapshotId: input.workset.provenance.snapshotId } : {}
155666
+ },
155667
+ ...input.workset.agentLoadout ? { loadout: input.workset.agentLoadout } : {}
155668
+ };
155669
+ }
155670
+ var init_context_receipt = __esm({
155671
+ "src/knowledge/context-receipt.ts"() {
155672
+ "use strict";
155673
+ init_esm_shims();
155674
+ }
155675
+ });
155676
+
155505
155677
  // src/codegraph/context-pack.ts
155506
155678
  var context_pack_exports = {};
155507
155679
  __export(context_pack_exports, {
@@ -155660,6 +155832,7 @@ async function attachTaskWorkset(input) {
155660
155832
  projectId: input.projectId,
155661
155833
  dataDir: input.dataDir,
155662
155834
  task: input.pack.task,
155835
+ ...input.agent ? { agent: input.agent } : {},
155663
155836
  lens: input.lens,
155664
155837
  currentFacts: input.currentFacts ?? [],
155665
155838
  ...input.codeState ? { codeState: input.codeState } : {},
@@ -160052,8 +160225,8 @@ var init_official_skills = __esm({
160052
160225
  "",
160053
160226
  "| Situation | Prefer | CLI fallback |",
160054
160227
  "|---|---|---|",
160055
- '| Starting a coding task and needing the best task-lensed project map | `memorix_project_context` with the user\'s task | `memorix context "<task>" --json` |',
160056
- '| Continuing prior project work | `memorix_project_context` with the user\'s task | `memorix resume "<task>" --json` |',
160228
+ '| Starting a coding task and needing the best task-lensed project map | `memorix_project_context` with the user\'s task | `memorix context "<task>" --brief-json` |',
160229
+ '| Continuing prior project work | `memorix_project_context` with the user\'s task | `memorix resume "<task>" --brief-json` |',
160057
160230
  '| Need structured refs/freshness for code-bound memories | `memorix_context_pack` | `memorix codegraph context-pack --task "<topic>"` |',
160058
160231
  '| Explicit memory graph question | `memorix_graph_context` | `memorix memory graph-context --query "<topic>"` |',
160059
160232
  '| Specific past decision, bug, file, or change | `memorix_search` | `memorix memory search --query "<topic>"` |',
@@ -160066,7 +160239,7 @@ var init_official_skills = __esm({
160066
160239
  "",
160067
160240
  "- Default first step for non-trivial coding work: call `memorix_project_context` before progress files, dev-log reads, ad-hoc file reads, or git archaeology. Pass the user's actual task so Memorix can choose a bugfix, feature, release, onboarding, refactor, docs, test, or general brief. Start by reading its suggested files.",
160068
160241
  "- In Claude Code headless/print-mode, an initial MCP `pending` status is not a failure by itself. Prefer MCP first: use the client's tool discovery/dynamic loading to find `memorix_project_context` when it is not in the first visible tool list.",
160069
- '- Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run `memorix resume "<task>" --json` exactly once before inspecting files, Git history, progress notes, or guessing. The absence of `.memorix` or visible memory files never proves project memory is empty. For a new task, use `memorix context "<task>" --json` instead. If that one command fails, report it and proceed normally; do not probe help, enumerate commands, or chain broad searches.',
160242
+ '- Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run `memorix resume "<task>" --brief-json` exactly once before inspecting files, Git history, progress notes, or guessing. The absence of `.memorix` or visible memory files never proves project memory is empty. For a new task, use `memorix context "<task>" --brief-json` instead. Use `--json` only when a diagnostic needs the detailed legacy payload. If that one command fails, report it and proceed normally; do not probe help, enumerate commands, or chain broad searches.',
160070
160243
  "- After a successful `memorix_project_context`, the brief is the default retrieval boundary. Do not call more Memorix retrieval tools after a complete brief. Use Context Pack, search, or detail only when the brief lacks a specific reference, freshness field, or fact needed for the task, or when the user explicitly asks for deeper history. In MCP, name that missing fact in `purpose` when intentionally expanding beyond the brief. Do not retrieve the same decision twice just to confirm an already-complete brief.",
160071
160244
  "- If the user asks for read-only work or says not to modify files, do not call `memorix_store` just to record an assessment. Store only when the user explicitly asks to preserve it.",
160072
160245
  "- Use `memorix_search` for a specific decision, bug, file, or prior change that the project context did not answer. Fetch detail only for a result you still need after the brief.",
@@ -161325,7 +161498,7 @@ alwaysApply: true
161325
161498
  "",
161326
161499
  `Default first step for non-trivial coding work: call \`memorix_project_context\` with the user's actual task before progress files, dev-log reads, ad-hoc file reads, or git archaeology. Memorix will choose a task-lensed brief (bugfix, feature, release, onboarding, refactor, docs, test, or general). When the task is continuing prior work, the same brief also includes a bounded prior-work projection. Treat its "Start here" files as the first ${contextNoun} files to inspect.`,
161327
161500
  "",
161328
- 'If the MCP tool is not visible yet but the client supports tool discovery or dynamic loading, search/select `memorix_project_context` first. Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run exactly one CLI brief with the user\'s real task before inspecting files, Git history, progress notes, or guessing: `memorix resume "<task>" --json`. For a new task, use `memorix context "<task>" --json` instead. The absence of `.memorix` or visible memory files never proves project memory is empty. If that one command fails, report it and proceed normally. Do not probe help, enumerate commands, chain broad searches, wait indefinitely on MCP startup, or hand-write tool-call syntax.',
161501
+ 'If the MCP tool is not visible yet but the client supports tool discovery or dynamic loading, search/select `memorix_project_context` first. Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run exactly one CLI brief with the user\'s real task before inspecting files, Git history, progress notes, or guessing: `memorix resume "<task>" --brief-json`. For a new task, use `memorix context "<task>" --brief-json` instead. The absence of `.memorix` or visible memory files never proves project memory is empty. Use `--json` only when a diagnostic needs the detailed legacy payload. If that one command fails, report it and proceed normally. Do not probe help, enumerate commands, chain broad searches, wait indefinitely on MCP startup, or hand-write tool-call syntax.',
161329
161502
  "",
161330
161503
  "After a successful `memorix_project_context` result, the brief is the default retrieval boundary. Do not call more Memorix retrieval tools after a complete brief. Use `memorix_context_pack`, `memorix_search`, or `memorix_detail` only when the brief lacks a specific reference, freshness field, or fact needed for the task, or when the user explicitly asks for deeper history. In MCP, name that missing fact in `purpose` when intentionally expanding beyond the brief. Do not retrieve the same decision twice just to confirm an already-complete brief.",
161331
161504
  "If the user asks for read-only work or says not to modify files, do not call `memorix_store` just to record an assessment. Store only when the user explicitly asks to preserve it.",
@@ -165778,7 +165951,7 @@ The path should point to a directory containing a .git folder.`
165778
165951
  };
165779
165952
  const server = existingServer ?? new McpServer({
165780
165953
  name: "memorix",
165781
- version: true ? "1.5.1" : "1.0.1"
165954
+ version: true ? "1.6.1" : "1.0.1"
165782
165955
  });
165783
165956
  const originalRegisterTool = server.registerTool.bind(server);
165784
165957
  server.registerTool = ((name, ...args) => {
@@ -166612,13 +166785,28 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
166612
166785
  refresh: z626.enum(["auto", "always", "never"]).optional().default("auto").describe(
166613
166786
  "Code Memory refresh policy. auto refreshes only when missing or stale."
166614
166787
  ),
166615
- format: z626.enum(["prompt", "summary", "json"]).optional().default("prompt").describe(
166616
- 'Output format. "prompt" is agent-ready; "summary" is human-readable; "json" is structured.'
166788
+ format: z626.enum(["prompt", "summary", "json", "receipt"]).optional().default("prompt").describe(
166789
+ 'Output format. "prompt" is agent-ready; "summary" is human-readable; "receipt" is bounded JSON; "json" is detailed diagnostics.'
166617
166790
  ),
166791
+ agent: z626.enum([
166792
+ "windsurf",
166793
+ "cursor",
166794
+ "claude-code",
166795
+ "codex",
166796
+ "copilot",
166797
+ "antigravity",
166798
+ "gemini-cli",
166799
+ "openclaw",
166800
+ "hermes",
166801
+ "omp",
166802
+ "kiro",
166803
+ "opencode",
166804
+ "trae"
166805
+ ]).optional().describe("Optional target agent for compatible workflow selection."),
166618
166806
  limit: z626.number().optional().describe("Reserved for future source limits; current prompt stays compact by default.")
166619
166807
  }
166620
166808
  },
166621
- async ({ task, refresh, format }) => {
166809
+ async ({ task, refresh, format, agent }) => {
166622
166810
  const unresolved = requireResolvedProject("build project context for the current project");
166623
166811
  if (unresolved) return unresolved;
166624
166812
  const [
@@ -166630,12 +166818,14 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
166630
166818
  },
166631
166819
  { getObservationStore: getObservationStore2 },
166632
166820
  { MaintenanceJobStore: MaintenanceJobStore2 },
166633
- { enqueueCodegraphRefresh: enqueueCodegraphRefresh2 }
166821
+ { enqueueCodegraphRefresh: enqueueCodegraphRefresh2 },
166822
+ { buildBoundedContextReceipt: buildBoundedContextReceipt2 }
166634
166823
  ] = await Promise.all([
166635
166824
  Promise.resolve().then(() => (init_auto_context(), auto_context_exports)),
166636
166825
  Promise.resolve().then(() => (init_obs_store(), obs_store_exports)),
166637
166826
  Promise.resolve().then(() => (init_maintenance_jobs(), maintenance_jobs_exports)),
166638
- Promise.resolve().then(() => (init_lifecycle(), lifecycle_exports))
166827
+ Promise.resolve().then(() => (init_lifecycle(), lifecycle_exports)),
166828
+ Promise.resolve().then(() => (init_context_receipt(), context_receipt_exports))
166639
166829
  ]);
166640
166830
  const observations2 = filterReadableObservations(
166641
166831
  await getObservationStore2().loadByProject(project.id, { status: "active" }),
@@ -166646,6 +166836,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
166646
166836
  dataDir: projectDir2,
166647
166837
  observations: observations2,
166648
166838
  task,
166839
+ agent,
166649
166840
  refresh: refresh ?? "auto",
166650
166841
  reader: getObservationReader(),
166651
166842
  enqueueRefresh: () => {
@@ -166658,7 +166849,10 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
166658
166849
  });
166659
166850
  }
166660
166851
  });
166661
- const text2 = format === "json" ? JSON.stringify({ ...context, brief: buildAutoProjectBrief2(context) }, null, 2) : format === "summary" ? formatAutoProjectContextSummary2(context) : formatAutoProjectContextPrompt2(context);
166852
+ const text2 = format === "json" ? JSON.stringify({ ...context, brief: buildAutoProjectBrief2(context) }, null, 2) : format === "receipt" ? JSON.stringify(buildBoundedContextReceipt2({
166853
+ workset: context.workset,
166854
+ providerQuality: context.providerQuality
166855
+ }), null, 2) : format === "summary" ? formatAutoProjectContextSummary2(context) : formatAutoProjectContextPrompt2(context);
166662
166856
  autopilotRetrievalBoundary = {
166663
166857
  projectId: project.id,
166664
166858
  issuedAt: Date.now(),