@polycode-projects/the-mechanical-code-talker 4.1.1 → 4.1.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.
- package/README.md +31 -18
- package/bin/tmct.mjs +3 -0
- package/data/templates/responses.jsonl +3 -0
- package/package.json +2 -1
- package/src/adapters/memory/core.mjs +1358 -196
- package/src/adapters/memory/inspect.mjs +11 -0
- package/src/adapters/memory/shacl.mjs +38 -0
- package/src/adapters/p2p/webrtc-transport.mjs +28 -5
- package/src/domain/ask-vocab.mjs +39 -0
- package/src/domain/ask.mjs +183 -34
- package/src/domain/grammar/assert.mjs +8 -2
- package/src/domain/hanoi-board.mjs +232 -0
- package/src/domain/ingest-facts.mjs +120 -0
- package/src/domain/interpret/normalize.mjs +49 -0
- package/src/domain/memory/compaction.mjs +284 -0
- package/src/domain/memory/resolution.mjs +171 -0
- package/src/domain/memory/trust.mjs +175 -5
- package/src/domain/memory-facts.mjs +139 -0
- package/src/domain/p2p/facts.mjs +21 -0
- package/src/domain/p2p/peer-id.mjs +15 -0
- package/src/domain/p2p/provenance-relabel.mjs +13 -2
- package/src/domain/p2p/sync-filter.mjs +5 -1
- package/src/domain/p2p/wire.mjs +7 -4
- package/src/domain/scene-compose.mjs +2 -2
- package/src/domain/sprite-facts.mjs +0 -0
- package/src/services/adventure-viz.mjs +5 -1
- package/src/services/adventure.mjs +70 -44
- package/src/services/chat-page-viz.mjs +381 -310
- package/src/services/chat.mjs +273 -155
- package/src/services/code-explorer-viz.mjs +141 -54
- package/src/services/index.mjs +1 -1
- package/src/services/ingest-viz.mjs +134 -9
- package/src/services/ledger-viz.mjs +7 -4
- package/src/services/memory-panel-viz.mjs +8 -3
- package/src/services/mud-turn.mjs +11 -8
- package/src/services/mud-viz.mjs +441 -206
- package/src/services/p2p-room.mjs +110 -23
- package/src/services/plan-viz.mjs +63 -4
- package/src/services/research-viz.mjs +18 -7
- package/src/services/share-overlay-viz.mjs +623 -0
- package/src/services/spider-fly-viz.mjs +2 -2
- package/src/services/sprite-catalog-viz.mjs +303 -78
- package/src/surfaces/web/adventure-browser-entry.mjs +27 -5
- package/src/surfaces/web/chat-browser-entry.mjs +37 -10
- package/src/surfaces/web/code-explorer-browser-entry.mjs +4 -3
- package/src/surfaces/web/ingest-browser-entry.mjs +73 -12
- package/src/surfaces/web/ledger-browser-entry.mjs +32 -7
- package/src/surfaces/web/memory-ask-browser.bundle.js +149 -116
- package/src/surfaces/web/mud-browser-entry.mjs +38 -7
- package/src/surfaces/web/p2p-browser-entry.mjs +1 -1
- package/src/surfaces/web/plan-browser-entry.mjs +33 -2
- package/src/surfaces/web/research-browser-entry.mjs +11 -19
- package/src/surfaces/web/sprites-browser-entry.mjs +39 -8
- package/src/surfaces/web/tmct-surface.mjs +12 -0
- package/src/surfaces/web/turn-session.mjs +10 -3
|
@@ -30,6 +30,7 @@ import { vocabExampleHint } from "../../services/chat.mjs";
|
|
|
30
30
|
import { createInMemoryStore, normFactTerm, loadMemory, readFactRows, applySeedPayload } from "../../adapters/memory/core.mjs";
|
|
31
31
|
import { splitSentencesPreservingPaths } from "../../services/sentences.mjs";
|
|
32
32
|
import { parseEntities } from "../../domain/codegraph.mjs";
|
|
33
|
+
import { memoryFactGraphPayload } from "../../domain/memory-facts.mjs";
|
|
33
34
|
import { loadLexicon } from "../../domain/grammar/lexicon.mjs";
|
|
34
35
|
import { registerWinkModel } from "../../adapters/wink-model.mjs";
|
|
35
36
|
import { setDigestStructures } from "../../adapters/corpus/digest-bank.mjs";
|
|
@@ -72,9 +73,14 @@ import { graphAsk, enginePlan } from "./engine-surface.mjs";
|
|
|
72
73
|
* is module-scope, last write wins, and every session created after this one
|
|
73
74
|
* shares it.
|
|
74
75
|
*
|
|
75
|
-
* Returns { memoryDir, sessionId, graph, turn }.
|
|
76
|
-
* { answer, end, record, plan } and threads
|
|
77
|
-
* calls exactly as the CLI session does.
|
|
76
|
+
* Returns { memoryDir, sessionId, graph, codeGraph, refreshGraph, turn }.
|
|
77
|
+
* `turn(line)` resolves to { answer, end, record, plan } and threads
|
|
78
|
+
* focus/last/planState between calls exactly as the CLI session does.
|
|
79
|
+
*
|
|
80
|
+
* The two graphs are separate on purpose. `codeGraph` is the known-empty index
|
|
81
|
+
* the turn engine reads, and `graph` is this session's memory store projected
|
|
82
|
+
* for `ask()` — a question about taught facts has a real graph to traverse
|
|
83
|
+
* while a code-structure question keeps its honest no-code-graph refusal.
|
|
78
84
|
*/
|
|
79
85
|
export function createChatSession({ seedPayload = null, vocabSeeded = false, liveReference = false, onLiveLookup = null, synthesisBudget = 12, digestStructures = null } = {}) {
|
|
80
86
|
setDigestStructures(digestStructures || []);
|
|
@@ -82,10 +88,24 @@ export function createChatSession({ seedPayload = null, vocabSeeded = false, liv
|
|
|
82
88
|
applySeedPayload(memoryDir, seedPayload);
|
|
83
89
|
|
|
84
90
|
// A known-empty code graph: code-structure questions get the same honest
|
|
85
|
-
// no-code-graph answer an un-pointed CLI session gives, never a crash.
|
|
86
|
-
|
|
91
|
+
// no-code-graph answer an un-pointed CLI session gives, never a crash. The
|
|
92
|
+
// turn engine keeps reading THIS one, so the identity-led greeting, the teach
|
|
93
|
+
// pointer and the zero module counts a page earns from an empty index all
|
|
94
|
+
// stay exactly as they were.
|
|
95
|
+
const codeGraph = parseEntities({ individuals: [], objectProperties: [] });
|
|
96
|
+
|
|
97
|
+
// What `tmct.ask()` traverses is a different graph: this session's own memory
|
|
98
|
+
// store, projected through memoryFactGraphPayload. Rebuilt on demand rather
|
|
99
|
+
// than once at open, because every teach, ingest and research turn grows the
|
|
100
|
+
// store — the same reason spider-fly rebuilds its board before each turn.
|
|
101
|
+
let memoryGraph = parseEntities({ individuals: [], objectProperties: [] });
|
|
102
|
+
async function refreshGraph() {
|
|
103
|
+
memoryGraph = parseEntities(memoryFactGraphPayload(readFactRows(await loadMemory(memoryDir))));
|
|
104
|
+
return memoryGraph;
|
|
105
|
+
}
|
|
106
|
+
|
|
87
107
|
const lexicon = loadLexicon();
|
|
88
|
-
const vocabHint = vocabExampleHint(vocabSeeded);
|
|
108
|
+
const vocabHint = vocabExampleHint(vocabSeeded, "browser");
|
|
89
109
|
const sessionId = globalThis.crypto?.randomUUID?.() ?? String(Date.now());
|
|
90
110
|
|
|
91
111
|
// Four-state, like the CLI: false (off), true (rescue on a miss),
|
|
@@ -99,10 +119,10 @@ export function createChatSession({ seedPayload = null, vocabSeeded = false, liv
|
|
|
99
119
|
let synthesisBudgetOn = Number.isFinite(synthesisBudget) ? synthesisBudget : 12;
|
|
100
120
|
|
|
101
121
|
const session = createTurnSession({
|
|
102
|
-
memoryDir, graph, lexicon, sessionId, vocabHint,
|
|
122
|
+
memoryDir, graph: codeGraph, lexicon, sessionId, vocabHint,
|
|
103
123
|
buildExtraOptions: () => ({
|
|
104
124
|
liveReference: liveReferenceOn, onLiveLookup,
|
|
105
|
-
|
|
125
|
+
synthesisBudget: synthesisBudgetOn,
|
|
106
126
|
}),
|
|
107
127
|
// `result.liveReference` mirrors a `/wiki on|off|supplement|always`
|
|
108
128
|
// command back into this session's own toggle state.
|
|
@@ -114,7 +134,9 @@ export function createChatSession({ seedPayload = null, vocabSeeded = false, liv
|
|
|
114
134
|
return {
|
|
115
135
|
memoryDir,
|
|
116
136
|
sessionId,
|
|
117
|
-
graph,
|
|
137
|
+
get graph() { return memoryGraph; },
|
|
138
|
+
codeGraph,
|
|
139
|
+
refreshGraph,
|
|
118
140
|
get liveReference() { return liveReferenceOn; },
|
|
119
141
|
/** The page's toggle seam: set the live Wikipedia mode for every later turn
|
|
120
142
|
* (the `/wiki on|off|supplement|always` command sets the same state). */
|
|
@@ -155,7 +177,12 @@ export async function researchedFactRows(memoryDir) {
|
|
|
155
177
|
// and paste-ingest controls run.
|
|
156
178
|
publishTmctSurface({
|
|
157
179
|
open: createChatSession,
|
|
158
|
-
ask
|
|
180
|
+
// The memory projection is rebuilt first, so a direct tmct.ask() sees every
|
|
181
|
+
// fact taught, pasted or researched since the last one.
|
|
182
|
+
ask: async (request, options, session) => {
|
|
183
|
+
await session.refreshGraph();
|
|
184
|
+
return graphAsk(request, options, session);
|
|
185
|
+
},
|
|
159
186
|
plan: enginePlan,
|
|
160
187
|
page: {
|
|
161
188
|
registerWinkModel, registerReferencePackProvider, registerLiveReferenceProvider,
|
|
@@ -53,7 +53,7 @@ export function createCodeExplorerSession({ graphPayload, seedPayload = null, vo
|
|
|
53
53
|
// the write path recounts — teach turns must work on any seed.
|
|
54
54
|
if (seedPayload) memoryDir.payload = { ...memoryDir.payload, ...seedPayload };
|
|
55
55
|
const lexicon = loadLexicon();
|
|
56
|
-
const vocabHint = vocabExampleHint(vocabSeeded);
|
|
56
|
+
const vocabHint = vocabExampleHint(vocabSeeded, "browser");
|
|
57
57
|
const sessionId = globalThis.crypto?.randomUUID?.() ?? String(Date.now());
|
|
58
58
|
// A stable virtual path: the provider answers every fetch, so no file is
|
|
59
59
|
// ever read, but the code lanes still do path math (join/dirname) on it.
|
|
@@ -233,8 +233,9 @@ export function askRelatedFacts(graphPayload, term) {
|
|
|
233
233
|
// `tmct.page` keeps the re-derivation helpers a graph swapped through the
|
|
234
234
|
// desktop picker re-renders with, plus the wink and term-normalizing seams the
|
|
235
235
|
// chat shares with the ledger page. `createCodeExplorerSession` sits there
|
|
236
|
-
// too:
|
|
237
|
-
//
|
|
236
|
+
// too: the page keeps its own session slot, created lazily on the first turn
|
|
237
|
+
// once the general-knowledge seed has landed, rather than the one `tmct.open`
|
|
238
|
+
// would install eagerly — so it calls the factory straight from the bag.
|
|
238
239
|
publishTmctSurface({
|
|
239
240
|
open: createCodeExplorerSession,
|
|
240
241
|
ask: graphAsk,
|
|
@@ -29,16 +29,24 @@ import { splitSentencesPreservingPaths, stripCitationResidue } from "../../servi
|
|
|
29
29
|
import { clauseCandidates, optimisticTriples } from "../../services/extract-facts.mjs";
|
|
30
30
|
import { touchedFactRows } from "../../domain/memory/touched-facts.mjs";
|
|
31
31
|
import { loadLexicon } from "../../domain/grammar/lexicon.mjs";
|
|
32
|
+
import { parseEntities } from "../../domain/codegraph.mjs";
|
|
33
|
+
import { ingestFactGraphPayload, ingestedFactRows } from "../../domain/ingest-facts.mjs";
|
|
32
34
|
import { registerWinkModel, winkInstance } from "../../adapters/wink-model.mjs";
|
|
33
35
|
import { memoryStats, exportFactsJsonl } from "./memory-stats.mjs";
|
|
34
36
|
import { openPersistedStore } from "./idb-persist.mjs";
|
|
37
|
+
import { createTurnSession } from "./turn-session.mjs";
|
|
35
38
|
import { publishTmctSurface } from "./tmct-surface.mjs";
|
|
39
|
+
import { graphAsk, enginePlan } from "./engine-surface.mjs";
|
|
36
40
|
|
|
37
41
|
// The pronoun subjects a bounded carry substitutes with the last unique
|
|
38
42
|
// grounded subject in the SAME paragraph. Reset at every blank line, so a
|
|
39
43
|
// fresh paragraph never resolves against a stale antecedent.
|
|
40
44
|
const PRONOUN_LEAD_RE = /^(?:they|it|these|those|this)\b\s*/i;
|
|
41
45
|
|
|
46
|
+
// The turn kinds that move the fact store, so the projected graph a later
|
|
47
|
+
// question traverses has to be rebuilt before it answers.
|
|
48
|
+
const STORE_WRITING_TURNS = new Set(["assert", "retract"]);
|
|
49
|
+
|
|
42
50
|
/**
|
|
43
51
|
* The single recognizer seam. Splits `text` into paragraphs (blank-line
|
|
44
52
|
* separated, so the pronoun carry never bridges a topic break) and each
|
|
@@ -171,35 +179,88 @@ export async function groundTextToFacts(text, { memoryDir, sessionId, lexicon, v
|
|
|
171
179
|
* the page can then export. `seedPayload` (optional) pre-loads a graph the
|
|
172
180
|
* recognizer can recall and link against.
|
|
173
181
|
*
|
|
174
|
-
* Returns { memoryDir, sessionId,
|
|
175
|
-
* optimistic })` is the
|
|
176
|
-
* against this session's store and returns
|
|
177
|
-
* skipped, facts } summary.
|
|
182
|
+
* Returns { memoryDir, sessionId, graph, refreshGraph, askableClasses, ingest,
|
|
183
|
+
* turn }. `ingest(text, { onFact, optimistic })` is the call the ingest panes
|
|
184
|
+
* make; it drives groundTextToFacts against this session's store and returns
|
|
185
|
+
* its { sentences, recognized, skipped, facts } summary. `turn(line)` is the
|
|
186
|
+
* ask dock's own entry point — the FULL chat turn engine (the exact dispatch
|
|
187
|
+
* the CLI runs) over the same store, so a question it can't ground gets the
|
|
188
|
+
* same refusal the CLI gives.
|
|
189
|
+
*
|
|
190
|
+
* `graph` is what a question actually traverses: the ingested rows projected
|
|
191
|
+
* through ingest-facts.mjs, rebuilt by `refreshGraph()` whenever the store has
|
|
192
|
+
* moved since the last one. The rebuild is gated on a dirty flag rather than
|
|
193
|
+
* run per call because a seeded store holds tens of thousands of rows, and
|
|
194
|
+
* re-reading all of them to answer a second question about the same two
|
|
195
|
+
* sentences is the one cost this page has to avoid.
|
|
178
196
|
*/
|
|
179
197
|
export function createIngestSession({ seedPayload = null, vocabSeeded = false } = {}) {
|
|
180
198
|
const memoryDir = createInMemoryStore();
|
|
181
199
|
applySeedPayload(memoryDir, seedPayload);
|
|
182
200
|
|
|
183
201
|
const lexicon = loadLexicon();
|
|
184
|
-
const vocabHint = vocabExampleHint(vocabSeeded);
|
|
202
|
+
const vocabHint = vocabExampleHint(vocabSeeded, "browser");
|
|
185
203
|
const sessionId = globalThis.crypto?.randomUUID?.() ?? String(Date.now());
|
|
186
204
|
|
|
205
|
+
let graph = parseEntities({ individuals: [], objectProperties: [] });
|
|
206
|
+
let storeMovedSinceGraph = true;
|
|
207
|
+
async function refreshGraph() {
|
|
208
|
+
if (!storeMovedSinceGraph) return graph;
|
|
209
|
+
const rows = ingestedFactRows(readFactRows(await loadMemory(memoryDir)));
|
|
210
|
+
graph = parseEntities(ingestFactGraphPayload(rows));
|
|
211
|
+
storeMovedSinceGraph = false;
|
|
212
|
+
return graph;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// An empty graph is not the same as no graph to runTurn: a non-null one
|
|
216
|
+
// makes it read an ordinary "the number of X" phrase as a graph count query
|
|
217
|
+
// instead of running the teach cascade, so before anything is ingested the
|
|
218
|
+
// dock keeps the plain conversational reading.
|
|
219
|
+
const graphForTurn = () => (graph.individuals.length ? graph : null);
|
|
220
|
+
|
|
221
|
+
const turnSession = createTurnSession({
|
|
222
|
+
memoryDir, lexicon, sessionId, vocabHint,
|
|
223
|
+
buildExtraOptions: () => ({ graph: graphForTurn() }),
|
|
224
|
+
captureExtraState: (result) => {
|
|
225
|
+
if (STORE_WRITING_TURNS.has(result?.record?.via) && !result.record.miss) storeMovedSinceGraph = true;
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
|
|
187
229
|
return {
|
|
188
230
|
memoryDir,
|
|
189
231
|
sessionId,
|
|
190
|
-
|
|
191
|
-
|
|
232
|
+
get graph() { return graph; },
|
|
233
|
+
refreshGraph,
|
|
234
|
+
/** The class nouns this graph can actually list, for a page building its
|
|
235
|
+
* own "try asking" hint out of real data rather than invented examples. */
|
|
236
|
+
askableClasses() {
|
|
237
|
+
return [...new Set(graph.individuals.map((i) => i.class).filter(Boolean))].sort();
|
|
238
|
+
},
|
|
239
|
+
async ingest(text, { onFact = null, optimistic = false } = {}) {
|
|
240
|
+
const summary = await groundTextToFacts(text, { memoryDir, sessionId, lexicon, vocabHint, onFact, optimistic });
|
|
241
|
+
if (summary.recognized) storeMovedSinceGraph = true;
|
|
242
|
+
return summary;
|
|
243
|
+
},
|
|
244
|
+
async turn(line) {
|
|
245
|
+
await refreshGraph();
|
|
246
|
+
return turnSession.turn(line);
|
|
192
247
|
},
|
|
193
248
|
};
|
|
194
249
|
}
|
|
195
250
|
|
|
196
|
-
//
|
|
197
|
-
// `tmct.turn`
|
|
198
|
-
//
|
|
199
|
-
//
|
|
200
|
-
//
|
|
251
|
+
// The page's own two calls are `tmct.session.ingest(text)` and, from the ask
|
|
252
|
+
// dock, `tmct.turn(line)`. `tmct.ask` puts one question straight to the graph
|
|
253
|
+
// this session projects from what it has ingested, rebuilding it first so a
|
|
254
|
+
// fact grounded a moment ago is already visible. `tmct.page` keeps the
|
|
255
|
+
// recognizer entry point the page also drives directly, the wink seam, the
|
|
256
|
+
// stats fold behind its counters, its IndexedDB wrapper and its JSONL export.
|
|
201
257
|
publishTmctSurface({
|
|
202
258
|
open: createIngestSession,
|
|
259
|
+
ask: async (request, options, session) => {
|
|
260
|
+
await session.refreshGraph();
|
|
261
|
+
return graphAsk(request, options, session);
|
|
262
|
+
},
|
|
263
|
+
plan: enginePlan,
|
|
203
264
|
page: {
|
|
204
265
|
groundTextToFacts, exportFactsJsonl, registerWinkModel, normFactTerm,
|
|
205
266
|
memoryStats, openPersistedStore,
|
|
@@ -17,9 +17,10 @@
|
|
|
17
17
|
// never published — only the hosted demo site's public/ledger.html links to
|
|
18
18
|
// it, as an optional sibling script the page degrades honestly without.
|
|
19
19
|
import { vocabExampleHint } from "../../services/chat.mjs";
|
|
20
|
-
import { createInMemoryStore, normFactTerm, applySeedPayload } from "../../adapters/memory/core.mjs";
|
|
20
|
+
import { createInMemoryStore, normFactTerm, applySeedPayload, loadMemory, readFactRows } from "../../adapters/memory/core.mjs";
|
|
21
21
|
import { splitSentencesPreservingPaths } from "../../services/sentences.mjs";
|
|
22
22
|
import { parseEntities } from "../../domain/codegraph.mjs";
|
|
23
|
+
import { memoryFactGraphPayload } from "../../domain/memory-facts.mjs";
|
|
23
24
|
import { loadLexicon } from "../../domain/grammar/lexicon.mjs";
|
|
24
25
|
import { registerWinkModel } from "../../adapters/wink-model.mjs";
|
|
25
26
|
import { registerResearchProvider } from "../../adapters/corpus/wikipedia-live.mjs";
|
|
@@ -37,7 +38,12 @@ import { graphAsk, enginePlan } from "./engine-surface.mjs";
|
|
|
37
38
|
* a fact taught through the dock extends the SAME graph the page renders
|
|
38
39
|
* from, never a disconnected one.
|
|
39
40
|
*
|
|
40
|
-
* Returns { memoryDir, sessionId, graph, turn },
|
|
41
|
+
* Returns { memoryDir, sessionId, graph, codeGraph, refreshGraph, turn },
|
|
42
|
+
* identical to createChatSession — including the two-graph split: `codeGraph`
|
|
43
|
+
* is the known-empty index the turn engine reads, and `graph` is the ledger's
|
|
44
|
+
* own store projected for `ask()`, so a question about the facts on the page
|
|
45
|
+
* traverses those facts while a code-structure question still refuses honestly.
|
|
46
|
+
*
|
|
41
47
|
* ledger-viz.mjs's own inline script calls computeLedgerDataFromPayload
|
|
42
48
|
* (re-exported below) on `memoryDir.payload` after a turn whose record shows
|
|
43
49
|
* a successful write (`via: "assert"` or `via: "retract"`, `miss: false`) to
|
|
@@ -48,13 +54,27 @@ export function createLedgerSession({ seedPayload = null, vocabSeeded = false }
|
|
|
48
54
|
const memoryDir = createInMemoryStore();
|
|
49
55
|
applySeedPayload(memoryDir, seedPayload);
|
|
50
56
|
|
|
51
|
-
const
|
|
57
|
+
const codeGraph = parseEntities({ individuals: [], objectProperties: [] });
|
|
58
|
+
|
|
59
|
+
let memoryGraph = parseEntities({ individuals: [], objectProperties: [] });
|
|
60
|
+
async function refreshGraph() {
|
|
61
|
+
memoryGraph = parseEntities(memoryFactGraphPayload(readFactRows(await loadMemory(memoryDir))));
|
|
62
|
+
return memoryGraph;
|
|
63
|
+
}
|
|
64
|
+
|
|
52
65
|
const lexicon = loadLexicon();
|
|
53
|
-
const vocabHint = vocabExampleHint(vocabSeeded);
|
|
66
|
+
const vocabHint = vocabExampleHint(vocabSeeded, "browser");
|
|
54
67
|
const sessionId = globalThis.crypto?.randomUUID?.() ?? String(Date.now());
|
|
55
68
|
|
|
56
|
-
const session = createTurnSession({ memoryDir, graph, lexicon, sessionId, vocabHint });
|
|
57
|
-
return {
|
|
69
|
+
const session = createTurnSession({ memoryDir, graph: codeGraph, lexicon, sessionId, vocabHint });
|
|
70
|
+
return {
|
|
71
|
+
memoryDir,
|
|
72
|
+
sessionId,
|
|
73
|
+
get graph() { return memoryGraph; },
|
|
74
|
+
codeGraph,
|
|
75
|
+
refreshGraph,
|
|
76
|
+
turn: session.turn,
|
|
77
|
+
};
|
|
58
78
|
}
|
|
59
79
|
|
|
60
80
|
// `tmct.page` keeps what the page's own script renders with and the engine has
|
|
@@ -64,7 +84,12 @@ export function createLedgerSession({ seedPayload = null, vocabSeeded = false }
|
|
|
64
84
|
// paste-ingest and JSONL export.
|
|
65
85
|
publishTmctSurface({
|
|
66
86
|
open: createLedgerSession,
|
|
67
|
-
ask
|
|
87
|
+
// The memory projection is rebuilt first, so a direct tmct.ask() sees every
|
|
88
|
+
// fact the dock or the ingest panel has taught since the last one.
|
|
89
|
+
ask: async (request, options, session) => {
|
|
90
|
+
await session.refreshGraph();
|
|
91
|
+
return graphAsk(request, options, session);
|
|
92
|
+
},
|
|
68
93
|
plan: enginePlan,
|
|
69
94
|
page: {
|
|
70
95
|
computeLedgerDataFromPayload, normFactTerm, registerWinkModel, registerResearchProvider,
|