@polycode-projects/the-mechanical-code-talker 0.5.0 → 0.7.0
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 +91 -27
- package/ROADMAP.md +45 -0
- package/bin/tmct.mjs +64 -2
- package/corpus/README.md +77 -5
- package/corpus/conceptnet/README.md +92 -33
- package/corpus/conceptnet/filter-dump.mjs +59 -2
- package/corpus/conceptnet/quality-filter.mjs +95 -0
- package/corpus/conceptnet/slice.jsonl +31067 -378
- package/corpus/seon/LICENSE-NOTICE +37 -0
- package/corpus/seon/README.md +121 -0
- package/corpus/seon/concepts.jsonl +238 -0
- package/corpus/seon/definitions.jsonl +288 -0
- package/corpus/seon/relations.jsonl +8 -0
- package/corpus/tier2/aws.jsonl +39 -0
- package/corpus/tier2/generate.mjs +253 -0
- package/corpus/tier2/java.jsonl +31 -0
- package/corpus/tier2/manifest.json +48 -0
- package/corpus/tier2/python.jsonl +30 -0
- package/data/templates/responses.jsonl +3 -0
- package/package.json +13 -2
- package/src/ask-vocab.mjs +19 -1
- package/src/ask.mjs +13 -13
- package/src/chat.mjs +759 -66
- package/src/codegraph.mjs +28 -5
- package/src/concept.mjs +393 -0
- package/src/conformance.mjs +166 -0
- package/src/corpus/conceptnet.mjs +42 -19
- package/src/init.mjs +12 -9
- package/src/interpret/normalize.mjs +42 -0
- package/src/interpret/pipeline.mjs +2 -2
- package/src/memory/core.mjs +84 -0
- package/src/memory/inspect.mjs +25 -0
- package/src/server.mjs +88 -7
- package/src/tui/app.mjs +26 -2
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// corpus/tier2/generate.mjs — the TIER-2 specialised-corpus generator + manifest
|
|
3
|
+
// writer. NOT part of the product path — a maintainer tool. Offline, $0.
|
|
4
|
+
//
|
|
5
|
+
// Tier-2 corpuses are LANGUAGE- or DOMAIN-specific fact sets (aws, python,
|
|
6
|
+
// java, …) that tmct fetches/generates into `.tmct/` at init time so it can
|
|
7
|
+
// "expand into a concept for an applicable codebase". They are NOT shipped in
|
|
8
|
+
// the npm package the way the tier-1 ConceptNet slice is — they are opt-in,
|
|
9
|
+
// selected per repo. See ../README.md for the full tier-1/2/3 policy.
|
|
10
|
+
//
|
|
11
|
+
// Every tier-2 corpus is written in the EXACT tier-1 fact shape
|
|
12
|
+
// (corpus/conceptnet/slice.jsonl): one JSON object per line,
|
|
13
|
+
// {"start":"/c/en/<term>","rel":"/r/<Rel>","end":"/c/en/<concept>","weight":N,"surfaceText":"…"}
|
|
14
|
+
// with `rel` drawn ONLY from the mapped relations in
|
|
15
|
+
// src/corpus/conceptnet-map.toml, so a tier-2 file loads through the very same
|
|
16
|
+
// loadSlice()/toFacts() path as the tier-1 slice (this file's --verify proves
|
|
17
|
+
// it). The Wave-2 tier-2 SEEDER (see ../README.md) is what stamps the right
|
|
18
|
+
// provenance (`corpus:tier2:<id> /r/…`) instead of the conceptnet default.
|
|
19
|
+
//
|
|
20
|
+
// node corpus/tier2/generate.mjs # (re)write every <id>.jsonl + manifest.json
|
|
21
|
+
// node corpus/tier2/generate.mjs --verify # generate + assert each file loads & seeds cleanly
|
|
22
|
+
//
|
|
23
|
+
// To ADD a specialised corpus: add an entry to CORPUSES below (a list of
|
|
24
|
+
// [subject, relation, concept] triples, optionally [.., surfaceText]) and
|
|
25
|
+
// re-run. Curated sets are authored here so they stay reviewable and diffable;
|
|
26
|
+
// a corpus too large to curate by hand is a `fetch` manifest entry instead
|
|
27
|
+
// (network, opt-in — see fetchCorpus() and ../README.md).
|
|
28
|
+
|
|
29
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
30
|
+
import { createHash } from "node:crypto";
|
|
31
|
+
import { fileURLToPath } from "node:url";
|
|
32
|
+
import { dirname, join } from "node:path";
|
|
33
|
+
|
|
34
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
35
|
+
|
|
36
|
+
// A curated triple is [subject, rel, concept] or [subject, rel, concept, weight].
|
|
37
|
+
// `rel` MUST be a mapped (ace != "none") relation in conceptnet-map.toml so the
|
|
38
|
+
// fact actually seeds. Terms are lowercase snake_case; the loader's termText()
|
|
39
|
+
// turns "/c/en/hash_table" into "hash table". Keep terms <= 3 words (the tier-1
|
|
40
|
+
// quality-filter rule) — curated data is clean by construction.
|
|
41
|
+
export const CORPUSES = {
|
|
42
|
+
aws: {
|
|
43
|
+
kind: "domain",
|
|
44
|
+
description: "Amazon Web Services core services and primitives (S3, Lambda, DynamoDB, EC2, IAM, SQS) mapped to general cloud/CS concepts.",
|
|
45
|
+
facts: [
|
|
46
|
+
["aws", "/r/IsA", "cloud_platform"],
|
|
47
|
+
["aws", "/r/IsA", "cloud"],
|
|
48
|
+
["aws", "/r/CapableOf", "host_applications"],
|
|
49
|
+
// S3
|
|
50
|
+
["s3", "/r/IsA", "object_storage"],
|
|
51
|
+
["s3", "/r/IsA", "storage_service"],
|
|
52
|
+
["s3", "/r/PartOf", "aws"],
|
|
53
|
+
["s3", "/r/HasA", "bucket"],
|
|
54
|
+
["s3", "/r/UsedFor", "storing_files"],
|
|
55
|
+
["s3", "/r/CapableOf", "store_objects"],
|
|
56
|
+
["bucket", "/r/IsA", "container"],
|
|
57
|
+
["bucket", "/r/PartOf", "s3"],
|
|
58
|
+
["bucket", "/r/UsedFor", "storing_objects"],
|
|
59
|
+
// Lambda
|
|
60
|
+
["lambda", "/r/IsA", "compute_service"],
|
|
61
|
+
["lambda", "/r/IsA", "function"],
|
|
62
|
+
["lambda", "/r/PartOf", "aws"],
|
|
63
|
+
["lambda", "/r/UsedFor", "running_code"],
|
|
64
|
+
["lambda", "/r/CapableOf", "run_code"],
|
|
65
|
+
["lambda", "/r/HasProperty", "serverless"],
|
|
66
|
+
// DynamoDB
|
|
67
|
+
["dynamodb", "/r/IsA", "database"],
|
|
68
|
+
["dynamodb", "/r/IsA", "nosql_database"],
|
|
69
|
+
["dynamodb", "/r/PartOf", "aws"],
|
|
70
|
+
["dynamodb", "/r/HasA", "table"],
|
|
71
|
+
["dynamodb", "/r/UsedFor", "storing_data"],
|
|
72
|
+
["dynamodb", "/r/HasProperty", "managed"],
|
|
73
|
+
// EC2
|
|
74
|
+
["ec2", "/r/IsA", "compute_service"],
|
|
75
|
+
["ec2", "/r/IsA", "virtual_machine"],
|
|
76
|
+
["ec2", "/r/PartOf", "aws"],
|
|
77
|
+
["ec2", "/r/HasA", "instance"],
|
|
78
|
+
["ec2", "/r/UsedFor", "running_servers"],
|
|
79
|
+
// IAM
|
|
80
|
+
["iam", "/r/IsA", "access_control"],
|
|
81
|
+
["iam", "/r/PartOf", "aws"],
|
|
82
|
+
["iam", "/r/UsedFor", "managing_permissions"],
|
|
83
|
+
["iam", "/r/HasA", "role"],
|
|
84
|
+
["iam", "/r/HasA", "policy"],
|
|
85
|
+
// SQS + queue
|
|
86
|
+
["sqs", "/r/IsA", "message_queue"],
|
|
87
|
+
["sqs", "/r/IsA", "queue"],
|
|
88
|
+
["sqs", "/r/PartOf", "aws"],
|
|
89
|
+
["sqs", "/r/UsedFor", "decoupling_services"],
|
|
90
|
+
["queue", "/r/IsA", "data_structure"],
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
python: {
|
|
95
|
+
kind: "language",
|
|
96
|
+
description: "Python language constructs and stdlib types mapped to the shared CS concept vocabulary (list->array, dict->hash table, …).",
|
|
97
|
+
facts: [
|
|
98
|
+
["python", "/r/IsA", "programming_language"],
|
|
99
|
+
["python", "/r/HasProperty", "interpreted"],
|
|
100
|
+
["python", "/r/HasProperty", "dynamically_typed"],
|
|
101
|
+
["python", "/r/UsedFor", "scripting"],
|
|
102
|
+
// built-in types → shared concepts
|
|
103
|
+
["list", "/r/IsA", "array"],
|
|
104
|
+
["list", "/r/IsA", "sequence"],
|
|
105
|
+
["list", "/r/IsA", "data_structure"],
|
|
106
|
+
["dict", "/r/IsA", "hash_table"],
|
|
107
|
+
["dict", "/r/IsA", "dictionary"],
|
|
108
|
+
["dict", "/r/IsA", "mapping"],
|
|
109
|
+
["tuple", "/r/IsA", "sequence"],
|
|
110
|
+
["tuple", "/r/HasProperty", "immutable"],
|
|
111
|
+
["set", "/r/IsA", "collection"],
|
|
112
|
+
["set", "/r/HasProperty", "unordered"],
|
|
113
|
+
["str", "/r/IsA", "string"],
|
|
114
|
+
// language constructs
|
|
115
|
+
["decorator", "/r/IsA", "function"],
|
|
116
|
+
["decorator", "/r/UsedFor", "modifying_functions"],
|
|
117
|
+
["generator", "/r/IsA", "iterator"],
|
|
118
|
+
["generator", "/r/UsedFor", "lazy_evaluation"],
|
|
119
|
+
["comprehension", "/r/IsA", "expression"],
|
|
120
|
+
["comprehension", "/r/UsedFor", "building_collections"],
|
|
121
|
+
["exception", "/r/IsA", "error"],
|
|
122
|
+
["module", "/r/IsA", "file"],
|
|
123
|
+
["package", "/r/IsA", "module"],
|
|
124
|
+
["method", "/r/IsA", "function"],
|
|
125
|
+
// tooling / runtime
|
|
126
|
+
["pip", "/r/IsA", "package_manager"],
|
|
127
|
+
["pip", "/r/UsedFor", "installing_packages"],
|
|
128
|
+
["gil", "/r/IsA", "lock"],
|
|
129
|
+
["gil", "/r/PartOf", "interpreter"],
|
|
130
|
+
["cpython", "/r/IsA", "interpreter"],
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
java: {
|
|
135
|
+
kind: "language",
|
|
136
|
+
description: "Java language and JVM constructs mapped to the shared CS concept vocabulary (ArrayList->list, HashMap->hash table, …).",
|
|
137
|
+
facts: [
|
|
138
|
+
["java", "/r/IsA", "programming_language"],
|
|
139
|
+
["java", "/r/HasProperty", "compiled"],
|
|
140
|
+
["java", "/r/HasProperty", "statically_typed"],
|
|
141
|
+
["java", "/r/UsedFor", "building_applications"],
|
|
142
|
+
// types → shared concepts
|
|
143
|
+
["arraylist", "/r/IsA", "list"],
|
|
144
|
+
["arraylist", "/r/IsA", "data_structure"],
|
|
145
|
+
["hashmap", "/r/IsA", "hash_table"],
|
|
146
|
+
["hashmap", "/r/IsA", "dictionary"],
|
|
147
|
+
["hashmap", "/r/IsA", "map"],
|
|
148
|
+
["interface", "/r/IsA", "type"],
|
|
149
|
+
["interface", "/r/IsA", "contract"],
|
|
150
|
+
["class", "/r/IsA", "type"],
|
|
151
|
+
["object", "/r/IsA", "instance"],
|
|
152
|
+
// JVM / runtime
|
|
153
|
+
["jvm", "/r/IsA", "virtual_machine"],
|
|
154
|
+
["jvm", "/r/UsedFor", "running_bytecode"],
|
|
155
|
+
["jvm", "/r/CapableOf", "execute_bytecode"],
|
|
156
|
+
["bytecode", "/r/IsA", "code"],
|
|
157
|
+
["garbage_collector", "/r/PartOf", "jvm"],
|
|
158
|
+
["garbage_collector", "/r/UsedFor", "freeing_memory"],
|
|
159
|
+
// packaging / tooling
|
|
160
|
+
["jar", "/r/IsA", "archive"],
|
|
161
|
+
["jar", "/r/IsA", "file"],
|
|
162
|
+
["jar", "/r/UsedFor", "packaging_classes"],
|
|
163
|
+
["maven", "/r/IsA", "build_tool"],
|
|
164
|
+
["maven", "/r/IsA", "package_manager"],
|
|
165
|
+
["gradle", "/r/IsA", "build_tool"],
|
|
166
|
+
// language features
|
|
167
|
+
["thread", "/r/IsA", "process"],
|
|
168
|
+
["thread", "/r/UsedFor", "concurrency"],
|
|
169
|
+
["generics", "/r/UsedFor", "type_safety"],
|
|
170
|
+
["annotation", "/r/IsA", "metadata"],
|
|
171
|
+
["exception", "/r/IsA", "error"],
|
|
172
|
+
["method", "/r/IsA", "function"],
|
|
173
|
+
],
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const conceptUri = (term) => `/c/en/${term}`;
|
|
178
|
+
const humanize = (term) => term.replace(/_/g, " ");
|
|
179
|
+
|
|
180
|
+
/** One curated triple → a tier-1-shaped slice row. */
|
|
181
|
+
export function toRow([subject, rel, concept, weight = 1]) {
|
|
182
|
+
return {
|
|
183
|
+
start: conceptUri(subject),
|
|
184
|
+
rel,
|
|
185
|
+
end: conceptUri(concept),
|
|
186
|
+
weight,
|
|
187
|
+
surfaceText: `[[${humanize(subject)}]] ${rel.replace("/r/", "")} [[${humanize(concept)}]]`,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** Curated corpus id → its JSONL text (deterministic order = authored order). */
|
|
192
|
+
export function corpusJsonl(id) {
|
|
193
|
+
return CORPUSES[id].facts.map((f) => JSON.stringify(toRow(f))).join("\n") + "\n";
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const sha256 = (text) => createHash("sha256").update(text).digest("hex");
|
|
197
|
+
|
|
198
|
+
// ---- network-fetch path (opt-in, offline-by-default) -----------------------
|
|
199
|
+
// A tier-2 corpus too large to curate by hand is declared in the manifest with
|
|
200
|
+
// { "source": { "kind": "fetch", "url": "...", "sha256": "..." } } and pulled by
|
|
201
|
+
// a Wave-2 fetch step. This helper is the reference implementation — it is NEVER
|
|
202
|
+
// called without an explicit --allow-network flag (the product default is $0,
|
|
203
|
+
// offline). No sample corpus uses it; the three samples are all `curated`.
|
|
204
|
+
export async function fetchCorpus(url, expectedSha) {
|
|
205
|
+
const res = await fetch(url, { headers: { accept: "application/x-ndjson,application/jsonl" } });
|
|
206
|
+
if (!res.ok) throw new Error(`fetch ${url}: HTTP ${res.status}`);
|
|
207
|
+
const text = await res.text();
|
|
208
|
+
const got = sha256(text);
|
|
209
|
+
if (expectedSha && got !== expectedSha) throw new Error(`checksum mismatch for ${url}: ${got} != ${expectedSha}`);
|
|
210
|
+
return text;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async function main() {
|
|
214
|
+
const verify = process.argv.includes("--verify");
|
|
215
|
+
const manifest = { version: 1, generated: "by corpus/tier2/generate.mjs", corpuses: [] };
|
|
216
|
+
|
|
217
|
+
for (const [id, spec] of Object.entries(CORPUSES)) {
|
|
218
|
+
const text = corpusJsonl(id);
|
|
219
|
+
await writeFile(join(HERE, `${id}.jsonl`), text);
|
|
220
|
+
manifest.corpuses.push({
|
|
221
|
+
id,
|
|
222
|
+
kind: spec.kind,
|
|
223
|
+
description: spec.description,
|
|
224
|
+
source: { kind: "curated", tool: "corpus/tier2/generate.mjs" },
|
|
225
|
+
file: `${id}.jsonl`,
|
|
226
|
+
facts: spec.facts.length,
|
|
227
|
+
bytes: Buffer.byteLength(text),
|
|
228
|
+
sha256: sha256(text),
|
|
229
|
+
license: "MPL-2.0",
|
|
230
|
+
});
|
|
231
|
+
console.error(` ${id}: ${spec.facts.length} facts, ${Buffer.byteLength(text)} bytes`);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const manifestText = JSON.stringify(manifest, null, 2) + "\n";
|
|
235
|
+
await writeFile(join(HERE, "manifest.json"), manifestText);
|
|
236
|
+
console.error(`wrote manifest.json (${manifest.corpuses.length} corpuses)`);
|
|
237
|
+
|
|
238
|
+
if (verify) {
|
|
239
|
+
const { loadSlice, loadMap, toFacts } = await import("../../src/corpus/conceptnet.mjs");
|
|
240
|
+
const map = await loadMap();
|
|
241
|
+
for (const c of manifest.corpuses) {
|
|
242
|
+
const assertions = await loadSlice(join(HERE, c.file));
|
|
243
|
+
const facts = toFacts(assertions, map); // throws on any unmapped rel
|
|
244
|
+
if (assertions.length !== c.facts) throw new Error(`${c.id}: loadSlice count ${assertions.length} != ${c.facts}`);
|
|
245
|
+
if (facts.length !== c.facts) throw new Error(`${c.id}: ${c.facts - facts.length} fact(s) did not seed (ace=none rel?)`);
|
|
246
|
+
console.error(` verify ${c.id}: ${assertions.length} assertions load, all ${facts.length} seed cleanly`);
|
|
247
|
+
}
|
|
248
|
+
console.error("verify: OK — every tier-2 corpus loads and seeds through the tier-1 path");
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const isMain = process.argv[1] && import.meta.url === new URL(`file://${process.argv[1]}`).href;
|
|
253
|
+
if (isMain) await main();
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{"start":"/c/en/java","rel":"/r/IsA","end":"/c/en/programming_language","weight":1,"surfaceText":"[[java]] IsA [[programming language]]"}
|
|
2
|
+
{"start":"/c/en/java","rel":"/r/HasProperty","end":"/c/en/compiled","weight":1,"surfaceText":"[[java]] HasProperty [[compiled]]"}
|
|
3
|
+
{"start":"/c/en/java","rel":"/r/HasProperty","end":"/c/en/statically_typed","weight":1,"surfaceText":"[[java]] HasProperty [[statically typed]]"}
|
|
4
|
+
{"start":"/c/en/java","rel":"/r/UsedFor","end":"/c/en/building_applications","weight":1,"surfaceText":"[[java]] UsedFor [[building applications]]"}
|
|
5
|
+
{"start":"/c/en/arraylist","rel":"/r/IsA","end":"/c/en/list","weight":1,"surfaceText":"[[arraylist]] IsA [[list]]"}
|
|
6
|
+
{"start":"/c/en/arraylist","rel":"/r/IsA","end":"/c/en/data_structure","weight":1,"surfaceText":"[[arraylist]] IsA [[data structure]]"}
|
|
7
|
+
{"start":"/c/en/hashmap","rel":"/r/IsA","end":"/c/en/hash_table","weight":1,"surfaceText":"[[hashmap]] IsA [[hash table]]"}
|
|
8
|
+
{"start":"/c/en/hashmap","rel":"/r/IsA","end":"/c/en/dictionary","weight":1,"surfaceText":"[[hashmap]] IsA [[dictionary]]"}
|
|
9
|
+
{"start":"/c/en/hashmap","rel":"/r/IsA","end":"/c/en/map","weight":1,"surfaceText":"[[hashmap]] IsA [[map]]"}
|
|
10
|
+
{"start":"/c/en/interface","rel":"/r/IsA","end":"/c/en/type","weight":1,"surfaceText":"[[interface]] IsA [[type]]"}
|
|
11
|
+
{"start":"/c/en/interface","rel":"/r/IsA","end":"/c/en/contract","weight":1,"surfaceText":"[[interface]] IsA [[contract]]"}
|
|
12
|
+
{"start":"/c/en/class","rel":"/r/IsA","end":"/c/en/type","weight":1,"surfaceText":"[[class]] IsA [[type]]"}
|
|
13
|
+
{"start":"/c/en/object","rel":"/r/IsA","end":"/c/en/instance","weight":1,"surfaceText":"[[object]] IsA [[instance]]"}
|
|
14
|
+
{"start":"/c/en/jvm","rel":"/r/IsA","end":"/c/en/virtual_machine","weight":1,"surfaceText":"[[jvm]] IsA [[virtual machine]]"}
|
|
15
|
+
{"start":"/c/en/jvm","rel":"/r/UsedFor","end":"/c/en/running_bytecode","weight":1,"surfaceText":"[[jvm]] UsedFor [[running bytecode]]"}
|
|
16
|
+
{"start":"/c/en/jvm","rel":"/r/CapableOf","end":"/c/en/execute_bytecode","weight":1,"surfaceText":"[[jvm]] CapableOf [[execute bytecode]]"}
|
|
17
|
+
{"start":"/c/en/bytecode","rel":"/r/IsA","end":"/c/en/code","weight":1,"surfaceText":"[[bytecode]] IsA [[code]]"}
|
|
18
|
+
{"start":"/c/en/garbage_collector","rel":"/r/PartOf","end":"/c/en/jvm","weight":1,"surfaceText":"[[garbage collector]] PartOf [[jvm]]"}
|
|
19
|
+
{"start":"/c/en/garbage_collector","rel":"/r/UsedFor","end":"/c/en/freeing_memory","weight":1,"surfaceText":"[[garbage collector]] UsedFor [[freeing memory]]"}
|
|
20
|
+
{"start":"/c/en/jar","rel":"/r/IsA","end":"/c/en/archive","weight":1,"surfaceText":"[[jar]] IsA [[archive]]"}
|
|
21
|
+
{"start":"/c/en/jar","rel":"/r/IsA","end":"/c/en/file","weight":1,"surfaceText":"[[jar]] IsA [[file]]"}
|
|
22
|
+
{"start":"/c/en/jar","rel":"/r/UsedFor","end":"/c/en/packaging_classes","weight":1,"surfaceText":"[[jar]] UsedFor [[packaging classes]]"}
|
|
23
|
+
{"start":"/c/en/maven","rel":"/r/IsA","end":"/c/en/build_tool","weight":1,"surfaceText":"[[maven]] IsA [[build tool]]"}
|
|
24
|
+
{"start":"/c/en/maven","rel":"/r/IsA","end":"/c/en/package_manager","weight":1,"surfaceText":"[[maven]] IsA [[package manager]]"}
|
|
25
|
+
{"start":"/c/en/gradle","rel":"/r/IsA","end":"/c/en/build_tool","weight":1,"surfaceText":"[[gradle]] IsA [[build tool]]"}
|
|
26
|
+
{"start":"/c/en/thread","rel":"/r/IsA","end":"/c/en/process","weight":1,"surfaceText":"[[thread]] IsA [[process]]"}
|
|
27
|
+
{"start":"/c/en/thread","rel":"/r/UsedFor","end":"/c/en/concurrency","weight":1,"surfaceText":"[[thread]] UsedFor [[concurrency]]"}
|
|
28
|
+
{"start":"/c/en/generics","rel":"/r/UsedFor","end":"/c/en/type_safety","weight":1,"surfaceText":"[[generics]] UsedFor [[type safety]]"}
|
|
29
|
+
{"start":"/c/en/annotation","rel":"/r/IsA","end":"/c/en/metadata","weight":1,"surfaceText":"[[annotation]] IsA [[metadata]]"}
|
|
30
|
+
{"start":"/c/en/exception","rel":"/r/IsA","end":"/c/en/error","weight":1,"surfaceText":"[[exception]] IsA [[error]]"}
|
|
31
|
+
{"start":"/c/en/method","rel":"/r/IsA","end":"/c/en/function","weight":1,"surfaceText":"[[method]] IsA [[function]]"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"generated": "by corpus/tier2/generate.mjs",
|
|
4
|
+
"corpuses": [
|
|
5
|
+
{
|
|
6
|
+
"id": "aws",
|
|
7
|
+
"kind": "domain",
|
|
8
|
+
"description": "Amazon Web Services core services and primitives (S3, Lambda, DynamoDB, EC2, IAM, SQS) mapped to general cloud/CS concepts.",
|
|
9
|
+
"source": {
|
|
10
|
+
"kind": "curated",
|
|
11
|
+
"tool": "corpus/tier2/generate.mjs"
|
|
12
|
+
},
|
|
13
|
+
"file": "aws.jsonl",
|
|
14
|
+
"facts": 39,
|
|
15
|
+
"bytes": 4802,
|
|
16
|
+
"sha256": "7ab3e656bc4bc717be3c50d97af030e8592d6597cde182b15390a1dfaca9755a",
|
|
17
|
+
"license": "MPL-2.0"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": "python",
|
|
21
|
+
"kind": "language",
|
|
22
|
+
"description": "Python language constructs and stdlib types mapped to the shared CS concept vocabulary (list->array, dict->hash table, …).",
|
|
23
|
+
"source": {
|
|
24
|
+
"kind": "curated",
|
|
25
|
+
"tool": "corpus/tier2/generate.mjs"
|
|
26
|
+
},
|
|
27
|
+
"file": "python.jsonl",
|
|
28
|
+
"facts": 30,
|
|
29
|
+
"bytes": 3794,
|
|
30
|
+
"sha256": "009245d024357bc4285e967fba486e32349ccec8fbe2796ba13011cb2be4c19c",
|
|
31
|
+
"license": "MPL-2.0"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"id": "java",
|
|
35
|
+
"kind": "language",
|
|
36
|
+
"description": "Java language and JVM constructs mapped to the shared CS concept vocabulary (ArrayList->list, HashMap->hash table, …).",
|
|
37
|
+
"source": {
|
|
38
|
+
"kind": "curated",
|
|
39
|
+
"tool": "corpus/tier2/generate.mjs"
|
|
40
|
+
},
|
|
41
|
+
"file": "java.jsonl",
|
|
42
|
+
"facts": 31,
|
|
43
|
+
"bytes": 3920,
|
|
44
|
+
"sha256": "d089426833c393f6f1574fe75c4ac94a1483ee80f72f79bd7fd32aaaa24a6e44",
|
|
45
|
+
"license": "MPL-2.0"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{"start":"/c/en/python","rel":"/r/IsA","end":"/c/en/programming_language","weight":1,"surfaceText":"[[python]] IsA [[programming language]]"}
|
|
2
|
+
{"start":"/c/en/python","rel":"/r/HasProperty","end":"/c/en/interpreted","weight":1,"surfaceText":"[[python]] HasProperty [[interpreted]]"}
|
|
3
|
+
{"start":"/c/en/python","rel":"/r/HasProperty","end":"/c/en/dynamically_typed","weight":1,"surfaceText":"[[python]] HasProperty [[dynamically typed]]"}
|
|
4
|
+
{"start":"/c/en/python","rel":"/r/UsedFor","end":"/c/en/scripting","weight":1,"surfaceText":"[[python]] UsedFor [[scripting]]"}
|
|
5
|
+
{"start":"/c/en/list","rel":"/r/IsA","end":"/c/en/array","weight":1,"surfaceText":"[[list]] IsA [[array]]"}
|
|
6
|
+
{"start":"/c/en/list","rel":"/r/IsA","end":"/c/en/sequence","weight":1,"surfaceText":"[[list]] IsA [[sequence]]"}
|
|
7
|
+
{"start":"/c/en/list","rel":"/r/IsA","end":"/c/en/data_structure","weight":1,"surfaceText":"[[list]] IsA [[data structure]]"}
|
|
8
|
+
{"start":"/c/en/dict","rel":"/r/IsA","end":"/c/en/hash_table","weight":1,"surfaceText":"[[dict]] IsA [[hash table]]"}
|
|
9
|
+
{"start":"/c/en/dict","rel":"/r/IsA","end":"/c/en/dictionary","weight":1,"surfaceText":"[[dict]] IsA [[dictionary]]"}
|
|
10
|
+
{"start":"/c/en/dict","rel":"/r/IsA","end":"/c/en/mapping","weight":1,"surfaceText":"[[dict]] IsA [[mapping]]"}
|
|
11
|
+
{"start":"/c/en/tuple","rel":"/r/IsA","end":"/c/en/sequence","weight":1,"surfaceText":"[[tuple]] IsA [[sequence]]"}
|
|
12
|
+
{"start":"/c/en/tuple","rel":"/r/HasProperty","end":"/c/en/immutable","weight":1,"surfaceText":"[[tuple]] HasProperty [[immutable]]"}
|
|
13
|
+
{"start":"/c/en/set","rel":"/r/IsA","end":"/c/en/collection","weight":1,"surfaceText":"[[set]] IsA [[collection]]"}
|
|
14
|
+
{"start":"/c/en/set","rel":"/r/HasProperty","end":"/c/en/unordered","weight":1,"surfaceText":"[[set]] HasProperty [[unordered]]"}
|
|
15
|
+
{"start":"/c/en/str","rel":"/r/IsA","end":"/c/en/string","weight":1,"surfaceText":"[[str]] IsA [[string]]"}
|
|
16
|
+
{"start":"/c/en/decorator","rel":"/r/IsA","end":"/c/en/function","weight":1,"surfaceText":"[[decorator]] IsA [[function]]"}
|
|
17
|
+
{"start":"/c/en/decorator","rel":"/r/UsedFor","end":"/c/en/modifying_functions","weight":1,"surfaceText":"[[decorator]] UsedFor [[modifying functions]]"}
|
|
18
|
+
{"start":"/c/en/generator","rel":"/r/IsA","end":"/c/en/iterator","weight":1,"surfaceText":"[[generator]] IsA [[iterator]]"}
|
|
19
|
+
{"start":"/c/en/generator","rel":"/r/UsedFor","end":"/c/en/lazy_evaluation","weight":1,"surfaceText":"[[generator]] UsedFor [[lazy evaluation]]"}
|
|
20
|
+
{"start":"/c/en/comprehension","rel":"/r/IsA","end":"/c/en/expression","weight":1,"surfaceText":"[[comprehension]] IsA [[expression]]"}
|
|
21
|
+
{"start":"/c/en/comprehension","rel":"/r/UsedFor","end":"/c/en/building_collections","weight":1,"surfaceText":"[[comprehension]] UsedFor [[building collections]]"}
|
|
22
|
+
{"start":"/c/en/exception","rel":"/r/IsA","end":"/c/en/error","weight":1,"surfaceText":"[[exception]] IsA [[error]]"}
|
|
23
|
+
{"start":"/c/en/module","rel":"/r/IsA","end":"/c/en/file","weight":1,"surfaceText":"[[module]] IsA [[file]]"}
|
|
24
|
+
{"start":"/c/en/package","rel":"/r/IsA","end":"/c/en/module","weight":1,"surfaceText":"[[package]] IsA [[module]]"}
|
|
25
|
+
{"start":"/c/en/method","rel":"/r/IsA","end":"/c/en/function","weight":1,"surfaceText":"[[method]] IsA [[function]]"}
|
|
26
|
+
{"start":"/c/en/pip","rel":"/r/IsA","end":"/c/en/package_manager","weight":1,"surfaceText":"[[pip]] IsA [[package manager]]"}
|
|
27
|
+
{"start":"/c/en/pip","rel":"/r/UsedFor","end":"/c/en/installing_packages","weight":1,"surfaceText":"[[pip]] UsedFor [[installing packages]]"}
|
|
28
|
+
{"start":"/c/en/gil","rel":"/r/IsA","end":"/c/en/lock","weight":1,"surfaceText":"[[gil]] IsA [[lock]]"}
|
|
29
|
+
{"start":"/c/en/gil","rel":"/r/PartOf","end":"/c/en/interpreter","weight":1,"surfaceText":"[[gil]] PartOf [[interpreter]]"}
|
|
30
|
+
{"start":"/c/en/cpython","rel":"/r/IsA","end":"/c/en/interpreter","weight":1,"surfaceText":"[[cpython]] IsA [[interpreter]]"}
|
|
@@ -62,7 +62,10 @@
|
|
|
62
62
|
{"id":"conversational-farewell","class":"conversational","register":"friendly","template":"Bye — flushing the session log. Come back with a question any time."}
|
|
63
63
|
{"id":"orientation-friendly","class":"orientation","register":"friendly","template":"I answer questions about THIS codebase's structure — imports, calls, definitions,\nhistory and counts. For example:\n which modules import walk.mjs\n what calls buildContextBundle\n how many classes are there\n/help for commands, /stats for an overview of the graph."}
|
|
64
64
|
{"id":"miss-no-previous-answer","class":"miss","register":"friendly","template":"No previous answer to expand yet — ask me a question first, then say \"why\" or \"say more\"."}
|
|
65
|
+
{"id":"conversational-greeting-empty","class":"conversational","register":"friendly","template":"Hi. There's no code graph loaded here — for code structure (imports, calls, definitions) I need a `.tmct/graph.json`: point me at one with `--repo <path>`, or try the shipped example `npm run example:mini`. (tmct reads graphs; it doesn't index code itself.) For general vocabulary, `tmct init` seeds concepts — try \"what is a cache\". /help for commands."}
|
|
66
|
+
{"id":"orientation-empty","class":"orientation","register":"friendly","template":"There's no code graph loaded here, so I can't answer structure questions (imports, calls, definitions) yet.\nFor those I need a `.tmct/graph.json` produced by a graph producer — point me at one with `--repo <path>`, or try the shipped example `npm run example:mini`. tmct reads graphs; it doesn't index code itself.\nFor general vocabulary, `tmct init` seeds concepts — try \"what is a cache\". /help for commands, /memory for what I remember."}
|
|
65
67
|
{"id":"technical-density","class":"count","register":"technical","template":"{subject} carries {count} {noun} across {scope} — a concentration well above what a codebase of this size typically sustains ({provenance})."}
|
|
66
68
|
{"id":"technical-comparison","class":"count","register":"technical","template":"At {count} {noun}, {subject} sits {comparison} the comparable-project baseline, a divergence that reflects deliberate structure rather than measurement noise ({provenance})."}
|
|
67
69
|
{"id":"technical-superlative","class":"count","register":"technical","template":"No {noun} in {scope} is more {metric} than {subject}; it leads the next candidate by a clear margin of {count} ({provenance})."}
|
|
68
70
|
{"id":"technical-ratio","class":"count","register":"technical","template":"{subject} sustains a ratio of {count} {noun} per {unit}, placing it in the upper band for projects of comparable {scope} ({provenance})."}
|
|
71
|
+
{"id":"concept-force","class":"concept","register":"friendly","template":"{definition}\n{examples}{followups}"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polycode-projects/the-mechanical-code-talker",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
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.",
|
|
@@ -48,7 +48,12 @@
|
|
|
48
48
|
"./relationKind": "./src/codegraph.mjs",
|
|
49
49
|
"./impactClosure": "./src/codegraph.mjs",
|
|
50
50
|
"./dispatchTool": "./src/server.mjs",
|
|
51
|
-
"./fetchEntities": "./src/source.mjs"
|
|
51
|
+
"./fetchEntities": "./src/source.mjs",
|
|
52
|
+
"./repository-interface": "./src/repository-interface.mjs",
|
|
53
|
+
"./graph-service": "./src/providers/graph-service.mjs",
|
|
54
|
+
"./providers/fixture": "./src/providers/fixture.mjs",
|
|
55
|
+
"./providers/bootstrap": "./src/providers/bootstrap.mjs",
|
|
56
|
+
"./conformance": "./src/conformance.mjs"
|
|
52
57
|
},
|
|
53
58
|
"files": [
|
|
54
59
|
"bin/",
|
|
@@ -72,6 +77,12 @@
|
|
|
72
77
|
"scripts": {
|
|
73
78
|
"test": "node --test \"test/**/*.test.mjs\"",
|
|
74
79
|
"chat": "node bin/tmct.mjs",
|
|
80
|
+
"chat:repo": "node bin/tmct.mjs chat --repo",
|
|
81
|
+
"init": "node bin/tmct.mjs init",
|
|
82
|
+
"memory": "node bin/tmct.mjs memory",
|
|
83
|
+
"syllogise": "node bin/tmct.mjs syllogise",
|
|
84
|
+
"example:mini": "node bin/tmct.mjs chat --repo examples/mini-webapp --ephemeral",
|
|
85
|
+
"example:polyglot": "node bin/tmct.mjs chat --repo examples/polyglot --ephemeral",
|
|
75
86
|
"chatbench:run": "node chatbench/run.mjs",
|
|
76
87
|
"chatbench:judge": "node chatbench/judge.mjs",
|
|
77
88
|
"audit": "npm audit --audit-level=high",
|
package/src/ask-vocab.mjs
CHANGED
|
@@ -529,7 +529,14 @@ export const AGGREGATE_TRIGGERS = Object.freeze([
|
|
|
529
529
|
// CONTENT_VOCAB and blocks the article's own noise-strip)
|
|
530
530
|
"how many", "how much", "how many of", "number of",
|
|
531
531
|
"total number of", "quantity of",
|
|
532
|
-
//
|
|
532
|
+
// "<measure> of <kind>" cardinality forms (widened net, cycle W2P): count = sum = total
|
|
533
|
+
// = tally = number of. The bare single words (sum/total/tally) stay CASCADE_SYNONYMS-
|
|
534
|
+
// mapped to "count" (identifier-fragment risk without the "of" anchor — see that table's
|
|
535
|
+
// note); the multi-word "of" forms are safe to promote to direct triggers because the
|
|
536
|
+
// trailing "of <kind>" pins them to a cardinality question, not a stray identifier.
|
|
537
|
+
"tally of", "sum of", "total of", "amount of",
|
|
538
|
+
// neutral / imperative (bare "tally"/"sum"/"total" stay CASCADE_SYNONYMS-mapped so the
|
|
539
|
+
// "tally the classes" relaxation path — pinned by a cascade test — is preserved).
|
|
533
540
|
"count", "count up", "count of", "tot up",
|
|
534
541
|
]);
|
|
535
542
|
|
|
@@ -593,6 +600,17 @@ export const EDGE_NOUN_TO_METRIC = Object.freeze({
|
|
|
593
600
|
connections: { kind: "*", dir: "both" },
|
|
594
601
|
edges: { kind: "*", dir: "both" },
|
|
595
602
|
connected: { kind: "*", dir: "both" },
|
|
603
|
+
// participle degree-nouns (widened net, cycle W2P): "the most imported / most
|
|
604
|
+
// depended-on / most used <module>" ranks by IN-degree — how many things import/depend
|
|
605
|
+
// on/use it — the ARGMAX-by-degree intent a developer expresses with a passive
|
|
606
|
+
// participle rather than the noun ("importers"). "depended" catches "depended-on" /
|
|
607
|
+
// "depended on" (both tokenize to a bare "depended"); "used" folds the symbol-grain
|
|
608
|
+
// callsSymbol callers in alongside importers so "most used" reads as most-relied-upon.
|
|
609
|
+
imported: { kind: "imports", dir: "in" },
|
|
610
|
+
"depended-on": { kind: "imports", dir: "in" },
|
|
611
|
+
depended: { kind: "imports", dir: "in" },
|
|
612
|
+
used: { kind: "imports", dir: "in", sibling: "callsSymbol" },
|
|
613
|
+
called: { kind: "calls", dir: "in", sibling: "callsSymbol" },
|
|
596
614
|
});
|
|
597
615
|
|
|
598
616
|
/** Anaphora triggers over the PREVIOUS result set (ask()'s `prev` id array):
|
package/src/ask.mjs
CHANGED
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
// grammar, split out of this file: normalization pre-pass, the two parsing
|
|
52
52
|
// strategies, and the bounded-fuzzy service. Re-exported below where existing
|
|
53
53
|
// callers/tests import them from here.
|
|
54
|
-
import { normalizeQuery, applyNegationFrames, matchNegationSet, STOPWORDS, splitWords, wordsOf } from "./interpret/normalize.mjs";
|
|
54
|
+
import { normalizeQuery, applyNegationFrames, applyPhrasingFrames, matchNegationSet, STOPWORDS, splitWords, wordsOf } from "./interpret/normalize.mjs";
|
|
55
55
|
import { editDistance, fuzzyBound } from "./interpret/fuzzy.mjs";
|
|
56
56
|
import { parseAnchored } from "./interpret/strategies/grammar.mjs";
|
|
57
57
|
import { parseKeywordSpot, findPhrase } from "./interpret/strategies/keywords.mjs";
|
|
@@ -168,7 +168,7 @@ export function parseQuery(query, { nlp = undefined } = {}) {
|
|
|
168
168
|
const adapter = nlp === undefined ? defaultNlp() : nlp;
|
|
169
169
|
const raw = String(query || "").trim().replace(/\s+/g, " ");
|
|
170
170
|
if (!raw) return null;
|
|
171
|
-
const text = applyNegationFrames(normalizeQuery(raw));
|
|
171
|
+
const text = applyPhrasingFrames(applyNegationFrames(normalizeQuery(raw)));
|
|
172
172
|
if (!text) return null;
|
|
173
173
|
// COMPOSITIONAL PARSE PATH (PLAN §5.16 P3) — the new PRIMARY layer: a recursive
|
|
174
174
|
// descent over CLAUSES for the compositional shapes (nested/relative, boolean,
|
|
@@ -1471,18 +1471,18 @@ export function traverse(graph, parsed, { contextId = null, prev = null } = {})
|
|
|
1471
1471
|
|
|
1472
1472
|
// reverse: "which <entityType> R <objMatch>". GRAIN-AWARE (Cycle 5, lever 3): a kind
|
|
1473
1473
|
// that carries a symbol-grain sibling reads off the SIBLING when a fine SUBJECT grain
|
|
1474
|
-
// was asked for ("which functions call X" → callsSymbol).
|
|
1475
|
-
//
|
|
1476
|
-
//
|
|
1477
|
-
//
|
|
1478
|
-
// edges
|
|
1479
|
-
//
|
|
1480
|
-
//
|
|
1481
|
-
//
|
|
1482
|
-
//
|
|
1474
|
+
// was asked for ("which functions call X" → callsSymbol). It ALSO reads off the sibling
|
|
1475
|
+
// when the RESOLVED OBJECT is itself a fine symbol, for EVERY kind with a sibling — not
|
|
1476
|
+
// only touches: the module-coarse edge (calls Module→Module, touches Commit→Module) can
|
|
1477
|
+
// NEVER point at a function/method, so a bare "what calls fnAlpha" scanning the coarse
|
|
1478
|
+
// `calls` edges returned a FALSE empty ("No modules found …") while the graph records a
|
|
1479
|
+
// real symbol-level caller (Widget.render --callsSymbol--> fnAlpha). The honest answer
|
|
1480
|
+
// reads off callsSymbol at symbol grain; a truly-uncalled symbol still renders the
|
|
1481
|
+
// honest empty, now with the accurate callsSymbol receipt. (Previously scoped to touches
|
|
1482
|
+
// only, which left this exact callsSymbol caller invisible — a genuine correctness bug.)
|
|
1483
1483
|
const symbolKind = SYMBOL_GRAIN_SIBLING[kind];
|
|
1484
|
-
const
|
|
1485
|
-
if (symbolKind && (FINE_ENTITY_TYPES.has(entityType) ||
|
|
1484
|
+
const objIsFineSymbol = !!(objMatch.class && FINE_ENTITY_TYPES.has(objMatch.class));
|
|
1485
|
+
if (symbolKind && (FINE_ENTITY_TYPES.has(entityType) || objIsFineSymbol)) {
|
|
1486
1486
|
const edges = edgesOfKind(graph, symbolKind).filter((e) => e.object === objMatch.id);
|
|
1487
1487
|
const subjects = uniqueById(edges.map((e) => graph.byId.get(e.subject)).filter(Boolean));
|
|
1488
1488
|
const matches = (!entityType || entityType === "Change") ? subjects : subjects.filter((i) => i.class === entityType);
|