@polycode-projects/the-mechanical-code-talker 1.5.4 → 1.8.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.
Files changed (46) hide show
  1. package/README.md +123 -14
  2. package/ROADMAP.md +233 -1392
  3. package/bin/tmct.mjs +479 -98
  4. package/corpus/README.md +3 -0
  5. package/corpus/generated/README.md +43 -0
  6. package/corpus/generated/ace-surface-variants.jsonl +17 -0
  7. package/corpus/generated/manifest.json +9 -0
  8. package/corpus/tier2/generate.mjs +14668 -0
  9. package/corpus/tier2/human-examples-large.jsonl +1928 -0
  10. package/corpus/tier2/human-examples-medium.jsonl +356 -0
  11. package/corpus/tier2/human-examples.jsonl +120 -0
  12. package/corpus/tier2/human-large.jsonl +12001 -0
  13. package/corpus/tier2/human-medium.jsonl +944 -0
  14. package/corpus/tier2/human.jsonl +664 -0
  15. package/corpus/tier2/manifest.json +42 -0
  16. package/package.json +14 -8
  17. package/src/answer-variants.json +47 -0
  18. package/src/answer-variants.mjs +67 -0
  19. package/src/ask-browser-entry.mjs +34 -0
  20. package/src/ask-browser.bundle.js +5095 -0
  21. package/src/ask-vocab.mjs +93 -8
  22. package/src/ask.mjs +451 -49
  23. package/src/chat.mjs +1391 -141
  24. package/src/cli-args.mjs +164 -0
  25. package/src/codegraph.mjs +170 -32
  26. package/src/completions/graph-adapter.mjs +118 -0
  27. package/src/extensions.mjs +100 -19
  28. package/src/grammar/ace.mjs +85 -3
  29. package/src/grammar/lexicon-core.json +9531 -63
  30. package/src/grammar/lexicon.mjs +58 -8
  31. package/src/graph-merge.mjs +114 -0
  32. package/src/index.mjs +14 -0
  33. package/src/init.mjs +40 -14
  34. package/src/interpret/normalize.mjs +88 -3
  35. package/src/interpret/strategies/grammar.mjs +10 -0
  36. package/src/interpret/strategies/keywords.mjs +20 -0
  37. package/src/interpret/strategies/noise-strip.mjs +73 -4
  38. package/src/memory/core.mjs +466 -8
  39. package/src/router/goal-reasoner.mjs +41 -7
  40. package/src/router/guardrail.mjs +37 -7
  41. package/src/router/resolver.mjs +50 -4
  42. package/src/sessions.mjs +5 -1
  43. package/src/source.mjs +54 -1
  44. package/src/syllogise.mjs +398 -27
  45. package/src/toml-config.mjs +13 -4
  46. package/src/viz.mjs +541 -0
package/ROADMAP.md CHANGED
@@ -1,1392 +1,233 @@
1
- # tmct ROADMAP
2
-
3
- tmct v0.1.0 was a **whole-package lift** of the seonix chat surface (published
4
- as `@polycode-projects/mct`): identical shape, green tests, new branding. That
5
- was deliberate. It gave every ambition below a working, tested starting point
6
- instead of a green field. v0.2.0 is the **reshape**: the lift's LLM fallback,
7
- extraction stack, and MCP server are gone, and the package, naming, and license
8
- now match the product this document describes.
9
-
10
- This roadmap is organized into phases. The original 16 ambition items are
11
- mapped into them (item numbers retained for traceability); the seven sketches
12
- formerly held in `code-talker-ideas.txt` are folded into items 8–11 below and
13
- the file has been deleted.
14
-
15
- ## Working model: coordinator + background sub-agents
16
-
17
- Standing orders for every session working this repo (copied verbatim from this repo's own
18
- `CLAUDE.md` on 2026-07-10, at the operator's request, so the discipline is visible directly in
19
- the project's own operating docs and not just the config file):
20
-
21
- Run big tasks in **concurrent background sub-agents** and keep the main chat free — the main
22
- session is the COORDINATOR (plans, launches, integrates, answers the operator), not the worker.
23
-
24
- - Decompose into workstreams with **clear file-ownership boundaries**; serialize on shared
25
- files (one agent owns `package.json`, `src/`, `bin/`, `test/` sequences; docs/site tracks
26
- run in parallel).
27
- - **Keep the chat for chat**: anything long-running (benchmarks, judge passes, builds, test
28
- sweeps) executes as a BACKGROUND task at maximum safe concurrency (the chatbench judge
29
- defaults to `--concurrency 12`); the main session launches it, keeps coordinating and
30
- conversing, and collects results on the completion notification. Never block the
31
- conversation on a run.
32
- - Commit per completed step with the repo-local identity (`antony@polycode.co.uk` /
33
- `Antony at Polycode`); keep `npm test` green at every commit.
34
- - Push/publish is gated on the operator (CI publishes on version bump on `main`).
35
- - **Version bump timing:** only bump the version (`package.json` + `package-lock.json`) at the
36
- moment of actually pushing a release the bump commit is part of that same push, not a
37
- separate step staged in advance. Default to a patch bump unless the batch is clearly
38
- feature-level (minor) or breaking (major). Do NOT pre-stage a future version number and leave
39
- it sitting unpushed in git between releases that produced confusing "linking to a version
40
- that doesn't exist yet" noise in practice and was reverted by operator instruction 2026-07-09.
41
- Between pushes, `package.json`'s version should always equal whatever's actually live on npm.
42
-
43
- ## Where we are now (2026-07-09)
44
-
45
- The full `SKILL_CHAT_PLAYTEST.md` dialogue-flow tier ladder is complete, tiers 0 through 6.
46
- Tiers 0, 1, 2, and 4 each closed in one pass. Tier 3 took 7 passes to track down a recurring
47
- `resolveObject` substring-match weakness. Tiers 5 and 6 each ran the full 5-cycle cap and each
48
- turned up one genuinely important correctness bug alongside a batch of routing fixes. Full
49
- per-cycle detail is in `HANDOVER.md`'s "The dialogue-flow playtest loop" section.
50
-
51
- `npm test` is green at **1355** (up from 1258 at the start of this session). v1.0.7 is
52
- published (0.9.11 → 1.0.0 → 1.0.7 across an earlier session; the exact release chain and
53
- file:line detail are in `HANDOVER.md`). Nothing has pushed since, so the local version sits at
54
- 1.0.9 per the bump-at-push-time policy.
55
-
56
- Test count across the session's later stretch:
57
-
58
- | Work | `npm test` |
59
- | --- | --- |
60
- | Playtest-freeze verification pass (Tiers 0/1/2/4 + operator bugs A-F, chat-tested live and frozen as regressions) | 1299 → 1303 |
61
- | `resolveObject` tier-3 derivational-stem bridge, closing the one dead-end the freeze pass found | 1303 → 1307 |
62
- | Tier 5 (teach + recall + reasoning in dialogue), 5 cycles | 1307 → 1328 |
63
- | Tier 6 (the messy real user), 5 cycles, run alongside a background test-suite health pass | 1328 → 1345 |
64
- | Compound-name resolution (multi-word queries to joined-token symbol names) | 1345 → 1352 |
65
- | Vocabulary-growth mirror fix known-subject/unknown-object mint (`unknownObjectFallback`), so new terms compound turn over turn | 1352 → 1355 |
66
- | `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 |
67
-
68
- **INFBENCH re-measured against 1.2.0** (measurement-only dispatch, 2026-07-09): `INFBENCH_1.2.0.md`
69
- confirms chat/INF-A2 now closes to 100% (the cax-sco/proof-chase win the STATUS banner above already
70
- claimed) but also finds chat/INF-C1 has flipped from an honest ceiling to a genuine 93%-fabrication
71
- regression, traced to the new general-verb-to-predicate query lane answering "no" on an absent fact
72
- instead of declininga real correctness bug, separate from and cheaper than the still-gating
73
- INF-B1 (`cax-dw`) work.
74
-
75
- **INF-C1 fabrication FIXED (2026-07-09, follow-up dispatch)**: `GENERAL_VERB_YESNO_RE`'s no-hit
76
- branch (`src/chat.mjs`) now declines (`null`) instead of asserting a confident "no" when no taught
77
- fact matches the queried subject/predicate/object triple, falling through to the ordinary
78
- honest-miss cascade same convention as `WHO_OWNS_RE`'s own no-hit branch. Re-ran `npm run
79
- infbench`: chat/INF-C1 is back to **93% completion / 0% fabrication**, its `0.8.2`-era honest
80
- ceiling, exactly as predicted (up from `1.2.0`'s 0% completion / 93% fabrication). Everything else
81
- in the ladder is unchanged still gated at INF-B1 (33% completion), unaffected by this fix.
82
- `npm test` 1361 1362 (this fix's own contribution; see `HANDOVER.md` for the combined total
83
- alongside the concurrent Rule-storage dispatch).
84
-
85
- **`PLAN_TAUGHT_RELATIONS.md`** (research/design, 2026-07-09, nothing implemented): scopes teaching
86
- tmct brand-new relations and rules through ordinary chat (a Prolog-style family tree father,
87
- parent, grandparent, descendant none of it hardcoded, all of it taught), reusing
88
- `findActionPath` for the hop-counted relation chase and a new sibling kernel, `findReachableSet`,
89
- for open-ended enumeration. Live-testing while designing it surfaced real, already-shipped gaps:
90
- the "is a kind of" teach phrasing isn't accepted anywhere today, a "parent" example in the original
91
- scoping conversation only worked by an accidental lexicon collision, and a wrapped property-teach
92
- shape (`TEACH_PROPERTY_RE`) has no groundedness check at all, unlike the newer subject/object
93
- mint-fallback pair's explicit discipline. See `HANDOVER.md` for the full finding list; this is
94
- next-session pickup material, not yet started.
95
-
96
- **`PLAN_TAUGHT_RELATIONS.md` Phase 3 DONE (2026-07-09)**: the Rule storage foundation landed in
97
- `src/memory/core.mjs` (`RULE_CLASS`, `appendRule`, `findRuleByName`) — pure plumbing, zero
98
- `chat.mjs` change, reusing the existing Source/trust pipeline unmodified. `npm test` 1361 1371.
99
- Phase 4 (compose2 query-side wiring) is next in that plan's build order.
100
-
101
- **`PLAN_TAUGHT_RELATIONS.md` Phase 1 DONE (2026-07-09)**: Item 1 (relational fact teach,
102
- `RELATION_FACT_TEACH_RE` "ahab is the father of john" mints an ordinary Fact via
103
- `generalVerbPredicate`, reused verbatim) and Item 5 (adjective-mint, `unknownAdjectiveFallback` —
104
- "the cache is bespoke" / "TaskController is bespoke" mint `mgx:hasProperty`) both landed in
105
- `src/chat.mjs`. Query-side readback for Item 1 needed zero new machinery ("what do you know about
106
- X" / "does X <role> Y" both already confirm it); Item 5's own groundedness guard needed tightening
107
- beyond the original design to avoid reopening the pinned "module is banana" regression — see
108
- `PLAN_TAUGHT_RELATIONS.md`'s "Phase 1DONE" note for the full adjustment, plus a sharper,
109
- live-confirmed restatement of that doc's Verification finding 4 (`isConversational`'s ≤3-word gate
110
- pre-empts the teach lane entirely for a short bare sentence, not just its decline text — flagged,
111
- not fixed, still out of scope). `npm test` 1371 1377.
112
-
113
- **`PLAN_TAUGHT_RELATIONS.md` Phase 6, KERNEL half DONE (2026-07-09)**: `findReachableSet`
114
- (`src/planning.mjs`), a sibling of `findActionPath` with no `isGoal` at all every state reachable
115
- from the start within `maxDepth` is a result, not just one goal. Shares only the frontier-seeding
116
- step with `findActionPath`; the expand loops stayed independent (halting/accumulation semantics
117
- differ enough to make a shared core more complex, not less). Proven against a toy graph with a real
118
- cycle and a same-length two-path convergence. `test/planning.test.mjs`, 5 new tests. The WIRING half
119
- (teach-shape recognizer + query-dispatcher branch, both in `chat.mjs`) is deliberately deferred,
120
- kernel-only per this task's own scoping see `PLAN_TAUGHT_RELATIONS.md`/`HANDOVER.md` for detail.
121
-
122
- **`PLAN_TAUGHT_RELATIONS.md` Phase 2 DONE (2026-07-09)**: closes Item 1's own live-found
123
- query-side gap ("is ahab the father of john" now resolves directly) and Item 2 (relation alias/union
124
- query-side chase a taught "father parent" alias lets "is ahab a parent of john" resolve off the
125
- father fact). One new recognizer (`RELATION_FACT_YESNO_RE`) and one new local helper
126
- (`relationFactsFor`) in `factReadBack`, tried BEFORE `ISA_ASK_RE` gets a chance at the overlapping
127
- shape. The teach-side "kind of"/"type of" fix (`stripKindOf`) is a genuine one-liner.
128
- `test/chat-taught-relations.test.mjs` (new file), 4 tests. `npm test` 1382 1386. Phase 4 (compose2
129
- rule, next in this plan's build order) reuses `relationFactsFor` as its own per-hop edge lookup.
130
-
131
- **`PLAN_TAUGHT_RELATIONS.md` Phase 4 — DONE (2026-07-09)**: Item 3 (fixed-hop `compose2` composition
132
- rule "a grandparent is a parent of a parent" teaches a Rule, and "is ahab a grandparent of
133
- ishmael" resolves via a hop-counted `findActionPath` search over the taught father facts,
134
- alias-chased through "parent" via Phase 2's own `relationFactsFor`). The hop-counting discipline
135
- (`{ entity, hopsTaken }` state, `isGoal` requiring exactly 2 hops) is live-verified load-bearing: a
136
- 1-hop and a 3-hop path through the SAME father/parent edges both correctly decline in the same store
137
- where the genuine 2-hop pair resolves yes. Full family-tree chain (two father facts + the alias + the
138
- compose2 rule) live-verified end-to-end via the piped CLI. `test/chat-taught-relations.test.mjs`
139
- extended with 5 more tests (9 total). `npm test` 1386 1391.
140
-
141
- **`PLAN_TAUGHT_RELATIONS.md` Phase 5 DONE (2026-07-09)**: Item 4 (property-filtered composition
142
- rule "a grandfather is a grandparent who is male" teaches a `filter`-kind Rule). Required
143
- refactoring Phase 2/4's `relAsk` dispatcher's three inline steps into one recursive closure,
144
- `resolveRelationChase`, so a filter rule's base resolves GENERICALLY the function calling itself —
145
- whether the base is a plain taught relation or another Rule (e.g. compose2), never assuming which.
146
- A hit requires both the base chase to resolve AND the subject to carry the taught property
147
- (`mgx:hasProperty`); live-verified both failure modes separately (base fails outright vs. base holds
148
- but the property filter correctly excludes the candidate) plus a filter whose base is a plain
149
- relation (not a compose2 rule at all), proving the genericity. `test/chat-taught-relations.test.mjs`
150
- extended with 4 more tests (13 total). `npm test` 1391 1395.
151
-
152
- **`PLAN_TAUGHT_RELATIONS.md` Phase 6 DONE (2026-07-09), WIRING half the plan's build is now
153
- COMPLETE, all six items.** Item 6 (recursive/reachability rule "a descendant is a parent, or a
154
- parent of a descendant" teaches a `recursive`-kind Rule; "list the descendants of ahab" enumerates
155
- the full reachability set via `findReachableSet`, the kernel half already shipped, reused unchanged).
156
- The query side is the one genuine kind-change among all six items (a reachability-SET enumeration,
157
- not a yes/no chase), landed as a sibling of Phase 5's `resolveRelationChase` rather than a fourth
158
- branch inside it mirroring `findActionPath`/`findReachableSet`'s own sibling split at the kernel
159
- level. Cycle safety (two individuals mutually taught as each other's parent) and a malformed
160
- self-reference teach attempt (guarded for free by the teach regex's own backreference) both
161
- live-verified. `test/chat-taught-relations.test.mjs` extended with 5 more tests, including one
162
- comprehensive ALL-SIX-items integration test (18 total). `npm test` 1395 → 1400. **Nothing remains
163
- outstanding from `PLAN_TAUGHT_RELATIONS.md`'s original six-item scope.**
164
-
165
- **INFBENCH re-measured against 1.3.1** (measurement-only dispatch, 2026-07-09): `INFBENCH_1.3.1.md`
166
- finds the ladder unchanged, byte-for-byte, since `1.3.0` the four `PLAN_TAUGHT_RELATIONS.md`
167
- phases that completed the plan (alias/union, `compose2`, property-filter, recursive/reachability
168
- wiring) don't touch any band, confirmed by a zero-diff row comparison of both runs' raw product
169
- files plus a direct check that no INFBENCH case's premises/query ever reach the new relational-teach
170
- phrasing. Still gated at INF-B1 (33% completion), unchanged for a fourth consecutive measured
171
- version an honest, expected result given the new surface and the ladder measure different things.
172
-
173
- **`PLAN_TAUGHT_RELATIONS.md` live-testing follow-up DONE (2026-07-09)**: the operator live-tested
174
- the full family-tree example end-to-end and found two real gaps, both fixed in `src/chat.mjs`. Gap 1:
175
- a recognized-but-unsatisfied relational query used to fall to the GENERIC structural wall instead of
176
- naming the relation fixed by distinguishing "relation/rule name never taught" from "name known, this
177
- pair's chase came up short" right in the `(a0)` block, each with its own specific decline text. Gap 2:
178
- the REVERSE query shape ("who is the grandparent of john") didn't exist at all — new recognizer
179
- `RELATION_WHO_ASK_RE` + a new `(a0.2)` block in `factReadBack`, re-deriving `resolveRelationChase`'s
180
- same resolution logic (direct/alias/compose2/filter) walked backward from the object, reusing
181
- `findReachableSet` unmodified for the compose2 reverse hop-chase. Live-verified the operator's own
182
- repro exactly: "who is the grandparent of ishmael" → ahab (full 2-hop derivation cited); "who is the
183
- grandparent of john" an honest empty (never a wrong guess). `test/chat-taught-relations.test.mjs`
184
- extended with 8 more tests (26 total). `npm test` 1400 → 1408, zero regressions. **Nothing remains
185
- outstanding from `PLAN_TAUGHT_RELATIONS.md`.**
186
-
187
- ### Shipped this session
188
-
189
- - **Tier 5** found 12 routing/recognition fixes across teach and recall: article/head-word gaps
190
- in "what do you know about X", an adverb mis-parsed as a verb in general-verb teach, passive
191
- ownership phrasing, a quantified-property mis-teach, missing yes/no readers for taught facts, a
192
- silently-null teach path, past-tense property support, a leading hedge-adverb gap. The final
193
- cycle also caught a real correctness bug: "is the validate module deprecated" confidently
194
- answered off an unrelated "logger module" fact, through a word-overlap fallback with no
195
- exclusion for common code-noun suffixes like "module". New `test/chatflow-tier5.test.mjs` (21
196
- cases).
197
- - **Tier 6**, the last rung of the ladder, found 23 routing/recognition fixes: a grain-word
198
- resolution ambiguity ("the logger module" tying a Module against a same-stem Class); five new
199
- closed preamble frames in `interpret/normalize.mjs` for topic-switch, self-interruption,
200
- acknowledgement, hedge-adverb, and browsing discourse markers, chaining correctly when several
201
- stack together; bare "inherits"/"inherit" alongside its sibling "extends"; a dozen more
202
- vague-opener idioms; dialect and register gaps like "yeah nah", "howdy pardner", "aight", "no
203
- worries". It also caught one important bug: "is the logger module tested" answered a
204
- fabricated "I don't know that yet" even though the structural engine had already computed the
205
- real, honest answer. An over-eager property-adjective matcher discarded it whenever a real
206
- graph-computed parse already existed. New `test/chatflow-tier6.test.mjs` (17 cases).
207
- - **A test-suite health pass**, run in the background alongside Tier 6: batched `syllogise()`'s
208
- per-fact writes via `appendFacts`; let two chatbench plumbing tests opt out of the corpus seed
209
- (`TMCT_NO_SEED`); added a shared once-per-process seeded-fixture builder
210
- (`test/helpers/seeded-fixture.mjs`) for tests that only consume seeded content; replaced a
211
- hand-rolled copy of `WALL_MISS_RE` with the real export; and extracted a shared session-driver
212
- helper (`test/helpers/session.mjs`), replacing 11 near-duplicate `drive()`/`driveSession()`
213
- implementations. Full detail is in `HANDOVER.md`'s "Test-suite health pass" entry.
214
- - **Vocabulary-growth mirror fix.** New vocabulary used to grow one-directionally only: "redis is
215
- a cache" could mint the unknown subject "redis" because the object "cache" was already a known
216
- noun, but the reverse ("every cache is a store," subject known, object unknown) declined
217
- outright. Added `unknownObjectFallback`, gated on a genuine universal quantifier ("every"/"each"/
218
- "all") so it can't reopen the general lexicon bypass the existing bare/"a" shapes rely on. A term
219
- minted by either direction now grounds a later sentence exactly like a lexicon word, using
220
- taught-only groundedness checks that deliberately exclude the bulk ConceptNet corpus seed (the
221
- corpus mentions ordinary English words constantly and must never silently count as "grounded").
222
- When both sides are totally ungrounded, tmct still declines, but now with an actionable grounding
223
- nudge instead of a bare "I couldn't store that." New coverage in
224
- `test/chat-teach-quantifier.test.mjs`.
225
- - **Compound-name resolution**, from the operator's own worked example: "the payment system" now
226
- finds `PaymentSystem`, `payment-system`, a compound path like
227
- `westfield-payment-system/src/MyCode.cs`, and an interface-style name like
228
- `IPaymentSystemImpl.cs`. `resolveObject` (`src/ask.mjs`) gained a multi-word compound-term
229
- tier, the same shape as the existing single-word basename-exact/prefix-suffix (`9dde2b3`) and
230
- derivational-stem (`6e2d96b`) tiers, gated to require an explicit separator in the candidate
231
- label so a pure-camelCase identifier still falls to tier 4's prose fallback unaffected (this
232
- protects a frozen "total price" `calculateTotalPrice` test). New
233
- `test/ask-compound-resolve.test.mjs` (7 cases). Full detail is in `HANDOVER.md`'s
234
- "Compound-name resolution addendum" entry.
235
- - **The first-run chat experience, rewritten (1.0.0).** A brand-new `npm install` plus a bare
236
- `tmct chat` used to lead with a "no code graph loaded" apology for any input, including plain
237
- greetings, even though the seeded ontology/lexicon could already answer them. This was a
238
- 0.6.0-era design over-applying its own honest empty-graph orientation. The fix: identity/
239
- capability-led responses ("I'm tmct — ..." before any caveat), a real self-description and a
240
- distinct "no LLM involved" answer for the identity/AI-ID family, provably-correct "try this"
241
- examples (a `vocabExampleHint` that only offers a term confirmed to resolve in the session's
242
- actual seed state), and broadened conversational recognition (dialect, register, slang,
243
- elongation, a bounded-fuzzy typo layer). All of it landed as curated closed-set additions, per
244
- the project's standing preference over general grammar rules.
245
- - **The dialogue-flow playtest loop, tiers 0-4.** Tier 0 (bootstrap/identity), Tier 1 (single
246
- touch plus one drill-down), Tier 2 (drill-down chains with anaphora), and Tier 4
247
- (compositional and comparative) each closed in one pass. Tier 3 (cross-concept and relation
248
- touches) took 7 passes: cycles 3-9 progressively found and fixed a recurring `resolveObject`
249
- substring-match weakness, where a missing minimum-length floor let short staccato connectives
250
- like "and"/"it" silently hijack the conversation's focus and produce confidently wrong answers
251
- on a later turn while the triggering turn still looked honest. It took three point-by-point
252
- patches before cycle 9 found and fixed the actual root cause in one place. The skill doc itself
253
- gained two rules from real incidents this run: always `mktemp -d` plus exact-path cleanup for
254
- scratch fixtures, and never `chat --repo` the committed example fixture directly.
255
- - **A live, client-side chat demo on the GitLab Pages homepage.** The real `src/ask.mjs` query
256
- engine runs directly in the visitor's browser as a live demo, not a scripted replay. wink-nlp
257
- loads from `esm.sh`, an import-map shim works around 3 leaf files' Node-only static imports, and
258
- the engine itself needed no changes since it was already browser-clean pure JS. It boots with a
259
- banner, replays a few real pre-verified Q&A turns as "history", asks one randomized (or
260
- `?q=`-primed) question live, and gives the visitor a genuine interactive input box to type
261
- their own questions and get real computed answers. `?compact=1` gives a minimal primed-link
262
- view; `window.tmctAnswer`/`tmctAsk`/`tmctParseEntities` are exposed for headless/Playwright
263
- consumers. There's no backend on GitLab Pages, so plain `curl`/`jq` never sees a computed
264
- answer, which is stated plainly in the code rather than oversold.
265
- - **Operator-found bugs, fixed as they turned up in hand-testing the shipped CLI.** Relation-
266
- specific vocabulary filtering (an ask like "what is a tree used for" was dumping every known
267
- relation instead of filtering to UsedFor); a teach-lane "did you mean" suggestion that could
268
- echo the user's own input byte-for-byte (a missing a/an agreement check); out-of-domain small
269
- talk ("what time is it") hitting the raw grammar wall instead of an honest nudge; a
270
- pronoun-subject teach-lane gap that could silently store a bogus fact ("he is a module"); a
271
- closed-set existence-question recognizer misreporting a relationship check as a verified
272
- existence negative; "what else is X" repeating the primary definition instead of surfacing
273
- more; bare "what is X" (no article) having no fact-lookup route at all, including for a fact
274
- the user had just taught; and general verb-to-predicate teaching ("remember margo eats ribs"
275
- mints its own predicate now, not just the closed is/has/are set, and "has a" interoperates with
276
- the existing ConceptNet-sourced `mgx:hasA` data).
277
- - **Six more operator-found bugs (A-F), from a later manual chat-testing pass.** A malformed
278
- "haves soup" render for past-tense "had" (a lemma fix); a broken "count soup" message when no
279
- code graph is loaded; "what is in your memory" (bare, and "... about X") falling to the
280
- structural miss instead of the memory summary/fact-lookup lanes. The "about X" form now also
281
- walks transitive subtypes of X over taught (never corpus-noise) isa facts; a closed-set
282
- indirect-request wrapper ("I want you to search for Widget") that used to be swallowed whole by
283
- the general-verb teach recognizer, now stripped centrally before dispatch, plus a "search for
284
- X"/"tell me X" (no "about") phrasing fix; and a `GOAL_BY_COMMAND` table that gives every
285
- slash-command dispatch its own honest "Goal (inferred): ..." line. Full detail per bug is in
286
- `HANDOVER.md`'s "Operator-found bugs A-F" entry.
287
- - **General verb-to-predicate teaching's query-side follow-up.** A taught general-verb fact now
288
- answers direct questions too: "does margo eat ribs" → yes, "did margo eat ribs" → yes, "does
289
- margo eat cake" → an honest no, "what does margo eat" → lists ribs. It reuses the same has/have
290
- predicate bridge the teach side already had.
291
- - **New-term teaching and quantifiers.** "redis is a cache" (a genuinely new term, not
292
- previously in the closed ACE lexicon) is now teachable through a write-side-only fix; the read
293
- path already worked generically over any subject string, including the existing 2-hop
294
- transitive `IsA` proof chase. Plus four new phrasings ("some/a few Xs are Ys", "your X is a Y",
295
- bare "X is Y" as a property assertion) and a stored-quantifier recall ("how many Xs are Ys" →
296
- "A few.").
297
- - **An always-on, short "Goal (inferred): ..." line** on every real structural or vocabulary
298
- answer, distinct from the pre-existing opt-in `/narrate` full-trace mode. Two correctness bugs
299
- in the goal-deduction hook itself got fixed along the way: a confidently wrong goal shown on
300
- failed teach attempts, and a missing goal on relation-force answers that resolve through a
301
- different path than the normal parse.
302
- - **Seonix's 17-round dogfooding backlog, triaged and worked through.** Seonix, a sibling
303
- project consuming tmct as a real dependency, ran extensive dogfooding against both a synthetic
304
- self-index and a real 27,929-module production estate, and relayed the findings over the
305
- inter-session inbox. The backlog was triaged into 5 priority batches (4 items were already
306
- fixed by intervening work). **Batch 1** (existence-query correctness) shipped first. **Batch
307
- 2**: bare "what is Commit" now parses (article optional, restricted to `ENTITY_TO_TYPE`'s
308
- closed vocabulary); a reverse `inherits` verb family ("is X a superclass/parent class of Y")
309
- swaps subject and object at parse time to agree with the existing forward phrasing; a curated
310
- trailing-scope-filler strip ("what is a Module in this graph" → "Module") works at both the
311
- grammar and chat-fact-lookup layers. **Batch 3**: purpose/identity phrasing ("whats X for/
312
- about") joins "what does X do"; bare "recent/latest/newest commits" render a real dated list
313
- instead of a false find-miss, and "the last/latest/most recent commit" as a query subject
314
- substitutes the actual newest Commit before parsing; onboarding/closing phrasings beyond the
315
- original closed set get the orientation nudge; present-tense cochange phrasing ("changes with")
316
- joins the past-tense form. **Batch 4/5**: the cross-graph disambiguation-ranking weakness never
317
- reproduced on tmct's own tiny example fixtures, so a new committed fixture graph
318
- (`test/fixtures/large-scale/`, vendored commander.js + express.js source) was built to
319
- reproduce it. It surfaced an exact basename match losing to a same-directory sibling that only
320
- shared a component; fixed in `resolveObject`'s tier-3 scoring, where a new exact/prefix/suffix
321
- basename tier now outranks the length-normalized overlap fallback. Separately, "which functions
322
- call X and test Y" (two different, both-recognized relation verbs joined by "and") used to fall
323
- to the legacy `ambiguousParse` path; the marker gate now also opens when every later
324
- "and"-branch names its own single-word recognized verb, composing a real set intersection,
325
- narrowly scoped so the pre-existing "which classes extends Base and couples to logging" compat
326
- case stays exactly as closed as before. Still open: cochange phrasing variants, and a single,
327
- not independently reverified "multi-root" substring over-match.
328
- - **The Tier-4 "of X" membership gap, walked through inheritance.** "public methods of
329
- TaskController" used to return a genuine-looking but incomplete empty when the class declared
330
- no members of its own but inherited real ones from a superclass. `src/ask.mjs`'s membership
331
- eval now tries the owner's own (qualifier-filtered) members first, and only walks
332
- `ancestorsOf` nearest-first when that's empty and the class participates in `inherits`. An
333
- inherited answer is disclosed out loud ("… has no own methods — inherited from Controller:
334
- …"), never silently presented as the owner's own.
335
- - **The version-bump policy, set then revised.** The session first tried bumping immediately
336
- after every push and holding the bump locally until the next batch shipped, to keep the
337
- published npm version matching the last pushed commit. That produced confusing "referencing a
338
- version that doesn't exist yet" noise, so it was reverted mid-session. Current policy, recorded
339
- in `CLAUDE.md`: bump only at the moment of actually pushing, as part of that same push.
340
-
341
- ### Next: the open follow-ups
342
-
343
- 1. **Judged CHATBENCH re-run.** Not run this session. This session's changes touch answer text
344
- on judged surfaces again (onboarding/identity responses, teach-lane wording, new relation
345
- phrasings), so the next judged pass needs to re-derive its stale set from answer-text diffs,
346
- not assume anything carries over from the 0.8.2-era baseline still on record.
347
- 2. **The reverse-`inherits` verb family's "the"-definite forms** from Seonix Batch 2 ("is the
348
- superclass of") aren't wired into `VERB_TO_KIND` yet. Doing so leaked the bare word "the"
349
- into `ask.mjs`'s CONTENT_VOCAB and broke the relaxation cascade's noise-strip tests, so it
350
- needs a CONTENT_VOCAB fix first.
351
- 3. **Seonix Batch 4/5's remaining items**: cochange phrasing variants, and the single,
352
- not-independently-reverified "multi-root" substring over-match noted above.
353
- 4. **Extend compound-symbol matching to `/describe`'s own resolver.** The compound-name
354
- resolution above only covers `resolveObject` (`src/ask.mjs`); `/describe`'s own resolver
355
- (`resolveSymbol` in `codegraph.mjs`) is a separate, stricter, pre-existing resolver that
356
- doesn't share `resolveObject`'s tiered scoring, so "describe the payment system" doesn't
357
- benefit yet. Not a regression, just not yet covered.
358
-
359
- ### Later: deferred by design, staged inside each plan
360
-
361
- Each plan doc stages its own later phases; this list just points to them rather than repeating
362
- their tables.
363
-
364
- - **infbench stages 1-5** (`PLAN_INFERENCE_TESTING.md` §4). The disjointness proof rule (unlocks
365
- B1), proof-chain materialization, cardinality entailment, consistency checking. The repeatable
366
- measure/gate/advance cycle for this ladder is now also captured as an invokable skill,
367
- `SKILL_INFERENCE_TESTING.md`.
368
- - **Advanced-grammar tracks b/d/e** (`PLAN_ADVANCED_GRAMMAR.md`). The constructions not landed
369
- this wave: stacked modality/passive, implicit arguments, and the rest of the CEFR inventory
370
- audit table.
371
- - **Ontology stage 3+** (`PLAN_ontology-hierarchies.md`). Beyond the synonym-wiring and
372
- disjointness growth landed this wave.
373
- - **`PLAN_CODE.md` tracks 2/3.** Small JS-function synthesis and HTML/CSS-fragment synthesis, both
374
- via a Playwright-sandboxed headless browser. Explicitly staged well behind Track 1, each gated
375
- on its own operator sign-off.
376
-
377
- ### History — what shipped in earlier releases
378
-
379
- **v0.9.12 → v1.0.7** (this session — the first-run UX rewrite + the 5-tier playtest sweep +
380
- the live browser demo): see "Where we are now" above for the full narrative; short form —
381
- 1.0.0 shipped the identity/capability-led onboarding rewrite; 1.0.1-1.0.7 shipped, in order, the
382
- redis/new-term teaching + quantifier phrasings, the always-on Goal-inference line, a teach-lane
383
- pronoun-subject guard, three operator-found bugs (used-for filtering, teach-suggestion echo,
384
- out-of-domain small talk), Tier-0/1/2 playtest passes, Tier-3's 7-pass convergence (ending in a
385
- root-cause fix for the recurring substring-match focus-corruption bug), the diagnosed Tier-4
386
- compositional-fold fix, the live in-browser chat demo, Seonix Batch 1 (existence-query
387
- correctness), Tier 4's own playtest pass, and a final bundle ("what else is X", bare "what is X",
388
- general verb-to-predicate teaching). `npm test` 1055 → 1245 across the session, every commit
389
- green. Full commit-level detail in `HANDOVER.md`.
390
-
391
- **v0.8.2** (the chat-feel wave + rule-general C2): tier-1 CHATBENCH 334/334 (draw A) + 285/285
392
- (draw B), zero regressions; the cycle-1 hard-fail `gq-functions-call-fnalpha` flipped green.
393
- Landed recall hygiene, preamble/politeness frames, calls∪callsSymbol + grain/meta fallbacks, the
394
- author lane, wall kindness + honest capability nudges, teach-lane widening, receipt tails
395
- prose→detail, plus a live-found scale hotfix (`edgesOfKind` argument-spread overflow past ~100k
396
- edges). AGENTBENCH ladder grew 43→56 cases; goal driver 100% plan / 98% result / 0% hallucination,
397
- all rungs gate-PASS; resolver floor clean A0–C1 100/100; C2 became rule-general (two declared
398
- goal-rules, pure `applicableRules` selection). Full detail: `CEFR_ENGLISH_0.8.2.md`,
399
- `AGENTBENCH_0.8.2.md`.
400
-
401
- **v0.8.1** (published): AGENTBENCH grades the executed composed result, not just the call-plan.
402
- Resolver 97% plan / 91% result / 0% hallucination. Stage 5 (the C2 goal-reasoner, BDI + Goal-Driven
403
- Autonomy) lifted result-completion +10pp on a like-for-like driver swap. Stage 2 (imperative intent
404
- frames + ACE reach) shipped at 100% plan / 95% result / 0% hallucination, `tmct_calls` genuinely
405
- NL-reachable. Chat surface: quick wins + two frozen playtest transcripts, no tier-1 regression vs
406
- 0.7.1. Full detail: `CEFR_ENGLISH_0.8.1.md`, `AGENTBENCH_0.8.1.md`.
407
-
408
- **v0.8.0** (published): all five Phase-11 tracks. The `/v1/messages` shim + Stage-0 registry +
409
- resolver/guardrail/planner (96% plan completion, 0% hallucination, closed-world C1); three chat
410
- levers; the `../bedrock-meter` $0 rung; the playtest; Stage-2/Stage-5 research notes. Full detail:
411
- `CEFR_ENGLISH_0.8.0.md`, `AGENTBENCH_0.8.0.md`.
412
-
413
- **Doc restructuring — `PLAN_AGENTS.md` (2026-07-10)**: `PLAN_TMCT_ECOSYSTEM_INTEGRATION.md` was
414
- rewritten and renamed to `PLAN_AGENTS.md`, absorbing six sibling docs (`PLAN_AGI_ARCHITECTURE.md`,
415
- `PLAN_CAPABILITY_ROUTER.md`, `PLAN_TAUGHT_RELATIONS.md`, `PLAN_OSS_ACE_PARSER.md`,
416
- `PLAN_ontology-hierarchies.md`, `PLAN_ADVANCED_GRAMMAR.md` — all now in `archive/`) and sequencing
417
- their durable content into Phase 0 (foundations) through Phase 4 (tmct as a pluggable LLM rung for
418
- Claude Code/Bedrock/Copilot), plus a tiered research horizon (R1–R3). Two fresh comparative audits
419
- of `../marginalia` and `../seonix` fed a new §2, "tmct uplift" — mechanisms those sibling repos
420
- already have that tmct lacks or does more crudely (memory-tree versioning, actor-level trust, a
421
- declarative SHACL-style ingest gate, real multi-language AST extraction, Chronograph-style temporal
422
- diffing, and several Repository-Interface wrapper gaps that just need to be pointed at logic already
423
- sitting in tmct's own `codegraph.mjs`). A new sibling doc, `PLAN_COMPLETIONS.md`, specs a second,
424
- competing "tmct produces an artifact" capability alongside `PLAN_CODE.md`'s program synthesis:
425
- mechanical, extractive text generation (broad search → group → infer between groups → summarize →
426
- prune → grammar/voice pass), never LLM-style free generation. Separately, the benchmark/skill doc
427
- landscape was unified: CHATBENCH stops splitting report+transcripts into two files going forward;
428
- `SKILL_CHAT_PLAYTEST.md` and `SKILL_PLAYTEST_SPRINT.md` merged into `SKILL_BENCHMARK_PLAYTEST.md`
429
- (with a new `CONVERSATIONBENCH_<version>.md` report convention); `SKILL_TUNING_CYCLE.md` and
430
- `SKILL_INFERENCE_TESTING.md` renamed to `SKILL_BENCHMARK_CEFR_ENGLISH.md`/`SKILL_BENCHMARK_INFERENCE.md`;
431
- a new `SKILL_BENCHMARK_AGENT.md` formalizes the previously-ad-hoc AGENTBENCH cycle;
432
- `SKILL_STRATEGY_ADVISOR.md`/`SKILL_PLAIN_PROSE.md` renamed to `SKILL_AGENT_STRATEGY_ADVISOR.md`/
433
- `SKILL_AGENT_PLAIN_PROSE.md`. A new shared reference doc, `docs/references/research-horizon.md`,
434
- consolidates three near-duplicate "research frontier" essays (the frame problem, word-sense
435
- disambiguation/ontology scale, Winograd-hard coreference) that had independently grown across the
436
- now-archived docs.
437
-
438
- **v1.4.0 — the first PLAN_AGENTS.md uplift batch (2026-07-11)**: built as four parallel,
439
- worktree-isolated background tracks, merged sequentially, watched throughout by a background
440
- strategy-advisor agent (full tick-by-tick record in `STRATEGY_ADVISOR.log`). 1543/1543 tests green
441
- at the final merge. Shipped: the Repository Interface wrapper fixes from the seonix audit (ranked
442
- `search()`, a real graph-only `context()` — `INTERFACE_VERSION` 1.0.0→1.1.0 — depth-capped
443
- `impact()`, source-backed `snippet()`, `edges()`/`search()` pagination, telemetry wiring), a
444
- path-traversal security fix found and closed along the way (`src/source-slice.mjs`), hub-dampened
445
- memory-fact ranking (on by default — the build found the original "modest degree, modest penalty"
446
- assumption was mathematically wrong and proved the real bound instead), memory-tree versioning
447
- (`snapshotMemory()`, manual trigger only), full session-scoped actor-level trust (shipped
448
- unconditionally, no config flag — operator decision, single consumer), the extension-pack seam
449
- (`src/extensions.mjs`, `[extensions]`/`[bias]` in `tmct.toml`, `tmct extend --validate`, and a
450
- deliberate bug fix — `tmct init` now seeds SEON as well as ConceptNet), bias-weighted fact ranking
451
- (`src/memory/bias.mjs`, verified by control-flow tracing to never drop a fact, only reorder it), and
452
- `tmct init --with-persona <name>`. One real merge conflict (Track A's `tel` param and Track D's
453
- `biasByBundle` param both threading through the same `chat.mjs` function signatures — resolved by
454
- keeping both). One bug the strategy advisor caught that the original brief missed: the
455
- path-traversal guard failed closed *incorrectly* under a relative `TMCT_GRAPH_FILE`, rejecting
456
- legitimate reads, not just traversal attempts — fixed at the source and defensively in the guard.
457
- One scope decision made mid-build: multi-language AST extraction stays in seonix permanently, not
458
- tmct's job — full detail in `PLAN_AGENTS.md` §13.
459
-
460
- **The 2026-07-10 uplift batch — largest single session to date, coordinator + ~20 concurrent
461
- background tracks.** `PLAN_CHAT_FEEL.md` fully archived (all 12 items shipped — item 6's
462
- remainder: 8 remaining temporal-composition red ids fixed via new `parseCommitFilter`/NP templates/
463
- a `PERFECT_AUX` carve-out; the presupposition regression turned out to be a stale test fixture, not
464
- a product bug; the garden-path regression is real, narrow, and documented open). `PLAN_COMPLETIONS.md`
465
- — a brand-new capability, operator-sign-off given this session — shipped end-to-end, Stages 0-3:
466
- `src/completions/` (`search.mjs`/`group.mjs`/`rank.mjs`/`infer.mjs`/`prune.mjs`/`complete.mjs`),
467
- connected-components grouping over `memory/blocks.mjs`'s block-similarity graph, a closed 4-relation
468
- cross-group inference vocabulary (supports/contradicts/elaborates/exemplifies, each with a named
469
- mechanical licensing test), PageRank+IDF extractive sentence ranking, and an auditable prune/assemble/
470
- grammar-pass pipeline — every output sentence traces to a source span, `finish.mjs` generalized from
471
- single-answer to genuinely multi-sentence output. `PLAN_INFERENCE_TESTING.md` stages 3-5: the
472
- `cax-dw` disjointness rule (kernel + a live, read-only chat-query wiring closing a real gap where the
473
- rule existed but was never reachable from a chat turn — INF-B1's gate), `cls-svf1` (someValuesFrom
474
- restriction membership) plus a new positive infbench template needed to actually measure it, and a
475
- new consistency checker (`findConsistencyViolations`) that REFUSES to answer from a subject whose own
476
- taught types contradict each other, naming the clash — INF-C2. `resolveRelationChase`/
477
- `resolveRelationChaseReverse` extracted from `chat.mjs` closures into standalone exported functions in
478
- `memory/core.mjs` (PLAN_COMPLETIONS Stage 1's prerequisite). `PLAN_AGENTS.md` Phase 0 essentially
479
- closed out (cross-repo smoke test, `agentbench/envelope.json`, the `ace-owl` standalone MPL-2.0
480
- package extraction, ontology-hierarchies tracks a-d, advanced-grammar tracks a/d/f — several tracks
481
- found already-shipped from earlier sessions and verified/extended rather than redone) — only the
482
- chat-surface debt re-measure remains open. The SHACL-style declarative ingest gate shipped as a small
483
- hand-rolled validator (`src/memory/shacl.mjs`) after `shacl-engine` was tried and rejected as
484
- disproportionately heavy for tmct's minimal-deps floor. A fourth tier2 corpus bundle
485
- (`tier2-general`) and a context-preserving unknown-word ingestion module shipped, though the latter's
486
- one production call site doesn't activate it yet (`PLAN_AGENTS.md` §4). CHATBENCH restructured
487
- (case-set v3): the full 1,075-case CEFR pool preserved at `chatbench/graded-pool-max.jsonl`;
488
- `chatbench/graded-pool.jsonl` is now a 109-case go-to default (10/CEFR-grade + the former
489
- `cases.jsonl`'s 49 hand-authored capability cases, each assigned a real grade+construction cell) at
490
- N=2/single-draw by default. A full capability audit (`CAPABILITIES_AUDIT_2026-07-10.md`) cataloged
491
- 83 distinct capabilities against every doc claim and the actual code — 57 implemented, 21
492
- claimed-only, 3 partial, its most notable finding being that `PLAN_AGENTS.md` itself (drafted the
493
- same session) already listed several now-shipped items as "not started," a same-session docs-lag
494
- issue, not months-old drift. See `HANDOVER.md` for the ranked next-steps this batch's four fresh
495
- benchmark runs (AGENTBENCH/INFBENCH/PLAYTEST/CHATBENCH) surfaced.
496
-
497
- ## The umbrella product definition (item 1)
498
-
499
- **A tolerant, ELIZA/PARRY-style chat, obsessed with software.** A best-efforts
500
- conversational surface that guides users toward precision queries.
501
- ELIZA/PARRY-style pattern reflection, but domain-obsessed the way PARRY was
502
- obsessed with the mafia — tmct may heavily assume a narrow context (you are
503
- asking about *this* codebase, or about what tmct itself remembers) and exploit
504
- that assumption to answer cheaply and confidently. Tolerant of loose, fuzzy,
505
- misspelled input; never silently wrong; **no LLM anywhere in the product**.
506
- Every phase below serves this definition.
507
-
508
- ---
509
-
510
- ## Phase 0 — Reshape (v0.2.0) — the current work
511
-
512
- One commit per step, `npm test` green at each.
513
-
514
- - **DONE — Strip the LLM fallback** (`--with-claude` / `--with-copilot` and the
515
- `hook-augment` mode removed; the product path is now provably model-free).
516
- - **DONE — Drop the extraction/viz stack** *(item 12: shed the codebase-index
517
- dependency)*: Python `ast`, tree-sitter, Roslyn/Java extractors, walk/viz/
518
- timeline/temporal modules, `roslyn/`, `java/`, `templates/` all deleted. tmct
519
- consumes a graph via the provider seam; it produces none.
520
- - **DONE — Drop the MCP server**: `@modelcontextprotocol/sdk` removed;
521
- `dispatchTool` survives as the plain internal tool switch.
522
- - **DONE — Carve `buildEntities`** into `src/graph-build.mjs`: the pure
523
- in-memory graph assembly function, kept as the future memory writer
524
- primitive.
525
- - **DONE — Empty-graph bootstrap** *(item 14, partial)*: a missing graph file
526
- is no longer an error; tmct starts empty, says so, and creates
527
- `.tmct/graph.json` from the conversation. The full provider adapter contract
528
- is Phase 1.
529
- - **DONE — tmct naming purge** *(item 15, widened)*: seonix AND the interim
530
- "mct" replaced throughout — package
531
- `@polycode-projects/the-mechanical-code-talker`, bin `tmct`
532
- (`bin/tmct.mjs`), tool prefix `tmct_*`, artifact dir `.tmct/`, env
533
- `TMCT_GRAPH_FILE`, prompt `tmct>`.
534
- - **DONE — License swap to MPL-2.0** (from AGPL-3.0): free commercial use,
535
- file-level publish-and-attribute copyleft.
536
- - **DONE — README rewrite + GitLab Pages home page** (`public/index.html`,
537
- `pages` CI job): https://polycode-projects.gitlab.io/the-mechanical-code-talker/
538
- - **DONE — `docs/references/` skeleton + `ontology/`**: the reference-library
539
- index (canonical URL / retrieval date / licence / consumer per entry), OWL 2
540
- vocabulary notes, ACE-OWL sub-fragment pattern table, ConceptNet relation
541
- list, and the `ontology/tmct-core.ttl` placeholder. This feeds the Phase 2
542
- grammar work; the library grows as sources are web-verified.
543
- - **DONE — Publish 0.2.0** under the new name; deprecate
544
- `@polycode-projects/mct@0.1.0` with a rename pointer.
545
-
546
- ---
547
-
548
- ## Phase 1 — Interpretation pipeline + memory foundations
549
-
550
- ### Item 8 — Multi-strategy request classification and ranking → `src/interpret/`
551
- Instead of a single best-guess parse, run the request through **all the classes
552
- of thing it could be**, parse it with each class's own strategy (grammar parse,
553
- keyword picking, noise-word removal, fuzzy matching — later the ACE strategy
554
- from Phase 2), execute the strategies that look like winners, then **merge
555
- same-class results** and surround **distinct-class results** with "if you mean
556
- X then …". Grows from `ask.mjs`'s existing 2-way merge into
557
- `interpret/pipeline.mjs` + `interpret/merge.mjs` + `interpret/strategies/*`.
558
- *(Covers sketch 1 of the former `code-talker-ideas.txt`: "request → all the
559
- classes of things it could be → parse using each class-specific strategy →
560
- execute winners → combine similar result classes and rank".)*
561
-
562
- ### Item 13 — The clean chat / primitives split
563
- Pull the movable conversational grammar out of the core primitives
564
- (`resolveObject`, `edgesOfKind`, `refineToEntities`, `traverse`) so the chat
565
- engine stands alone. `chat.mjs` slims to the conversational layer + `runTurn`
566
- orchestration.
567
-
568
- ### Item 10 — Input normalization pass (grammar / spell / style checks)
569
- Run a grammar check, spell check, and style check over input as a
570
- normalization pass alongside classification (item 8), so misspelled or
571
- ungrammatical input is repaired or scored before template matching — the
572
- concrete mechanism behind item 1's "tolerant of loose, fuzzy, misspelled
573
- input" promise. The same checks later serve the "observe" ambition (item 6)
574
- over repo prose. *(Covers sketches 3, 4, and 5 of the former ideas file:
575
- grammar check, spell check, style check.)*
576
-
577
- ### Item 9 — Conversational memory as its own graph → `src/memory/`
578
- Record every parsed request as an "a-visitor-said" item and every response
579
- alongside it, in tmct's own OWL-labelled graph (`memory/core.mjs`), with text
580
- blocks under a PageRank-style relevance index (`memory/blocks.mjs`) and
581
- session-log cleaning/folding (`memory/fold.mjs`). Future input can then match
582
- against **prior questions** by similarity, not just against a provided code
583
- graph. This is tmct's own data under `.tmct/`, distinct from any
584
- provider-supplied graph and not written back through the provider adapter.
585
- *(Covers sketch 2 of the former ideas file: "once parsed the text is added to
586
- the graph as a-visitor-said item; responses from queries go in the graph; text
587
- matching may find similar questions".)*
588
-
589
- ### Item 14 (finish) — The graph-provider adapter contract
590
- Define the provider touchpoint interface — a loader yielding
591
- `{ individuals, byId, relations, proseIndex }` plus the published primitives —
592
- so seonix or any other producer can feed tmct without tmct importing an
593
- indexer. Phase 0 shipped the bootstrap seam; this finishes the contract.
594
-
595
- ### Item 16 — Library-first design for extension
596
- Keep the `exports` map and the primitives stable and documented as the
597
- internals are refactored.
598
-
599
- ### Shell work
600
- - **Ink console shell** (`src/tui/app.mjs`, ink + react, no build step) around
601
- the shared session sink; readline `runChat` stays as `--plain` and as the
602
- test surface. *(Decision: OpenTUI ruled out — `@opentui/core` depends on Bun
603
- FFI (`bun-ffi-structs`, native Zig renderer), not Node-clean; revisit when it
604
- runs under plain Node.)*
605
- - Fold the surviving `bin/cli.mjs` arms into `bin/tmct.mjs`; delete `cli.mjs`.
606
-
607
- ---
608
-
609
- ## Phase 2 — Grammar → OWL + corpus
610
-
611
- ### Item 2 — Its own well-defined grammar → `src/grammar/ace.mjs`
612
- A first-class, documented, testable grammar — an **ACE-inspired controlled
613
- fragment** (~8 sentence patterns; see
614
- `docs/references/schemas/ace-owl-fragment.md`) that emits **OWL-labelled
615
- triples** when text fits it, backed by a declared lexicon
616
- (`grammar/lexicon.mjs`, TOML/JSONL data). Plugs into the item-8 pipeline as
617
- one strategy among several: fitting the grammar is a strong signal, missing it
618
- falls back to the tolerant strategies.
619
-
620
- ### Item 3 — Ontology grounding: core OWL/RDF + SE vocabularies
621
- Ground the memory vocabulary in real ontologies: core **OWL 2 / RDF / RDFS**
622
- scaffolding plus software-entity concepts (the SEON-derived terms the graph
623
- already uses — `seon:`, `mgx:` prefixes — with **OWL-SEON** and **FAMIX** as
624
- reference vocabularies). Deliverable: `ontology/tmct-core.ttl`.
625
-
626
- ### Items 4 + 7 — Template libraries, phrase book, plain data formats
627
- Sentence-fragment template libraries for matching input and generating
628
- responses, plus a software-engineering phrase book — all in plain, diffable
629
- formats (**JSONL**, **TOML**, **.txt** line files).
630
-
631
- ### ConceptNet corpus slice
632
- A committed, filtered English/tech-domain **ConceptNet slice** (CC-BY-SA 4.0
633
- notice, size-budgeted) with the ~35-row relation→ACE-OWL-pattern mapping table
634
- (`src/corpus/conceptnet.mjs` + `conceptnet-map.toml`; relation list in
635
- `docs/references/schemas/conceptnet-relations.md`). The corpus seeds the
636
- bootstrap graph so an empty tmct still has a vocabulary.
637
-
638
- ### Reference library growth
639
- Grow `docs/references/` with web-verified sources: ACE/APE papers, ConceptNet
640
- docs, ELIZA/PARRY lineage papers (only redistributable licences committed) —
641
- and finish `ontology/tmct-core.ttl` alongside the grammar work.
642
-
643
- ---
644
-
645
- ## Phase 3 — Chat tuning cycle (autonomous)
646
-
647
- The measurement loop that turns the above into a tunable product — specified
648
- in `SKILL_TUNING_CYCLE.md`:
649
-
650
- - a fixed, versioned **chatbench case set** (`chatbench/cases.jsonl`);
651
- - a **deterministic replay runner** over `runTurn` (the product is
652
- deterministic — one run per arm suffices);
653
- - **LLM-as-judge** scoring (N≥3 samples per case; groundedness / correctness /
654
- honesty-on-miss / rephrase-hint helpfulness). The judge lives in the **eval
655
- harness only** — the product stays no-LLM;
656
- - `CEFR_ENGLISH_0NN.md` artifacts and an autonomous cycle loop (no hard pause;
657
- each cycle logs its ranked decision menu and continues).
658
- - **The graded benchmark** (case-set v2, operator-specified 2026-07-04): a
659
- scaled ladder fitted to HUMAN LANGUAGE STANDARDS, not AI-benchmark mechanics
660
- (bAbI explicitly rejected — it tests expected-AI mechanics and overfits the
661
- same way our own cases would). Every case carries a **CEFR band (A1–C2)** +
662
- a **construction specialization** tag (TROG-2/CELF-5 style blocks, adapted:
663
- naming/vocabulary, SVO queries, pronoun binding, reversible/passive,
664
- relative/embedded clauses, quantifiers+counting, negation, temporal,
665
- coordination/compositional, multi-turn discourse reference, declarative
666
- assert+recall). Multiple questions per grade × specialization with a little
667
- overlap — authored as a POOL ~10× the per-run need (deterministic generator;
668
- each run samples ~10% stratified, ≥5 items per populated cell, recorded
669
- seed), with COMBINATION cells alongside single-area cells so weakness is
670
- attributable to an area alone or to a specific pairing.
671
- **Ladder gating:** advanced grades are SKIPPED until every grade
672
- below passes reliably; when a grade reaches unit-test-level reliability its
673
- cases become ALWAYS-RUN deterministic tests (judge-free, promoted alongside
674
- test/showcase.test.mjs). Winograd/WinoGrande items stay as permanent
675
- ceiling markers; CHILDES as naturalistic easy-band input source. Licence
676
- rule: TROG/CELF are commercial — borrow the construction taxonomy and
677
- grading structure, author ORIGINAL items, never copy instrument content.
678
- A case at 0% is a ceiling marker, not a failure.
679
- - **Retained showcase** (landed): the five most complex achieved sequences are
680
- frozen as unit-timescale regression tests in `test/showcase.test.mjs`; a
681
- showcase regression voids a cycle PASS regardless of the mean.
682
-
683
- Inside this loop, two earlier ambitions become **tuning levers** rather than
684
- standalone features:
685
-
686
- ### Item 5 — Calculation surfaced as reasoning
687
- Derived facts presented as lightweight reasoning ("there are a lot of tests
688
- for a codebase of that size", "this module is unusually central") —
689
- calculations, not inference: deterministic, explainable, cheap.
690
-
691
- ### Item 6 — Optionally running linters/tests to *observe*
692
- Let tmct run linters or tests to observe whether something actually worked,
693
- reporting the observation — measurement, not reasoning.
694
-
695
- ### Item 11 — Formal logical reasoning over the ontology (Prolog / Progol) — exploratory, gated; matured into Phase LATER tier-5 "entailment-on-miss"
696
- Apply real rules of inference (modus tollens, etc.) to formulas extracted from
697
- parsed prose, checked against the axioms in the ontology (item 3) — a step
698
- beyond item 5's arithmetic. The sketch: map OWL constructs into templates over
699
- parameter expressions (Prolog terms or similar), then use a theorem prover —
700
- Progol (inductive logic programming) is the named candidate — to prove goals
701
- against parsed prose. Materially bigger than item 5 and dependent on the
702
- Phase 2 ontology landing; **exploratory until a spike confirms the
703
- OWL-to-template mapping is tractable**. *(Covers sketches 6 and 7 of the
704
- former ideas file: "reasoning as the application of logic rules to the formula
705
- created from prose against the set of axioms in the graph, possibly search
706
- using Prolog" and "fit OWL constructs into templates / parameter expressions,
707
- then use Progol to theorem-prove against parsed prose".)*
708
-
709
- ---
710
-
711
- ## Phase 4 — The wiring wave (operator-directed 2026-07-04)
712
-
713
- Five subsystems are built, tested, and consumed by NOTHING in the answer path. They measured
714
- zero on case-set v1 because no case could see them. This phase wires each into answering, with
715
- **unit tests at the seam AND graded-benchmark cells that measure it** (the graded pool creates
716
- the cases that make each lever visible). Wired as one operator-directed wave; cycle-level
717
- attribution resumes per-lever afterwards.
718
-
719
- | # | Wiring | Seam | Unit test | Bench coverage |
720
- |---|---|---|---|---|
721
- | W1 | **Templates → render path** | answer rendering consumes `data/templates/responses.jsonl` via `src/corpus/templates.mjs` instead of hardcoded strings (same output first — byte-stable swap — then variation) | render parity + slot lint | every existing case re-measures the swap; `via:"template"` provenance |
722
- | W2 | **retrieveBlocks → miss path** | a bare-question miss consults the memory block index before the honest miss; a hit answers with the recalled block + provenance ("you asked this on …") | recall hit/miss seam | memory-recall cells (mr-asked-before flips) |
723
- | W3 | **seedMemory → bootstrap** | first run in a graph-less repo seeds a capped corpus slice (limit ~500) into `.tmct/memory/`; banner says so honestly | seeded-bootstrap test | bootstrap-empty + vocabulary cells ("what is a cache?") |
724
- | W4 | **Asserted Facts → answers** | "what is a module?" / "is a module a component?" consults remembered `rdfs:subClassOf`/`rdf:type` facts alongside the code graph, cited with provenance | fact-lookup seam | assert-recall cells |
725
- | W5 | **Corpus on-demand** | unknown-term misses may consult the corpus slice (local first; network tier only behind an explicit flag) | on-demand seam, offline-degrades test | naming-vocabulary cells at higher grades |
726
-
727
- Answer-path **provenance** lands with W1: every turn record carries `via`
728
- (composed | template | count | recall | fact | corpus) — the field the dual-banding
729
- benchmark (Phase 5) and the memory inspector read.
730
-
731
- ### Corpus tiering policy (the committed/seeded/on-demand cutoff)
732
-
733
- - **Tier 1 — committed & shipped in the npm tarball**: small, load-bearing, licence-clean,
734
- diffable — the lexicon, response templates, phrasebook, the relation→OWL map, and the CORE
735
- ConceptNet slice. Budget: **~2 MB total tarball**; rule: what the product needs to be useful
736
- offline out of the box.
737
- - **Tier 2 — fetched at seed time into install-local folders** (`.tmct/corpus/` per repo, or a
738
- user-level cache): growable corpora — extended ConceptNet neighbourhoods, acquired template
739
- libraries (Phase 5), any corpus > ~2 MB. Fetched once by `tmct seed` (or first bootstrap with
740
- consent), checksummed, provenance-recorded, never committed.
741
- - **Tier 3 — on-demand at question time**: unbounded/live sources (ConceptNet API for unknown
742
- terms, paper phrase-mining), consulted ONLY behind an explicit opt-in flag, cached down into
743
- tier 2 after use. **Network failure degrades to the honest miss** — the $0-offline default is
744
- inviolable; tiers 2-3 are additive, never required.
745
- - **Tier 4 — learn-on-miss (Phase LATER, not now)**: the term IS in the lexicon and the query
746
- built cleanly, but the graph+memory+corpus all return nothing → web search, clean the fetched
747
- text into tmct's own dialect (the ACE-ish controlled grammar), store on disk (tier 2), ingest,
748
- THEN answer — the full acquisition loop at question time. See Phase LATER.
749
-
750
- ### Memory inspection (seeing into the memory)
751
-
752
- Graph-vis exploration hasn't earned its keep; the in-ethos answer is TEXT. A `/memory` chat
753
- command + `tmct memory` CLI: the memory graph grouped by **OWL superclass** (Utterance, Fact,
754
- Session; code classes when present), counts per class with **balanced samples scaled to class
755
- size** (log-scaled so a 10,000-fact class shows ~8 exemplars and a 3-session class shows all 3),
756
- top facts ranked by provenance breadth (corpus+chat-agreed facts first), recent utterance pairs,
757
- and the block-index summary (blocks, tokens, top PageRank blocks). Same renderer serves
758
- `/stats`-style terse and `why`-style verbose.
759
-
760
- ## Phase 5 — The cycle-4+ tuning arc (near-term: make the floor reliable)
761
-
762
- > **STATUS: in progress — the two headline B1 levers shipped.** Negation as a bounded SET
763
- > COMPLEMENT ("which X do not <verb> Y") and reversible-passive traversal ("X is imported by Y")
764
- > are live; the harness meta-fixes and the rest of the ranked lever board (levers 3–6 + the C2
765
- > ceiling, below) continue. **This section is the durable home for the tuning arc** — the detailed
766
- > cycle-4 plan was archived to `archive/PLAN_CYCLE_4.md` once its substance lived here.
767
-
768
- > The dependency audit that also fed this phase is archived at `archive/PLAN_DEPENDENCY_STRATEGY.md`
769
- > (verdict: no dep changes now; a standing adoption register + avoid-list for phases 6-9; two
770
- > near-term actions, both shipped — see below).
771
-
772
- The immediate work: drive the graded benchmark up the CEFR ladder, one lever per cycle, per
773
- `SKILL_TUNING_CYCLE.md`. Cycle 3 (post-wiring-wave, CEFR_ENGLISH_003) gave the first full-spectrum
774
- reading — A1 1.72 / A2 1.70 / **B1 0.77 (the cliff)** / B2 0.97 / C1 1.07 / C2 0.69 — and two
775
- META-fixes gate everything:
776
-
777
- - **Meta-1 — fix the harness artifact BEFORE trusting groundedness.** The judge systematically
778
- scores TRUTHFUL product output (/describe attributes, recall frames, session ids) as
779
- fabrication because `FIXTURE_CONTEXT` omits the detail the product legitimately emits.
780
- Measurement integrity: lands in its own cycle, re-measured, before any product lever — else
781
- every groundedness delta is confounded. A harness correction, logged as such (like cycle-2's
782
- H1a/H1b), not a product change.
783
- - **Meta-2 — the ladder rule: get B1 reliable before judging C-grades.** Don't pay to judge a
784
- ceiling while the floor leaks. A/B grades carry the judged spend; C1/C2 stay tier-1-only
785
- ceiling markers, judged only occasionally to confirm they're still ceilings (the existing
786
- `--ladder`/`--grade` flags).
787
-
788
- Then the product levers, one per cycle, in ranked order: **(1) B1 negation operator** — the
789
- deepest gap, the engine tokenizes "not"/"don't" as an entity ("no module matching 'not' found");
790
- add set-complement to traversal; predicted B1 0.77→~1.05, ~10 hard fails cleared. **(2)
791
- reversible-passive** ("is imported by" reverses edge direction). **(3) under-covered pool
792
- growth** (B1 pronoun/temporal, C1 temporal — instrument fix, parallelizable). **(4)
793
- assert-recall read-back**, **(5) quantifier+temporal composition**, **(6) the help-text honesty
794
- leak** (hardcoded examples naming non-fixture entities — a real product fabrication, distinct
795
- from meta-1's harness artifact), **C2 ceiling LAST**. Operator decision 2026-07-05: **do all of
796
- them**. Exit criterion in the plan (roughly: B1 grade mean ≥ ~1.5 with all cells dual-draw
797
- agreeing unlocks C-grade judging).
798
-
799
- ## Near-term actions (from the dependency audit, archive/PLAN_DEPENDENCY_STRATEGY.md)
800
-
801
- > **STATUS: both shipped.** The wink browser-loader seam is added (shared model loader with a
802
- > browser registration path) and `fnv1a` is single-sourced into `src/hash.mjs`.
803
-
804
- Two concrete, low-risk actions the audit surfaced — not features, not dep changes:
805
-
806
- 1. **Fix wink's `createRequire` browser-loader gap** — the wink model IS the browser build, but
807
- our adapters load it via `createRequire(import.meta.url)` (`ask-nlp.mjs:29`, `prose-nlp.mjs:31`),
808
- which is Node-only. Browser mode needs a bundler `import` path. **A Phase 8 (browser-mode)
809
- blocker** — budget it into `archive/PLAN_REPOSITORY_INTERFACE.md`; it is a wiring fix, not a dependency
810
- change (the model is already browser-capable).
811
- 2. **Single-source `fnv1a`** — extract the content-address hash to one `src/hash.mjs` so the
812
- cross-version-stable fact-id contract has a single definition. Trivial refactor, do any time;
813
- no dependency (the audit confirmed home-grown FNV-1a is the correct choice — sync + browser +
814
- version-stable, which every library candidate fails).
815
-
816
- ## Provenance & trust — the unified source-link primitive (cross-cutting)
817
-
818
- > **STATUS: shipped.** `mgx:createdAt` universal; `Source` first-class individuals linked by
819
- > `mgx:derivedFrom` / `mgx:statedBy` / `mgx:canonicalisedFrom`; a deterministic `computeTrust`
820
- > (source-type prior × corroboration × recency); retrieval weighted by relevance × trust; the
821
- > `/memory` inspector surfaces contradictions with provenance. Legacy `mgx:factProvenance` kept
822
- > as a compat shim.
823
-
824
- > Detailed plan: **archive/PLAN_PROVENANCE_TRUST.md**.
825
-
826
- *(Operator-specified 2026-07-05, from the observation that Phase-6 canonicalise-and-link,
827
- tier-4 learn-on-miss, and the ConceptNet slice all share one shape: raw source preserved,
828
- derived form linked back.)* Promote that shape to a FIRST-CLASS primitive used everywhere a
829
- fact enters memory:
830
-
831
- - **Every fact/block carries a `Source` and a link to it** — one predicate family
832
- (`mgx:derivedFrom` / `mgx:canonicalisedFrom` / `mgx:statedBy`) instead of the current
833
- per-writer `mgx:factProvenance` string. Sources are first-class individuals (class `Source`:
834
- operator-chat, corpus:conceptnet, learned:web:<url>, entailed:<rule>, provider:seonix), so a
835
- fact can cite MANY sources (the existing "|"-union becomes real edges).
836
- - **Everything created is TIMESTAMPED** (`mgx:createdAt`), universally — Facts don't carry one
837
- today (only Utterances do), a Phase-6-trust gap to close: recency is a trust input and the
838
- novelty signal (below) needs it. Backfill on write; the timestamp is itself provenance.
839
- - **Calculable trust scores per source**, deterministic and explainable: a source-type prior
840
- (operator > provider graph > curated corpus > web > unverified entailment) combined with
841
- corroboration (how many independent sources assert the same fact — the union already tells us)
842
- and recency/agreement signals. Trust is a computed attribute, never hand-set, always
843
- traceable to its inputs.
844
- - **Trust as RETRIEVAL WEIGHTING**: `retrieveBlocks` / fact lookup / the memory inspector rank
845
- by relevance × trust, not relevance alone — a corroborated operator-stated fact outranks a
846
- lone web scrape on the same query. Contradiction becomes visible (two high-trust sources
847
- disagree → surface both with their provenance, never silently pick).
848
- - **Feeds tier-5**: the Syllogist's entailed facts get a derived trust (min/product of premise
849
- trusts × rule confidence) — a conclusion is only as trustworthy as its weakest premise, and
850
- that number is computed, not asserted.
851
-
852
- ## Phase 6 — Formulaic competence: the template-acquisition learning loop
853
-
854
- > **STATUS: shipped.** A technical (C1) register of templates and productive/performance
855
- > dual-banding (computed from the `via` provenance) are live in the benchmark.
856
-
857
- > Detailed plan: **`archive/PLAN_FORMULAIC_COMPETENCE.md`**.
858
-
859
- The operator's insight upgraded to the strategy: a consistently-failed C1/C2 graded cell whose
860
- answer EXISTS as a stable phrasing in technical prose is not a ceiling — it is a
861
- **template-acquisition lever**. tmct learns the way human learners do: formulaic chunks first
862
- (Wray's formulaic sequences), productive competence later.
863
-
864
- - **Dual banding**: every graded score splits into a **productive band** (composed answers only)
865
- and a **performance band** (templates allowed), computed from the `via` provenance (W1). The
866
- band GAP is a first-class metric: how much fluency is memorized vs generated.
867
- - **Template-lane benchmarking**: cases that target templated capability are TAGGED as such —
868
- a template-carried C1 pass counts in the performance band and never inflates the productive
869
- band; template-lane cells get their own agreement/reliability treatment (they are additional
870
- benchmarking, not replacements — a level we would otherwise expect to fail at is being
871
- deliberately faked, and the bench must say so).
872
- - **The shopping list**: each cycle, the write-up extracts consistently-failed C1/C2 cells and
873
- ranks them by template-acquirability (does a stable technical-prose phrasing exist? is the
874
- slot structure mechanical — counts, comparisons, provenance we already compute?). Acquiring
875
- the template IS the lever; the graded bench measures the flip in the performance band.
876
- - **Mechanical conclusions at paragraph grade**: counting + comparison + superlatives (item 5)
877
- composed through acquired C1-register templates — "X has 340 tests across 12 suites, unusually
878
- dense for a codebase this size" — tech-domain answers can be genuinely advanced while the CEFR
879
- banding tells us honestly how good the conversation AROUND them is.
880
- - **Generalization path**: fixed tech domain first (templates hand-picked from technical-paper
881
- register); then template acquisition generalizes — mining candidate templates from corpus
882
- blocks (tier-2), scored by slot-fillability, promoted into `data/templates/` with provenance.
883
-
884
- ## Phase 7 — Response finishing: the grammar pass (tone of voice dropped for now)
885
-
886
- > **STATUS: shipped.** Answers segment into typed spans (prose vs protected); the grammar-rule
887
- > pass runs on prose spans only under a protected-span invariance guard. The a/an article fix is
888
- > active; broader voice/agreement rules are implemented-but-parked.
889
-
890
- > Detailed plan: **`archive/PLAN_RESPONSE_FINISHING.md`**.
891
-
892
- *(Refined 2026-07-05; decisions settled with the operator. Fact invariance is achieved by
893
- CONSTRUCTION, not by hope. Finishing operates over a SEGMENTED answer, never a raw string.
894
- Tone-of-voice synonym substitution is DROPPED: once every term with technical significance is
895
- protected — entities, paths, vocabulary, receipts, provenance — the substitutable surface is
896
- mostly connectives: high accuracy risk, thin reward. "Keen on the trickery to make a helpful
897
- product, but not at the cost of accuracy." Moved to Phase LATER should a provably-safe subset
898
- ever emerge.)*
899
-
900
- - **The segmentation IR (the foundation, lever 1)**: every answer becomes a list of typed spans
901
- before it becomes text — `prose` vs PROTECTED (`entity`, `path`, `number`, `code`,
902
- `provenance`, `receipt`). Protected spans are byte-copied through finishing; only prose spans
903
- are ever touched. The W1 template renderer is already slot-aware (slots ARE the protected
904
- spans); composed renders adopt segmentation progressively via a conservative masker. Phase 5's
905
- dual banding reads the same spans.
906
- - **Grammar pass (lever 2)**: a data-driven rule table (TOML, item-7 formats) over prose spans —
907
- article selection ("a artifact" → "an artifact", an observed defect class), subject–verb
908
- agreement against slot plurality, capitalization, list/terminal punctuation. Grammar
909
- corrections IMPROVE accuracy (they fix our own generated defects); that is why they survive
910
- the tone cut. Neutral behavior is byte-stable except where a rule fixes a genuine defect —
911
- each rule lands as a bench-measured lever.
912
- - **Memory decision (settled)**: memory stores BOTH — the **as-spoken** turns live as larger
913
- prose blocks on the graph (the honest record), and the **canonical** form is derived and
914
- LINKED to its source prose blocks (canonise + link, never replace). Recall and folding read
915
- canonical; provenance walks back to as-spoken.
916
- - **Verification**: unit invariance checker (protected-span multiset identical pre/post) +
917
- golden files per rule + the graded bench measuring each grammar rule as a lever.
918
-
919
- ## Phase 8 — The Repository Interface (seonix inverts to a tmct user)
920
-
921
- > **STATUS: shipped.** A versioned (1.0.0), OWL-grounded service contract
922
- > (`docs/repository-interface.md` + `.schema.json`); a typed graph-service with a first-class
923
- > miss contract (a miss is a value, not a throw); fixture + bootstrap reference providers; a
924
- > runnable conformance/compatibility suite; and `tmct init` (scaffold `.tmct/`, `tmct.toml`,
925
- > tier-1 seed, provenance).
926
-
927
- > Detailed plan: **`archive/PLAN_REPOSITORY_INTERFACE.md`**.
928
-
929
- *(Operator-specified 2026-07-05; upgraded from research item to a build phase. tmct was spun OUT
930
- of seonix; this inverts the relationship: seonix reorients as a USER that imports the tmct
931
- library and exposes its graph to tmct as a typed service. Grows item 14's provider adapter from
932
- a passive payload loader into the product's primary integration surface.)*
933
-
934
- **Phase deliverables — define, reference-implement, and test the interface:**
935
- 1. **The interface DEFINITION**: the typed, OWL-grounded service contract as a versioned
936
- document + machine-readable shape (docs/repository-interface.md + a JSON-schema/typedef of
937
- every service, its arguments, result types, and error contract) — tmct owns and versions it.
938
- 2. **A REFERENCE IMPLEMENTATION tmct ships itself**: the in-repo provider (fixture graph +
939
- bootstrap/empty graph) implementing EVERY service of the interface — the executable
940
- specification any external producer reads first.
941
- 3. **The contract test suite (the compatibility kit)**: a runnable suite any implementation is
942
- tested against — tmct's reference implementation passes it in `npm test`; seonix runs the
943
- SAME suite against its native implementation to claim conformance. Conformance = the suite,
944
- not prose.
945
- 4. **The session-handle lifecycle**, implemented: create/dispose context handles (focus, last,
946
- memory dir, lexicon), provider-owned caching, documented re-entrancy — proven by the
947
- contract suite's concurrent-session cases.
948
- 5. **`tmct init`** shipped as part of this phase (it is the interface's onboarding surface).
949
-
950
- - **tmct defines the adapter shape** — not the producer. Rationale: tmct is the brittle side
951
- (query interpretation), so it must own and optimize around a STABLE interface; because the
952
- vocabulary is OWL-grounded, the human/code world is already quantized into types both sides
953
- understand, so the interface is built from those shared types, not ad-hoc JSON.
954
- - **A rich instruction set, translated from what seonix already exposes**: survey seonix's
955
- native tool surface (describe / members / subclasses / impact / callers / callees / tests-for /
956
- untested / history / exports / architecture / search / context / snippet / locate / digest —
957
- the dispatchTool catalog tmct carried at the lift) and translate it into tmct's language as
958
- the REPOSITORY INTERFACE: a consistent set of typed services any graph producer implements
959
- natively (seonix first; the empty/bootstrap and fixture providers are degenerate
960
- implementations tmct ships itself).
961
- - **The flow** (LLM-agent front door): Claude Code et al. is briefed to use seonix → when the
962
- agent judges it useful, seonix's "ask" tools pass NATURAL LANGUAGE to tmct → seonix calls the
963
- tmct library in-process with the query PLUS a callbacks object (functions implementing the
964
- repository interface over its native graph) → tmct resolves the query mechanically, calling
965
- back into seonix's services for graph truth → results return through seonix to the LLM agent.
966
- The mechanical interpreter becomes the NL front-end for any agent-facing graph tool; the LLM
967
- stays outside tmct, exactly as the no-LLM ethos requires.
968
- - **In-process lifecycle research (the hard part)**: seonix calls tmct directly, and the
969
- interface is wider than the in-house chat — so define explicitly what is HELD IN MEMORY
970
- between function calls: an explicit session/context handle (focus, last-answer, memory dir,
971
- loaded lexicon) created and disposed by the caller instead of process-global state; graph
972
- caching delegated to the provider (tmct never caches provider truth — the known source.mjs
973
- process-cache staleness in long-lived servers becomes the provider's concern, by contract);
974
- re-entrancy and concurrent-session guarantees documented per service.
975
- - **seonix chat becomes tmct chat + a pointer**: seonix's chat surface loads tmct's chat with
976
- the repository-interface handle — one chat implementation, N graph backends.
977
- - **Browser mode**: the same inversion works in seonix's browser/code-browser surface — seonix
978
- finds its own graph (it already ships one to the page) and embeds an OFF-THE-SHELF tmct: the
979
- engine core (interpret / ask / render, lexicon, templates) is already pure JS with no
980
- node-only dependency — wink's eng-lite-web-model is literally the browser build — so the
981
- repository interface + a browser storage seam for memory (or provider-supplied persistence)
982
- is all that separates the npm package from running in the page. The fs/readline/child_process
983
- seams stay node-side; the browser gets the library surface, not the shell.
984
- - **Distribution: `tmct init`** — a CLI command that initializes a local directory for tmct:
985
- seeds/links the text corpuses (tier-1/2 policy applies), writes the externalized configuration
986
- (tmct.toml — the seonix.toml pattern), creates `.tmct/`, and records provenance — so a host
987
- package (seonix) or a bare user gets a working install with one command.
988
-
989
- ## Phase 9 — Speculative inference: a step toward the Syllogist
990
-
991
- > **STATUS: shipped.** `tmct syllogise [--depth n] [--budget n]` — an offline, bounded,
992
- > deterministic maintenance job that forward-chains the `rdfs:subClassOf` closure into low-trust,
993
- > retractable entailed facts; runs once after seeding, never on the chat hot path.
994
-
995
- *(Operator-specified 2026-07-05. Tier-5 entailment answers a MISS on demand; this is the step
996
- before it — PROACTIVELY extending memory with inferences that will be useful later, forward and
997
- backward chaining over the OWL base during idle/fold time rather than at query time.)*
998
-
999
- > Detailed plan: **`archive/PLAN_SPECULATIVE_INFERENCE.md`**.
1000
-
1001
- **A maintenance job, not a query-time cost.** Speculative inference runs as an explicit
1002
- batch — `npx tmct syllogise --depth <N>` (default depth bounded, e.g. 32) — and **once
1003
- automatically after seeding** (the W3 bootstrap seed is the natural trigger: a fresh corpus is
1004
- exactly when pre-deriving the useful closure pays off). Never on the chat's hot path.
1005
-
1006
- **The selection criterion, sharpened by the operator (2026-07-05):** the guiding question is
1007
- *"what do the assertions of the sources I TRUST allow me to infer about this topic that is of
1008
- RELEVANCE"* — so **novelty × trust is the primary driver**: the pass walks
1009
- outward from high-trust premises (the provenance primitive) toward novel, relevant conclusions,
1010
- timestamping each so recency and novelty stay computable. The mechanics are the easy half
1011
- (bounded forward chaining materializes entailments; backward chaining from frequent query shapes
1012
- pre-derives likely answers). **The residual hard half is still the FRAME PROBLEM / relevance
1013
- realization — unsolved in the general case and not pretended otherwise.** This is not one problem
1014
- but two, of different hardness (full literature + citations in `PLAN_CAPABILITY_ROUTER.md`'s "The
1015
- open-world boundary" section):
1016
-
1017
- - **The frame-*axiom* problem — solved, inside a declared world.** McCarthy & Hayes named it in
1018
- 1969 ("Some Philosophical Problems from the Standpoint of Artificial Intelligence", *Machine
1019
- Intelligence* 4); Reiter's 1991 successor-state axioms and Kowalski & Sergot's 1986 event
1020
- calculus (*New Generation Computing* 4(1)) both solve the narrow reading — stating what changes
1021
- without enumerating what doesn't — inside a **declared** effect/predicate model. That's exactly
1022
- the OWL base the Syllogist forward-chains over: the axioms and rules are declared, so applying
1023
- them is mechanical, bounded, and already shipped (`src/syllogise.mjs`).
1024
- - **The relevance-*bounding* problem — genuinely open, and possibly not just unbuilt.** Given the
1025
- unbounded set of entailments a rich KB licenses, which ones are worth materializing *before
1026
- anyone asks* — without an oracle telling the pass what matters? That is McCarthy's deeper,
1027
- unsolved reading, and it has no known algorithm. It is also, independently, the central problem
1028
- a live cognitive-science literature has converged on: Vervaeke, Lillicrap & Richards ("Relevance
1029
- Realization and the Emerging Framework in Cognitive Science", *Journal of Logic and Computation*
1030
- 22(1):79–99, 2012) frame it as the pervasive problem cognitive science keeps rediscovering: Jaeger,
1031
- Riedl, Djedovic, Vervaeke & Walsh ("Naturalizing relevance realization: why agency and cognition
1032
- are fundamentally not computational", *Frontiers in Psychology*, 2024) go further and argue —
1033
- contestably, but rigorously, not as a popular-science claim — that relevance realization
1034
- *cannot* be an algorithmic process at all, by an analogy to Gödelian incompleteness. Take that as
1035
- a live, unresolved argument, not a proof: the honest position is that tmct doesn't know whether
1036
- this is "hard" or "impossible", and says so.
1037
-
1038
- trust+novelty+relevance (query-shape frequency, recent-focus connectivity, a hard depth/budget
1039
- cap) are the **tractable approximation** the plan actually ships — a proxy for relevance, not a
1040
- solution to it, and openly so. **A speculative angle, still respecting no-LLM-in-product:** the
1041
- same bounded-region trick sketched for the router's open-world goal recognition
1042
- (`PLAN_CAPABILITY_ROUTER.md`) applies here. Instead of trying to bound relevance globally (the
1043
- open problem above), bound it *per query-shape*: a query shape already declares which
1044
- predicates/fluents it touches — it's how `parseQuery` resolves it — so restricting speculative
1045
- forward-chaining to premises reachable within N hops of an **observed** query shape's declared
1046
- predicates is a *structurally*-bounded relevance filter, not a learned or statistical one. It is
1047
- narrower than "what's relevant in general" (that stays open) but might be enough to keep
1048
- materialization from drifting into computing entailments nobody will ever ask about — trading
1049
- "relevant to anyone" (unsolved) for "relevant to what this system has actually been asked"
1050
- (a proxy, but a principled, deterministic one). This has not been built or measured; it is a
1051
- candidate for the plan's next spike, not a claimed result. Everything else is deferred to the
1052
- plan's open questions, where the relevance problem is named as the open research risk it is.
1053
-
1054
- ### Open-source the ACE-OWL parser as a standalone library
1055
- > **STATUS: tried, reverted (2026-07-10).** A session extracted `ace.mjs`/`lexicon.mjs` into
1056
- > `packages/ace-owl`, a new npm workspace, and pointed tmct's own `package.json` at it as a
1057
- > registry dependency — but never published the package. That broke `npm install` for tmct
1058
- > itself (`@polycode-projects/ace-owl` 404s on the public registry, since it only ever existed as
1059
- > a local workspace symlink). Folded back into `src/grammar/` the same day, on operator
1060
- > instruction, once the break was found. If this is worth doing again, publish the package FIRST
1061
- > (or in the same change), never split the two steps across a batch. See `PLAN_OSS_ACE_PARSER.md`.
1062
-
1063
- *(Operator-specified 2026-07-05, from the dependency audit's publish-not-replace finding.)* The
1064
- pure-JS, ESM, dependency-free ACE-OWL controlled-grammar parser (`src/grammar/ace.mjs` +
1065
- `lexicon.mjs`) that turns controlled-English sentences into OWL-labelled triples is a RARE thing:
1066
- the reference implementation (APE) is GPL + SWI-Prolog (native), so there is no permissive,
1067
- browser-capable, npm-installable ACE→OWL parser in the JS ecosystem. tmct's is exactly that.
1068
- Extracting it to its own MPL-2.0 package (tmct depending on it back) would give the wider
1069
- RDF/OWL/semantic-web JS community a controlled-natural-language front-end that runs in the
1070
- browser — genuine value, but only once actually published; see `PLAN_OSS_ACE_PARSER.md` for the
1071
- full design and the note above for what went wrong the first attempt. Sibling publish-candidates
1072
- (the bounded-Damerau fuzzy matcher, the PageRank+IDF block ranker) are lower priority than getting
1073
- this one right before trying another.
1074
-
1075
- ## Phase 10 — Conversational competence & onboarding (0.6.0 → 0.7.0)
1076
-
1077
- *(Operator-directed, from live new-user testing.)* Once a graph is loaded the engine is strong;
1078
- the weak surfaces were the FIRST RUN and the VAGUE question. This phase makes the miss graceful,
1079
- the empty state honest, and the vague touch a guided answer — realising item 1's "tolerant, guides
1080
- you toward precision" promise on the conversational surface.
1081
-
1082
- - **Onboarding UX (shipped 0.6.0):** the grammar wall moved behind `/help` (a short, tailored miss
1083
- instead); intent lanes for memory/teach ("remember that X"), meta/self ("what is this codebase",
1084
- "what do you know"), routed only when a graph query would miss; empty/degenerate-graph
1085
- orientation that distinguishes CODE STRUCTURE (needs a `.tmct/graph.json` via a producer or
1086
- `--repo`; tmct reads graphs, it does not index code) from VOCABULARY (`tmct init`/bootstrap seeds
1087
- concepts); `TMCT_GRAPH_FILE` honoured by chat; slash-optional commands (`stats`≡`/stats`);
1088
- `/memory` explore hooks; up/down-arrow prompt history in the TUI.
1089
- - **Knowledge (shipped 0.6.0 → 0.7.0):** the curated `corpus/seon` ontology — a software-sense
1090
- definition for EVERY lexicon term, language-neutral (Java/C#/Python `class` → one concept); the
1091
- ConceptNet slice quality-filtered (word-sense noise cut) and regrown to ~40k facts; tier-2
1092
- specialised corpuses (aws/python/java) with `tmct init --corpus`; batched `appendFacts` (one
1093
- write, 419s→2.5s) enabling **seed-all** so a fresh repo knows the whole curated vocabulary.
1094
- - **The concept force (shipped 0.7.0):** a vague touch on a concept X, where tmct knows X and has instances,
1095
- answers in three bands — **the definition** (from `corpus/seon`), **the examples** (real code-graph
1096
- + memory instances of X), and **a soft guided follow-up** ("Want to go deeper?" + 2–3 questions
1097
- built from the real instances × the query shapes valid for that kind, each pre-validated to
1098
- resolve). Applies to NOUN concepts (`what is a class` → define + Base/Widget/Button + drill-ins)
1099
- AND **RELATION concepts** (`what about imports` / `what calls are there` → the verb definition +
1100
- example edges + guided queries), fixing the vague-query dead-ends. Fact rendering is
1101
- de-anthropomorphised (no first-person "i learned:" over-claim — corpus facts read as data +
1102
- provenance; `you told me` stays for operator-asserted facts); listings cap at 32 with a "say
1103
- 'more'" pagination that holds the remainder in session state.
1104
- - **Dead-end routing + read-only demos (shipped 0.7.0):** natural drill-down phrasings are routed
1105
- onto the canonical shapes they mean — `what functions are in X` → members-of-class, `what defined
1106
- X` → where-is-X-defined, a no-context `what about X` → the concept/relation force (the discourse
1107
- continuation still wins when there IS a prior answer). `tmct chat --ephemeral` (and the
1108
- `npm run example:*` demos) reads a graph but writes nothing back, so a checked-in example is never
1109
- dirtied by a demo run.
1110
- - **The dialogue-flow loop (`SKILL_CHAT_PLAYTEST.md`, 0.7.0):** a fast, qualitative tuning loop that
1111
- complements the LLM-judge benchmark — Claude plays a curious user, hunts *dead-ends* (walls,
1112
- "unknown qualifier", phrasing-misses, invited follow-ups the engine can't take), fixes them by
1113
- ROUTING to existing capabilities, replays the same conversations until they flow, freezes them as
1114
- regression transcripts, then ratchets the complexity tier. The drill-down transcript above is its
1115
- first frozen fixture (`test/chatflow-drilldown.test.mjs`).
1116
- - **Measured** by the version-matched benchmark (`CEFR_ENGLISH_<version>` per `SKILL_BENCHMARK_CEFR_ENGLISH.md`),
1117
- with new graded cells for the miss / empty-graph / concept-touch surfaces so these become
1118
- regression-protected levers, not one-off polish.
1119
-
1120
- ## Phase 11 — The capability router & the agentic bench (0.8.0 shipped · 0.8.1 deepened · 0.8.2 feel + rule-general C2)
1121
-
1122
- *(Operator-directed 2026-07-06; built the same day across five concurrent tracks.)* tmct as a **deterministic, no-LLM
1123
- tool router** behind an Anthropic-compatible API — the workstream specified in
1124
- `PLAN_CAPABILITY_ROUTER.md`, grounded in `docs/references/planning/`. This is a **new capability on a
1125
- new axis** (driving a tool loop, not answering a chat turn), so it gets its **own benchmark**:
1126
- **`AGENTBENCH`**, a sibling to CHATBENCH — same versioned-naming + grading discipline
1127
- (`AGENTBENCH_<version>.md`, `_00N` for re-runs), but the levels are the **A0→C2 agentic rungs** and a
1128
- **hallucinated tool call is an automatic fail**.
1129
-
1130
- **Status: DEMONSTRATED (with a stated scope caveat).** The router is built and measured:
1131
- `AGENTBENCH_0.8.0_001` = **96% completion at 0% hallucination on every rung**, closed-world ladder
1132
- cleared to **C1**. The gate the phase was staked on — a **0% hallucination rate on a real domain** (the
1133
- graph-query toolset over the fixture) — **is met.** The honest scope line, held from the start:
1134
- AGENTBENCH grades the correct **call-plan + causal-link proof, not the executed composed result**; the
1135
- B1/B2/C1 rungs are **thin (2–3 cases)**; and the one C2 case is **refused** (the Stage-5 goal-reasoner
1136
- is designed, not built). So "closed-world C1" means *the router provably selects and binds the right
1137
- tool sequence*, not *end-to-end multi-step reasoning* — the demonstrated-vs-designed boundary is the
1138
- real deliverable. The five tracks below are all built; the two research-agent stages (Track 4 below)
1139
- remain designed-not-built by intent.
1140
-
1141
- ### Track 1 — chat-surface levers (next CHATBENCH; all three)
1142
-
1143
- > **STATUS (0.8.2):** the surrounding feel surface landed — PLAN_CHAT_FEEL items **1–5, 7, 8**
1144
- > (recall hygiene, preamble frames, call-relation self-consistency, author lane, wall kindness,
1145
- > teach-lane widening, honest nudges) shipped and gate-verified deterministically. **The trio
1146
- > below is DEFERRED post-release with measured targets** (advisor tick-4): pronoun red set = 18
1147
- > g-b1-pron ids; temporal = g-b1-temp ×5 + g-c1-temp ×9; discourse-count re-measure first — it
1148
- > sampled 0/5 red and is likely already green. See HANDOVER follow-up #3.
1149
-
1150
- The three levers `CEFR_ENGLISH_0.7.1` measured + ranked — which **double as router prerequisites** (they
1151
- gate the A2→B1→C1 rungs, per Phase B of the router plan):
1152
- 1. **Pronoun / focus binding** — the "it → Commit" mis-bind (`B1 pron 1.24`); biggest movable mass.
1153
- 2. **Discourse-count anaphora** — "count them / how many of those" over a prior listing (clears the 2
1154
- `CEFR_ENGLISH_0.7.1` tier-1 misses).
1155
- 3. **C1 temporal-over-relative composition** — the two-hop ceiling (`C1 temp 0.31`).
1156
- Land all three (not just #1); they raise the chat floor *and* the router's floor at once.
1157
-
1158
- ### Track 2 — the router build (the within-horizon slice, in order)
1159
-
1160
- > **STATUS (0.8.2):** the C1 composition gap closed — the **member-filter HTN method + per-member
1161
- > callees hop** flips the standing C1 red in both drivers (resolver floor A0–C1 all 100/100); the
1162
- > ladder grew 43→56 fixture-linted cases; the bench-import smell is inverted
1163
- > (`src/router/call-validator.mjs` + `set-algebra.mjs`).
1164
-
1165
- Buildable now with a frontier model as co-author (see PLAN §"solved vs unsolved"):
1166
- - **Phase A — the shim.** An Anthropic Messages API endpoint (`/v1/messages`, `tool_use`/`tool_result`
1167
- blocks). **Extended:** also present as a **`bedrock-meter`-compatible routing target** (see below).
1168
- - **Phase B — measure today → `AGENTBENCH_0.7.2.md`.** Shim + a small graph-query toolset up the
1169
- A0→C2 ladder; the honest baseline (expected A0 solid, A1–A2 partial, per the CEFR_ENGLISH_0.7.1
1170
- inherited assets).
1171
- - **Phase C — the grading ladder.** The AGENTBENCH benchmark itself (rungs as levels, comparable
1172
- local/hosted models as reference bands, zero-hallucination gate).
1173
- - **Stage 0 — capability registry** (`Capability`/`Parameter`/`Precondition`/`Effect` = STRIPS/PDDL
1174
- operators as facts).
1175
- - **Stage 1 — the resolver** (unification + backward chaining / a mini Datalog).
1176
- - **Stage 4 — the guardrail** (validate an LLM's proposed `tool_use` against declared preconditions —
1177
- the hybrid fast-path; cheap once 0–1 exist).
1178
- - **Stage 3 — the planner** (POP/HTN over operators + Steel & Ho monitor-and-replan → **closed-world
1179
- C1**; optionally defer search to an external PDDL solver).
1180
-
1181
- ### Phase A extension — the `bedrock-meter` deployment surface
1182
- `../bedrock-meter` is pre-flight Bedrock cost metering + capping, with a **roadmap optimiser** that
1183
- "cheaply assesses a task's complexity … and routes to the lowest-cost capable model" (it already
1184
- meters Nova Lite + Nova Micro). tmct — **benchmarked against agent capabilities by AGENTBENCH** — slots
1185
- in as the **$0 floor *below* Nova-micro** in that routing ladder: for a request class AGENTBENCH proves
1186
- in-envelope, the optimiser routes to tmct (deterministic, ~$0, ms latency) instead of any metered
1187
- model. So Phase A's shim is built **bedrock-meter-pluggable**, and AGENTBENCH is what defines the
1188
- envelope the optimiser is allowed to trust. This is the concrete "near-free alternative" deployment.
1189
-
1190
- ### Track 3 — playtest alongside the build (`git worktree`)
1191
- Run `SKILL_CHAT_PLAYTEST.md` **in a parallel `git worktree`** while the router is built — the
1192
- dialogue-flow dead-end hunt keeps running without blocking the build, and its fixes **merge back**.
1193
- (The worktree is auto-cleaned if unchanged; merge the frozen `test/chatflow-*` transcripts in.)
1194
-
1195
- ### Track 4 — research agents (the "at the edge" stages)
1196
- Two stages need design judgment + exploration, so they run as **background research agents**, off the
1197
- critical build path:
1198
- - **Stage 2 — intent frames, controlled fragment** — imperative NL → structured intent for the
1199
- controlled command language (the front-end; the general case stays out-of-scope / escalate).
1200
- - **Stage 5 — goal-reasoner, closed-world C2** — BDI + Goal-Driven Autonomy: deduce-goals (long-chain
1201
- deduction) → plan-each (C1) → threat-aware, *persistent* first-step arbitration.
1202
-
1203
- > **STATUS (0.8.2):** both research stages are now BUILT and measured. Stage 2 landed in 0.8.1_002;
1204
- > Stage 5's 0.8.1 "one thin rule" caveat is retired — **C2 is rule-general**: two declared
1205
- > goal-rules (`coverage-invariant`, `cochange-risk-invariant`) selected by pure `applicableRules`
1206
- > deduction with honest refusals at both failure modes (0 applicable = open-world, >1 = ambiguous),
1207
- > zero request keywords. Goal driver: 100% plan / 98% result / 0% hallucination over 56 cases.
1208
-
1209
- ## Phase LATER — recognized, deferred, not now
1210
-
1211
- Features we have deliberately shaped seams for but will not build until the phases above have
1212
- earned them. **Not everything below is deferred for the same reason** — the design horizon,
1213
- stated explicitly (2026-07-08 research pass):
1214
-
1215
- **`PLAN_AGENTS.md` (2026-07-10) is the governing plan for tmct's next major arc** — mounting tmct
1216
- hard into `../marginalia` and `../seonix` as their shared NL↔graph engine and tool-loop/completions
1217
- API, plus a pluggable LLM rung for Claude Code, Amazon Bedrock, and GitHub Copilot. It sequences
1218
- Phase 0 (foundations — an extension-pack/corpus-lexicon seam, RI wrapper fixes, several other
1219
- small known-how items) through Phase 4 (the LLM-rung protocol shims), a "tmct uplift" section
1220
- grounded in fresh comparative audits of both sibling repos, and a tiered research horizon (R1–R3).
1221
- It supersedes the six phase/track pointers below that reference now-archived docs — treat this
1222
- paragraph as the up-to-date entry point, and the items below as historical record of how those six
1223
- docs' scope was reached before consolidation.
1224
-
1225
- ### Future direction: a genuine planning/agentic loop (flagged 2026-07-09, research pass done, not implemented)
1226
-
1227
- The operator's own framing, explicitly out of scope for the routing-level `GOAL_BY_COMMAND`/
1228
- Goal-inference generalization this session shipped (HANDOVER's Bug F point 5, which only labels
1229
- an already-computed answer's intent — it never plans ahead of one): infer the goal, read the
1230
- relevant subgraph, reason about candidate action-paths and their effects, pick the next step,
1231
- execute, repeat.
1232
-
1233
- Two companion research docs (2026-07-09, design only, zero code shipped) scope this against
1234
- minimal benchmark domains before anything domain-general is attempted:
1235
- - `PLAN_HANOI.md` — the OPEN-LOOP case (a whole solution path is computable up front from the
1236
- start state). Recommends representing state as taught facts in the memory store (not the
1237
- read-only, provider-owned code graph), a new `restsOn` edge encoding stack order, and genuine
1238
- bounded state-space search — reusing `syllogise.mjs`'s `findIsaChain` (already, in shape, a
1239
- bounded rooted BFS path search) — over hard-coding Hanoi's known closed-form recursive solution,
1240
- so the result is an actual generalizable planner, not a Hanoi-shaped trick.
1241
- - `PLAN_GUESS_NUMBER.md` — the CLOSED-LOOP case ("I am thinking of a number," both as guesser —
1242
- belief-interval bisection over repeated higher/lower observations — and as thinker — tmct holds
1243
- a secret and gives honest feedback, no search needed). Recommends a new parallel session-state
1244
- slot (`game`) threaded through `createSession`/`runTurn` exactly the way `focus` already is,
1245
- kept deliberately separate from the `pending` pagination field since a game must survive an
1246
- aside mid-play, unlike a listing remainder.
1247
- - `PLAN_TAUGHT_RELATIONS.md` — teaching tmct brand-new relations and rules through ordinary chat
1248
- (a taught Prolog-style family tree, none of the kinship vocabulary hardcoded), the first of the
1249
- three to need a successor function SYNTHESIZED from data the user taught in an earlier turn,
1250
- rather than hand-written per domain the way Hanoi's `legalMoves` and guess-number's
1251
- interval-update rule are. Its own enumeration capability ("list the descendants of X," no fixed
1252
- goal) needs a genuine new sibling kernel, `findReachableSet`, since `findActionPath` only ever
1253
- searches toward one goal.
1254
-
1255
- All three docs converged on the one genuinely new primitive none of them found already built
1256
- anywhere in tmct: something that computes a SUCCESSOR STATE (apply a chosen action, produce the
1257
- next graph/belief to reason over) — every existing traversal (`ancestorsOf`, `computeFind`,
1258
- `findIsaChain` itself) is read-only. That primitive now exists (`findActionPath`, `src/planning.mjs`,
1259
- shipped this session — see "Shipped this session" above), proven against a small toy graph but not
1260
- wired into any of the three domains yet. The remaining next-session scope is that wiring, plus a
1261
- still-open recognition question: how tmct notices "the user wants goal-directed action" at all, and
1262
- whether multi-step execution needs confirmation before running.
1263
-
1264
- ### The design horizon
1265
-
1266
- **Before the horizon — known-how, not-yet-built, no research risk.** Sequencing or engineering
1267
- debt: the technique exists (in tmct's own prior work or the wider literature), building it is a
1268
- matter of scheduling and effort, not discovery. Everything shipped this session lives here, plus:
1269
- tone-of-voice adaptation (below — deliberately dropped by design choice, not unsolved);
1270
- tier-4 learn-on-miss (below — prerequisites not yet met, not research-blocked); `PLAN_CODE.md`
1271
- Tracks 2–4 (mutation search/repair, JS/HTML/CSS synthesis — APR and CEGIS are established
1272
- techniques); `PLAN_OSS_ACE_PARSER.md` (pure extraction/packaging); OWL 2 RL forward-chaining and
1273
- DL tableau consistency checking (`PLAN_INFERENCE_TESTING.md` stages 3–5 — the W3C's own OWL 2 RL
1274
- profile is a published, complete rule table; Pellet/HermiT/RDFox/Jena are real production
1275
- reasoners built on solved theory); RETE/incremental forward-chaining (same doc — Forgy 1982 is a
1276
- citable, portable algorithm); contingent/conformant planning under initial-state uncertainty
1277
- (`PLAN_CAPABILITY_ROUTER.md` — Bonet & Geffner 2000, Hoffmann & Brafman 2006, Petrick & Bacchus
1278
- 2002 all have working algorithms); ordinary closed-domain anaphora resolution (`nextFocus`,
1279
- already shipped, plus a real theoretical grounding available in Grosz/Joshi/Weinstein's centering
1280
- theory, 1995).
1281
-
1282
- **After the horizon — genuinely unsolved in the field, or abandoned by the field in favor of
1283
- approaches tmct's no-LLM ethos rules out.** Named as real research targets, with citations, not
1284
- stop signs (full detail + full citation lists in each owning doc):
1285
- - **The frame problem / relevance realization** — the open-world planning boundary
1286
- (`PLAN_CAPABILITY_ROUTER.md`'s "The open-world boundary" section; this doc's tier-5 Syllogist
1287
- paragraph below). McCarthy & Hayes 1969 named it; Jaeger, Riedl, Djedovic, Vervaeke & Walsh
1288
- (2024) argue it may not be algorithmically solvable in the general case at all. Speculative
1289
- angle recorded: bounded (N+1) goal recognition — recognize declared goal 1..N, or reject to an
1290
- explicit "escalate" class, via parse-shape membership (the same mechanism Bug 8's domain gate
1291
- already uses) — not published anywhere found.
1292
- - **Symbolic (non-neural) dependency parsing at real coverage** — `PLAN_ADVANCED_GRAMMAR.md`
1293
- track (c). Largely abandoned by mainstream NLP research once neural parsers won CoNLL
1294
- 2017/2018, not disproven at any fixed data budget. Speculative angle: a hand-built,
1295
- closed-vocabulary disjunct/category dictionary (Link Grammar/CCG-style) scoped only to tmct's
1296
- own closed relation vocabulary, registered as another additive interpretation strategy.
1297
- - **Winograd-hard commonsense coreference** — `PLAN_ADVANCED_GRAMMAR.md` track (g). Genuinely
1298
- open without either massive statistical priors (ruled out) or a full commonsense KB (Cyc's
1299
- decades-long cautionary history). Speculative angle: tmct's own closed, complete graph makes a
1300
- *narrow slice* of Winograd-shaped ambiguity a graph-query-filtering problem rather than
1301
- open-domain commonsense reasoning — explicitly not the same as solving Winograd.
1302
- - **Bounded, incremental, trust-tiered, retraction-safe justification tracking** —
1303
- `PLAN_INFERENCE_TESTING.md`'s stage-3/4/5 discussion. Doyle's JTMS (1979) and de Kleer's ATMS
1304
- (1986) solve retraction; DRed/RDFox's Backward-Forward solve incremental Datalog maintenance;
1305
- nobody has published the specific combination with tmct's multi-trust-tier, hard-budget
1306
- requirement. Speculative angle: an ATMS-lite extension to `syllogise.mjs`'s currently-flat
1307
- provenance tag, sketched but unbuilt.
1308
- - **A shared ~2M-word cross-domain ontology (1M general-English base + 1M
1309
- technical/scientific/engineering/programming-language/slang)** — `PLAN_ontology-hierarchies.md`
1310
- §7, additive to (not a revision of) that doc's existing track (e), which stays about importing
1311
- raw WordNet into tmct's own small tier-1 corpus specifically. Walked into, not avoided: merging
1312
- two 1M-word vocabularies collides senses of lexically-shared words (`class`, `cache`, `thread`,
1313
- `wave`, `cell`, `field`, `state`, …) across general/CS/physics/biology/slang registers —
1314
- knowledge-based (non-neural) WSD is real but measurably weaker than supervised/neural WSD (Lesk
1315
- 1986; Raganato, Camacho-Collados & Navigli, EACL 2017), and BabelNet (Navigli & Ponzetto,
1316
- *Artificial Intelligence* 193, 2012) proves automatic cross-resource sense merging at this scale
1317
- is achievable — but its own pipeline moved toward statistical/graph-ML methods as it scaled,
1318
- solves the cross-*lingual* not cross-*domain* axis, and carries a non-commercial licence, so it
1319
- is a precedent, not a usable vehicle. Speculative angle recorded: mutual disambiguation from
1320
- already-resolved neighbouring terms in tmct's own closed graph (a structurally-bounded,
1321
- deterministic reading of Gale/Church/Yarowsky's "one sense per discourse/collocation"
1322
- regularities) — not published anywhere found for this application.
1323
-
1324
- Every item above is honestly labeled speculative — a direction recorded so it isn't
1325
- re-discovered from scratch, not a committed build plan. None of it is scheduled; the phases above
1326
- this line are still the actual near-term work.
1327
-
1328
- ### Tone-of-voice adaptation (dropped from Phase 6, 2026-07-05)
1329
- Per-voice synonym/phrase substitution over prose spans. Dropped because tmct's protected-span
1330
- analysis leaves too little safely-substitutable text: any term with technical significance is
1331
- untouchable, and accuracy outranks helpfulness trickery. Revisit only if a provably-safe
1332
- substitutable subset emerges (e.g. connective-only voice profiles, or per-voice template
1333
- overrides authored as whole alternatives rather than substitutions). The grammar-preference
1334
- half of the idea survives inside Phase 6's rule table.
1335
-
1336
- ### Tier-4 corpus: learn-on-miss acquisition
1337
- The strongest miss signal tmct can emit is: *lexicon term recognized, query built cleanly,
1338
- zero matches anywhere* — the question was well-formed and the knowledge is simply absent. The
1339
- tier-4 loop answers it by learning: web search on the resolved term → clean the fetched text
1340
- into tmct's own dialect (normalize into the ACE-OWL controlled grammar; whatever survives the
1341
- grammar becomes Facts, whatever doesn't becomes tier-2 text blocks under the PageRank index) →
1342
- store on disk with source provenance → ingest → answer the original question from the newly
1343
- learned material, citing what was just learned and from where. Strictly opt-in, network tier
1344
- rules apply (offline default inviolable; failure degrades to the honest miss). Prerequisites:
1345
- W1-W5 wired and measured, the Phase-5 template/dialect cleaning machinery (the "clean dialect"
1346
- IS the acquisition format), and a provenance-trust policy for web-sourced facts (never blended
1347
- silently with graph/operator facts — the `via`/provenance discipline extends to "learned:web").
1348
-
1349
- ### Tier-5: entailment-on-miss — "the Syllogist" (deductive inference over the OWL base)
1350
- *(Item 11 matured from exploratory sketch to a designed tier; the "theorem-prove against
1351
- parsed prose" thread of the original code-talker ideas.)*
1352
-
1353
- **The concept, classically:** answering from the **deductive closure** of a knowledge base —
1354
- KB ⊨ φ ("the knowledge base *entails* φ") — content that is nowhere ASSERTED in the graph,
1355
- memory, or corpus, but is a logical CONSEQUENCE of what is. Deductive inference (modus ponens,
1356
- modus tollens, syllogistic chains) predates ELIZA by ~2,300 years (Aristotle's syllogisms →
1357
- Frege's predicate logic → Robinson's resolution principle 1965 → Kowalski's "logic as a
1358
- programming language" → Prolog's SLD resolution; on the rules side, forward-chaining production
1359
- systems and the Rete algorithm; on the OWL side, description-logic reasoners and the RDFS/OWL
1360
- entailment regimes). tmct's version: a well-formed query misses everywhere → run the inference
1361
- layer over the OWL-encoded facts + axioms → if the answer is ENTAILED, materialize it as a Fact
1362
- with `via:"entailed"` and a **proof-chain provenance** (the applied rules + premise facts,
1363
- renderable as a chain of thought in words: "every cache is a store; every store is a component;
1364
- so a cache is a component") → the same query now yields an answer that shows its derivation.
1365
-
1366
- **Worked shape (modus tollens over the code graph):** axiom "every tested module is covered by
1367
- a suite"; fact "m.mjs is covered by no suite" ⊨ "m.mjs is not tested" — never asserted,
1368
- honestly derived, provenance = the two premises + the rule name.
1369
-
1370
- **Engine choice (the Prolog / graph-query question):** the classical candidates are embedded
1371
- Prolog (SLD, backward-chaining, item 11's original sketch), a graph query syntax (SPARQL under
1372
- entailment regimes / datalog / openCypher), or a description-logic tableau reasoner. The
1373
- recommended target is **OWL 2 RL** — the profile DESIGNED to be implemented as forward-chaining
1374
- rules (datalog-style semi-naive materialization, polynomial, decidable): pure-JS implementable,
1375
- mechanical, explainable rule-by-rule — exactly in ethos. Prolog-style backward chaining stays
1376
- the fallback for query-time-only derivation if materialization proves too eager. Progol/ILP
1377
- (learning NEW rules from examples) remains a separate, further-out spike.
1378
-
1379
- **Gates:** the full-domain lexicon + OWL encoding in a queriable structure (Phases 2+4+5 and
1380
- tier-4's acquisition feed it), the provenance-trust policy (entailed facts must never silently
1381
- mix with asserted ones — a wrong axiom poisons the closure, so entailments are retractable by
1382
- provenance), and bench cells that measure inference specifically (premises in, conclusion
1383
- asked, derivation shown).
1384
-
1385
- ## Explicitly out of scope (for now)
1386
-
1387
- - No AWS, no benchmark rig — tmct is a published npm library + CLI with a
1388
- static GitLab Pages home page only.
1389
- - No auto-publish: releasing a version is gated on a deliberate version-bump
1390
- commit plus a configured `NPM_TOKEN` in CI.
1391
- - No MCP server, no LLM in the product path — permanently out of scope, not
1392
- just "for now".
1
+ # ROADMAP — tmct's current shape and what's next
2
+
3
+ Forward-looking at a **feature level**: what tmct is capable of right now, and what's planned next.
4
+ No session narrative, no dated diary, no "shipped/DONE" history — that's what git log and the
5
+ `archive/`/`BENCHMARK_*.md`/`CAPABILITIES_*.md` records are for. For **task-level** pickup (specific
6
+ open items, session-scoped), see `HANDOVER.md` instead this file doesn't duplicate that list.
7
+
8
+ ## What tmct is
9
+
10
+ A tolerant, ELIZA/PARRY-style chat surface over a codebase, obsessed with software the way PARRY was
11
+ obsessed with the mafia deterministic, zero-cost, **no LLM anywhere in the product path**. Guides a
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.
14
+
15
+ ## Ambition
16
+
17
+ Declared, forward-looking goals not yet achieved, stated here so they steer future work instead of
18
+ getting silently traded away by inherited caution:
19
+
20
+ - **Reach for Llama-3-level natural language fluency.** Not by putting an LLM in the product path
21
+ (still permanent, see "Explicitly out of scope") by growing rich template/surface-realization
22
+ variety, so an answer shape has many valid phrasings instead of one fixed slot-fill.
23
+ - **Resolve ambiguity breadth-first, always.** Every genuinely valid reading gets its own real answer
24
+ restated in full, never a bare "could mean X or Y — try rephrasing" punt, bounded only by existing
25
+ clipping/pagination limits. Landed for both ambiguity shapes tmct has: parse-level ties
26
+ (`renderCore`'s real-answer resolution, `CAPABILITIES_1.7.3.md` item 92) and entity-level ties (one
27
+ term matching several real graph individuals every fuzzy-match tie, every noise-strip alt-object
28
+ collision, `PLAN_BREADTH_FIRST_NLU.md` §1). CEFR-confirmed: `BENCHMARK_CEFR_ENGLISH_1.8.0.md`'s
29
+ `ambiguity`-tagged cell moved 1.438 → 1.875 (+0.437, the largest single-tag move on record), and
30
+ the fix resolved a case pair the `1.7.0` report called permanently unfixable (`am-meta-imports` vs
31
+ `g-a1-naming-9` same input, previously-incompatible expectations; both now score well against
32
+ one breadth-first answer). A dedicated audit found the two generic top-level bail-out hints
33
+ (`rephraseHint`/`compositionalHint`) are provably unavoidable at their actual miss sites, not
34
+ unwired nothing left to generalize there.
35
+ - **Paraphrase alongside the original, verified, never instead of it.** A surface-realization variant
36
+ sits next to the literal grounded answer, never replacing it, and its accuracy is checked, not
37
+ assumed by running tmct's own deterministic inference/consistency machinery (`src/syllogise.mjs`)
38
+ against both the original and the paraphrase: they must entail the same conclusions, and neither may
39
+ contradict the other sentence-by-sentence. The paraphrase generator itself stays template/rule-based,
40
+ same as everything else in the product path the novelty is verifying that variety costs nothing in
41
+ accuracy, not the generation mechanism itself.
42
+
43
+ These sit alongside, not against, the zero-fabrication discipline: an answer with no grounding is
44
+ still an honest miss, and breadth-first resolution means showing every real answer a genuine reading
45
+ produces, never inventing one to fill a gap.
46
+
47
+ ## Current capability surface
48
+
49
+ - **Grammar & parsing** (`src/grammar/`): an ACE-inspired controlled fragment (~8 sentence
50
+ patterns), plus multi-candidate ambiguity resolution — when a sentence has genuinely more than one
51
+ valid reading, every surviving interpretation is surfaced instead of one being guessed
52
+ (`archive/PLAN_DID_YOU_SEE_HER_DUCK.md`).
53
+ - **Compositional queries** (`src/ask.mjs`): recursive-descent over relative clauses, boolean
54
+ set-algebra (and/or/but-not), qualifiers, aggregates, superlatives, anaphora. Includes real
55
+ two-hop object-relative composition ("which modules import something that X depends on" —
56
+ `parseNested` `reverseSet`/`forwardSet`, nesting to depth ≥2), confirmed still working via a
57
+ live-tested example (`TOO_HARD_AUDIT.md` U2) after a stale benchmark write-up called it
58
+ "known-hard territory" it was always built and tested, just never re-checked.
59
+ - **Memory** (`src/memory/`): an OWL-labelled JSON graph on disk. Three persistence backends: flat
60
+ JSON (default), pure in-memory (zero disk I/O), SQLite (cached, incrementally-patched reads).
61
+ - **Reasoning** (`src/syllogise.mjs`): an OWL 2 RL-grounded rule ladder (subclass transitivity,
62
+ disjointness, someValuesFrom subsumption, cardinality, consistency checking), plus taught-relation
63
+ rules learned through ordinary chat (alias/union, fixed-hop composition, property-filtered
64
+ composition, recursive/reachability) none of it hardcoded per domain.
65
+ - **Default persona**: a general-knowledge "human-world" vocabulary seeded by default (three size
66
+ tiers, `--persona-size small|medium|large`), sourced from Open English WordNet and Schema.org.
67
+ Code-domain vocabulary (SEON/ConceptNet) is opt-in (`--with-persona code`). Query coverage
68
+ includes forward/reverse CapableOf, reverse-HasA, and reverse-inherits/subClassOf shapes (`"can a
69
+ dog bark"`, `"what has a tail"`, `"what inherits from horse"`) against both corpus-seeded and
70
+ freshly-taught facts.
71
+ - **Genuine multi-reading ambiguity resolves and answers, not just describes**: when a sentence has
72
+ two-plus valid readingswhether the ambiguity is in how the sentence PARSES or in which real graph
73
+ ENTITY a term names — tmct traverses and renders each one's real answer inline (not just a one-line
74
+ label), so the same input always reproduces the same full, useful answer.
75
+ - **Every answer carries a canonical restatement of what was understood**: an English gloss in tmct's
76
+ own preferred phrasing plus the same fact in a compact, machine-parsable notation
77
+ (`shape(kind, args...)` for a query, `fact(subject, predicate, object)` for a taught fact)
78
+ landed for the ask/query and teach/assert lanes; other chat lanes (conversational, commands) don't
79
+ have a real canonical form yet.
80
+ - **Graph traversal and provenance timestamps extend to the memory graph, now with a real viewer AND
81
+ a live embedded chat**: the hub-avoiding `spiralExpand` walk (previously code-graph/Module-only)
82
+ generalizes to any graph via a caller-supplied class predicate and id-normalizer; edges carry a
83
+ `createdAt` stamp and nodes get a derived `updatedAt`. `tmct viz [--focus <id>] [--output graph.html]`
84
+ renders it as one self-contained, locally-navigable HTML file (pan/zoom, click-to-inspect, a depth
85
+ stepper, per-class visibility filters, no server, no external deps) `npm run viz -- --output
86
+ graph.html && open graph.html`. The page embeds a real "Ask the graph" chat panel running tmct's
87
+ OWN `ask.mjs` engine client-side (bundled via esbuild, adapter-less no wink model, ~220KB): a
88
+ query resolves against the full graph and re-centres the view on the answer (focus-follows-answer),
89
+ and a node's class/label are click-to-query affordances.
90
+ - **Completions** (`src/completions/`): extractive, multi-sentence answers for broad "how does X
91
+ work" questions, grounded and source-cited never invents a fact beyond what's retrieved, though
92
+ see "Ambition" above for growing the phrasing variety around what's retrieved.
93
+ - **Capability router** (`src/router/`): a deterministic, closed-toolset agentic router behind an
94
+ Anthropic-compatible API measured by `AGENTBENCH`, not general function-calling. An ambiguous tool
95
+ argument stays an honest refusal (never a guess) but, since every registered capability is
96
+ read-only, now additionally carries each tied candidate's real dispatched result alongside it.
97
+ The C1 resolver defers a ranking/superlative request (a declared `SUPERLATIVE_EXTREMES` cue, e.g.
98
+ "what MOST needs a test") to the C2 goal-reasoner's keystone-argmax arbitration instead of
99
+ half-answering it with a flat unranked list — AGENTBENCH C2 is 11/11, 100% plan- and
100
+ result-complete (`TOO_HARD_AUDIT.md` M2, fixed).
101
+ - **Interfaces**: the `tmct` CLI, a documented library `exports` surface, and a Repository Interface
102
+ for downstream consumers (seonix).
103
+
104
+ Measured state for all of the above: the four `BENCHMARK_<TYPE>_<version>.md` reports
105
+ (`AGENT`/`CEFR_ENGLISH`/`CONVERSATION`/`INFERENCE`) and the periodic `CAPABILITIES_<version>.md`
106
+ audit always check the latest-dated one, not this file, for real numbers.
107
+
108
+ ## What's next (feature-shapedsee `HANDOVER.md` for the current task-level list)
109
+
110
+ - **`PLAN_BREADTH_FIRST_NLU.md`'s own remaining scope** all six tracks shipped (entity-tie
111
+ ambiguity, router candidate enrichment, `tmct viz` + its embedded chat panel, template-coverage
112
+ harness, alternates-on-hits, canonical representation for the ask/teach lanes — all now in "Current
113
+ capability surface" above). Two named items are satisfied and closed, per their own track's
114
+ original scope (an explicit operator decision, not a silent drop): (a) canonical representation
115
+ for every OTHER chat lane (conversational, commands, recall, ~78 `chat.mjs` return sites)
116
+ Track 6's own deliverable was the `canonical` field present on every response (even `null` where
117
+ unpopulated), which is met; full population everywhere was always a bigger, separately-scoped
118
+ follow-on. (b) growing the ACE grammar's free-form coverage past its measured 0/2,949-sentence
119
+ baseline §6's own stated non-goal was a harness + baseline + first generated batch, not closing
120
+ the gap itself, which is met; growing coverage further is `archive/PLAN_TEMPLATE_COVERAGE.md`'s
121
+ own remaining scope (needs more grammar patterns or vocabulary, not tooling). What's genuinely
122
+ still open: (c) the paraphrase-verified-via-`syllogise.mjs` piece of "Ambition" not started;
123
+ (d) a real "list/count all X of class Y" query shape for memory-graph classes live testing
124
+ during the viz chat panel's build confirmed no such shape exists via `ask.mjs` alone (only
125
+ `chat.mjs`'s heavier `factAnswer` cascade has it, out of the browser bundle's scope), so the viz
126
+ panel's class-badge click currently falls back to a real client-side filter + a "where is X
127
+ mentioned" query rather than a true "list all" a genuine, now-documented gap, not a silent one.
128
+ - **`archive/PLAN_TEMPLATE_COVERAGE.md`** archived; the coverage-harness/generation design from
129
+ (b) above, including the real baseline number and the first 17-row generated batch. **Coverage
130
+ growth attempted 2026-07-12**: a residue audit found only 19 words across 2,664 docs sentences
131
+ have pure content-word (vocabulary-only) residue the rest is genuinely grammar-structure
132
+ residue (coordination/negation/relative clauses), unfixable by vocabulary alone. Added 9 real,
133
+ generalizable words (`danger`/`push`/`refusal`/`tooling`/`legitimate`/`ranked`/`related`/
134
+ `sacred`/`unaffected`) to `src/grammar/lexicon-core.json`; real, honest delta: 0→1 hit (60.2%→
135
+ 60.1% residue a few sentences correctly reclassified residue→miss once their vocabulary gap
136
+ closed and a separate structural gap was exposed). Confirms the ceiling is structural, not a
137
+ vocabulary backlog closing it further needs real grammar-pattern work (a coordination/relative-
138
+ clause-capable parser), not more lexicon entries. **Second follow-on, wiring output variety into
139
+ the live answer path done 2026-07-12, scoped down honestly.** Split in two: (1) a dead-end
140
+ example-correctness sweep (`SKILL_AGENT_FAST_LOOP.md`'s "an offered example that itself fails"
141
+ rubric) found and fixed 3 genuinely broken examples across `ask.mjs`/`chat.mjs` (a `touches`-verb
142
+ hint that could never resolve for any input, a count hint that never parses, an unseeded-session
143
+ vocab-hint that lied). (2) surface-variety wiring landed 7 phrasing pools / 14 variants across 8
144
+ template sites (`src/answer-variants.mjs`, deterministic per-key hash selectionnever random),
145
+ scoped down from an original ~50-template/~100-variant target after inventory showed most
146
+ candidate templates either name a relation verb (off-limits never vary `imports`/`calls`/
147
+ `tests`/etc.) or are miss/rephrase-hint templates (handled by (1) instead, also off-limits).
148
+ Deliberately left `ask.mjs`'s two "X is defined in Y" `whereShape` sites unvaried:
149
+ `chatbench/graded-pool-max.jsonl` pins that exact substring as ground truth for 11 cases (2 in
150
+ the always-run promoted subset), and that pool is append-only per its own governing skill doc.
151
+ - **A fresh `CAPABILITIES_1.8.0.md` audit** — `CAPABILITIES_1.7.3.md` is pinned at commit `981c9b2`
152
+ and doesn't cover any of `PLAN_BREADTH_FIRST_NLU.md`'s six tracks; this doc's "Current capability
153
+ surface" above covers them narratively, but no full overlay audit has run since. Not done this
154
+ pass `BENCHMARK_CEFR_ENGLISH_1.8.0.md` alone was in scope.
155
+ - **`PLAN_ADVENTURE.md`** a text-adventure architectural stretch: an imperative command grammar,
156
+ mutable turn-by-turn world/player state as ordinary graph nodes (no special player-state store),
157
+ and an NPC turn scheduler. Design-only.
158
+ - **`PLAN_SYLLOGIST.md`**retraction-aware consistency checking under a hard budget and trust
159
+ tiers, the one open piece of the reasoning engine's research horizon. Design-only.
160
+ - **`archive/PLAN_CONVERSATION.md` Finding 4** an anaphoric "SUBJECT verb which N" inheritance
161
+ question misroutes into teach-a-fact; needs a discontiguous verb-frame parser, a POS-aware
162
+ mid-sentence interrogative detector, and a union-kind reverse-question fix. Large, three
163
+ sub-problems, not attempted in a single pass — a concrete first-increment sketch exists
164
+ (`HANDOVER.md`), not an undesignable question.
165
+ - **`PLAN_GUESS_NUMBER.md` / `PLAN_HANOI.md`** — closed-loop and open-loop planning domains for the
166
+ `findActionPath`/`findReachableSet` kernels, both already built and proven but not yet wired to
167
+ either domain. Design-only.
168
+ - **`PLAN_CODE.md`** small JS-function and HTML/CSS-fragment synthesis via a sandboxed headless
169
+ browser (Track 1, program synthesis, already shipped). Blocked on a sandbox dependency decision.
170
+ - **`PLAN_AGENTS.md`** the governing plan for tmct's broader multi-repo arc (marginalia, seonix,
171
+ a pluggable LLM rung for Claude Code/Bedrock/Copilot). Check its own sequencing table for current
172
+ phase status, not this file.
173
+ - **`archive/PLAN_VIZ.md`** archived; CLI-wiring and rendering (`tmct viz`, a recency-seeded,
174
+ hub-avoiding spiral walk with pseudo-3D depth rendering) shipped and are done. Three real items
175
+ remain, un-staffed: (1) the code-graph timestamp-provider architectural decision (provider-
176
+ populated vs. a new tmct-owned local-git mode); (2) the maintainer-side git-log-corpus generation
177
+ step, wiring seed-time `README.md` ingestion, and a new `Source` "seed" kind; (3) an eager
178
+ session/sessionless anchor individual with a `mode` field (deciding the two-Session-classes
179
+ question at the same time). See the archived doc's own "Next step" for the full detail.
180
+
181
+ ## Research horizon
182
+
183
+ *(2026-07-08 research pass a direction recorded so it isn't re-discovered from scratch, not a
184
+ committed build plan. Nothing below is scheduled.)*
185
+
186
+ **Before the horizon — known-how, no research risk**, just scheduling: `PLAN_CODE.md` Tracks 2-4
187
+ (mutation search/repair, JS/HTML/CSS synthesis — APR and CEGIS are established techniques);
188
+ RETE/incremental forward-chaining (`PLAN_SYLLOGIST.md` §2 — Forgy 1982, a citable algorithm not yet
189
+ ported); contingent/conformant planning under initial-state uncertainty (Bonet & Geffner 2000,
190
+ Hoffmann & Brafman 2006, Petrick & Bacchus 2002 all have working algorithms, none yet applied here).
191
+
192
+ **After the horizon genuinely unsolved in the field**, named as real research targets with
193
+ citations, not stop signs:
194
+ - **The frame problem / relevance realization** (open-world planning boundary). McCarthy & Hayes
195
+ 1969 named it; Jaeger, Riedl, Djedovic, Vervaeke & Walsh (2024) argue it may not be algorithmically
196
+ solvable in the general case. Speculative angle: bounded (N+1) goal recognition — recognize
197
+ declared goal 1..N, or reject to an explicit "escalate" class, via parse-shape membership.
198
+ - **Bounded, incremental, trust-tiered, retraction-safe justification tracking** `PLAN_SYLLOGIST.md`
199
+ §3. Doyle's JTMS (1979) and de Kleer's ATMS (1986) solve retraction; DRed/RDFox's Backward-Forward
200
+ solve incremental Datalog maintenance; nobody's published the combination with tmct's
201
+ multi-trust-tier, hard-budget requirement. Speculative angle: an ATMS-lite extension to
202
+ `syllogise.mjs`'s currently-flat provenance tag, sketched but unbuilt.
203
+ - **A shared ~2M-word cross-domain ontology** (general-English + technical/scientific/programming).
204
+ Merging collides senses of lexically-shared words (`class`, `cache`, `thread`, `field`, `state`)
205
+ across registers; knowledge-based WSD is real but weaker than supervised/neural WSD (Lesk 1986;
206
+ Raganato, Camacho-Collados & Navigli, EACL 2017). BabelNet proves cross-resource sense merging is
207
+ achievable at scale but solves the cross-*lingual*, not cross-*domain*, axis, and carries a
208
+ non-commercial licence. Speculative angle: mutual disambiguation from already-resolved neighbouring
209
+ terms in tmct's own closed graph (a bounded reading of Gale/Church/Yarowsky's "one sense per
210
+ discourse" regularity) not published anywhere found for this application. Fresh live instance
211
+ (2026-07-11): `"tail"` (Unix process vs. animal body part) collides under `normFactTerm`'s
212
+ cross-corpus flattening, `src/memory/core.mjs:1109-1134`.
213
+
214
+ **Tier-4: learn-on-miss acquisition** (a real planned capability, not just research). The strongest
215
+ miss signal tmct can emit: lexicon term recognized, query built cleanly, zero matches anywhere the
216
+ question was well-formed and the knowledge is simply absent. Web search on the resolved term → clean
217
+ the fetched text into the ACE-OWL controlled grammar store with source provenance → answer the
218
+ original question, citing what was just learned. Strictly opt-in, offline default inviolable.
219
+ Prerequisites: the provenance-trust policy must extend to `via:"learned:web"`, never silently
220
+ blending web-sourced facts with graph/operator facts.
221
+
222
+ ## Explicitly out of scope
223
+
224
+ - No AWS, no benchmark rig — a published npm library + CLI with a static GitLab Pages home page only.
225
+ - No auto-publish a version release is gated on a deliberate version-bump commit.
226
+ - No MCP server, no LLM in the product path — permanent, not "for now."
227
+
228
+ ## Design docs
229
+
230
+ Every substantial design lives in its own `PLAN_*.md` at the repo root (active) or `archive/`
231
+ (shipped and closed) this file points to them, it doesn't repeat their content. `SKILL_*.md` docs
232
+ specify the repeatable measurement/build cycles (benchmarks, capability audits, the fast-loop
233
+ trap-catching pattern). `HANDOVER.md` is the single current-open-items list.