@polycode-projects/the-mechanical-code-talker 1.10.14 → 1.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/README.md CHANGED
@@ -114,6 +114,23 @@ tmct> /exit
114
114
  **[Try it live in your browser →](https://polycode-projects.gitlab.io/the-mechanical-code-talker/)**
115
115
  is a real, interactive chat demo running client-side. Your browser runs the
116
116
  actual query engine against a small example codebase, no server, no install.
117
+ The page leads with the **memory ledger**: every fact as a readable sentence,
118
+ drill by clicking the terms inside them, and an in-page chat whose answers
119
+ focus the ledger.
120
+
121
+ Two more surfaces, both generated by tmct itself:
122
+
123
+ ```bash
124
+ npx tmct viz # ledger.html — your own memory as the same
125
+ # readable, self-contained explorer
126
+ npx tmct init
127
+ npx tmct import --file .tmct/imports/games/hanoi-3.txt
128
+ npx tmct chat --prompt 'disk-1 rests on disk-2. disk-2 rests on disk-3.
129
+ disk-3 rests on peg-a. the goal is that every disk rests on peg-c. solve it.' \
130
+ --render blocks --output plan.html # an animated replay of the solved plan
131
+ ```
132
+
133
+ More on the game file and the planner under "Teach it a game" below.
117
134
 
118
135
  ## How it interprets you
119
136
 
@@ -127,65 +144,38 @@ Those triples are statements it can store, retrieve, and answer from later.
127
144
  Text that doesn't fit the grammar still gets the tolerant strategies. Nothing
128
145
  is rejected for being loose, fuzzy, or misspelled.
129
146
 
130
- **Everyday question shapes.** Bare "what is Commit" (no article) now resolves
131
- like "what is a commit" for tmct's own vocabulary. "What's model.mjs for" and
132
- "what's model.mjs about" answer like "what does model.mjs do". "Is Base a
133
- superclass of Widget" is read as the reverse of "is Widget a subclass of
134
- Base", the same relationship either way round. "Recent commits" and "the last
135
- commit" resolve to real dated history, not a literal string miss. Polite or
136
- indirect framing reaches the same capability as a direct request: "I'd like
137
- you to remember X" teaches like bare "remember X"; "please tell me about X"
138
- and "search for X" describe and find exactly as their direct forms do.
139
-
140
- **Negation and passive.** "Which modules do *not* import X?" computes a bounded
141
- **set complement** over the graph. An empty result stays a miss rather than a
142
- fabricated list (a non-enumerable type, like arbitrary *changes*, is refused
143
- outright). Reversible-passive questions traverse the right direction:
144
- "what is imported by Y" and "what does Y import" are understood as opposite
145
- edges, not the same one.
146
-
147
- **Finding by description.** "find me the payment class" searches by type and a
148
- fuzzy match against the entity's own properties, instead of making you name it
149
- exactly. It checks the type itself and its subclasses first. Only if nothing
150
- matches there does it widen to a related type, and when it does, it says so
151
- plainly rather than presenting the looser match as exact.
152
-
153
- **Comparing two things.** "compare TaskController and UserController" or "how
154
- is TaskController different from UserController" lines up both entities'
155
- shared and differing edges side by side: *"Comparing TaskController and
156
- UserController (both Class): inherits [seon:hasSuperType]: TaskController (1)
157
- -> Controller; UserController (1) -> Controller"*. Every row is a real edge
158
- or attribute from the graph, never a hand-written diff.
159
-
160
- **Up-refining to a containing module.** A class rarely has its own
161
- symbol-precise commit or import record. "who touched TaskController" answers
162
- from its containing module's real history instead of a confident-looking but
163
- wrong "nothing touched it".
164
-
165
- **Following a list.** tmct remembers the last list it gave you. After
166
- "which modules import src/core/model.mjs", "which of those are tested" or
167
- "how many of those" resolves "those"/"them" against that list, not a fresh,
168
- unresolved pronoun.
169
-
170
- **Synonyms and everyday phrasing.** tmct matches many of the words people
171
- actually use for the same idea, from a curated synonym list plus a filtered
172
- ConceptNet slice. A slightly different word for the same concept still
173
- resolves. It also follows a few common sentence shapes: clauses starting with
174
- *because/although/while*, and conditionals ("if X were removed, what
175
- breaks"). It flags a question whose premise doesn't hold, too: "why does X
176
- still import Y" when it no longer does.
177
-
178
- **Response finishing.** Before an answer is printed it is segmented into typed
179
- spans: prose versus *protected* entities, paths, numbers, code, provenance, and
180
- receipts. A small data-driven grammar pass then runs on the prose spans only,
181
- under a guard that proves the protected spans came through byte-for-byte. Today
182
- that pass fixes the a/an article defect. Broader voice and agreement rules are
183
- implemented but parked until they earn their place on the benchmark.
147
+ On top of that base, tmct reads the shapes people actually use, and each one
148
+ resolves to a real graph traversal or declines honestly:
149
+
150
+ - everyday question forms: "what is Commit", "what's model.mjs for",
151
+ "recent commits" as real dated history;
152
+ - polite or indirect framing: "I'd like you to remember X" teaches like bare
153
+ "remember X";
154
+ - negation as a bounded **set complement**: "which modules do *not* import
155
+ X?", with an empty result staying a miss, never a fabricated list;
156
+ - reversible passives: "what is imported by Y" and "what does Y import" are
157
+ opposite edges, not the same one;
158
+ - finding by description: "find me the payment class" checks the type and
159
+ its subclasses first, and says so plainly when it widens;
160
+ - comparison: "compare TaskController and UserController" lines up both
161
+ entities' real edges side by side, never a hand-written diff;
162
+ - list follow-ups: after "which modules import src/core/model.mjs",
163
+ "which of those are tested" resolves against that list;
164
+ - curated synonyms plus a filtered ConceptNet slice, clause openers
165
+ (*because/although/while*), conditionals, and false-premise flags ("why
166
+ does X still import Y" when it no longer does).
167
+
168
+ The full catalog with measured coverage lives in `CAPABILITIES_1.7.3.md` and
169
+ the `BENCHMARK_*.md` reports.
170
+
171
+ **Response finishing.** Before an answer prints, it is segmented into typed
172
+ spans: prose versus *protected* entities, paths, numbers, code, provenance,
173
+ and receipts. A small data-driven grammar pass runs on the prose spans only,
174
+ under a guard that proves the protected spans came through byte-for-byte.
184
175
 
185
176
  A frozen regression suite plays out full multi-turn dialogues built from these
186
- phrasings, at every complexity level this project defines. That ranges from a
187
- single question up to a messy, typo-ridden real user. Tier-by-tier detail is
188
- in `HANDOVER.md` and `ROADMAP.md`.
177
+ phrasings, from a single question up to a messy, typo-ridden real user.
178
+ Tier-by-tier detail is in `HANDOVER.md` and `ROADMAP.md`.
189
179
 
190
180
  ## How it guides you
191
181
 
@@ -250,13 +240,7 @@ const memory = await loadMemory(dir);
250
240
  const graphService = createCompletionsGraphAdapter(graph, memory);
251
241
 
252
242
  const { text } = await generateCompletion(dir, "Store", { query: "Store", graph, memory, graphService });
253
- console.log(text);
254
- ```
255
-
256
- ```
257
- Attribute: prose_tokens = memory record store [mgx:hasProseTokens]. Attribute:
258
- doc = In-memory record store. [seon:hasDoc]. Other matches: src/core/store.mjs
259
- (Module), loadStore (Function), saveStore (Function), testLoadStore (Function).
243
+ console.log(text); // prints the same text as the chat answer above
260
244
  ```
261
245
 
262
246
  Full pipeline design in `archive/PLAN_COMPLETIONS.md`.
@@ -328,6 +312,45 @@ proof chain, composed answer) for a caller that wants to consume this
328
312
  programmatically rather than read the report. `tmct plan --help` has the full
329
313
  flag reference.
330
314
 
315
+ ## Teach it a game, then ask it to plan
316
+
317
+ The planner above works over a fixed toolset. This one works over rules you
318
+ teach. A game definition is a plain-text file of controlled English — the
319
+ classes, the pieces, the ordering, and the legal moves as taught action
320
+ rules — with `#` comment lines carrying example prompts. `tmct init`
321
+ scaffolds one at `.tmct/imports/games/hanoi-3.txt`, and
322
+ `tmct import --file` teaches it sentence by sentence, reporting every line
323
+ and refusing (exit 1) if any sentence declines.
324
+
325
+ Then one message states the board and the goal, and "solve it" searches the
326
+ taught rules for the shortest move sequence:
327
+
328
+ ```
329
+ tmct> disk-1 rests on disk-2. disk-2 rests on disk-3. disk-3 rests on peg-a.
330
+ the goal is that every disk rests on peg-c. solve it.
331
+ plan found — 7 moves (shortest):
332
+ 1. move disk-1 onto peg-c
333
+ 2. move disk-2 onto peg-b
334
+ 3. move disk-1 onto disk-2
335
+ 4. move disk-3 onto peg-c
336
+ 5. move disk-1 onto peg-a
337
+ 6. move disk-2 onto disk-3
338
+ 7. move disk-1 onto disk-2
339
+
340
+ because — you taught me the "move onto" rule and 3 ordering facts. Say "next" to make move 1, or ask "what moves are legal now".
341
+
342
+ Goal (inferred): Plan a move sequence from the current state to the goal (7 moves).
343
+ ```
344
+
345
+ "next" executes one move at a time, writing each board state into memory as
346
+ facts; the final step re-reads those facts and confirms the goal from them,
347
+ never assuming success. The search is genuine and domain-general: the test
348
+ suite teaches Towers of Hanoi purely as sentences for 1 to 8 disks and
349
+ asserts the plan is exactly 2^n − 1 moves every time, and a second game
350
+ (`crates.txt`, stacking crates with different rules and a two-goal
351
+ conjunction) solves with zero interpreter changes. `--render blocks` writes
352
+ the plan as a self-contained animated page (see "Two more surfaces" above).
353
+
331
354
  ## How it remembers
332
355
 
333
356
  tmct's memory has two layers, both fed by every parsed request and response and
@@ -359,38 +382,21 @@ reasoning). Design detail and the full fact-count tables are in `archive/PLAN_SE
359
382
  The default memory backend writes an OWL-labelled JSON file under `.tmct/`.
360
383
  Two more exist: `memory` keeps taught facts in the process only, nothing
361
384
  written to disk; `sqlite` persists them to a local SQLite file instead
362
- (`.tmct/memory/graph.sqlite`).
363
-
364
- Pick one at init time and it sticks. `tmct init --memory-backend sqlite`
365
- writes the choice into `tmct.toml`, and every later `tmct chat` in that repo
366
- uses it with no flag needed:
367
-
368
- ```bash
369
- tmct init --memory-backend sqlite # writes [memory] backend = "sqlite" to tmct.toml
370
- tmct chat # picks it up automatically
371
- tmct chat --memory-backend memory # override for just this session
372
- ```
373
-
374
- Precedence is `--memory-backend` flag > `TMCT_MEMORY_BACKEND` env > tmct.toml's
375
- `[memory] backend` > the default. A library caller sets the same thing
376
- directly: `runChat({ memoryBackend: "sqlite" })`.
385
+ (`.tmct/memory/graph.sqlite`). `tmct init --memory-backend sqlite` writes the
386
+ choice into `tmct.toml` and every later `tmct chat` in that repo picks it up.
387
+ Precedence is `--memory-backend` flag > `TMCT_MEMORY_BACKEND` env >
388
+ tmct.toml's `[memory] backend` > the default. A library caller sets the same
389
+ thing directly: `runChat({ memoryBackend: "sqlite" })`.
377
390
 
378
391
  Teaching isn't limited to the ACE grammar's fixed shapes. Tell tmct an
379
392
  arbitrary fact, like "margo really eats ribs", and it mints a fact you can
380
- later ask about directly: "what does margo eat", or "does margo eat ribs".
381
-
382
- New vocabulary compounds as you teach it. "redis is a cache" mints "redis" as
383
- a class-level concept even though it was never in the built-in lexicon, and a
384
- later "every cache is a store" does the same for "store," the other way
385
- round, as long as one side of the sentence is already grounded. tmct never
386
- mints a fact between two totally ungrounded terms. It declines instead, and
387
- nudges you to ground one side first. Quantified teaching works too: "some
388
- functions are risky" stores the quantifier, and a later "how many functions
389
- are risky" answers "A few."
390
-
391
- Once you've taught a few facts, "how many facts are there" counts them back.
392
- That's the same count phrasing a code graph answers "how many classes are
393
- there" with, just now reading tmct's own memory.
393
+ ask about directly: "what does margo eat". New vocabulary compounds as you
394
+ teach: "redis is a cache" mints "redis" even though it was never in the
395
+ built-in lexicon, as long as one side of the sentence is already grounded
396
+ tmct never mints a fact between two totally ungrounded terms; it declines and
397
+ nudges you to ground one side first. Quantified teaching stores the
398
+ quantifier ("some functions are risky" "how many functions are risky"
399
+ "A few."), and "how many facts are there" counts the store back.
394
400
 
395
401
  ### Provenance and trust
396
402
 
@@ -410,10 +416,8 @@ provenance** rather than silently picking a winner.
410
416
 
411
417
  `tmct syllogise [--depth n] [--budget n]` is an offline, bounded, deterministic
412
418
  batch that forward-chains the memory's `rdfs:subClassOf` closure into new
413
- **entailed** facts, pre-deriving what the trusted sources already imply. It runs
414
- once automatically after seeding and on demand; the entailed facts are
415
- **low-trust and retractable** (never outranking a stated fact) and this never runs
416
- on the chat's hot path.
419
+ **entailed** facts. They are low-trust and retractable, never outranking a
420
+ stated fact, and this never runs on the chat's hot path.
417
421
 
418
422
  ## Install & use
419
423
 
@@ -423,7 +427,7 @@ tmct # bare = chat (the headline)
423
427
  tmct chat --repo /abs/path/to/repo # chat over a specific repo's graph
424
428
  tmct init # scaffold .tmct/, tmct.toml, seed + provenance
425
429
  tmct syllogise # offline: pre-derive entailed facts (maintenance)
426
- npm run viz -- --output graph.html && open graph.html # self-contained HTML graph view
430
+ npm run viz && open ledger.html # self-contained HTML memory-ledger explorer
427
431
  ```
428
432
 
429
433
  Inside the chat: `/help` lists commands, `/memory` inspects what tmct remembers
@@ -461,6 +465,11 @@ Usage:
461
465
  see src/graph-merge.mjs); wins over --repo/TMCT_GRAPH_FILE/tmct.toml
462
466
  [--config <path>] an alternate tmct.toml location (a file or a directory)
463
467
  [--ephemeral] read the graph but write nothing back (demo/read-only)
468
+ [--prompt "<text>"] one-shot: run the prompt's sentences as turns and print
469
+ the final answer (teach state first, trigger last)
470
+ [--render blocks] with --prompt: when the final turn produced a plan,
471
+ write it as a self-contained animated page
472
+ [--output <path>] the rendered page's path (default plan.html)
464
473
  [--narrate] start with narrate mode on — a verbose, developer-facing
465
474
  trace of decision points/matched pattern/results/goal per
466
475
  turn, appended under a "--- narrate ---" marker (also
@@ -518,6 +527,9 @@ already set up. Its `--graph` flag works differently from the others: it appends
518
527
  [--ontology <name|path>] DIFFERENT operation from the others: it APPENDS to
519
528
  [--lexicon <name|path>] tmct.toml's graph_files array (multi-graph growth),
520
529
  [--graph <path>] never an extensions-bundle activation.
530
+ [--file <definition.txt>] teach a plain-text definition file sentence by
531
+ sentence (# lines are comments); any declined
532
+ sentence exits non-zero with the sentence named
521
533
  [--memory-backend <default|memory|sqlite>] same knob as `tmct init`
522
534
  [--config <path>]
523
535
  ```
@@ -540,23 +552,18 @@ inference" above:
540
552
  [--config <path>] bounded, low-trust, retractable entailed facts (never on the chat path)
541
553
  ```
542
554
 
543
- `tmct viz` renders the memory graph to a single HTML file you can open in a browser:
555
+ `tmct viz` renders the memory graph as the ledger explorer a single,
556
+ self-contained HTML file you can open in a browser:
544
557
 
545
558
  ```
546
- tmct viz [--repo <abs>] write one self-contained, navigable HTML file rendering the
547
- [--focus <id>] memory graph: pan/zoom, click a node for its label/class/
548
- [--term <word>] timestamps. Seeds from the most recently created individual
549
- [--depth <n>] by default (--focus <id> or --term <word> override it);
550
- [--limit <n>] --output defaults to graph.html in the cwd.
551
- [--hub-degree <n>] --depth = max arcs (hops) from the focus node (default 3);
552
- [--edge-kind <mode>] --limit = spiral length, total nodes walked (default 300);
553
- [--output <path>] --hub-degree = stop expanding THROUGH a node above N
554
- [--config <path>] connections, still shows it (default 40); --edge-kind =
555
- meta|relation|both (default both) — which edge kinds the
556
- walk follows (provenance-only, concept-relations-only, or
557
- both — see the page's own edge-kind toggle to change this
558
- live); --term <word> resolves to the Fact(s) whose subject/
559
- object normalizes to that word and seeds from there.
559
+ tmct viz [--repo <abs>] write one self-contained HTML page: the memory graph as a
560
+ [--focus <term>] readable ledger of fact-sentences around one focus term,
561
+ [--term <word>] with segments, a two-hop minimap, and an in-page chat dock
562
+ [--limit <n>] that answers from the embedded graph. Focuses on the newest
563
+ [--output <path>] taught fact's subject by default (--focus <term> or
564
+ [--config <path>] --term <word> override it); --output defaults to
565
+ ledger.html in the cwd; --limit caps the embedded fact
566
+ rows; --term resolves via the same normalization chat uses.
560
567
  ```
561
568
 
562
569
  `tmct serve` runs an Anthropic Messages API-compatible HTTP endpoint over the graph,
@@ -606,7 +613,7 @@ recognized key set, so you can see the full surface in one place
606
613
  # Newline-delimited-file form is also accepted: repositories = "repos.txt"
607
614
  repositories = ["../other-service", "../another-service"]
608
615
 
609
- # Where generated output (e.g. tmct viz's default graph.html) resolves to.
616
+ # Where generated output (e.g. tmct viz's default ledger.html) resolves to.
610
617
  out_root = "./out"
611
618
 
612
619
  # The code-graph JSON artifact. TMCT_GRAPH_FILE overrides this at runtime.
package/ROADMAP.md CHANGED
@@ -10,7 +10,10 @@ open items, session-scoped), see `HANDOVER.md` instead — this file doesn't dup
10
10
  A tolerant, ELIZA/PARRY-style chat surface over a codebase, obsessed with software the way PARRY was
11
11
  obsessed with the mafia — deterministic, zero-cost, **no LLM anywhere in the product path**. Guides a
12
12
  user toward precision queries rather than guessing; every answer is grounded, restates every genuine
13
- reading it finds in full, or is an honest miss when nothing grounds it at all.
13
+ reading it finds in full, or is an honest miss when nothing grounds it at all. Its visual surfaces —
14
+ the ledger explorer with its in-browser chat (`tmct viz`), the animated plan page
15
+ (`chat --prompt … --render blocks`), and the Pages homepage hero — are the same graph read out loud:
16
+ same engine, same provenance, no LLM.
14
17
 
15
18
  ## Ambition
16
19
 
@@ -48,9 +51,16 @@ getting silently traded away by inherited caution:
48
51
  and an NPC turn scheduler. Design-only.
49
52
  - **`PLAN_SYLLOGIST.md`** — retraction-aware consistency checking under a hard budget and trust
50
53
  tiers, the one open piece of the reasoning engine's research horizon. Design-only.
51
- - **`PLAN_GUESS_NUMBER.md` / `PLAN_HANOI.md`** — closed-loop and open-loop planning domains for the
52
- `findActionPath`/`findReachableSet` kernels, both already built and proven but not yet wired to
53
- either domain. Design-only.
54
+ - **`PLAN_HANOI.md`** — shipped in full, including the follow-ups: river-crossing (co-travel
55
+ effects, the forbidden-together constraint frame, 7-crossing oracle) and planner-side
56
+ consumption of `taught:` capability records (`/plan` in chat and bin). See its dated addenda.
57
+ - **`PLAN_GUESS_NUMBER.md`** — the closed-loop (observe-and-replan) planning domain for the same
58
+ kernels. Design-only.
59
+ - **`PLAN_VIZ_LEDGER.md`** — shipped in full, including the follow-ups, all resolved by
60
+ operator decision 2026-07-15: the ledger IS the `tmct viz` surface (node-link page removed),
61
+ `factAnswer`/`factReadBack` carry the additive `goal` field the dock renders, multi-valued
62
+ has/can facts are exempt from `findContradictions`, and page weight is budgeted (~561 KB
63
+ after this batch; revisit only if outgrown). See its dated addendum.
54
64
  - **`PLAN_CODE.md`** — small JS-function and HTML/CSS-fragment synthesis via a sandboxed headless
55
65
  browser (Track 1, program synthesis, already shipped). Blocked on a sandbox dependency decision.
56
66
  - **`PLAN_AGENTS.md`** — the governing plan for tmct's broader multi-repo arc (marginalia, seonix,