@tangle-network/agent-knowledge 6.2.0 → 7.0.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/CHANGELOG.md +13 -0
- package/README.md +1 -1
- package/dist/benchmarks/index.d.ts +1 -1
- package/dist/benchmarks/index.js +1 -1
- package/dist/{benchmarks-CmW6iORW.js → benchmarks-C8L7HJb4.js} +2 -2
- package/dist/{benchmarks-CmW6iORW.js.map → benchmarks-C8L7HJb4.js.map} +1 -1
- package/dist/cli.js +1 -1
- package/dist/{ids-DRqPZ42_.js → ids-Bevz_pXV.js} +6 -2
- package/dist/ids-Bevz_pXV.js.map +1 -0
- package/dist/{index-3z3lFJnE.d.ts → index-D0wc4GYg.d.ts} +2 -2
- package/dist/{index-3z3lFJnE.d.ts.map → index-D0wc4GYg.d.ts.map} +1 -1
- package/dist/{index-DHebFLgU.d.ts → index-Dwp3Mx-w.d.ts} +3 -3
- package/dist/{index-DHebFLgU.d.ts.map → index-Dwp3Mx-w.d.ts.map} +1 -1
- package/dist/index.d.ts +42 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +86 -35
- package/dist/index.js.map +1 -1
- package/dist/{inspect-LUMkas6A.js → inspect-CJQGYuKa.js} +156 -33
- package/dist/inspect-CJQGYuKa.js.map +1 -0
- package/dist/memory/index.d.ts +2 -2
- package/dist/memory/index.js +2 -2
- package/dist/{memory-C6KPRhoU.js → memory-CIYRB_Q8.js} +3 -3
- package/dist/{memory-C6KPRhoU.js.map → memory-CIYRB_Q8.js.map} +1 -1
- package/dist/sources/index.js +1 -1
- package/dist/{types-Cd57BPRt.d.ts → types-BOfmvDe-.d.ts} +21 -6
- package/dist/{types-Cd57BPRt.d.ts.map → types-BOfmvDe-.d.ts.map} +1 -1
- package/dist/viz/index.d.ts +1 -1
- package/docs/architecture.md +4 -2
- package/package.json +1 -1
- package/dist/ids-DRqPZ42_.js.map +0 -1
- package/dist/inspect-LUMkas6A.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as slugify, r as stableId, t as sha256 } from "./ids-
|
|
1
|
+
import { i as textSourceId, n as slugify, r as stableId, t as sha256 } from "./ids-Bevz_pXV.js";
|
|
2
2
|
import { n as searchKnowledge } from "./search-CP0QtBJZ.js";
|
|
3
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
4
4
|
import { lstat, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm } from "node:fs/promises";
|
|
@@ -1241,10 +1241,20 @@ function claimId(text) {
|
|
|
1241
1241
|
function claimEvidenceId(claim) {
|
|
1242
1242
|
return `e_${sha256(JSON.stringify([
|
|
1243
1243
|
claim.claimId,
|
|
1244
|
+
claim.sourceId,
|
|
1244
1245
|
claim.sourceUri,
|
|
1246
|
+
claim.sourceContentHash,
|
|
1245
1247
|
claim.contradictsClaimId ?? null
|
|
1246
1248
|
])).slice(0, 16)}`;
|
|
1247
1249
|
}
|
|
1250
|
+
/** Canonical key for one exact registry-id + original-URI + hash source version. */
|
|
1251
|
+
function researchSourceVersionKey(source) {
|
|
1252
|
+
return JSON.stringify([
|
|
1253
|
+
source.sourceId,
|
|
1254
|
+
source.uri,
|
|
1255
|
+
source.contentHash
|
|
1256
|
+
]);
|
|
1257
|
+
}
|
|
1248
1258
|
/** Case-, whitespace-, and stylistic-punctuation-insensitive claim identity form. */
|
|
1249
1259
|
function normalizeClaimText(text) {
|
|
1250
1260
|
return text.normalize("NFKC").toLowerCase().replace(/<=|≤/gu, " symbol_less_than_or_equal ").replace(/>=|≥/gu, " symbol_greater_than_or_equal ").replace(/!=|≠/gu, " symbol_not_equal ").replace(/==|=/gu, " symbol_equal ").replace(/±/gu, " symbol_plus_or_minus ").replace(/[≈~]/gu, " symbol_approximately ").replace(/<|←|⇐/gu, " symbol_less_or_left ").replace(/>|→|⇒/gu, " symbol_greater_or_right ").replace(/[+]/gu, " symbol_plus_or_positive ").replace(/[-−]/gu, " symbol_minus_or_negative ").replace(/[^\p{L}\p{N}\s]+/gu, " ").replace(/\s+/g, " ").trim();
|
|
@@ -1279,6 +1289,7 @@ function deepQuestionId(kind, text) {
|
|
|
1279
1289
|
function assertTrackedClaimIntegrity(claim) {
|
|
1280
1290
|
if (claim.id !== claimId(claim.text)) throw new Error(`claim '${claim.id}' does not match its text-derived identity`);
|
|
1281
1291
|
if (claim.text !== claim.text.trim()) throw new Error(`claim '${claim.id}' text must not have surrounding whitespace`);
|
|
1292
|
+
if (claim.supportingUris.length === 0) throw new Error(`claim '${claim.id}' must have registered supporting evidence`);
|
|
1282
1293
|
assertSortedUnique(`claim '${claim.id}' supportingUris`, claim.supportingUris);
|
|
1283
1294
|
assertSortedUnique(`claim '${claim.id}' supportingHosts`, claim.supportingHosts);
|
|
1284
1295
|
assertSortedUnique(`claim '${claim.id}' contradicts`, claim.contradicts);
|
|
@@ -1286,6 +1297,7 @@ function assertTrackedClaimIntegrity(claim) {
|
|
|
1286
1297
|
if (!sameStrings(claim.supportingHosts, expectedHosts)) throw new Error(`claim '${claim.id}' supportingHosts must equal the hosts derived from supportingUris`);
|
|
1287
1298
|
if (claim.contradicts.includes(claim.id)) throw new Error(`claim '${claim.id}' cannot contradict itself`);
|
|
1288
1299
|
if (claim.contradicts.length > 0 && !claim.contested) throw new Error(`claim '${claim.id}' with a contradiction must be contested`);
|
|
1300
|
+
if (claim.contested && claim.contradicts.length === 0) throw new Error(`claim '${claim.id}' cannot be contested without a contradiction`);
|
|
1289
1301
|
}
|
|
1290
1302
|
/** Refuse a deep question whose stable identity or set fields are malformed. */
|
|
1291
1303
|
function assertDeepQuestionIntegrity(question) {
|
|
@@ -1298,25 +1310,50 @@ function assertResearchClaimEvidenceIntegrity(evidence) {
|
|
|
1298
1310
|
if (evidence.claimId !== claimId(evidence.text)) throw new Error(`claim evidence '${evidence.id}' does not match its text-derived claim identity`);
|
|
1299
1311
|
if (evidence.id !== claimEvidenceId(evidence)) throw new Error(`claim evidence '${evidence.id}' does not match its content-derived identity`);
|
|
1300
1312
|
if (evidence.text !== evidence.text.trim()) throw new Error(`claim evidence '${evidence.id}' text must not have surrounding whitespace`);
|
|
1313
|
+
if (!/^[a-f0-9]{64}$/.test(evidence.sourceContentHash)) throw new Error(`claim evidence '${evidence.id}' sourceContentHash must be a SHA-256 digest`);
|
|
1314
|
+
const expectedSourceId = textSourceId(evidence.sourceUri, evidence.sourceContentHash);
|
|
1315
|
+
if (evidence.sourceId !== expectedSourceId) throw new Error(`claim evidence '${evidence.id}' sourceId does not match URI-and-content identity`);
|
|
1301
1316
|
if (evidence.contradictsClaimId === evidence.claimId) throw new Error(`claim evidence '${evidence.id}' cannot contradict its own claim`);
|
|
1302
1317
|
}
|
|
1303
1318
|
/** Refuse a ledger that is not one canonical, internally consistent record. */
|
|
1304
1319
|
function assertResearchClaimLedgerIntegrity(ledger) {
|
|
1320
|
+
if (ledger.schemaVersion !== 2) throw new Error(`claim ledger '${ledger.id}' must use schema version 2`);
|
|
1305
1321
|
if (ledger.preparedRounds !== void 0 && ledger.preparedRounds <= ledger.rounds) throw new Error(`claim ledger '${ledger.id}' preparedRounds must be greater than completed rounds`);
|
|
1306
1322
|
assertSortedUnique(`claim ledger '${ledger.id}' claimEvidence`, ledger.claimEvidence.map((evidence) => evidence.id));
|
|
1307
|
-
|
|
1323
|
+
for (const source of ledger.registeredSources) {
|
|
1324
|
+
if (source.sourceId.length === 0 || source.uri.length === 0 || !/^[a-f0-9]{64}$/.test(source.contentHash)) throw new Error(`claim ledger '${ledger.id}' contains an invalid registered source version`);
|
|
1325
|
+
const expectedSourceId = textSourceId(source.uri, source.contentHash);
|
|
1326
|
+
if (source.sourceId !== expectedSourceId) throw new Error(`registered source '${source.sourceId}' does not match URI-and-content identity '${expectedSourceId}'`);
|
|
1327
|
+
}
|
|
1328
|
+
assertSortedUnique(`claim ledger '${ledger.id}' registeredSources`, ledger.registeredSources.map((source) => source.sourceId));
|
|
1308
1329
|
assertSortedUnique(`claim ledger '${ledger.id}' claims`, ledger.claims.map((claim) => claim.id));
|
|
1309
1330
|
assertSortedUnique(`claim ledger '${ledger.id}' questions`, ledger.questions.map((question) => question.id));
|
|
1310
1331
|
for (const evidence of ledger.claimEvidence) assertResearchClaimEvidenceIntegrity(evidence);
|
|
1311
|
-
const
|
|
1332
|
+
const registeredSources = new Set(ledger.registeredSources.map(researchSourceVersionKey));
|
|
1333
|
+
const registeredEvidence = ledger.claimEvidence.filter((evidence) => registeredSources.has(researchSourceVersionKey({
|
|
1334
|
+
sourceId: evidence.sourceId,
|
|
1335
|
+
uri: evidence.sourceUri,
|
|
1336
|
+
contentHash: evidence.sourceContentHash
|
|
1337
|
+
})));
|
|
1338
|
+
const materializedClaims = new Map(ledger.claims.map((claim) => [claim.id, claim]));
|
|
1312
1339
|
for (const claim of ledger.claims) {
|
|
1313
1340
|
assertTrackedClaimIntegrity(claim);
|
|
1314
|
-
for (const sourceUri of claim.supportingUris) if (!
|
|
1341
|
+
for (const sourceUri of claim.supportingUris) if (!registeredEvidence.some((evidence) => evidence.claimId === claim.id && evidence.sourceUri === sourceUri)) throw new Error(`claim '${claim.id}' counts source '${sourceUri}' without exact registered evidence`);
|
|
1342
|
+
for (const contradictedClaimId of claim.contradicts) {
|
|
1343
|
+
const contradictedClaim = materializedClaims.get(contradictedClaimId);
|
|
1344
|
+
if (!contradictedClaim) throw new Error(`claim '${claim.id}' contradicts unmaterialized claim '${contradictedClaimId}'`);
|
|
1345
|
+
if (!contradictedClaim.contradicts.includes(claim.id)) throw new Error(`claim '${claim.id}' has an asymmetric contradiction with '${contradictedClaimId}'`);
|
|
1346
|
+
if (!registeredEvidence.some((evidence) => evidence.claimId === claim.id && evidence.contradictsClaimId === contradictedClaimId || evidence.claimId === contradictedClaimId && evidence.contradictsClaimId === claim.id)) throw new Error(`claim '${claim.id}' contradicts '${contradictedClaimId}' without exact registered evidence`);
|
|
1347
|
+
}
|
|
1315
1348
|
}
|
|
1316
|
-
const claimsById =
|
|
1349
|
+
const claimsById = materializedClaims;
|
|
1317
1350
|
const claimIds = new Set(claimsById.keys());
|
|
1318
1351
|
for (const evidence of ledger.claimEvidence) {
|
|
1319
|
-
if (!
|
|
1352
|
+
if (!registeredSources.has(researchSourceVersionKey({
|
|
1353
|
+
sourceId: evidence.sourceId,
|
|
1354
|
+
uri: evidence.sourceUri,
|
|
1355
|
+
contentHash: evidence.sourceContentHash
|
|
1356
|
+
}))) continue;
|
|
1320
1357
|
const claim = claimsById.get(evidence.claimId);
|
|
1321
1358
|
if (!claim?.supportingUris.includes(evidence.sourceUri)) throw new Error(`registered claim evidence '${evidence.id}' must be materialized in its claim`);
|
|
1322
1359
|
if (evidence.contradictsClaimId !== void 0 && claimsById.has(evidence.contradictsClaimId) && !claim.contradicts.includes(evidence.contradictsClaimId)) throw new Error(`registered claim evidence '${evidence.id}' must materialize its contradiction`);
|
|
@@ -1329,12 +1366,13 @@ function assertResearchClaimLedgerIntegrity(ledger) {
|
|
|
1329
1366
|
/** A ledger with nothing in it yet. */
|
|
1330
1367
|
function emptyClaimLedger(id, goal) {
|
|
1331
1368
|
return {
|
|
1369
|
+
schemaVersion: 2,
|
|
1332
1370
|
id,
|
|
1333
1371
|
...goal === void 0 ? {} : { goal },
|
|
1334
1372
|
updatedAt: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
1335
1373
|
rounds: 0,
|
|
1336
1374
|
claimEvidence: [],
|
|
1337
|
-
|
|
1375
|
+
registeredSources: [],
|
|
1338
1376
|
claims: [],
|
|
1339
1377
|
questions: []
|
|
1340
1378
|
};
|
|
@@ -1347,10 +1385,10 @@ function emptyClaimLedger(id, goal) {
|
|
|
1347
1385
|
* writer and an evidence-producing writer can arrive in either order.
|
|
1348
1386
|
*/
|
|
1349
1387
|
function materializeRegisteredClaimEvidence(ledger) {
|
|
1350
|
-
const registered = new Set(ledger.
|
|
1388
|
+
const registered = new Set(ledger.registeredSources.map(researchSourceVersionKey));
|
|
1351
1389
|
const claims = new Map(ledger.claims.map((claim) => [claim.id, claim]));
|
|
1352
1390
|
for (const evidence of ledger.claimEvidence) {
|
|
1353
|
-
if (!registered.has(evidence
|
|
1391
|
+
if (!registered.has(sourceVersionKeyOfEvidence(evidence))) continue;
|
|
1354
1392
|
const host = claimSourceHost(evidence.sourceUri);
|
|
1355
1393
|
const observed = {
|
|
1356
1394
|
id: evidence.claimId,
|
|
@@ -1366,7 +1404,7 @@ function materializeRegisteredClaimEvidence(ledger) {
|
|
|
1366
1404
|
}
|
|
1367
1405
|
for (const evidence of ledger.claimEvidence) {
|
|
1368
1406
|
const otherId = evidence.contradictsClaimId;
|
|
1369
|
-
if (!registered.has(evidence
|
|
1407
|
+
if (!registered.has(sourceVersionKeyOfEvidence(evidence)) || !otherId || !claims.has(otherId)) continue;
|
|
1370
1408
|
const claim = claims.get(evidence.claimId);
|
|
1371
1409
|
if (!claim) continue;
|
|
1372
1410
|
claims.set(claim.id, {
|
|
@@ -1380,6 +1418,13 @@ function materializeRegisteredClaimEvidence(ledger) {
|
|
|
1380
1418
|
claims: [...claims.values()].sort((left, right) => left.id.localeCompare(right.id))
|
|
1381
1419
|
});
|
|
1382
1420
|
}
|
|
1421
|
+
function sourceVersionKeyOfEvidence(evidence) {
|
|
1422
|
+
return researchSourceVersionKey({
|
|
1423
|
+
sourceId: evidence.sourceId,
|
|
1424
|
+
uri: evidence.sourceUri,
|
|
1425
|
+
contentHash: evidence.sourceContentHash
|
|
1426
|
+
});
|
|
1427
|
+
}
|
|
1383
1428
|
/**
|
|
1384
1429
|
* Raised when two ledgers that accumulated evidence for DIFFERENT goals are
|
|
1385
1430
|
* combined. Merging them would pool two questions' evidence into one
|
|
@@ -1461,13 +1506,14 @@ function mergeClaimLedgers(base, incoming) {
|
|
|
1461
1506
|
const rounds = Math.max(base.rounds, incoming.rounds);
|
|
1462
1507
|
const preparedRounds = Math.max(base.preparedRounds ?? base.rounds, incoming.preparedRounds ?? incoming.rounds);
|
|
1463
1508
|
return materializeRegisteredClaimEvidence({
|
|
1509
|
+
schemaVersion: 2,
|
|
1464
1510
|
id: base.id,
|
|
1465
1511
|
...goal === void 0 ? {} : { goal },
|
|
1466
1512
|
updatedAt: incoming.updatedAt.localeCompare(base.updatedAt) > 0 ? incoming.updatedAt : base.updatedAt,
|
|
1467
1513
|
rounds,
|
|
1468
1514
|
...preparedRounds > rounds ? { preparedRounds } : {},
|
|
1469
1515
|
claimEvidence: [...claimEvidence.values()].sort((left, right) => left.id.localeCompare(right.id)),
|
|
1470
|
-
|
|
1516
|
+
registeredSources: mergeSourceVersions(base.registeredSources, incoming.registeredSources),
|
|
1471
1517
|
claims: [...claims.values()].sort((a, b) => a.id.localeCompare(b.id)),
|
|
1472
1518
|
questions: [...questions.values()].sort((a, b) => a.id.localeCompare(b.id))
|
|
1473
1519
|
});
|
|
@@ -1475,7 +1521,7 @@ function mergeClaimLedgers(base, incoming) {
|
|
|
1475
1521
|
function mergeClaimEvidence(base, incoming) {
|
|
1476
1522
|
assertResearchClaimEvidenceIntegrity(base);
|
|
1477
1523
|
assertResearchClaimEvidenceIntegrity(incoming);
|
|
1478
|
-
if (base.id !== incoming.id || base.claimId !== incoming.claimId || base.sourceUri !== incoming.sourceUri || base.contradictsClaimId !== incoming.contradictsClaimId) throw new Error(`claim evidence '${base.id}' has conflicting immutable content`);
|
|
1524
|
+
if (base.id !== incoming.id || base.claimId !== incoming.claimId || base.sourceId !== incoming.sourceId || base.sourceUri !== incoming.sourceUri || base.sourceContentHash !== incoming.sourceContentHash || base.contradictsClaimId !== incoming.contradictsClaimId) throw new Error(`claim evidence '${base.id}' has conflicting immutable content`);
|
|
1479
1525
|
const text = incoming.firstSeenRound < base.firstSeenRound ? incoming.text : incoming.firstSeenRound > base.firstSeenRound ? base.text : incoming.text < base.text ? incoming.text : base.text;
|
|
1480
1526
|
return {
|
|
1481
1527
|
...base,
|
|
@@ -1483,6 +1529,15 @@ function mergeClaimEvidence(base, incoming) {
|
|
|
1483
1529
|
firstSeenRound: Math.min(base.firstSeenRound, incoming.firstSeenRound)
|
|
1484
1530
|
};
|
|
1485
1531
|
}
|
|
1532
|
+
function mergeSourceVersions(base, incoming) {
|
|
1533
|
+
const versions = /* @__PURE__ */ new Map();
|
|
1534
|
+
for (const source of [...base, ...incoming]) {
|
|
1535
|
+
const existing = versions.get(source.sourceId);
|
|
1536
|
+
if (existing && researchSourceVersionKey(existing) !== researchSourceVersionKey(source)) throw new Error(`registered source '${source.sourceId}' has conflicting immutable content`);
|
|
1537
|
+
versions.set(source.sourceId, source);
|
|
1538
|
+
}
|
|
1539
|
+
return [...versions.values()].sort((left, right) => left.sourceId.localeCompare(right.sourceId));
|
|
1540
|
+
}
|
|
1486
1541
|
/**
|
|
1487
1542
|
* Make every contradiction edge symmetric and mark both ends contested.
|
|
1488
1543
|
*
|
|
@@ -1494,16 +1549,16 @@ function mergeClaimEvidence(base, incoming) {
|
|
|
1494
1549
|
* the same rule stated over a whole ledger, for writers that assemble one from
|
|
1495
1550
|
* events rather than from a live loop.
|
|
1496
1551
|
*
|
|
1497
|
-
*
|
|
1498
|
-
*
|
|
1499
|
-
*
|
|
1500
|
-
*
|
|
1501
|
-
* because the counterpart has not shown up yet is the failure this prevents.
|
|
1552
|
+
* One-sided observations stay in `claimEvidence` until both claims are backed
|
|
1553
|
+
* by registered source versions. The materialized claim projection contains
|
|
1554
|
+
* only closed pairs, so it cannot report a lone weak claim as settled merely
|
|
1555
|
+
* because its evidence named a claim that never arrived.
|
|
1502
1556
|
*/
|
|
1503
1557
|
function linkClaimContradictions(ledger) {
|
|
1558
|
+
const claimIds = new Set(ledger.claims.map((claim) => claim.id));
|
|
1504
1559
|
const inbound = /* @__PURE__ */ new Map();
|
|
1505
1560
|
for (const claim of ledger.claims) for (const other of claim.contradicts) {
|
|
1506
|
-
if (other === claim.id) continue;
|
|
1561
|
+
if (other === claim.id || !claimIds.has(other)) continue;
|
|
1507
1562
|
const edges = inbound.get(other);
|
|
1508
1563
|
if (edges) edges.push(claim.id);
|
|
1509
1564
|
else inbound.set(other, [claim.id]);
|
|
@@ -1511,11 +1566,11 @@ function linkClaimContradictions(ledger) {
|
|
|
1511
1566
|
return {
|
|
1512
1567
|
...ledger,
|
|
1513
1568
|
claims: ledger.claims.map((claim) => {
|
|
1514
|
-
const contradicts = union(claim.contradicts.filter((other) => other !== claim.id), inbound.get(claim.id) ?? []);
|
|
1569
|
+
const contradicts = union(claim.contradicts.filter((other) => other !== claim.id && claimIds.has(other)), inbound.get(claim.id) ?? []);
|
|
1515
1570
|
return {
|
|
1516
1571
|
...claim,
|
|
1517
1572
|
contradicts,
|
|
1518
|
-
contested:
|
|
1573
|
+
contested: contradicts.length > 0
|
|
1519
1574
|
};
|
|
1520
1575
|
}).sort((a, b) => a.id.localeCompare(b.id))
|
|
1521
1576
|
};
|
|
@@ -1655,24 +1710,32 @@ const ResearchClaimRecordSchema = z.object({
|
|
|
1655
1710
|
}).strict().superRefine((claim, context) => {
|
|
1656
1711
|
reportIntegrityError(context, () => assertTrackedClaimIntegrity(claim));
|
|
1657
1712
|
});
|
|
1713
|
+
const ResearchSourceVersionSchema = z.object({
|
|
1714
|
+
sourceId: z.string().min(1),
|
|
1715
|
+
uri: z.string().min(1),
|
|
1716
|
+
contentHash: z.string().regex(/^[a-f0-9]{64}$/)
|
|
1717
|
+
}).strict();
|
|
1658
1718
|
const ResearchClaimEvidenceSchema = z.object({
|
|
1659
1719
|
id: z.string().min(1),
|
|
1660
1720
|
claimId: z.string().min(1),
|
|
1661
1721
|
text: z.string().min(1),
|
|
1722
|
+
sourceId: z.string().min(1),
|
|
1662
1723
|
sourceUri: z.string().min(1),
|
|
1724
|
+
sourceContentHash: z.string().regex(/^[a-f0-9]{64}$/),
|
|
1663
1725
|
contradictsClaimId: z.string().min(1).optional(),
|
|
1664
1726
|
firstSeenRound: z.number().int().nonnegative()
|
|
1665
1727
|
}).strict().superRefine((evidence, context) => {
|
|
1666
1728
|
reportIntegrityError(context, () => assertResearchClaimEvidenceIntegrity(evidence));
|
|
1667
1729
|
});
|
|
1668
1730
|
const ResearchClaimLedgerSchema = z.object({
|
|
1731
|
+
schemaVersion: z.literal(2),
|
|
1669
1732
|
id: z.string().min(1),
|
|
1670
1733
|
goal: z.string().trim().min(1).optional(),
|
|
1671
1734
|
updatedAt: z.iso.datetime(),
|
|
1672
1735
|
rounds: z.number().int().nonnegative(),
|
|
1673
1736
|
preparedRounds: z.number().int().nonnegative().optional(),
|
|
1674
1737
|
claimEvidence: z.array(ResearchClaimEvidenceSchema),
|
|
1675
|
-
|
|
1738
|
+
registeredSources: z.array(ResearchSourceVersionSchema),
|
|
1676
1739
|
claims: z.array(ResearchClaimRecordSchema),
|
|
1677
1740
|
questions: z.array(DeepQuestionSchema)
|
|
1678
1741
|
}).strict().superRefine((ledger, context) => {
|
|
@@ -1756,6 +1819,17 @@ function assertClaimLedgerId(id) {
|
|
|
1756
1819
|
if (!LEDGER_ID_PATTERN.test(id) || id === "." || id === "..") throw new Error(`claim ledger id must match ${LEDGER_ID_PATTERN} and cannot be a path segment: ${id}`);
|
|
1757
1820
|
return id;
|
|
1758
1821
|
}
|
|
1822
|
+
/** A URI-only ledger cannot be upgraded without re-verifying its source bytes. */
|
|
1823
|
+
var ClaimLedgerMigrationRequiredError = class extends Error {
|
|
1824
|
+
ledgerId;
|
|
1825
|
+
foundSchemaVersion;
|
|
1826
|
+
constructor(ledgerId, foundSchemaVersion) {
|
|
1827
|
+
super(`claim ledger '${ledgerId}' uses source identity schema '${foundSchemaVersion}'; archive it and re-verify its sources into a new ledger before use`);
|
|
1828
|
+
this.ledgerId = ledgerId;
|
|
1829
|
+
this.foundSchemaVersion = foundSchemaVersion;
|
|
1830
|
+
this.name = "ClaimLedgerMigrationRequiredError";
|
|
1831
|
+
}
|
|
1832
|
+
};
|
|
1759
1833
|
var MemoryKbStore = class {
|
|
1760
1834
|
sources = /* @__PURE__ */ new Map();
|
|
1761
1835
|
pages = /* @__PURE__ */ new Map();
|
|
@@ -1806,7 +1880,7 @@ var MemoryKbStore = class {
|
|
|
1806
1880
|
return out.slice(-(query.limit ?? out.length)).map(clone);
|
|
1807
1881
|
}
|
|
1808
1882
|
async putClaimLedger(ledger) {
|
|
1809
|
-
const parsed =
|
|
1883
|
+
const parsed = parseResearchClaimLedger(ledger);
|
|
1810
1884
|
this.claimLedgers.set(assertClaimLedgerId(parsed.id), clone(parsed));
|
|
1811
1885
|
}
|
|
1812
1886
|
async getClaimLedger(id) {
|
|
@@ -1902,13 +1976,16 @@ var FileSystemKbStore = class {
|
|
|
1902
1976
|
});
|
|
1903
1977
|
}
|
|
1904
1978
|
async putClaimLedger(ledger) {
|
|
1905
|
-
const parsed =
|
|
1979
|
+
const parsed = parseResearchClaimLedger(ledger);
|
|
1906
1980
|
const path = this.claimLedgerPath(parsed.id);
|
|
1907
|
-
await withKnowledgeMutation(this.root, () =>
|
|
1981
|
+
await withKnowledgeMutation(this.root, async () => {
|
|
1982
|
+
await readJsonFile(this.root, path, researchClaimLedgerParser);
|
|
1983
|
+
await writeJsonDurableWithinRoot(this.root, path, parsed);
|
|
1984
|
+
});
|
|
1908
1985
|
}
|
|
1909
1986
|
async getClaimLedger(id) {
|
|
1910
1987
|
const path = this.claimLedgerPath(id);
|
|
1911
|
-
return withKnowledgeRead(this.root, () => readJsonFile(this.root, path,
|
|
1988
|
+
return withKnowledgeRead(this.root, () => readJsonFile(this.root, path, researchClaimLedgerParser));
|
|
1912
1989
|
}
|
|
1913
1990
|
async listClaimLedgers() {
|
|
1914
1991
|
return withKnowledgeRead(this.root, async () => {
|
|
@@ -1922,7 +1999,7 @@ var FileSystemKbStore = class {
|
|
|
1922
1999
|
const ledgers = [];
|
|
1923
2000
|
for (const file of files) {
|
|
1924
2001
|
if (!file.path.endsWith(".json")) continue;
|
|
1925
|
-
ledgers.push(
|
|
2002
|
+
ledgers.push(parseResearchClaimLedger(JSON.parse(file.bytes.toString("utf8"))));
|
|
1926
2003
|
}
|
|
1927
2004
|
return ledgers.sort((a, b) => a.id.localeCompare(b.id));
|
|
1928
2005
|
});
|
|
@@ -1930,7 +2007,7 @@ var FileSystemKbStore = class {
|
|
|
1930
2007
|
async mergeClaimLedger(id, merge) {
|
|
1931
2008
|
const key = assertClaimLedgerId(id);
|
|
1932
2009
|
return withKnowledgeMutation(this.root, async () => {
|
|
1933
|
-
const current = await readJsonFile(this.root, this.claimLedgerPath(key),
|
|
2010
|
+
const current = await readJsonFile(this.root, this.claimLedgerPath(key), researchClaimLedgerParser);
|
|
1934
2011
|
const next = assertMergedLedgerId(key, merge(current));
|
|
1935
2012
|
await this.putClaimLedger(next);
|
|
1936
2013
|
return next;
|
|
@@ -1983,6 +2060,42 @@ async function readJsonFile(root, relativePath, schema) {
|
|
|
1983
2060
|
throw error;
|
|
1984
2061
|
}
|
|
1985
2062
|
}
|
|
2063
|
+
const researchClaimLedgerParser = { parse: parseResearchClaimLedger };
|
|
2064
|
+
const legacyResearchClaimLedgerSchema = z.object({
|
|
2065
|
+
id: z.string().min(1),
|
|
2066
|
+
goal: z.string().trim().min(1).optional(),
|
|
2067
|
+
updatedAt: z.iso.datetime(),
|
|
2068
|
+
rounds: z.number().int().nonnegative(),
|
|
2069
|
+
preparedRounds: z.number().int().nonnegative().optional(),
|
|
2070
|
+
claimEvidence: z.array(z.object({
|
|
2071
|
+
id: z.string().min(1),
|
|
2072
|
+
claimId: z.string().min(1),
|
|
2073
|
+
text: z.string().min(1),
|
|
2074
|
+
sourceUri: z.string().min(1),
|
|
2075
|
+
contradictsClaimId: z.string().min(1).optional(),
|
|
2076
|
+
firstSeenRound: z.number().int().nonnegative()
|
|
2077
|
+
}).strict()),
|
|
2078
|
+
registeredSourceUris: z.array(z.string().min(1)),
|
|
2079
|
+
claims: z.array(z.object({
|
|
2080
|
+
id: z.string().min(1),
|
|
2081
|
+
text: z.string().min(1),
|
|
2082
|
+
supportingHosts: z.array(z.string().min(1)),
|
|
2083
|
+
supportingUris: z.array(z.string().min(1)),
|
|
2084
|
+
contradicts: z.array(z.string().min(1)),
|
|
2085
|
+
contested: z.boolean(),
|
|
2086
|
+
firstSeenRound: z.number().int().nonnegative()
|
|
2087
|
+
}).strict()),
|
|
2088
|
+
questions: z.array(DeepQuestionSchema)
|
|
2089
|
+
}).strict();
|
|
2090
|
+
function parseResearchClaimLedger(value) {
|
|
2091
|
+
const legacy = legacyResearchClaimLedgerSchema.safeParse(value);
|
|
2092
|
+
if (legacy.success) throw new ClaimLedgerMigrationRequiredError(legacy.data.id, "unversioned");
|
|
2093
|
+
if (isRecord(value) && value.schemaVersion !== 2 && "registeredSourceUris" in value) throw new ClaimLedgerMigrationRequiredError(typeof value.id === "string" ? value.id : "unknown", typeof value.schemaVersion === "number" ? value.schemaVersion : "unversioned");
|
|
2094
|
+
return ResearchClaimLedgerSchema.parse(value);
|
|
2095
|
+
}
|
|
2096
|
+
function isRecord(value) {
|
|
2097
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2098
|
+
}
|
|
1986
2099
|
function clone(value) {
|
|
1987
2100
|
return value == null ? value : JSON.parse(JSON.stringify(value));
|
|
1988
2101
|
}
|
|
@@ -1992,6 +2105,10 @@ const sourceRegistrySchema = z.object({
|
|
|
1992
2105
|
generatedAt: z.string().min(1),
|
|
1993
2106
|
sources: z.array(SourceRecordSchema.passthrough())
|
|
1994
2107
|
}).strict();
|
|
2108
|
+
/** Copy and freeze an untrusted source proposal before any asynchronous work. */
|
|
2109
|
+
function snapshotSourceTextInput(input) {
|
|
2110
|
+
return deepFreeze(structuredClone(input));
|
|
2111
|
+
}
|
|
1995
2112
|
async function loadSourceRegistry(root) {
|
|
1996
2113
|
return withKnowledgeRead(root, () => loadSourceRegistryUnlocked(root));
|
|
1997
2114
|
}
|
|
@@ -2070,7 +2187,7 @@ async function preparePathSource(root, sourcePath, mode, options) {
|
|
|
2070
2187
|
};
|
|
2071
2188
|
}
|
|
2072
2189
|
async function addSourceText(root, input, options = {}) {
|
|
2073
|
-
const [record] = await commitSourceBatch(root, [await prepareTextSource(input, options)], options);
|
|
2190
|
+
const [record] = await commitSourceBatch(root, [await prepareTextSource(snapshotSourceTextInput(input), options)], options);
|
|
2074
2191
|
return record;
|
|
2075
2192
|
}
|
|
2076
2193
|
async function prepareTextSource(input, options) {
|
|
@@ -2084,9 +2201,9 @@ async function prepareTextSource(input, options) {
|
|
|
2084
2201
|
};
|
|
2085
2202
|
const adapter = (options.adapters ?? [textSourceAdapter]).find((candidate) => candidate.canLoad(adapterInput));
|
|
2086
2203
|
const loaded = adapter ? await adapter.load(adapterInput) : {};
|
|
2087
|
-
const id =
|
|
2204
|
+
const id = textSourceId(input.uri, contentHash);
|
|
2088
2205
|
const targetRel = rawSourcePath(fileName, contentHash, ".txt");
|
|
2089
|
-
const rawContent = text
|
|
2206
|
+
const rawContent = text;
|
|
2090
2207
|
return {
|
|
2091
2208
|
record: {
|
|
2092
2209
|
id,
|
|
@@ -2161,6 +2278,12 @@ function sameMutation(left, right) {
|
|
|
2161
2278
|
if (Buffer.isBuffer(left.content) && Buffer.isBuffer(right.content)) return left.content.equals(right.content);
|
|
2162
2279
|
return left.content === right.content;
|
|
2163
2280
|
}
|
|
2281
|
+
function deepFreeze(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
2282
|
+
if (typeof value !== "object" || value === null || seen.has(value)) return value;
|
|
2283
|
+
seen.add(value);
|
|
2284
|
+
for (const nested of Object.values(value)) deepFreeze(nested, seen);
|
|
2285
|
+
return Object.freeze(value);
|
|
2286
|
+
}
|
|
2164
2287
|
async function listSourceFiles(root) {
|
|
2165
2288
|
const entries = await readdir(root, { withFileTypes: true });
|
|
2166
2289
|
const out = [];
|
|
@@ -2177,7 +2300,7 @@ async function listSourceFiles(root) {
|
|
|
2177
2300
|
return out;
|
|
2178
2301
|
}
|
|
2179
2302
|
function rawSourcePath(fileName, contentHash, extension) {
|
|
2180
|
-
return join("raw", "sources", `${slugify(fileName.replace(/\.[^.]+$/, ""))}-${contentHash
|
|
2303
|
+
return join("raw", "sources", `${slugify(fileName.replace(/\.[^.]+$/, ""))}-${contentHash}${extension}`).replace(/\\/g, "/");
|
|
2181
2304
|
}
|
|
2182
2305
|
function ext(fileName) {
|
|
2183
2306
|
const idx = fileName.lastIndexOf(".");
|
|
@@ -2534,6 +2657,6 @@ function explainKnowledgeTarget(index, target) {
|
|
|
2534
2657
|
};
|
|
2535
2658
|
}
|
|
2536
2659
|
//#endregion
|
|
2537
|
-
export {
|
|
2660
|
+
export { mergeTrackedClaims as $, KnowledgeGraphNodeSchema as A, removeDurable as At, ClaimLedgerGoalConflictError as B, textSourceAdapter as Bt, KB_STORE_DIR as C, prepareKnowledgeFileTransaction as Ct, KnowledgeBaseCandidateSchema as D, listRegularFilesWithinRoot as Dt, DeepQuestionSchema as E, isMissingFile as Et, ResearchClaimRecordSchema as F, writeFileDurable as Ft, claimEvidenceId as G, assertResearchClaimEvidenceIntegrity as H, ResearchSourceVersionSchema as I, writeFileDurableWithinRoot as It, deepQuestionId as J, claimId as K, SourceAnchorSchema as L, writeJsonDurable as Lt, KnowledgePageSchema as M, syncDirectory as Mt, ResearchClaimEvidenceSchema as N, withSafeDescendant as Nt, KnowledgeEventSchema as O, readRegularFileNoFollow as Ot, ResearchClaimLedgerSchema as P, withSafeDirectory as Pt, mergeClaimLedgers as Q, SourceRecordSchema as R, writeJsonDurableWithinRoot as Rt, KB_INDEX_PATH as S, knowledgeFileTransactionPlanHash as St, assertClaimLedgerId as T, isKernelAnchoredPath as Tt, assertResearchClaimLedgerIntegrity as U, assertDeepQuestionIntegrity as V, assertTrackedClaimIntegrity as W, linkClaimContradictions as X, emptyClaimLedger as Y, materializeRegisteredClaimEvidence as Z, writeSourceRegistry as _, withKnowledgeMutation as _t, applyKnowledgeWriteBlocksFile as a, isScaffoldPath as at, KB_CLAIM_LEDGER_DIR as b, assertKnowledgeMutationPath as bt, validateKnowledgeIndex as c, writeJson as ct, writeKnowledgeIndex as d, normalizeLinkTarget as dt, normalizeClaimText as et, addSourcePath as f, formatFrontmatter as ft, sourceRegistryPath as g, recoverPendingKnowledgeMutation as gt, snapshotSourceTextInput as h, inspectPendingKnowledgeMutation as ht, applyKnowledgeWriteBlocks as i, initKnowledgeBase as it, KnowledgeIndexSchema as j, renameDurable as jt, KnowledgeGraphEdgeSchema as k, readRegularFileWithinRoot as kt, lintKnowledgeIndex as l, WIKILINK_REGEX as lt, loadSourceRegistry as m, acquireDurableFileLock as mt, inspectKnowledgeIndex as n, buildKnowledgeGraph as nt, isSafeKnowledgePath as o, layoutFor as ot, addSourceText as p, parseFrontmatter as pt, claimSourceHost as q, stringMetadata as r, SCAFFOLD_PAGE_BASENAMES as rt, parseKnowledgeWriteBlocks as s, loadKnowledgePages as st, explainKnowledgeTarget as t, researchSourceVersionKey as tt, buildKnowledgeIndex as u, extractWikilinks as ut, ClaimLedgerMigrationRequiredError as v, withKnowledgeRead as vt, MemoryKbStore as w, rollbackKnowledgeFileTransaction as wt, KB_EVENTS_PATH as x, finishKnowledgeFileTransaction as xt, FileSystemKbStore as y, applyKnowledgeFileTransaction as yt, KNOWLEDGE_EVENT_TYPES as z, mediaTypeFor$1 as zt };
|
|
2538
2661
|
|
|
2539
|
-
//# sourceMappingURL=inspect-
|
|
2662
|
+
//# sourceMappingURL=inspect-CJQGYuKa.js.map
|