@polycode-projects/the-mechanical-code-talker 1.12.0 → 2.0.2

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 (148) hide show
  1. package/README.md +244 -48
  2. package/ROADMAP.md +23 -34
  3. package/bin/tmct.mjs +107 -71
  4. package/corpus/LICENSES.json +118 -0
  5. package/corpus/README.md +17 -13
  6. package/corpus/conceptnet/README.md +5 -5
  7. package/corpus/conceptnet/fetch-slice.mjs +1 -1
  8. package/corpus/conceptnet/filter-dump.mjs +1 -1
  9. package/corpus/generated/README.md +9 -10
  10. package/corpus/namenet/README.md +39 -0
  11. package/corpus/seon/README.md +2 -2
  12. package/corpus/tier2/generate.mjs +58 -9
  13. package/corpus/tier2/manifest.json +44 -0
  14. package/corpus/wordnet/README.md +37 -0
  15. package/corpus/wordnet/generate.mjs +1 -1
  16. package/data/templates/constructions/agent-noun-relations.toml +2 -2
  17. package/data/templates/grammar-rules.toml +1 -1
  18. package/package.json +13 -22
  19. package/src/{ask-nlp.mjs → adapters/ask-nlp.mjs} +1 -1
  20. package/src/{config.mjs → adapters/config.mjs} +1 -1
  21. package/src/{corpus → adapters/corpus}/conceptnet-map.toml +4 -4
  22. package/src/{corpus → adapters/corpus}/conceptnet.mjs +3 -3
  23. package/src/adapters/corpus/construction-banks.mjs +43 -0
  24. package/src/{corpus → adapters/corpus}/templates.mjs +1 -1
  25. package/src/{embed.mjs → adapters/embed.mjs} +1 -11
  26. package/src/{graph-build.mjs → adapters/graph-build.mjs} +6 -6
  27. package/src/{memory → adapters/memory}/blocks.mjs +2 -2
  28. package/src/{memory → adapters/memory}/core.mjs +38 -94
  29. package/src/adapters/prose-tokens.mjs +98 -0
  30. package/src/{providers → adapters/providers}/bootstrap.mjs +2 -2
  31. package/src/{providers → adapters/providers}/fixture.mjs +3 -3
  32. package/src/{providers → adapters/providers}/graph-service.mjs +9 -4
  33. package/src/{source-slice.mjs → adapters/source-slice.mjs} +2 -2
  34. package/src/{source.mjs → adapters/source.mjs} +1 -1
  35. package/src/{toml-config.mjs → adapters/toml-config.mjs} +1 -1
  36. package/src/{answer-variants.json → domain/answer-variants.json} +1 -1
  37. package/src/domain/answer-variants.mjs +23 -0
  38. package/src/{ask-vocab.mjs → domain/ask-vocab.mjs} +37 -5
  39. package/src/{ask.mjs → domain/ask.mjs} +216 -52
  40. package/src/{codegraph.mjs → domain/codegraph.mjs} +31 -315
  41. package/src/{completions → domain/completions}/complete.mjs +16 -10
  42. package/src/{completions → domain/completions}/graph-adapter.mjs +10 -4
  43. package/src/{completions → domain/completions}/group.mjs +14 -6
  44. package/src/{completions → domain/completions}/infer.mjs +57 -39
  45. package/src/domain/completions/injected.mjs +21 -0
  46. package/src/{completions → domain/completions}/rank.mjs +15 -8
  47. package/src/{completions → domain/completions}/search.mjs +4 -2
  48. package/src/{grammar → domain/grammar}/ace.mjs +3 -3
  49. package/src/{grammar → domain/grammar}/assert.mjs +12 -8
  50. package/src/{grammar → domain/grammar}/lexicon-core.json +1 -1
  51. package/src/{grammar → domain/grammar}/lexicon.mjs +4 -6
  52. package/src/domain/hash.mjs +147 -0
  53. package/src/{interpret → domain/interpret}/fuzzy.mjs +42 -4
  54. package/src/domain/interpret/nlp-registry.mjs +20 -0
  55. package/src/{interpret → domain/interpret}/normalize.mjs +35 -5
  56. package/src/{interpret → domain/interpret}/pipeline.mjs +1 -5
  57. package/src/{interpret → domain/interpret}/strategies/ace.mjs +1 -1
  58. package/src/{interpret → domain/interpret}/strategies/constructions.mjs +30 -52
  59. package/src/{interpret → domain/interpret}/strategies/keywords.mjs +48 -26
  60. package/src/domain/memory/capability.mjs +235 -0
  61. package/src/domain/memory/fold.mjs +54 -0
  62. package/src/domain/memory/session-turns.mjs +7 -0
  63. package/src/{memory → domain/memory}/trust.mjs +48 -0
  64. package/src/{paraphrase.mjs → domain/paraphrase.mjs} +2 -2
  65. package/src/{prose.mjs → domain/prose.mjs} +1 -1
  66. package/src/domain/real-word-collisions.json +1 -0
  67. package/src/{router → domain/router}/call-validator.mjs +1 -1
  68. package/src/{router → domain/router}/drive.mjs +34 -25
  69. package/src/{router → domain/router}/goal-reasoner.mjs +1 -1
  70. package/src/{router → domain/router}/guardrail.mjs +1 -1
  71. package/src/{router → domain/router}/planner.mjs +1 -1
  72. package/src/{router → domain/router}/registry.mjs +5 -5
  73. package/src/{router → domain/router}/resolver.mjs +16 -13
  74. package/src/{router → domain/router}/results.mjs +1 -1
  75. package/src/{router → domain/router}/set-algebra.mjs +1 -1
  76. package/src/{router → domain/router}/taught.mjs +10 -9
  77. package/src/{syllogise.mjs → domain/syllogise.mjs} +21 -4
  78. package/src/domain/vector.mjs +12 -0
  79. package/src/services/chat-session.mjs +451 -0
  80. package/src/{chat.mjs → services/chat.mjs} +1209 -684
  81. package/src/{cli-args.mjs → services/cli-args.mjs} +2 -2
  82. package/src/services/completions.mjs +55 -0
  83. package/src/{extensions.mjs → services/extensions.mjs} +7 -7
  84. package/src/{finish.mjs → services/finish.mjs} +2 -2
  85. package/src/{memory → services}/fold.mjs +0 -0
  86. package/src/{import-file.mjs → services/import-file.mjs} +3 -3
  87. package/src/{index.mjs → services/index.mjs} +21 -12
  88. package/src/{init.mjs → services/init.mjs} +9 -9
  89. package/src/{ledger-viz.mjs → services/ledger-viz.mjs} +3 -3
  90. package/src/{plan-viz.mjs → services/plan-viz.mjs} +98 -28
  91. package/src/{sentences.mjs → services/sentences.mjs} +1 -1
  92. package/src/{sessions.mjs → services/sessions.mjs} +4 -5
  93. package/src/{telemetry.mjs → services/telemetry.mjs} +1 -1
  94. package/src/{server-http.mjs → surfaces/http/server-http.mjs} +11 -65
  95. package/src/{tui → surfaces/tui}/app.mjs +3 -3
  96. package/src/{memory-ask-browser-entry.mjs → surfaces/web/memory-ask-browser-entry.mjs} +5 -5
  97. package/src/{memory-ask-browser.bundle.js → surfaces/web/memory-ask-browser.bundle.js} +9465 -6366
  98. package/src/tools/catalog.mjs +29 -0
  99. package/src/{conformance.mjs → tools/conformance.mjs} +2 -2
  100. package/src/tools/definitions.mjs +288 -0
  101. package/src/tools/graph-load.mjs +20 -0
  102. package/src/tools/handlers/index.mjs +54 -0
  103. package/src/tools/handlers/kit.mjs +33 -0
  104. package/src/tools/handlers/tmct-architecture.mjs +7 -0
  105. package/src/tools/handlers/tmct-ask.mjs +14 -0
  106. package/src/tools/handlers/tmct-callees.mjs +6 -0
  107. package/src/tools/handlers/tmct-callers.mjs +6 -0
  108. package/src/tools/handlers/tmct-calls.mjs +6 -0
  109. package/src/tools/handlers/tmct-class-history.mjs +6 -0
  110. package/src/tools/handlers/tmct-cochanges.mjs +6 -0
  111. package/src/tools/handlers/tmct-context-more.mjs +9 -0
  112. package/src/tools/handlers/tmct-context.mjs +163 -0
  113. package/src/tools/handlers/tmct-describe.mjs +15 -0
  114. package/src/tools/handlers/tmct-exports.mjs +9 -0
  115. package/src/tools/handlers/tmct-file-history.mjs +6 -0
  116. package/src/tools/handlers/tmct-history.mjs +6 -0
  117. package/src/tools/handlers/tmct-impact.mjs +9 -0
  118. package/src/tools/handlers/tmct-members.mjs +16 -0
  119. package/src/tools/handlers/tmct-method-history.mjs +6 -0
  120. package/src/tools/handlers/tmct-search.mjs +22 -0
  121. package/src/tools/handlers/tmct-signature.mjs +6 -0
  122. package/src/tools/handlers/tmct-snippet.mjs +37 -0
  123. package/src/tools/handlers/tmct-subclasses.mjs +16 -0
  124. package/src/tools/handlers/tmct-tests-for.mjs +6 -0
  125. package/src/tools/handlers/tmct-untested.mjs +7 -0
  126. package/src/tools/memory-fallthrough.mjs +65 -0
  127. package/src/{schema-docs.mjs → tools/schema-docs.mjs} +1 -1
  128. package/src/tools/server.mjs +61 -0
  129. package/src/answer-variants.mjs +0 -39
  130. package/src/hash.mjs +0 -24
  131. package/src/server.mjs +0 -501
  132. /package/src/{corpus → adapters/corpus}/unknown-ingest.mjs +0 -0
  133. /package/src/{graph-merge.mjs → adapters/graph-merge.mjs} +0 -0
  134. /package/src/{memory → adapters/memory}/inspect.mjs +0 -0
  135. /package/src/{memory → adapters/memory}/shacl.mjs +0 -0
  136. /package/src/{prose-nlp.mjs → adapters/prose-nlp.mjs} +0 -0
  137. /package/src/{repository-interface.mjs → adapters/repository-interface.mjs} +0 -0
  138. /package/src/{uuid.mjs → adapters/uuid.mjs} +0 -0
  139. /package/src/{wink-model.mjs → adapters/wink-model.mjs} +0 -0
  140. /package/src/{completions → domain/completions}/prune.mjs +0 -0
  141. /package/src/{concept.mjs → domain/concept.mjs} +0 -0
  142. /package/src/{domain.mjs → domain/domain.mjs} +0 -0
  143. /package/src/{interpret → domain/interpret}/merge.mjs +0 -0
  144. /package/src/{interpret → domain/interpret}/strategies/grammar.mjs +0 -0
  145. /package/src/{interpret → domain/interpret}/strategies/noise-strip.mjs +0 -0
  146. /package/src/{memory → domain/memory}/bias.mjs +0 -0
  147. /package/src/{planning.mjs → domain/planning.mjs} +0 -0
  148. /package/src/{viz-theme.mjs → services/viz-theme.mjs} +0 -0
package/corpus/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  The corpuses tmct ships so that an **empty** tmct still has a vocabulary
4
4
  (ROADMAP Phase 2). Everything here is plain, diffable data; the loaders live
5
- in `src/corpus/`. Related committed data lives in `data/` (response templates
5
+ in `src/adapters/corpus/`. Related committed data lives in `data/` (response templates
6
6
  + the SE phrase book — items 4+7).
7
7
 
8
8
  ## The tiering policy (tier-1 / tier-2 / tier-3)
@@ -13,7 +13,7 @@ tmct's knowledge arrives in three tiers, distinguished by **when** it lands and
13
13
  | Tier | What | Ships in the package? | Lands when | Provenance |
14
14
  |---|---|---|---|---|
15
15
  | **1 — base** | the general English/tech ConceptNet slice + the response templates + the SE phrasebook — the vocabulary every tmct has out of the box | **yes**, committed here | `tmct init` seeds `.tmct/` from committed data (offline, $0) | `corpus:conceptnet /r/…` |
16
- | **2 — specialised** | LANGUAGE- or DOMAIN-specific fact sets (`aws`, `python`, `java`) plus one deliberately NON-code-domain "wider general-knowledge" bundle (`general`) so tmct can "expand into a concept for an applicable codebase" — or into a seed set that isn't code at all | **no** — selected per repo | activated via `src/extensions.mjs`'s `[extensions.tier2-<id>] active = true` (or `tmct init --corpus <id>`), inactive by default | `corpus:tier2-<id> /r/…` |
16
+ | **2 — specialised** | LANGUAGE- or DOMAIN-specific fact sets (`aws`, `python`, `java`) plus one deliberately NON-code-domain "wider general-knowledge" bundle (`general`) so tmct can "expand into a concept for an applicable codebase" — or into a seed set that isn't code at all | **no** — selected per repo | activated via `src/services/extensions.mjs`'s `[extensions.tier2-<id>] active = true` (or `tmct init --corpus <id>`), inactive by default | `corpus:tier2-<id> /r/…` |
17
17
  | **3 — learned** | facts tmct writes from the actual conversation / the actual codebase it is pointed at | never committed | at runtime, into `.tmct/memory/` | `chat:…`, `codegraph:…` |
18
18
 
19
19
  **Offline / $0 is the default at every tier.** Tier-1 is committed. Tier-2's
@@ -29,6 +29,10 @@ loudly instead of seeding garbage.
29
29
 
30
30
  ## What's here
31
31
 
32
+ `LICENSES.json` in this directory is the machine-readable rollup of the table
33
+ below — one entry per corpus family ({path, upstream, license, shareAlike,
34
+ notice}), guarded by `test/estate/corpus-licences.test.mjs`.
35
+
32
36
  | Path | What | Size | Licence |
33
37
  |---|---|---|---|
34
38
  | `conceptnet/slice.jsonl` | tier-1: filtered English/tech-domain ConceptNet 5.7 slice, quality-filtered (one assertion per line) | ~1.35 MB | **CC-BY-SA 4.0** (see `conceptnet/LICENSE-NOTICE`) |
@@ -39,9 +43,9 @@ loudly instead of seeding garbage.
39
43
  | `tier2/manifest.json` | tier-2: index of specialised corpuses (id, kind, description, source, sha256, size) | — | MPL-2.0 |
40
44
  | `tier2/generate.mjs` | tier-2: the curated-corpus generator + manifest writer (+ opt-in network-fetch path) | — | MPL-2.0 |
41
45
  | `tier2/{aws,python,java,general}.jsonl` | tier-2 SAMPLE corpuses — same fact shape as the tier-1 slice, loadable via the same path (`general` is the one deliberately non-code-domain bundle) | ~4-6 KB each | MPL-2.0 |
42
- | `tier2/human.jsonl` | the DEFAULT active bundle (archive/PLAN_SEED.md): the everyday "human-world" persona, Small tier (664 facts) — hand-curated from Open English WordNet, bridged to Schema.org's top-level classes (archive/PLAN_SEED.md §3, §8) | ~80 KB | MPL-2.0 (hand-authored fact set; not a verbatim WordNet/Schema.org excerpt — see `tier2/generate.mjs`'s own header comment) |
43
- | `tier2/human-medium.jsonl` / `tier2/human-large.jsonl` | SIZE tiers of the SAME `human` bundle (archive/PLAN_SEED.md §3) — each holds ONLY the facts that size adds beyond the previous one; both shipped INACTIVE by default, activated via `tmct init --persona-size medium\|large`. Built by `scripts/build-persona-tiers.mjs` from the same WordNet source, automatically curated (sense-ranked, blocklist/denylist-filtered) rather than hand-typed one at a time, given the scale (944 / ~12,000 facts) | ~111 KB / ~1.4 MB | MPL-2.0 (same "hand-authored in homage to the source's shape" basis as `human.jsonl`) |
44
- | `tier2/human-examples.jsonl` / `tier2/human-examples-medium.jsonl` / `tier2/human-examples-large.jsonl` | the example-sentence corpus (archive/PLAN_SEED.md §9) — real natural-language sentences mapped to the same curated vocabulary, NOT fact triples. Small/Medium tiers are 100% WordNet's own inline `example:` field (same CC-BY-4.0 basis as the fact bundles). Large tier ALSO includes a SemCor-filtered supplement (real Brown Corpus text, re-tagged to modern OEWN senses) for categories where WordNet's own inline coverage is thin (`human-nature` especially — `noun.animal.yaml`'s inline rate is under 1%, archive/PLAN_SEED.md §9's own measurement) | ~11 KB / ~43 KB / ~257 KB | **The WordNet-inline entries**: CC-BY-4.0 (Princeton WordNet + Open English WordNet team), reproduced verbatim (these ARE the source's own example sentences, not a paraphrase). **The `source: "semcor:…"` entries**: CC-BY-4.0 per this SemCor fork's own `LICENSE.md` (`~/projects/globalwordnet/semcor/`, real Brown Corpus text re-tagged to modern senses — the original 1960s Brown Corpus permissions aren't independently re-verified beyond that fork's own license statement; proceeding with attribution was an explicit operator decision, archive/PLAN_SEED.md §9) — each entry's own `source` field names its origin file (`semcor:<genre>/<file>.yaml`) for exactly this reason |
46
+ | `tier2/human.jsonl` | the DEFAULT active bundle: the everyday "human-world" persona, Small tier (664 facts) — hand-curated from Open English WordNet, bridged to Schema.org's top-level classes | ~80 KB | MPL-2.0 (hand-authored fact set; not a verbatim WordNet/Schema.org excerpt — see `tier2/generate.mjs`'s own header comment) |
47
+ | `tier2/human-medium.jsonl` / `tier2/human-large.jsonl` | SIZE tiers of the SAME `human` bundle — each holds ONLY the facts that size adds beyond the previous one; both shipped INACTIVE by default, activated via `tmct init --persona-size medium\|large`. Built by `scripts/build-persona-tiers.mjs` from the same WordNet source, automatically curated (sense-ranked, blocklist/denylist-filtered) rather than hand-typed one at a time, given the scale (944 / ~12,000 facts) | ~111 KB / ~1.4 MB | MPL-2.0 (same "hand-authored in homage to the source's shape" basis as `human.jsonl`) |
48
+ | `tier2/human-examples.jsonl` / `tier2/human-examples-medium.jsonl` / `tier2/human-examples-large.jsonl` | the example-sentence corpus — real natural-language sentences mapped to the same curated vocabulary, NOT fact triples. Small/Medium tiers are 100% WordNet's own inline `example:` field (same CC-BY-4.0 basis as the fact bundles). Large tier ALSO includes a SemCor-filtered supplement (real Brown Corpus text, re-tagged to modern OEWN senses) for categories where WordNet's own inline coverage is thin (`human-nature` especially — `noun.animal.yaml`'s inline rate is under 1%) | ~11 KB / ~43 KB / ~257 KB | **The WordNet-inline entries**: CC-BY-4.0 (Princeton WordNet + Open English WordNet team), reproduced verbatim (these ARE the source's own example sentences, not a paraphrase). **The `source: "semcor:…"` entries**: CC-BY-4.0 per this SemCor fork's own `LICENSE.md` (a local uncommitted checkout of `globalwordnet/semcor`, real Brown Corpus text re-tagged to modern senses — the original 1960s Brown Corpus permissions aren't independently re-verified beyond that fork's own license statement; proceeding with attribution was an explicit operator decision) — each entry's own `source` field names its origin file (`semcor:<genre>/<file>.yaml`) for exactly this reason |
45
49
 
46
50
  And alongside (same phase, different directory because it is tmct-original
47
51
  data, not a derived corpus):
@@ -53,17 +57,17 @@ data, not a derived corpus):
53
57
 
54
58
  ## How seeding works
55
59
 
56
- `src/corpus/conceptnet.mjs` turns the slice into tmct memory facts:
60
+ `src/adapters/corpus/conceptnet.mjs` turns the slice into tmct memory facts:
57
61
 
58
62
  ```js
59
- import { seedMemory } from "./src/corpus/conceptnet.mjs";
63
+ import { seedMemory } from "./src/adapters/corpus/conceptnet.mjs";
60
64
  await seedMemory(repoDir); // writes <repoDir>/.tmct/memory/graph.json
61
65
  await seedMemory(repoDir, { limit: 500 }); // capped (fast bootstrap)
62
66
  ```
63
67
 
64
68
  - Each assertion whose relation maps to an ACE-OWL pattern
65
- (`src/corpus/conceptnet-map.toml`, `ace != "none"`) becomes one reified
66
- fact via `src/memory/core.mjs` `appendFact`:
69
+ (`src/adapters/corpus/conceptnet-map.toml`, `ace != "none"`) becomes one reified
70
+ fact via `src/adapters/memory/core.mjs` `appendFact`:
67
71
  `{subject:"software bug", predicate:"rdfs:subClassOf", object:"error",
68
72
  provenance:"corpus:conceptnet /r/IsA"}`.
69
73
  - **Idempotent**: fact ids are content-hashed from the normalized triple, and
@@ -79,7 +83,7 @@ A tier-2 corpus is a small, curated, LANGUAGE- or DOMAIN-specific fact set in
79
83
  the **exact tier-1 fact shape** — one JSON object per line,
80
84
  `{"start":"/c/en/…","rel":"/r/…","end":"/c/en/…","weight":N,"surfaceText":"…"}`,
81
85
  with `rel` drawn only from the mapped relations in
82
- `src/corpus/conceptnet-map.toml`. Because the shape is identical, a tier-2 file
86
+ `src/adapters/corpus/conceptnet-map.toml`. Because the shape is identical, a tier-2 file
83
87
  loads and seeds through the very same `loadSlice()`/`toFacts()` path as the
84
88
  tier-1 slice — `tier2/generate.mjs --verify` proves it (each sample loads and
85
89
  all its facts seed cleanly, no `ace=none` dead rows).
@@ -97,7 +101,7 @@ sha256) in one deterministic pass. Curated data is authored in that file so it
97
101
  stays reviewable; a corpus too big to hand-curate is a `fetch` manifest entry
98
102
  (URL + sha256, opt-in network — `fetchCorpus()` is the reference downloader).
99
103
 
100
- **How tier-2 wires into `tmct init` (done — `src/extensions.mjs`):**
104
+ **How tier-2 wires into `tmct init` (done — `src/services/extensions.mjs`):**
101
105
  `resolveExtensions(repoRoot)` ships all four tier-2 bundles as
102
106
  shipped-but-inactive `BUILTIN_EXTENSIONS` entries (`tier2-aws`/`tier2-python`/
103
107
  `tier2-java`/`tier2-general`); `[extensions.tier2-<id>] active = true` in
@@ -116,13 +120,13 @@ A term that would otherwise be silently dropped when a bundle is seeded (an
116
120
  `ace = "none"` relation like RelatedTo/HasContext, e.g. from a broader slice)
117
121
  can optionally be captured instead of vanishing: `seedMemory`'s
118
122
  `captureUnknownContext: true` option (default off) runs
119
- `src/corpus/unknown-ingest.mjs` over the same batch — see that module's own
123
+ `src/adapters/corpus/unknown-ingest.mjs` over the same batch — see that module's own
120
124
  doc comment.
121
125
 
122
126
  ## How to regenerate / extend
123
127
 
124
128
  See `conceptnet/README.md` — one command per route (API vs dump), the
125
129
  quality-filter pass, plus the seed-term list to extend. The test suite
126
- (`test/corpus-conceptnet.test.mjs`, `test/corpus-templates.test.mjs`) guards the
130
+ (`test/adapters/corpus-conceptnet.test.mjs`, `test/corpus-templates.test.mjs`) guards the
127
131
  contracts: slice/mapping drift, en→en shape, the ≤ 1.5 MB budget, template
128
132
  ids/slots, and end-to-end seeding.
@@ -31,7 +31,7 @@ see `LICENSE-NOTICE` in this directory for the full attribution.
31
31
  suffixes are stripped (`/c/en/bug/n` → `/c/en/bug`); self-loops after
32
32
  stripping are dropped.
33
33
  2. **Canonical relations only**: the closed set of 34 relations (the same set
34
- mapped in `src/corpus/conceptnet-map.toml`), minus three filtered by
34
+ mapped in `src/adapters/corpus/conceptnet-map.toml`), minus three filtered by
35
35
  policy: `/r/EtymologicallyRelatedTo`, `/r/EtymologicallyDerivedFrom`,
36
36
  `/r/ExternalURL` (etymology noise and link-outs — no consumer in tmct).
37
37
  3. **Tech-domain seed terms**: at least one endpoint's bare term is in the
@@ -90,7 +90,7 @@ from the same ConceptNet dump by (a) widening the tech domain with the
90
90
  `EXTRA_SEEDS` list in `filter-dump.mjs` (~230 tech terms — languages,
91
91
  frameworks, data structures, cloud/infra, protocols, tools, ML) and (b) raising
92
92
  `MAX_BYTES` in `filter-dump.mjs` from 1.4 MB to 4.5 MB with the matching test
93
- budget assertion (`test/corpus-conceptnet.test.mjs`) raised from 1.5 MB to
93
+ budget assertion (`test/adapters/corpus-conceptnet.test.mjs`) raised from 1.5 MB to
94
94
  5 MB. The widened seed set matched **45,633 unique en→en assertions** (all under
95
95
  budget, so no tier-trimming was needed this pass), and the quality filter
96
96
  trimmed them to the committed **44,947 clean facts**. Regenerate with:
@@ -149,14 +149,14 @@ To extend the domain, add seed terms to `EXTRA_SEEDS` in `filter-dump.mjs` (the
149
149
  dump route that produces the committed slice) or `SEED_TERMS` in
150
150
  `fetch-slice.mjs` (the API route) and re-run. `npm test` guards the contract:
151
151
  every relation present in the slice must have a row in
152
- `src/corpus/conceptnet-map.toml` (drift guard), en→en shape and the ≤ 5 MB
152
+ `src/adapters/corpus/conceptnet-map.toml` (drift guard), en→en shape and the ≤ 5 MB
153
153
  budget are asserted, and the seeding path is exercised end-to-end.
154
154
 
155
155
  ## Consumers
156
156
 
157
- - `src/corpus/conceptnet.mjs` — `loadSlice()` / `toFacts()` / `seedMemory()`:
157
+ - `src/adapters/corpus/conceptnet.mjs` — `loadSlice()` / `toFacts()` / `seedMemory()`:
158
158
  maps mappable assertions onto memory facts
159
159
  (`{subject, predicate, object, provenance:"corpus:conceptnet /r/…"}`)
160
160
  and seeds `.tmct/memory/` via `appendFact` (idempotent).
161
- - `src/corpus/conceptnet-map.toml` — the relation → ACE-OWL pattern table
161
+ - `src/adapters/corpus/conceptnet-map.toml` — the relation → ACE-OWL pattern table
162
162
  deciding which relations emit facts and under which predicate URI.
@@ -12,7 +12,7 @@
12
12
  // Filter rules (also documented in README.md here):
13
13
  // - /query?node=/c/en/<term>&other=/c/en — both endpoints English;
14
14
  // - keep only edges whose rel is one of the 34 canonical relations
15
- // (src/corpus/conceptnet-map.toml is the same closed set);
15
+ // (src/adapters/corpus/conceptnet-map.toml is the same closed set);
16
16
  // - drop en→en edges whose start/end still carry a sense suffix mismatch
17
17
  // (we keep the bare /c/en/<term> and /c/en/<term>/<pos> forms, normalized
18
18
  // to the bare term URI);
@@ -28,7 +28,7 @@
28
28
 
29
29
  import { createInterface } from "node:readline";
30
30
  import { SEED_TERMS, CANONICAL_RELS, FILTERED_RELS, bareEnTerm } from "./fetch-slice.mjs";
31
- import { loadMap } from "../../src/corpus/conceptnet.mjs";
31
+ import { loadMap } from "../../src/adapters/corpus/conceptnet.mjs";
32
32
 
33
33
  const MAX_BYTES = 4_500_000; // committed-slice budget (hard cap 5 MB), grown for the ~40k tier-1 target
34
34
 
@@ -1,36 +1,35 @@
1
1
  # corpus/generated/ — mechanically-generated ACE surface variants
2
2
 
3
- `ace-surface-variants.jsonl` — archive/PLAN_BREADTH_FIRST_NLU.md §6a's raw material for
4
- tmct's "richer template/surface-realization variety" goal. Never an LLM, never
3
+ `ace-surface-variants.jsonl` — raw material for tmct's "richer
4
+ template/surface-realization variety" goal. Never an LLM, never
5
5
  invented text: every row is a real seed sentence with one word swapped for a
6
6
  real WordNet synset sibling, or a real sentence's alternate ACE-grammar-
7
7
  declared surface form. Every row is self-verified — it re-parses against
8
- tmct's own `parseAce` (`src/grammar/ace.mjs`) before being written; a swap
8
+ tmct's own `parseAce` (`src/domain/grammar/ace.mjs`) before being written; a swap
9
9
  that doesn't re-parse is dropped, never committed.
10
10
 
11
11
  Regenerate: `node scripts/generate-template-variants.mjs`. Coverage
12
12
  measurement: `node scripts/template-coverage.mjs` (baseline) and
13
13
  `node scripts/template-coverage.mjs --rescue corpus/generated/ace-surface-variants.jsonl`
14
- (after). See `archive/PLAN_TEMPLATE_COVERAGE.md` for the design and the real
15
- before/after numbers.
14
+ (after).
16
15
 
17
16
  ## Row shapes
18
17
 
19
18
  | `kind` | What | Fields |
20
19
  |---|---|---|
21
- | `rescue` | A real docs-corpus sentence that almost fit the ACE grammar (exactly one undeclared word), rescued by substituting a WordNet synonym of that word that's ALSO already declared in `src/grammar/lexicon-core.json` | `sentence`, `rescued`, `from`, `to`, `pos`, `synsetId`, `sourceFile` |
20
+ | `rescue` | A real docs-corpus sentence that almost fit the ACE grammar (exactly one undeclared word), rescued by substituting a WordNet synonym of that word that's ALSO already declared in `src/domain/grammar/lexicon-core.json` | `sentence`, `rescued`, `from`, `to`, `pos`, `synsetId`, `sourceFile` |
22
21
  | `variant` | A real WordNet/SemCor example sentence (`corpus/tier2/human-examples*.jsonl`) that already hits `parseAce`, with one content word swapped for a same-synset sibling (both ends independently declared in tmct's own lexicon) | `seed`, `generated`, `from`, `to`, `pos`, `synsetId`, `sourceCorpus` |
23
- | `alt-phrasing` | A possessive-pattern (#7) hit rewritten in the ACE grammar's OTHER declared surface form for the same triple (`"X's Y is Z"` <-> `"the Y of X is Z"`, both routed through `buildPossessive` in `src/grammar/ace.mjs`) | `seed`, `generated`, `pattern`, `form` |
22
+ | `alt-phrasing` | A possessive-pattern (#7) hit rewritten in the ACE grammar's OTHER declared surface form for the same triple (`"X's Y is Z"` <-> `"the Y of X is Z"`, both routed through `buildPossessive` in `src/domain/grammar/ace.mjs`) | `seed`, `generated`, `pattern`, `form` |
24
23
 
25
24
  Every row also carries `provenance` (`wordnet:<synsetId>` or
26
25
  `grammar:ace.mjs pattern 7 (possessive) — …`).
27
26
 
28
27
  ## Not wired into the product path
29
28
 
30
- This corpus is not loaded by `src/chat.mjs`/`src/ask.mjs` or any other
29
+ This corpus is not loaded by `src/services/chat.mjs`/`src/domain/ask.mjs` or any other
31
30
  product code — it is committed raw material, verified by
32
- `scripts/template-coverage.mjs`, per archive/PLAN_BREADTH_FIRST_NLU.md §6's explicit
33
- non-goal. Wiring it into live answer rendering is a separate, future phase.
31
+ `scripts/template-coverage.mjs`. Wiring it into live answer rendering is a
32
+ separate, future phase.
34
33
 
35
34
  ## Licence
36
35
 
@@ -0,0 +1,39 @@
1
+ # corpus/namenet — the committed Open English Namenet conversion
2
+
3
+ `namenet.jsonl` is a mechanical, ConceptNet-shape conversion of **three
4
+ human-reviewed linking tables from the Open English Namenet project** — one
5
+ `/r/Synonym` row per accepted name/label link:
6
+
7
+ ```json
8
+ {"start":"/c/en/canis_lupus","rel":"/r/Synonym","end":"/c/en/wolf","weight":2,"surfaceText":"[[Canis lupus]] means the same as [[wolf]]"}
9
+ ```
10
+
11
+ **Licence: CC-BY-4.0** as this repository's conservative label — the source
12
+ repository declares no explicit licence of its own. Read `LICENSE-NOTICE` in
13
+ this directory before redistributing more widely.
14
+
15
+ ## Provenance
16
+
17
+ - **Source:** three reviewed CSVs (`species_reviewed.csv`,
18
+ `taxon2common_reviewed.csv`, `linked_occupations_reviewed.csv`) from a local
19
+ uncommitted checkout of
20
+ [globalwordnet/english-namenet](https://github.com/globalwordnet/english-namenet)
21
+ — never vendored into this repository. Species rows also cross-reference a
22
+ local Open English WordNet checkout (the same source
23
+ `corpus/wordnet/generate.mjs` reads) to resolve synset ids into lemmas.
24
+ - **Why every row is `/r/Synonym`:** each accepted CSV row links two
25
+ name-lists a human reviewer confirmed denote the SAME real-world thing (a
26
+ species, a folk-taxonomic category, an occupation) — never a
27
+ broader/narrower or capability relation. See `generate.mjs`'s header comment
28
+ for the accept/skip rules per source file.
29
+ - The output is indexed with a byte count and sha256 checksum in
30
+ `manifest.json`.
31
+
32
+ ## How to regenerate
33
+
34
+ ```
35
+ node corpus/namenet/generate.mjs [namenetDir]
36
+ TMCT_NAMENET_DIR=/path/to/english-namenet node corpus/namenet/generate.mjs
37
+ ```
38
+
39
+ A maintainer tool, run by hand, offline.
@@ -26,7 +26,7 @@ CC-BY-SA like the ConceptNet slice.
26
26
 
27
27
  Each line is exactly `{ "start", "rel", "end", "weight" }` with `/c/en/<term>`
28
28
  endpoints, so the existing `loadSlice` / `loadMap` / `toFacts` / `seedMemory`
29
- (`src/corpus/conceptnet.mjs`) consume this file with **no code change** — pass it as
29
+ (`src/adapters/corpus/conceptnet.mjs`) consume this file with **no code change** — pass it as
30
30
  the `slicePath`.
31
31
 
32
32
  ```jsonc
@@ -36,7 +36,7 @@ the `slicePath`.
36
36
  {"start":"/c/en/java_class","rel":"/r/IsA","end":"/c/en/class","weight":2}
37
37
  ```
38
38
 
39
- Only relations already mapped in `src/corpus/conceptnet-map.toml` are used, so there
39
+ Only relations already mapped in `src/adapters/corpus/conceptnet-map.toml` are used, so there
40
40
  is **no slice/map drift** (verified: the file loads through `toFacts` cleanly). The
41
41
  emitted-predicate breakdown:
42
42
 
@@ -12,7 +12,7 @@
12
12
  // (corpus/conceptnet/slice.jsonl): one JSON object per line,
13
13
  // {"start":"/c/en/<term>","rel":"/r/<Rel>","end":"/c/en/<concept>","weight":N,"surfaceText":"…"}
14
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
15
+ // src/adapters/corpus/conceptnet-map.toml, so a tier-2 file loads through the very same
16
16
  // loadSlice()/toFacts() path as the tier-1 slice (this file's --verify proves
17
17
  // it). The Wave-2 tier-2 SEEDER (see ../README.md) is what stamps the right
18
18
  // provenance (`corpus:tier2:<id> /r/…`) instead of the conceptnet default.
@@ -244,7 +244,7 @@ export const CORPUSES = {
244
244
  // PLAN_SEED.md — the default "human-world" persona (the operator's own
245
245
  // framing: SEON+ConceptNet's code-domain bias was never the only sensible
246
246
  // default; this is the general-knowledge seed set that REPLACES it as the
247
- // default active bundle, per src/extensions.mjs's builtinExtensions()).
247
+ // default active bundle, per src/services/extensions.mjs's builtinExtensions()).
248
248
  // Hand-curated from two locally-cloned reference sources
249
249
  // (scripts/extract-persona-sources.mjs's worksheet — never a mechanical
250
250
  // dump of either): Open English WordNet (CC-BY-4.0, Princeton WordNet +
@@ -264,7 +264,7 @@ export const CORPUSES = {
264
264
  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.",
265
265
  // Every noun/verb/adjective this corpus's facts depend on, so a live
266
266
  // sentence built from the SAME curated vocabulary ("a man has a hat") can
267
- // actually parse — src/grammar/lexicon-core.json carries the real
267
+ // actually parse — src/domain/grammar/lexicon-core.json carries the real
268
268
  // entries (PLAN_SEED.md §4's "two vocabulary surfaces", gated
269
269
  // independently); this list is the --verify drift-guard's source of
270
270
  // truth (below), not a second copy of the lexicon file itself.
@@ -684,7 +684,7 @@ export const CORPUSES = {
684
684
  // ---- human-bridge (~10 facts) — the cross-ontology showcase
685
685
  // (PLAN_SEED.md §8): a WordNet-side root/common term paired with its
686
686
  // Schema.org-inspired counterpart from human-base, above. scm-sco
687
- // (src/syllogise.mjs, unmodified) proves a chain spanning both
687
+ // (src/domain/syllogise.mjs, unmodified) proves a chain spanning both
688
688
  // sources once a WordNet-side ⊑-chain reaches one of these —
689
689
  // test/chat-cross-ontology-bridge.test.mjs exercises this live.
690
690
  ["person", "/r/IsA", "schema_person"],
@@ -14883,7 +14883,7 @@ export async function fetchCorpus(url, expectedSha) {
14883
14883
  * Alignment drift-guard for a corpus entry that declares an optional
14884
14884
  * `lexicon` sub-key (today: only `human` — PLAN_SEED.md §4's "two vocabulary
14885
14885
  * surfaces" seam): the corpus fact set and the ACE parser's closed-set
14886
- * vocabulary (src/grammar/lexicon-core.json) are two SEPARATE files, gated
14886
+ * vocabulary (src/domain/grammar/lexicon-core.json) are two SEPARATE files, gated
14887
14887
  * independently, so nothing stops them drifting apart over time. Two
14888
14888
  * directions, both real (mirroring conceptnet-map.toml's own "slice relation
14889
14889
  * missing from map = error" precedent):
@@ -14916,7 +14916,7 @@ async function verifyLexiconAlignment(id, spec) {
14916
14916
  const properNames = (spec.lexicon.properNames || []).map((n) => n.toLowerCase());
14917
14917
  const declared = [...nouns, ...verbs, ...adjectives, ...properNames];
14918
14918
 
14919
- const lexPath = fileURLToPath(new URL("../../src/grammar/lexicon-core.json", import.meta.url));
14919
+ const lexPath = fileURLToPath(new URL("../../src/domain/grammar/lexicon-core.json", import.meta.url));
14920
14920
  const lex = JSON.parse(await readFile(lexPath, "utf8"));
14921
14921
  const inLexicon = (w) => Boolean(lex.nouns[w] || lex.verbs[w] || lex.adjectives[w]
14922
14922
  || (lex.properNames || []).some((n) => n.toLowerCase() === w));
@@ -14945,9 +14945,56 @@ async function verifyLexiconAlignment(id, spec) {
14945
14945
  console.error(` verify ${id}: lexicon sub-key (${declared.length} words: ${nouns.length} nouns, ${verbs.length} verbs, ${adjectives.length} adjectives, ${properNames.length} proper names) is aligned both ways`);
14946
14946
  }
14947
14947
 
14948
+ // The human-examples bundles are real example SENTENCES (Open English WordNet
14949
+ // inline examples; the large tier also SemCor text), not fact triples: they are
14950
+ // built by scripts/build-persona-examples.mjs, never seed through
14951
+ // loadSlice()/toFacts(), and carry the source text's CC-BY-4.0 licence rather
14952
+ // than the curated fact bundles' MPL-2.0. They are indexed under a separate
14953
+ // `examples` key (NOT `corpuses`, which `tmct init --corpus` treats as
14954
+ // seedable fact sets) so the licence record and checksums stay machine-readable
14955
+ // without making the sentence files look importable.
14956
+ const EXAMPLE_BUNDLES = [
14957
+ {
14958
+ id: "human-examples",
14959
+ file: "human-examples.jsonl",
14960
+ description: "Example sentences for the Small human persona: Open English WordNet's own inline example sentences, reproduced verbatim.",
14961
+ },
14962
+ {
14963
+ id: "human-examples-medium",
14964
+ file: "human-examples-medium.jsonl",
14965
+ description: "Example sentences added by the Medium persona tier: Open English WordNet inline examples, reproduced verbatim.",
14966
+ },
14967
+ {
14968
+ id: "human-examples-large",
14969
+ file: "human-examples-large.jsonl",
14970
+ description: "Example sentences added by the Large persona tier: Open English WordNet inline examples plus a SemCor-filtered supplement (Brown Corpus text re-tagged to modern OEWN senses).",
14971
+ },
14972
+ ];
14973
+
14974
+ const EXAMPLES_LICENSE = "CC-BY-4.0 (verbatim Open English WordNet / SemCor example sentences — see corpus/README.md and corpus/LICENSES.json)";
14975
+
14976
+ async function exampleBundleManifestEntries() {
14977
+ const entries = [];
14978
+ for (const { id, file, description } of EXAMPLE_BUNDLES) {
14979
+ const text = await readFile(join(HERE, file), "utf8");
14980
+ entries.push({
14981
+ id,
14982
+ kind: "examples",
14983
+ description,
14984
+ source: { kind: "curated", tool: "scripts/build-persona-examples.mjs" },
14985
+ file,
14986
+ rows: text.split("\n").filter(Boolean).length,
14987
+ bytes: Buffer.byteLength(text),
14988
+ sha256: sha256(text),
14989
+ license: EXAMPLES_LICENSE,
14990
+ });
14991
+ }
14992
+ return entries;
14993
+ }
14994
+
14948
14995
  async function main() {
14949
14996
  const verify = process.argv.includes("--verify");
14950
- const manifest = { version: 1, generated: "by corpus/tier2/generate.mjs", corpuses: [] };
14997
+ const manifest = { version: 1, generated: "by corpus/tier2/generate.mjs", corpuses: [], examples: [] };
14951
14998
 
14952
14999
  for (const [id, spec] of Object.entries(CORPUSES)) {
14953
15000
  const text = corpusJsonl(id);
@@ -14966,12 +15013,14 @@ async function main() {
14966
15013
  console.error(` ${id}: ${spec.facts.length} facts, ${Buffer.byteLength(text)} bytes`);
14967
15014
  }
14968
15015
 
15016
+ manifest.examples = await exampleBundleManifestEntries();
15017
+
14969
15018
  const manifestText = JSON.stringify(manifest, null, 2) + "\n";
14970
15019
  await writeFile(join(HERE, "manifest.json"), manifestText);
14971
- console.error(`wrote manifest.json (${manifest.corpuses.length} corpuses)`);
15020
+ console.error(`wrote manifest.json (${manifest.corpuses.length} corpuses, ${manifest.examples.length} example bundles)`);
14972
15021
 
14973
15022
  if (verify) {
14974
- const { loadSlice, loadMap, toFacts } = await import("../../src/corpus/conceptnet.mjs");
15023
+ const { loadSlice, loadMap, toFacts } = await import("../../src/adapters/corpus/conceptnet.mjs");
14975
15024
  const map = await loadMap();
14976
15025
  for (const c of manifest.corpuses) {
14977
15026
  const assertions = await loadSlice(join(HERE, c.file));
@@ -100,5 +100,49 @@
100
100
  "sha256": "754d9d4c046f92994a5f5fa0abde27af65a47ec546b3051bf972bfa76b642917",
101
101
  "license": "MPL-2.0"
102
102
  }
103
+ ],
104
+ "examples": [
105
+ {
106
+ "id": "human-examples",
107
+ "kind": "examples",
108
+ "description": "Example sentences for the Small human persona: Open English WordNet's own inline example sentences, reproduced verbatim.",
109
+ "source": {
110
+ "kind": "curated",
111
+ "tool": "scripts/build-persona-examples.mjs"
112
+ },
113
+ "file": "human-examples.jsonl",
114
+ "rows": 120,
115
+ "bytes": 11168,
116
+ "sha256": "592b3525248379b03b5818237a8b76c83060a704a585ee91a13996b22252a7a9",
117
+ "license": "CC-BY-4.0 (verbatim Open English WordNet / SemCor example sentences — see corpus/README.md and corpus/LICENSES.json)"
118
+ },
119
+ {
120
+ "id": "human-examples-medium",
121
+ "kind": "examples",
122
+ "description": "Example sentences added by the Medium persona tier: Open English WordNet inline examples, reproduced verbatim.",
123
+ "source": {
124
+ "kind": "curated",
125
+ "tool": "scripts/build-persona-examples.mjs"
126
+ },
127
+ "file": "human-examples-medium.jsonl",
128
+ "rows": 356,
129
+ "bytes": 43269,
130
+ "sha256": "40313cbf63d49fb4af08f0cb27d92c55877d3dbe7eb0bc791bd63e56c183418e",
131
+ "license": "CC-BY-4.0 (verbatim Open English WordNet / SemCor example sentences — see corpus/README.md and corpus/LICENSES.json)"
132
+ },
133
+ {
134
+ "id": "human-examples-large",
135
+ "kind": "examples",
136
+ "description": "Example sentences added by the Large persona tier: Open English WordNet inline examples plus a SemCor-filtered supplement (Brown Corpus text re-tagged to modern OEWN senses).",
137
+ "source": {
138
+ "kind": "curated",
139
+ "tool": "scripts/build-persona-examples.mjs"
140
+ },
141
+ "file": "human-examples-large.jsonl",
142
+ "rows": 1928,
143
+ "bytes": 257180,
144
+ "sha256": "fa5646f45451f948156686882f46c522939bbe43158ee42a7628fccf74d8966f",
145
+ "license": "CC-BY-4.0 (verbatim Open English WordNet / SemCor example sentences — see corpus/README.md and corpus/LICENSES.json)"
146
+ }
103
147
  ]
104
148
  }
@@ -0,0 +1,37 @@
1
+ # corpus/wordnet — the committed Open English WordNet conversion
2
+
3
+ `wordnet-xl.jsonl` and `wordnet-full.jsonl` are a mechanical, ConceptNet-shape
4
+ conversion of **real Open English WordNet (OEWN) structural relation data** —
5
+ one row per relation edge or synonym-chain pair:
6
+
7
+ ```json
8
+ {"start":"/c/en/dog","rel":"/r/IsA","end":"/c/en/canine","weight":2,"surfaceText":"[[dog]] is a kind of [[canine]]"}
9
+ ```
10
+
11
+ **Licence: CC-BY-4.0** (Open English WordNet-derived data; NOT this repo's
12
+ MPL-2.0) — see `LICENSE-NOTICE` in this directory for the full attribution.
13
+
14
+ ## Provenance
15
+
16
+ - **Source:** the Open English WordNet YAML synset source
17
+ (`src/yaml/{noun,verb,adj,adv}.*.yaml`, 107,526 synsets), read from a local
18
+ uncommitted checkout of
19
+ [globalwordnet/english-wordnet](https://github.com/globalwordnet/english-wordnet)
20
+ — never vendored into this repository.
21
+ - **What is read:** each synset's structural fields (`hypernym`, `mero_part`,
22
+ `mero_member`, `mero_substance`, `causes`, `attribute`, `similar`, `also`,
23
+ `members`) — never the `definition`/`example` free prose.
24
+ - `wordnet-xl.jsonl` is a bounded ~24,000-fact prioritized subset (hypernym
25
+ backbone plus synonym chains for the most-referenced synsets);
26
+ `wordnet-full.jsonl` is the complete conversion. Both are indexed with byte
27
+ counts and sha256 checksums in `manifest.json`.
28
+
29
+ ## How to regenerate
30
+
31
+ ```
32
+ node corpus/wordnet/generate.mjs [yamlDir]
33
+ TMCT_WORDNET_YAML_DIR=/path/to/yaml node corpus/wordnet/generate.mjs
34
+ ```
35
+
36
+ A maintainer tool, run by hand, offline. See `generate.mjs`'s header comment
37
+ for the full relation-mapping table and direction rules.
@@ -100,7 +100,7 @@ export const RELATION_MAP = Object.freeze({
100
100
  export const SKIPPED_RELATIONS = Object.freeze(["entails", "exemplifies"]);
101
101
 
102
102
  // ---- term encoding (pure, unit-tested) -------------------------------------
103
- // Exact inverse of src/corpus/conceptnet.mjs's termText() decode
103
+ // Exact inverse of src/adapters/corpus/conceptnet.mjs's termText() decode
104
104
  // (`/^\/c\/en\/([^/]+)/` then `.replace(/_/g, " ")`): lowercase, spaces ->
105
105
  // underscores, wrapped as `/c/en/<term>`. Nothing else is touched — any other
106
106
  // punctuation (apostrophes, hyphens) round-trips through termText() unchanged
@@ -1,6 +1,6 @@
1
1
  # data/templates/constructions/agent-noun-relations.toml — construction-grammar
2
2
  # template bank (PLAN_ADVANCED_GRAMMAR.md track (d)): per-construction closed
3
- # template families as DATA, loaded by src/interpret/strategies/constructions.mjs
3
+ # template families as DATA, loaded by src/domain/interpret/strategies/constructions.mjs
4
4
  # beside grammar.mjs's anchored T1-T10 grammar (this file's constructions are the
5
5
  # next numbers, T11-T13 — see the `id` field on each [[construction]] below; do
6
6
  # not renumber grammar.mjs's own T1-T10, this is an ADDITIVE, own-class strategy).
@@ -59,7 +59,7 @@ kind = "inherits"
59
59
  entityType = "Class" # inherits is Class -> Class only
60
60
 
61
61
  # ---- constructions: pattern -> AST skeleton -------------------------------
62
- # Pattern DSL (src/interpret/strategies/constructions.mjs compiles this):
62
+ # Pattern DSL (src/domain/interpret/strategies/constructions.mjs compiles this):
63
63
  # <AGENT> one of the [[relation]] nouns above (closed alternation, longest
64
64
  # noun first so e.g. a hypothetical multi-word noun would never be
65
65
  # shadowed by a shorter one sharing a prefix)
@@ -2,7 +2,7 @@
2
2
  # (PLAN_RESPONSE_FINISHING.md, "The grammar pass (lever 2)").
3
3
  #
4
4
  # Each [[rule]] is a corrective grammar rule applied by applyGrammar() in
5
- # src/finish.mjs over the PROSE spans of a segmented answer — NEVER the flat
5
+ # src/services/finish.mjs over the PROSE spans of a segmented answer — NEVER the flat
6
6
  # string, and NEVER a protected span (entity / path / number / code / provenance
7
7
  # / receipt). The engine reads STRUCTURE, never guesses from surface: an article
8
8
  # rule that would touch the word inside the following protected span refuses to
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polycode-projects/the-mechanical-code-talker",
3
- "version": "1.12.0",
3
+ "version": "2.0.2",
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.",
@@ -39,27 +39,14 @@
39
39
  "bin": {
40
40
  "tmct": "./bin/tmct.mjs"
41
41
  },
42
- "main": "./src/index.mjs",
42
+ "main": "./src/services/index.mjs",
43
43
  "exports": {
44
- ".": "./src/index.mjs",
45
- "./chat": "./src/chat.mjs",
46
- "./resolveObject": "./src/ask.mjs",
47
- "./ask": "./src/ask.mjs",
48
- "./relationKind": "./src/codegraph.mjs",
49
- "./impactClosure": "./src/codegraph.mjs",
50
- "./dispatchTool": "./src/server.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",
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",
62
- "./plan": "./src/router/drive.mjs"
44
+ ".": "./src/services/index.mjs",
45
+ "./plan": "./src/domain/router/drive.mjs",
46
+ "./generateCompletion": "./src/services/completions.mjs",
47
+ "./createCompletionsGraphAdapter": "./src/services/completions.mjs",
48
+ "./repository-interface": "./src/adapters/repository-interface.mjs",
49
+ "./conformance": "./src/tools/conformance.mjs"
63
50
  },
64
51
  "files": [
65
52
  "bin/",
@@ -83,6 +70,8 @@
83
70
  "scripts": {
84
71
  "help": "node bin/tmct.mjs --help",
85
72
  "test": "node --test \"test/**/*.test.mjs\"",
73
+ "test:e2e": "node --test \"e2e/**/*.test.mjs\"",
74
+ "e2e:browsers": "playwright install chromium",
86
75
  "chat": "node bin/tmct.mjs",
87
76
  "chat:repo": "node bin/tmct.mjs chat --repo",
88
77
  "init": "node bin/tmct.mjs init",
@@ -110,6 +99,8 @@
110
99
  },
111
100
  "devDependencies": {
112
101
  "esbuild": "^0.28.1",
113
- "ink-testing-library": "^4.0.0"
102
+ "ink-testing-library": "^4.0.0",
103
+ "playwright": "1.61.1",
104
+ "publint": "0.3.21"
114
105
  }
115
106
  }
@@ -1,5 +1,5 @@
1
1
  // ask-nlp.mjs — the optional wink-nlp adapter behind ask.mjs's lemma/POS tier.
2
- // Loaded lazily via src/wink-model.mjs; failure is cached as null, never a throw.
2
+ // Loaded lazily via src/adapters/wink-model.mjs; failure is cached as null, never a throw.
3
3
 
4
4
  import { winkInstance } from "./wink-model.mjs";
5
5
 
@@ -21,7 +21,7 @@ export class ToolError extends Error {
21
21
 
22
22
  export function loadConfig(env = process.env, cwd = process.cwd()) {
23
23
  // Always resolve to an absolute path, even when TMCT_GRAPH_FILE is set to a
24
- // relative one — src/source-slice.mjs's path-traversal guard compares an
24
+ // relative one — src/adapters/source-slice.mjs's path-traversal guard compares an
25
25
  // always-absolute resolve(repoRoot, site.path) against repoRoot itself, so a
26
26
  // relative repoRoot (derived from this graphFile) would make that guard
27
27
  // reject every read, not just traversal attempts.