@polycode-projects/the-mechanical-code-talker 1.2.0 → 1.3.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.
package/README.md CHANGED
@@ -127,6 +127,15 @@ Teaching isn't limited to the ACE grammar's fixed shapes. Tell tmct an
127
127
  arbitrary fact, like "margo eats ribs", and it mints a fact you can later ask
128
128
  about directly: "what does margo eat", or "does margo eat ribs".
129
129
 
130
+ New vocabulary compounds as you teach it. "redis is a cache" mints "redis" as
131
+ a class-level concept even though it was never in the built-in lexicon, and a
132
+ later "every cache is a store" does the same for "store," the other way
133
+ round, as long as one side of the sentence is already grounded. tmct never
134
+ mints a fact between two totally ungrounded terms; it declines and nudges you
135
+ to ground one side first. Quantified teaching works too: "some functions are
136
+ risky" stores the quantifier, and a later "how many functions are risky"
137
+ answers "A few."
138
+
130
139
  ### Provenance and trust
131
140
 
132
141
  Every fact and text block records **where it came from and when**. Sources are
package/ROADMAP.md CHANGED
@@ -35,6 +35,126 @@ Test count across the session's later stretch:
35
35
  | Tier 6 (the messy real user), 5 cycles, run alongside a background test-suite health pass | 1328 → 1345 |
36
36
  | Compound-name resolution (multi-word queries to joined-token symbol names) | 1345 → 1352 |
37
37
  | Vocabulary-growth mirror fix — known-subject/unknown-object mint (`unknownObjectFallback`), so new terms compound turn over turn | 1352 → 1355 |
38
+ | `findActionPath` (`src/planning.mjs`) — generic bounded on-demand-successor state-space search, `PLAN_HANOI.md`'s Phase 2 kernel, proven against a small toy graph; not wired into chat, Hanoi itself not started | 1355 → 1361 |
39
+
40
+ **INFBENCH re-measured against 1.2.0** (measurement-only dispatch, 2026-07-09): `INFBENCH_1.2.0.md`
41
+ confirms chat/INF-A2 now closes to 100% (the cax-sco/proof-chase win the STATUS banner above already
42
+ claimed) but also finds chat/INF-C1 has flipped from an honest ceiling to a genuine 93%-fabrication
43
+ regression, traced to the new general-verb-to-predicate query lane answering "no" on an absent fact
44
+ instead of declining — a real correctness bug, separate from and cheaper than the still-gating
45
+ INF-B1 (`cax-dw`) work.
46
+
47
+ **INF-C1 fabrication FIXED (2026-07-09, follow-up dispatch)**: `GENERAL_VERB_YESNO_RE`'s no-hit
48
+ branch (`src/chat.mjs`) now declines (`null`) instead of asserting a confident "no" when no taught
49
+ fact matches the queried subject/predicate/object triple, falling through to the ordinary
50
+ honest-miss cascade — same convention as `WHO_OWNS_RE`'s own no-hit branch. Re-ran `npm run
51
+ infbench`: chat/INF-C1 is back to **93% completion / 0% fabrication**, its `0.8.2`-era honest
52
+ ceiling, exactly as predicted (up from `1.2.0`'s 0% completion / 93% fabrication). Everything else
53
+ in the ladder is unchanged — still gated at INF-B1 (33% completion), unaffected by this fix.
54
+ `npm test` 1361 → 1362 (this fix's own contribution; see `HANDOVER.md` for the combined total
55
+ alongside the concurrent Rule-storage dispatch).
56
+
57
+ **`PLAN_TAUGHT_RELATIONS.md`** (research/design, 2026-07-09, nothing implemented): scopes teaching
58
+ tmct brand-new relations and rules through ordinary chat (a Prolog-style family tree — father,
59
+ parent, grandparent, descendant — none of it hardcoded, all of it taught), reusing
60
+ `findActionPath` for the hop-counted relation chase and a new sibling kernel, `findReachableSet`,
61
+ for open-ended enumeration. Live-testing while designing it surfaced real, already-shipped gaps:
62
+ the "is a kind of" teach phrasing isn't accepted anywhere today, a "parent" example in the original
63
+ scoping conversation only worked by an accidental lexicon collision, and a wrapped property-teach
64
+ shape (`TEACH_PROPERTY_RE`) has no groundedness check at all, unlike the newer subject/object
65
+ mint-fallback pair's explicit discipline. See `HANDOVER.md` for the full finding list; this is
66
+ next-session pickup material, not yet started.
67
+
68
+ **`PLAN_TAUGHT_RELATIONS.md` Phase 3 — DONE (2026-07-09)**: the Rule storage foundation landed in
69
+ `src/memory/core.mjs` (`RULE_CLASS`, `appendRule`, `findRuleByName`) — pure plumbing, zero
70
+ `chat.mjs` change, reusing the existing Source/trust pipeline unmodified. `npm test` 1361 → 1371.
71
+ Phase 4 (compose2 query-side wiring) is next in that plan's build order.
72
+
73
+ **`PLAN_TAUGHT_RELATIONS.md` Phase 1 — DONE (2026-07-09)**: Item 1 (relational fact teach,
74
+ `RELATION_FACT_TEACH_RE` — "ahab is the father of john" mints an ordinary Fact via
75
+ `generalVerbPredicate`, reused verbatim) and Item 5 (adjective-mint, `unknownAdjectiveFallback` —
76
+ "the cache is bespoke" / "TaskController is bespoke" mint `mgx:hasProperty`) both landed in
77
+ `src/chat.mjs`. Query-side readback for Item 1 needed zero new machinery ("what do you know about
78
+ X" / "does X <role> Y" both already confirm it); Item 5's own groundedness guard needed tightening
79
+ beyond the original design to avoid reopening the pinned "module is banana" regression — see
80
+ `PLAN_TAUGHT_RELATIONS.md`'s "Phase 1 — DONE" note for the full adjustment, plus a sharper,
81
+ live-confirmed restatement of that doc's Verification finding 4 (`isConversational`'s ≤3-word gate
82
+ pre-empts the teach lane entirely for a short bare sentence, not just its decline text — flagged,
83
+ not fixed, still out of scope). `npm test` 1371 → 1377.
84
+
85
+ **`PLAN_TAUGHT_RELATIONS.md` Phase 6, KERNEL half — DONE (2026-07-09)**: `findReachableSet`
86
+ (`src/planning.mjs`), a sibling of `findActionPath` with no `isGoal` at all — every state reachable
87
+ from the start within `maxDepth` is a result, not just one goal. Shares only the frontier-seeding
88
+ step with `findActionPath`; the expand loops stayed independent (halting/accumulation semantics
89
+ differ enough to make a shared core more complex, not less). Proven against a toy graph with a real
90
+ cycle and a same-length two-path convergence. `test/planning.test.mjs`, 5 new tests. The WIRING half
91
+ (teach-shape recognizer + query-dispatcher branch, both in `chat.mjs`) is deliberately deferred,
92
+ kernel-only per this task's own scoping — see `PLAN_TAUGHT_RELATIONS.md`/`HANDOVER.md` for detail.
93
+
94
+ **`PLAN_TAUGHT_RELATIONS.md` Phase 2 — DONE (2026-07-09)**: closes Item 1's own live-found
95
+ query-side gap ("is ahab the father of john" now resolves directly) and Item 2 (relation alias/union
96
+ query-side chase — a taught "father ⊑ parent" alias lets "is ahab a parent of john" resolve off the
97
+ father fact). One new recognizer (`RELATION_FACT_YESNO_RE`) and one new local helper
98
+ (`relationFactsFor`) in `factReadBack`, tried BEFORE `ISA_ASK_RE` gets a chance at the overlapping
99
+ shape. The teach-side "kind of"/"type of" fix (`stripKindOf`) is a genuine one-liner.
100
+ `test/chat-taught-relations.test.mjs` (new file), 4 tests. `npm test` 1382 → 1386. Phase 4 (compose2
101
+ rule, next in this plan's build order) reuses `relationFactsFor` as its own per-hop edge lookup.
102
+
103
+ **`PLAN_TAUGHT_RELATIONS.md` Phase 4 — DONE (2026-07-09)**: Item 3 (fixed-hop `compose2` composition
104
+ rule — "a grandparent is a parent of a parent" teaches a Rule, and "is ahab a grandparent of
105
+ ishmael" resolves via a hop-counted `findActionPath` search over the taught father facts,
106
+ alias-chased through "parent" via Phase 2's own `relationFactsFor`). The hop-counting discipline
107
+ (`{ entity, hopsTaken }` state, `isGoal` requiring exactly 2 hops) is live-verified load-bearing: a
108
+ 1-hop and a 3-hop path through the SAME father/parent edges both correctly decline in the same store
109
+ where the genuine 2-hop pair resolves yes. Full family-tree chain (two father facts + the alias + the
110
+ compose2 rule) live-verified end-to-end via the piped CLI. `test/chat-taught-relations.test.mjs`
111
+ extended with 5 more tests (9 total). `npm test` 1386 → 1391.
112
+
113
+ **`PLAN_TAUGHT_RELATIONS.md` Phase 5 — DONE (2026-07-09)**: Item 4 (property-filtered composition
114
+ rule — "a grandfather is a grandparent who is male" teaches a `filter`-kind Rule). Required
115
+ refactoring Phase 2/4's `relAsk` dispatcher's three inline steps into one recursive closure,
116
+ `resolveRelationChase`, so a filter rule's base resolves GENERICALLY — the function calling itself —
117
+ whether the base is a plain taught relation or another Rule (e.g. compose2), never assuming which.
118
+ A hit requires both the base chase to resolve AND the subject to carry the taught property
119
+ (`mgx:hasProperty`); live-verified both failure modes separately (base fails outright vs. base holds
120
+ but the property filter correctly excludes the candidate) plus a filter whose base is a plain
121
+ relation (not a compose2 rule at all), proving the genericity. `test/chat-taught-relations.test.mjs`
122
+ extended with 4 more tests (13 total). `npm test` 1391 → 1395.
123
+
124
+ **`PLAN_TAUGHT_RELATIONS.md` Phase 6 — DONE (2026-07-09), WIRING half — the plan's build is now
125
+ COMPLETE, all six items.** Item 6 (recursive/reachability rule — "a descendant is a parent, or a
126
+ parent of a descendant" teaches a `recursive`-kind Rule; "list the descendants of ahab" enumerates
127
+ the full reachability set via `findReachableSet`, the kernel half already shipped, reused unchanged).
128
+ The query side is the one genuine kind-change among all six items (a reachability-SET enumeration,
129
+ not a yes/no chase), landed as a sibling of Phase 5's `resolveRelationChase` rather than a fourth
130
+ branch inside it — mirroring `findActionPath`/`findReachableSet`'s own sibling split at the kernel
131
+ level. Cycle safety (two individuals mutually taught as each other's parent) and a malformed
132
+ self-reference teach attempt (guarded for free by the teach regex's own backreference) both
133
+ live-verified. `test/chat-taught-relations.test.mjs` extended with 5 more tests, including one
134
+ comprehensive ALL-SIX-items integration test (18 total). `npm test` 1395 → 1400. **Nothing remains
135
+ outstanding from `PLAN_TAUGHT_RELATIONS.md`'s original six-item scope.**
136
+
137
+ **INFBENCH re-measured against 1.3.1** (measurement-only dispatch, 2026-07-09): `INFBENCH_1.3.1.md`
138
+ finds the ladder unchanged, byte-for-byte, since `1.3.0` — the four `PLAN_TAUGHT_RELATIONS.md`
139
+ phases that completed the plan (alias/union, `compose2`, property-filter, recursive/reachability
140
+ wiring) don't touch any band, confirmed by a zero-diff row comparison of both runs' raw product
141
+ files plus a direct check that no INFBENCH case's premises/query ever reach the new relational-teach
142
+ phrasing. Still gated at INF-B1 (33% completion), unchanged for a fourth consecutive measured
143
+ version — an honest, expected result given the new surface and the ladder measure different things.
144
+
145
+ **`PLAN_TAUGHT_RELATIONS.md` live-testing follow-up — DONE (2026-07-09)**: the operator live-tested
146
+ the full family-tree example end-to-end and found two real gaps, both fixed in `src/chat.mjs`. Gap 1:
147
+ a recognized-but-unsatisfied relational query used to fall to the GENERIC structural wall instead of
148
+ naming the relation — fixed by distinguishing "relation/rule name never taught" from "name known, this
149
+ pair's chase came up short" right in the `(a0)` block, each with its own specific decline text. Gap 2:
150
+ the REVERSE query shape ("who is the grandparent of john") didn't exist at all — new recognizer
151
+ `RELATION_WHO_ASK_RE` + a new `(a0.2)` block in `factReadBack`, re-deriving `resolveRelationChase`'s
152
+ same resolution logic (direct/alias/compose2/filter) walked backward from the object, reusing
153
+ `findReachableSet` unmodified for the compose2 reverse hop-chase. Live-verified the operator's own
154
+ repro exactly: "who is the grandparent of ishmael" → ahab (full 2-hop derivation cited); "who is the
155
+ grandparent of john" → an honest empty (never a wrong guess). `test/chat-taught-relations.test.mjs`
156
+ extended with 8 more tests (26 total). `npm test` 1400 → 1408, zero regressions. **Nothing remains
157
+ outstanding from `PLAN_TAUGHT_RELATIONS.md`.**
38
158
 
39
159
  ### Shipped this session
40
160
 
@@ -63,6 +183,17 @@ Test count across the session's later stretch:
63
183
  hand-rolled copy of `WALL_MISS_RE` with the real export; and extracted a shared session-driver
64
184
  helper (`test/helpers/session.mjs`), replacing 11 near-duplicate `drive()`/`driveSession()`
65
185
  implementations. Full detail is in `HANDOVER.md`'s "Test-suite health pass" entry.
186
+ - **Vocabulary-growth mirror fix.** New vocabulary used to grow one-directionally only: "redis is
187
+ a cache" could mint the unknown subject "redis" because the object "cache" was already a known
188
+ noun, but the reverse ("every cache is a store," subject known, object unknown) declined
189
+ outright. Added `unknownObjectFallback`, gated on a genuine universal quantifier ("every"/"each"/
190
+ "all") so it can't reopen the general lexicon bypass the existing bare/"a" shapes rely on. A term
191
+ minted by either direction now grounds a later sentence exactly like a lexicon word, using
192
+ taught-only groundedness checks that deliberately exclude the bulk ConceptNet corpus seed (the
193
+ corpus mentions ordinary English words constantly and must never silently count as "grounded").
194
+ When both sides are totally ungrounded, tmct still declines, but now with an actionable grounding
195
+ nudge instead of a bare "I couldn't store that." New coverage in
196
+ `test/chat-teach-quantifier.test.mjs`.
66
197
  - **Compound-name resolution**, from the operator's own worked example: "the payment system" now
67
198
  finds `PaymentSystem`, `payment-system`, a compound path like
68
199
  `westfield-payment-system/src/MyCode.cs`, and an interface-style name like
@@ -985,14 +1116,22 @@ minimal benchmark domains before anything domain-general is attempted:
985
1116
  slot (`game`) threaded through `createSession`/`runTurn` exactly the way `focus` already is,
986
1117
  kept deliberately separate from the `pending` pagination field since a game must survive an
987
1118
  aside mid-play, unlike a listing remainder.
988
-
989
- Both docs converge on the SAME one genuinely new primitive neither doc found already built
1119
+ - `PLAN_TAUGHT_RELATIONS.md` — teaching tmct brand-new relations and rules through ordinary chat
1120
+ (a taught Prolog-style family tree, none of the kinship vocabulary hardcoded), the first of the
1121
+ three to need a successor function SYNTHESIZED from data the user taught in an earlier turn,
1122
+ rather than hand-written per domain the way Hanoi's `legalMoves` and guess-number's
1123
+ interval-update rule are. Its own enumeration capability ("list the descendants of X," no fixed
1124
+ goal) needs a genuine new sibling kernel, `findReachableSet`, since `findActionPath` only ever
1125
+ searches toward one goal.
1126
+
1127
+ All three docs converged on the one genuinely new primitive none of them found already built
990
1128
  anywhere in tmct: something that computes a SUCCESSOR STATE (apply a chosen action, produce the
991
1129
  next graph/belief to reason over) — every existing traversal (`ancestorsOf`, `computeFind`,
992
- `findIsaChain` itself) is read-only. That primitive, plus a still-open recognition question (how
993
- tmct notices "the user wants goal-directed action" at all, and whether multi-step execution needs
994
- confirmation before running) is the real next-session scope a dedicated design/implementation
995
- session, not a routing fix.
1130
+ `findIsaChain` itself) is read-only. That primitive now exists (`findActionPath`, `src/planning.mjs`,
1131
+ shipped this session see "Shipped this session" above), proven against a small toy graph but not
1132
+ wired into any of the three domains yet. The remaining next-session scope is that wiring, plus a
1133
+ still-open recognition question: how tmct notices "the user wants goal-directed action" at all, and
1134
+ whether multi-step execution needs confirmation before running.
996
1135
 
997
1136
  ### The design horizon
998
1137
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polycode-projects/the-mechanical-code-talker",
3
- "version": "1.2.0",
3
+ "version": "1.3.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.",