@shadowforge0/aquifer-memory 1.8.0 → 1.9.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/.env.example +1 -0
- package/README.md +49 -22
- package/README_CN.md +24 -22
- package/README_TW.md +20 -22
- package/aquifer.config.example.json +2 -1
- package/consumers/cli.js +560 -4
- package/consumers/codex.js +1 -1
- package/consumers/mcp.js +3 -0
- package/consumers/openclaw-ext/index.js +64 -6
- package/consumers/openclaw-ext/openclaw.plugin.json +1 -1
- package/consumers/openclaw-ext/package.json +1 -1
- package/consumers/openclaw-install.js +326 -0
- package/consumers/openclaw-plugin.js +39 -1
- package/consumers/shared/config.js +2 -0
- package/core/aquifer.js +180 -33
- package/core/backends/local.js +109 -0
- package/core/doctor.js +924 -0
- package/core/finalization-inspector.js +164 -0
- package/core/memory-explain.js +624 -0
- package/core/memory-recall.js +49 -23
- package/core/memory-records.js +16 -5
- package/core/memory-review.js +891 -0
- package/core/memory-serving.js +61 -4
- package/core/operator-observability.js +249 -0
- package/core/postgres-migrations.js +13 -0
- package/core/session-finalization.js +76 -1
- package/core/storage.js +124 -8
- package/docs/getting-started.md +34 -1
- package/docs/setup.md +102 -22
- package/package.json +5 -4
- package/schema/019-v1-memory-review-resolutions.sql +53 -0
- package/scripts/codex-checkpoint-commands.js +28 -0
- package/scripts/codex-checkpoint-runtime.js +109 -0
- package/scripts/codex-recovery.js +16 -4
package/core/aquifer.js
CHANGED
|
@@ -657,29 +657,24 @@ function createAquifer(config = {}) {
|
|
|
657
657
|
// --- read path ---
|
|
658
658
|
|
|
659
659
|
async memoryRecall(query, opts = {}) {
|
|
660
|
+
assertMemoryRecallQuery(query);
|
|
660
661
|
memoryServing.assertCuratedRecallOpts(opts);
|
|
661
|
-
await ensureMigrated();
|
|
662
|
-
if (typeof query !== 'string' || query.trim().length === 0) {
|
|
663
|
-
throw new Error('memory.recall(query): query must be a non-empty string');
|
|
664
|
-
}
|
|
665
662
|
const validModes = new Set(['fts', 'hybrid', 'vector']);
|
|
666
663
|
const mode = opts.mode || 'hybrid';
|
|
667
664
|
if (!validModes.has(mode)) {
|
|
668
665
|
throw new Error(`Invalid curated recall mode: "${mode}". Must be one of: fts, hybrid, vector`);
|
|
669
666
|
}
|
|
667
|
+
if (mode === 'vector' && !embedFn) {
|
|
668
|
+
throw new Error('curated memory_recall mode=vector requires config.embed.fn or EMBED_PROVIDER env');
|
|
669
|
+
}
|
|
670
|
+
const scopedOpts = memoryServing.withDefaultScope(opts);
|
|
671
|
+
await ensureMigrated();
|
|
670
672
|
let queryVec = null;
|
|
671
|
-
if (mode === 'hybrid' || mode === 'vector') {
|
|
672
|
-
if (!embedFn) {
|
|
673
|
-
if (mode === 'vector') {
|
|
674
|
-
throw new Error('curated memory_recall mode=vector requires config.embed.fn or EMBED_PROVIDER env');
|
|
675
|
-
}
|
|
676
|
-
} else {
|
|
673
|
+
if ((mode === 'hybrid' || mode === 'vector') && embedFn) {
|
|
677
674
|
const embedded = await embedFn([query]);
|
|
678
675
|
queryVec = Array.isArray(embedded) && Array.isArray(embedded[0]) ? embedded[0] : null;
|
|
679
676
|
if (!queryVec && mode === 'vector') throw new Error('embedFn returned empty vector for curated memory_recall');
|
|
680
|
-
}
|
|
681
677
|
}
|
|
682
|
-
const scopedOpts = memoryServing.withDefaultScope(opts);
|
|
683
678
|
const limit = Math.max(1, Math.min(50, scopedOpts.limit || 10));
|
|
684
679
|
const runLexical = mode === 'fts' || mode === 'hybrid';
|
|
685
680
|
const runVector = (mode === 'vector' || mode === 'hybrid') && queryVec;
|
|
@@ -1195,6 +1190,7 @@ function createAquifer(config = {}) {
|
|
|
1195
1190
|
memoryServingMode: memoryServing.servingMode,
|
|
1196
1191
|
memoryActiveScopeKey: memoryServing.defaultActiveScopeKey,
|
|
1197
1192
|
memoryActiveScopePath: memoryServing.defaultActiveScopePath,
|
|
1193
|
+
memoryAllowedScopeKeys: memoryServing.defaultAllowedScopeKeys,
|
|
1198
1194
|
backendKind,
|
|
1199
1195
|
backendProfile: backendInfo.profile,
|
|
1200
1196
|
capabilities: backendInfo.capabilities,
|
|
@@ -1299,6 +1295,11 @@ function createAquifer(config = {}) {
|
|
|
1299
1295
|
latestFinalizedAt: null,
|
|
1300
1296
|
latestUpdatedAt: null,
|
|
1301
1297
|
};
|
|
1298
|
+
let pendingSessions = {
|
|
1299
|
+
available: false,
|
|
1300
|
+
total: null,
|
|
1301
|
+
statuses: {},
|
|
1302
|
+
};
|
|
1302
1303
|
try {
|
|
1303
1304
|
const finalizationResult = await pool.query(
|
|
1304
1305
|
`SELECT
|
|
@@ -1327,7 +1328,38 @@ function createAquifer(config = {}) {
|
|
|
1327
1328
|
.sort()
|
|
1328
1329
|
.pop() || null,
|
|
1329
1330
|
};
|
|
1330
|
-
} catch {
|
|
1331
|
+
} catch (err) {
|
|
1332
|
+
if (err?.code !== '42P01') throw err;
|
|
1333
|
+
/* session_finalizations table may not exist on older installs */
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
try {
|
|
1337
|
+
const actionablePending = await pool.query(
|
|
1338
|
+
`SELECT s.processing_status, COUNT(*)::int AS count
|
|
1339
|
+
FROM ${qi(schema)}.sessions s
|
|
1340
|
+
WHERE s.tenant_id = $1
|
|
1341
|
+
AND s.processing_status IN ('pending', 'failed')
|
|
1342
|
+
AND NOT EXISTS (
|
|
1343
|
+
SELECT 1
|
|
1344
|
+
FROM ${qi(schema)}.session_finalizations f
|
|
1345
|
+
WHERE f.tenant_id = s.tenant_id
|
|
1346
|
+
AND f.session_id = s.session_id
|
|
1347
|
+
AND f.agent_id = s.agent_id
|
|
1348
|
+
AND f.source = s.source
|
|
1349
|
+
AND f.status IN ('finalized', 'skipped', 'declined', 'deferred')
|
|
1350
|
+
)
|
|
1351
|
+
GROUP BY s.processing_status`,
|
|
1352
|
+
[tenantId]
|
|
1353
|
+
);
|
|
1354
|
+
pendingSessions = {
|
|
1355
|
+
available: true,
|
|
1356
|
+
total: actionablePending.rows.reduce((sum, row) => sum + row.count, 0),
|
|
1357
|
+
statuses: Object.fromEntries(actionablePending.rows.map(row => [row.processing_status, row.count])),
|
|
1358
|
+
};
|
|
1359
|
+
} catch (err) {
|
|
1360
|
+
if (err?.code !== '42P01') throw err;
|
|
1361
|
+
/* session_finalizations table may not exist on older installs */
|
|
1362
|
+
}
|
|
1331
1363
|
|
|
1332
1364
|
return {
|
|
1333
1365
|
backendKind,
|
|
@@ -1336,6 +1368,7 @@ function createAquifer(config = {}) {
|
|
|
1336
1368
|
mode: memoryServing.servingMode,
|
|
1337
1369
|
activeScopeKey: memoryServing.defaultActiveScopeKey,
|
|
1338
1370
|
activeScopePath: memoryServing.defaultActiveScopePath,
|
|
1371
|
+
allowedScopeKeys: memoryServing.defaultAllowedScopeKeys,
|
|
1339
1372
|
},
|
|
1340
1373
|
sessions: Object.fromEntries(sessions.rows.map(r => [r.processing_status, r.count])),
|
|
1341
1374
|
sessionTotal: sessions.rows.reduce((s, r) => s + r.count, 0),
|
|
@@ -1344,6 +1377,7 @@ function createAquifer(config = {}) {
|
|
|
1344
1377
|
entities: entityCount,
|
|
1345
1378
|
memoryRecords,
|
|
1346
1379
|
sessionFinalizations,
|
|
1380
|
+
pendingSessions,
|
|
1347
1381
|
earliest: timeRange.rows[0]?.earliest || null,
|
|
1348
1382
|
latest: timeRange.rows[0]?.latest || null,
|
|
1349
1383
|
};
|
|
@@ -1351,15 +1385,38 @@ function createAquifer(config = {}) {
|
|
|
1351
1385
|
|
|
1352
1386
|
async getPendingSessions(opts = {}) {
|
|
1353
1387
|
const limit = opts.limit !== undefined ? opts.limit : 100;
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1388
|
+
let result;
|
|
1389
|
+
try {
|
|
1390
|
+
result = await pool.query(
|
|
1391
|
+
`SELECT s.session_id, s.agent_id, s.processing_status
|
|
1392
|
+
FROM ${qi(schema)}.sessions s
|
|
1393
|
+
WHERE s.tenant_id = $1
|
|
1394
|
+
AND s.processing_status IN ('pending', 'failed')
|
|
1395
|
+
AND NOT EXISTS (
|
|
1396
|
+
SELECT 1
|
|
1397
|
+
FROM ${qi(schema)}.session_finalizations f
|
|
1398
|
+
WHERE f.tenant_id = s.tenant_id
|
|
1399
|
+
AND f.session_id = s.session_id
|
|
1400
|
+
AND f.agent_id = s.agent_id
|
|
1401
|
+
AND f.source = s.source
|
|
1402
|
+
AND f.status IN ('finalized', 'skipped', 'declined', 'deferred')
|
|
1403
|
+
)
|
|
1404
|
+
ORDER BY s.started_at DESC
|
|
1405
|
+
LIMIT $2`,
|
|
1406
|
+
[tenantId, limit]
|
|
1407
|
+
);
|
|
1408
|
+
} catch (err) {
|
|
1409
|
+
if (err?.code !== '42P01') throw err;
|
|
1410
|
+
result = await pool.query(
|
|
1411
|
+
`SELECT session_id, agent_id, processing_status
|
|
1412
|
+
FROM ${qi(schema)}.sessions
|
|
1413
|
+
WHERE tenant_id = $1
|
|
1414
|
+
AND processing_status IN ('pending', 'failed')
|
|
1415
|
+
ORDER BY started_at DESC
|
|
1416
|
+
LIMIT $2`,
|
|
1417
|
+
[tenantId, limit]
|
|
1418
|
+
);
|
|
1419
|
+
}
|
|
1363
1420
|
return result.rows;
|
|
1364
1421
|
},
|
|
1365
1422
|
|
|
@@ -1386,9 +1443,10 @@ function createAquifer(config = {}) {
|
|
|
1386
1443
|
},
|
|
1387
1444
|
|
|
1388
1445
|
async memoryBootstrap(opts = {}) {
|
|
1389
|
-
await ensureMigrated();
|
|
1390
1446
|
memoryServing.assertCuratedBootstrapOpts(opts);
|
|
1391
|
-
|
|
1447
|
+
const scopedOpts = memoryServing.withDefaultScope(opts);
|
|
1448
|
+
await ensureMigrated();
|
|
1449
|
+
return memoryBootstrap.bootstrap(scopedOpts);
|
|
1392
1450
|
},
|
|
1393
1451
|
|
|
1394
1452
|
async historicalBootstrap(opts = {}) {
|
|
@@ -1426,6 +1484,10 @@ function createAquifer(config = {}) {
|
|
|
1426
1484
|
const { createMemoryConsolidation } = require('./memory-consolidation');
|
|
1427
1485
|
const { createSessionFinalization } = require('./session-finalization');
|
|
1428
1486
|
const { createSessionCheckpoints } = require('./session-checkpoints');
|
|
1487
|
+
const { createOperatorObservability } = require('./operator-observability');
|
|
1488
|
+
const { createDoctor } = require('./doctor');
|
|
1489
|
+
const { createMemoryExplain } = require('./memory-explain');
|
|
1490
|
+
const { createMemoryReview } = require('./memory-review');
|
|
1429
1491
|
const qSchema = qi(schema);
|
|
1430
1492
|
aquifer.narratives = createNarratives({ pool, schema: qSchema, defaultTenantId: tenantId });
|
|
1431
1493
|
aquifer.timeline = createTimeline({ pool, schema: qSchema, defaultTenantId: tenantId });
|
|
@@ -1476,6 +1538,33 @@ function createAquifer(config = {}) {
|
|
|
1476
1538
|
schema,
|
|
1477
1539
|
defaultTenantId: tenantId,
|
|
1478
1540
|
});
|
|
1541
|
+
const operatorObservability = createOperatorObservability({
|
|
1542
|
+
pool,
|
|
1543
|
+
schema: qSchema,
|
|
1544
|
+
defaultTenantId: tenantId,
|
|
1545
|
+
});
|
|
1546
|
+
const doctor = createDoctor({
|
|
1547
|
+
pool,
|
|
1548
|
+
schema,
|
|
1549
|
+
recordsSchema: qSchema,
|
|
1550
|
+
defaultTenantId: tenantId,
|
|
1551
|
+
dbConfigured: Boolean(dbInput),
|
|
1552
|
+
backendKind,
|
|
1553
|
+
backendProfile: backendInfo.profile,
|
|
1554
|
+
memoryServing,
|
|
1555
|
+
listPendingMigrations: () => migrationRuntime.listPendingMigrations(),
|
|
1556
|
+
operatorObservability,
|
|
1557
|
+
});
|
|
1558
|
+
const memoryExplain = createMemoryExplain({
|
|
1559
|
+
pool,
|
|
1560
|
+
schema: qSchema,
|
|
1561
|
+
defaultTenantId: tenantId,
|
|
1562
|
+
});
|
|
1563
|
+
const memoryReview = createMemoryReview({
|
|
1564
|
+
pool,
|
|
1565
|
+
schema: qSchema,
|
|
1566
|
+
defaultTenantId: tenantId,
|
|
1567
|
+
});
|
|
1479
1568
|
|
|
1480
1569
|
function currentMemoryScopeKeys(opts = {}) {
|
|
1481
1570
|
if (Array.isArray(opts.activeScopePath) && opts.activeScopePath.length > 0) {
|
|
@@ -1485,6 +1574,12 @@ function createAquifer(config = {}) {
|
|
|
1485
1574
|
return null;
|
|
1486
1575
|
}
|
|
1487
1576
|
|
|
1577
|
+
function assertMemoryRecallQuery(query) {
|
|
1578
|
+
if (typeof query !== 'string' || query.trim().length === 0) {
|
|
1579
|
+
throw new Error('memory.recall(query): query must be a non-empty string');
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1488
1583
|
// v1 curated-memory sidecar. Top-level recall/bootstrap can opt into this
|
|
1489
1584
|
// plane through memory.servingMode while legacy/evidence mode remains
|
|
1490
1585
|
// available for compatibility and debugging.
|
|
@@ -1520,21 +1615,25 @@ function createAquifer(config = {}) {
|
|
|
1520
1615
|
return memoryPromotion.promote(candidates, opts);
|
|
1521
1616
|
},
|
|
1522
1617
|
bootstrap: async (opts = {}) => {
|
|
1618
|
+
memoryServing.assertCuratedBootstrapOpts(opts);
|
|
1619
|
+
const scopedOpts = memoryServing.withDefaultScope(opts);
|
|
1523
1620
|
await ensureMigrated();
|
|
1524
|
-
return memoryBootstrap.bootstrap(
|
|
1621
|
+
return memoryBootstrap.bootstrap(scopedOpts);
|
|
1525
1622
|
},
|
|
1526
1623
|
current: async (opts = {}) => {
|
|
1624
|
+
const scopedOpts = memoryServing.withDefaultScope(opts);
|
|
1527
1625
|
await ensureMigrated();
|
|
1528
|
-
return memoryRecords.currentProjection(
|
|
1626
|
+
return memoryRecords.currentProjection(scopedOpts);
|
|
1529
1627
|
},
|
|
1530
1628
|
listCurrentMemory: async (opts = {}) => {
|
|
1629
|
+
const scopedOpts = memoryServing.withDefaultScope(opts);
|
|
1531
1630
|
await ensureMigrated();
|
|
1532
|
-
return memoryRecords.currentProjection(
|
|
1631
|
+
return memoryRecords.currentProjection(scopedOpts);
|
|
1533
1632
|
},
|
|
1534
1633
|
backfillEmbeddings: async (opts = {}) => {
|
|
1535
|
-
await ensureMigrated();
|
|
1536
1634
|
requireEmbed('memory.backfillEmbeddings');
|
|
1537
1635
|
const scopedOpts = memoryServing.withDefaultScope(opts);
|
|
1636
|
+
await ensureMigrated();
|
|
1538
1637
|
const listInput = {
|
|
1539
1638
|
tenantId: scopedOpts.tenantId || tenantId,
|
|
1540
1639
|
asOf: scopedOpts.asOf,
|
|
@@ -1611,20 +1710,39 @@ function createAquifer(config = {}) {
|
|
|
1611
1710
|
};
|
|
1612
1711
|
},
|
|
1613
1712
|
recall: async (query, opts = {}) => {
|
|
1713
|
+
assertMemoryRecallQuery(query);
|
|
1714
|
+
memoryServing.assertCuratedRecallOpts(opts);
|
|
1715
|
+
const scopedOpts = memoryServing.withDefaultScope(opts);
|
|
1614
1716
|
await ensureMigrated();
|
|
1615
|
-
return memoryRecall.recall(query,
|
|
1717
|
+
return memoryRecall.recall(query, scopedOpts);
|
|
1616
1718
|
},
|
|
1617
1719
|
recallViaEvidenceItems: async (query, opts = {}) => {
|
|
1720
|
+
assertMemoryRecallQuery(query);
|
|
1721
|
+
memoryServing.assertCuratedRecallOpts(opts);
|
|
1722
|
+
const scopedOpts = memoryServing.withDefaultScope(opts);
|
|
1618
1723
|
await ensureMigrated();
|
|
1619
|
-
return memoryRecall.recallViaEvidenceItems(query,
|
|
1724
|
+
return memoryRecall.recallViaEvidenceItems(query, scopedOpts);
|
|
1620
1725
|
},
|
|
1621
1726
|
recallViaMemoryEmbeddings: async (queryVec, opts = {}) => {
|
|
1727
|
+
memoryServing.assertCuratedRecallOpts(opts);
|
|
1728
|
+
const scopedOpts = memoryServing.withDefaultScope(opts);
|
|
1622
1729
|
await ensureMigrated();
|
|
1623
|
-
return memoryRecall.recallViaMemoryEmbeddings(queryVec,
|
|
1730
|
+
return memoryRecall.recallViaMemoryEmbeddings(queryVec, scopedOpts);
|
|
1624
1731
|
},
|
|
1625
1732
|
recallViaLinkedSummaryEmbeddings: async (queryVec, opts = {}) => {
|
|
1733
|
+
memoryServing.assertCuratedRecallOpts(opts);
|
|
1734
|
+
const scopedOpts = memoryServing.withDefaultScope(opts);
|
|
1626
1735
|
await ensureMigrated();
|
|
1627
|
-
return memoryRecall.recallViaLinkedSummaryEmbeddings(queryVec,
|
|
1736
|
+
return memoryRecall.recallViaLinkedSummaryEmbeddings(queryVec, scopedOpts);
|
|
1737
|
+
},
|
|
1738
|
+
explainBootstrap: async (opts = {}) => {
|
|
1739
|
+
return memoryExplain.explainBootstrap(memoryServing.withDefaultScope(opts));
|
|
1740
|
+
},
|
|
1741
|
+
explainCurrent: async (query, opts = {}) => {
|
|
1742
|
+
return memoryExplain.explainCurrent(query, memoryServing.withDefaultScope(opts));
|
|
1743
|
+
},
|
|
1744
|
+
explainMemory: async (query, opts = {}) => {
|
|
1745
|
+
return memoryExplain.explainMemory(query, memoryServing.withDefaultScope(opts));
|
|
1628
1746
|
},
|
|
1629
1747
|
rankHybridMemoryRows: (lexicalRows, embeddingRows, opts = {}) => {
|
|
1630
1748
|
return memoryRecall.rankHybridMemoryRows(lexicalRows, embeddingRows, opts);
|
|
@@ -1665,9 +1783,11 @@ function createAquifer(config = {}) {
|
|
|
1665
1783
|
return sessionFinalization.get(input);
|
|
1666
1784
|
},
|
|
1667
1785
|
list: async (input = {}) => {
|
|
1668
|
-
await ensureMigrated();
|
|
1669
1786
|
return sessionFinalization.list(input);
|
|
1670
1787
|
},
|
|
1788
|
+
inspect: async (input = {}) => {
|
|
1789
|
+
return sessionFinalization.inspect(input);
|
|
1790
|
+
},
|
|
1671
1791
|
updateStatus: async (input = {}) => {
|
|
1672
1792
|
await ensureMigrated();
|
|
1673
1793
|
return sessionFinalization.updateStatus(input);
|
|
@@ -1722,6 +1842,33 @@ function createAquifer(config = {}) {
|
|
|
1722
1842
|
},
|
|
1723
1843
|
};
|
|
1724
1844
|
|
|
1845
|
+
aquifer.operator = {
|
|
1846
|
+
status: async (input = {}) => operatorObservability.status(input),
|
|
1847
|
+
inspect: async (input = {}) => operatorObservability.inspect(input),
|
|
1848
|
+
};
|
|
1849
|
+
|
|
1850
|
+
aquifer.doctor = {
|
|
1851
|
+
run: async (input = {}) => doctor.run(input),
|
|
1852
|
+
};
|
|
1853
|
+
|
|
1854
|
+
aquifer.review = {
|
|
1855
|
+
queue: async (input = {}) => {
|
|
1856
|
+
const scopedInput = memoryServing.withDefaultScope(input);
|
|
1857
|
+
await ensureMigrated();
|
|
1858
|
+
return memoryReview.queue(scopedInput);
|
|
1859
|
+
},
|
|
1860
|
+
inspect: async (input = {}) => {
|
|
1861
|
+
const scopedInput = memoryServing.withDefaultScope(input);
|
|
1862
|
+
await ensureMigrated();
|
|
1863
|
+
return memoryReview.inspect(scopedInput);
|
|
1864
|
+
},
|
|
1865
|
+
resolve: async (input = {}) => {
|
|
1866
|
+
const scopedInput = memoryServing.withDefaultScope(input);
|
|
1867
|
+
await ensureMigrated();
|
|
1868
|
+
return memoryReview.resolve(scopedInput);
|
|
1869
|
+
},
|
|
1870
|
+
};
|
|
1871
|
+
|
|
1725
1872
|
aquifer.finalizeSession = aquifer.finalization.finalizeSession;
|
|
1726
1873
|
|
|
1727
1874
|
return aquifer;
|
package/core/backends/local.js
CHANGED
|
@@ -299,6 +299,115 @@ function createLocalAquifer(config = {}) {
|
|
|
299
299
|
async memoryBootstrap() {
|
|
300
300
|
unsupported('memoryBootstrap', 'curatedBootstrap');
|
|
301
301
|
},
|
|
302
|
+
doctor: {
|
|
303
|
+
async run() {
|
|
304
|
+
return {
|
|
305
|
+
ok: false,
|
|
306
|
+
status: 'warn',
|
|
307
|
+
checks: [
|
|
308
|
+
{
|
|
309
|
+
id: 'backend',
|
|
310
|
+
status: 'warn',
|
|
311
|
+
summary: 'Local starter backend is running with degraded governance coverage.',
|
|
312
|
+
details: {
|
|
313
|
+
backendKind: 'local',
|
|
314
|
+
backendProfile: capabilities.profile,
|
|
315
|
+
backendPath,
|
|
316
|
+
capabilities: capabilities.capabilities,
|
|
317
|
+
},
|
|
318
|
+
nextAction: capabilities.upgradeHint,
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
id: 'db',
|
|
322
|
+
status: 'warn',
|
|
323
|
+
summary: 'PostgreSQL governance ledgers are unavailable on the local starter backend.',
|
|
324
|
+
details: {
|
|
325
|
+
configured: false,
|
|
326
|
+
tenantId,
|
|
327
|
+
},
|
|
328
|
+
nextAction: 'Use the PostgreSQL backend for migrations, finalization ledgers, and operator workflows.',
|
|
329
|
+
},
|
|
330
|
+
],
|
|
331
|
+
};
|
|
332
|
+
},
|
|
333
|
+
},
|
|
334
|
+
finalization: {
|
|
335
|
+
async list() {
|
|
336
|
+
unsupported('finalization list', 'finalizationLedger');
|
|
337
|
+
},
|
|
338
|
+
async inspect() {
|
|
339
|
+
unsupported('finalization inspect', 'finalizationLedger');
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
operator: {
|
|
343
|
+
async status() {
|
|
344
|
+
return {
|
|
345
|
+
readOnly: true,
|
|
346
|
+
compaction: {
|
|
347
|
+
available: false,
|
|
348
|
+
latest: [],
|
|
349
|
+
staleClaims: [],
|
|
350
|
+
statusCounts: {},
|
|
351
|
+
error: 'operator compaction ledger is unavailable on the local starter backend',
|
|
352
|
+
},
|
|
353
|
+
checkpoint: {
|
|
354
|
+
available: false,
|
|
355
|
+
latest: [],
|
|
356
|
+
statusCounts: {},
|
|
357
|
+
error: 'operator checkpoint ledger is unavailable on the local starter backend',
|
|
358
|
+
},
|
|
359
|
+
};
|
|
360
|
+
},
|
|
361
|
+
async inspect() {
|
|
362
|
+
unsupported('operator inspect', 'operatorCompaction');
|
|
363
|
+
},
|
|
364
|
+
},
|
|
365
|
+
memory: {
|
|
366
|
+
async explainBootstrap() {
|
|
367
|
+
unsupported('explain bootstrap', 'curatedBootstrap');
|
|
368
|
+
},
|
|
369
|
+
async explainCurrent() {
|
|
370
|
+
unsupported('explain memory', 'curatedRecall');
|
|
371
|
+
},
|
|
372
|
+
async explainMemory() {
|
|
373
|
+
unsupported('explain memory', 'curatedRecall');
|
|
374
|
+
},
|
|
375
|
+
},
|
|
376
|
+
review: {
|
|
377
|
+
async queue() {
|
|
378
|
+
return {
|
|
379
|
+
readOnly: true,
|
|
380
|
+
derived: true,
|
|
381
|
+
available: false,
|
|
382
|
+
items: [],
|
|
383
|
+
reviewQueue: [],
|
|
384
|
+
scope: {
|
|
385
|
+
activeScopeKey: null,
|
|
386
|
+
activeScopePath: [],
|
|
387
|
+
},
|
|
388
|
+
filters: {},
|
|
389
|
+
summary: {
|
|
390
|
+
scanned: 0,
|
|
391
|
+
queued: 0,
|
|
392
|
+
truncated: false,
|
|
393
|
+
severityCounts: {},
|
|
394
|
+
feedbackTypeCounts: {},
|
|
395
|
+
},
|
|
396
|
+
totals: {
|
|
397
|
+
items: 0,
|
|
398
|
+
issueFeedback: 0,
|
|
399
|
+
allFeedback: 0,
|
|
400
|
+
},
|
|
401
|
+
error: 'Memory review queue is unavailable on the local starter backend',
|
|
402
|
+
};
|
|
403
|
+
},
|
|
404
|
+
async inspect() {
|
|
405
|
+
unsupported('review inspect', 'curatedRecall');
|
|
406
|
+
},
|
|
407
|
+
async resolve() {
|
|
408
|
+
unsupported('review resolve', 'curatedRecall');
|
|
409
|
+
},
|
|
410
|
+
},
|
|
302
411
|
async historicalBootstrap(opts = {}) {
|
|
303
412
|
return this.bootstrap(opts);
|
|
304
413
|
},
|