@polycode-projects/the-mechanical-code-talker 0.9.9 → 0.9.10

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/ROADMAP.md CHANGED
@@ -82,13 +82,13 @@ In priority order (full detail and measured targets in `HANDOVER.md`):
82
82
  unscoped lister shows matches. Found dogfooding a 191k-entity monorepo graph.
83
83
  3. **Bug 7.** A modal auxiliary ("should") survives the fuzzy-correction cascade and misreads as
84
84
  "hold". The diagnosed fix is adding modals to `STOPWORDS`.
85
- 4. **`PLAN_TMCT_ECOSYSTEM_INTEGRATION.md`.** A separate concurrent session is drafting this
86
- 3-part tmct/bedrock-meter/marginalia integration plan. Check for completion and finalize.
87
- 5. **`PLAN_CODE.md`'s sign-off decision.** Track 1 (rule/frame synthesis) is the lowest-risk
88
- candidate; decide with the operator whether to greenlight it.
89
- 6. Smaller chat-feel residuals from the 0.8.2 confirmation playtest, the Track-1 trio (pronoun,
90
- temporal, discourse-count, measured red sets), and `edgesOfKind` memoization for monorepo-scale
91
- latency. (The version bump plus push is done — see "Now" above.)
85
+ 4. ~~`PLAN_TMCT_ECOSYSTEM_INTEGRATION.md`~~ **shipped** see "Now" above.
86
+ 5. ~~`PLAN_CODE.md` Track 1 sign-off~~ **signed off and shipped** — see "Now" above.
87
+ 6. **Still open**: the function-grain forward-shape gap (Bug C+D's grain resolution doesn't
88
+ cover the "forward" traversal shape), 8 remaining temporal red ids (each a distinct small
89
+ grammar gap), the un-flagged `C1:presupposition`/`C2:garden-path` regression, the
90
+ `edgesOfKind` by-subject/by-object endpoint indices (memoization itself is done). Full
91
+ detail in `HANDOVER.md`.
92
92
  7. **`SKILL_PLAYTEST_SPRINT.md`, in progress.** A capped, delegated, chained playtest loop (each
93
93
  round a background chat session against `examples/mini-webapp`, appraised and fixed+shipped
94
94
  live). Rounds 1-3 shipped 3 real fixes (0.9.3-0.9.5); cap raised from 3 to 8 rounds mid-run;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polycode-projects/the-mechanical-code-talker",
3
- "version": "0.9.9",
3
+ "version": "0.9.10",
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-vocab.mjs CHANGED
@@ -157,6 +157,12 @@ export const RELATIONS = {
157
157
  "change alongside", "shares commits with", "share commits with",
158
158
  "tends to change together with", "tend to change together with",
159
159
  "moves together with", "move together with",
160
+ // Track-1 trio (temporal lever): the bare "changed/change together with" form
161
+ // (no "tends to"/"tend to" prefix) was missing outright — "which modules
162
+ // changed together with X" fell through to the "touch(ed)" verb instead (a
163
+ // Commit->Module kind, structurally unable to match a Module subject), always
164
+ // producing a confidently-empty answer regardless of real cochange data.
165
+ "changed together with", "change together with", "changes together with",
160
166
  ],
161
167
  },
162
168
  reexports: {
package/src/ask.mjs CHANGED
@@ -2159,6 +2159,21 @@ export function traverse(graph, parsed, { contextId = null, prev = null } = {})
2159
2159
  // Module individuals and a FINER entityType was asked for do we refine via `defines`
2160
2160
  // (imports) — never blindly treat an edge's subject id as if it were always a module id.
2161
2161
  let edges = kindsFor(kind).flatMap((k) => edgesOfKind(graph, k)).filter((e) => e.object === gObjMatch.id);
2162
+ // cochange (Module<->Module, mgx:changeCoupledWith) is a SYMMETRIC relation but
2163
+ // stored as ONE directed edge per pair (extractor convention, not a meaningful
2164
+ // subject/object direction) — "which modules cochange with X" must also match
2165
+ // when X is the STORED SUBJECT of the pair, reading the OTHER endpoint (Track-1
2166
+ // trio, temporal lever). Flip subject<->object on that side so the subjects-
2167
+ // collection loop below (which reads e.subject) picks up the partner uniformly;
2168
+ // the object-side match above is untouched, so an existing non-empty answer is
2169
+ // byte-identical.
2170
+ if (kind === "cochange") {
2171
+ edges = edges.concat(
2172
+ kindsFor(kind).flatMap((k) => edgesOfKind(graph, k))
2173
+ .filter((e) => e.subject === gObjMatch.id)
2174
+ .map((e) => ({ ...e, subject: e.object, object: e.subject })),
2175
+ );
2176
+ }
2162
2177
  let extNote = "";
2163
2178
  if (!edges.length && gObjMatch.class) {
2164
2179
  // Unresolved ext:<Name> endpoints with the SAME name as the resolved entity:
package/src/chat.mjs CHANGED
@@ -2478,13 +2478,26 @@ async function runAsk(query, { config, source, graph, focus, last, templates, me
2478
2478
  note(trace, `lane: (1) META/SELF — bare self/session question recognized, answered via="${meta.via}"`);
2479
2479
  }
2480
2480
  }
2481
- if (!handled && miss && isConversational(query)) {
2481
+ if (!handled && miss && !envelope?.parsed && isConversational(query)) {
2482
2482
  // A conversational miss (a greeting, "what can you do", a very short non-code
2483
2483
  // line) gets the friendly orientation (module-aware: empty → --repo/tmct init).
2484
2484
  // Bug B1 (0.8.2 follow-up): this branch carries via:"template" and never
2485
2485
  // reaches the composed-only wall-shortening gate below, so a second
2486
2486
  // identical orientation-class turn used to repeat the full blurb verbatim —
2487
2487
  // collapse to a one-liner on that repeat, mirroring WALL_REPEAT_ONELINER.
2488
+ //
2489
+ // `!envelope?.parsed` (Track-1 trio, pronoun/focus binding — "biggest movable
2490
+ // mass"): isConversational() is a TEXT-ONLY heuristic (≤3 words, no code-ish
2491
+ // token) — it has no way to know the query already compiled to a real
2492
+ // structural AST shape. A pronoun-shortened follow-up ("who touched it"/
2493
+ // "that"/"this") is exactly 3 words and "touched" isn't in STRUCT_WORDS, so
2494
+ // isConversational used to fire AFTER ask() had already parsed the reverse
2495
+ // "touches" shape, resolved the pronoun off the focus, run the traversal, and
2496
+ // composed an honest (possibly empty) answer — discarding that correct answer
2497
+ // for the generic orientation wall. When envelope.parsed stood, the query WAS
2498
+ // structural (by construction, not word-count guesswork); its own composed
2499
+ // answer — hit, honest empty, or "it needs a referent" — is always more
2500
+ // truthful than the orientation card.
2488
2501
  const orientation = orientationAnswer(templates, graph);
2489
2502
  const repeat = last?.answer === orientation;
2490
2503
  answer = repeat ? ORIENTATION_REPEAT_ONELINER : orientation;