@polycode-projects/the-mechanical-code-talker 1.5.5 → 1.8.4

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 (45) 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 +1273 -137
  24. package/src/cli-args.mjs +164 -0
  25. package/src/codegraph.mjs +170 -32
  26. package/src/extensions.mjs +100 -19
  27. package/src/grammar/ace.mjs +85 -3
  28. package/src/grammar/lexicon-core.json +9531 -63
  29. package/src/grammar/lexicon.mjs +58 -8
  30. package/src/graph-merge.mjs +114 -0
  31. package/src/index.mjs +14 -0
  32. package/src/init.mjs +40 -14
  33. package/src/interpret/normalize.mjs +75 -1
  34. package/src/interpret/strategies/grammar.mjs +10 -0
  35. package/src/interpret/strategies/keywords.mjs +20 -0
  36. package/src/interpret/strategies/noise-strip.mjs +73 -4
  37. package/src/memory/core.mjs +466 -8
  38. package/src/router/goal-reasoner.mjs +41 -7
  39. package/src/router/guardrail.mjs +37 -7
  40. package/src/router/resolver.mjs +50 -4
  41. package/src/sessions.mjs +5 -1
  42. package/src/source.mjs +54 -1
  43. package/src/syllogise.mjs +398 -27
  44. package/src/toml-config.mjs +13 -4
  45. package/src/viz.mjs +541 -0
@@ -57,6 +57,48 @@
57
57
  "bytes": 5826,
58
58
  "sha256": "01284f1350fa2ca9653b1c5f52a39fdcb657727c65e77693eae954cb95a14a2e",
59
59
  "license": "MPL-2.0"
60
+ },
61
+ {
62
+ "id": "human",
63
+ "kind": "domain",
64
+ "description": "The default human-world persona (PLAN_SEED.md): everyday people, places, objects, nature, time/events, body/food and mind vocabulary, hand-curated from Open English WordNet (CC-BY-4.0) and bridged to Schema.org's (Apache-2.0) top-level classes — replaces the code-domain SEON+ConceptNet default.",
65
+ "source": {
66
+ "kind": "curated",
67
+ "tool": "corpus/tier2/generate.mjs"
68
+ },
69
+ "file": "human.jsonl",
70
+ "facts": 664,
71
+ "bytes": 81430,
72
+ "sha256": "040e6d1f6761a29a080f7825ff8aae60caf879125c1f7a1480340ef04129bcd5",
73
+ "license": "MPL-2.0"
74
+ },
75
+ {
76
+ "id": "human-medium",
77
+ "kind": "domain",
78
+ "description": "The Medium tier of the default human-world persona (PLAN_SEED.md): incremental facts beyond Small only — activated alongside \"human\" via --persona-size medium, never active by default.",
79
+ "source": {
80
+ "kind": "curated",
81
+ "tool": "corpus/tier2/generate.mjs"
82
+ },
83
+ "file": "human-medium.jsonl",
84
+ "facts": 944,
85
+ "bytes": 110796,
86
+ "sha256": "63270a928f4d304489bd552c1e50704ff2d6f17841cf11a87a292418eaa572c0",
87
+ "license": "MPL-2.0"
88
+ },
89
+ {
90
+ "id": "human-large",
91
+ "kind": "domain",
92
+ "description": "The Large tier of the default human-world persona (PLAN_SEED.md): incremental facts beyond Medium only — activated alongside \"human\" via --persona-size large, never active by default.",
93
+ "source": {
94
+ "kind": "curated",
95
+ "tool": "corpus/tier2/generate.mjs"
96
+ },
97
+ "file": "human-large.jsonl",
98
+ "facts": 12001,
99
+ "bytes": 1464850,
100
+ "sha256": "754d9d4c046f92994a5f5fa0abde27af65a47ec546b3051bf972bfa76b642917",
101
+ "license": "MPL-2.0"
60
102
  }
61
103
  ]
62
104
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polycode-projects/the-mechanical-code-talker",
3
- "version": "1.5.5",
3
+ "version": "1.8.4",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "The Mechanical Code Talker (tmct) — a tolerant, offline, $0 chat surface that guides you toward precision queries about a software repository. ELIZA/PARRY-style but domain-obsessed with code. No model calls; no codebase index of its own.",
@@ -53,7 +53,12 @@
53
53
  "./graph-service": "./src/providers/graph-service.mjs",
54
54
  "./providers/fixture": "./src/providers/fixture.mjs",
55
55
  "./providers/bootstrap": "./src/providers/bootstrap.mjs",
56
- "./conformance": "./src/conformance.mjs"
56
+ "./conformance": "./src/conformance.mjs",
57
+ "./init": "./src/init.mjs",
58
+ "./extensions": "./src/extensions.mjs",
59
+ "./toml-config": "./src/toml-config.mjs",
60
+ "./generateCompletion": "./src/completions/complete.mjs",
61
+ "./createCompletionsGraphAdapter": "./src/completions/graph-adapter.mjs"
57
62
  },
58
63
  "files": [
59
64
  "bin/",
@@ -79,13 +84,12 @@
79
84
  "chat": "node bin/tmct.mjs",
80
85
  "chat:repo": "node bin/tmct.mjs chat --repo",
81
86
  "init": "node bin/tmct.mjs init",
82
- "init:persona:code": "node bin/tmct.mjs init --with-persona code",
83
- "init:corpus:general": "node bin/tmct.mjs init --corpus general",
84
- "init:corpus:aws": "node bin/tmct.mjs init --corpus aws",
85
- "init:corpus:python": "node bin/tmct.mjs init --corpus python",
86
- "init:corpus:java": "node bin/tmct.mjs init --corpus java",
87
+ "init:persona:human": "node bin/tmct.mjs init --with-persona human",
88
+ "init:persona:empty": "node bin/tmct.mjs init --with-persona empty",
89
+ "init:large": "node bin/tmct.mjs init && node bin/tmct.mjs import --corpus seon && node bin/tmct.mjs import --corpus conceptnet && node bin/tmct.mjs import --corpus aws && node bin/tmct.mjs import --corpus python && node bin/tmct.mjs import --corpus java",
87
90
  "memory": "node bin/tmct.mjs memory",
88
91
  "syllogise": "node bin/tmct.mjs syllogise",
92
+ "viz": "node bin/tmct.mjs viz",
89
93
  "example:mini": "node bin/tmct.mjs chat --repo examples/mini-webapp --ephemeral",
90
94
  "example:polyglot": "node bin/tmct.mjs chat --repo examples/polyglot --ephemeral",
91
95
  "chatbench:run": "node chatbench/run.mjs",
@@ -95,9 +99,11 @@
95
99
  "infbench": "node infbench/generate-cases.mjs && node infbench/run.mjs",
96
100
  "audit": "npm audit --audit-level=high",
97
101
  "audit:fix": "npm audit fix",
98
- "demo:build": "node scripts/build-demo-site.mjs"
102
+ "demo:build": "node scripts/build-demo-site.mjs",
103
+ "build:ask-bundle": "node scripts/build-ask-bundle.mjs"
99
104
  },
100
105
  "devDependencies": {
106
+ "esbuild": "^0.28.1",
101
107
  "ink-testing-library": "^4.0.0"
102
108
  }
103
109
  }
@@ -0,0 +1,47 @@
1
+ {
2
+ "version": 1,
3
+ "curation": "Hand-curated. scripts/generate-answer-variants.mjs cross-checked each pool against real Open English WordNet synsets (scripts/lib/wordnet-synonyms.mjs) where a sense fit; most of these are domain-specific code-graph connector phrases WordNet's own sense-1 convention resolves to the wrong sense for -- e.g. 'locate' -> 'turn up', 'record' -> 'enter, put down', 'module' -> 'mental faculty' -- so every entry below was accepted or rejected by hand against the exact rendered sentence it replaces, never auto-accepted from a raw synset match. See src/answer-variants.mjs for how these are selected at render time.",
4
+ "pools": {
5
+ "defined-in": {
6
+ "base": "defined in",
7
+ "variants": ["located in", "found in"],
8
+ "usedBy": [
9
+ "ask.mjs renderComposite exists-hit (\"Yes - X is a Y, defined in Z.\")",
10
+ "ask.mjs metaFallbackEntityAnswer (\"X is a Y in this codebase, defined in Z ...\")"
11
+ ],
12
+ "deliberatelyNotUsedBy": [
13
+ "ask.mjs renderCore whereShape (\"X is defined in Y at line(s) Z\" / \"X is defined in Y (no line span...)\") -- chatbench/graded-pool-max.jsonl pins this exact substring as ground truth for 11 'where is X defined' cases (2 in the always-run promoted subset), and that pool is append-only/never-edited-mid-arc per SKILL_BENCHMARK_CEFR_ENGLISH.md."
14
+ ]
15
+ },
16
+ "is-dated": {
17
+ "base": "is dated",
18
+ "variants": ["was made on", "was recorded on"],
19
+ "usedBy": ["ask.mjs renderCore whenShape, the exact-subject hit (\"commit X is dated Y.\")"]
20
+ },
21
+ "full-breakdown": {
22
+ "base": "for the full breakdown",
23
+ "variants": ["for the full details", "for more detail"],
24
+ "usedBy": ["chat.mjs moduleOverviewText's /describe pointer"]
25
+ },
26
+ "ask-about-lead": {
27
+ "base": "Ask about",
28
+ "variants": ["Try asking about", "You can ask about"],
29
+ "usedBy": ["chat.mjs orientationText's capability sentence"]
30
+ },
31
+ "facts-across": {
32
+ "base": "across",
33
+ "variants": ["spanning", "over"],
34
+ "usedBy": ["chat.mjs memorySummary (\"I remember N facts across M relation types.\")"]
35
+ },
36
+ "full-picture": {
37
+ "base": "the full picture",
38
+ "variants": ["the whole picture", "the complete picture"],
39
+ "usedBy": ["chat.mjs whatElseAnswer's exhausted-facts pointer"]
40
+ },
41
+ "beyond-that-lead": {
42
+ "base": "Beyond that,",
43
+ "variants": ["Also,", "In addition,"],
44
+ "usedBy": ["chat.mjs whatElseAnswer's follow-on fact listing"]
45
+ }
46
+ }
47
+ }
@@ -0,0 +1,67 @@
1
+ // answer-variants.mjs — deterministic, committed answer-phrasing variety
2
+ // ("wiring the generated corpus into the live answer path", ROADMAP.md's
3
+ // What's next item / archive/PLAN_TEMPLATE_COVERAGE.md's stated follow-on).
4
+ //
5
+ // A SMALL, curated, committed table (answer-variants.json) of safe cosmetic/
6
+ // locational/connector-word rephrasings for a deliberately narrow set of
7
+ // answer templates in ask.mjs/chat.mjs -- never a relation verb (imports/
8
+ // calls/tests/inherits/touches), never an entity id/label/path, never a miss/
9
+ // rephrase-hint template. Each pool was hand-reviewed for meaning-safety in
10
+ // its SPECIFIC rendered sentence (see answer-variants.json's own "curation"
11
+ // field) -- WordNet was consulted but its sense-1 lookups mostly resolved to
12
+ // the wrong sense for this domain-specific connector vocabulary, so nothing
13
+ // here was auto-accepted from a raw synset match.
14
+ //
15
+ // Selection is a pure hash, never Math.random/Date.now: the SAME (poolId, key)
16
+ // always picks the SAME form, so the same query against the same entity
17
+ // renders byte-identical text every time (pinnable in tests), while different
18
+ // entities/answers spread across the pool's forms. This is the ONE place that
19
+ // hash-and-pick logic lives -- every call site below imports pickPhrase
20
+ // rather than re-deriving its own index arithmetic.
21
+ //
22
+ // Lazy + failure-tolerant load (chat.mjs's own "a turn never crashes" ethos,
23
+ // see chatTemplates()): a missing/corrupt data file, or `node:fs` simply
24
+ // being unavailable, degrades to always returning `base` -- never a throw.
25
+ // That second case is load-bearing, not theoretical: ask.mjs is bundled
26
+ // whole into the browser "Ask the graph" panel (scripts/build-ask-bundle.mjs
27
+ // stubs node:fs's readFileSync as a function that THROWS when called, so the
28
+ // browser bundle still boots; this module's readFileSync call only ever
29
+ // happens lazily inside pickPhrase, wrapped in try/catch, exactly so that
30
+ // throw is caught here and never reaches the caller.
31
+
32
+ import { readFileSync } from "node:fs";
33
+ import { fileURLToPath } from "node:url";
34
+ import { dirname, join } from "node:path";
35
+ import { createHash } from "node:crypto";
36
+
37
+ const DATA_FILE = join(dirname(fileURLToPath(import.meta.url)), "answer-variants.json");
38
+
39
+ let dataCache; // undefined = not yet attempted; null = load failed/unavailable
40
+ function loadData() {
41
+ if (dataCache !== undefined) return dataCache;
42
+ try {
43
+ dataCache = JSON.parse(readFileSync(DATA_FILE, "utf8"));
44
+ } catch {
45
+ dataCache = null;
46
+ }
47
+ return dataCache;
48
+ }
49
+
50
+ /** Deterministically choose `base` or one of `poolId`'s committed variants,
51
+ * keyed on `key` -- pass something stable that identifies THIS specific
52
+ * answer (an entity's own `id` for entity-anchored templates; any other
53
+ * stable string, e.g. a graph-summary key, for templates with no single
54
+ * entity). Same (poolId, key) always returns the same string; an unknown
55
+ * pool, a missing/unreadable data file, or a falsy `key` all fall back to
56
+ * `base` unconditionally -- variety is strictly additive, never a way to
57
+ * lose the original wording. */
58
+ export function pickPhrase(poolId, key, base) {
59
+ if (!key) return base;
60
+ const data = loadData();
61
+ const variants = data?.pools?.[poolId]?.variants;
62
+ if (!Array.isArray(variants) || !variants.length) return base;
63
+ const forms = [base, ...variants];
64
+ const digest = createHash("sha256").update(`${poolId}:${String(key)}`).digest();
65
+ const idx = digest[0] % forms.length;
66
+ return forms[idx];
67
+ }
@@ -0,0 +1,34 @@
1
+ // ask-browser-entry.mjs — the esbuild entry for `tmct viz`'s embedded "Ask the
2
+ // graph" chat panel (PLAN_BREADTH_FIRST_NLU.md §5 follow-on, operator directive
3
+ // 2026-07-11: a real NL chat running client-side against the embedded graph,
4
+ // via tmct's OWN JS engine — not reimplemented, not a stub).
5
+ //
6
+ // Precedent: seonix's own `src/ask-browser-entry.mjs` (PLAN_CHAT_EXTRACTION.md
7
+ // Stage 5) proved this exact approach in production — esbuild + a Node-builtin
8
+ // stub plugin bundles tmct's real ask() into a single browser IIFE. This entry
9
+ // mirrors that pattern, adapted for tmct bundling its OWN ask.mjs directly
10
+ // (no external package import needed — we're already inside the source tree)
11
+ // and extended with the graph-traversal exports `tmct viz`'s own client-side
12
+ // re-focus/re-walk needs (spiralExpand etc. — seonix's code-graph viewer
13
+ // recomputes depth with its own hand-rolled client-side BFS; tmct's viewer
14
+ // reuses the real spiralExpand instead, so the browser walk is byte-identical
15
+ // to the CLI's).
16
+ //
17
+ // Bundled by scripts/build-ask-bundle.mjs into src/ask-browser.bundle.js (an
18
+ // IIFE), which viz.mjs inlines verbatim into the viewer page's own <script>.
19
+ // Runs adapter-less (no wink model in the browser — ask()'s lemma/POS tier
20
+ // degrades to its curated + fuzzy tiers, exactly the boundary
21
+ // test/ask-nlp.test.mjs's own "viewer bundle without wink" test proves stays
22
+ // answerable) and grammar-lite (no ACE/construction-grammar strategies, both
23
+ // fs-dependent — the plain grammar/keyword-spot/noise-strip strategies still
24
+ // answer every shape tmct viz's own memory-graph queries need).
25
+ import { ask, parseQuery } from "./ask.mjs";
26
+ import {
27
+ parseEntities, spiralExpand, mostRecentIndividual, derivedUpdatedAt, MEMORY_SPIRAL_EXPAND_KINDS,
28
+ buildVizNodesAndEdges,
29
+ } from "./codegraph.mjs";
30
+
31
+ globalThis.tmctViz = {
32
+ ask, parseQuery, parseEntities, spiralExpand, mostRecentIndividual, derivedUpdatedAt,
33
+ MEMORY_SPIRAL_EXPAND_KINDS, buildVizNodesAndEdges,
34
+ };