@polycode-projects/the-mechanical-code-talker 0.9.0 → 0.9.1

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/ask.mjs +20 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polycode-projects/the-mechanical-code-talker",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
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/ask.mjs CHANGED
@@ -821,15 +821,19 @@ function parseRelationalOrQualified(w, lc, nlp, depth) {
821
821
  while (i < lc.length && QUALIFIERS[lc[i]]) { quals.push(lc[i]); i += 1; }
822
822
  const noun = i < lc.length ? entityNoun(lc[i]) : null;
823
823
  if (!noun) {
824
- // an unknown adjective sitting in the qualifier slot, right before a known
825
- // entity noun ("which shiny methods", "static frobnicated functions") — an
826
- // honest miss that NAMES the supported qualifiers, never a guess (PLAN P3).
827
- // STOPWORDS are excluded so a normal question auxiliary in that position ("what
828
- // DID commit X touch", "what WAS in <sha>") is left for the existing parser, not
829
- // mistaken for an unknown qualifier.
830
- if ((framed || quals.length) && i + 1 < lc.length && /^[a-z]+$/.test(lc[i])
831
- && !VERB_TO_KIND[lc[i]] && !STOPWORDS.has(lc[i]) && entityNoun(lc[i + 1])) {
832
- return { node: "miss", reason: `unknown qualifier "${lc[i]}" — supported: ${Object.keys(QUALIFIERS).join(", ")}` };
824
+ // An unknown adjective sitting in the qualifier slot, right before a known entity
825
+ // noun ("list payment modules", "which shiny methods") — try it as a predicate-find
826
+ // fuzzy term FIRST ("payment" filtering Module labels/attributes) before declaring
827
+ // it an unrecognized qualifier: a real, honest answer beats an error message, and a
828
+ // genuine zero-hit still renders find's own honest "no <noun> found matching <term>"
829
+ // miss (never a confident-wrong guess either way — same discipline as everywhere
830
+ // else this AST node is produced). STOPWORDS are excluded so a normal question
831
+ // auxiliary in that position ("what DID commit X touch") is left for the existing
832
+ // parser, not mistaken for a term.
833
+ const nextNoun = i + 1 < lc.length ? entityNoun(lc[i + 1]) : null;
834
+ if ((framed || quals.length) && nextNoun && /^[a-z]+$/.test(lc[i])
835
+ && !VERB_TO_KIND[lc[i]] && !STOPWORDS.has(lc[i])) {
836
+ return { node: "find", entityType: nextNoun.entityType, term: w[i] };
833
837
  }
834
838
  return null; // no subject entity → not this shape
835
839
  }
@@ -2286,11 +2290,16 @@ function renderCore(parsed, result) {
2286
2290
  }
2287
2291
  if (result.ambiguous) {
2288
2292
  // the candidates say what KIND of thing is ambiguous — a shared commit-sha
2289
- // prefix must read "more than one commit", not "module".
2293
+ // prefix must read "more than one commit", not "module". Name the actual
2294
+ // candidates in the prose (not just the structured `candidates` field) —
2295
+ // "narrow the term" is not itself actionable if the reader can't see what
2296
+ // it's ambiguous between; mirrors the mentionsShape branch's listing above.
2290
2297
  const pool = [result.objMatch, ...(result.candidates || [])].filter(Boolean);
2291
2298
  const noun = pool.length && pool.every((i) => i.class === "Commit") ? "commit" : "module";
2299
+ const shown = pool.slice(0, OVERFLOW_CAP).map((i) => i.label);
2300
+ const extra = pool.length > OVERFLOW_CAP ? `, …and ${pool.length - OVERFLOW_CAP} more` : "";
2292
2301
  return {
2293
- content: `"${parsed.object}" matches more than one ${noun} ambiguously — please narrow the term.`,
2302
+ content: `"${parsed.object}" matches more than one ${noun} ambiguously — did you mean ${listJoin(shown)}${extra}? Try one of those.`,
2294
2303
  miss: false, ambiguous: true, candidates: pool.map((i) => i.label),
2295
2304
  };
2296
2305
  }