@jungjaehoon/mama-core 5.0.0 → 5.1.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.
package/README.md CHANGED
@@ -4,7 +4,7 @@ The shared engine for storage, records and revisions, evidence links, memory, se
4
4
  runtime drivers. Consumers supply their own database, principals, source access and product
5
5
  vocabulary through public exports. Core does not require the MAMA OS daemon.
6
6
 
7
- Version **5.0.0**; Node.js 22.13+. This README describes the current rebuild checkout.
7
+ Version **5.1.0**; Node.js 22.13+. This README describes the current rebuild checkout.
8
8
  See [architecture](../../docs/explanation/architecture.md) and
9
9
  [the shared-engine goal](../../INTENT.md).
10
10
 
@@ -1367,7 +1367,7 @@ function coreActionRegistrations(knowledge, adapter, deps) {
1367
1367
  memoryId: typeof body.memory_id === 'string' ? body.memory_id : '',
1368
1368
  status,
1369
1369
  reason: typeof body.reason === 'string' ? body.reason : '',
1370
- }, { ...writeAccess, scopes }, requiredOperationId(context, 'memory.retire'));
1370
+ }, { ...writeAccess, scopes }, requiredOperationId(context, 'memory.retire'), context.session);
1371
1371
  recordWriteReceipt(context, 'memory.retire', retired.id);
1372
1372
  return retired;
1373
1373
  },
@@ -17,7 +17,7 @@ const tableColumnCache = new WeakMap();
17
17
  // Keep memory-truth quarantine semantics excluded for legacy/backcompat rows even though the
18
18
  // decisions.status terminal states: 'superseded' is history a caller holding
19
19
  // scope may read under includeReplaced; the rest are holds excluded always.
20
- const RETIRED_MEMORY_STATUSES = new Set(['quarantined', 'contradicted', 'stale']);
20
+ const RETIRED_MEMORY_STATUSES = new Set(['contradicted', 'stale']);
21
21
  class TwinRefNotVisibleError extends Error {
22
22
  constructor(ref) {
23
23
  super(`Twin ref is not visible to requested visibility: ${ref.kind}:${ref.id}`);
@@ -19,7 +19,7 @@ export { observationVersionId, appendObservationVersion, getObservationVersion,
19
19
  export { createWork, readWork, reviseWork, withdrawWork } from './commitments.js';
20
20
  export { parseExactDueAt, assertIsoDate, assertWorkPatchValues, WORK_PATCH_DEADLINE_PATTERN, WORK_PATCH_DUE_AT_PATTERN, type ParsedExactDueAt, } from './work-dates.js';
21
21
  export type { CommitmentPage, CommitmentChainEntry, CommitmentRevision, CommitmentView, CreateWorkCommand, ReviseWorkCommand, WithdrawWorkCommand, WorkRead, WorkWriteResult, } from './commitments.js';
22
- export { vectorSearch, fts5Search } from './search.js';
22
+ export { vectorSearch, fts5Search, RECALL_EXCLUDED_STATUSES } from './search.js';
23
23
  export { queryDecisionGraph, querySemanticEdges, STATED_DECISION_EDGES, getGraphNeighborhood, getGraphPaths, getGraphTimeline, queryGraph, AgentGraphValidationError, type AgentGraphAdapter, type AgentGraphEdgeFilters, type AgentGraphResult, type AgentGraphCurrentProjection, type AgentGraphPath, type AgentGraphTimelineEvent, type AgentGraphTimelineMemoryEvent, type AgentGraphTimelineCaseEvent, type AgentGraphTimelineRawEvent, type AgentGraphTimelineEdgeEvent, type GraphNeighborhoodInput, type GraphPathsInput, type GraphPathsResult, type GraphTimelineInput, type GraphTimelineResult, } from './graph-query.js';
24
24
  export type { SourceIngestCommand, SourceIngestReceipt } from './source-ingest.js';
25
25
  export interface KnowledgeOptions extends JudgmentKnowledgeOptions {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AgentGraphValidationError = exports.queryGraph = exports.getGraphTimeline = exports.getGraphPaths = exports.getGraphNeighborhood = exports.STATED_DECISION_EDGES = exports.querySemanticEdges = exports.queryDecisionGraph = exports.fts5Search = exports.vectorSearch = exports.WORK_PATCH_DUE_AT_PATTERN = exports.WORK_PATCH_DEADLINE_PATTERN = exports.assertWorkPatchValues = exports.assertIsoDate = exports.parseExactDueAt = exports.withdrawWork = exports.reviseWork = exports.readWork = exports.createWork = exports.isObservationVisibilityRowVisible = exports.isObservationVersionVisible = exports.readObservationVersion = exports.searchOwnerObservationVersions = exports.getObservationVersion = exports.appendObservationVersion = exports.observationVersionId = exports.correctIdentity = exports.ingestSource = exports.TWIN_REF_KINDS = exports.TWIN_EDGE_TYPES = exports.TWIN_EDGE_SOURCES = exports.TwinRefNotVisibleError = exports.visibleTwinRefKeysRecursive = exports.visibleTwinRefKeys = exports.listVisibleTwinEdgesForRefs = exports.isChannelGranted = exports.channelGrantClause = exports.assertTwinRefsVisible = exports.linkEdgeId = exports.findLink = exports.appendLink = exports.mapTwinEdgeRow = exports.listTwinEdgesForRefs = exports.getTwinEdge = exports.appendJudgment = exports.JudgmentError = exports.WORK_RECLASSIFY_DISPOSITIONS = exports.judgmentRecordId = void 0;
3
+ exports.AgentGraphValidationError = exports.queryGraph = exports.getGraphTimeline = exports.getGraphPaths = exports.getGraphNeighborhood = exports.STATED_DECISION_EDGES = exports.querySemanticEdges = exports.queryDecisionGraph = exports.RECALL_EXCLUDED_STATUSES = exports.fts5Search = exports.vectorSearch = exports.WORK_PATCH_DUE_AT_PATTERN = exports.WORK_PATCH_DEADLINE_PATTERN = exports.assertWorkPatchValues = exports.assertIsoDate = exports.parseExactDueAt = exports.withdrawWork = exports.reviseWork = exports.readWork = exports.createWork = exports.isObservationVisibilityRowVisible = exports.isObservationVersionVisible = exports.readObservationVersion = exports.searchOwnerObservationVersions = exports.getObservationVersion = exports.appendObservationVersion = exports.observationVersionId = exports.correctIdentity = exports.ingestSource = exports.TWIN_REF_KINDS = exports.TWIN_EDGE_TYPES = exports.TWIN_EDGE_SOURCES = exports.TwinRefNotVisibleError = exports.visibleTwinRefKeysRecursive = exports.visibleTwinRefKeys = exports.listVisibleTwinEdgesForRefs = exports.isChannelGranted = exports.channelGrantClause = exports.assertTwinRefsVisible = exports.linkEdgeId = exports.findLink = exports.appendLink = exports.mapTwinEdgeRow = exports.listTwinEdgesForRefs = exports.getTwinEdge = exports.appendJudgment = exports.JudgmentError = exports.WORK_RECLASSIFY_DISPOSITIONS = exports.judgmentRecordId = void 0;
4
4
  exports.createKnowledge = createKnowledge;
5
5
  const links_js_1 = require("./links.js");
6
6
  const judgments_js_1 = require("./judgments.js");
@@ -62,6 +62,7 @@ Object.defineProperty(exports, "WORK_PATCH_DUE_AT_PATTERN", { enumerable: true,
62
62
  var search_js_1 = require("./search.js");
63
63
  Object.defineProperty(exports, "vectorSearch", { enumerable: true, get: function () { return search_js_1.vectorSearch; } });
64
64
  Object.defineProperty(exports, "fts5Search", { enumerable: true, get: function () { return search_js_1.fts5Search; } });
65
+ Object.defineProperty(exports, "RECALL_EXCLUDED_STATUSES", { enumerable: true, get: function () { return search_js_1.RECALL_EXCLUDED_STATUSES; } });
65
66
  var graph_query_js_2 = require("./graph-query.js");
66
67
  Object.defineProperty(exports, "queryDecisionGraph", { enumerable: true, get: function () { return graph_query_js_2.queryDecisionGraph; } });
67
68
  Object.defineProperty(exports, "querySemanticEdges", { enumerable: true, get: function () { return graph_query_js_2.querySemanticEdges; } });
@@ -8,6 +8,8 @@
8
8
  */
9
9
  import type { DatabaseInstance, DecisionRecord } from '../db-manager.js';
10
10
  import type { MemoryKindFilter } from '../memory/types.js';
11
+ /** Statuses default recall leaves out; history (`includeHistory`) shows them. */
12
+ export declare const RECALL_EXCLUDED_STATUSES: readonly ["superseded", "contradicted", "stale"];
11
13
  /**
12
14
  * Brute-force cosine similarity search over stored embeddings.
13
15
  *
@@ -31,7 +33,10 @@ export declare function vectorSearch(adapter: DatabaseInstance, queryEmbedding:
31
33
  * @param limit - Max rows to return
32
34
  * @returns Matching decision IDs with BM25 rank scores
33
35
  */
34
- export declare function fts5Search(adapter: DatabaseInstance, query: string, limit?: number, kind?: MemoryKindFilter): Promise<{
36
+ export declare function fts5Search(adapter: DatabaseInstance, query: string, limit?: number, kind?: MemoryKindFilter, exclude?: {
37
+ statuses?: readonly string[];
38
+ amendments?: boolean;
39
+ }): Promise<{
35
40
  id: string;
36
41
  rank: number;
37
42
  }[]>;
@@ -8,8 +8,11 @@
8
8
  * @module knowledge/search
9
9
  */
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.RECALL_EXCLUDED_STATUSES = void 0;
11
12
  exports.vectorSearch = vectorSearch;
12
13
  exports.fts5Search = fts5Search;
14
+ /** Statuses default recall leaves out; history (`includeHistory`) shows them. */
15
+ exports.RECALL_EXCLUDED_STATUSES = ['superseded', 'contradicted', 'stale'];
13
16
  /**
14
17
  * Brute-force cosine similarity search over stored embeddings.
15
18
  *
@@ -59,7 +62,7 @@ async function vectorSearch(adapter, queryEmbedding, limit = 5, threshold = 0.7,
59
62
  * @param limit - Max rows to return
60
63
  * @returns Matching decision IDs with BM25 rank scores
61
64
  */
62
- async function fts5Search(adapter, query, limit = 10, kind) {
65
+ async function fts5Search(adapter, query, limit = 10, kind, exclude) {
63
66
  // An absent FTS table is a real answer - no rows. A failing adapter is not,
64
67
  // so this lookup is left unguarded and its errors reach the caller.
65
68
  const tableCheck = adapter
@@ -68,24 +71,27 @@ async function fts5Search(adapter, query, limit = 10, kind) {
68
71
  if (!tableCheck)
69
72
  return [];
70
73
  // Query execution - let errors propagate to the caller
71
- const kindClause = Array.isArray(kind)
72
- ? `AND d.kind IN (${kind.map(() => '?').join(', ')})`
73
- : kind === undefined
74
- ? ''
75
- : 'AND d.kind = ?';
74
+ const kinds = Array.isArray(kind) ? kind : kind === undefined ? [] : [kind];
75
+ const kindClause = kinds.length === 0 ? '' : `AND d.kind IN (${kinds.map(() => '?').join(', ')})`;
76
+ // Excluded rows are left out before LIMIT, so they cannot fill the pool ahead of rows that stay.
77
+ const statuses = exclude?.statuses ?? [];
78
+ const statusClause = statuses.length === 0
79
+ ? ''
80
+ : `AND (d.status IS NULL OR d.status NOT IN (${statuses.map(() => '?').join(', ')}))`;
81
+ const amendmentClause = exclude?.amendments
82
+ ? "AND json_extract(d.payload_json, '$.amended') IS NULL"
83
+ : '';
76
84
  const stmt = adapter.prepare(`
77
85
  SELECT d.id, rank
78
86
  FROM decisions_fts
79
87
  JOIN decisions d ON decisions_fts.rowid = d.rowid
80
88
  WHERE decisions_fts MATCH ?
81
89
  ${kindClause}
90
+ ${statusClause}
91
+ ${amendmentClause}
82
92
  ORDER BY rank
83
93
  LIMIT ?
84
94
  `);
85
- return (Array.isArray(kind)
86
- ? stmt.all(query, ...kind, limit)
87
- : kind === undefined
88
- ? stmt.all(query, limit)
89
- : stmt.all(query, kind, limit));
95
+ return stmt.all(query, ...kinds, ...statuses, limit);
90
96
  }
91
97
  //# sourceMappingURL=search.js.map
@@ -76,7 +76,7 @@ export declare function retireMemoryRecord(adapter: DatabaseInstance, input: {
76
76
  memoryId: string;
77
77
  status: MemoryRetirementStatus;
78
78
  reason: string;
79
- }, access: JudgmentAccess, commandId: string): Promise<{
79
+ }, access: JudgmentAccess, commandId: string, session?: ActionSessionFacts): Promise<{
80
80
  success: true;
81
81
  id: string;
82
82
  status: MemoryRetirementStatus;
@@ -713,7 +713,7 @@ async function saveLegacyMemory(adapter, input, legacy, access) {
713
713
  return saveMemoryInternal(adapter, clean, provenance, effectiveAccess, legacy);
714
714
  }
715
715
  /** Append an access-checked status amendment for one stored memory record. */
716
- async function retireMemoryRecord(adapter, input, access, commandId) {
716
+ async function retireMemoryRecord(adapter, input, access, commandId, session) {
717
717
  const id = input.memoryId.trim();
718
718
  const reason = input.reason.trim();
719
719
  if (!id)
@@ -729,11 +729,30 @@ async function retireMemoryRecord(adapter, input, access, commandId) {
729
729
  }
730
730
  const admittedScopes = record.scopes.filter((recordScope) => access.scopes.some((scope) => scope.kind === recordScope.kind && scope.id === recordScope.id));
731
731
  const summary = `Status '${input.status}' applied to ${id}: ${reason}`;
732
+ // Who retired it, stated by the host as for a save, so a retirement can be traced to its turn.
733
+ const provenance = (0, provenance_js_1.normalizeMemoryWriteProvenance)({
734
+ actor: session?.actor ?? 'main_agent',
735
+ agent_id: access.agentId,
736
+ model_run_id: session?.modelRunId,
737
+ envelope_hash: session?.envelopeHash,
738
+ tool_name: session?.toolName,
739
+ gateway_call_id: session?.gatewayCallId,
740
+ context_packet_id: session?.contextPacketId,
741
+ source_turn_id: session?.sourceTurnId,
742
+ source_message_ref: session?.sourceMessageRef,
743
+ source_refs: session?.sourceRefs ? [...session.sourceRefs] : undefined,
744
+ });
732
745
  const receipt = await (0, index_js_1.appendJudgment)({
733
746
  commandId,
734
747
  topic: `judgment/${id}`,
735
748
  summary,
736
749
  recordKind: 'judgment',
750
+ sourceRefs: provenance.source_refs,
751
+ provenance: provenance.provenance,
752
+ agentId: provenance.agent_id,
753
+ modelRunId: provenance.model_run_id,
754
+ envelopeHash: provenance.envelope_hash,
755
+ gatewayCallId: provenance.gateway_call_id,
737
756
  payload: { amended: id, status: input.status, reason },
738
757
  scopes: admittedScopes,
739
758
  links: [{ relation: 'amends', target: { kind: 'memory', id } }],
@@ -747,12 +766,15 @@ async function buildProfile(adapter, scopes) {
747
766
  const records = await loadScopedMemories(adapter, scopes);
748
767
  return (0, profile_builder_js_1.classifyProfileEntries)(records);
749
768
  }
750
- const EXCLUDED_STATUSES = new Set([
751
- 'superseded',
752
- 'quarantined',
753
- 'contradicted',
754
- 'stale',
755
- ]);
769
+ const EXCLUDED_STATUSES = new Set(search_js_1.RECALL_EXCLUDED_STATUSES);
770
+ /** The ids among these that only amend another record (a retirement or an outcome change). */
771
+ function amendmentIds(adapter, ids) {
772
+ const rows = adapter
773
+ .prepare(`SELECT id FROM decisions WHERE id IN (${ids.map(() => '?').join(',')})
774
+ AND json_extract(payload_json, '$.amended') IS NOT NULL`)
775
+ .all(...ids);
776
+ return new Set(rows.map((row) => row.id));
777
+ }
756
778
  async function recallMemory(adapter, query, options = {}) {
757
779
  const bundle = (0, types_js_1.createEmptyRecallBundle)(query);
758
780
  const searchOptions = (0, search_quality_js_1.normalizeSearchQualityOptions)(options);
@@ -930,7 +952,7 @@ async function recallMemory(adapter, query, options = {}) {
930
952
  .map((t) => stemToken(t))
931
953
  .filter((t) => !FTS5_NOISE_WORDS.has(t));
932
954
  const ftsQuery = ftsTokens.length > 0 ? ftsTokens.join(' OR ') : query;
933
- const ftsResults = await (0, search_js_1.fts5Search)(searchAdapter, ftsQuery, lexicalLimit, options.kind);
955
+ const ftsResults = await (0, search_js_1.fts5Search)(searchAdapter, ftsQuery, lexicalLimit, options.kind, options.includeHistory ? undefined : { statuses: [...EXCLUDED_STATUSES], amendments: true });
934
956
  if (ftsResults.length > 0) {
935
957
  const adapter = searchAdapter;
936
958
  const fallbackSource = {
@@ -1012,6 +1034,10 @@ async function recallMemory(adapter, query, options = {}) {
1012
1034
  if (options.kind !== undefined) {
1013
1035
  lexicalRecords = lexicalRecords.filter((r) => matchesKind(r.kind));
1014
1036
  }
1037
+ if (!options.includeHistory && lexicalRecords.length > 0) {
1038
+ const amendments = amendmentIds(adapter, lexicalRecords.map((r) => r.id));
1039
+ lexicalRecords = lexicalRecords.filter((r) => !amendments.has(r.id));
1040
+ }
1015
1041
  lexicalCandidates = buildLexicalCandidates(lexicalRecords, query);
1016
1042
  if (subQueries.length > 1) {
1017
1043
  for (const sq of subQueries.slice(1)) {
@@ -1187,6 +1213,15 @@ async function recallMemory(adapter, query, options = {}) {
1187
1213
  ];
1188
1214
  });
1189
1215
  fusedHits = fusedHits.filter((hit) => hit.source_type !== 'decision' || acceptedPrimaryIds.has(hit.source_id));
1216
+ // A retirement or an outcome change audits another record; it is not a belief. Default recall
1217
+ // leaves it out and history shows it. Only the host writers put `amended` in a payload.
1218
+ if (!options.includeHistory && matched.length > 0) {
1219
+ const amendments = amendmentIds(adapter, matched.map((record) => record.id));
1220
+ if (amendments.size > 0) {
1221
+ matched = matched.filter((record) => !amendments.has(record.id));
1222
+ fusedHits = fusedHits.filter((hit) => hit.source_type !== 'decision' || !amendments.has(hit.source_id));
1223
+ }
1224
+ }
1190
1225
  // Honor options.limit on the final memories (matched is RRF-rank-sorted, canonical
1191
1226
  // dual-write appends last). Without this cap the full fusion set (hundreds of records)
1192
1227
  // flowed into bundle.memories AND the per-record enrichment SQL loops below.
@@ -1198,14 +1233,20 @@ async function recallMemory(adapter, query, options = {}) {
1198
1233
  const cappedIds = new Set(matched.map((record) => record.id));
1199
1234
  fusedHits = fusedHits.filter((hit) => hit.source_type !== 'decision' || cappedIds.has(hit.source_id));
1200
1235
  }
1201
- // Enrich active records with summaries from their superseded predecessors.
1202
- // When ingestConversation extracts multiple facts under the same topic, only
1203
- // the last survives as "active" — the earlier ones become superseded and are
1204
- // excluded from search. This recovers their key information so it is not lost.
1236
+ // Superseded records are excluded from search, so an active record carries what it replaced:
1237
+ // the reader sees the correction and what it corrected. A predecessor is shown only inside the
1238
+ // reader's scopes, and marked as replaced.
1205
1239
  if (matched.length > 0) {
1206
1240
  const stmtChain = adapter.prepare(`SELECT id, summary, decision FROM decisions WHERE superseded_by = ?`);
1241
+ const readerScopes = options.scopes && options.scopes.length > 0
1242
+ ? new Set(options.scopes.map((scope) => `${scope.kind}:${scope.id}`))
1243
+ : null;
1207
1244
  for (const record of matched) {
1208
- const predecessors = stmtChain.all(record.id);
1245
+ let predecessors = stmtChain.all(record.id);
1246
+ if (readerScopes && predecessors.length > 0) {
1247
+ const scopeMap = batchLoadScopes(adapter, predecessors.map((predecessor) => predecessor.id));
1248
+ predecessors = predecessors.filter((predecessor) => (scopeMap.get(predecessor.id) ?? []).some((scope) => readerScopes.has(`${scope.kind}:${scope.id}`)));
1249
+ }
1209
1250
  if (predecessors.length > 0) {
1210
1251
  const extra = predecessors
1211
1252
  .map((p) => String(p.summary ?? p.decision ?? ''))
@@ -1213,8 +1254,8 @@ async function recallMemory(adapter, query, options = {}) {
1213
1254
  .join(' | ');
1214
1255
  if (extra) {
1215
1256
  record.details = record.details
1216
- ? `${record.details}\n[Prior context] ${extra}`
1217
- : `[Prior context] ${extra}`;
1257
+ ? `${record.details}\n[Replaced by this record] ${extra}`
1258
+ : `[Replaced by this record] ${extra}`;
1218
1259
  }
1219
1260
  }
1220
1261
  }
@@ -1243,6 +1284,11 @@ async function recallMemory(adapter, query, options = {}) {
1243
1284
  const status = row?.status || '';
1244
1285
  return matchesKind(row?.kind) && (!status || !EXCLUDED_STATUSES.has(status));
1245
1286
  });
1287
+ // A link an agent stated can point at a retirement or an outcome change; it stays out too.
1288
+ if (expandedOnly.length > 0) {
1289
+ const amendments = amendmentIds(adapter, expandedOnly.map((e) => e.id));
1290
+ expandedOnly = expandedOnly.filter((e) => !amendments.has(e.id));
1291
+ }
1246
1292
  }
1247
1293
  else if (options.kind !== undefined) {
1248
1294
  expandedOnly = expandedOnly.filter((e) => {
@@ -24,7 +24,7 @@ exports.OBSERVATION_COLUMNS = `observation_id AS event_index_id, source AS sourc
24
24
  * Statuses every memory read path excludes (source-readers.ts:293, and recall's own
25
25
  * history exclusion). Mirrored so a citation cannot present a retired record as current.
26
26
  */
27
- const RETIRED_MEMORY_STATUSES = new Set(['superseded', 'quarantined', 'contradicted', 'stale']);
27
+ const RETIRED_MEMORY_STATUSES = new Set(['superseded', 'contradicted', 'stale']);
28
28
  /**
29
29
  * Parse a stored source ref into what it actually is.
30
30
  *
@@ -29,7 +29,7 @@ export type MemoryKind = (typeof MEMORY_KINDS)[number];
29
29
  export type MemoryKindFilter = MemoryKind | [MemoryKind, ...MemoryKind[]];
30
30
  export declare const MEMORY_STATUSES: readonly ["active", "superseded", "contradicted", "stale"];
31
31
  export type MemoryStatus = (typeof MEMORY_STATUSES)[number];
32
- export declare const MEMORY_TRUTH_STATUSES: readonly ["active", "superseded", "contradicted", "stale", "quarantined"];
32
+ export declare const MEMORY_TRUTH_STATUSES: readonly ["active", "superseded", "contradicted", "stale"];
33
33
  export type MemoryTruthStatus = (typeof MEMORY_TRUTH_STATUSES)[number];
34
34
  export declare const MEMORY_EDGE_TYPES: readonly ["supersedes", "builds_on", "synthesizes", "contradicts"];
35
35
  export type MemoryEdgeType = (typeof MEMORY_EDGE_TYPES)[number];
@@ -35,13 +35,7 @@ exports.MEMORY_KINDS = [
35
35
  'workflow',
36
36
  ];
37
37
  exports.MEMORY_STATUSES = ['active', 'superseded', 'contradicted', 'stale'];
38
- exports.MEMORY_TRUTH_STATUSES = [
39
- 'active',
40
- 'superseded',
41
- 'contradicted',
42
- 'stale',
43
- 'quarantined',
44
- ];
38
+ exports.MEMORY_TRUTH_STATUSES = ['active', 'superseded', 'contradicted', 'stale'];
45
39
  exports.MEMORY_EDGE_TYPES = ['supersedes', 'builds_on', 'synthesizes', 'contradicts'];
46
40
  exports.MEMORY_AGENT_ACTIONS = [
47
41
  'save',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jungjaehoon/mama-core",
3
- "version": "5.0.0",
3
+ "version": "5.1.0",
4
4
  "description": "MAMA Core - Shared modules for Memory-Augmented MCP Assistant",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",