@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.
- package/README.md +123 -14
- package/ROADMAP.md +233 -1392
- package/bin/tmct.mjs +479 -98
- package/corpus/README.md +3 -0
- package/corpus/generated/README.md +43 -0
- package/corpus/generated/ace-surface-variants.jsonl +17 -0
- package/corpus/generated/manifest.json +9 -0
- package/corpus/tier2/generate.mjs +14668 -0
- package/corpus/tier2/human-examples-large.jsonl +1928 -0
- package/corpus/tier2/human-examples-medium.jsonl +356 -0
- package/corpus/tier2/human-examples.jsonl +120 -0
- package/corpus/tier2/human-large.jsonl +12001 -0
- package/corpus/tier2/human-medium.jsonl +944 -0
- package/corpus/tier2/human.jsonl +664 -0
- package/corpus/tier2/manifest.json +42 -0
- package/package.json +14 -8
- package/src/answer-variants.json +47 -0
- package/src/answer-variants.mjs +67 -0
- package/src/ask-browser-entry.mjs +34 -0
- package/src/ask-browser.bundle.js +5095 -0
- package/src/ask-vocab.mjs +93 -8
- package/src/ask.mjs +451 -49
- package/src/chat.mjs +1273 -137
- package/src/cli-args.mjs +164 -0
- package/src/codegraph.mjs +170 -32
- package/src/extensions.mjs +100 -19
- package/src/grammar/ace.mjs +85 -3
- package/src/grammar/lexicon-core.json +9531 -63
- package/src/grammar/lexicon.mjs +58 -8
- package/src/graph-merge.mjs +114 -0
- package/src/index.mjs +14 -0
- package/src/init.mjs +40 -14
- package/src/interpret/normalize.mjs +75 -1
- package/src/interpret/strategies/grammar.mjs +10 -0
- package/src/interpret/strategies/keywords.mjs +20 -0
- package/src/interpret/strategies/noise-strip.mjs +73 -4
- package/src/memory/core.mjs +466 -8
- package/src/router/goal-reasoner.mjs +41 -7
- package/src/router/guardrail.mjs +37 -7
- package/src/router/resolver.mjs +50 -4
- package/src/sessions.mjs +5 -1
- package/src/source.mjs +54 -1
- package/src/syllogise.mjs +398 -27
- package/src/toml-config.mjs +13 -4
- 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.
|
|
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:
|
|
83
|
-
"init:
|
|
84
|
-
"init:
|
|
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
|
+
};
|