@polycode-projects/the-mechanical-code-talker 0.9.2 → 0.9.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polycode-projects/the-mechanical-code-talker",
3
- "version": "0.9.2",
3
+ "version": "0.9.3",
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.",
@@ -485,6 +485,12 @@ export const STOPWORDS = new Set([
485
485
  // literally named "last" would be the accepted residual cost, same trade as
486
486
  // every other stopword.
487
487
  "last",
488
+ // frequency-adverb filler ("what does X usually change together with", "what does
489
+ // X typically call") — found live: "usually" glued onto the object term instead of
490
+ // being stripped, corrupting resolution ("src/core/store.mjs usually" instead of
491
+ // the module alone). Same trade as every other stopword: a symbol literally named
492
+ // "usually" would be the accepted residual cost.
493
+ "usually", "typically", "generally", "normally", "often", "commonly", "mostly",
488
494
  ]);
489
495
 
490
496
  /** Split free text into words: trailing "?" run stripped, commas treated as
@@ -150,6 +150,21 @@ export function parseKeywordSpot(text, nlp = null) {
150
150
  const consumed = new Set();
151
151
  const mark = (hit) => { if (hit) for (let i = hit.start; i < hit.end; i += 1) consumed.add(i); };
152
152
  mark(verbHit);
153
+ // A redundant SAME-KIND verb immediately after the matched one ("what TESTS
154
+ // cover X" — "tests" is read as the relation trigger, but "cover" — also a
155
+ // `tests` verb, ask-vocab.mjs's own synonym list — is the word the sentence
156
+ // actually intends as the verb) would otherwise fall into afterText raw and
157
+ // corrupt the object ("cover src/core/model.mjs" instead of the module alone).
158
+ // Anchored to the exact position right after verbHit (never a general re-scan),
159
+ // and gated on matching the SAME kind, so this can only strip a genuine
160
+ // restatement, never eat a real object term. Found live: "what tests cover X",
161
+ // "which tests test X" both misparsed this way before this fix.
162
+ for (const [phrase, kind] of Object.entries(VERB_TO_KIND)) {
163
+ if (kind !== verbHit.kind) continue;
164
+ const pWords = phrase.split(" ");
165
+ const start = verbHit.end;
166
+ if (pWords.every((w, j) => canonWords[start + j] === w)) { mark({ start, end: start + pWords.length }); break; }
167
+ }
153
168
  const entityHit = findPhrase(canonWords, ENTITY_TO_TYPE, consumed);
154
169
  mark(entityHit);
155
170
  const modifierHit = findPhrase(canonWords, MODIFIER_TO_KIND, consumed);