memorix 1.5.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +3 -3
  3. package/README.zh-CN.md +3 -3
  4. package/TEAM.md +86 -86
  5. package/dist/cli/index.js +243 -42
  6. package/dist/cli/memcode.js +0 -0
  7. package/dist/index.js +167 -20
  8. package/dist/maintenance-runner.js +5 -4
  9. package/dist/media-audio-runner.js +5 -4
  10. package/dist/media-video-runner.js +5 -4
  11. package/dist/memcode-runtime/CHANGELOG.md +23 -0
  12. package/dist/sdk.js +166 -19
  13. package/dist/vector-backfill-runner.js +5 -4
  14. package/docs/1.2.4-PERSISTENT-MEMORY-DELIVERY.md +1 -1
  15. package/docs/API_REFERENCE.md +1 -1
  16. package/docs/DESIGN_DECISIONS.md +357 -357
  17. package/docs/DEVELOPMENT.md +5 -3
  18. package/package.json +1 -1
  19. package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
  20. package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
  21. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  22. package/plugins/copilot/memorix/plugin.json +1 -1
  23. package/plugins/gemini/memorix/gemini-extension.json +1 -1
  24. package/plugins/omp/memorix/package.json +1 -1
  25. package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
  26. package/plugins/pi/memorix/package.json +1 -1
  27. package/server.json +2 -2
  28. package/src/audit/index.ts +156 -156
  29. package/src/cli/commands/codegraph.ts +48 -5
  30. package/src/cli/commands/context.ts +20 -4
  31. package/src/cli/commands/formation.ts +48 -48
  32. package/src/cli/commands/git-hook-install.ts +111 -111
  33. package/src/cli/commands/handoff.ts +54 -54
  34. package/src/cli/commands/hooks-status.ts +63 -63
  35. package/src/cli/commands/ingest.ts +44 -44
  36. package/src/cli/commands/integrate-shared.ts +15 -15
  37. package/src/cli/commands/lock.ts +82 -82
  38. package/src/cli/commands/message.ts +104 -104
  39. package/src/cli/commands/poll.ts +58 -58
  40. package/src/cli/commands/reasoning.ts +118 -118
  41. package/src/cli/commands/resume.ts +4 -0
  42. package/src/cli/commands/skills.ts +114 -114
  43. package/src/cli/commands/task.ts +167 -167
  44. package/src/cli/commands/transfer.ts +47 -47
  45. package/src/cli/index.ts +406 -406
  46. package/src/cli/tui/ChatView.tsx +234 -234
  47. package/src/cli/tui/CommandBar.tsx +312 -312
  48. package/src/cli/tui/ContextRail.tsx +118 -118
  49. package/src/cli/tui/HeaderBar.tsx +72 -72
  50. package/src/cli/tui/LogoBanner.tsx +51 -51
  51. package/src/cli/tui/index.ts +41 -41
  52. package/src/cli/version.ts +7 -7
  53. package/src/cli/workbench.ts +1 -1
  54. package/src/codegraph/auto-context.ts +4 -1
  55. package/src/codegraph/context-pack.ts +3 -1
  56. package/src/codegraph/external-provider.ts +93 -0
  57. package/src/dashboard/project-classification.ts +64 -64
  58. package/src/git/hooks-path.ts +85 -85
  59. package/src/hooks/installers/index.ts +1 -1
  60. package/src/hooks/official-skills.ts +3 -3
  61. package/src/hooks/pattern-detector.ts +173 -173
  62. package/src/hooks/rules/memorix-agent-rules.md +1 -1
  63. package/src/hooks/significance-filter.ts +250 -250
  64. package/src/knowledge/context-receipt.ts +41 -0
  65. package/src/knowledge/workflows.ts +6 -3
  66. package/src/knowledge/workset.ts +56 -2
  67. package/src/llm/memory-manager.ts +328 -328
  68. package/src/llm/quality.ts +248 -248
  69. package/src/memory/attribution-guard.ts +249 -249
  70. package/src/memory/disclosure-policy.ts +135 -135
  71. package/src/memory/entity-extractor.ts +197 -197
  72. package/src/memory/formation/evaluate.ts +217 -217
  73. package/src/memory/freshness.ts +122 -122
  74. package/src/memory/graph.ts +197 -197
  75. package/src/memory/refs.ts +94 -94
  76. package/src/memory/secret-filter.ts +79 -79
  77. package/src/orchestrate/adapters/claude-stream.ts +192 -192
  78. package/src/orchestrate/adapters/claude.ts +111 -111
  79. package/src/orchestrate/adapters/codex-stream.ts +134 -134
  80. package/src/orchestrate/adapters/codex.ts +41 -41
  81. package/src/orchestrate/adapters/gemini-stream.ts +166 -166
  82. package/src/orchestrate/adapters/gemini.ts +42 -42
  83. package/src/orchestrate/adapters/index.ts +73 -73
  84. package/src/orchestrate/adapters/opencode-stream.ts +143 -143
  85. package/src/orchestrate/adapters/opencode.ts +47 -47
  86. package/src/orchestrate/adapters/types.ts +77 -77
  87. package/src/orchestrate/capability-router.ts +284 -284
  88. package/src/orchestrate/cost-tracker.ts +219 -219
  89. package/src/orchestrate/error-recovery.ts +191 -191
  90. package/src/orchestrate/evidence.ts +140 -140
  91. package/src/orchestrate/ledger.ts +110 -110
  92. package/src/orchestrate/memorix-bridge.ts +343 -343
  93. package/src/orchestrate/output-budget.ts +80 -80
  94. package/src/orchestrate/permission.ts +152 -152
  95. package/src/orchestrate/pipeline-trace.ts +131 -131
  96. package/src/orchestrate/prompt-builder.ts +155 -155
  97. package/src/orchestrate/ring-buffer.ts +37 -37
  98. package/src/orchestrate/task-graph.ts +389 -389
  99. package/src/project/aliases.ts +374 -374
  100. package/src/rules/adapters/trae.ts +56 -56
  101. package/src/rules/syncer.ts +235 -235
  102. package/src/search/query-expansion.ts +52 -52
  103. package/src/server/formation-timeout.ts +27 -27
  104. package/src/server.ts +15 -3
  105. package/src/skills/mini-skills.ts +386 -386
  106. package/src/store/chat-store.ts +119 -119
  107. package/src/store/graph-store.ts +249 -249
  108. package/src/store/mini-skill-store.ts +349 -349
  109. package/src/store/persistence-json.ts +212 -212
  110. package/src/store/persistence.ts +291 -291
  111. package/src/store/project-affinity.ts +195 -195
  112. package/src/team/event-bus.ts +76 -76
  113. package/src/team/handoff.ts +161 -161
  114. package/src/team/poll.ts +132 -132
  115. package/src/workspace/mcp-adapters/codex.ts +191 -191
  116. package/src/workspace/mcp-adapters/copilot.ts +105 -105
  117. package/src/workspace/mcp-adapters/cursor.ts +53 -53
  118. package/src/workspace/mcp-adapters/kiro.ts +64 -64
  119. package/src/workspace/mcp-adapters/opencode.ts +123 -123
  120. package/src/workspace/mcp-adapters/trae.ts +134 -134
  121. package/src/workspace/mcp-adapters/windsurf.ts +91 -91
  122. package/src/workspace/sanitizer.ts +60 -60
package/dist/index.js CHANGED
@@ -148858,6 +148858,7 @@ var init_task_lens = __esm({
148858
148858
  var workflows_exports = {};
148859
148859
  __export(workflows_exports, {
148860
148860
  WORKFLOW_ADAPTER_TARGETS: () => WORKFLOW_ADAPTER_TARGETS,
148861
+ WORKFLOW_AGENT_TARGETS: () => WORKFLOW_AGENT_TARGETS,
148861
148862
  applyWorkflowAdapter: () => applyWorkflowAdapter,
148862
148863
  importWindsurfWorkflows: () => importWindsurfWorkflows,
148863
148864
  parseWorkflowMarkdown: () => parseWorkflowMarkdown,
@@ -148923,7 +148924,7 @@ function optionalStatus(data) {
148923
148924
  return value;
148924
148925
  }
148925
148926
  function normalizeAgents(values) {
148926
- const unknown3 = values.filter((value) => !KNOWN_AGENTS.includes(value));
148927
+ const unknown3 = values.filter((value) => !WORKFLOW_AGENT_TARGETS.includes(value));
148927
148928
  if (unknown3.length > 0) {
148928
148929
  throw new Error("workflow frontmatter has unsupported agent: " + unknown3[0]);
148929
148930
  }
@@ -149199,7 +149200,7 @@ function taskScore(workflow, task) {
149199
149200
  return { score, reasons: [...new Set(reasons)] };
149200
149201
  }
149201
149202
  function selectWorkflows(input) {
149202
- const selected = input.workflows.filter((workflow) => workflow.status === "active").map((workflow) => {
149203
+ const selected = input.workflows.filter((workflow) => workflow.status === "active" && (!input.agent || workflow.compatibleAgents.includes(input.agent))).map((workflow) => {
149203
149204
  const match2 = taskScore(workflow, input.task);
149204
149205
  const cautions = input.store && input.projectId ? input.store.recentFailureCautions(input.projectId, workflow.id) : [];
149205
149206
  return {
@@ -149479,7 +149480,7 @@ async function selectWorkspaceWorkflows(input) {
149479
149480
  errors: synced.errors
149480
149481
  };
149481
149482
  }
149482
- var KNOWN_AGENTS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
149483
+ var WORKFLOW_AGENT_TARGETS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
149483
149484
  var init_workflows2 = __esm({
149484
149485
  "src/knowledge/workflows.ts"() {
149485
149486
  "use strict";
@@ -149491,7 +149492,7 @@ var init_workflows2 = __esm({
149491
149492
  init_workflow_store();
149492
149493
  init_outcome_store();
149493
149494
  init_task_lens();
149494
- KNOWN_AGENTS = [
149495
+ WORKFLOW_AGENT_TARGETS = [
149495
149496
  "windsurf",
149496
149497
  "cursor",
149497
149498
  "claude-code",
@@ -157127,6 +157128,15 @@ function workflowOutput(selection) {
157127
157128
  cautions: selection.cautions.map((caution) => short(caution, 22))
157128
157129
  };
157129
157130
  }
157131
+ function workflowLoadout(agent, selections) {
157132
+ if (!agent) return void 0;
157133
+ return {
157134
+ agent,
157135
+ workflowIds: selections.map((selection) => selection.workflow.id),
157136
+ requiredContext: unique(selections.flatMap((selection) => selection.workflow.requiredContext)).map((item) => short(item, 18)).slice(0, 4),
157137
+ allowedTools: unique(selections.flatMap((selection) => selection.workflow.allowedTools)).map((item) => short(item, 12)).slice(0, 6)
157138
+ };
157139
+ }
157130
157140
  function appendLine(lines, candidate, maxTokens, omitted, omittedKind, selected, receiptSelection) {
157131
157141
  const next = lines.length ? lines.join("\n") + "\n" + candidate : candidate;
157132
157142
  if (countTextTokens(next) <= maxTokens) {
@@ -157587,6 +157597,22 @@ function renderTaskWorksetPrompt(input) {
157587
157597
  );
157588
157598
  }
157589
157599
  }
157600
+ if (input.agentLoadout) {
157601
+ appendLine(lines, "", maxTokens, omitted, "agent-loadout-heading");
157602
+ appendLine(lines, "Agent loadout (" + input.agentLoadout.agent + ")", maxTokens, omitted, "agent-loadout-heading");
157603
+ for (const required of input.agentLoadout.requiredContext.slice(0, 2)) {
157604
+ appendLine(lines, "- Need: " + required, maxTokens, omitted, "agent-loadout-context");
157605
+ }
157606
+ if (input.agentLoadout.allowedTools.length > 0) {
157607
+ appendLine(
157608
+ lines,
157609
+ "- Workflow tools: " + input.agentLoadout.allowedTools.join(", "),
157610
+ maxTokens,
157611
+ omitted,
157612
+ "agent-loadout-tools"
157613
+ );
157614
+ }
157615
+ }
157590
157616
  if (input.verification.length > 0) {
157591
157617
  appendLine(lines, "", maxTokens, omitted, "verification-heading");
157592
157618
  appendLine(lines, "Verify", maxTokens, omitted, "verification-heading");
@@ -157678,6 +157704,7 @@ async function buildTaskWorkset(input) {
157678
157704
  let workspace;
157679
157705
  let pages = [];
157680
157706
  let workflows = [];
157707
+ let workflowSelections = [];
157681
157708
  try {
157682
157709
  workspace = await preferredWorkspace(input.projectId, input.dataDir);
157683
157710
  if (workspace) {
@@ -157694,14 +157721,15 @@ async function buildTaskWorkset(input) {
157694
157721
  if (task) {
157695
157722
  const workflowStore = new WorkflowStore();
157696
157723
  await workflowStore.init(input.dataDir);
157697
- const selected = selectWorkflows({
157724
+ workflowSelections = selectWorkflows({
157698
157725
  workflows: workflowStore.listWorkflows(workspace.id, "active"),
157699
157726
  task,
157700
157727
  projectId: input.projectId,
157701
157728
  store: workflowStore,
157729
+ ...input.agent ? { agent: input.agent } : {},
157702
157730
  limit: 2
157703
157731
  });
157704
- workflows = selected.map(workflowOutput);
157732
+ workflows = workflowSelections.map(workflowOutput);
157705
157733
  for (const workflow of workflows) {
157706
157734
  for (const caution of workflow.cautions) {
157707
157735
  cautions.push({ kind: "workflow-failed-verification", message: caution });
@@ -157723,6 +157751,10 @@ async function buildTaskWorkset(input) {
157723
157751
  workflows
157724
157752
  });
157725
157753
  const governedDurableIds = new Set(governed.durableMemory.map((memory) => memory.id));
157754
+ const agentLoadout = workflowLoadout(
157755
+ input.agent,
157756
+ workflowSelections.filter((selection2) => governed.workflows.some((workflow) => workflow.id === selection2.workflow.id))
157757
+ );
157726
157758
  const evidenceIds = unique(governed.claims.flatMap((claim) => evidenceIdsForClaim(
157727
157759
  claim,
157728
157760
  evidenceByClaim.get(claim.id) ?? []
@@ -157767,6 +157799,7 @@ async function buildTaskWorkset(input) {
157767
157799
  pages: pages.filter((page) => page.claimIds.some((claimId) => governed.claims.some((claim) => claim.id === claimId))),
157768
157800
  durableMemory: governed.durableMemory,
157769
157801
  workflows: governed.workflows,
157802
+ ...agentLoadout ? { agentLoadout } : {},
157770
157803
  cautions: normalizedCautions,
157771
157804
  verification,
157772
157805
  evidenceIds,
@@ -157985,10 +158018,12 @@ var init_current_facts = __esm({
157985
158018
  var external_provider_exports = {};
157986
158019
  __export(external_provider_exports, {
157987
158020
  DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS: () => DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS,
158021
+ EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS: () => EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS,
157988
158022
  MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES: () => MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES,
157989
158023
  MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS: () => MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS,
157990
158024
  getExternalCodeGraphContext: () => getExternalCodeGraphContext,
157991
- inspectExternalCodeGraph: () => inspectExternalCodeGraph
158025
+ inspectExternalCodeGraph: () => inspectExternalCodeGraph,
158026
+ runExternalCodeGraphLifecycle: () => runExternalCodeGraphLifecycle
157992
158027
  });
157993
158028
  import { spawn as spawn5 } from "child_process";
157994
158029
  import { existsSync as existsSync15, readFileSync as readFileSync10 } from "fs";
@@ -158187,6 +158222,66 @@ async function inspectExternalCodeGraph(input) {
158187
158222
  const health = healthFromStatus(status);
158188
158223
  return { health, quality: providerQuality({ mode, health }) };
158189
158224
  }
158225
+ async function runExternalCodeGraphLifecycle(input) {
158226
+ const mode = input.mode ?? "auto";
158227
+ if (mode === "off") {
158228
+ const health = { state: "disabled", reason: "External CodeGraph is disabled by configuration." };
158229
+ return {
158230
+ action: input.action,
158231
+ performed: false,
158232
+ message: "External CodeGraph is disabled by configuration.",
158233
+ health,
158234
+ quality: providerQuality({ mode, health })
158235
+ };
158236
+ }
158237
+ const indexPath = join20(input.projectRoot, ".codegraph");
158238
+ if (input.action === "sync" && !existsSync15(indexPath)) {
158239
+ const health = { state: "not-detected", reason: "No local .codegraph index is present for this project." };
158240
+ return {
158241
+ action: input.action,
158242
+ performed: false,
158243
+ message: 'Initialize CodeGraph first with "memorix codegraph init".',
158244
+ health,
158245
+ quality: providerQuality({ mode, health })
158246
+ };
158247
+ }
158248
+ if (input.action === "init" && existsSync15(indexPath)) {
158249
+ const inspected2 = await inspectExternalCodeGraph(input);
158250
+ return {
158251
+ action: input.action,
158252
+ performed: false,
158253
+ message: "A local CodeGraph directory already exists; no initialization was performed.",
158254
+ ...inspected2
158255
+ };
158256
+ }
158257
+ const result = await runSafely(input.runner ?? defaultRunner, {
158258
+ command: input.command,
158259
+ args: input.action === "init" ? ["init", input.projectRoot] : ["sync", input.projectRoot, "--quiet"],
158260
+ cwd: input.projectRoot,
158261
+ // A context read must stay fast; an explicit user-requested index sync is
158262
+ // a different operation and gets its own bounded maintenance window.
158263
+ timeoutMs: EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS,
158264
+ maxOutputBytes: MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES
158265
+ });
158266
+ if (!result.ok) {
158267
+ const health = unavailableHealth(result);
158268
+ return {
158269
+ action: input.action,
158270
+ performed: false,
158271
+ message: "CodeGraph " + input.action + " did not complete: " + (health.reason ?? "unknown local error"),
158272
+ health,
158273
+ quality: providerQuality({ mode, health })
158274
+ };
158275
+ }
158276
+ const inspected = await inspectExternalCodeGraph(input);
158277
+ const remainsStale = inspected.health.state === "stale";
158278
+ return {
158279
+ action: input.action,
158280
+ performed: true,
158281
+ 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.",
158282
+ ...inspected
158283
+ };
158284
+ }
158190
158285
  function safeRelativePath(projectRoot, value, exclude) {
158191
158286
  const path37 = safeText(value, 1024);
158192
158287
  if (!path37 || isAbsolute(path37)) return void 0;
@@ -158312,7 +158407,7 @@ async function getExternalCodeGraphContext(input) {
158312
158407
  quality: providerQuality({ mode, health: inspected.health, ...contributes ? { selected: "external" } : {} })
158313
158408
  };
158314
158409
  }
158315
- 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;
158410
+ 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;
158316
158411
  var init_external_provider = __esm({
158317
158412
  "src/codegraph/external-provider.ts"() {
158318
158413
  "use strict";
@@ -158322,6 +158417,7 @@ var init_external_provider = __esm({
158322
158417
  init_ids();
158323
158418
  DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS = 1200;
158324
158419
  MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS = 5e3;
158420
+ EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS = 3e4;
158325
158421
  MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES = 256 * 1024;
158326
158422
  MAX_EXTERNAL_NODE_COUNT = 16;
158327
158423
  MAX_EXTERNAL_EDGE_COUNT = 24;
@@ -159147,6 +159243,7 @@ async function buildAutoProjectContext(input) {
159147
159243
  projectId: input.project.id,
159148
159244
  dataDir: input.dataDir,
159149
159245
  ...task ? { task } : {},
159246
+ ...input.agent ? { agent: input.agent } : {},
159150
159247
  lens: lens.id,
159151
159248
  startHere,
159152
159249
  ...alwaysOn.profile.length > 0 || alwaysOn.state || alwaysOn.durable.length > 0 ? { alwaysOn } : {},
@@ -159483,6 +159580,34 @@ var init_auto_context = __esm({
159483
159580
  }
159484
159581
  });
159485
159582
 
159583
+ // src/knowledge/context-receipt.ts
159584
+ var context_receipt_exports = {};
159585
+ __export(context_receipt_exports, {
159586
+ buildBoundedContextReceipt: () => buildBoundedContextReceipt
159587
+ });
159588
+ function buildBoundedContextReceipt(input) {
159589
+ const provider2 = input.providerQuality ?? input.workset.provenance.codeProvider;
159590
+ return {
159591
+ schemaVersion: "1",
159592
+ task: input.workset.task,
159593
+ brief: input.workset.prompt,
159594
+ receipt: input.workset.receipt,
159595
+ code: {
159596
+ selected: provider2?.selected ?? "lite",
159597
+ quality: provider2?.selectedQuality ?? "heuristic",
159598
+ externalState: provider2?.external.state ?? "not-detected",
159599
+ ...input.workset.provenance.snapshotId ? { snapshotId: input.workset.provenance.snapshotId } : {}
159600
+ },
159601
+ ...input.workset.agentLoadout ? { loadout: input.workset.agentLoadout } : {}
159602
+ };
159603
+ }
159604
+ var init_context_receipt = __esm({
159605
+ "src/knowledge/context-receipt.ts"() {
159606
+ "use strict";
159607
+ init_esm_shims();
159608
+ }
159609
+ });
159610
+
159486
159611
  // src/codegraph/context-pack.ts
159487
159612
  var context_pack_exports = {};
159488
159613
  __export(context_pack_exports, {
@@ -159641,6 +159766,7 @@ async function attachTaskWorkset(input) {
159641
159766
  projectId: input.projectId,
159642
159767
  dataDir: input.dataDir,
159643
159768
  task: input.pack.task,
159769
+ ...input.agent ? { agent: input.agent } : {},
159644
159770
  lens: input.lens,
159645
159771
  currentFacts: input.currentFacts ?? [],
159646
159772
  ...input.codeState ? { codeState: input.codeState } : {},
@@ -164033,8 +164159,8 @@ var init_official_skills = __esm({
164033
164159
  "",
164034
164160
  "| Situation | Prefer | CLI fallback |",
164035
164161
  "|---|---|---|",
164036
- '| Starting a coding task and needing the best task-lensed project map | `memorix_project_context` with the user\'s task | `memorix context "<task>" --json` |',
164037
- '| Continuing prior project work | `memorix_project_context` with the user\'s task | `memorix resume "<task>" --json` |',
164162
+ '| 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` |',
164163
+ '| Continuing prior project work | `memorix_project_context` with the user\'s task | `memorix resume "<task>" --brief-json` |',
164038
164164
  '| Need structured refs/freshness for code-bound memories | `memorix_context_pack` | `memorix codegraph context-pack --task "<topic>"` |',
164039
164165
  '| Explicit memory graph question | `memorix_graph_context` | `memorix memory graph-context --query "<topic>"` |',
164040
164166
  '| Specific past decision, bug, file, or change | `memorix_search` | `memorix memory search --query "<topic>"` |',
@@ -164047,7 +164173,7 @@ var init_official_skills = __esm({
164047
164173
  "",
164048
164174
  "- 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.",
164049
164175
  "- 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.",
164050
- '- 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.',
164176
+ '- 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.',
164051
164177
  "- 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.",
164052
164178
  "- 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.",
164053
164179
  "- 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.",
@@ -165306,7 +165432,7 @@ alwaysApply: true
165306
165432
  "",
165307
165433
  `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.`,
165308
165434
  "",
165309
- '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.',
165435
+ '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.',
165310
165436
  "",
165311
165437
  "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.",
165312
165438
  "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.",
@@ -165970,7 +166096,7 @@ The path should point to a directory containing a .git folder.`
165970
166096
  };
165971
166097
  const server = existingServer ?? new McpServer({
165972
166098
  name: "memorix",
165973
- version: true ? "1.5.1" : "1.0.1"
166099
+ version: true ? "1.6.0" : "1.0.1"
165974
166100
  });
165975
166101
  const originalRegisterTool = server.registerTool.bind(server);
165976
166102
  server.registerTool = ((name, ...args) => {
@@ -166804,13 +166930,28 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
166804
166930
  refresh: z626.enum(["auto", "always", "never"]).optional().default("auto").describe(
166805
166931
  "Code Memory refresh policy. auto refreshes only when missing or stale."
166806
166932
  ),
166807
- format: z626.enum(["prompt", "summary", "json"]).optional().default("prompt").describe(
166808
- 'Output format. "prompt" is agent-ready; "summary" is human-readable; "json" is structured.'
166933
+ format: z626.enum(["prompt", "summary", "json", "receipt"]).optional().default("prompt").describe(
166934
+ 'Output format. "prompt" is agent-ready; "summary" is human-readable; "receipt" is bounded JSON; "json" is detailed diagnostics.'
166809
166935
  ),
166936
+ agent: z626.enum([
166937
+ "windsurf",
166938
+ "cursor",
166939
+ "claude-code",
166940
+ "codex",
166941
+ "copilot",
166942
+ "antigravity",
166943
+ "gemini-cli",
166944
+ "openclaw",
166945
+ "hermes",
166946
+ "omp",
166947
+ "kiro",
166948
+ "opencode",
166949
+ "trae"
166950
+ ]).optional().describe("Optional target agent for compatible workflow selection."),
166810
166951
  limit: z626.number().optional().describe("Reserved for future source limits; current prompt stays compact by default.")
166811
166952
  }
166812
166953
  },
166813
- async ({ task, refresh, format }) => {
166954
+ async ({ task, refresh, format, agent }) => {
166814
166955
  const unresolved = requireResolvedProject("build project context for the current project");
166815
166956
  if (unresolved) return unresolved;
166816
166957
  const [
@@ -166822,12 +166963,14 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
166822
166963
  },
166823
166964
  { getObservationStore: getObservationStore2 },
166824
166965
  { MaintenanceJobStore: MaintenanceJobStore2 },
166825
- { enqueueCodegraphRefresh: enqueueCodegraphRefresh2 }
166966
+ { enqueueCodegraphRefresh: enqueueCodegraphRefresh2 },
166967
+ { buildBoundedContextReceipt: buildBoundedContextReceipt2 }
166826
166968
  ] = await Promise.all([
166827
166969
  Promise.resolve().then(() => (init_auto_context(), auto_context_exports)),
166828
166970
  Promise.resolve().then(() => (init_obs_store(), obs_store_exports)),
166829
166971
  Promise.resolve().then(() => (init_maintenance_jobs(), maintenance_jobs_exports)),
166830
- Promise.resolve().then(() => (init_lifecycle(), lifecycle_exports))
166972
+ Promise.resolve().then(() => (init_lifecycle(), lifecycle_exports)),
166973
+ Promise.resolve().then(() => (init_context_receipt(), context_receipt_exports))
166831
166974
  ]);
166832
166975
  const observations2 = filterReadableObservations(
166833
166976
  await getObservationStore2().loadByProject(project.id, { status: "active" }),
@@ -166838,6 +166981,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
166838
166981
  dataDir: projectDir2,
166839
166982
  observations: observations2,
166840
166983
  task,
166984
+ agent,
166841
166985
  refresh: refresh ?? "auto",
166842
166986
  reader: getObservationReader(),
166843
166987
  enqueueRefresh: () => {
@@ -166850,7 +166994,10 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
166850
166994
  });
166851
166995
  }
166852
166996
  });
166853
- const text2 = format === "json" ? JSON.stringify({ ...context, brief: buildAutoProjectBrief2(context) }, null, 2) : format === "summary" ? formatAutoProjectContextSummary2(context) : formatAutoProjectContextPrompt2(context);
166997
+ const text2 = format === "json" ? JSON.stringify({ ...context, brief: buildAutoProjectBrief2(context) }, null, 2) : format === "receipt" ? JSON.stringify(buildBoundedContextReceipt2({
166998
+ workset: context.workset,
166999
+ providerQuality: context.providerQuality
167000
+ }), null, 2) : format === "summary" ? formatAutoProjectContextSummary2(context) : formatAutoProjectContextPrompt2(context);
166854
167001
  autopilotRetrievalBoundary = {
166855
167002
  projectId: project.id,
166856
167003
  issuedAt: Date.now(),
@@ -170355,7 +170502,7 @@ var init_serve_shared = __esm({
170355
170502
 
170356
170503
  // src/cli/version.ts
170357
170504
  function getCliVersion() {
170358
- return true ? "1.5.1" : pkg.version;
170505
+ return true ? "1.6.0" : pkg.version;
170359
170506
  }
170360
170507
  var init_version3 = __esm({
170361
170508
  "src/cli/version.ts"() {
@@ -146819,6 +146819,7 @@ var init_task_lens = __esm({
146819
146819
  var workflows_exports = {};
146820
146820
  __export(workflows_exports, {
146821
146821
  WORKFLOW_ADAPTER_TARGETS: () => WORKFLOW_ADAPTER_TARGETS,
146822
+ WORKFLOW_AGENT_TARGETS: () => WORKFLOW_AGENT_TARGETS,
146822
146823
  applyWorkflowAdapter: () => applyWorkflowAdapter,
146823
146824
  importWindsurfWorkflows: () => importWindsurfWorkflows,
146824
146825
  parseWorkflowMarkdown: () => parseWorkflowMarkdown,
@@ -146884,7 +146885,7 @@ function optionalStatus(data) {
146884
146885
  return value;
146885
146886
  }
146886
146887
  function normalizeAgents(values) {
146887
- const unknown3 = values.filter((value) => !KNOWN_AGENTS.includes(value));
146888
+ const unknown3 = values.filter((value) => !WORKFLOW_AGENT_TARGETS.includes(value));
146888
146889
  if (unknown3.length > 0) {
146889
146890
  throw new Error("workflow frontmatter has unsupported agent: " + unknown3[0]);
146890
146891
  }
@@ -147160,7 +147161,7 @@ function taskScore(workflow, task) {
147160
147161
  return { score, reasons: [...new Set(reasons)] };
147161
147162
  }
147162
147163
  function selectWorkflows(input) {
147163
- const selected = input.workflows.filter((workflow) => workflow.status === "active").map((workflow) => {
147164
+ const selected = input.workflows.filter((workflow) => workflow.status === "active" && (!input.agent || workflow.compatibleAgents.includes(input.agent))).map((workflow) => {
147164
147165
  const match2 = taskScore(workflow, input.task);
147165
147166
  const cautions = input.store && input.projectId ? input.store.recentFailureCautions(input.projectId, workflow.id) : [];
147166
147167
  return {
@@ -147440,7 +147441,7 @@ async function selectWorkspaceWorkflows(input) {
147440
147441
  errors: synced.errors
147441
147442
  };
147442
147443
  }
147443
- var KNOWN_AGENTS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
147444
+ var WORKFLOW_AGENT_TARGETS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
147444
147445
  var init_workflows2 = __esm({
147445
147446
  "src/knowledge/workflows.ts"() {
147446
147447
  "use strict";
@@ -147452,7 +147453,7 @@ var init_workflows2 = __esm({
147452
147453
  init_workflow_store();
147453
147454
  init_outcome_store();
147454
147455
  init_task_lens();
147455
- KNOWN_AGENTS = [
147456
+ WORKFLOW_AGENT_TARGETS = [
147456
147457
  "windsurf",
147457
147458
  "cursor",
147458
147459
  "claude-code",
@@ -146451,6 +146451,7 @@ var init_task_lens = __esm({
146451
146451
  var workflows_exports = {};
146452
146452
  __export(workflows_exports, {
146453
146453
  WORKFLOW_ADAPTER_TARGETS: () => WORKFLOW_ADAPTER_TARGETS,
146454
+ WORKFLOW_AGENT_TARGETS: () => WORKFLOW_AGENT_TARGETS,
146454
146455
  applyWorkflowAdapter: () => applyWorkflowAdapter,
146455
146456
  importWindsurfWorkflows: () => importWindsurfWorkflows,
146456
146457
  parseWorkflowMarkdown: () => parseWorkflowMarkdown,
@@ -146516,7 +146517,7 @@ function optionalStatus(data) {
146516
146517
  return value;
146517
146518
  }
146518
146519
  function normalizeAgents(values) {
146519
- const unknown3 = values.filter((value) => !KNOWN_AGENTS.includes(value));
146520
+ const unknown3 = values.filter((value) => !WORKFLOW_AGENT_TARGETS.includes(value));
146520
146521
  if (unknown3.length > 0) {
146521
146522
  throw new Error("workflow frontmatter has unsupported agent: " + unknown3[0]);
146522
146523
  }
@@ -146792,7 +146793,7 @@ function taskScore(workflow, task) {
146792
146793
  return { score, reasons: [...new Set(reasons)] };
146793
146794
  }
146794
146795
  function selectWorkflows(input) {
146795
- const selected = input.workflows.filter((workflow) => workflow.status === "active").map((workflow) => {
146796
+ const selected = input.workflows.filter((workflow) => workflow.status === "active" && (!input.agent || workflow.compatibleAgents.includes(input.agent))).map((workflow) => {
146796
146797
  const match2 = taskScore(workflow, input.task);
146797
146798
  const cautions = input.store && input.projectId ? input.store.recentFailureCautions(input.projectId, workflow.id) : [];
146798
146799
  return {
@@ -147072,7 +147073,7 @@ async function selectWorkspaceWorkflows(input) {
147072
147073
  errors: synced.errors
147073
147074
  };
147074
147075
  }
147075
- var KNOWN_AGENTS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
147076
+ var WORKFLOW_AGENT_TARGETS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
147076
147077
  var init_workflows2 = __esm({
147077
147078
  "src/knowledge/workflows.ts"() {
147078
147079
  "use strict";
@@ -147084,7 +147085,7 @@ var init_workflows2 = __esm({
147084
147085
  init_workflow_store();
147085
147086
  init_outcome_store();
147086
147087
  init_task_lens();
147087
- KNOWN_AGENTS = [
147088
+ WORKFLOW_AGENT_TARGETS = [
147088
147089
  "windsurf",
147089
147090
  "cursor",
147090
147091
  "claude-code",
@@ -146790,6 +146790,7 @@ var init_task_lens = __esm({
146790
146790
  var workflows_exports = {};
146791
146791
  __export(workflows_exports, {
146792
146792
  WORKFLOW_ADAPTER_TARGETS: () => WORKFLOW_ADAPTER_TARGETS,
146793
+ WORKFLOW_AGENT_TARGETS: () => WORKFLOW_AGENT_TARGETS,
146793
146794
  applyWorkflowAdapter: () => applyWorkflowAdapter,
146794
146795
  importWindsurfWorkflows: () => importWindsurfWorkflows,
146795
146796
  parseWorkflowMarkdown: () => parseWorkflowMarkdown,
@@ -146855,7 +146856,7 @@ function optionalStatus(data) {
146855
146856
  return value;
146856
146857
  }
146857
146858
  function normalizeAgents(values) {
146858
- const unknown3 = values.filter((value) => !KNOWN_AGENTS.includes(value));
146859
+ const unknown3 = values.filter((value) => !WORKFLOW_AGENT_TARGETS.includes(value));
146859
146860
  if (unknown3.length > 0) {
146860
146861
  throw new Error("workflow frontmatter has unsupported agent: " + unknown3[0]);
146861
146862
  }
@@ -147131,7 +147132,7 @@ function taskScore(workflow, task) {
147131
147132
  return { score, reasons: [...new Set(reasons)] };
147132
147133
  }
147133
147134
  function selectWorkflows(input) {
147134
- const selected = input.workflows.filter((workflow) => workflow.status === "active").map((workflow) => {
147135
+ const selected = input.workflows.filter((workflow) => workflow.status === "active" && (!input.agent || workflow.compatibleAgents.includes(input.agent))).map((workflow) => {
147135
147136
  const match2 = taskScore(workflow, input.task);
147136
147137
  const cautions = input.store && input.projectId ? input.store.recentFailureCautions(input.projectId, workflow.id) : [];
147137
147138
  return {
@@ -147411,7 +147412,7 @@ async function selectWorkspaceWorkflows(input) {
147411
147412
  errors: synced.errors
147412
147413
  };
147413
147414
  }
147414
- var KNOWN_AGENTS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
147415
+ var WORKFLOW_AGENT_TARGETS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
147415
147416
  var init_workflows2 = __esm({
147416
147417
  "src/knowledge/workflows.ts"() {
147417
147418
  "use strict";
@@ -147423,7 +147424,7 @@ var init_workflows2 = __esm({
147423
147424
  init_workflow_store();
147424
147425
  init_outcome_store();
147425
147426
  init_task_lens();
147426
- KNOWN_AGENTS = [
147427
+ WORKFLOW_AGENT_TARGETS = [
147427
147428
  "windsurf",
147428
147429
  "cursor",
147429
147430
  "claude-code",
@@ -4,6 +4,29 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.6.0] - 2026-08-17
8
+
9
+ ### Added
10
+ - **Bounded context receipts** -- `memorix context|resume --brief-json`,
11
+ `memorix codegraph context-pack --brief-json`, and MCP project-context
12
+ `format: "receipt"` return only the agent-ready brief, selection receipt,
13
+ CodeGraph quality, and optional Agent loadout. The detailed `--json` and
14
+ MCP `format: "json"` forms remain available for diagnostics.
15
+ - **Task-scoped Agent loadouts** -- `--agent <target>` selects only compatible
16
+ project workflows and reports their required context and workflow tools.
17
+ This is guidance, not a replacement for the host agent's authorization.
18
+ - **Explicit external CodeGraph lifecycle** -- `memorix codegraph init|sync`
19
+ manages an already installed local CodeGraph index. It never invokes
20
+ CodeGraph's agent installer or writes Agent configuration.
21
+
22
+ ### Changed
23
+ - **Honest CodeGraph status** -- Status now distinguishes the persistent Lite
24
+ Code State index from the provider actually usable for the current task.
25
+ A stale external graph falls back to Lite instead of being presented as fresh.
26
+ - **Bounded fallback guidance** -- Newly generated Agent rules teach
27
+ `--brief-json` for the one CLI fallback; `--json` is reserved for deliberate
28
+ detailed diagnostics.
29
+
7
30
  ## [1.5.1] - 2026-08-16
8
31
 
9
32
  ### Fixed