memorix 1.2.9 → 1.3.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 (68) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +30 -4
  3. package/README.zh-CN.md +28 -2
  4. package/assets/star-history-dark.svg +30 -0
  5. package/assets/star-history-light.svg +30 -0
  6. package/assets/star-history.json +599 -0
  7. package/dist/cli/index.js +1945 -579
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/index.js +1292 -267
  10. package/dist/index.js.map +1 -1
  11. package/dist/maintenance-runner.js +97 -21
  12. package/dist/maintenance-runner.js.map +1 -1
  13. package/dist/memcode-runtime/CHANGELOG.md +24 -0
  14. package/dist/sdk.d.ts +1 -1
  15. package/dist/sdk.js +1294 -269
  16. package/dist/sdk.js.map +1 -1
  17. package/dist/types.d.ts +99 -1
  18. package/dist/types.js.map +1 -1
  19. package/dist/vector-backfill-runner.js +97 -21
  20. package/dist/vector-backfill-runner.js.map +1 -1
  21. package/docs/1.3-MEMORY-ARCHITECTURE.md +236 -0
  22. package/docs/AGENT_OPERATOR_PLAYBOOK.md +5 -3
  23. package/docs/API_REFERENCE.md +20 -1
  24. package/docs/ARCHITECTURE.md +34 -1
  25. package/docs/DEVELOPMENT.md +10 -3
  26. package/docs/INTEGRATIONS.md +1 -1
  27. package/docs/MODULES.md +27 -1
  28. package/docs/README.md +3 -3
  29. package/docs/SETUP.md +6 -4
  30. package/docs/dev-log/progress.txt +22 -0
  31. package/docs/hooks-architecture.md +1 -1
  32. package/llms-full.txt +5 -1
  33. package/llms.txt +2 -0
  34. package/package.json +7 -2
  35. package/plugins/antigravity/memorix/rules/memorix.md +2 -0
  36. package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
  37. package/plugins/claude/memorix/skills/memorix-memory/SKILL.md +3 -0
  38. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  39. package/plugins/codex/memorix/skills/memorix-memory/SKILL.md +3 -0
  40. package/plugins/copilot/memorix/plugin.json +1 -1
  41. package/plugins/copilot/memorix/skills/memorix-memory/SKILL.md +3 -0
  42. package/plugins/cursor/memorix/skills/memorix-memory/SKILL.md +3 -0
  43. package/plugins/gemini/memorix/GEMINI.md +2 -0
  44. package/plugins/gemini/memorix/gemini-extension.json +1 -1
  45. package/plugins/omp/memorix/package.json +1 -1
  46. package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
  47. package/plugins/pi/memorix/package.json +1 -1
  48. package/plugins/pi/memorix/skills/memorix-memory/SKILL.md +3 -0
  49. package/server.json +38 -0
  50. package/src/cli/command-guide.ts +9 -1
  51. package/src/cli/commands/agent-integrations.ts +12 -6
  52. package/src/cli/commands/codegraph.ts +1 -0
  53. package/src/cli/commands/memory.ts +217 -1
  54. package/src/cli/commands/setup.ts +200 -23
  55. package/src/codegraph/auto-context.ts +11 -0
  56. package/src/codegraph/context-pack.ts +3 -0
  57. package/src/embedding/api-provider.ts +23 -9
  58. package/src/embedding/provider.ts +21 -10
  59. package/src/hooks/installers/index.ts +2 -0
  60. package/src/knowledge/context-assembly.ts +2 -1
  61. package/src/knowledge/workset.ts +77 -4
  62. package/src/memory/long-term-store.ts +242 -0
  63. package/src/memory/long-term-types.ts +136 -0
  64. package/src/memory/long-term.ts +626 -0
  65. package/src/memory/owner.ts +75 -0
  66. package/src/server.ts +112 -30
  67. package/src/store/sqlite-db.ts +74 -0
  68. package/src/types.ts +20 -0
@@ -6,6 +6,7 @@ import { KnowledgeWorkspaceStore } from './workspace-store.js';
6
6
  import { loadKnowledgeWorkspace } from './workspace.js';
7
7
  import { WorkflowStore } from './workflow-store.js';
8
8
  import { selectWorkflows } from './workflows.js';
9
+ import { renderLongTermMemorySummary, selectLongTermMemoriesForTask } from '../memory/long-term.js';
9
10
  import type {
10
11
  ContextCandidateFreshness,
11
12
  ContextCandidateKind,
@@ -18,6 +19,8 @@ import type { CodeGraphProviderQuality, ExternalCodeGraphOutline } from '../code
18
19
  import type { KnowledgeClaim, ClaimEvidenceRef } from './types.js';
19
20
  import type { KnowledgePageRecord, KnowledgeWorkspace } from './workspace-types.js';
20
21
  import type { WorkflowSelection } from './workflow-types.js';
22
+ import type { ObservationReader } from '../types.js';
23
+ import type { LongTermMemory, LongTermMemoryEvidence } from '../memory/long-term-types.js';
21
24
 
22
25
  export type WorksetCautionKind =
23
26
  | 'dirty-worktree'
@@ -77,6 +80,18 @@ export interface WorksetMemorySource {
77
80
  reason?: string;
78
81
  }
79
82
 
83
+ /** A task-matching curated long-term item. The full record stays behind CLI detail. */
84
+ export interface WorksetLongTermMemory {
85
+ id: string;
86
+ kind: LongTermMemory['kind'];
87
+ scope: LongTermMemory['scope'];
88
+ state: LongTermMemory['state'];
89
+ title: string;
90
+ summary: string;
91
+ evidenceRefs: string[];
92
+ reason: string;
93
+ }
94
+
80
95
  /** Prior-work evidence selected only for an explicit or inferred continuation. */
81
96
  export interface WorksetContinuation {
82
97
  previousSession?: {
@@ -103,7 +118,7 @@ export interface WorksetContinuation {
103
118
  }
104
119
 
105
120
  export interface TaskWorkset {
106
- version: '1.2';
121
+ version: '1.3';
107
122
  task: string;
108
123
  lens: string;
109
124
  currentFacts: string[];
@@ -117,6 +132,7 @@ export interface TaskWorkset {
117
132
  hiddenCautionMemoryCount: number;
118
133
  claims: WorksetClaim[];
119
134
  pages: WorksetPage[];
135
+ durableMemory: WorksetLongTermMemory[];
120
136
  workflows: WorksetWorkflow[];
121
137
  cautions: WorksetCaution[];
122
138
  verification: string[];
@@ -164,6 +180,8 @@ export interface BuildTaskWorksetInput {
164
180
  stale: number;
165
181
  };
166
182
  runtimeCautions?: WorksetCaution[];
183
+ /** Reader identity used only for team-scoped durable memory filtering. */
184
+ reader?: ObservationReader;
167
185
  maxTokens?: number;
168
186
  /** Delivery surface controls receipt semantics without changing prompt shape. */
169
187
  deliveryTarget?: ContextDeliveryTarget;
@@ -297,6 +315,7 @@ function receiptOmissionKind(raw: string): ContextCandidateKind | undefined {
297
315
  if (raw.includes('state')) return 'code-state';
298
316
  if (raw.includes('semantic')) return 'semantic-code';
299
317
  if (raw.includes('start')) return 'start-here';
318
+ if (raw.includes('durable-memory')) return 'durable-memory';
300
319
  if (raw.includes('memory')) return 'memory';
301
320
  if (raw.includes('claim')) return 'claim';
302
321
  if (raw.includes('knowledge-page')) return 'knowledge-page';
@@ -593,6 +612,27 @@ export function renderTaskWorksetPrompt(input: Omit<TaskWorkset, 'prompt' | 'bud
593
612
  }
594
613
  }
595
614
 
615
+ if (input.durableMemory.length > 0) {
616
+ appendLine(lines, '', maxTokens, omitted, 'durable-memory-heading');
617
+ appendLine(lines, 'Durable memory', maxTokens, omitted, 'durable-memory-heading');
618
+ for (const memory of input.durableMemory.slice(0, 3)) {
619
+ appendLine(
620
+ lines,
621
+ '- ' + memory.kind + ' (' + memory.scope + ', ' + memory.state + '; ref durable:' + memory.id + '): ' + memory.summary,
622
+ maxTokens,
623
+ omitted,
624
+ 'durable-memory',
625
+ selected,
626
+ {
627
+ kind: 'durable-memory',
628
+ id: 'durable:' + memory.id,
629
+ reason: memory.reason,
630
+ trust: 'source-backed',
631
+ },
632
+ );
633
+ }
634
+ }
635
+
596
636
  if (input.workflows.length > 0) {
597
637
  appendLine(lines, '', maxTokens, omitted, 'workflow-heading');
598
638
  appendLine(lines, 'Project workflow', maxTokens, omitted, 'workflow-heading');
@@ -674,6 +714,35 @@ export async function buildTaskWorkset(input: BuildTaskWorksetInput): Promise<Ta
674
714
  reason: selection.reasons[claim.id] ?? 'source-qualified task match',
675
715
  }));
676
716
 
717
+ let durableMemory: WorksetLongTermMemory[] = [];
718
+ let durableEvidence: LongTermMemoryEvidence[] = [];
719
+ if (task) {
720
+ try {
721
+ const selected = await selectLongTermMemoriesForTask({
722
+ dataDir: input.dataDir,
723
+ projectId: input.projectId,
724
+ task,
725
+ ...(input.reader?.agentId ? { agentId: input.reader.agentId } : {}),
726
+ ...(input.reader?.isTeamMember ? { isTeamMember: true } : {}),
727
+ limit: 3,
728
+ });
729
+ durableMemory = selected.map(item => ({
730
+ id: item.memory.id,
731
+ kind: item.memory.kind,
732
+ scope: item.memory.scope,
733
+ state: item.memory.state,
734
+ title: item.memory.title,
735
+ summary: renderLongTermMemorySummary(item.memory, 20),
736
+ evidenceRefs: item.evidence.map(evidence => evidence.id),
737
+ reason: item.reason,
738
+ }));
739
+ durableEvidence = selected.flatMap(item => item.evidence);
740
+ } catch {
741
+ // Long-term memory is optional enrichment; a local identity or schema
742
+ // problem must never block current source/code context delivery.
743
+ }
744
+ }
745
+
677
746
  let workspace: KnowledgeWorkspace | undefined;
678
747
  let pages: WorksetPage[] = [];
679
748
  let workflows: WorksetWorkflow[] = [];
@@ -719,7 +788,10 @@ export async function buildTaskWorkset(input: BuildTaskWorksetInput): Promise<Ta
719
788
  const evidenceIds = unique(selection.claims.flatMap(claim => evidenceIdsForClaim(
720
789
  claim,
721
790
  evidenceByClaim.get(claim.id) ?? [],
722
- )));
791
+ )).concat(
792
+ durableMemory.map(memory => 'durable:' + memory.id),
793
+ durableEvidence.map(evidence => 'durable-evidence:' + evidence.id),
794
+ ));
723
795
  const verification = unique([
724
796
  ...workflows.flatMap(workflow => workflow.verificationGates),
725
797
  ...input.verificationHints,
@@ -758,7 +830,7 @@ export async function buildTaskWorkset(input: BuildTaskWorksetInput): Promise<Ta
758
830
  }
759
831
  : undefined;
760
832
  const base = {
761
- version: '1.2' as const,
833
+ version: '1.3' as const,
762
834
  task,
763
835
  lens: input.lens,
764
836
  currentFacts: input.currentFacts?.map(fact => fact.startsWith('Historical note:')
@@ -773,6 +845,7 @@ export async function buildTaskWorkset(input: BuildTaskWorksetInput): Promise<Ta
773
845
  hiddenCautionMemoryCount: input.hiddenCautionMemoryCount ?? 0,
774
846
  claims,
775
847
  pages,
848
+ durableMemory,
776
849
  workflows,
777
850
  cautions: normalizedCautions,
778
851
  verification,
@@ -789,7 +862,7 @@ export async function buildTaskWorkset(input: BuildTaskWorksetInput): Promise<Ta
789
862
  budget: { maxTokens },
790
863
  });
791
864
  const receipt: ContextReceipt = {
792
- version: '1.2.4',
865
+ version: '1.3',
793
866
  target: input.deliveryTarget ?? 'project-context',
794
867
  elapsedMs: Math.max(0, Date.now() - startedAt),
795
868
  budget: {
@@ -0,0 +1,242 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { getDatabase } from '../store/sqlite-db.js';
3
+ import type {
4
+ LongTermMemory,
5
+ LongTermMemoryEvidence,
6
+ LongTermMemoryEvent,
7
+ } from './long-term-types.js';
8
+
9
+ function optionalText(value: unknown): string | undefined {
10
+ return typeof value === 'string' && value.trim() ? value : undefined;
11
+ }
12
+
13
+ function arrayValue(value: unknown): string[] {
14
+ if (typeof value !== 'string' || !value) return [];
15
+ try {
16
+ const parsed = JSON.parse(value);
17
+ return Array.isArray(parsed) ? parsed.filter((item): item is string => typeof item === 'string') : [];
18
+ } catch {
19
+ return [];
20
+ }
21
+ }
22
+
23
+ function rowToMemory(row: any): LongTermMemory {
24
+ return {
25
+ id: row.id,
26
+ originProjectId: row.originProjectId,
27
+ ownerId: row.ownerId,
28
+ scope: row.scope,
29
+ kind: row.kind,
30
+ state: row.state,
31
+ portability: row.portability,
32
+ title: row.title,
33
+ content: row.content,
34
+ facts: arrayValue(row.factsJson),
35
+ tags: arrayValue(row.tagsJson),
36
+ ...(optionalText(row.applicability) ? { applicability: row.applicability } : {}),
37
+ origin: row.origin,
38
+ createdAt: row.createdAt,
39
+ updatedAt: row.updatedAt,
40
+ ...(optionalText(row.qualifiedAt) ? { qualifiedAt: row.qualifiedAt } : {}),
41
+ ...(optionalText(row.approvedAt) ? { approvedAt: row.approvedAt } : {}),
42
+ ...(optionalText(row.archivedAt) ? { archivedAt: row.archivedAt } : {}),
43
+ ...(optionalText(row.supersededBy) ? { supersededBy: row.supersededBy } : {}),
44
+ ...(optionalText(row.lastValidatedAt) ? { lastValidatedAt: row.lastValidatedAt } : {}),
45
+ accessCount: Number(row.accessCount ?? 0),
46
+ ...(optionalText(row.lastAccessedAt) ? { lastAccessedAt: row.lastAccessedAt } : {}),
47
+ } as LongTermMemory;
48
+ }
49
+
50
+ function rowToEvidence(row: any): LongTermMemoryEvidence {
51
+ return {
52
+ id: row.id,
53
+ memoryId: row.memoryId,
54
+ kind: row.kind,
55
+ referenceId: row.referenceId,
56
+ relation: row.relation,
57
+ ...(optionalText(row.locator) ? { locator: row.locator } : {}),
58
+ ...(optionalText(row.capturedHash) ? { capturedHash: row.capturedHash } : {}),
59
+ createdAt: row.createdAt,
60
+ } as LongTermMemoryEvidence;
61
+ }
62
+
63
+ function rowToEvent(row: any): LongTermMemoryEvent {
64
+ return {
65
+ id: row.id,
66
+ memoryId: row.memoryId,
67
+ kind: row.kind,
68
+ ...(optionalText(row.fromState) ? { fromState: row.fromState } : {}),
69
+ ...(optionalText(row.toState) ? { toState: row.toState } : {}),
70
+ ...(optionalText(row.detail) ? { detail: row.detail } : {}),
71
+ createdAt: row.createdAt,
72
+ } as LongTermMemoryEvent;
73
+ }
74
+
75
+ /** Persistence only. Lifecycle, privacy, and portability policy live in long-term.ts. */
76
+ export class LongTermMemoryStore {
77
+ private db: any = null;
78
+
79
+ async init(dataDir: string): Promise<void> {
80
+ this.db = getDatabase(dataDir);
81
+ }
82
+
83
+ transaction<T>(fn: () => T): T {
84
+ return this.db.transaction(fn)();
85
+ }
86
+
87
+ get(id: string): LongTermMemory | undefined {
88
+ const row = this.db.prepare('SELECT * FROM long_term_memories WHERE id = ?').get(id);
89
+ return row ? rowToMemory(row) : undefined;
90
+ }
91
+
92
+ list(options: { ownerId?: string; originProjectId?: string; limit?: number } = {}): LongTermMemory[] {
93
+ const limit = Math.max(1, Math.min(1_000, Math.floor(options.limit ?? 500)));
94
+ const clauses: string[] = [];
95
+ const params: unknown[] = [];
96
+ if (options.ownerId) {
97
+ clauses.push('ownerId = ?');
98
+ params.push(options.ownerId);
99
+ }
100
+ if (options.originProjectId) {
101
+ clauses.push('originProjectId = ?');
102
+ params.push(options.originProjectId);
103
+ }
104
+ const where = clauses.length ? ' WHERE ' + clauses.join(' AND ') : '';
105
+ const rows = this.db.prepare(
106
+ 'SELECT * FROM long_term_memories' + where + ' ORDER BY updatedAt DESC, id LIMIT ?',
107
+ ).all(...params, limit);
108
+ return rows.map(rowToMemory);
109
+ }
110
+
111
+ insert(memory: LongTermMemory): void {
112
+ this.db.prepare(`
113
+ INSERT INTO long_term_memories (
114
+ id, originProjectId, ownerId, scope, kind, state, portability,
115
+ title, content, factsJson, tagsJson, applicability, origin,
116
+ createdAt, updatedAt, qualifiedAt, approvedAt, archivedAt,
117
+ supersededBy, lastValidatedAt, accessCount, lastAccessedAt
118
+ ) VALUES (
119
+ @id, @originProjectId, @ownerId, @scope, @kind, @state, @portability,
120
+ @title, @content, @factsJson, @tagsJson, @applicability, @origin,
121
+ @createdAt, @updatedAt, @qualifiedAt, @approvedAt, @archivedAt,
122
+ @supersededBy, @lastValidatedAt, @accessCount, @lastAccessedAt
123
+ )
124
+ `).run({
125
+ ...memory,
126
+ factsJson: JSON.stringify(memory.facts),
127
+ tagsJson: JSON.stringify(memory.tags),
128
+ applicability: memory.applicability ?? null,
129
+ qualifiedAt: memory.qualifiedAt ?? null,
130
+ approvedAt: memory.approvedAt ?? null,
131
+ archivedAt: memory.archivedAt ?? null,
132
+ supersededBy: memory.supersededBy ?? null,
133
+ lastValidatedAt: memory.lastValidatedAt ?? null,
134
+ lastAccessedAt: memory.lastAccessedAt ?? null,
135
+ });
136
+ }
137
+
138
+ update(memory: LongTermMemory): void {
139
+ this.db.prepare(`
140
+ UPDATE long_term_memories SET
141
+ scope = @scope,
142
+ kind = @kind,
143
+ state = @state,
144
+ portability = @portability,
145
+ title = @title,
146
+ content = @content,
147
+ factsJson = @factsJson,
148
+ tagsJson = @tagsJson,
149
+ applicability = @applicability,
150
+ updatedAt = @updatedAt,
151
+ qualifiedAt = @qualifiedAt,
152
+ approvedAt = @approvedAt,
153
+ archivedAt = @archivedAt,
154
+ supersededBy = @supersededBy,
155
+ lastValidatedAt = @lastValidatedAt,
156
+ accessCount = @accessCount,
157
+ lastAccessedAt = @lastAccessedAt
158
+ WHERE id = @id
159
+ `).run({
160
+ ...memory,
161
+ factsJson: JSON.stringify(memory.facts),
162
+ tagsJson: JSON.stringify(memory.tags),
163
+ applicability: memory.applicability ?? null,
164
+ qualifiedAt: memory.qualifiedAt ?? null,
165
+ approvedAt: memory.approvedAt ?? null,
166
+ archivedAt: memory.archivedAt ?? null,
167
+ supersededBy: memory.supersededBy ?? null,
168
+ lastValidatedAt: memory.lastValidatedAt ?? null,
169
+ lastAccessedAt: memory.lastAccessedAt ?? null,
170
+ });
171
+ }
172
+
173
+ insertEvidence(input: Omit<LongTermMemoryEvidence, 'id' | 'createdAt'> & { createdAt?: string }): LongTermMemoryEvidence {
174
+ const evidence: LongTermMemoryEvidence = {
175
+ id: randomUUID(),
176
+ ...input,
177
+ createdAt: input.createdAt ?? new Date().toISOString(),
178
+ };
179
+ this.db.prepare(`
180
+ INSERT INTO long_term_memory_evidence (
181
+ id, memoryId, kind, referenceId, relation, locator, capturedHash, createdAt
182
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
183
+ `).run(
184
+ evidence.id,
185
+ evidence.memoryId,
186
+ evidence.kind,
187
+ evidence.referenceId,
188
+ evidence.relation,
189
+ evidence.locator ?? null,
190
+ evidence.capturedHash ?? null,
191
+ evidence.createdAt,
192
+ );
193
+ return evidence;
194
+ }
195
+
196
+ listEvidence(memoryId: string): LongTermMemoryEvidence[] {
197
+ return this.db.prepare(`
198
+ SELECT * FROM long_term_memory_evidence WHERE memoryId = ? ORDER BY createdAt ASC, id
199
+ `).all(memoryId).map(rowToEvidence);
200
+ }
201
+
202
+ recordEvent(input: Omit<LongTermMemoryEvent, 'id' | 'createdAt'> & { createdAt?: string }): LongTermMemoryEvent {
203
+ const event: LongTermMemoryEvent = {
204
+ id: randomUUID(),
205
+ ...input,
206
+ createdAt: input.createdAt ?? new Date().toISOString(),
207
+ };
208
+ this.db.prepare(`
209
+ INSERT INTO long_term_memory_events (id, memoryId, kind, fromState, toState, detail, createdAt)
210
+ VALUES (?, ?, ?, ?, ?, ?, ?)
211
+ `).run(
212
+ event.id,
213
+ event.memoryId,
214
+ event.kind,
215
+ event.fromState ?? null,
216
+ event.toState ?? null,
217
+ event.detail ?? null,
218
+ event.createdAt,
219
+ );
220
+ return event;
221
+ }
222
+
223
+ listEvents(memoryId: string): LongTermMemoryEvent[] {
224
+ return this.db.prepare(`
225
+ SELECT * FROM long_term_memory_events WHERE memoryId = ? ORDER BY createdAt ASC, rowid ASC
226
+ `).all(memoryId).map(rowToEvent);
227
+ }
228
+
229
+ markAccess(ids: string[], at = new Date().toISOString()): void {
230
+ const unique = [...new Set(ids.filter(Boolean))];
231
+ if (unique.length === 0) return;
232
+ const statement = this.db.prepare(`
233
+ UPDATE long_term_memories
234
+ SET accessCount = accessCount + 1, lastAccessedAt = ?
235
+ WHERE id = ?
236
+ `);
237
+ this.db.transaction(() => {
238
+ for (const id of unique) statement.run(at, id);
239
+ })();
240
+ }
241
+
242
+ }
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Durable cognitive-memory contracts. These types are intentionally separate
3
+ * from Observation provenance and Knowledge Claim truth contracts.
4
+ */
5
+
6
+ export const LONG_TERM_MEMORY_KINDS = ['episodic', 'semantic', 'procedural'] as const;
7
+ export type LongTermMemoryKind = typeof LONG_TERM_MEMORY_KINDS[number];
8
+
9
+ export const LONG_TERM_MEMORY_SCOPES = ['project', 'user', 'team'] as const;
10
+ export type LongTermMemoryScope = typeof LONG_TERM_MEMORY_SCOPES[number];
11
+
12
+ export const LONG_TERM_MEMORY_STATES = [
13
+ 'candidate',
14
+ 'qualified',
15
+ 'approved',
16
+ 'archived',
17
+ 'superseded',
18
+ ] as const;
19
+ export type LongTermMemoryState = typeof LONG_TERM_MEMORY_STATES[number];
20
+
21
+ export const LONG_TERM_MEMORY_PORTABILITIES = ['project-bound', 'portable'] as const;
22
+ export type LongTermMemoryPortability = typeof LONG_TERM_MEMORY_PORTABILITIES[number];
23
+
24
+ export const LONG_TERM_MEMORY_EVIDENCE_KINDS = [
25
+ 'observation',
26
+ 'claim',
27
+ 'workflow',
28
+ 'session',
29
+ 'checkpoint',
30
+ 'git',
31
+ 'code',
32
+ 'test',
33
+ 'run',
34
+ 'document',
35
+ 'manual',
36
+ 'user',
37
+ ] as const;
38
+ export type LongTermMemoryEvidenceKind = typeof LONG_TERM_MEMORY_EVIDENCE_KINDS[number];
39
+
40
+ export const LONG_TERM_MEMORY_EVIDENCE_RELATIONS = [
41
+ 'supports',
42
+ 'verifies',
43
+ 'derives',
44
+ 'user-confirmed',
45
+ ] as const;
46
+ export type LongTermMemoryEvidenceRelation = typeof LONG_TERM_MEMORY_EVIDENCE_RELATIONS[number];
47
+
48
+ export type LongTermMemoryOrigin = 'manual' | 'agent' | 'hook' | 'git' | 'migration';
49
+
50
+ export interface LongTermMemoryEvidence {
51
+ id: string;
52
+ memoryId: string;
53
+ kind: LongTermMemoryEvidenceKind;
54
+ referenceId: string;
55
+ relation: LongTermMemoryEvidenceRelation;
56
+ locator?: string;
57
+ capturedHash?: string;
58
+ createdAt: string;
59
+ }
60
+
61
+ export interface LongTermMemory {
62
+ id: string;
63
+ /** Project from which this item and its evidence originated. */
64
+ originProjectId: string;
65
+ /** Local stable owner identity. Team and project records retain attribution. */
66
+ ownerId: string;
67
+ scope: LongTermMemoryScope;
68
+ kind: LongTermMemoryKind;
69
+ state: LongTermMemoryState;
70
+ portability: LongTermMemoryPortability;
71
+ title: string;
72
+ content: string;
73
+ facts: string[];
74
+ tags: string[];
75
+ /** Short condition explaining when the procedure/fact applies. */
76
+ applicability?: string;
77
+ origin: LongTermMemoryOrigin;
78
+ createdAt: string;
79
+ updatedAt: string;
80
+ qualifiedAt?: string;
81
+ approvedAt?: string;
82
+ archivedAt?: string;
83
+ supersededBy?: string;
84
+ lastValidatedAt?: string;
85
+ accessCount: number;
86
+ lastAccessedAt?: string;
87
+ }
88
+
89
+ export type LongTermMemoryEventKind = 'created' | 'qualified' | 'approved' | 'archived' | 'superseded';
90
+
91
+ export interface LongTermMemoryEvent {
92
+ id: string;
93
+ memoryId: string;
94
+ kind: LongTermMemoryEventKind;
95
+ fromState?: LongTermMemoryState;
96
+ toState?: LongTermMemoryState;
97
+ detail?: string;
98
+ createdAt: string;
99
+ }
100
+
101
+ export interface LongTermMemoryReader {
102
+ projectId: string;
103
+ ownerId?: string;
104
+ agentId?: string;
105
+ isTeamMember?: boolean;
106
+ }
107
+
108
+ export interface LongTermMemoryEvidenceInput {
109
+ kind: LongTermMemoryEvidenceKind;
110
+ referenceId: string;
111
+ relation: LongTermMemoryEvidenceRelation;
112
+ locator?: string;
113
+ capturedHash?: string;
114
+ }
115
+
116
+ export interface CreateLongTermMemoryInput {
117
+ originProjectId: string;
118
+ ownerId: string;
119
+ scope: LongTermMemoryScope;
120
+ kind: LongTermMemoryKind;
121
+ portability?: LongTermMemoryPortability;
122
+ title: string;
123
+ content: string;
124
+ facts?: string[];
125
+ tags?: string[];
126
+ applicability?: string;
127
+ origin?: LongTermMemoryOrigin;
128
+ evidence: LongTermMemoryEvidenceInput[];
129
+ }
130
+
131
+ export interface LongTermMemorySelection {
132
+ memory: LongTermMemory;
133
+ evidence: LongTermMemoryEvidence[];
134
+ score: number;
135
+ reason: string;
136
+ }