@polycode-projects/the-mechanical-code-talker 2.11.4 → 2.11.5
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polycode-projects/the-mechanical-code-talker",
|
|
3
|
-
"version": "2.11.
|
|
3
|
+
"version": "2.11.5",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "The Mechanical Code Talker (tmct) — a tolerant, offline, $0 chat surface that guides you toward precision queries about a software repository. ELIZA/PARRY-style but domain-obsessed with code. No model calls; no codebase index of its own.",
|
package/src/services/chat.mjs
CHANGED
|
@@ -6737,9 +6737,27 @@ const RELATION_WHO_ASK_RE =
|
|
|
6737
6737
|
* ([\w-]+) so the 's split is unambiguous. */
|
|
6738
6738
|
const GENITIVE_WHO_ASK_RE =
|
|
6739
6739
|
/^(?:who|what)\s+(?:is|are|was|were)\s+([\w-]+(?:\s+[A-Z][\w-]*)?)'s\s+([a-z][\w-]*)[?.!\s]*$/i;
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6740
|
+
/** The fact lane reads the raw surface, so the ask path's contraction table
|
|
6741
|
+
* never reaches these readers — expand just the interrogative lead
|
|
6742
|
+
* ("who's"/"whos"/"what's"/"whats") so both relation-ask surfaces accept it.
|
|
6743
|
+
* "whose" never matches (the trailing "e" fails the boundary). */
|
|
6744
|
+
const WHO_WHAT_LEAD_CONTRACTION_RE = /^(who|what)'?s\s+/i;
|
|
6745
|
+
const expandWhoWhatLead = (q) => String(q).replace(WHO_WHAT_LEAD_CONTRACTION_RE, (full, w) => `${w} is `);
|
|
6746
|
+
/** The apostrophe-less genitive ("who is petes father") — accepted ONLY when
|
|
6747
|
+
* the stripped possessor is already a term some stored fact names, so a
|
|
6748
|
+
* plain plural or a pronoun ("who is his father") can never be mis-split
|
|
6749
|
+
* into a claimed-then-missed relation ask; this reader's own miss text is
|
|
6750
|
+
* definitive, never a fall-through, so the gate must sit at match time. */
|
|
6751
|
+
const GENITIVE_WHO_ASK_BARE_RE =
|
|
6752
|
+
/^(?:who|what)\s+(?:is|are|was|were)\s+([\w-]{2,}?)s\s+([a-z][\w-]*)[?.!\s]*$/i;
|
|
6753
|
+
function matchGenitiveWhoAsk(q, isKnownFactTerm = null) {
|
|
6754
|
+
const expanded = expandWhoWhatLead(q);
|
|
6755
|
+
const g = expanded.match(GENITIVE_WHO_ASK_RE);
|
|
6756
|
+
if (g) return [g[0], g[2], g[1]];
|
|
6757
|
+
if (!isKnownFactTerm) return null;
|
|
6758
|
+
const b = expanded.match(GENITIVE_WHO_ASK_BARE_RE);
|
|
6759
|
+
if (!b) return null;
|
|
6760
|
+
return isKnownFactTerm(b[1]) ? [b[0], b[2], b[1]] : null;
|
|
6743
6761
|
}
|
|
6744
6762
|
|
|
6745
6763
|
/** "list the descendants of ahab" — the REACHABILITY-SET list query: a
|
|
@@ -7184,7 +7202,7 @@ function withDeducedGoal(res, envelope, query) {
|
|
|
7184
7202
|
if (!goal && res.generalVerbQuery) goal = TAUGHT_FACT_LOOKUP_GOAL;
|
|
7185
7203
|
if (!goal) {
|
|
7186
7204
|
const yesNo = q.match(RELATION_FACT_YESNO_RE);
|
|
7187
|
-
const whoAsk = yesNo ? null : (q.match(RELATION_WHO_ASK_RE) || matchGenitiveWhoAsk(q));
|
|
7205
|
+
const whoAsk = yesNo ? null : (expandWhoWhatLead(q).match(RELATION_WHO_ASK_RE) || matchGenitiveWhoAsk(q));
|
|
7188
7206
|
const role = yesNo ? yesNo[2] : whoAsk ? whoAsk[1] : null;
|
|
7189
7207
|
if (role && !ISA_IDIOM_ROLE_WORDS.has(role.toLowerCase())) goal = TAUGHT_FACT_LOOKUP_GOAL;
|
|
7190
7208
|
}
|
|
@@ -8624,7 +8642,10 @@ async function factReadBackReaders(memoryDir, query, envelope, miss, graph = nul
|
|
|
8624
8642
|
// sharing it with (a0): RELATION_WHO_ASK_RE and RELATION_FACT_YESNO_RE never
|
|
8625
8643
|
// both match the same query (one starts with "who", the other with
|
|
8626
8644
|
// "is/are/was/were"), so the two blocks never run in the same call.
|
|
8627
|
-
const whoAsk = qHedge.match(RELATION_WHO_ASK_RE) || matchGenitiveWhoAsk(qHedge)
|
|
8645
|
+
const whoAsk = expandWhoWhatLead(qHedge).match(RELATION_WHO_ASK_RE) || matchGenitiveWhoAsk(qHedge, (base) => {
|
|
8646
|
+
const known = factTermVariants(normFactTerm, base);
|
|
8647
|
+
return rows.some((f) => known.has(f.subject) || known.has(f.object));
|
|
8648
|
+
});
|
|
8628
8649
|
if (whoAsk) {
|
|
8629
8650
|
const relationName = whoAsk[1].trim().toLowerCase();
|
|
8630
8651
|
const rawObject = whoAsk[2].trim();
|
|
@@ -8684,7 +8705,7 @@ async function factReadBackReaders(memoryDir, query, envelope, miss, graph = nul
|
|
|
8684
8705
|
// oddly as "I don't know ANYONE who is the capital…" — the neutral
|
|
8685
8706
|
// "nothing/anyone" split below matches whichever interrogative word the
|
|
8686
8707
|
// query actually used.
|
|
8687
|
-
const isWhatAsk = /^what\b/i.test(qHedge);
|
|
8708
|
+
const isWhatAsk = /^what\b/i.test(expandWhoWhatLead(qHedge));
|
|
8688
8709
|
return {
|
|
8689
8710
|
text: isWhatAsk
|
|
8690
8711
|
? `I don't know what the ${relationName} of ${object} is from what you've told me.`
|