@polycode-projects/the-mechanical-code-talker 2.5.2 → 2.5.3
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 +11 -7
- package/bin/tmct.mjs +7 -4
- package/corpus/LICENSES.json +7 -0
- package/corpus/reference/LICENSE-NOTICE +36 -0
- package/corpus/reference/README.md +19 -0
- package/corpus/reference/index.json.gz +0 -0
- package/corpus/reference/manifest.json +367 -0
- package/corpus/reference/shards/ref-00.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-01.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-02.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-03.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-04.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-05.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-06.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-07.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-08.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-09.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-0a.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-0b.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-0c.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-0d.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-0e.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-0f.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-10.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-11.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-12.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-13.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-14.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-15.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-16.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-17.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-18.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-19.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-1a.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-1b.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-1c.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-1d.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-1e.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-1f.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-20.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-21.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-22.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-23.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-24.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-25.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-26.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-27.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-28.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-29.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-2a.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-2b.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-2c.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-2d.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-2e.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-2f.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-30.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-31.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-32.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-33.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-34.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-35.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-36.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-37.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-38.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-39.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-3a.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-3b.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-3c.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-3d.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-3e.jsonl.gz +0 -0
- package/corpus/reference/shards/ref-3f.jsonl.gz +0 -0
- package/package.json +5 -1
- package/src/adapters/corpus/reference-pack.mjs +107 -0
- package/src/adapters/memory/core.mjs +104 -10
- package/src/domain/ask.mjs +66 -9
- package/src/domain/cli-verbs.mjs +3 -3
- package/src/domain/codegraph.mjs +6 -0
- package/src/domain/dialogue-acts.mjs +155 -0
- package/src/domain/interpret/normalize.mjs +14 -2
- package/src/domain/interpret/strategies/keywords.mjs +10 -1
- package/src/domain/memory/trust.mjs +12 -0
- package/src/domain/reference-pack.mjs +72 -0
- package/src/domain/skos-view.mjs +111 -0
- package/src/domain/syllogise.mjs +647 -56
- package/src/services/chat.mjs +497 -121
- package/src/surfaces/web/chat-browser-entry.mjs +87 -0
- package/src/surfaces/web/memory-ask-browser.bundle.js +864 -73
- package/src/tools/definitions.mjs +13 -0
- package/src/tools/handlers/index.mjs +2 -0
- package/src/tools/handlers/tmct-related.mjs +30 -0
|
@@ -975,6 +975,12 @@
|
|
|
975
975
|
function provenanceTagToSource(tag) {
|
|
976
976
|
const t = String(tag || "").trim();
|
|
977
977
|
if (!t) return null;
|
|
978
|
+
if (t.startsWith("reference:")) {
|
|
979
|
+
const rest = t.slice("reference:".length);
|
|
980
|
+
const colon = rest.indexOf(":");
|
|
981
|
+
if (colon < 0) return { kind: "reference", pack: rest || "unknown", article: "" };
|
|
982
|
+
return { kind: "reference", pack: rest.slice(0, colon) || "unknown", article: rest.slice(colon + 1) };
|
|
983
|
+
}
|
|
978
984
|
const head = t.split(/\s+/)[0];
|
|
979
985
|
if (head.startsWith("corpus-weak:")) return { kind: "corpusWeak", name: head.slice("corpus-weak:".length) || "unknown" };
|
|
980
986
|
if (head.startsWith("corpus:")) return { kind: "corpus", name: head.slice("corpus:".length) || "unknown" };
|
|
@@ -1056,6 +1062,7 @@
|
|
|
1056
1062
|
teach: 0.95,
|
|
1057
1063
|
provider: 0.9,
|
|
1058
1064
|
corpus: 0.7,
|
|
1065
|
+
reference: 0.6,
|
|
1059
1066
|
corpusWeak: 0.55,
|
|
1060
1067
|
web: 0.4,
|
|
1061
1068
|
extracted: 0.45,
|
|
@@ -1346,6 +1353,7 @@
|
|
|
1346
1353
|
if (!subjModId || !objModId) continue;
|
|
1347
1354
|
const subjLabel = graph.byId.get(subjModId)?.label || subjModId;
|
|
1348
1355
|
addDependent(objModId, subjModId, subjLabel, g.predicate);
|
|
1356
|
+
if (subjModId !== objModId) addDependent(e.object, subjModId, subjLabel, g.predicate);
|
|
1349
1357
|
}
|
|
1350
1358
|
} else if (kind === "tests") {
|
|
1351
1359
|
for (const e of g.edges) {
|
|
@@ -2875,8 +2883,8 @@ ${shown.join("\n")}${tail}`;
|
|
|
2875
2883
|
EXPLAIN_WRAPPER_RE = /^explain\s+(?:to\s+me\s+|please\s+)*(.+?)\??$/i;
|
|
2876
2884
|
TELL_ME_WRAPPER_RE = /^tell\s+me\s+(.+?)\??$/i;
|
|
2877
2885
|
KNOW_WRAPPER_RE = /^do\s+you\s+know\s+(.+?)\??$/i;
|
|
2878
|
-
WANT_KNOW_WRAPPER_RE = /^i(?:'d|\s+would)?\s+(?:like|want|need)\s+to\s+know\s+(.+?)\??$/i;
|
|
2879
|
-
WONDERING_WRAPPER_RE = /^i(?:\s+was|\s+am|'m)?\s+(?:just\s+)?(?:wonder(?:ing|ed)
|
|
2886
|
+
WANT_KNOW_WRAPPER_RE = /^i(?:'d|\s+would)?\s+(?:(?:like|want|need)\s+to|wanna)\s+know\s+(.+?)\??$/i;
|
|
2887
|
+
WONDERING_WRAPPER_RE = /^i(?:\s+was|\s+am|'m)?\s+(?:just\s+)?(?:wonder(?:ing|ed)?|curious)(?:\s+(?:if|whether|about))?\s+(.+?)\??$/i;
|
|
2880
2888
|
EMBEDDED_WHATIS_RE = /^what\s+((?:an?\s+|the\s+)?[\w'-]+(?:\s+[\w'-]+){0,2})\s+(is|are)\??$/i;
|
|
2881
2889
|
EMBEDDED_MEANS_RE = /^what\s+((?:an?\s+|the\s+)?[\w'-]+(?:\s+[\w'-]+){0,2})\s+means\??$/i;
|
|
2882
2890
|
SHOW_GIVE_ME_RE = /^(?:show|give)\s+me\s+(?:the\s+)?(.+?)\??$/i;
|
|
@@ -2992,6 +3000,17 @@ ${shown.join("\n")}${tail}`;
|
|
|
2992
3000
|
{ re: /^(?:is|are)\s+(?!.*\bnot\b)(.+?)\s+tested\??$/i, to: (m) => `what tests ${m[1]}` },
|
|
2993
3001
|
// NEEDS-TESTS → the untested-module survey.
|
|
2994
3002
|
{ re: /^what\s+needs\s+(?:to\s+be\s+)?(?:a\s+)?(?:tested|tests?|testing|coverage|covering)\??$/i, to: () => "untested modules" },
|
|
3003
|
+
// NO-TESTS → the same untested survey, attributive form. "no tests" would
|
|
3004
|
+
// otherwise read as a literal object term ("…defines no tests") and the
|
|
3005
|
+
// resulting empty answers as "it has none" to a coverage question.
|
|
3006
|
+
{
|
|
3007
|
+
re: /^(?:which|what|list|show(?:\s+me)?|find)?\s*(?:the\s+|all\s+)?([a-z][a-z-]*?)\s+(?:(?:that|which)\s+)?(?:have|has|having|with)\s+no\s+tests?\??$/i,
|
|
3008
|
+
to: (m) => `untested ${m[1].toLowerCase()}`
|
|
3009
|
+
},
|
|
3010
|
+
{
|
|
3011
|
+
re: /^(?:which|what|list|show(?:\s+me)?|find)?\s*(?:the\s+|all\s+)?([a-z][a-z-]*?)\s+without\s+(?:any\s+)?tests?\??$/i,
|
|
3012
|
+
to: (m) => `untested ${m[1].toLowerCase()}`
|
|
3013
|
+
},
|
|
2995
3014
|
// DOES-X-VERB-ANYTHING-ELSE → "what does X <verb>" (drops the placeholder
|
|
2996
3015
|
// "anything/something else" object, which otherwise made the two parse
|
|
2997
3016
|
// strategies disagree on the span). Anchored to VERB_TO_KIND so it can't
|
|
@@ -3410,7 +3429,10 @@ ${shown.join("\n")}${tail}`;
|
|
|
3410
3429
|
if (INHERITS_REVERSE_VERBS.includes(verbPhrase)) [subject, object] = [object, subject];
|
|
3411
3430
|
return stamp({ shape: "ask", entityType: null, modifier: "direct", kind, subject, object });
|
|
3412
3431
|
}
|
|
3413
|
-
if (afterText)
|
|
3432
|
+
if (afterText) {
|
|
3433
|
+
const resultType = entityHit && entityHit.start >= verbHit.end ? null : entityType;
|
|
3434
|
+
return stamp({ shape: "reverse", entityType: resultType, modifier, kind, object: afterText });
|
|
3435
|
+
}
|
|
3414
3436
|
if (kind === "inherits" && !beforeText && entityHit && entityHit.start === verbHit.end) {
|
|
3415
3437
|
const entityText = canonWords.slice(entityHit.start, entityHit.end).join(" ");
|
|
3416
3438
|
if (entityText) return stamp({ shape: "reverse", entityType: null, modifier, kind, object: entityText });
|
|
@@ -3855,7 +3877,9 @@ ${shown.join("\n")}${tail}`;
|
|
|
3855
3877
|
return classes;
|
|
3856
3878
|
}
|
|
3857
3879
|
function kindObjectClass(graph, kind) {
|
|
3858
|
-
const
|
|
3880
|
+
const kinds = kindsFor(kind);
|
|
3881
|
+
const coarse = kinds.filter((k) => !SYMBOL_GRAIN_KINDS.has(k));
|
|
3882
|
+
const classes = classesForKinds(graph, coarse.length ? coarse : kinds);
|
|
3859
3883
|
return classes.size === 1 ? [...classes][0] : null;
|
|
3860
3884
|
}
|
|
3861
3885
|
function parseSetPhrase(text, nlp, depth) {
|
|
@@ -4233,7 +4257,9 @@ ${shown.join("\n")}${tail}`;
|
|
|
4233
4257
|
if (!entityType) return { node: "miss", reason: "a superlative needs an entity kind (module, class, function, \u2026)" };
|
|
4234
4258
|
}
|
|
4235
4259
|
if (!metric) return { node: "miss", reason: "name what to rank by (imports, callers, methods, tests, or connections)" };
|
|
4236
|
-
|
|
4260
|
+
const NEED_LACK_WORDS = ["needs", "need", "needing", "lacks", "lack", "lacking", "misses", "missing"];
|
|
4261
|
+
const extreme = lc.some((x) => NEED_LACK_WORDS.includes(x)) ? ext === "most" ? "fewest" : "most" : ext;
|
|
4262
|
+
return { node: "superlative", entityType, metric, metricNoun, extreme };
|
|
4237
4263
|
}
|
|
4238
4264
|
function parseFind(w, lc, nlp, depth) {
|
|
4239
4265
|
if (lc[0] !== "find") return null;
|
|
@@ -5426,7 +5452,20 @@ ${shown.join("\n")}${tail}`;
|
|
|
5426
5452
|
return out;
|
|
5427
5453
|
}
|
|
5428
5454
|
function declineOnUnplacedWords(result, term) {
|
|
5429
|
-
if (!result?.match || result.
|
|
5455
|
+
if (!result?.match || result.tier !== 3 || result.matchedVia) return result;
|
|
5456
|
+
if (result.ambiguous) {
|
|
5457
|
+
const pool = [result.match, ...result.candidates || []];
|
|
5458
|
+
const shared = pool.map((m) => new Set(unplacedTermWords(term, m.label))).reduce((acc, s) => acc.filter((w) => s.has(w)), unplacedTermWords(term, pool[0].label));
|
|
5459
|
+
if (!shared.length) return result;
|
|
5460
|
+
return {
|
|
5461
|
+
match: null,
|
|
5462
|
+
candidates: [],
|
|
5463
|
+
tier: null,
|
|
5464
|
+
ambiguous: false,
|
|
5465
|
+
unplacedWords: shared,
|
|
5466
|
+
nearestLabel: listJoin(pool.slice(0, 4).map((m) => m.label))
|
|
5467
|
+
};
|
|
5468
|
+
}
|
|
5430
5469
|
const unplaced = unplacedTermWords(term, result.match.label);
|
|
5431
5470
|
if (!unplaced.length) return result;
|
|
5432
5471
|
return {
|
|
@@ -5774,7 +5813,7 @@ ${shown.join("\n")}${tail}`;
|
|
|
5774
5813
|
traversal: `reverse dependency closure over imports+calls edges from ${objMatch.label} (impactClosure, maxDepth=${TRANSITIVE_MAX_DEPTH})`
|
|
5775
5814
|
};
|
|
5776
5815
|
}
|
|
5777
|
-
const symbolKind = SYMBOL_GRAIN_SIBLING[kind];
|
|
5816
|
+
const symbolKind = SYMBOL_GRAIN_SIBLING[kind] || kindsFor(kind).find((k) => SYMBOL_GRAIN_KINDS.has(k)) || null;
|
|
5778
5817
|
const objIsFineSymbol = !!(objMatch.class && FINE_ENTITY_TYPES.has(objMatch.class));
|
|
5779
5818
|
if (symbolKind && (FINE_ENTITY_TYPES.has(entityType) || objIsFineSymbol)) {
|
|
5780
5819
|
const edges2 = edgesOfKind2(graph, symbolKind).filter((e) => e.object === objMatch.id);
|
|
@@ -5789,7 +5828,7 @@ ${shown.join("\n")}${tail}`;
|
|
|
5789
5828
|
widenNote = `, widened to ${siblingClass} subjects (no ${entityType} recorded)`;
|
|
5790
5829
|
}
|
|
5791
5830
|
}
|
|
5792
|
-
const upRefineEligible = (kind === "touches" || kind === "calls") && objMatch.class === "Class" && !edgesOfKind2(graph, "contains").some((e) => e.subject === objMatch.id);
|
|
5831
|
+
const upRefineEligible = (kind === "touches" || kind === "calls" || kind === "uses") && objMatch.class === "Class" && !edgesOfKind2(graph, "contains").some((e) => e.subject === objMatch.id);
|
|
5793
5832
|
const upRefineModule = upRefineEligible ? graph.byId.get(moduleIdOf2(graph, objMatch) || "") : null;
|
|
5794
5833
|
if (matches2.length || !(upRefineEligible && upRefineModule)) {
|
|
5795
5834
|
return { matches: matches2, objMatch, candidates, traversal: `${symbolKind} edges where object = ${objMatch.label}${widenNote}`, ambiguous, matchedVia };
|
|
@@ -6224,6 +6263,14 @@ ${result.branches.map((b, i) => `${i + 1}) ${b.candidate.label}: ${b.rendered.co
|
|
|
6224
6263
|
}
|
|
6225
6264
|
if (!result.matches.length) {
|
|
6226
6265
|
if (parsed.shape === "forward") {
|
|
6266
|
+
if (MEMBERSHIP_KINDS.includes(parsed.kind) && graph && result.objMatch) {
|
|
6267
|
+
for (const alt of MEMBERSHIP_KINDS) {
|
|
6268
|
+
if (alt === parsed.kind) continue;
|
|
6269
|
+
const altParsed = { ...parsed, kind: alt };
|
|
6270
|
+
const altResult = traverse(graph, altParsed, { pinnedObjMatch: result.objMatch });
|
|
6271
|
+
if (altResult?.matches?.length && !altResult.ambiguous) return renderCore(altParsed, altResult, graph);
|
|
6272
|
+
}
|
|
6273
|
+
}
|
|
6227
6274
|
return {
|
|
6228
6275
|
content: `${result.objMatch.label} has no ${verbFor(parsed.kind)} edges in the index.`,
|
|
6229
6276
|
miss: true,
|
|
@@ -6265,7 +6312,7 @@ ${result.branches.map((b, i) => `${i + 1}) ${b.candidate.label}: ${b.rendered.co
|
|
|
6265
6312
|
return { content: clauses.join(" and ") + extra + ".", miss: false, ambiguous: false, matches: result.matches };
|
|
6266
6313
|
}
|
|
6267
6314
|
function fuzzyCascadeWord(w) {
|
|
6268
|
-
if (w.length < 4) return null;
|
|
6315
|
+
if (w.length < 4 || CASCADE_FUZZY_REAL_WORDS.has(w)) return null;
|
|
6269
6316
|
const bound = fuzzyBound(w);
|
|
6270
6317
|
let best = bound + 1;
|
|
6271
6318
|
let hit2 = null;
|
|
@@ -6582,7 +6629,7 @@ ${lines.join("\n")}`;
|
|
|
6582
6629
|
}
|
|
6583
6630
|
};
|
|
6584
6631
|
}
|
|
6585
|
-
var askEdgesOfKindCache, SYMBOL_GRAIN_SIBLING, FINE_ENTITY_TYPES, FINE_CLASS_SIBLING, KIND_UNIONS, kindsFor, OVERFLOW_CAP, PLURAL_FORMS, REVERSE_MISS_VERB, PLURAL_SUBJECT_VERB, pluralVerbFor, LEADING_RELATION_VERB_RE, FROZEN_META_AMBIGUOUS_TERMS, MAX_COMPOSE_DEPTH, NEST_SENTINEL, PRED_LEAD_SKIP, FRAME_WORDS, COPULA_WORDS, entityNoun, isGerundVerb, UNIVERSAL_DET, FWD_NEG_FRAME, PLURAL_ANAPHORA_OBJECT, TEMPORAL_AUX, TEMPORAL_TAIL, TEMPORAL_TRAIL_FILLER, TEMPORAL_DET, COMMIT_FILTER_OPS, ANAPHORA_NAME_TOKEN_RE, AGG_TAIL_FILLER, LIST_SKIP, LIST_TRIGGERS_SORTED, LISTABLE_KINDS, SCOPE_PREPOSITIONS, FIND_LINKERS, RECENT_COMMIT_LEAD, qualCache, META_FALLBACK_CLASSES, inheritsApplicableCache, FIND_TIER, oppositeQualifierSpec, DEGREE_KINDS, COMMIT_FILTER_DATE_RE, compositeList, LEADING_ARTICLE_RE, TRAILING_GRAIN_WORD_RE, ENTRY_POINT_QUERY_RE, ENTRY_POINT_BASENAMES, TEST_FIXTURE_PATH_SEGMENTS, moduleStemOf, isTestFixturePath, TRANSITIVE_MAX_DEPTH, CONTENT_VOCAB, STRUCTURAL_WORDS, CASCADE_NOISE_SET, NOISE_OR_SCAFFOLD, TRIGGER_FUZZY_WORDS, CASCADE_FUZZY_TARGETS, LAST_COMMIT_PHRASE_RE, BARE_WHEN_COMMIT_RE, DYNAMIC_LIST_TRIGGER_RE, DYNAMIC_COUNT_TRIGGER_RE, DYNAMIC_TAIL_OK_RE, BARE_META_WHATIS_RE, WHATIS_FOR_FALLBACK_RE;
|
|
6632
|
+
var askEdgesOfKindCache, SYMBOL_GRAIN_SIBLING, FINE_ENTITY_TYPES, FINE_CLASS_SIBLING, KIND_UNIONS, kindsFor, SYMBOL_GRAIN_KINDS, OVERFLOW_CAP, PLURAL_FORMS, REVERSE_MISS_VERB, PLURAL_SUBJECT_VERB, pluralVerbFor, LEADING_RELATION_VERB_RE, FROZEN_META_AMBIGUOUS_TERMS, MAX_COMPOSE_DEPTH, NEST_SENTINEL, PRED_LEAD_SKIP, FRAME_WORDS, COPULA_WORDS, entityNoun, isGerundVerb, UNIVERSAL_DET, FWD_NEG_FRAME, PLURAL_ANAPHORA_OBJECT, TEMPORAL_AUX, TEMPORAL_TAIL, TEMPORAL_TRAIL_FILLER, TEMPORAL_DET, COMMIT_FILTER_OPS, ANAPHORA_NAME_TOKEN_RE, AGG_TAIL_FILLER, LIST_SKIP, LIST_TRIGGERS_SORTED, LISTABLE_KINDS, SCOPE_PREPOSITIONS, FIND_LINKERS, RECENT_COMMIT_LEAD, qualCache, META_FALLBACK_CLASSES, inheritsApplicableCache, FIND_TIER, oppositeQualifierSpec, DEGREE_KINDS, COMMIT_FILTER_DATE_RE, compositeList, LEADING_ARTICLE_RE, TRAILING_GRAIN_WORD_RE, ENTRY_POINT_QUERY_RE, ENTRY_POINT_BASENAMES, TEST_FIXTURE_PATH_SEGMENTS, moduleStemOf, isTestFixturePath, TRANSITIVE_MAX_DEPTH, CONTENT_VOCAB, STRUCTURAL_WORDS, CASCADE_NOISE_SET, NOISE_OR_SCAFFOLD, TRIGGER_FUZZY_WORDS, CASCADE_FUZZY_TARGETS, CASCADE_FUZZY_REAL_WORDS, LAST_COMMIT_PHRASE_RE, BARE_WHEN_COMMIT_RE, DYNAMIC_LIST_TRIGGER_RE, DYNAMIC_COUNT_TRIGGER_RE, DYNAMIC_TAIL_OK_RE, BARE_META_WHATIS_RE, WHATIS_FOR_FALLBACK_RE;
|
|
6586
6633
|
var init_ask = __esm({
|
|
6587
6634
|
"src/domain/ask.mjs"() {
|
|
6588
6635
|
init_codegraph();
|
|
@@ -6603,6 +6650,7 @@ ${lines.join("\n")}`;
|
|
|
6603
6650
|
FINE_CLASS_SIBLING = { Function: "Method", Method: "Function" };
|
|
6604
6651
|
KIND_UNIONS = { uses: ["imports", "calls", "callsSymbol"] };
|
|
6605
6652
|
kindsFor = (kind) => KIND_UNIONS[kind] || [kind];
|
|
6653
|
+
SYMBOL_GRAIN_KINDS = new Set(Object.values(SYMBOL_GRAIN_SIBLING));
|
|
6606
6654
|
OVERFLOW_CAP = 12;
|
|
6607
6655
|
PLURAL_FORMS = {
|
|
6608
6656
|
Function: ["function", "functions"],
|
|
@@ -6752,6 +6800,7 @@ ${lines.join("\n")}`;
|
|
|
6752
6800
|
...Object.keys(ENTITY_TO_TYPE),
|
|
6753
6801
|
...TRIGGER_FUZZY_WORDS
|
|
6754
6802
|
])].filter((wd) => /^[a-z]+$/.test(wd) && wd.length >= 4 && !STOPWORDS2.has(wd));
|
|
6803
|
+
CASCADE_FUZZY_REAL_WORDS = /* @__PURE__ */ new Set(["impact", "impacts", "impacted"]);
|
|
6755
6804
|
LAST_COMMIT_PHRASE_RE = /\b(?:the\s+)?(?:last|latest|most\s+recent)\s+commit\b/i;
|
|
6756
6805
|
BARE_WHEN_COMMIT_RE = /^when\s+(?:was|were|is|did|does|do)\s+commit\s+[0-9a-fA-F:]+$/i;
|
|
6757
6806
|
DYNAMIC_LIST_TRIGGER_RE = /^(?:list|show(?:\s+me)?)\s+(?:all\s+|the\s+)?([a-z][a-z'-]*)\s*(.*)$/i;
|
|
@@ -7599,6 +7648,7 @@ ${bodyText}` : graphText, tier });
|
|
|
7599
7648
|
CAX_MAXC0_RULE_CONFIDENCE: () => CAX_MAXC0_RULE_CONFIDENCE,
|
|
7600
7649
|
CLS_SVF1_RULE: () => CLS_SVF1_RULE,
|
|
7601
7650
|
CLS_SVF1_RULE_CONFIDENCE: () => CLS_SVF1_RULE_CONFIDENCE,
|
|
7651
|
+
DEFAULT_MAX_ENVIRONMENTS: () => DEFAULT_MAX_ENVIRONMENTS,
|
|
7602
7652
|
DISJOINT_PREDICATE: () => DISJOINT_PREDICATE,
|
|
7603
7653
|
ENTAILED_DISJOINT_PROVENANCE: () => ENTAILED_DISJOINT_PROVENANCE,
|
|
7604
7654
|
ENTAILED_PROVENANCE: () => ENTAILED_PROVENANCE,
|
|
@@ -7612,10 +7662,12 @@ ${bodyText}` : graphText, tier });
|
|
|
7612
7662
|
SUBCLASS_PREDICATE: () => SUBCLASS_PREDICATE,
|
|
7613
7663
|
TYPE_PREDICATE: () => TYPE_PREDICATE,
|
|
7614
7664
|
buildCardinalityRestrictions: () => buildCardinalityRestrictions,
|
|
7665
|
+
buildRelevanceFrontier: () => buildRelevanceFrontier,
|
|
7615
7666
|
deriveDisjointViolations: () => deriveDisjointViolations,
|
|
7616
7667
|
deriveSomeValuesFromApplication: () => deriveSomeValuesFromApplication,
|
|
7617
7668
|
deriveSomeValuesFromSubsumption: () => deriveSomeValuesFromSubsumption,
|
|
7618
7669
|
deriveSubClassClosure: () => deriveSubClassClosure,
|
|
7670
|
+
deriveSubClassClosureDelta: () => deriveSubClassClosureDelta,
|
|
7619
7671
|
deriveTypePropagation: () => deriveTypePropagation,
|
|
7620
7672
|
entailedTrustFrom: () => entailedTrustFrom,
|
|
7621
7673
|
findConsistencyViolations: () => findConsistencyViolations,
|
|
@@ -7693,6 +7745,65 @@ ${bodyText}` : graphText, tier });
|
|
|
7693
7745
|
}
|
|
7694
7746
|
return derived;
|
|
7695
7747
|
}
|
|
7748
|
+
function deriveSubClassClosureDelta(allEdges, deltaEdges, { depth = 32, budget = 50, focus = null } = {}) {
|
|
7749
|
+
const present = /* @__PURE__ */ new Set();
|
|
7750
|
+
const succ = /* @__PURE__ */ new Map();
|
|
7751
|
+
const pred = /* @__PURE__ */ new Map();
|
|
7752
|
+
for (const [a, b] of allEdges || []) {
|
|
7753
|
+
if (!a || !b || a === b) continue;
|
|
7754
|
+
present.add(`${a}${SEP}${b}`);
|
|
7755
|
+
if (!succ.has(a)) succ.set(a, /* @__PURE__ */ new Set());
|
|
7756
|
+
succ.get(a).add(b);
|
|
7757
|
+
if (!pred.has(b)) pred.set(b, /* @__PURE__ */ new Set());
|
|
7758
|
+
pred.get(b).add(a);
|
|
7759
|
+
}
|
|
7760
|
+
let delta = [];
|
|
7761
|
+
const seenDelta = /* @__PURE__ */ new Set();
|
|
7762
|
+
for (const [a, b] of deltaEdges || []) {
|
|
7763
|
+
if (!a || !b || a === b) continue;
|
|
7764
|
+
const key = `${a}${SEP}${b}`;
|
|
7765
|
+
if (seenDelta.has(key)) continue;
|
|
7766
|
+
seenDelta.add(key);
|
|
7767
|
+
delta.push([a, b]);
|
|
7768
|
+
}
|
|
7769
|
+
const focusSet = focus instanceof Set ? focus.size ? focus : null : normalizeFocus(focus);
|
|
7770
|
+
const inFocus = (a, b, c) => !focusSet || focusSet.has(a) || focusSet.has(b) || focusSet.has(c);
|
|
7771
|
+
const derived = [];
|
|
7772
|
+
const derivedKeys = /* @__PURE__ */ new Set();
|
|
7773
|
+
for (let round2 = 0; round2 < depth && delta.length; round2 += 1) {
|
|
7774
|
+
const additions = [];
|
|
7775
|
+
const consider = (a, b, c) => {
|
|
7776
|
+
if (a === c) return;
|
|
7777
|
+
const key = `${a}${SEP}${c}`;
|
|
7778
|
+
if (present.has(key) || derivedKeys.has(key)) return;
|
|
7779
|
+
if (!inFocus(a, b, c)) return;
|
|
7780
|
+
additions.push([a, b, c, key]);
|
|
7781
|
+
};
|
|
7782
|
+
for (const [a, b] of delta) {
|
|
7783
|
+
for (const c of succ.get(b) || []) consider(a, b, c);
|
|
7784
|
+
for (const z of pred.get(a) || []) consider(z, a, b);
|
|
7785
|
+
}
|
|
7786
|
+
if (!additions.length) break;
|
|
7787
|
+
additions.sort((x, y) => x[0].localeCompare(y[0]) || x[2].localeCompare(y[2]) || x[1].localeCompare(y[1]));
|
|
7788
|
+
let progressed = false;
|
|
7789
|
+
const nextDelta = [];
|
|
7790
|
+
for (const [a, b, c, key] of additions) {
|
|
7791
|
+
if (derivedKeys.has(key)) continue;
|
|
7792
|
+
if (derived.length >= budget) break;
|
|
7793
|
+
derivedKeys.add(key);
|
|
7794
|
+
derived.push({ subject: a, object: c, via: b });
|
|
7795
|
+
if (!succ.has(a)) succ.set(a, /* @__PURE__ */ new Set());
|
|
7796
|
+
succ.get(a).add(c);
|
|
7797
|
+
if (!pred.has(c)) pred.set(c, /* @__PURE__ */ new Set());
|
|
7798
|
+
pred.get(c).add(a);
|
|
7799
|
+
nextDelta.push([a, c]);
|
|
7800
|
+
progressed = true;
|
|
7801
|
+
}
|
|
7802
|
+
if (derived.length >= budget || !progressed) break;
|
|
7803
|
+
delta = nextDelta;
|
|
7804
|
+
}
|
|
7805
|
+
return derived;
|
|
7806
|
+
}
|
|
7696
7807
|
function buildAncestorCloser(subClassEdges) {
|
|
7697
7808
|
const succ = /* @__PURE__ */ new Map();
|
|
7698
7809
|
for (const [a, b] of subClassEdges || []) {
|
|
@@ -7715,11 +7826,41 @@ ${bodyText}` : graphText, tier });
|
|
|
7715
7826
|
return seen;
|
|
7716
7827
|
};
|
|
7717
7828
|
}
|
|
7718
|
-
function
|
|
7829
|
+
function buildDescendantCloser(subClassEdges) {
|
|
7830
|
+
return buildAncestorCloser((subClassEdges || []).map(([a, b]) => [b, a]));
|
|
7831
|
+
}
|
|
7832
|
+
function buildRelevanceFrontier(rows, seedTerms) {
|
|
7833
|
+
const subClassEdges = [];
|
|
7834
|
+
const typeEdges = [];
|
|
7835
|
+
const onPropertyOf = /* @__PURE__ */ new Map();
|
|
7836
|
+
const someValuesFromOf = /* @__PURE__ */ new Map();
|
|
7837
|
+
for (const r of rows || []) {
|
|
7838
|
+
if (!r || !r.subject || !r.predicate || !r.object) continue;
|
|
7839
|
+
if (isSubClassOf(r.predicate)) subClassEdges.push([r.subject, r.object]);
|
|
7840
|
+
else if (isType(r.predicate)) typeEdges.push([r.subject, r.object]);
|
|
7841
|
+
else if (isOnProperty(r.predicate)) onPropertyOf.set(r.subject, r.object);
|
|
7842
|
+
else if (isSomeValuesFrom(r.predicate)) someValuesFromOf.set(r.subject, r.object);
|
|
7843
|
+
}
|
|
7844
|
+
const descendantsOf2 = buildDescendantCloser(subClassEdges);
|
|
7845
|
+
const affectedClasses = /* @__PURE__ */ new Set();
|
|
7846
|
+
for (const t of seedTerms || []) {
|
|
7847
|
+
const n = normFactTerm(t);
|
|
7848
|
+
if (!n) continue;
|
|
7849
|
+
affectedClasses.add(n);
|
|
7850
|
+
for (const d of descendantsOf2(n)) affectedClasses.add(d);
|
|
7851
|
+
}
|
|
7852
|
+
const frontier = new Set(affectedClasses);
|
|
7853
|
+
for (const [x, c] of typeEdges) if (affectedClasses.has(c)) frontier.add(x);
|
|
7854
|
+
for (const [restriction, target] of someValuesFromOf) {
|
|
7855
|
+
if (onPropertyOf.has(restriction) && affectedClasses.has(target)) frontier.add(restriction);
|
|
7856
|
+
}
|
|
7857
|
+
return frontier;
|
|
7858
|
+
}
|
|
7859
|
+
function deriveTypePropagation(typeEdges, subClassEdges, { budget = 50, focus = null, presentTypeEdges = typeEdges } = {}) {
|
|
7719
7860
|
const ancestorsOf2 = buildAncestorCloser(subClassEdges);
|
|
7720
7861
|
const present = /* @__PURE__ */ new Set();
|
|
7721
7862
|
const seenTypeEdge = /* @__PURE__ */ new Set();
|
|
7722
|
-
for (const [x, c] of
|
|
7863
|
+
for (const [x, c] of presentTypeEdges || []) if (x && c) present.add(`${x}${SEP}${c}`);
|
|
7723
7864
|
const focusSet = focus instanceof Set ? focus.size ? focus : null : normalizeFocus(focus);
|
|
7724
7865
|
const inFocus = (x, c, d) => !focusSet || focusSet.has(x) || focusSet.has(c) || focusSet.has(d);
|
|
7725
7866
|
const candidates = [];
|
|
@@ -8015,8 +8156,17 @@ ${bodyText}` : graphText, tier });
|
|
|
8015
8156
|
}
|
|
8016
8157
|
return derived;
|
|
8017
8158
|
}
|
|
8018
|
-
async function syllogise(repoDir, {
|
|
8159
|
+
async function syllogise(repoDir, {
|
|
8160
|
+
depth = 32,
|
|
8161
|
+
budget = 50,
|
|
8162
|
+
focus = null,
|
|
8163
|
+
expandFocus = false,
|
|
8164
|
+
maxEnvironments = DEFAULT_MAX_ENVIRONMENTS,
|
|
8165
|
+
full = false,
|
|
8166
|
+
store
|
|
8167
|
+
} = {}) {
|
|
8019
8168
|
const { loadMemory: loadMemory2, readFactRows: readFactRows2, appendFacts: appendFacts2 } = requireStore(store, ["loadMemory", "readFactRows", "appendFacts"], "syllogise");
|
|
8169
|
+
const stateFnsPresent = typeof store?.loadSyllogiseState === "function" && typeof store?.saveSyllogiseState === "function";
|
|
8020
8170
|
const memory = await loadMemory2(repoDir);
|
|
8021
8171
|
const rows = readFactRows2(memory);
|
|
8022
8172
|
const subClassEdges = rows.filter((r) => isSubClassOf(r.predicate)).map((r) => [r.subject, r.object]);
|
|
@@ -8036,22 +8186,64 @@ ${bodyText}` : graphText, tier });
|
|
|
8036
8186
|
const target = someValuesFromOf.get(restriction);
|
|
8037
8187
|
if (target) restrictionEdges.push({ restriction, property, target });
|
|
8038
8188
|
}
|
|
8039
|
-
const
|
|
8189
|
+
const callerFocus = normalizeFocus(focus);
|
|
8190
|
+
const normalizedFocus = expandFocus && callerFocus ? buildRelevanceFrontier(rows, [...callerFocus]) : callerFocus;
|
|
8191
|
+
const state = normalizedFocus === null && stateFnsPresent ? await store.loadSyllogiseState(repoDir) : null;
|
|
8192
|
+
const currentIdSet = new Set(rows.map((r) => r.id));
|
|
8193
|
+
const removedSinceLast = Array.isArray(state?.factIds) ? state.factIds.filter((id) => !currentIdSet.has(id)) : [];
|
|
8194
|
+
const mode = state && Array.isArray(state.factIds) && !removedSinceLast.length && !full ? "delta" : "full";
|
|
8195
|
+
const watermark = mode === "delta" ? new Set(state.factIds) : null;
|
|
8196
|
+
const deltaRows = mode === "delta" ? rows.filter((r) => !watermark.has(r.id)) : rows;
|
|
8197
|
+
const deltaSize = deltaRows.length;
|
|
8040
8198
|
const trustByTriple = /* @__PURE__ */ new Map();
|
|
8041
8199
|
for (const r of rows) trustByTriple.set(`${r.subject}${SEP}${r.predicate}${SEP}${r.object}`, r.trust);
|
|
8042
8200
|
const premiseTrust = (s, p, o) => trustByTriple.get(`${s}${SEP}${p}${SEP}${o}`);
|
|
8043
8201
|
const hasTriple = (s, p, o) => trustByTriple.has(`${s}${SEP}${p}${SEP}${o}`);
|
|
8044
8202
|
const numericOnly = (arr) => arr.filter((t) => typeof t === "number");
|
|
8045
|
-
const
|
|
8203
|
+
const deltaEmpty = mode === "delta" && !deltaRows.length;
|
|
8204
|
+
const deltaSubEdges = mode === "delta" ? deltaRows.filter((r) => isSubClassOf(r.predicate)).map((r) => [r.subject, r.object]) : [];
|
|
8205
|
+
const scmDerived = mode === "delta" ? deltaSubEdges.length ? deriveSubClassClosureDelta(subClassEdges, deltaSubEdges, { depth, budget, focus: normalizedFocus }) : [] : deriveSubClassClosure(subClassEdges, { depth, budget, focus: normalizedFocus });
|
|
8046
8206
|
const enlargedSubClassEdges = subClassEdges.concat(scmDerived.map((d) => [d.subject, d.object]));
|
|
8207
|
+
let kernelFocus = normalizedFocus;
|
|
8208
|
+
let frontier = null;
|
|
8209
|
+
if (mode === "delta" && !deltaEmpty) {
|
|
8210
|
+
const frontierRows = rows.concat(scmDerived.map((d) => ({ subject: d.subject, predicate: SUBCLASS_PREDICATE, object: d.object })));
|
|
8211
|
+
const seeds = [];
|
|
8212
|
+
for (const r of deltaRows) seeds.push(r.subject, r.object);
|
|
8213
|
+
frontier = buildRelevanceFrontier(frontierRows, seeds);
|
|
8214
|
+
kernelFocus = frontier;
|
|
8215
|
+
}
|
|
8216
|
+
const inFrontier = (t) => !frontier || frontier.has(t);
|
|
8217
|
+
const caxTypeEdges = frontier ? typeEdges.filter(([x, c]) => inFrontier(x) || inFrontier(c)) : typeEdges;
|
|
8218
|
+
const deltaDwEndpoints = /* @__PURE__ */ new Set();
|
|
8219
|
+
if (frontier) {
|
|
8220
|
+
for (const r of deltaRows) {
|
|
8221
|
+
if (isDisjoint(r.predicate)) {
|
|
8222
|
+
deltaDwEndpoints.add(r.subject);
|
|
8223
|
+
deltaDwEndpoints.add(r.object);
|
|
8224
|
+
}
|
|
8225
|
+
}
|
|
8226
|
+
}
|
|
8227
|
+
const dwAncestorsOf = frontier && deltaDwEndpoints.size ? buildAncestorCloser(enlargedSubClassEdges) : null;
|
|
8228
|
+
const dwTypeEdges = frontier ? typeEdges.filter(([x, c]) => inFrontier(x) || inFrontier(c) || dwAncestorsOf && [...dwAncestorsOf(c)].some((a) => deltaDwEndpoints.has(a))) : typeEdges;
|
|
8229
|
+
const deltaRestrictionProperties = /* @__PURE__ */ new Set();
|
|
8230
|
+
if (frontier) {
|
|
8231
|
+
for (const r of deltaRows) {
|
|
8232
|
+
if (isOnProperty(r.predicate) || isSomeValuesFrom(r.predicate)) {
|
|
8233
|
+
const property = onPropertyOf.get(r.subject);
|
|
8234
|
+
if (property) deltaRestrictionProperties.add(normFactTerm(property));
|
|
8235
|
+
}
|
|
8236
|
+
}
|
|
8237
|
+
}
|
|
8238
|
+
const svf1PropertyEdges = frontier ? propertyEdges.filter(([x, p, y]) => inFrontier(x) || inFrontier(y) || deltaRestrictionProperties.has(normFactTerm(p))) : propertyEdges;
|
|
8047
8239
|
const remainingBudget = Math.max(0, budget - scmDerived.length);
|
|
8048
|
-
const caxDerived = remainingBudget > 0 ? deriveTypePropagation(
|
|
8240
|
+
const caxDerived = remainingBudget > 0 && !deltaEmpty ? deriveTypePropagation(caxTypeEdges, enlargedSubClassEdges, { budget: remainingBudget, focus: kernelFocus, presentTypeEdges: typeEdges }) : [];
|
|
8049
8241
|
const remainingBudgetDw = Math.max(0, budget - scmDerived.length - caxDerived.length);
|
|
8050
|
-
const dwDerived = remainingBudgetDw > 0 ? deriveDisjointViolations(
|
|
8242
|
+
const dwDerived = remainingBudgetDw > 0 && !deltaEmpty ? deriveDisjointViolations(dwTypeEdges, enlargedSubClassEdges, disjointEdges, { budget: remainingBudgetDw, focus: kernelFocus }) : [];
|
|
8051
8243
|
const remainingBudgetSvf1 = Math.max(0, budget - scmDerived.length - caxDerived.length - dwDerived.length);
|
|
8052
|
-
const svf1Derived = remainingBudgetSvf1 > 0 && restrictionEdges.length ? deriveSomeValuesFromApplication(
|
|
8244
|
+
const svf1Derived = remainingBudgetSvf1 > 0 && restrictionEdges.length && !deltaEmpty ? deriveSomeValuesFromApplication(svf1PropertyEdges, typeEdges, enlargedSubClassEdges, restrictionEdges, { budget: remainingBudgetSvf1, focus: kernelFocus }) : [];
|
|
8053
8245
|
const remainingBudgetScmSvf = Math.max(0, budget - scmDerived.length - caxDerived.length - dwDerived.length - svf1Derived.length);
|
|
8054
|
-
const scmSvfDerived = remainingBudgetScmSvf > 0 && restrictionEdges.length > 1 ? deriveSomeValuesFromSubsumption(restrictionEdges, enlargedSubClassEdges, { budget: remainingBudgetScmSvf, focus:
|
|
8246
|
+
const scmSvfDerived = remainingBudgetScmSvf > 0 && restrictionEdges.length > 1 && !deltaEmpty ? deriveSomeValuesFromSubsumption(restrictionEdges, enlargedSubClassEdges, { budget: remainingBudgetScmSvf, focus: kernelFocus }) : [];
|
|
8055
8247
|
const restrictionByRid = new Map(restrictionEdges.map((r) => [r.restriction, r]));
|
|
8056
8248
|
const toWrite = [
|
|
8057
8249
|
...scmDerived.map((d) => ({
|
|
@@ -8059,16 +8251,18 @@ ${bodyText}` : graphText, tier });
|
|
|
8059
8251
|
predicate: SUBCLASS_PREDICATE,
|
|
8060
8252
|
object: d.object,
|
|
8061
8253
|
provenance: ENTAILED_PROVENANCE,
|
|
8062
|
-
// Persisted justification:
|
|
8063
|
-
//
|
|
8064
|
-
//
|
|
8254
|
+
// Persisted justification: one environment per independent derivation,
|
|
8255
|
+
// each an ordered premise fact-id list — this first one is the premise
|
|
8256
|
+
// set the conclusion rode (a⊑b, b⊑c); the alternate-discovery step
|
|
8257
|
+
// below may append more. Content-addressed ids work even when a premise
|
|
8258
|
+
// is itself an entailment this same pass just derived. Read back by
|
|
8065
8259
|
// retractSubClassOf (below) to find every entailment a retracted
|
|
8066
8260
|
// premise could have supported. All five rules persist one, each
|
|
8067
8261
|
// citing its own premise shape.
|
|
8068
|
-
justification: [
|
|
8262
|
+
justification: [[
|
|
8069
8263
|
factIdForTriple(d.subject, SUBCLASS_PREDICATE, d.via),
|
|
8070
8264
|
factIdForTriple(d.via, SUBCLASS_PREDICATE, d.object)
|
|
8071
|
-
]
|
|
8265
|
+
]]
|
|
8072
8266
|
})),
|
|
8073
8267
|
...caxDerived.map((d) => ({
|
|
8074
8268
|
subject: d.subject,
|
|
@@ -8079,10 +8273,10 @@ ${bodyText}` : graphText, tier });
|
|
|
8079
8273
|
// taught chain is multi-hop: scm-sco materialises that edge (this same
|
|
8080
8274
|
// pass or an earlier one), and retraction re-VERIFIES every candidate
|
|
8081
8275
|
// anyway, so a citation left dangling by budget truncation is inert.
|
|
8082
|
-
justification: [
|
|
8276
|
+
justification: [[
|
|
8083
8277
|
factIdForTriple(d.subject, TYPE_PREDICATE, d.via),
|
|
8084
8278
|
factIdForTriple(d.via, SUBCLASS_PREDICATE, d.object)
|
|
8085
|
-
]
|
|
8279
|
+
]]
|
|
8086
8280
|
})),
|
|
8087
8281
|
...dwDerived.map((d) => {
|
|
8088
8282
|
const dwStoredForward = hasTriple(d.viaClass, DISJOINT_PREDICATE, d.object);
|
|
@@ -8099,11 +8293,11 @@ ${bodyText}` : graphText, tier });
|
|
|
8099
8293
|
predicate: DISJOINT_PREDICATE,
|
|
8100
8294
|
object: d.object,
|
|
8101
8295
|
provenance: ENTAILED_DISJOINT_PROVENANCE,
|
|
8102
|
-
justification: [
|
|
8296
|
+
justification: [[
|
|
8103
8297
|
factIdForTriple(d.subject, TYPE_PREDICATE, d.viaType),
|
|
8104
8298
|
factIdForTriple(dwS, DISJOINT_PREDICATE, dwO),
|
|
8105
8299
|
...d.viaClass !== d.viaType ? [factIdForTriple(d.viaType, SUBCLASS_PREDICATE, d.viaClass)] : []
|
|
8106
|
-
],
|
|
8300
|
+
]],
|
|
8107
8301
|
...premiseTrusts.length ? { premiseTrusts, ruleConfidence: CAX_DW_RULE_CONFIDENCE } : {}
|
|
8108
8302
|
};
|
|
8109
8303
|
}),
|
|
@@ -8122,13 +8316,13 @@ ${bodyText}` : graphText, tier });
|
|
|
8122
8316
|
predicate: TYPE_PREDICATE,
|
|
8123
8317
|
object: d.object,
|
|
8124
8318
|
provenance: ENTAILED_SVF1_PROVENANCE,
|
|
8125
|
-
justification: [
|
|
8319
|
+
justification: [[
|
|
8126
8320
|
factIdForTriple(d.subject, d.viaProperty, d.viaValue),
|
|
8127
8321
|
factIdForTriple(d.viaValue, TYPE_PREDICATE, d.viaType),
|
|
8128
8322
|
factIdForTriple(d.object, ON_PROPERTY_PREDICATE, d.viaPropertyKey),
|
|
8129
8323
|
factIdForTriple(d.object, SOME_VALUES_FROM_PREDICATE, d.viaTarget),
|
|
8130
8324
|
...d.viaType !== d.viaTarget ? [factIdForTriple(d.viaType, SUBCLASS_PREDICATE, d.viaTarget)] : []
|
|
8131
|
-
],
|
|
8325
|
+
]],
|
|
8132
8326
|
// same sub-1 discount as cax-dw, same reason (see CAX_DW_RULE_CONFIDENCE).
|
|
8133
8327
|
...premiseTrusts.length ? { premiseTrusts, ruleConfidence: CLS_SVF1_RULE_CONFIDENCE } : {}
|
|
8134
8328
|
};
|
|
@@ -8148,18 +8342,70 @@ ${bodyText}` : graphText, tier });
|
|
|
8148
8342
|
predicate: SUBCLASS_PREDICATE,
|
|
8149
8343
|
object: d.object,
|
|
8150
8344
|
provenance: ENTAILED_SCM_SVF_PROVENANCE,
|
|
8151
|
-
justification: [
|
|
8345
|
+
justification: [[
|
|
8152
8346
|
...r1 ? [factIdForTriple(d.subject, ON_PROPERTY_PREDICATE, r1.property)] : [],
|
|
8153
8347
|
factIdForTriple(d.subject, SOME_VALUES_FROM_PREDICATE, d.viaY1),
|
|
8154
8348
|
...r2 ? [factIdForTriple(d.object, ON_PROPERTY_PREDICATE, r2.property)] : [],
|
|
8155
8349
|
factIdForTriple(d.object, SOME_VALUES_FROM_PREDICATE, d.viaY2),
|
|
8156
8350
|
factIdForTriple(d.viaY1, SUBCLASS_PREDICATE, d.viaY2)
|
|
8157
|
-
],
|
|
8351
|
+
]],
|
|
8158
8352
|
// same sub-1 discount as cax-dw/cls-svf1, same reason (see CAX_DW_RULE_CONFIDENCE).
|
|
8159
8353
|
...premiseTrusts.length ? { premiseTrusts, ruleConfidence: SCM_SVF_RULE_CONFIDENCE } : {}
|
|
8160
8354
|
};
|
|
8161
8355
|
})
|
|
8162
8356
|
];
|
|
8357
|
+
const conclusionCandidates = toWrite.map((w) => ({
|
|
8358
|
+
id: factIdForTriple(w.subject, w.predicate, w.object),
|
|
8359
|
+
subject: w.subject,
|
|
8360
|
+
predicate: w.predicate,
|
|
8361
|
+
object: w.object,
|
|
8362
|
+
environments: w.justification,
|
|
8363
|
+
write: w
|
|
8364
|
+
}));
|
|
8365
|
+
const enumerateSupport = buildSupportEnumerator(rows.concat(conclusionCandidates.map((c) => ({
|
|
8366
|
+
id: c.id,
|
|
8367
|
+
subject: c.subject,
|
|
8368
|
+
predicate: c.predicate,
|
|
8369
|
+
object: c.object
|
|
8370
|
+
}))));
|
|
8371
|
+
const rowById = new Map(rows.map((r) => [r.id, r]));
|
|
8372
|
+
const ownedPredicate = (p) => isSubClassOf(p) || isType(p) || isDisjoint(p);
|
|
8373
|
+
const storedCandidateInScope = (r) => mode !== "delta" || frontier !== null && (frontier.has(r.subject) || frontier.has(r.object));
|
|
8374
|
+
const storedCandidates = rows.filter((r) => ownedPredicate(r.predicate) && isPurelyEntailed(r.provenance) && environmentsOf(r).length < maxEnvironments && storedCandidateInScope(r)).map((r) => ({
|
|
8375
|
+
id: r.id,
|
|
8376
|
+
subject: r.subject,
|
|
8377
|
+
predicate: r.predicate,
|
|
8378
|
+
object: r.object,
|
|
8379
|
+
environments: environmentsOf(r),
|
|
8380
|
+
provenance: r.provenance
|
|
8381
|
+
}));
|
|
8382
|
+
const alternateCandidates = [...conclusionCandidates, ...storedCandidates].sort((a, b) => a.subject.localeCompare(b.subject) || a.predicate.localeCompare(b.predicate) || a.object.localeCompare(b.object));
|
|
8383
|
+
let environmentsAdded = 0;
|
|
8384
|
+
let alternatesTruncated = false;
|
|
8385
|
+
let examined = 0;
|
|
8386
|
+
for (const cand of alternateCandidates) {
|
|
8387
|
+
if (examined >= budget) {
|
|
8388
|
+
alternatesTruncated = true;
|
|
8389
|
+
break;
|
|
8390
|
+
}
|
|
8391
|
+
examined += 1;
|
|
8392
|
+
const discovered = enumerateSupport(cand, { maxEnvironments: maxEnvironments + 1 });
|
|
8393
|
+
const { kept, truncated: mergeTruncated } = capMergeEnvironments(cand.environments, discovered, maxEnvironments);
|
|
8394
|
+
if (mergeTruncated) alternatesTruncated = true;
|
|
8395
|
+
if (kept.length <= cand.environments.length) continue;
|
|
8396
|
+
environmentsAdded += kept.length - cand.environments.length;
|
|
8397
|
+
if (cand.write) {
|
|
8398
|
+
cand.write.justification = kept;
|
|
8399
|
+
continue;
|
|
8400
|
+
}
|
|
8401
|
+
toWrite.push({
|
|
8402
|
+
subject: cand.subject,
|
|
8403
|
+
predicate: cand.predicate,
|
|
8404
|
+
object: cand.object,
|
|
8405
|
+
justification: kept,
|
|
8406
|
+
...bestEnvironmentTrustOpts(cand.provenance, kept, (pid) => rowById.get(pid)?.trust) || {}
|
|
8407
|
+
});
|
|
8408
|
+
}
|
|
8163
8409
|
const { ids } = await appendFacts2(repoDir, toWrite);
|
|
8164
8410
|
const written = [];
|
|
8165
8411
|
let i = 0;
|
|
@@ -8183,7 +8429,27 @@ ${bodyText}` : graphText, tier });
|
|
|
8183
8429
|
written.push({ id: ids[i], subject: d.subject, object: d.object, via: d.viaY1, rule: SCM_SVF_RULE });
|
|
8184
8430
|
i += 1;
|
|
8185
8431
|
}
|
|
8186
|
-
|
|
8432
|
+
const truncated = written.length >= budget;
|
|
8433
|
+
if (normalizedFocus === null && stateFnsPresent && !truncated) {
|
|
8434
|
+
const factIds = new Set(currentIdSet);
|
|
8435
|
+
for (const id of ids) factIds.add(id);
|
|
8436
|
+
await store.saveSyllogiseState(repoDir, {
|
|
8437
|
+
version: 1,
|
|
8438
|
+
factIds: [...factIds].sort(),
|
|
8439
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8440
|
+
});
|
|
8441
|
+
}
|
|
8442
|
+
return {
|
|
8443
|
+
derived: written,
|
|
8444
|
+
count: written.length,
|
|
8445
|
+
budget,
|
|
8446
|
+
depth,
|
|
8447
|
+
truncated,
|
|
8448
|
+
mode,
|
|
8449
|
+
deltaSize,
|
|
8450
|
+
environmentsAdded,
|
|
8451
|
+
alternatesTruncated
|
|
8452
|
+
};
|
|
8187
8453
|
}
|
|
8188
8454
|
function isPurelyEntailed(provenance) {
|
|
8189
8455
|
const tags = String(provenance || "").split(" | ").filter(Boolean);
|
|
@@ -8254,8 +8520,185 @@ ${bodyText}` : graphText, tier });
|
|
|
8254
8520
|
return true;
|
|
8255
8521
|
};
|
|
8256
8522
|
}
|
|
8257
|
-
|
|
8523
|
+
function buildSupportEnumerator(rows) {
|
|
8524
|
+
const storedIds = /* @__PURE__ */ new Set();
|
|
8525
|
+
const subClassEdges = [];
|
|
8526
|
+
const succ = /* @__PURE__ */ new Map();
|
|
8527
|
+
const typesOf = /* @__PURE__ */ new Map();
|
|
8528
|
+
const disjointForward = /* @__PURE__ */ new Set();
|
|
8529
|
+
const disjointOf = /* @__PURE__ */ new Map();
|
|
8530
|
+
const onPropertyOf = /* @__PURE__ */ new Map();
|
|
8531
|
+
const someValuesFromOf = /* @__PURE__ */ new Map();
|
|
8532
|
+
const propertyEdgesOf = /* @__PURE__ */ new Map();
|
|
8533
|
+
for (const r of rows) {
|
|
8534
|
+
if (!r || !r.subject || !r.predicate || !r.object) continue;
|
|
8535
|
+
if (r.id) storedIds.add(r.id);
|
|
8536
|
+
const pLower = String(r.predicate || "").trim().toLowerCase();
|
|
8537
|
+
if (isSubClassOf(r.predicate)) {
|
|
8538
|
+
subClassEdges.push([r.subject, r.object]);
|
|
8539
|
+
if (!succ.has(r.subject)) succ.set(r.subject, /* @__PURE__ */ new Set());
|
|
8540
|
+
succ.get(r.subject).add(r.object);
|
|
8541
|
+
} else if (isType(r.predicate)) {
|
|
8542
|
+
if (!typesOf.has(r.subject)) typesOf.set(r.subject, /* @__PURE__ */ new Set());
|
|
8543
|
+
typesOf.get(r.subject).add(r.object);
|
|
8544
|
+
} else if (isDisjoint(r.predicate)) {
|
|
8545
|
+
disjointForward.add(`${r.subject}${SEP}${r.object}`);
|
|
8546
|
+
if (!disjointOf.has(r.subject)) disjointOf.set(r.subject, /* @__PURE__ */ new Set());
|
|
8547
|
+
disjointOf.get(r.subject).add(r.object);
|
|
8548
|
+
if (!disjointOf.has(r.object)) disjointOf.set(r.object, /* @__PURE__ */ new Set());
|
|
8549
|
+
disjointOf.get(r.object).add(r.subject);
|
|
8550
|
+
} else if (isOnProperty(r.predicate)) onPropertyOf.set(r.subject, r.object);
|
|
8551
|
+
else if (isSomeValuesFrom(r.predicate)) someValuesFromOf.set(r.subject, r.object);
|
|
8552
|
+
else if (!RESERVED_PREDICATES.has(pLower)) {
|
|
8553
|
+
if (!propertyEdgesOf.has(r.subject)) propertyEdgesOf.set(r.subject, []);
|
|
8554
|
+
propertyEdgesOf.get(r.subject).push([r.predicate, r.object]);
|
|
8555
|
+
}
|
|
8556
|
+
}
|
|
8557
|
+
const ancestorsOf2 = buildAncestorCloser(subClassEdges);
|
|
8558
|
+
const succOf = (a) => succ.get(a) || /* @__PURE__ */ new Set();
|
|
8559
|
+
const restrictionOf = (node) => {
|
|
8560
|
+
const property = onPropertyOf.get(node);
|
|
8561
|
+
const target = someValuesFromOf.get(node);
|
|
8562
|
+
return property && target ? { property, propertyKey: normFactTerm(property), target } : null;
|
|
8563
|
+
};
|
|
8564
|
+
return (row, { maxEnvironments = DEFAULT_MAX_ENVIRONMENTS } = {}) => {
|
|
8565
|
+
const out = [];
|
|
8566
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8567
|
+
const admit = (env) => {
|
|
8568
|
+
if (out.length >= maxEnvironments) return;
|
|
8569
|
+
if (row.id && env.includes(row.id)) return;
|
|
8570
|
+
if (!env.every((id) => storedIds.has(id))) return;
|
|
8571
|
+
const key = [...env].sort().join(" ");
|
|
8572
|
+
if (seen.has(key)) return;
|
|
8573
|
+
seen.add(key);
|
|
8574
|
+
out.push(env);
|
|
8575
|
+
};
|
|
8576
|
+
if (isSubClassOf(row.predicate)) {
|
|
8577
|
+
for (const m of [...succOf(row.subject)].sort()) {
|
|
8578
|
+
if (out.length >= maxEnvironments) break;
|
|
8579
|
+
if (m === row.subject || m === row.object) continue;
|
|
8580
|
+
if (!succOf(m).has(row.object)) continue;
|
|
8581
|
+
admit([
|
|
8582
|
+
factIdForTriple(row.subject, SUBCLASS_PREDICATE, m),
|
|
8583
|
+
factIdForTriple(m, SUBCLASS_PREDICATE, row.object)
|
|
8584
|
+
]);
|
|
8585
|
+
}
|
|
8586
|
+
if (out.length < maxEnvironments) {
|
|
8587
|
+
const r1 = restrictionOf(row.subject);
|
|
8588
|
+
const r2 = restrictionOf(row.object);
|
|
8589
|
+
if (r1 && r2 && r1.propertyKey === r2.propertyKey && r1.target !== r2.target && succOf(r1.target).has(r2.target)) {
|
|
8590
|
+
admit([
|
|
8591
|
+
factIdForTriple(row.subject, ON_PROPERTY_PREDICATE, r1.property),
|
|
8592
|
+
factIdForTriple(row.subject, SOME_VALUES_FROM_PREDICATE, r1.target),
|
|
8593
|
+
factIdForTriple(row.object, ON_PROPERTY_PREDICATE, r2.property),
|
|
8594
|
+
factIdForTriple(row.object, SOME_VALUES_FROM_PREDICATE, r2.target),
|
|
8595
|
+
factIdForTriple(r1.target, SUBCLASS_PREDICATE, r2.target)
|
|
8596
|
+
]);
|
|
8597
|
+
}
|
|
8598
|
+
}
|
|
8599
|
+
return out;
|
|
8600
|
+
}
|
|
8601
|
+
if (isType(row.predicate)) {
|
|
8602
|
+
for (const c of [...typesOf.get(row.subject) || []].sort()) {
|
|
8603
|
+
if (out.length >= maxEnvironments) break;
|
|
8604
|
+
if (c === row.object) continue;
|
|
8605
|
+
if (!succOf(c).has(row.object)) continue;
|
|
8606
|
+
admit([
|
|
8607
|
+
factIdForTriple(row.subject, TYPE_PREDICATE, c),
|
|
8608
|
+
factIdForTriple(c, SUBCLASS_PREDICATE, row.object)
|
|
8609
|
+
]);
|
|
8610
|
+
}
|
|
8611
|
+
const rec = restrictionOf(row.object);
|
|
8612
|
+
if (rec) {
|
|
8613
|
+
const edges = [...propertyEdgesOf.get(row.subject) || []].filter(([p]) => normFactTerm(p) === rec.propertyKey).sort((a, b) => a[0].localeCompare(b[0]) || a[1].localeCompare(b[1]));
|
|
8614
|
+
for (const [p, y] of edges) {
|
|
8615
|
+
if (out.length >= maxEnvironments) break;
|
|
8616
|
+
for (const c of [...typesOf.get(y) || []].sort()) {
|
|
8617
|
+
if (out.length >= maxEnvironments) break;
|
|
8618
|
+
if (c !== rec.target && !succOf(c).has(rec.target)) continue;
|
|
8619
|
+
admit([
|
|
8620
|
+
factIdForTriple(row.subject, p, y),
|
|
8621
|
+
factIdForTriple(y, TYPE_PREDICATE, c),
|
|
8622
|
+
factIdForTriple(row.object, ON_PROPERTY_PREDICATE, rec.propertyKey),
|
|
8623
|
+
factIdForTriple(row.object, SOME_VALUES_FROM_PREDICATE, rec.target),
|
|
8624
|
+
...c !== rec.target ? [factIdForTriple(c, SUBCLASS_PREDICATE, rec.target)] : []
|
|
8625
|
+
]);
|
|
8626
|
+
}
|
|
8627
|
+
}
|
|
8628
|
+
}
|
|
8629
|
+
return out;
|
|
8630
|
+
}
|
|
8631
|
+
if (isDisjoint(row.predicate)) {
|
|
8632
|
+
const pairs = [];
|
|
8633
|
+
for (const c of typesOf.get(row.subject) || []) {
|
|
8634
|
+
for (const d of [c, ...ancestorsOf2(c)]) {
|
|
8635
|
+
if ((disjointOf.get(d) || /* @__PURE__ */ new Set()).has(row.object)) pairs.push([c, d]);
|
|
8636
|
+
}
|
|
8637
|
+
}
|
|
8638
|
+
pairs.sort((a, b) => a[0].localeCompare(b[0]) || a[1].localeCompare(b[1]));
|
|
8639
|
+
for (const [c, d] of pairs) {
|
|
8640
|
+
if (out.length >= maxEnvironments) break;
|
|
8641
|
+
const dwStoredForward = disjointForward.has(`${d}${SEP}${row.object}`);
|
|
8642
|
+
const [dwS, dwO] = dwStoredForward ? [d, row.object] : [row.object, d];
|
|
8643
|
+
admit([
|
|
8644
|
+
factIdForTriple(row.subject, TYPE_PREDICATE, c),
|
|
8645
|
+
factIdForTriple(dwS, DISJOINT_PREDICATE, dwO),
|
|
8646
|
+
...d !== c ? [factIdForTriple(c, SUBCLASS_PREDICATE, d)] : []
|
|
8647
|
+
]);
|
|
8648
|
+
}
|
|
8649
|
+
return out;
|
|
8650
|
+
}
|
|
8651
|
+
return out;
|
|
8652
|
+
};
|
|
8653
|
+
}
|
|
8654
|
+
function capMergeEnvironments(storedEnvs, discoveredEnvs, cap) {
|
|
8655
|
+
const kept = [];
|
|
8656
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8657
|
+
let truncated = false;
|
|
8658
|
+
for (const env of [...storedEnvs || [], ...discoveredEnvs || []]) {
|
|
8659
|
+
if (!Array.isArray(env) || !env.length) continue;
|
|
8660
|
+
const key = [...env].sort().join(" ");
|
|
8661
|
+
if (seen.has(key)) continue;
|
|
8662
|
+
if (kept.length >= cap) {
|
|
8663
|
+
truncated = true;
|
|
8664
|
+
continue;
|
|
8665
|
+
}
|
|
8666
|
+
seen.add(key);
|
|
8667
|
+
kept.push(env);
|
|
8668
|
+
}
|
|
8669
|
+
return { kept, truncated };
|
|
8670
|
+
}
|
|
8671
|
+
function bestEnvironmentTrustOpts(provenance, environments, trustOfId) {
|
|
8672
|
+
let ruleConfidence;
|
|
8673
|
+
for (const tag of String(provenance || "").split(" | ")) {
|
|
8674
|
+
const rc = ENTAILED_RULE_CONFIDENCE_BY_TAG.get(tag);
|
|
8675
|
+
if (rc !== void 0) {
|
|
8676
|
+
ruleConfidence = rc;
|
|
8677
|
+
break;
|
|
8678
|
+
}
|
|
8679
|
+
}
|
|
8680
|
+
if (ruleConfidence === void 0) return null;
|
|
8681
|
+
let best = null;
|
|
8682
|
+
let bestMin = -1;
|
|
8683
|
+
for (const env of environments || []) {
|
|
8684
|
+
const trusts = env.map((id) => trustOfId(id)).filter((t) => typeof t === "number");
|
|
8685
|
+
if (trusts.length !== env.length) continue;
|
|
8686
|
+
const weakest = Math.min(...trusts);
|
|
8687
|
+
if (weakest > bestMin) {
|
|
8688
|
+
bestMin = weakest;
|
|
8689
|
+
best = trusts;
|
|
8690
|
+
}
|
|
8691
|
+
}
|
|
8692
|
+
return best ? { premiseTrusts: best, ruleConfidence } : null;
|
|
8693
|
+
}
|
|
8694
|
+
async function retractSubClassOf(repoDir, subject, object, {
|
|
8695
|
+
budget = 50,
|
|
8696
|
+
depth = 32,
|
|
8697
|
+
maxEnvironments = DEFAULT_MAX_ENVIRONMENTS,
|
|
8698
|
+
store
|
|
8699
|
+
} = {}) {
|
|
8258
8700
|
const { loadMemory: loadMemory2, readFactRows: readFactRows2, removeFacts: removeFacts2 } = requireStore(store, ["loadMemory", "readFactRows", "removeFacts"], "retractSubClassOf");
|
|
8701
|
+
const appendFactsFn = typeof store?.appendFacts === "function" ? store.appendFacts : null;
|
|
8259
8702
|
const s = normFactTerm(subject);
|
|
8260
8703
|
const o = normFactTerm(object);
|
|
8261
8704
|
const targetId = factIdForTriple(s, SUBCLASS_PREDICATE, o);
|
|
@@ -8263,28 +8706,58 @@ ${bodyText}` : graphText, tier });
|
|
|
8263
8706
|
const rows = readFactRows2(memory);
|
|
8264
8707
|
const byId = new Map(rows.map((r) => [r.id, r]));
|
|
8265
8708
|
if (!byId.has(targetId)) return { retracted: [], count: 0, budget, depth, truncated: false, found: false };
|
|
8266
|
-
const entailedRows = rows.filter((r) => r.
|
|
8709
|
+
const entailedRows = rows.filter((r) => environmentsOf(r).length && isPurelyEntailed(r.provenance));
|
|
8710
|
+
const citedBy = /* @__PURE__ */ new Map();
|
|
8711
|
+
for (const r of entailedRows) {
|
|
8712
|
+
for (const env of environmentsOf(r)) {
|
|
8713
|
+
for (const premiseId of env) {
|
|
8714
|
+
if (!citedBy.has(premiseId)) citedBy.set(premiseId, /* @__PURE__ */ new Set());
|
|
8715
|
+
citedBy.get(premiseId).add(r.id);
|
|
8716
|
+
}
|
|
8717
|
+
}
|
|
8718
|
+
}
|
|
8267
8719
|
const removed = /* @__PURE__ */ new Set([targetId]);
|
|
8268
8720
|
const order = [targetId];
|
|
8721
|
+
const reground = /* @__PURE__ */ new Map();
|
|
8269
8722
|
let truncated = false;
|
|
8270
8723
|
let round2 = 0;
|
|
8724
|
+
let newlyRemoved = [targetId];
|
|
8271
8725
|
for (; round2 < depth; round2 += 1) {
|
|
8272
|
-
const
|
|
8726
|
+
const candidateIds = /* @__PURE__ */ new Set();
|
|
8727
|
+
for (const id of newlyRemoved) {
|
|
8728
|
+
for (const cited of citedBy.get(id) || []) {
|
|
8729
|
+
if (!removed.has(cited)) candidateIds.add(cited);
|
|
8730
|
+
}
|
|
8731
|
+
}
|
|
8732
|
+
const candidates = [...candidateIds].map((id) => byId.get(id)).sort((a, b) => a.subject.localeCompare(b.subject) || a.predicate.localeCompare(b.predicate) || a.object.localeCompare(b.object));
|
|
8273
8733
|
if (!candidates.length) break;
|
|
8274
|
-
const
|
|
8275
|
-
const
|
|
8276
|
-
|
|
8277
|
-
);
|
|
8734
|
+
const survivors = rows.filter((r) => !removed.has(r.id) && !candidateIds.has(r.id));
|
|
8735
|
+
const survivorIds = new Set(survivors.map((r) => r.id));
|
|
8736
|
+
const enumerateSupport = buildSupportEnumerator(survivors);
|
|
8737
|
+
const stillDerivable = buildSurvivorDerivabilityCheck(survivors);
|
|
8278
8738
|
let progressed = false;
|
|
8279
8739
|
let hitBudget = false;
|
|
8740
|
+
newlyRemoved = [];
|
|
8280
8741
|
for (const c of candidates) {
|
|
8281
8742
|
if (removed.size >= budget) {
|
|
8282
8743
|
hitBudget = true;
|
|
8283
8744
|
break;
|
|
8284
8745
|
}
|
|
8746
|
+
const environments = environmentsOf(c);
|
|
8747
|
+
const intact = environments.filter((env) => env.every((id) => survivorIds.has(id)));
|
|
8748
|
+
if (intact.length) {
|
|
8749
|
+
if (intact.length !== environments.length) reground.set(c.id, intact);
|
|
8750
|
+
continue;
|
|
8751
|
+
}
|
|
8752
|
+
const fresh = enumerateSupport(c, { maxEnvironments });
|
|
8753
|
+
if (fresh.length) {
|
|
8754
|
+
reground.set(c.id, fresh);
|
|
8755
|
+
continue;
|
|
8756
|
+
}
|
|
8285
8757
|
if (stillDerivable(c)) continue;
|
|
8286
8758
|
removed.add(c.id);
|
|
8287
8759
|
order.push(c.id);
|
|
8760
|
+
newlyRemoved.push(c.id);
|
|
8288
8761
|
progressed = true;
|
|
8289
8762
|
}
|
|
8290
8763
|
if (hitBudget) {
|
|
@@ -8297,6 +8770,20 @@ ${bodyText}` : graphText, tier });
|
|
|
8297
8770
|
truncated = entailedRows.some((r) => !removed.has(r.id) && r.justification.some((j) => removed.has(j)));
|
|
8298
8771
|
}
|
|
8299
8772
|
const { removed: actuallyRemoved } = await removeFacts2(repoDir, order);
|
|
8773
|
+
if (appendFactsFn) {
|
|
8774
|
+
const regroundWrites = [...reground.entries()].filter(([id]) => !removed.has(id)).sort((a, b) => a[0].localeCompare(b[0])).map(([id, environments]) => {
|
|
8775
|
+
const row = byId.get(id);
|
|
8776
|
+
return {
|
|
8777
|
+
subject: row.subject,
|
|
8778
|
+
predicate: row.predicate,
|
|
8779
|
+
object: row.object,
|
|
8780
|
+
// provenance omitted — appendFacts' first-write-wins keeps the union
|
|
8781
|
+
justification: environments,
|
|
8782
|
+
...bestEnvironmentTrustOpts(row.provenance, environments, (pid) => byId.get(pid)?.trust) || {}
|
|
8783
|
+
};
|
|
8784
|
+
});
|
|
8785
|
+
if (regroundWrites.length) await appendFactsFn(repoDir, regroundWrites);
|
|
8786
|
+
}
|
|
8300
8787
|
return { retracted: actuallyRemoved, count: actuallyRemoved.length, budget, depth, truncated, found: true };
|
|
8301
8788
|
}
|
|
8302
8789
|
function findIsaChain(subj, targets, typeEdges, subClassEdges, { maxHops = 6 } = {}) {
|
|
@@ -8331,7 +8818,7 @@ ${bodyText}` : graphText, tier });
|
|
|
8331
8818
|
}
|
|
8332
8819
|
return null;
|
|
8333
8820
|
}
|
|
8334
|
-
var SUBCLASS_PREDICATE, SYLLOGISE_RULE, ENTAILED_PROVENANCE, TYPE_PREDICATE, CAX_SCO_RULE, ENTAILED_TYPE_PROVENANCE, DISJOINT_PREDICATE, CAX_DW_RULE, ENTAILED_DISJOINT_PROVENANCE, CAX_DW_RULE_CONFIDENCE, ON_PROPERTY_PREDICATE, SOME_VALUES_FROM_PREDICATE, CLS_SVF1_RULE, ENTAILED_SVF1_PROVENANCE, CLS_SVF1_RULE_CONFIDENCE, SEP, isSubClassOf, isType, isDisjoint, isOnProperty, isSomeValuesFrom, isOnClass, RESERVED_PREDICATES, HAS_PROPERTY_KEY, CARDINALITY_KIND_OF, SCM_SVF_RULE, ENTAILED_SCM_SVF_PROVENANCE, SCM_SVF_RULE_CONFIDENCE, CARDINALITY_RULE_CONFIDENCE, CAX_MAXC0_RULE_CONFIDENCE;
|
|
8821
|
+
var SUBCLASS_PREDICATE, SYLLOGISE_RULE, ENTAILED_PROVENANCE, TYPE_PREDICATE, CAX_SCO_RULE, ENTAILED_TYPE_PROVENANCE, DISJOINT_PREDICATE, CAX_DW_RULE, ENTAILED_DISJOINT_PROVENANCE, CAX_DW_RULE_CONFIDENCE, ON_PROPERTY_PREDICATE, SOME_VALUES_FROM_PREDICATE, CLS_SVF1_RULE, ENTAILED_SVF1_PROVENANCE, CLS_SVF1_RULE_CONFIDENCE, DEFAULT_MAX_ENVIRONMENTS, SEP, isSubClassOf, isType, isDisjoint, isOnProperty, isSomeValuesFrom, isOnClass, RESERVED_PREDICATES, HAS_PROPERTY_KEY, CARDINALITY_KIND_OF, SCM_SVF_RULE, ENTAILED_SCM_SVF_PROVENANCE, SCM_SVF_RULE_CONFIDENCE, CARDINALITY_RULE_CONFIDENCE, CAX_MAXC0_RULE_CONFIDENCE, environmentsOf, ENTAILED_RULE_CONFIDENCE_BY_TAG;
|
|
8335
8822
|
var init_syllogise = __esm({
|
|
8336
8823
|
"src/domain/syllogise.mjs"() {
|
|
8337
8824
|
init_hash();
|
|
@@ -8350,6 +8837,7 @@ ${bodyText}` : graphText, tier });
|
|
|
8350
8837
|
CLS_SVF1_RULE = "someValuesFrom";
|
|
8351
8838
|
ENTAILED_SVF1_PROVENANCE = `entailed:${CLS_SVF1_RULE}`;
|
|
8352
8839
|
CLS_SVF1_RULE_CONFIDENCE = 0.95;
|
|
8840
|
+
DEFAULT_MAX_ENVIRONMENTS = 4;
|
|
8353
8841
|
SEP = "\u241F";
|
|
8354
8842
|
isSubClassOf = (p) => String(p || "").trim().toLowerCase() === "rdfs:subclassof";
|
|
8355
8843
|
isType = (p) => String(p || "").trim().toLowerCase() === "rdf:type";
|
|
@@ -8372,6 +8860,12 @@ ${bodyText}` : graphText, tier });
|
|
|
8372
8860
|
SCM_SVF_RULE_CONFIDENCE = 0.95;
|
|
8373
8861
|
CARDINALITY_RULE_CONFIDENCE = 0.95;
|
|
8374
8862
|
CAX_MAXC0_RULE_CONFIDENCE = 0.95;
|
|
8863
|
+
environmentsOf = (row) => row.environments || (Array.isArray(row.justification) && row.justification.length ? [row.justification] : []);
|
|
8864
|
+
ENTAILED_RULE_CONFIDENCE_BY_TAG = /* @__PURE__ */ new Map([
|
|
8865
|
+
[ENTAILED_DISJOINT_PROVENANCE, CAX_DW_RULE_CONFIDENCE],
|
|
8866
|
+
[ENTAILED_SVF1_PROVENANCE, CLS_SVF1_RULE_CONFIDENCE],
|
|
8867
|
+
[ENTAILED_SCM_SVF_PROVENANCE, SCM_SVF_RULE_CONFIDENCE]
|
|
8868
|
+
]);
|
|
8375
8869
|
}
|
|
8376
8870
|
});
|
|
8377
8871
|
|
|
@@ -8698,6 +9192,7 @@ ${bodyText}` : graphText, tier });
|
|
|
8698
9192
|
SOURCE_CLASS: () => SOURCE_CLASS,
|
|
8699
9193
|
SOURCE_RELIABILITY_PROP: () => SOURCE_RELIABILITY_PROP,
|
|
8700
9194
|
STATED_BY_PROP: () => STATED_BY_PROP,
|
|
9195
|
+
SYLLOGISE_STATE_REL: () => SYLLOGISE_STATE_REL,
|
|
8701
9196
|
UPDATED_AT_PROP: () => UPDATED_AT_PROP,
|
|
8702
9197
|
UTTERANCE_CLASS: () => UTTERANCE_CLASS,
|
|
8703
9198
|
appendFact: () => appendFact,
|
|
@@ -8714,6 +9209,7 @@ ${bodyText}` : graphText, tier });
|
|
|
8714
9209
|
findRuleByName: () => findRuleByName,
|
|
8715
9210
|
findRulesByName: () => findRulesByName,
|
|
8716
9211
|
loadMemory: () => loadMemory,
|
|
9212
|
+
loadSyllogiseState: () => loadSyllogiseState,
|
|
8717
9213
|
normFactPredicate: () => normFactPredicate,
|
|
8718
9214
|
normFactTerm: () => normFactTerm,
|
|
8719
9215
|
openMemoryBackend: () => openMemoryBackend,
|
|
@@ -8725,6 +9221,7 @@ ${bodyText}` : graphText, tier });
|
|
|
8725
9221
|
resolveMemoryGraphFile: () => resolveMemoryGraphFile,
|
|
8726
9222
|
resolveRelationChase: () => resolveRelationChase,
|
|
8727
9223
|
resolveRelationChaseReverse: () => resolveRelationChaseReverse,
|
|
9224
|
+
saveSyllogiseState: () => saveSyllogiseState,
|
|
8728
9225
|
snapshotMemory: () => snapshotMemory
|
|
8729
9226
|
});
|
|
8730
9227
|
function emptyMemory() {
|
|
@@ -9035,7 +9532,9 @@ ${bodyText}` : graphText, tier });
|
|
|
9035
9532
|
for (const ind of payload.individuals) {
|
|
9036
9533
|
if (Array.isArray(ind?.derived_from) && ind.derived_from.length) ind.derived_from = ind.derived_from.map(remapId);
|
|
9037
9534
|
const just = (ind?.attributes || []).find((a) => a?.prop === "mgx:factJustification");
|
|
9038
|
-
if (just?.value)
|
|
9535
|
+
if (just?.value) {
|
|
9536
|
+
just.value = just.value.split(" | ").map((env) => env.split(" ").filter(Boolean).map(remapId).join(" ")).filter(Boolean).join(" | ");
|
|
9537
|
+
}
|
|
9039
9538
|
}
|
|
9040
9539
|
return payload;
|
|
9041
9540
|
}
|
|
@@ -9051,6 +9550,32 @@ ${bodyText}` : graphText, tier });
|
|
|
9051
9550
|
await mkdir2(dirname(memoryGraphFile(dir)), { recursive: true });
|
|
9052
9551
|
await atomicWriteJson(memoryGraphFile(dir), payload);
|
|
9053
9552
|
}
|
|
9553
|
+
async function loadSyllogiseState(dir) {
|
|
9554
|
+
if (isMemoryHandle(dir)) return dir.syllogiseState ? structuredClone(dir.syllogiseState) : null;
|
|
9555
|
+
if (isSqliteHandle(dir)) {
|
|
9556
|
+
const row = dir.db.prepare("SELECT v FROM meta WHERE k = ?").get(SQLITE_SYLLOGISE_STATE_KEY);
|
|
9557
|
+
return row?.v ? JSON.parse(row.v) : null;
|
|
9558
|
+
}
|
|
9559
|
+
try {
|
|
9560
|
+
return JSON.parse(await readFile2(join(dir, SYLLOGISE_STATE_REL), "utf8"));
|
|
9561
|
+
} catch (e) {
|
|
9562
|
+
if (e?.code === "ENOENT") return null;
|
|
9563
|
+
throw e;
|
|
9564
|
+
}
|
|
9565
|
+
}
|
|
9566
|
+
async function saveSyllogiseState(dir, state) {
|
|
9567
|
+
if (isMemoryHandle(dir)) {
|
|
9568
|
+
dir.syllogiseState = structuredClone(state);
|
|
9569
|
+
return;
|
|
9570
|
+
}
|
|
9571
|
+
if (isSqliteHandle(dir)) {
|
|
9572
|
+
dir.db.prepare("INSERT OR REPLACE INTO meta(k, v) VALUES (?, ?)").run(SQLITE_SYLLOGISE_STATE_KEY, JSON.stringify(state));
|
|
9573
|
+
return;
|
|
9574
|
+
}
|
|
9575
|
+
const file = join(dir, SYLLOGISE_STATE_REL);
|
|
9576
|
+
await mkdir2(dirname(file), { recursive: true });
|
|
9577
|
+
await atomicWriteJson(file, state);
|
|
9578
|
+
}
|
|
9054
9579
|
function buildMemoryIndex(payload) {
|
|
9055
9580
|
const individualsById = /* @__PURE__ */ new Map();
|
|
9056
9581
|
const sourcesById = /* @__PURE__ */ new Map();
|
|
@@ -9097,6 +9622,10 @@ ${bodyText}` : graphText, tier });
|
|
|
9097
9622
|
return { id: `src:provider:${desc.name}`, type: "provider" };
|
|
9098
9623
|
case "corpus":
|
|
9099
9624
|
return { id: `src:corpus:${desc.name}`, type: "corpus" };
|
|
9625
|
+
// One Source per pack article (the @revid stays in the article segment),
|
|
9626
|
+
// so two facts from the same article corroborate nothing extra.
|
|
9627
|
+
case "reference":
|
|
9628
|
+
return { id: `src:reference:${desc.pack}:${desc.article}`, type: "reference" };
|
|
9100
9629
|
// One Source per source-file basename, not per extraction run.
|
|
9101
9630
|
case "extracted":
|
|
9102
9631
|
return { id: `src:extracted:${desc.name}`, type: "extracted" };
|
|
@@ -9407,6 +9936,21 @@ ${bodyText}` : graphText, tier });
|
|
|
9407
9936
|
});
|
|
9408
9937
|
return { id };
|
|
9409
9938
|
}
|
|
9939
|
+
function normalizeJustificationEnvironments(justification) {
|
|
9940
|
+
if (!Array.isArray(justification)) return void 0;
|
|
9941
|
+
const rawEnvs = justification.some(Array.isArray) ? justification.filter(Array.isArray) : [justification];
|
|
9942
|
+
const envs = [];
|
|
9943
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9944
|
+
for (const raw of rawEnvs) {
|
|
9945
|
+
const env = raw.filter((id) => typeof id === "string" && id);
|
|
9946
|
+
if (!env.length) continue;
|
|
9947
|
+
const key = [...env].sort().join(" ");
|
|
9948
|
+
if (seen.has(key)) continue;
|
|
9949
|
+
seen.add(key);
|
|
9950
|
+
envs.push(env);
|
|
9951
|
+
}
|
|
9952
|
+
return envs.length ? envs : void 0;
|
|
9953
|
+
}
|
|
9410
9954
|
async function appendFacts(dir, facts) {
|
|
9411
9955
|
const prepared = [];
|
|
9412
9956
|
let skipped = 0;
|
|
@@ -9432,7 +9976,7 @@ ${bodyText}` : graphText, tier });
|
|
|
9432
9976
|
quantifier: normText(f?.quantifier),
|
|
9433
9977
|
premiseTrusts: Array.isArray(f?.premiseTrusts) ? f.premiseTrusts : void 0,
|
|
9434
9978
|
ruleConfidence: typeof f?.ruleConfidence === "number" ? f.ruleConfidence : void 0,
|
|
9435
|
-
|
|
9979
|
+
environments: normalizeJustificationEnvironments(f?.justification)
|
|
9436
9980
|
});
|
|
9437
9981
|
}
|
|
9438
9982
|
const ids = [];
|
|
@@ -9465,7 +10009,7 @@ ${bodyText}` : graphText, tier });
|
|
|
9465
10009
|
...provs.length ? [{ prop: "mgx:factProvenance", key: "provenance", value: provs.join(" | ") }] : [],
|
|
9466
10010
|
...f.tokens.length ? [{ prop: "mgx:hasProseTokens", key: "prose_tokens", value: f.tokens.join(" ") }] : [],
|
|
9467
10011
|
...qVal ? [{ prop: "mgx:factQuantifier", key: "quantifier", value: qVal }] : [],
|
|
9468
|
-
...f.
|
|
10012
|
+
...f.environments ? [{ prop: "mgx:factJustification", key: "justification", value: f.environments.map((e) => e.join(" ")).join(" | ") }] : []
|
|
9469
10013
|
]
|
|
9470
10014
|
};
|
|
9471
10015
|
const stored = upsertIndividual(payload, ind);
|
|
@@ -9700,6 +10244,22 @@ ${bodyText}` : graphText, tier });
|
|
|
9700
10244
|
const sourceIds = byFact.get(ind.id) || [];
|
|
9701
10245
|
const sourceTypes = sourceIds.map((id) => (sourcesById.get(id)?.attributes || []).find((a) => a?.prop === "mgx:sourceType")?.value).filter(Boolean);
|
|
9702
10246
|
const justificationRaw = get("justification");
|
|
10247
|
+
const environments = [];
|
|
10248
|
+
if (justificationRaw) {
|
|
10249
|
+
for (const chunk of justificationRaw.split(" | ")) {
|
|
10250
|
+
const env = chunk.split(" ").filter(Boolean);
|
|
10251
|
+
if (env.length) environments.push(env);
|
|
10252
|
+
}
|
|
10253
|
+
}
|
|
10254
|
+
const justification = [];
|
|
10255
|
+
const seenPremise = /* @__PURE__ */ new Set();
|
|
10256
|
+
for (const env of environments) {
|
|
10257
|
+
for (const id of env) {
|
|
10258
|
+
if (seenPremise.has(id)) continue;
|
|
10259
|
+
seenPremise.add(id);
|
|
10260
|
+
justification.push(id);
|
|
10261
|
+
}
|
|
10262
|
+
}
|
|
9703
10263
|
rows.push({
|
|
9704
10264
|
id: ind.id,
|
|
9705
10265
|
subject: get("subject"),
|
|
@@ -9712,9 +10272,11 @@ ${bodyText}` : graphText, tier });
|
|
|
9712
10272
|
sourceIds,
|
|
9713
10273
|
sourceTypes,
|
|
9714
10274
|
trust: Number((ind.attributes || []).find((a) => a?.prop === TRUST_SCORE_PROP)?.value) || 0,
|
|
9715
|
-
//
|
|
9716
|
-
//
|
|
9717
|
-
|
|
10275
|
+
// `environments`: every persisted premise set (empty unless entailed);
|
|
10276
|
+
// `justification`: their deduped union in first-occurrence order, for
|
|
10277
|
+
// readers that only need "which premises does this fact cite at all".
|
|
10278
|
+
environments,
|
|
10279
|
+
justification
|
|
9718
10280
|
});
|
|
9719
10281
|
}
|
|
9720
10282
|
return rows;
|
|
@@ -9759,7 +10321,7 @@ ${bodyText}` : graphText, tier });
|
|
|
9759
10321
|
}
|
|
9760
10322
|
return out.sort((a, b) => `${a[0].subject} ${a[0].predicate}`.localeCompare(`${b[0].subject} ${b[0].predicate}`));
|
|
9761
10323
|
}
|
|
9762
|
-
var MEMORY_DIR_REL, MEMORY_GRAPH_REL, UTTERANCE_CLASS, FACT_CLASS, MEMORY_SESSION_CLASS, SOURCE_CLASS, RULE_CLASS, SAID_IN_SESSION_PROP, IN_REPLY_TO_PROP, DERIVED_FROM_PROP, STATED_BY_PROP, CANONICALISED_FROM_PROP, SOURCE_RELIABILITY_PROP, OPERATOR_SOURCE_ID, TEACH_SOURCE_ID, ROLES, LABEL_CAP, MEMORY_VOCABULARY, memoryGraphFile, BACKEND_MEMORY, BACKEND_SQLITE, SQLITE_DDL, STD_EDGE_KEYS, cloneJson, MEMORY_MANIFEST_REL, DEFAULT_RETENTION, resolveManifestFile, LEGACY_FACT_ID_RE, MEMORY_INDEX, memoryIndexOf, labelOf, nowIso, sourceLabel, PROV_CLASS_BY_SOURCE_TYPE, isSessionScopedSourceId, RULE_KIND_COMPOSE2, RULE_KIND_FILTER, RULE_KIND_RECURSIVE, RULE_KIND_ACTION_SIGNATURE, RULE_KIND_ACTION_PRECOND, RULE_KIND_ACTION_EFFECT, RULE_KIND_ACTION_CONSTRAINT, RULE_KINDS2, RULE_NAME_PROP, RULE_KIND_PROP, RULE_SLOT_SPEC, ruleIdFor, CONTRADICTION_TRUST_FLOOR, HAS_A_PREDICATE, CAPABLE_OF_PREDICATE2, MULTI_VALUED_PREDICATES;
|
|
10324
|
+
var MEMORY_DIR_REL, MEMORY_GRAPH_REL, UTTERANCE_CLASS, FACT_CLASS, MEMORY_SESSION_CLASS, SOURCE_CLASS, RULE_CLASS, SAID_IN_SESSION_PROP, IN_REPLY_TO_PROP, DERIVED_FROM_PROP, STATED_BY_PROP, CANONICALISED_FROM_PROP, SOURCE_RELIABILITY_PROP, OPERATOR_SOURCE_ID, TEACH_SOURCE_ID, ROLES, LABEL_CAP, MEMORY_VOCABULARY, memoryGraphFile, BACKEND_MEMORY, BACKEND_SQLITE, SQLITE_DDL, STD_EDGE_KEYS, cloneJson, MEMORY_MANIFEST_REL, DEFAULT_RETENTION, resolveManifestFile, LEGACY_FACT_ID_RE, SYLLOGISE_STATE_REL, SQLITE_SYLLOGISE_STATE_KEY, MEMORY_INDEX, memoryIndexOf, labelOf, nowIso, sourceLabel, PROV_CLASS_BY_SOURCE_TYPE, isSessionScopedSourceId, RULE_KIND_COMPOSE2, RULE_KIND_FILTER, RULE_KIND_RECURSIVE, RULE_KIND_ACTION_SIGNATURE, RULE_KIND_ACTION_PRECOND, RULE_KIND_ACTION_EFFECT, RULE_KIND_ACTION_CONSTRAINT, RULE_KINDS2, RULE_NAME_PROP, RULE_KIND_PROP, RULE_SLOT_SPEC, ruleIdFor, CONTRADICTION_TRUST_FLOOR, HAS_A_PREDICATE, CAPABLE_OF_PREDICATE2, MULTI_VALUED_PREDICATES;
|
|
9763
10325
|
var init_core = __esm({
|
|
9764
10326
|
"src/adapters/memory/core.mjs"() {
|
|
9765
10327
|
init_promises();
|
|
@@ -9801,6 +10363,7 @@ ${bodyText}` : graphText, tier });
|
|
|
9801
10363
|
{ prop: "rdf:object", note: "reified fact: the triple's object term" },
|
|
9802
10364
|
{ prop: "mgx:factProvenance", note: "LEGACY COMPAT SHIM: the ' | '-joined provenance tag string a fact came from; the source-of-truth is now the mgx:statedBy edges derived from it" },
|
|
9803
10365
|
{ prop: "mgx:factQuantifier", note: "OPTIONAL: the quantifier word a plural class-membership teach used ('every'/'some'/'a few'), for literal recall by 'how many Xs are Ys' \u2014 never real cardinality counting" },
|
|
10366
|
+
{ prop: "mgx:factJustification", note: "an entailed Fact's supporting premise fact ids: ' | '-separated environments, one space-separated premise-id list per independent derivation, capped by syllogise's maxEnvironments knob; a value with no ' | ' is a single environment" },
|
|
9804
10367
|
{ prop: "mgx:ruleName", note: "a taught Rule's own name (e.g. 'grandparent') \u2014 the query-dispatcher's lookup key, PLAN_TAUGHT_RELATIONS.md \xA72/\xA73" },
|
|
9805
10368
|
{ prop: "mgx:ruleKind", note: "a taught Rule's SHAPE tag \u2014 the closed vocabulary compose2 | filter | recursive (structural, like 'Fact'/'Rule' themselves, never a domain word)" },
|
|
9806
10369
|
{ prop: "mgx:ruleBase1", note: "compose2: the first hop's base relation name; filter: the base rule/relation being filtered (same 'base relation' role in both kinds, so the name is shared)" },
|
|
@@ -9813,7 +10376,7 @@ ${bodyText}` : graphText, tier });
|
|
|
9813
10376
|
{ prop: DERIVED_FROM_PROP, predicate: "derivedFrom", note: "umbrella: a Fact derived from a Source (or another Fact). ext ref prov:wasDerivedFrom (UNVERIFIED-pending-web-check)" },
|
|
9814
10377
|
{ prop: STATED_BY_PROP, predicate: "statedBy", note: "subPropertyOf derivedFrom: a Source directly asserts this Fact (one edge per independent source \u2014 replaces the factProvenance union)" },
|
|
9815
10378
|
{ prop: CANONICALISED_FROM_PROP, predicate: "canonicalisedFrom", note: "subPropertyOf derivedFrom: a canonical Fact cleaned from a raw Block/Source, never replacing it" },
|
|
9816
|
-
{ prop: "mgx:sourceType", note: "a Source's kind: operator | teach | provider | corpus | corpusWeak | extracted | web | entailed (the trust-prior key)" },
|
|
10379
|
+
{ prop: "mgx:sourceType", note: "a Source's kind: operator | teach | provider | corpus | corpusWeak | reference | extracted | web | entailed (the trust-prior key)" },
|
|
9817
10380
|
{ prop: "mgx:sourceUrl", note: "a web Source's URL" },
|
|
9818
10381
|
{ prop: "mgx:sourceRule", note: "an entailed Source's rule id" },
|
|
9819
10382
|
{ prop: "mgx:sourceReliability", note: "actor-level (session-scoped) trust nudge in [0.5,1.5], neutral 1.0 when absent \u2014 materialised by recomputeSourceReliability from a session's asserted-vs-contradicted track record (memory/trust.mjs's sessionReliabilityFrom); folds into computeTrust's per-source prior" },
|
|
@@ -9839,6 +10402,8 @@ CREATE INDEX IF NOT EXISTS edges_by_prop ON edges(prop);
|
|
|
9839
10402
|
DEFAULT_RETENTION = 5;
|
|
9840
10403
|
resolveManifestFile = (dir) => join(dir, MEMORY_MANIFEST_REL);
|
|
9841
10404
|
LEGACY_FACT_ID_RE = /^fact:[0-9a-f]{8}$/;
|
|
10405
|
+
SYLLOGISE_STATE_REL = join(MEMORY_DIR_REL, "syllogise-state.json");
|
|
10406
|
+
SQLITE_SYLLOGISE_STATE_KEY = "syllogiseState";
|
|
9842
10407
|
MEMORY_INDEX = /* @__PURE__ */ Symbol("mutateMemory lookup index");
|
|
9843
10408
|
memoryIndexOf = (payload) => payload?.[MEMORY_INDEX] || null;
|
|
9844
10409
|
labelOf = (text) => text.length > LABEL_CAP ? text.slice(0, LABEL_CAP - 1) + "\u2026" : text;
|
|
@@ -9850,6 +10415,7 @@ CREATE INDEX IF NOT EXISTS edges_by_prop ON edges(prop);
|
|
|
9850
10415
|
provider: { subClass: "tmct:AgentSource", prov: "prov:Agent" },
|
|
9851
10416
|
corpus: { subClass: "tmct:DocumentSource", prov: "prov:Entity" },
|
|
9852
10417
|
corpusWeak: { subClass: "tmct:DocumentSource", prov: "prov:Entity" },
|
|
10418
|
+
reference: { subClass: "tmct:DocumentSource", prov: "prov:Entity" },
|
|
9853
10419
|
web: { subClass: "tmct:DocumentSource", prov: "prov:Entity" },
|
|
9854
10420
|
extracted: { subClass: "tmct:DocumentSource", prov: "prov:Entity" },
|
|
9855
10421
|
entailed: { subClass: "tmct:ActivitySource", prov: "prov:Activity" }
|
|
@@ -21187,6 +21753,19 @@ ${codeblock}`, options);
|
|
|
21187
21753
|
inputSchema: classArg("The class to walk the inheritance edges of."),
|
|
21188
21754
|
example: { class: "Field" }
|
|
21189
21755
|
},
|
|
21756
|
+
{
|
|
21757
|
+
name: "tmct_related",
|
|
21758
|
+
tier: "cold",
|
|
21759
|
+
summary: "A term's synonyms (skos:altLabel) and related concepts (skos:related), from the memory graph's relation facts.",
|
|
21760
|
+
inputSchema: {
|
|
21761
|
+
type: "object",
|
|
21762
|
+
required: ["term"],
|
|
21763
|
+
properties: {
|
|
21764
|
+
term: { type: "string", description: "The term whose synonyms / related concepts you want." }
|
|
21765
|
+
}
|
|
21766
|
+
},
|
|
21767
|
+
example: { term: "sofa" }
|
|
21768
|
+
},
|
|
21190
21769
|
{
|
|
21191
21770
|
name: "tmct_architecture",
|
|
21192
21771
|
tier: "cold",
|
|
@@ -21770,6 +22349,110 @@ ${hint}` : ""}${cand}`;
|
|
|
21770
22349
|
resolveOrThrow(svc, symbol, "class");
|
|
21771
22350
|
}
|
|
21772
22351
|
|
|
22352
|
+
// src/tools/handlers/tmct-related.mjs
|
|
22353
|
+
init_config();
|
|
22354
|
+
|
|
22355
|
+
// src/domain/skos-view.mjs
|
|
22356
|
+
init_hash();
|
|
22357
|
+
var SKOS_NS = "http://www.w3.org/2004/02/skos/core#";
|
|
22358
|
+
var DEFAULT_RELATION_MAP = {
|
|
22359
|
+
synonym: ["mgx:synonym"],
|
|
22360
|
+
related: ["mgx:relatedTo", "mgx:similarTo"]
|
|
22361
|
+
};
|
|
22362
|
+
function buildSkosConceptView(rows, { conceptBase = "concept:", relationMap = DEFAULT_RELATION_MAP } = {}) {
|
|
22363
|
+
const synonymPreds = new Set(relationMap.synonym || []);
|
|
22364
|
+
const relatedPreds = new Set(relationMap.related || []);
|
|
22365
|
+
const parent = /* @__PURE__ */ new Map();
|
|
22366
|
+
const ensure = (t) => {
|
|
22367
|
+
if (!parent.has(t)) parent.set(t, t);
|
|
22368
|
+
};
|
|
22369
|
+
const find = (x) => {
|
|
22370
|
+
let r = x;
|
|
22371
|
+
while (parent.get(r) !== r) r = parent.get(r);
|
|
22372
|
+
while (parent.get(x) !== r) {
|
|
22373
|
+
const next = parent.get(x);
|
|
22374
|
+
parent.set(x, r);
|
|
22375
|
+
x = next;
|
|
22376
|
+
}
|
|
22377
|
+
return r;
|
|
22378
|
+
};
|
|
22379
|
+
const union = (a, b) => {
|
|
22380
|
+
const ra = find(a), rb = find(b);
|
|
22381
|
+
if (ra === rb) return;
|
|
22382
|
+
if (ra < rb) parent.set(rb, ra);
|
|
22383
|
+
else parent.set(ra, rb);
|
|
22384
|
+
};
|
|
22385
|
+
const relatedRaw = [];
|
|
22386
|
+
for (const r of rows) {
|
|
22387
|
+
const p = r.predicate;
|
|
22388
|
+
if (!synonymPreds.has(p) && !relatedPreds.has(p)) continue;
|
|
22389
|
+
const s = normFactTerm(r.subject), o = normFactTerm(r.object);
|
|
22390
|
+
if (!s || !o) continue;
|
|
22391
|
+
ensure(s);
|
|
22392
|
+
ensure(o);
|
|
22393
|
+
if (synonymPreds.has(p)) union(s, o);
|
|
22394
|
+
else relatedRaw.push({ s, o });
|
|
22395
|
+
}
|
|
22396
|
+
const iriFor = (rep) => conceptBase + rep.replace(/ /g, "_");
|
|
22397
|
+
const componentTerms = /* @__PURE__ */ new Map();
|
|
22398
|
+
for (const t of parent.keys()) {
|
|
22399
|
+
const rep = find(t);
|
|
22400
|
+
if (!componentTerms.has(rep)) componentTerms.set(rep, /* @__PURE__ */ new Set());
|
|
22401
|
+
componentTerms.get(rep).add(t);
|
|
22402
|
+
}
|
|
22403
|
+
const concepts = [];
|
|
22404
|
+
for (const [rep, terms] of componentTerms) {
|
|
22405
|
+
const sorted = [...terms].sort();
|
|
22406
|
+
concepts.push({ id: iriFor(rep), prefLabel: rep, altLabels: sorted.filter((t) => t !== rep) });
|
|
22407
|
+
}
|
|
22408
|
+
concepts.sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
|
|
22409
|
+
const seen = /* @__PURE__ */ new Set();
|
|
22410
|
+
const related = [];
|
|
22411
|
+
for (const { s, o } of relatedRaw) {
|
|
22412
|
+
const cs = iriFor(find(s)), co = iriFor(find(o));
|
|
22413
|
+
if (cs === co) continue;
|
|
22414
|
+
const key = cs < co ? `${cs}\0${co}` : `${co}\0${cs}`;
|
|
22415
|
+
if (seen.has(key)) continue;
|
|
22416
|
+
seen.add(key);
|
|
22417
|
+
related.push({ subject: cs, object: co });
|
|
22418
|
+
}
|
|
22419
|
+
related.sort((a, b) => `${a.subject}${a.object}` < `${b.subject}${b.object}` ? -1 : 1);
|
|
22420
|
+
const conceptIdForTerm = (term) => {
|
|
22421
|
+
const t = normFactTerm(term);
|
|
22422
|
+
return parent.has(t) ? iriFor(find(t)) : null;
|
|
22423
|
+
};
|
|
22424
|
+
return { concepts, related, conceptIdForTerm, namespace: SKOS_NS };
|
|
22425
|
+
}
|
|
22426
|
+
function relatedForTerm(rows, term, options = {}) {
|
|
22427
|
+
const view = buildSkosConceptView(rows, options);
|
|
22428
|
+
const conceptId = view.conceptIdForTerm(term);
|
|
22429
|
+
if (!conceptId) return null;
|
|
22430
|
+
const byId = new Map(view.concepts.map((c) => [c.id, c]));
|
|
22431
|
+
const concept = byId.get(conceptId);
|
|
22432
|
+
const queried = normFactTerm(term);
|
|
22433
|
+
const synonyms = [concept.prefLabel, ...concept.altLabels].filter((label) => label !== queried);
|
|
22434
|
+
const related = view.related.filter((r) => r.subject === conceptId || r.object === conceptId).map((r) => byId.get(r.subject === conceptId ? r.object : r.subject)).filter(Boolean);
|
|
22435
|
+
return { conceptId, prefLabel: concept.prefLabel, altLabels: concept.altLabels, synonyms, related };
|
|
22436
|
+
}
|
|
22437
|
+
|
|
22438
|
+
// src/tools/handlers/tmct-related.mjs
|
|
22439
|
+
init_memory_fallthrough();
|
|
22440
|
+
async function tmct_related(args, { config }) {
|
|
22441
|
+
const term = requiredArg(args, "term");
|
|
22442
|
+
const hit2 = relatedForTerm(await memoryFactRows(config), term);
|
|
22443
|
+
if (!hit2) {
|
|
22444
|
+
throw new ToolError(
|
|
22445
|
+
`no synonym or related facts for "${term}" in the memory graph. This view answers where the store holds mgx:synonym / mgx:relatedTo facts (a corpus import seeds them).`
|
|
22446
|
+
);
|
|
22447
|
+
}
|
|
22448
|
+
const lines = [`${hit2.prefLabel} [${hit2.conceptId}]`];
|
|
22449
|
+
if (hit2.synonyms.length) lines.push(`synonyms (skos:altLabel): ${hit2.synonyms.join(", ")}`);
|
|
22450
|
+
if (hit2.related.length) lines.push(`related (skos:related): ${hit2.related.map((c) => c.prefLabel).join(", ")}`);
|
|
22451
|
+
lines.push("(from the memory graph's mgx:synonym / mgx:relatedTo / mgx:similarTo facts)");
|
|
22452
|
+
return lines.join("\n");
|
|
22453
|
+
}
|
|
22454
|
+
tmct_related.ownsGraphLoad = true;
|
|
22455
|
+
|
|
21773
22456
|
// src/tools/handlers/tmct-architecture.mjs
|
|
21774
22457
|
init_codegraph();
|
|
21775
22458
|
function tmct_architecture(args, { graph }) {
|
|
@@ -21847,6 +22530,7 @@ ${JSON.stringify(envelope, null, 2)}`;
|
|
|
21847
22530
|
tmct_search,
|
|
21848
22531
|
tmct_members,
|
|
21849
22532
|
tmct_subclasses,
|
|
22533
|
+
tmct_related,
|
|
21850
22534
|
tmct_architecture,
|
|
21851
22535
|
tmct_exports,
|
|
21852
22536
|
tmct_untested,
|
|
@@ -22326,7 +23010,15 @@ ${JSON.stringify(envelope, null, 2)}`;
|
|
|
22326
23010
|
"i"
|
|
22327
23011
|
);
|
|
22328
23012
|
var GOAL_TEACH_IMPERATIVE_RE = new RegExp(
|
|
22329
|
-
`^(?:get|put|place)\\s+(?:(every|each|all|both)\\s+)?(?:the\\s+)?([\\w-]+?)\\s+(${PREP_SRC})\\s+([\\w-]+)[?.!]*$`,
|
|
23013
|
+
`^(?:get|put|place|stack)\\s+(?:(every|each|all|both)\\s+)?(?:the\\s+)?([\\w-]+?)\\s+(${PREP_SRC})\\s+([\\w-]+)[?.!]*$`,
|
|
23014
|
+
"i"
|
|
23015
|
+
);
|
|
23016
|
+
var GOAL_TEACH_NP_RE = new RegExp(
|
|
23017
|
+
`^the\\s+goal\\s+is\\s+(?:(every|each|all|both)\\s+)?(?:the\\s+)?([\\w-]+?)\\s+(${PREP_SRC})\\s+([\\w-]+)[?.!]*$`,
|
|
23018
|
+
"i"
|
|
23019
|
+
);
|
|
23020
|
+
var GOAL_CONJUNCT_RE = new RegExp(
|
|
23021
|
+
`^(?:(every|each|all)\\s+)?([\\w-]+)\\s+([a-z]+s)\\s+(${PREP_SRC})\\s+([\\w-]+)$`,
|
|
22330
23022
|
"i"
|
|
22331
23023
|
);
|
|
22332
23024
|
var BOARD_REVERSE_LOC_RE = new RegExp(
|
|
@@ -22533,6 +23225,13 @@ ${JSON.stringify(envelope, null, 2)}`;
|
|
|
22533
23225
|
if (hit2) return { text: `yes \u2014 ${renderFactLine(hit2)}`, replace: true };
|
|
22534
23226
|
return null;
|
|
22535
23227
|
}
|
|
23228
|
+
function isaInconsistencyRefusal(posFact, disjointFact) {
|
|
23229
|
+
const cite = (f) => `${factPhrase(f)}${f.provenance ? ` (source: ${f.provenance})` : ""}`;
|
|
23230
|
+
return {
|
|
23231
|
+
text: `you've told me both ${cite(posFact)} and ${cite(disjointFact)} \u2014 together those contradict, and I won't derive an answer from an inconsistency. To settle it, say "forget that ${posFact.subject} is ${indefiniteArticleFor(posFact.object)} ${posFact.object}".`,
|
|
23232
|
+
replace: true
|
|
23233
|
+
};
|
|
23234
|
+
}
|
|
22536
23235
|
function renderIsaChain(premises) {
|
|
22537
23236
|
const step = (f) => `${factPhrase(f)}${f.provenance ? ` (source: ${f.provenance})` : ""}`;
|
|
22538
23237
|
const first = premises[0];
|
|
@@ -22588,6 +23287,12 @@ ${JSON.stringify(envelope, null, 2)}`;
|
|
|
22588
23287
|
return raw;
|
|
22589
23288
|
}
|
|
22590
23289
|
}
|
|
23290
|
+
function suggestibleSubjectPhrase(subject) {
|
|
23291
|
+
const m = String(subject || "").trim().match(/^(?:all|every|each|both|most|some)\s+([\w-]+)$/i);
|
|
23292
|
+
if (!m) return teachableSubjectOf(subject);
|
|
23293
|
+
const singular = teachableSubjectOf(singularizeSurface(m[1]));
|
|
23294
|
+
return `${indefiniteArticleFor(singular)} ${singular}`;
|
|
23295
|
+
}
|
|
22591
23296
|
var QUANTIFIER_LEAD_RE = /^(?:every|each|all|any)\s+/i;
|
|
22592
23297
|
function factTermVariants(normFactTerm2, term) {
|
|
22593
23298
|
const t = normFactTerm2(term);
|
|
@@ -23067,8 +23772,13 @@ ${shown.map(renderFactLine).join("\n")}`,
|
|
|
23067
23772
|
if (isa) {
|
|
23068
23773
|
const subj = factTermVariants(normFactTerm2, isa[1]);
|
|
23069
23774
|
const obj = factTermVariants(normFactTerm2, isa[2]);
|
|
23070
|
-
const isaRows = await
|
|
23775
|
+
const isaRows = await factRows(memoryDir, cache2);
|
|
23071
23776
|
const onTerms = (f) => subj.has(f.subject) && obj.has(f.object);
|
|
23777
|
+
const { DISJOINT_PREDICATE: DISJOINT_PREDICATE2 } = await Promise.resolve().then(() => (init_syllogise(), syllogise_exports));
|
|
23778
|
+
const touchesAskedTerm = (f) => subj.has(f.subject) || subj.has(f.object) || obj.has(f.subject) || obj.has(f.object);
|
|
23779
|
+
if (isaRows.some((f) => f.predicate === DISJOINT_PREDICATE2 && isOperatorTaught(f) && touchesAskedTerm(f))) {
|
|
23780
|
+
return null;
|
|
23781
|
+
}
|
|
23072
23782
|
const reply = isaPolarityReply(
|
|
23073
23783
|
isaRows.find((f) => ISA_PREDICATES2.has(f.predicate) && onTerms(f)),
|
|
23074
23784
|
isaRows.find((f) => f.predicate === NEG_SUBCLASS_PREDICATE && onTerms(f))
|
|
@@ -23096,10 +23806,20 @@ ${shown.map(renderFactLine).join("\n")}`,
|
|
|
23096
23806
|
if (doesHave) {
|
|
23097
23807
|
const subj = factTermVariants(normFactTerm2, doesHave[1]);
|
|
23098
23808
|
const obj = factTermVariants(normFactTerm2, doesHave[2]);
|
|
23099
|
-
const
|
|
23100
|
-
|
|
23809
|
+
const HAS_PREDICATES = /* @__PURE__ */ new Set(["mgx:hasA", "tmct:has"]);
|
|
23810
|
+
const facts = await memoryFacts(memoryDir);
|
|
23811
|
+
const hasHit = (subjectSet) => facts.find(
|
|
23812
|
+
(f) => HAS_PREDICATES.has(f.predicate) && subjectSet.has(f.subject) && obj.has(f.object)
|
|
23101
23813
|
);
|
|
23814
|
+
const hit2 = hasHit(subj);
|
|
23102
23815
|
if (hit2) return { text: `yes \u2014 ${renderFactLine(hit2)}`, replace: true };
|
|
23816
|
+
const isaStep = facts.find((f) => ISA_PREDICATES2.has(f.predicate) && subj.has(f.subject));
|
|
23817
|
+
if (isaStep) {
|
|
23818
|
+
const lifted = hasHit(factTermVariants(normFactTerm2, isaStep.object));
|
|
23819
|
+
if (lifted) {
|
|
23820
|
+
return { text: `yes \u2014 ${renderFactLine(isaStep)}; ${renderFactLine(lifted)}`, replace: true };
|
|
23821
|
+
}
|
|
23822
|
+
}
|
|
23103
23823
|
return null;
|
|
23104
23824
|
}
|
|
23105
23825
|
const doAsk = positiveQuestionSurface(q).match(DO_VERB_ASK_RE);
|
|
@@ -23128,6 +23848,14 @@ ${shown.map(renderFactLine).join("\n")}`,
|
|
|
23128
23848
|
}
|
|
23129
23849
|
const base = capabilityBaseRateReply(doAsk[2], doAsk[3], facts);
|
|
23130
23850
|
if (base) return base;
|
|
23851
|
+
if (!/\s/.test(doAsk[2].trim()) && !facts.some((f) => subj.has(f.subject) || subj.has(f.object))) {
|
|
23852
|
+
const noun = singularizeSurface(teachableSubjectOf(doAsk[2]));
|
|
23853
|
+
return {
|
|
23854
|
+
text: `I can't confirm that \u2014 I don't know anything about "${doAsk[2]}" yet. Teach me "a ${noun} can ${doAsk[3]}" (or "a ${noun} cannot ${doAsk[3]}") and I'll remember it.`,
|
|
23855
|
+
replace: true,
|
|
23856
|
+
miss: true
|
|
23857
|
+
};
|
|
23858
|
+
}
|
|
23131
23859
|
}
|
|
23132
23860
|
}
|
|
23133
23861
|
const canDo = q.match(WHAT_CAN_DO_RE);
|
|
@@ -23550,11 +24278,55 @@ ${shown.join("\n")}${extra}`, replace: true, ...rest.length ? { pending: { items
|
|
|
23550
24278
|
const objVariants = factTermVariants(normFactTerm2, stripTrailingDiscourseTag(isaAsk[2]));
|
|
23551
24279
|
const isaSubject = focusLabel && IS_ADJECTIVE_PRONOUN_RE.test(isaAsk[1].trim()) ? focusLabel : isaAsk[1];
|
|
23552
24280
|
const subjCandidates = new Set(factTermVariants(normFactTerm2, isaSubject));
|
|
24281
|
+
if ([...subjCandidates].some((s) => objVariants.has(s))) {
|
|
24282
|
+
const kindEcho = stripTrailingDiscourseTag(isaAsk[2]).trim();
|
|
24283
|
+
return {
|
|
24284
|
+
text: `yes \u2014 ${indefiniteArticleFor(kindEcho)} ${kindEcho} is ${indefiniteArticleFor(kindEcho)} ${kindEcho}, trivially: every kind is a kind of itself.`,
|
|
24285
|
+
replace: true
|
|
24286
|
+
};
|
|
24287
|
+
}
|
|
23553
24288
|
const noun = await entityClassNoun(graph, isaSubject);
|
|
23554
24289
|
if (noun) for (const v of factTermVariants(normFactTerm2, noun)) subjCandidates.add(v);
|
|
24290
|
+
const {
|
|
24291
|
+
findIsaChain: findIsaChain2,
|
|
24292
|
+
deriveDisjointViolations: deriveDisjointViolations2,
|
|
24293
|
+
SUBCLASS_PREDICATE: SC_PREDICATE,
|
|
24294
|
+
TYPE_PREDICATE: RDF_TYPE_PREDICATE,
|
|
24295
|
+
DISJOINT_PREDICATE: DISJOINT_PREDICATE2
|
|
24296
|
+
} = await Promise.resolve().then(() => (init_syllogise(), syllogise_exports));
|
|
24297
|
+
const isTaught = isOperatorTaught;
|
|
24298
|
+
const chainSubClassRows = isa.filter((f) => f.predicate === SC_PREDICATE && isTaught(f));
|
|
24299
|
+
const chainTypeRows = isa.filter((f) => f.predicate === RDF_TYPE_PREDICATE && isTaught(f));
|
|
24300
|
+
const chainSubClassEdges = chainSubClassRows.map((f) => [f.subject, f.object]);
|
|
24301
|
+
const chainTypeEdges = chainTypeRows.map((f) => [f.subject, f.object]);
|
|
24302
|
+
const mixedSubClassRows = isa.filter((f) => f.predicate === SC_PREDICATE);
|
|
24303
|
+
const mixedTypeRows = isa.filter((f) => f.predicate === RDF_TYPE_PREDICATE);
|
|
24304
|
+
const mixedTypeEdges = mixedTypeRows.map((f) => [f.subject, f.object]);
|
|
24305
|
+
const mixedSubClassEdges = mixedSubClassRows.map((f) => [f.subject, f.object]);
|
|
24306
|
+
const disjointRows = rows.filter((f) => f.predicate === DISJOINT_PREDICATE2 && isTaught(f));
|
|
24307
|
+
const disjointEdges = disjointRows.map((f) => [f.subject, f.object]);
|
|
24308
|
+
const disjointGateViolations = disjointRows.length ? deriveDisjointViolations2(
|
|
24309
|
+
mixedTypeEdges.concat(mixedSubClassEdges),
|
|
24310
|
+
mixedSubClassEdges,
|
|
24311
|
+
disjointEdges,
|
|
24312
|
+
{ budget: 20, focus: /* @__PURE__ */ new Set([...subjCandidates, ...objVariants]) }
|
|
24313
|
+
) : [];
|
|
24314
|
+
const disjointRefusalFor = (subj) => {
|
|
24315
|
+
const v = disjointGateViolations.find((vv) => vv.subject === subj && objVariants.has(vv.object));
|
|
24316
|
+
if (!v) return null;
|
|
24317
|
+
const posFact = isa.filter((f) => objVariants.has(f.object) && (f.subject === v.viaClass || f.subject === v.subject)).sort(byTrust)[0];
|
|
24318
|
+
const disjointFact = disjointRows.find((f) => f.subject === v.viaClass && f.object === v.object || f.subject === v.object && f.object === v.viaClass);
|
|
24319
|
+
if (!posFact || !disjointFact) return null;
|
|
24320
|
+
return isaInconsistencyRefusal(posFact, disjointFact);
|
|
24321
|
+
};
|
|
23555
24322
|
const hit2 = isa.filter((f) => subjCandidates.has(f.subject) && objVariants.has(f.object)).sort(byTrust)[0];
|
|
23556
24323
|
const negHit = rows.filter((f) => f.predicate === NEG_SUBCLASS_PREDICATE && subjCandidates.has(f.subject) && objVariants.has(f.object)).sort(byTrust)[0];
|
|
23557
|
-
const
|
|
24324
|
+
const directDisjoint = disjointRows.find((f) => subjCandidates.has(f.subject) && objVariants.has(f.object) || subjCandidates.has(f.object) && objVariants.has(f.subject));
|
|
24325
|
+
if (hit2 && !negHit) {
|
|
24326
|
+
const chainRefusal = disjointRefusalFor(hit2.subject);
|
|
24327
|
+
if (chainRefusal) return chainRefusal;
|
|
24328
|
+
}
|
|
24329
|
+
const polarityReply = isaPolarityReply(hit2, negHit || directDisjoint);
|
|
23558
24330
|
if (polarityReply) return polarityReply;
|
|
23559
24331
|
const ent = await resolveEntity(graph, isaSubject);
|
|
23560
24332
|
if (ent) {
|
|
@@ -23572,34 +24344,26 @@ ${shown.join("\n")}${extra}`, replace: true, ...rest.length ? { pending: { items
|
|
|
23572
24344
|
};
|
|
23573
24345
|
}
|
|
23574
24346
|
}
|
|
23575
|
-
const { findIsaChain: findIsaChain2, SUBCLASS_PREDICATE: SC_PREDICATE, TYPE_PREDICATE: RDF_TYPE_PREDICATE } = await Promise.resolve().then(() => (init_syllogise(), syllogise_exports));
|
|
23576
|
-
const isTaught = isOperatorTaught;
|
|
23577
|
-
const chainSubClassRows = isa.filter((f) => f.predicate === SC_PREDICATE && isTaught(f));
|
|
23578
|
-
const chainTypeRows = isa.filter((f) => f.predicate === RDF_TYPE_PREDICATE && isTaught(f));
|
|
23579
|
-
const chainSubClassEdges = chainSubClassRows.map((f) => [f.subject, f.object]);
|
|
23580
|
-
const chainTypeEdges = chainTypeRows.map((f) => [f.subject, f.object]);
|
|
23581
24347
|
const factForStep = (step) => (step.predicate === SC_PREDICATE ? chainSubClassRows : chainTypeRows).find((f) => f.subject === step.subject && f.object === step.object);
|
|
23582
24348
|
for (const subj of subjCandidates) {
|
|
23583
24349
|
const chain = findIsaChain2(subj, objVariants, chainTypeEdges, chainSubClassEdges, { maxHops: 2 });
|
|
23584
24350
|
if (!chain) continue;
|
|
24351
|
+
const chainRefusal = disjointRefusalFor(subj);
|
|
24352
|
+
if (chainRefusal) return chainRefusal;
|
|
23585
24353
|
const premises = chain.map(factForStep);
|
|
23586
24354
|
if (premises.every(Boolean)) return { text: `yes \u2014 ${renderIsaChain(premises)}`, replace: true };
|
|
23587
24355
|
}
|
|
23588
|
-
const mixedSubClassRows = isa.filter((f) => f.predicate === SC_PREDICATE);
|
|
23589
|
-
const mixedTypeRows = isa.filter((f) => f.predicate === RDF_TYPE_PREDICATE);
|
|
23590
24356
|
const mixedFactForStep = (step) => (step.predicate === SC_PREDICATE ? mixedSubClassRows : mixedTypeRows).find((f) => f.subject === step.subject && f.object === step.object);
|
|
23591
|
-
const mixedTypeEdges = mixedTypeRows.map((f) => [f.subject, f.object]);
|
|
23592
|
-
const mixedSubClassEdges = mixedSubClassRows.map((f) => [f.subject, f.object]);
|
|
23593
24357
|
for (const subj of subjCandidates) {
|
|
23594
24358
|
const chain = findIsaChain2(subj, objVariants, mixedTypeEdges, mixedSubClassEdges, { maxHops: 2 });
|
|
23595
24359
|
if (!chain) continue;
|
|
24360
|
+
const chainRefusal = disjointRefusalFor(subj);
|
|
24361
|
+
if (chainRefusal) return chainRefusal;
|
|
23596
24362
|
const premises = chain.map(mixedFactForStep);
|
|
23597
24363
|
if (premises.every(Boolean) && premises.some(isTaught)) {
|
|
23598
24364
|
return { text: `yes \u2014 ${renderIsaChain(premises)}`, replace: true };
|
|
23599
24365
|
}
|
|
23600
24366
|
}
|
|
23601
|
-
const { deriveDisjointViolations: deriveDisjointViolations2, DISJOINT_PREDICATE: DISJOINT_PREDICATE2 } = await Promise.resolve().then(() => (init_syllogise(), syllogise_exports));
|
|
23602
|
-
const disjointRows = rows.filter((f) => f.predicate === DISJOINT_PREDICATE2 && isTaught(f));
|
|
23603
24367
|
const negSubjectMatch = isaSubject.match(/^(.*\S)\s+not$/i);
|
|
23604
24368
|
const negSubject = negSubjectMatch && [
|
|
23605
24369
|
negSubjectMatch[0],
|
|
@@ -23621,14 +24385,16 @@ ${shown.join("\n")}${extra}`, replace: true, ...rest.length ? { pending: { items
|
|
|
23621
24385
|
};
|
|
23622
24386
|
}
|
|
23623
24387
|
if (disjointRows.length) {
|
|
23624
|
-
const
|
|
23625
|
-
|
|
23626
|
-
|
|
23627
|
-
|
|
24388
|
+
const violations = deriveDisjointViolations2(
|
|
24389
|
+
chainTypeEdges.concat(chainSubClassEdges),
|
|
24390
|
+
chainSubClassEdges,
|
|
24391
|
+
disjointEdges,
|
|
24392
|
+
{ budget: 10 }
|
|
24393
|
+
);
|
|
23628
24394
|
for (const subj of subjCandidates) {
|
|
23629
24395
|
const v = violations.find((vv) => vv.subject === subj && objVariants.has(vv.object));
|
|
23630
24396
|
if (!v) continue;
|
|
23631
|
-
const typeFact = chainTypeRows.find((f) => f.subject === v.subject && f.object === v.viaType);
|
|
24397
|
+
const typeFact = chainTypeRows.concat(chainSubClassRows).find((f) => f.subject === v.subject && f.object === v.viaType);
|
|
23632
24398
|
const disjointFact = disjointRows.find((f) => f.subject === v.viaClass && f.object === v.object || f.subject === v.object && f.object === v.viaClass);
|
|
23633
24399
|
const parts = [typeFact, disjointFact].filter(Boolean).map(renderFactLine);
|
|
23634
24400
|
return { text: `no \u2014 ${parts.length ? parts.join("; ") : `${v.viaClass} and ${v.object} are disjoint.`}`, replace: true };
|
|
@@ -23725,6 +24491,14 @@ ${shown.join("\n")}${extra}`, replace: true, ...rest.length ? { pending: { items
|
|
|
23725
24491
|
// still a MISS in the turn record — honest wording, not an answer
|
|
23726
24492
|
};
|
|
23727
24493
|
}
|
|
24494
|
+
const converseHit = isa.filter((f) => subjCandidates.has(f.object) && objVariants.has(f.subject)).sort(byTrust)[0];
|
|
24495
|
+
if (converseHit) {
|
|
24496
|
+
return {
|
|
24497
|
+
text: `I can't confirm that \u2014 what I know runs the other way: ${renderFactLine(converseHit)}. A kind doesn't reverse. If it's true, teach me: "every ${subjectWord} is a ${kindWord}".`,
|
|
24498
|
+
replace: true,
|
|
24499
|
+
miss: true
|
|
24500
|
+
};
|
|
24501
|
+
}
|
|
23728
24502
|
if (!ent && !noun && !isPronoun(subjectWord) && !rows.some((f) => subjCandidates.has(f.subject) || subjCandidates.has(f.object))) {
|
|
23729
24503
|
return {
|
|
23730
24504
|
text: `I can't confirm that \u2014 I don't know "${subjectWord}" at all yet. If it's true, teach me: "${subjectWord} is a kind of ${kindWord}".`,
|
|
@@ -23902,7 +24676,7 @@ ${shown.join("\n")}${extra}`, replace: true, ...rest.length ? { pending: { items
|
|
|
23902
24676
|
}
|
|
23903
24677
|
}
|
|
23904
24678
|
if (rows.some(subjectMatch) && !envelope?.parsed) {
|
|
23905
|
-
return { text: `I don't have a fact saying ${
|
|
24679
|
+
return { text: `I don't have a fact saying ${suggestibleSubjectPhrase(subject)} is ${adjective}.`, replace: true };
|
|
23906
24680
|
}
|
|
23907
24681
|
if (!envelope?.parsed) return unknownAdjectiveOffer(subject, adjective);
|
|
23908
24682
|
}
|
|
@@ -24024,8 +24798,25 @@ ${shown.join("\n")}${extra}`, replace: true, ...rest.length ? { pending: { items
|
|
|
24024
24798
|
capabilities: "see what /plan can plan over \u2014 built-in query tools and taught actions",
|
|
24025
24799
|
syllogise: "materialize the entailed facts that follow from what's remembered about one term"
|
|
24026
24800
|
};
|
|
24801
|
+
var IMPACT_CHANGE_VERBS = "(?:changed?|modif(?:y|ied)|edits?|edited|touch(?:es|ed)?|updates?|updated|alters?|altered|deletes?|deleted|removes?|removed|drops?|dropped)";
|
|
24027
24802
|
var IMPACT_PARAPHRASE_RE = new RegExp(
|
|
24028
|
-
|
|
24803
|
+
`^what\\s+(?:would|will|might|could|does|do)?\\s*(?:breaks?|fails?|happens?|stops?\\s+working|is\\s+affected|are\\s+affected|gets?\\s+affected|be\\s+affected|is\\s+impacted|be\\s+impacted)\\s+if\\s+(?:i|we|you|one|someone)\\s+${IMPACT_CHANGE_VERBS}\\s+(?:the\\s+)?(.+?)[?.!\\s]*$`,
|
|
24804
|
+
"i"
|
|
24805
|
+
);
|
|
24806
|
+
var IMPACT_REVERSED_RE = new RegExp(
|
|
24807
|
+
`^if\\s+(?:i|we|you|one|someone)\\s+${IMPACT_CHANGE_VERBS}\\s+(?:the\\s+)?(.+?),?\\s+what\\s+(?:would\\s+|will\\s+|might\\s+|could\\s+|does\\s+|do\\s+)?(?:breaks?|fails?|happens?|stops?\\s+working|is\\s+affected|are\\s+affected|gets?\\s+affected|be\\s+affected|would\\s+break|will\\s+break)[?.!\\s]*$`,
|
|
24808
|
+
"i"
|
|
24809
|
+
);
|
|
24810
|
+
var IMPACT_AFFECTED_BY_RE = new RegExp(
|
|
24811
|
+
"^what\\s+(?:is|are|gets?|would\\s+be|will\\s+be)\\s+(?:affected|impacted|broken)\\s+(?:by|when|if)\\s+(?:i\\s+|we\\s+|you\\s+)?(?:chang(?:e|es|ing)|edit(?:s|ing)?|modif(?:y|ies|ying)|touch(?:es|ing)?|updat(?:e|es|ing)|delet(?:e|es|ing)|remov(?:e|es|ing)|a\\s+change\\s+to)\\s+(?:the\\s+)?(.+?)[?.!\\s]*$",
|
|
24812
|
+
"i"
|
|
24813
|
+
);
|
|
24814
|
+
var IMPACT_SAFE_CHANGE_RE = new RegExp(
|
|
24815
|
+
"^(?:(?:can|could)\\s+(?:i|we|you|one|someone)\\s+safely|is\\s+it\\s+safe\\s+to)\\s+(?:change|edit|modify|touch|update|alter|delete|remove|drop)\\s+(?:the\\s+)?(.+?)[?.!\\s]*$",
|
|
24816
|
+
"i"
|
|
24817
|
+
);
|
|
24818
|
+
var IMPACT_NOUN_RE = new RegExp(
|
|
24819
|
+
"^(?:what(?:'s|\\s+is)\\s+the\\s+)?(?:blast\\s+radius|impact)\\s+(?:of|for)\\s+(?:chang(?:ing|es)\\s+|editing\\s+|modifying\\s+|touching\\s+|updating\\s+|deleting\\s+|removing\\s+)?(?:the\\s+)?(.+?)[?.!\\s]*$",
|
|
24029
24820
|
"i"
|
|
24030
24821
|
);
|
|
24031
24822
|
var BASE_QUALIFIER_SRC = "as\\s+(?:its|the|an?)?\\s*(?:base\\s+class|parent\\s+class|base|parent)";
|