memorix 1.4.3 → 1.4.4

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 (144) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +11 -4
  3. package/README.zh-CN.md +7 -1
  4. package/TEAM.md +86 -86
  5. package/assets/star-history-dark.svg +8 -8
  6. package/assets/star-history-light.svg +8 -8
  7. package/assets/star-history.json +16 -2
  8. package/dist/cli/index.js +194 -109
  9. package/dist/cli/memcode.js +0 -0
  10. package/dist/index.js +39 -12
  11. package/dist/maintenance-runner.js +9 -7
  12. package/dist/media-audio-runner.js +9 -7
  13. package/dist/media-video-runner.js +9 -7
  14. package/dist/memcode/index.js +9 -7
  15. package/dist/memcode-runtime/CHANGELOG.md +19 -0
  16. package/dist/sdk.js +38 -11
  17. package/dist/vector-backfill-runner.js +9 -7
  18. package/docs/AGENT_OPERATOR_PLAYBOOK.md +3 -3
  19. package/docs/API_REFERENCE.md +9 -5
  20. package/docs/CONFIGURATION.md +15 -5
  21. package/docs/DESIGN_DECISIONS.md +357 -357
  22. package/docs/DEVELOPMENT.md +2 -2
  23. package/docs/KNOWN_ISSUES_AND_ROADMAP.md +3 -3
  24. package/docs/MODULES.md +1 -1
  25. package/docs/README.md +1 -1
  26. package/docs/SETUP.md +3 -3
  27. package/docs/hooks-architecture.md +2 -1
  28. package/llms-full.txt +4 -4
  29. package/llms.txt +2 -2
  30. package/package.json +1 -1
  31. package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
  32. package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
  33. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  34. package/plugins/copilot/memorix/plugin.json +1 -1
  35. package/plugins/gemini/memorix/gemini-extension.json +1 -1
  36. package/plugins/omp/memorix/package.json +1 -1
  37. package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
  38. package/plugins/pi/memorix/package.json +1 -1
  39. package/server.json +2 -2
  40. package/src/audit/index.ts +156 -156
  41. package/src/cli/commands/audit-list.ts +89 -89
  42. package/src/cli/commands/formation.ts +48 -48
  43. package/src/cli/commands/git-hook-install.ts +111 -111
  44. package/src/cli/commands/handoff.ts +54 -54
  45. package/src/cli/commands/hooks-status.ts +63 -63
  46. package/src/cli/commands/ingest.ts +44 -44
  47. package/src/cli/commands/integrate-shared.ts +15 -15
  48. package/src/cli/commands/lock.ts +82 -82
  49. package/src/cli/commands/media-image.ts +27 -0
  50. package/src/cli/commands/media.ts +8 -1
  51. package/src/cli/commands/memory.ts +44 -34
  52. package/src/cli/commands/message.ts +104 -104
  53. package/src/cli/commands/operator-shared.ts +62 -18
  54. package/src/cli/commands/poll.ts +58 -58
  55. package/src/cli/commands/purge-all-memory.ts +85 -85
  56. package/src/cli/commands/purge-project-memory.ts +83 -83
  57. package/src/cli/commands/reasoning.ts +118 -118
  58. package/src/cli/commands/skills.ts +114 -114
  59. package/src/cli/commands/task.ts +167 -167
  60. package/src/cli/commands/transfer.ts +47 -47
  61. package/src/cli/commands/uninstall-project-artifacts.ts +85 -85
  62. package/src/cli/tui/ChatView.tsx +234 -234
  63. package/src/cli/tui/CommandBar.tsx +312 -312
  64. package/src/cli/tui/ContextRail.tsx +118 -118
  65. package/src/cli/tui/HeaderBar.tsx +72 -72
  66. package/src/cli/tui/LogoBanner.tsx +51 -51
  67. package/src/cli/tui/Sidebar.tsx +179 -179
  68. package/src/cli/tui/index.ts +41 -41
  69. package/src/cli/tui/markdown-render.tsx +371 -371
  70. package/src/cli/tui/use-mouse.ts +157 -157
  71. package/src/cli/tui/useNavigation.ts +56 -56
  72. package/src/cli/version.ts +7 -7
  73. package/src/cli/workbench.ts +1 -1
  74. package/src/dashboard/project-classification.ts +64 -64
  75. package/src/git/hooks-path.ts +85 -85
  76. package/src/hooks/pattern-detector.ts +173 -173
  77. package/src/hooks/significance-filter.ts +250 -250
  78. package/src/llm/memory-manager.ts +328 -328
  79. package/src/llm/provider.ts +885 -885
  80. package/src/llm/quality.ts +248 -248
  81. package/src/media/minimax.ts +9 -1
  82. package/src/memory/attribution-guard.ts +249 -249
  83. package/src/memory/disclosure-policy.ts +135 -135
  84. package/src/memory/entity-extractor.ts +197 -197
  85. package/src/memory/formation/evaluate.ts +217 -217
  86. package/src/memory/formation/extract.ts +361 -361
  87. package/src/memory/formation/index.ts +417 -417
  88. package/src/memory/formation/resolve.ts +344 -344
  89. package/src/memory/formation/types.ts +315 -315
  90. package/src/memory/freshness.ts +122 -122
  91. package/src/memory/graph.ts +197 -197
  92. package/src/memory/refs.ts +94 -94
  93. package/src/memory/secret-filter.ts +79 -79
  94. package/src/orchestrate/adapters/claude-stream.ts +192 -192
  95. package/src/orchestrate/adapters/claude.ts +111 -111
  96. package/src/orchestrate/adapters/codex-stream.ts +134 -134
  97. package/src/orchestrate/adapters/codex.ts +41 -41
  98. package/src/orchestrate/adapters/gemini-stream.ts +166 -166
  99. package/src/orchestrate/adapters/gemini.ts +42 -42
  100. package/src/orchestrate/adapters/index.ts +73 -73
  101. package/src/orchestrate/adapters/opencode-stream.ts +143 -143
  102. package/src/orchestrate/adapters/opencode.ts +47 -47
  103. package/src/orchestrate/adapters/types.ts +77 -77
  104. package/src/orchestrate/capability-router.ts +284 -284
  105. package/src/orchestrate/context-compact.ts +188 -188
  106. package/src/orchestrate/cost-tracker.ts +219 -219
  107. package/src/orchestrate/error-recovery.ts +191 -191
  108. package/src/orchestrate/evidence.ts +140 -140
  109. package/src/orchestrate/ledger.ts +110 -110
  110. package/src/orchestrate/memorix-bridge.ts +343 -343
  111. package/src/orchestrate/output-budget.ts +80 -80
  112. package/src/orchestrate/permission.ts +152 -152
  113. package/src/orchestrate/pipeline-trace.ts +131 -131
  114. package/src/orchestrate/prompt-builder.ts +155 -155
  115. package/src/orchestrate/ring-buffer.ts +37 -37
  116. package/src/orchestrate/task-graph.ts +389 -389
  117. package/src/project/aliases.ts +374 -374
  118. package/src/rules/adapters/trae.ts +56 -56
  119. package/src/rules/syncer.ts +235 -235
  120. package/src/search/query-expansion.ts +52 -52
  121. package/src/server/formation-timeout.ts +27 -27
  122. package/src/server.ts +23 -1
  123. package/src/skills/mini-skills.ts +386 -386
  124. package/src/store/chat-store.ts +119 -119
  125. package/src/store/graph-store.ts +249 -249
  126. package/src/store/mini-skill-store.ts +349 -349
  127. package/src/store/persistence-json.ts +212 -212
  128. package/src/store/persistence.ts +291 -291
  129. package/src/store/project-affinity.ts +195 -195
  130. package/src/team/event-bus.ts +76 -76
  131. package/src/team/file-locks.ts +173 -173
  132. package/src/team/handoff.ts +161 -161
  133. package/src/team/messages.ts +203 -203
  134. package/src/team/poll.ts +132 -132
  135. package/src/team/tasks.ts +211 -211
  136. package/src/workspace/mcp-adapters/codex.ts +191 -191
  137. package/src/workspace/mcp-adapters/copilot.ts +105 -105
  138. package/src/workspace/mcp-adapters/cursor.ts +53 -53
  139. package/src/workspace/mcp-adapters/kiro.ts +64 -64
  140. package/src/workspace/mcp-adapters/opencode.ts +123 -123
  141. package/src/workspace/mcp-adapters/trae.ts +134 -134
  142. package/src/workspace/mcp-adapters/windsurf.ts +91 -91
  143. package/src/workspace/sanitizer.ts +60 -60
  144. package/dist/memcode-runtime/docs/images/exy.png +0 -0
@@ -1,87 +1,87 @@
1
- /**
2
- * Team Handoff — Structured context transfer between agents.
3
- *
4
- * Phase 4b: Creates a handoff artifact as a standard observation
5
- * (canonical path — no new JSON/file persistence).
6
- *
7
- * Architectural boundary (B4): The canonical record is an Observation
8
- * stored via storeObservation(). TeamStore only holds a reference pointer.
9
- * Handoff artifacts use valueCategory: 'core' so they are immune to
10
- * retention archival (Phase 1 provenance: core = immune).
11
- */
12
-
13
- import type { TeamStore } from './team-store.js';
14
- import type { ObservationType } from '../types.js';
15
-
16
- // ── Types ──────────────────────────────────────────────────────────
17
-
18
- export interface HandoffInput {
19
- projectId: string;
20
- fromAgentId: string;
21
- toAgentId?: string; // null = anyone can pick up
22
- taskId?: string; // link to specific task
23
- summary: string; // human-readable summary of what was done
24
- context: string; // machine-readable context for the next agent
25
- filesModified?: string[]; // files touched during the work
26
- concepts?: string[]; // key concepts for search discoverability
27
- }
28
-
29
- export interface HandoffResult {
30
- observationId: number;
31
- taskId?: string;
32
- fromAgentId: string;
33
- toAgentId?: string;
34
- summary: string;
35
- }
36
-
37
- // ── createHandoffArtifact ──────────────────────────────────────────
38
-
39
- /**
40
- * Create a structured handoff artifact stored as an observation.
41
- *
42
- * @param input - Handoff details
43
- * @param storeObservation - The canonical storeObservation function (injected to avoid circular deps)
44
- * @param teamStore - For sending notification message to recipient
45
- */
46
- export async function createHandoffArtifact(
47
- input: HandoffInput,
48
- storeObservation: (params: {
49
- entityName: string;
50
- type: ObservationType;
51
- title: string;
52
- narrative: string;
53
- facts?: string[];
54
- filesModified?: string[];
55
- concepts?: string[];
56
- projectId: string;
57
- topicKey?: string;
1
+ /**
2
+ * Team Handoff — Structured context transfer between agents.
3
+ *
4
+ * Phase 4b: Creates a handoff artifact as a standard observation
5
+ * (canonical path — no new JSON/file persistence).
6
+ *
7
+ * Architectural boundary (B4): The canonical record is an Observation
8
+ * stored via storeObservation(). TeamStore only holds a reference pointer.
9
+ * Handoff artifacts use valueCategory: 'core' so they are immune to
10
+ * retention archival (Phase 1 provenance: core = immune).
11
+ */
12
+
13
+ import type { TeamStore } from './team-store.js';
14
+ import type { ObservationType } from '../types.js';
15
+
16
+ // ── Types ──────────────────────────────────────────────────────────
17
+
18
+ export interface HandoffInput {
19
+ projectId: string;
20
+ fromAgentId: string;
21
+ toAgentId?: string; // null = anyone can pick up
22
+ taskId?: string; // link to specific task
23
+ summary: string; // human-readable summary of what was done
24
+ context: string; // machine-readable context for the next agent
25
+ filesModified?: string[]; // files touched during the work
26
+ concepts?: string[]; // key concepts for search discoverability
27
+ }
28
+
29
+ export interface HandoffResult {
30
+ observationId: number;
31
+ taskId?: string;
32
+ fromAgentId: string;
33
+ toAgentId?: string;
34
+ summary: string;
35
+ }
36
+
37
+ // ── createHandoffArtifact ──────────────────────────────────────────
38
+
39
+ /**
40
+ * Create a structured handoff artifact stored as an observation.
41
+ *
42
+ * @param input - Handoff details
43
+ * @param storeObservation - The canonical storeObservation function (injected to avoid circular deps)
44
+ * @param teamStore - For sending notification message to recipient
45
+ */
46
+ export async function createHandoffArtifact(
47
+ input: HandoffInput,
48
+ storeObservation: (params: {
49
+ entityName: string;
50
+ type: ObservationType;
51
+ title: string;
52
+ narrative: string;
53
+ facts?: string[];
54
+ filesModified?: string[];
55
+ concepts?: string[];
56
+ projectId: string;
57
+ topicKey?: string;
58
58
  sourceDetail?: 'explicit' | 'hook' | 'git-ingest';
59
59
  valueCategory?: 'core' | 'contextual' | 'ephemeral';
60
60
  visibility?: 'personal' | 'project' | 'team';
61
61
  sharedWithAgentIds?: string[];
62
62
  createdByAgentId?: string;
63
- }) => Promise<{ observation: { id: number }; upserted: boolean }>,
64
- teamStore: TeamStore,
65
- ): Promise<HandoffResult> {
66
- // Build facts from handoff context
67
- const facts: string[] = [
68
- `Handoff from agent ${input.fromAgentId}`,
69
- ];
70
- if (input.toAgentId) facts.push(`Intended recipient: ${input.toAgentId}`);
71
- if (input.taskId) facts.push(`Related task: ${input.taskId}`);
72
- facts.push(`Context: ${input.context}`);
73
-
74
- // Store as observation — this IS the canonical record
75
- const { observation } = await storeObservation({
76
- entityName: 'team-handoff',
77
- type: 'what-changed',
78
- title: `[Handoff] ${input.summary}`,
79
- narrative: input.context,
80
- facts,
81
- filesModified: input.filesModified,
82
- concepts: ['handoff', ...(input.concepts ?? [])],
83
- projectId: input.projectId,
84
- topicKey: input.taskId ? `handoff:${input.taskId}:${input.fromAgentId}` : undefined,
63
+ }) => Promise<{ observation: { id: number }; upserted: boolean }>,
64
+ teamStore: TeamStore,
65
+ ): Promise<HandoffResult> {
66
+ // Build facts from handoff context
67
+ const facts: string[] = [
68
+ `Handoff from agent ${input.fromAgentId}`,
69
+ ];
70
+ if (input.toAgentId) facts.push(`Intended recipient: ${input.toAgentId}`);
71
+ if (input.taskId) facts.push(`Related task: ${input.taskId}`);
72
+ facts.push(`Context: ${input.context}`);
73
+
74
+ // Store as observation — this IS the canonical record
75
+ const { observation } = await storeObservation({
76
+ entityName: 'team-handoff',
77
+ type: 'what-changed',
78
+ title: `[Handoff] ${input.summary}`,
79
+ narrative: input.context,
80
+ facts,
81
+ filesModified: input.filesModified,
82
+ concepts: ['handoff', ...(input.concepts ?? [])],
83
+ projectId: input.projectId,
84
+ topicKey: input.taskId ? `handoff:${input.taskId}:${input.fromAgentId}` : undefined,
85
85
  sourceDetail: 'explicit',
86
86
  valueCategory: 'core', // immune to retention archival
87
87
  // A direct handoff is not a project-wide memo. The sender retains access
@@ -90,85 +90,85 @@ export async function createHandoffArtifact(
90
90
  visibility: input.toAgentId ? 'personal' : 'team',
91
91
  ...(input.toAgentId ? { sharedWithAgentIds: [input.toAgentId] } : {}),
92
92
  createdByAgentId: input.fromAgentId,
93
- });
94
-
95
- // Emit handoff:created event (best-effort, process-local only).
96
- // Happens AFTER canonical write succeeds — listener errors never affect the handoff.
97
- try {
98
- teamStore.getEventBus()?.emit('handoff:created', {
99
- observationId: observation.id,
100
- projectId: input.projectId,
101
- fromAgent: input.fromAgentId,
102
- toAgent: input.toAgentId,
103
- taskId: input.taskId,
104
- });
105
- } catch {
106
- // Best-effort: event emission failure never affects canonical handoff
107
- }
108
-
109
- // Send notification message to recipient.
110
- // Broadcast handoff uses fanout-on-write (方案 A): instead of one NULL-recipient
111
- // shared message, each active agent (excluding sender) gets their own copy.
112
- // This prevents Agent A's markRead from consuming Agent B's unread state.
113
- try {
114
- if (input.toAgentId) {
115
- // Role validation: if the handoff is linked to a task with required_role,
116
- // verify the recipient's role matches before sending.
117
- if (input.taskId) {
118
- const task = teamStore.getTask(input.taskId);
119
- if (task?.required_role) {
120
- const recipient = teamStore.getAgent(input.toAgentId);
121
- if (recipient && recipient.role !== task.required_role) {
122
- // Log warning but don't block — handoff observation is still created
123
- console.error(
124
- `[memorix] Handoff role mismatch: task "${input.taskId}" requires role "${task.required_role}" but recipient "${input.toAgentId}" has role "${recipient.role}". Handoff proceeds but claim will be rejected.`
125
- );
126
- }
127
- }
128
- }
129
- // Targeted handoff — single recipient-specific message
130
- teamStore.sendMessage({
131
- projectId: input.projectId,
132
- senderAgentId: input.fromAgentId,
133
- recipientAgentId: input.toAgentId,
134
- type: 'handoff',
135
- content: `Handoff: ${input.summary}`,
136
- payload: {
137
- observationId: observation.id,
138
- taskId: input.taskId,
139
- filesModified: input.filesModified,
140
- },
141
- taskId: input.taskId,
142
- });
143
- } else {
144
- // Broadcast handoff — fanout to each active agent (excluding sender)
145
- const agents = teamStore.listAgents(input.projectId, { status: 'active' });
146
- for (const agent of agents) {
147
- if (agent.agent_id === input.fromAgentId) continue;
148
- teamStore.sendMessage({
149
- projectId: input.projectId,
150
- senderAgentId: input.fromAgentId,
151
- recipientAgentId: agent.agent_id,
152
- type: 'handoff',
153
- content: `Handoff: ${input.summary}`,
154
- payload: {
155
- observationId: observation.id,
156
- taskId: input.taskId,
157
- filesModified: input.filesModified,
158
- },
159
- taskId: input.taskId,
160
- });
161
- }
162
- }
163
- } catch {
164
- // Message sending is best-effort — handoff observation is the canonical record
165
- }
166
-
167
- return {
168
- observationId: observation.id,
169
- taskId: input.taskId,
170
- fromAgentId: input.fromAgentId,
171
- toAgentId: input.toAgentId,
172
- summary: input.summary,
173
- };
174
- }
93
+ });
94
+
95
+ // Emit handoff:created event (best-effort, process-local only).
96
+ // Happens AFTER canonical write succeeds — listener errors never affect the handoff.
97
+ try {
98
+ teamStore.getEventBus()?.emit('handoff:created', {
99
+ observationId: observation.id,
100
+ projectId: input.projectId,
101
+ fromAgent: input.fromAgentId,
102
+ toAgent: input.toAgentId,
103
+ taskId: input.taskId,
104
+ });
105
+ } catch {
106
+ // Best-effort: event emission failure never affects canonical handoff
107
+ }
108
+
109
+ // Send notification message to recipient.
110
+ // Broadcast handoff uses fanout-on-write (方案 A): instead of one NULL-recipient
111
+ // shared message, each active agent (excluding sender) gets their own copy.
112
+ // This prevents Agent A's markRead from consuming Agent B's unread state.
113
+ try {
114
+ if (input.toAgentId) {
115
+ // Role validation: if the handoff is linked to a task with required_role,
116
+ // verify the recipient's role matches before sending.
117
+ if (input.taskId) {
118
+ const task = teamStore.getTask(input.taskId);
119
+ if (task?.required_role) {
120
+ const recipient = teamStore.getAgent(input.toAgentId);
121
+ if (recipient && recipient.role !== task.required_role) {
122
+ // Log warning but don't block — handoff observation is still created
123
+ console.error(
124
+ `[memorix] Handoff role mismatch: task "${input.taskId}" requires role "${task.required_role}" but recipient "${input.toAgentId}" has role "${recipient.role}". Handoff proceeds but claim will be rejected.`
125
+ );
126
+ }
127
+ }
128
+ }
129
+ // Targeted handoff — single recipient-specific message
130
+ teamStore.sendMessage({
131
+ projectId: input.projectId,
132
+ senderAgentId: input.fromAgentId,
133
+ recipientAgentId: input.toAgentId,
134
+ type: 'handoff',
135
+ content: `Handoff: ${input.summary}`,
136
+ payload: {
137
+ observationId: observation.id,
138
+ taskId: input.taskId,
139
+ filesModified: input.filesModified,
140
+ },
141
+ taskId: input.taskId,
142
+ });
143
+ } else {
144
+ // Broadcast handoff — fanout to each active agent (excluding sender)
145
+ const agents = teamStore.listAgents(input.projectId, { status: 'active' });
146
+ for (const agent of agents) {
147
+ if (agent.agent_id === input.fromAgentId) continue;
148
+ teamStore.sendMessage({
149
+ projectId: input.projectId,
150
+ senderAgentId: input.fromAgentId,
151
+ recipientAgentId: agent.agent_id,
152
+ type: 'handoff',
153
+ content: `Handoff: ${input.summary}`,
154
+ payload: {
155
+ observationId: observation.id,
156
+ taskId: input.taskId,
157
+ filesModified: input.filesModified,
158
+ },
159
+ taskId: input.taskId,
160
+ });
161
+ }
162
+ }
163
+ } catch {
164
+ // Message sending is best-effort — handoff observation is the canonical record
165
+ }
166
+
167
+ return {
168
+ observationId: observation.id,
169
+ taskId: input.taskId,
170
+ fromAgentId: input.fromAgentId,
171
+ toAgentId: input.toAgentId,
172
+ summary: input.summary,
173
+ };
174
+ }